Initial commit of Object Teams Dynamic Runtime Environment
in accordance with CQ 7018.
diff --git a/plugins/org.eclipse.objectteams.otredyn/.classpath b/plugins/org.eclipse.objectteams.otredyn/.classpath
new file mode 100644
index 0000000..64c5e31
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/.classpath
@@ -0,0 +1,7 @@
+<?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="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.eclipse.objectteams.otredyn/.project b/plugins/org.eclipse.objectteams.otredyn/.project
new file mode 100644
index 0000000..e0a35ad
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.objectteams.otredyn</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.otredyn/.settings/org.eclipse.jdt.core.prefs b/plugins/org.eclipse.objectteams.otredyn/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..8871fec
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,79 @@
+#Fri Jul 15 18:22:12 CEST 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.5
+org.eclipse.objectteams.otdt.compiler.option.pure_java=enabled
diff --git a/plugins/org.eclipse.objectteams.otredyn/META-INF/MANIFEST.MF b/plugins/org.eclipse.objectteams.otredyn/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..4732fce
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/META-INF/MANIFEST.MF
@@ -0,0 +1,18 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.objectteams.otredyn
+Bundle-Version: 0.8.0.qualifier
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Export-Package: org.objectteams,
+ org.eclipse.objectteams.otredyn.bytecode,
+ org.eclipse.objectteams.otredyn.bytecode.asm,
+ org.eclipse.objectteams.otredyn.runtime,
+ org.eclipse.objectteams.otredyn.transformer,
+ org.eclipse.objectteams.otredyn.transformer.jplis,
+ org.eclipse.objectteams.otredyn.transformer.names,
+ org.eclipse.objectteams.otredyn.util
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Bundle-ClassPath: .
+Require-Bundle: org.objectweb.asm;bundle-version="3.3.1"
diff --git a/plugins/org.eclipse.objectteams.otredyn/build.properties b/plugins/org.eclipse.objectteams.otredyn/build.properties
new file mode 100644
index 0000000..b5e3b75
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/build.properties
@@ -0,0 +1,4 @@
+source.. = src/
+bin.includes = META-INF/,\
+               .,\
+               plugin.properties
diff --git a/plugins/org.eclipse.objectteams.otredyn/plugin.properties b/plugins/org.eclipse.objectteams.otredyn/plugin.properties
new file mode 100644
index 0000000..f48715f
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/plugin.properties
@@ -0,0 +1,2 @@
+pluginName=Object Teams Dynamic Runtime Environment
+providerName=Eclipse.org - Object Teams
diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/AbstractBoundClass.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/AbstractBoundClass.java
new file mode 100644
index 0000000..ff292ad
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/AbstractBoundClass.java
@@ -0,0 +1,1036 @@
+/**********************************************************************
+ * This file is part of "Object Teams Dynamic Runtime Environment"
+ * 
+ * Copyright 2009, 2012 Oliver Frank and others.
+ * 
+ * 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:
+ *		Oliver Frank - Initial API and implementation
+ *		Stephan Herrmann - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otredyn.bytecode;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.objectteams.otredyn.runtime.ClassIdentifierProviderFactory;
+import org.eclipse.objectteams.otredyn.runtime.IBinding;
+import org.eclipse.objectteams.otredyn.runtime.IBoundClass;
+import org.eclipse.objectteams.otredyn.runtime.IMethod;
+import org.eclipse.objectteams.otredyn.runtime.TeamManager;
+import org.eclipse.objectteams.otredyn.runtime.ISubclassWiringTask;
+import org.eclipse.objectteams.otredyn.transformer.jplis.ObjectTeamsTransformer;
+
+import org.objectweb.asm.Opcodes;
+
+/**
+ * This class represents a java class.
+ * It stores the information about a class parsed from the bytecode and
+ * it handles callin and decapsulation bindings for the class
+ * @author Oliver Frank
+ */
+public abstract class AbstractBoundClass implements IBoundClass {
+	
+	/**
+	 * A structure that is internally used to store which methods are still woven
+	 * and which has to be woven.
+	 */
+	private static class WeavingTask {
+		public static enum WeavingTaskType {
+			WEAVE_BINDING_OF_SUBCLASS,
+			WEAVE_BINDING,
+			WEAVE_INHERITED_BINDING,
+			WEAVE_METHOD_ACCESS,
+			WEAVE_FIELD_ACCESS,
+			WEAVE_INHERITED_MEMBER_ACCESS
+		}
+		
+		private WeavingTaskType weavingTaskType;
+		private String memberName;
+		private String memberSignature;
+		private boolean doAllTransformations;
+		private boolean isHandleCovariantReturn;
+
+		public WeavingTask(WeavingTaskType weavingTaskType, String memberName, String memberSignature, boolean handleCovariantReturn) {
+			this.weavingTaskType = weavingTaskType;
+			this.memberName = memberName;
+			this.memberSignature = memberSignature;
+			this.isHandleCovariantReturn = handleCovariantReturn;
+		}
+		
+		/**
+		 * Returns the type of the WeavingTask
+		 * @return
+		 */
+		public WeavingTaskType getType() {
+			return weavingTaskType;
+		}
+		
+		/**
+		 * Returns the name of the member, that has to be woven
+		 * @return
+		 */
+		public String getMemberName() {
+			return memberName;
+		}
+
+		/**
+		 * Returns the signature of the member, that has to be woven
+		 * @return
+		 */
+		public String getMemberSignature() {
+			return memberSignature;
+		}
+		
+		/**
+		 * This information is only needed for callin bindings.
+		 * @return If true, all transformation has to be done, if false,
+		 * only callAllBindings has to be redefined
+		 */
+		public boolean doAllTransformations() {
+			return doAllTransformations;
+		}
+
+		public void setDoAllTransformations(boolean doAllTransformations) {
+			this.doAllTransformations = doAllTransformations;
+		}
+
+		public boolean isHandleCovariantReturn() {
+			return this.isHandleCovariantReturn;
+		}
+	}
+
+	// completed WeavingTasks for callin bindings mapped by the method,
+	// that was woven
+	private Map<Method, WeavingTask> completedBindingTasks;
+	
+	// not completed WeavingTasks for callin bindings mapped by the method,
+	// that has to be woven
+	private Map<Method, WeavingTask> openBindingTasks;
+	
+	// completed WeavingTasks for decapsulation bindings mapped by the member,
+	// that was woven
+	private Map<Member, WeavingTask> completedAccessTasks;
+	
+	// open WeavingTasks for decapsulation bindings mapped by the member,
+	// that has to be woven
+	private Map<Member, WeavingTask> openAccessTasks;
+	
+	private List<ISubclassWiringTask> wiringTasks;
+	
+	//FQN (e.g. "foo.bar.MyClass")
+	private String name;
+	
+	//internal FQN (e.g. "foo/bar/MyClass.class")
+	private String internalName;
+	
+	// A globally unique identifier for the class
+	private String id;
+	private String superClassName;
+	private String internalSuperClassName;
+	private AbstractBoundClass superclass;
+	private AbstractBoundClass enclosingClass;
+	private Map<String, Method> methods;
+	private Map<String, Field> fields;
+	private Map<AbstractBoundClass, Object> subclasses;
+	
+	// Is the java class, that was represented by the AbstractBoundClass
+	// already loaded by a class loader or not
+	private boolean isLoaded;
+	
+	// Does this AbstractBoundClass represent a team
+	private boolean isTeam;
+	private boolean isInterface;
+
+	private int otClassFlags;
+	private int visibilityFlags;
+	private boolean implicitTeamActivationEnabled = false;
+	private Set<String> methodsForImplicitActivation;
+
+	protected ClassLoader loader;
+
+
+	/**
+	 * No public constructor, beacause only the ClassRepository should
+	 * create AbstractBoundClasses
+	 * @param name dot-separated class name
+	 * @param id unique identifier, able to differentiate same-named classes from different classloaders
+	 * @param loader classloader responsible for loading this class
+	 */
+	protected AbstractBoundClass(String name, String id, ClassLoader loader) {
+		if (name.indexOf('/')!= -1)
+			new RuntimeException(name).printStackTrace(System.out);
+		this.name = name;
+		this.internalName = name.replace('.', '/');
+		this.id = id;
+		this.loader = loader;
+		completedBindingTasks = new IdentityHashMap<Method, WeavingTask>();
+		openBindingTasks = new IdentityHashMap<Method, WeavingTask>();
+		openAccessTasks = new IdentityHashMap<Member, WeavingTask>();
+		completedAccessTasks = new IdentityHashMap<Member, WeavingTask>();
+		methods = new HashMap<String, Method>();
+		fields = new HashMap<String, Field>();
+		subclasses = new IdentityHashMap<AbstractBoundClass, Object>();
+		
+		// don't fetch a anonymous subclass for a anonymous subclass
+		if (!name.equals(ClassRepository.ANONYMOUS_SUBCLASS_NAME)) {
+			AbstractBoundClass anonymousSubclass = ClassRepository
+					.getInstance().getAnonymousSubclass(this);
+			subclasses.put(anonymousSubclass, null);
+		}
+	}
+
+	/**
+	 * Returns the name of the Class
+	 * @return
+	 */
+	public String getName() {
+		return name;
+	}
+
+	public String getId() {
+		return id;
+	}
+
+	public boolean isAnonymous() {
+		return getName().equals(ClassRepository.ANONYMOUS_SUBCLASS_NAME);
+	}
+	
+	/**
+	 * Returns the classloader responsible for loading this class.
+	 * @return
+	 */
+	public ClassLoader getClassLoader() {
+		return this.loader;
+	}
+	
+	/**
+	 * Set the name of the super class of this class
+	 * @param superClassName
+	 */
+	public void setSuperClassName(String superClassName) {
+		if (superClassName == null) {
+			return;
+		}
+		this.superClassName = superClassName.replace('/', '.');
+		this.internalSuperClassName = superClassName.replace('.', '/');
+	}
+
+	public boolean isJavaLangObject() {
+		return this.name.equals("java.lang.Object");
+	}
+
+	/**
+	 * Is the class a interface?
+	 * @return
+	 */
+	public boolean isInterface() {
+		parseBytecode();
+		return isInterface;
+	}
+
+	/**
+	 * Mark as interface
+	 * @param isInterface
+	 */
+	public void setInterface(boolean isInterface) {
+		this.isInterface = isInterface;
+	}
+	
+	/**
+	 * Does this AbstractBoundClass represents a Team.
+	 * @return if true, the method getTeam of the ClassRepository 
+	 * could be called to get an instance of AbstractTeam 
+	 */
+	public boolean isTeam() {
+		parseBytecode();
+		return isTeam;
+	}
+
+	/**
+	 * Mark as team
+	 * @param isTeam
+	 */
+	public void setTeam(boolean isTeam) {
+		this.isTeam = isTeam;
+	}
+
+	public void setOTClassFlags(int flags) {
+		this.otClassFlags = flags;		
+	}
+	public void setVisibility(int flags) {
+		this.visibilityFlags = flags;
+	}
+	
+	public boolean isRole() {
+		return (this.otClassFlags & Types.ROLE_FLAG) != 0;
+	}
+
+	public boolean isProtected() {
+		return (this.visibilityFlags & Opcodes.ACC_PROTECTED) != 0;
+	}
+
+	public void enableImplicitActivation() {
+		this.implicitTeamActivationEnabled = true;		
+	}
+
+	public void registerMethodForImplicitActivation(String methodNameAndDesc) {
+		if (this.methodsForImplicitActivation == null)
+			this.methodsForImplicitActivation = new HashSet<String>();
+		this.methodsForImplicitActivation.add(methodNameAndDesc);
+	}
+
+	public boolean hasMethodImplicitActivation(String methodNameAndDesc) {
+		if (this.implicitTeamActivationEnabled) // for all methods
+			return true;
+		if (this.methodsForImplicitActivation == null)
+			return false;
+		return this.methodsForImplicitActivation.contains(methodNameAndDesc);
+	}
+
+	/**
+	 * Do all needed transformations needed at load time:
+	 * Add the interface IBoundBase
+	 * Add the empty method callOrig
+	 * Add the empty method callOrigStatic
+	 * Add the empty method access
+	 * Add the empty method accessStatic
+	 * Add the empty method callAllBindings
+	 */
+	public void transformAtLoadTime() {
+		handleTaskList();
+	}
+
+	/**
+	 * Mark as loaded
+	 */
+	public void setLoaded() {
+		this.isLoaded = true;
+	}
+	
+	/**
+	 * Returns an instance of AbstractBoundClass that represents 
+	 * the super class of this class.
+	 * It parses the bytecode, if that has not already been done 
+	 * @return an instance of AbstractBoundClass that represents 
+	 * the super class of this class
+	 */
+	public synchronized AbstractBoundClass getSuperclass() {
+		parseBytecode();
+		if (superClassName != null && superclass == null) {
+			String superclassId = ClassIdentifierProviderFactory.getClassIdentifierProvider().getSuperclassIdentifier(id, internalSuperClassName);
+			
+			//if superclassId is null the class could be "Object" or an interface
+			if (superclassId != null) {
+				superclass = ClassRepository.getInstance().getBoundClass(superClassName, superclassId, loader);
+				superclass.addSubclass(this);
+				// FIXME(SH): can we avoid adding all subclasses to j.l.Object?
+			}
+		}
+		return superclass;
+	}
+
+	/**
+	 * Returns an instance of AbstractBoundClass that represents 
+	 * the enclosing class of this class.
+	 * It parses the bytecode, if that has not already been done 
+	 * @return an instance of AbstractBoundClass that represents 
+	 * the enclosing class of this class
+	 */
+	public synchronized AbstractBoundClass getEnclosingClass() {
+		parseBytecode();
+		int pos = this.internalName.lastIndexOf('$');
+		if (pos != -1) {
+			String enclosingClassName = this.internalName.substring(0, pos); 
+			// FIXME(SH): do we need a new getEnclosingClassIdentifier?
+			String enclosingClassID = ClassIdentifierProviderFactory.getClassIdentifierProvider().getSuperclassIdentifier(id, enclosingClassName);
+			
+			if (enclosingClassID != null) {
+				enclosingClass = ClassRepository.getInstance().getBoundClass(enclosingClassName, enclosingClassID, loader);
+				enclosingClass.addSubclass(this);
+			}
+		}
+		return enclosingClass;
+	}
+
+	public synchronized String getEnclosingClassName() {
+		parseBytecode();
+		int pos = this.internalName.lastIndexOf('$');
+		if (pos != -1) {
+			return this.internalName.substring(0, pos); 
+		}
+		return null;
+	}
+
+	/**
+	 * This method parses the bytecode, if that has not already been done 
+	 */
+	protected abstract void parseBytecode();
+	
+	/**
+	 * Returns the internal name of the super class of this class
+	 * It parses the bytecode, if that has not already been done
+	 * @return
+	 */
+	protected String getInternalSuperClassName() {
+		parseBytecode();
+		return internalSuperClassName;
+	}
+
+	/**
+	 * Returns the internal name of this class
+	 * @return
+	 */
+	protected String getInternalName() {
+		return internalName;
+	}
+	
+	/**
+	 * Returns the name of the super class of this class
+	 * It parses the bytecode, if that has not already been done
+	 * @return
+	 */
+	public String getSuperClassName() {
+		parseBytecode();
+		return superClassName;
+	}
+
+	/**
+	 * Adds a method to this class.
+	 * This method is intended to be called, 
+	 * while parsing the bytecode
+	 * @param name the name of the field
+	 * @param desc the signature of the method
+	 * @param isStatic is this method static
+	 * @param isPrivate is this method private
+	 */
+	public void addMethod(String name, String desc, boolean isStatic, int accessFlags) {
+		String methodKey = getMethodKey(name, desc);
+		Method method = methods.get(methodKey);
+		// Does this method already exists?
+		// Methods are created by getMethod, if the class is not loaded
+		if (method == null) {
+			method = new Method(name, desc, isStatic, accessFlags);
+			method.setImplemented(true);
+			methods.put(methodKey, method);
+		} else {
+			// Yes, so set additional information.
+			method.setImplemented(true);
+			method.setStatic(isStatic);
+		}
+	}
+
+	/** Method signature sauf the return type. */
+	private String getMethodKey(String name, String desc) {
+		int pos = desc.indexOf(')');
+		return name+desc.substring(0,pos+1);
+	}
+
+	/**
+	 * Adds a field to this class.
+	 * This method is intended to be called, 
+	 * while parsing the bytecode
+	 * @param name the name of the field
+	 * @param desc the signature of the field
+	 * @param isStatic is this field static
+	 * @param accessFlag ACC_PUBLIC, ACC_PROTECTED, ACC_PRIVATE or 0.
+	 */
+	public void addField(String name, String desc, boolean isStatic, int accessFlags) {
+		Field field = fields.get(name);
+		if (field == null) {
+			field = new Field(name, desc, isStatic, accessFlags);
+			fields.put(name, field);
+		} else {
+			field.setStatic(isStatic);
+		}
+	}
+
+	public synchronized Method getMethod(String name, String desc, boolean allowCovariantReturn) {
+		parseBytecode();
+		String methodKey = getMethodKey(name, desc);
+		Method method = methods.get(methodKey);
+		if (!allowCovariantReturn && method != null && !method.getSignature().equals(desc))
+			method = null; // don't use this
+		if (method == null) {
+			// class was not yet loaded
+			method = new Method(name, desc);
+			methods.put(methodKey, method);
+		}
+		return method;
+	}
+
+	// same as above but specifically request a static/non-static method
+	public synchronized Method getMethod(String name, String desc, boolean allowCovariantReturn, boolean isStatic) {
+		parseBytecode();
+		String methodKey = getMethodKey(name, desc);
+		Method method = methods.get(methodKey);
+		if (!allowCovariantReturn && method != null && !method.getSignature().equals(desc))
+			method = null; // don't use this
+		if (method == null) {
+			// class was not yet loaded
+			method = new Method(name, desc);
+			method.setStatic(isStatic);
+			methods.put(methodKey, method);
+		}
+		assert method.isStatic() == isStatic : "Mismatching static/non-static methods "+getName()+'.'+name+desc;
+		return method;
+	}
+
+	public synchronized Field getField(String name, String desc) {
+		parseBytecode();
+		Field field = fields.get(name);
+		if (field == null) {
+			// class was not yet loaded
+			field = new Field(name, desc);
+			fields.put(name, field);
+		}
+		return field;
+	}
+
+
+	public String getMethodIdentifier(IMethod method) {
+		return getId() + method.getName() + method.getSignature();
+	}
+
+	/**
+	 * Adds a subclass to this class
+	 * @param subclass
+	 */
+	protected void addSubclass(AbstractBoundClass subclass) {
+		subclasses.put(subclass, null);
+	}
+
+	/**
+	 * Remove subclass from this class. It's only needed
+	 * to remove a anonymous subclass, if a real subclass is loaded
+	 * @param subclass
+	 */
+	protected void removeSubclass(AbstractBoundClass subclass) {
+		subclasses.remove(subclass);
+	}
+
+	/**
+	 * Returns all subclasses of this class, 
+	 * including the anonymous subclass
+	 * @return
+	 */
+	private Collection<AbstractBoundClass> getSubclasses() {
+		return subclasses.keySet();
+	}
+
+	/**
+	 * Handle all open weaving tasks for this class.
+	 * It redefines the class, if it is not called while loading
+	 */
+	public synchronized void handleTaskList() {
+		Set<Map.Entry<Method, WeavingTask>> bindingEntrySet = openBindingTasks
+				.entrySet();
+
+		Set<Map.Entry<Member, WeavingTask>> accessEntrySet = openAccessTasks
+				.entrySet();
+
+		// Are there not handled callin or decapsulation bindings 
+		// for this class
+		if (bindingEntrySet.size() > 0 || accessEntrySet.size() > 0) {
+			// Yes, so start the transformation, parse the bytecode
+			// and do load time transforming, if this method is called
+			// at load time
+			startTransformation();
+			parseBytecode();
+			prepareAsPossibleBaseClass();
+			prepareTeamActivation();
+		} else if (isFirstTransformation()) {
+			// No, so only do load time transforming, if this method is called
+			// at load time
+			startTransformation();
+			prepareAsPossibleBaseClass();
+			prepareTeamActivation();
+			endTransformation();
+		}
+
+		for (Map.Entry<Method, WeavingTask> entry : bindingEntrySet) {
+			WeavingTask task = entry.getValue();
+			Method method = entry.getKey();
+			switch (task.getType()) {
+			// Weave callin binding to a method of a subclass, that is not implemented
+			// in the subclass
+			case WEAVE_BINDING_OF_SUBCLASS:
+				// Is the method implemented in this class?
+				if (method.isImplemented()) {
+					// Yes, so weave this class
+					weaveBindingOfSubclass(task);
+				} else {
+					//No, so just delegate the weaving task to the superclass
+					AbstractBoundClass superclass = getSuperclass();
+					// If superclass is null, her is something wrong
+					if (superclass != null) {
+						superclass.addWeavingTask(task);
+						weaveSuperCallInCallOrig(task); // ensure we're actually calling that super version
+					}
+				}
+				break;
+			// Weave callin binding to a method of this class
+			case WEAVE_BINDING:
+				if (method.isStatic()) {
+					weaveBindingInStaticMethod(task);
+				} else {
+					// Is the method implemented in this class?
+					if (method.isImplemented()) {
+						// So redefine the method
+						weaveBindingInImplementedMethod(task);
+					} else {
+						//No, so weave this class and delegate to the super class
+						weaveBindingInNotImplementedMethod(task);
+						AbstractBoundClass superclass = getSuperclass();
+						Method superMethod = superclass.getMethod(method.getName(), method.getSignature(),
+																  task.isHandleCovariantReturn());
+						WeavingTask newTask = new WeavingTask(
+								WeavingTask.WeavingTaskType.WEAVE_BINDING_OF_SUBCLASS,
+								superMethod.getName(), superMethod.getSignature(),
+								task.isHandleCovariantReturn());
+						superclass.addWeavingTask(newTask);
+					}
+
+// Original comment:
+//   If this method is private, the callin binding is not
+//   inherited by the subclasses
+// However, this conflicts with test415_nonexistingBaseMethod3i,
+// where an empty callAllBindings() was overriding a non-empty one.
+// see also Method.getId()
+//					if (!method.isPrivate()) {
+						// Delegate the WeavingTask to the subclasses
+						for (AbstractBoundClass subclass : getSubclasses()) {
+							Method subMethod = subclass.getMethod(method.getName(), method.getSignature(),
+																  task.isHandleCovariantReturn());
+							WeavingTask newTask = new WeavingTask(
+									WeavingTask.WeavingTaskType.WEAVE_INHERITED_BINDING,
+									subMethod.getName(), subMethod.getSignature(),
+									task.isHandleCovariantReturn());
+							subclass.addWeavingTask(newTask);
+							TeamManager.mergeJoinpoints(this, subclass, method, subMethod, task.isHandleCovariantReturn());
+						}
+//					}
+				}
+				break;
+			// Weave Binding inherited from the superclass
+			case WEAVE_INHERITED_BINDING:
+				if (method.isImplemented()) {
+					weaveBindingInImplementedMethod(task);
+				} else {
+					weaveBindingInNotImplementedMethod(task);
+				}
+
+				// Delegate the WeavingTask to the subclasses
+				for (AbstractBoundClass subclass : getSubclasses()) {
+					Method subMethod = subclass.getMethod(method.getName(), method.getSignature(),
+														  task.isHandleCovariantReturn());
+					WeavingTask newTask = new WeavingTask(
+							WeavingTask.WeavingTaskType.WEAVE_INHERITED_BINDING, subMethod
+									.getName(), subMethod.getSignature(),
+									task.isHandleCovariantReturn());
+					subclass.addWeavingTask(newTask);
+					TeamManager.mergeJoinpoints(this, subclass, method, subMethod, task.isHandleCovariantReturn());
+				}
+
+				break;
+			}
+			
+			// Mark all WeavingTasks for callin bindings 
+			// as completed
+			completedBindingTasks.put(method, task);
+		}
+		
+		//handle all WeavinTasks for decapsulation bindings
+		for (Map.Entry<Member, WeavingTask> entry : accessEntrySet) {
+			WeavingTask task = entry.getValue();
+			Member member = entry.getKey();
+			
+			switch (task.getType()) {
+			// handle decapsulation binding to a field
+			case WEAVE_FIELD_ACCESS:
+				prepareForFirstMemberAccess();
+				Field field = getField(task.getMemberName(), task
+						.getMemberSignature());
+				weaveFieldAccess(field, field.getId(this));
+				if (!field.isStatic()) {
+					// If the field is not static it could be accessed through a subclass
+					// so weave the subclass
+					for (AbstractBoundClass subclass : getSubclasses()) {
+						WeavingTask newTask = new WeavingTask(
+								WeavingTask.WeavingTaskType.WEAVE_INHERITED_MEMBER_ACCESS,
+								null, null, false/*handleCovariantReturn*/);
+						subclass.addWeavingTask(newTask);
+					}
+				}
+				break;
+			// handle decaspulation binding to a method
+			case WEAVE_METHOD_ACCESS:
+				prepareForFirstMemberAccess();
+				Method method = getMethod(task.getMemberName(), task.getMemberSignature(),
+										  task.isHandleCovariantReturn());
+				weaveMethodAccess(method, method.getId(this));
+				if (!method.isStatic()) {
+					// If the method is not static it could be accessed through a subclass
+					// so weave the subclass
+					for (AbstractBoundClass subclass : getSubclasses()) {
+						WeavingTask newTask = new WeavingTask(
+								WeavingTask.WeavingTaskType.WEAVE_INHERITED_MEMBER_ACCESS,
+								null, null, false/*handleCovariantReturn*/);
+						subclass.addWeavingTask(newTask);
+					}
+				}
+				break;
+			case WEAVE_INHERITED_MEMBER_ACCESS:
+				prepareForFirstMemberAccess();
+				break;
+			}
+			
+			// Mark all WeavingTasks for decapsulation bindings 
+			// as completed
+			completedAccessTasks.put(member, task);
+		}
+		if (openBindingTasks.size() > 0 || openAccessTasks.size() > 0) {
+			// Weave the class, if the method is not called at load time
+			endTransformation();
+		}
+		openBindingTasks.clear();
+		openAccessTasks.clear();
+	}
+
+	public void handleAddingOfBinding(IBinding binding) {
+		WeavingTask.WeavingTaskType type = null;
+		switch (binding.getType()) {
+		case CALLIN_BINDING:
+			type = WeavingTask.WeavingTaskType.WEAVE_BINDING;
+			break;
+		case FIELD_ACCESS:
+			type = WeavingTask.WeavingTaskType.WEAVE_FIELD_ACCESS;
+			break;
+		case METHOD_ACCESS:
+			type = WeavingTask.WeavingTaskType.WEAVE_METHOD_ACCESS;
+			break;
+		default:
+			throw new RuntimeException("Unknown binding type: "
+					+ binding.getType().name());
+		}
+		if (   binding.getType() == IBinding.BindingType.CALLIN_BINDING 
+			&& !binding.getBoundClass().equals(binding.getDeclaringBaseClassName()))
+			try {
+				// need to load the declaring base class outside the transform() callback:
+				this.loader.loadClass(binding.getDeclaringBaseClassName().replace('/', '.'));
+			} catch (ClassNotFoundException e) {
+				throw new NoClassDefFoundError(e.getMessage());
+			}
+		WeavingTask task = new WeavingTask(type, binding.getMemberName(), binding.getMemberSignature(), binding.isHandleCovariantReturn());
+		addWeavingTask(task);
+	}
+	
+	private void addWeavingTask(WeavingTask task) {
+		boolean isNewTask = addWeavingTaskLazy(task);
+
+		if (this.isLoaded && isNewTask) {
+			handleTaskList();
+		}
+	}
+	
+	private boolean addWeavingTaskLazy(WeavingTask task) {
+		WeavingTask.WeavingTaskType type = task.getType();
+		boolean isNewTask = false;
+		if (type == WeavingTask.WeavingTaskType.WEAVE_BINDING
+				|| type == WeavingTask.WeavingTaskType.WEAVE_BINDING_OF_SUBCLASS
+				|| type == WeavingTask.WeavingTaskType.WEAVE_INHERITED_BINDING) {
+			isNewTask = addBindingWeavingTask(task);
+		} else {
+			isNewTask = addAccessWeavingTask(task);
+		}
+		
+		return isNewTask;
+	}
+
+	/**
+	 * Handle a new WeavingTask for decapsulation and 
+	 * figures out if weaving is needed for this task 
+	 * @param task
+	 * @return
+	 */
+	private boolean addAccessWeavingTask(WeavingTask task) {
+		WeavingTask.WeavingTaskType type = task.getType();
+		Member member = null;
+		switch (type) {
+		case WEAVE_FIELD_ACCESS:
+			member = getField(task.getMemberName(), task.getMemberSignature());
+			break;
+		case WEAVE_METHOD_ACCESS:
+			member = getMethod(task.getMemberName(), task.getMemberSignature(), false/*covariantReturn*/);
+			break;
+		case WEAVE_INHERITED_MEMBER_ACCESS:
+			openAccessTasks.put(null, task);
+			return true;
+		}
+		
+		synchronized (member) {
+			WeavingTask prevTask = completedAccessTasks.get(member);
+			// Is there a already completed task for the member?
+			if (prevTask == null) {
+				// No, so check the open tasks
+				prevTask = openAccessTasks.get(member);
+			}
+	
+			// Is there a open task for the member?
+			if (prevTask == null) {
+				// No, so weaving is needed
+				openAccessTasks.put(member, task);
+				return true;
+			} else {
+				//Yes, so weaving is not needed
+				return false;
+			}
+		}
+	}
+
+	/**
+	 * Handle a new WeavingTask for a callin binding and 
+	 * figures out if weaving is needed for this task 
+	 * @param task
+	 * @return
+	 */
+	private boolean addBindingWeavingTask(WeavingTask task) {
+		Method method = getMethod(task.getMemberName(), task.getMemberSignature(),
+								  task.isHandleCovariantReturn());
+		synchronized (method) {
+			WeavingTask prevTask = completedBindingTasks.get(method);
+			// Is there a already completed task for the method?
+			if (prevTask == null) {
+				// No, so check the open tasks
+				prevTask = openBindingTasks.get(method);
+			}
+		
+			// Is there a open task for the member?
+			if (prevTask == null) {
+				//No, so weaving is needed
+				task.setDoAllTransformations(true);
+				openBindingTasks.put(method, task);
+				return true;
+			}
+	
+			switch (prevTask.getType()) {
+			case WEAVE_BINDING:
+				return false;
+			case WEAVE_BINDING_OF_SUBCLASS:
+				// In  this case only the callAllBings was redefined.
+				if (task.getType() != WeavingTask.WeavingTaskType.WEAVE_BINDING_OF_SUBCLASS) {
+					// Do the other transformations, if the new WeavingTask is not the same
+					// as already existing
+					openBindingTasks.put(method, task);
+					return true;
+				}
+				return false;
+			case WEAVE_INHERITED_BINDING:
+				return false;
+			default:
+				throw new RuntimeException("Unknown WeavingTaskType: "
+						+ prevTask.getType().name());
+			}
+		}
+	}
+
+	/**
+	 * Merge tasks of two AbstractBoundClasses (this class and a other).
+	 * This method is called if a currently loaded has to be merged 
+	 * with a anonymous subclass
+	 * @param clazz
+	 * @return
+	 */
+	protected boolean mergeTasks(AbstractBoundClass clazz) {
+		boolean isNewTask = false;
+		for (Map.Entry<Method, WeavingTask> entry : clazz.openBindingTasks
+				.entrySet()) {
+			isNewTask |= addWeavingTaskLazy(entry.getValue());
+		}
+		
+		for (Map.Entry<Member, WeavingTask> entry : clazz.openAccessTasks
+				.entrySet()) {
+			isNewTask |= addWeavingTaskLazy(entry.getValue());
+		}
+		
+		return isNewTask;
+	}
+
+	private void weaveBindingInStaticMethod(WeavingTask task) {
+		prepareForFirstStaticTransformation();
+		Method method = getMethod(task.getMemberName(), task.getMemberSignature(),
+								  false/*covariantReturn*/);
+		int joinpointId = TeamManager
+				.getJoinpointId(getMethodIdentifier(method));
+		int boundMethodId = method.getId(this);
+
+		moveCodeToCallOrig(method, boundMethodId);
+		createDispatchCodeInOrgMethod(method, joinpointId, boundMethodId);
+	}
+
+	/**
+	 * Do all transformations for a method, that is not implemented
+	 * in this class
+	 * @param task
+	 */
+	private void weaveBindingInNotImplementedMethod(WeavingTask task) {
+		prepareForFirstTransformation();
+		Method method = getMethod(task.getMemberName(), task.getMemberSignature(),
+								  task.isHandleCovariantReturn());
+		int joinpointId = TeamManager
+				.getJoinpointId(getMethodIdentifier(method));
+		int boundMethodId = method.getId(this);
+		if (task.doAllTransformations()) {
+			createDispatchCodeInCallAllBindings(joinpointId, boundMethodId);
+			// TODO(SH): instead of iterating superclasses fetch it from the Binding
+			boolean isWeavable = true; // weavable unless we find it to be declared in an unweavable super
+			AbstractBoundClass superClass = getSuperclass();
+			while (superClass != null) {
+				if (superClass.isJavaLangObject()) {
+					isWeavable = false;
+					break;
+				}
+				Method superMethod = superClass.getMethod(task.getMemberName(), task.getMemberSignature(), task.isHandleCovariantReturn());
+				if (superMethod.isImplemented()) {
+					isWeavable = ObjectTeamsTransformer.isWeavable(superClass.getInternalName());
+					break;
+				}
+				superClass = superClass.getSuperclass();
+			}
+			if (isWeavable)
+				createSuperCallInCallOrig(boundMethodId);
+			else
+				// can't weave into the declaring class, add an override here:
+				createCallAllBindingsCallInOrgMethod(method, joinpointId, true/*needToAddMethod*/);
+		} else {
+			createDispatchCodeInCallAllBindings(joinpointId, boundMethodId);
+		}
+	}
+
+	/** 
+	 * While delegating a task from a sub class to the super class,
+ 	 * ensure that the super version is actually called.
+	 */
+	private void weaveSuperCallInCallOrig(WeavingTask task) {
+		prepareForFirstTransformation();
+		Method method = getMethod(task.getMemberName(), task.getMemberSignature(),
+				                  task.isHandleCovariantReturn());
+		int boundMethodId = method.getId(this);
+		if (task.doAllTransformations()) {
+			createSuperCallInCallOrig(boundMethodId);
+		}		
+	}
+
+	/**
+	 * Do all transformations for a method, that is implemented
+	 * in this class
+	 * @param task
+	 */
+	private void weaveBindingInImplementedMethod(WeavingTask task) {
+		prepareForFirstTransformation();
+		Method method = getMethod(task.getMemberName(), task.getMemberSignature(),
+								  task.isHandleCovariantReturn());
+		int joinpointId = TeamManager
+				.getJoinpointId(getMethodIdentifier(method));
+		int boundMethodId = method.getId(this);
+		if (task.doAllTransformations()) {
+			moveCodeToCallOrig(method, boundMethodId);
+			createDispatchCodeInCallAllBindings(joinpointId, boundMethodId);
+			createCallAllBindingsCallInOrgMethod(method, boundMethodId, false);
+		} else {
+			createDispatchCodeInCallAllBindings(joinpointId, joinpointId);
+		}
+	}
+
+	/**
+	 * Do all transformations for a method, that is bound 
+	 * but not implemented in a subclass
+	 * @param task
+	 */
+	private void weaveBindingOfSubclass(WeavingTask task) {
+		prepareForFirstTransformation();
+		Method method = getMethod(task.getMemberName(), task.getMemberSignature(),
+								  task.isHandleCovariantReturn());
+		int boundMethodId = method.getId(this);
+		moveCodeToCallOrig(method, boundMethodId);
+		createCallAllBindingsCallInOrgMethod(method, boundMethodId, false);
+
+	}
+	
+	@Override
+	public String toString() {
+		return this.name+"["+this.id+"]";
+	}
+
+	// See AsmBoundClass or AsmWritableBoundClass for documentation
+	
+	protected abstract void startTransformation();
+
+	protected abstract void endTransformation();
+
+	protected abstract void prepareAsPossibleBaseClass();
+
+	protected abstract void prepareTeamActivation();
+
+	protected abstract void createSuperCallInCallOrig(int boundMethodId);
+
+	protected abstract void createCallAllBindingsCallInOrgMethod(
+			Method boundMethod, int joinpointId, boolean needToAddMethod);
+
+	protected abstract void createDispatchCodeInCallAllBindings(
+			int joinpointId, int boundMethodId);
+
+	protected abstract void moveCodeToCallOrig(Method boundMethod, int boundMethodId);
+
+	protected abstract void prepareForFirstTransformation();
+
+	protected abstract void prepareForFirstStaticTransformation();
+
+	protected abstract boolean isFirstTransformation();
+
+	protected abstract void createDispatchCodeInOrgMethod(Method boundMethod,
+			int joinpointId, int boundMethodId);
+
+	protected abstract void prepareForFirstMemberAccess();
+
+	protected abstract void weaveFieldAccess(Field field, int accessId);
+
+	protected abstract void weaveMethodAccess(Method method, int accessId);
+
+	public abstract boolean isTransformationActive();
+	
+	public abstract byte[] getBytecode();
+
+	public void dump(byte[] classfileBuffer, String postfix) {}
+
+	public abstract int compare(String callinLabel1, String callinLabel2);
+
+	public void addWiringTask(ISubclassWiringTask wiringTask) {
+		if (this.wiringTasks == null)
+			this.wiringTasks = new ArrayList<ISubclassWiringTask>();
+		this.wiringTasks.add(wiringTask);
+	}
+
+	public void performWiringTasks(AbstractBoundClass superclass, AbstractBoundClass subclass) {
+		if (this.wiringTasks == null)
+			return;
+		synchronized (this.wiringTasks) {			
+			for (ISubclassWiringTask task : this.wiringTasks)
+				task.wire(superclass, subclass);
+			this.wiringTasks.clear();
+		}
+	}
+
+}
diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/AbstractTeam.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/AbstractTeam.java
new file mode 100644
index 0000000..31504ca
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/AbstractTeam.java
@@ -0,0 +1,76 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode;

+

+import java.util.Collection;

+import java.util.Set;

+import java.util.TreeSet;

+

+import org.eclipse.objectteams.otredyn.runtime.IBoundTeam;

+

+/**

+ * Represents a team class and stores the bindings this team has got.

+ */

+public abstract class AbstractTeam extends AbstractBoundClass implements IBoundTeam {

+	/**

+	 * All relevant bindings (callin and decapsulation) of this team.

+	 * By internally using a TreeSet the set of bindings is naturally sorted 

+	 * based on {@link Binding#compareTo(Binding)} (see there).

+	 */

+	private Set<Binding> bindings;

+	private int highestAccessId;

+

+	protected AbstractTeam(String name, String id, ClassLoader loader) {

+		super(name, id, loader);

+		bindings = new TreeSet<Binding>();

+	}

+

+	/**

+	 * Adds a binding to the team.

+	 * This method is intended to be called, 

+	 * while parsing the bytecode

+	 * @param binding

+	 */

+	public void addBinding(Binding binding) {

+		bindings.add(binding);

+	}

+

+	public Collection<Binding> getBindings() {

+		parseBytecode();

+		return bindings;

+	}

+	

+	/**

+	 * Returns the superclass of this team as AbstractTeam

+	 */

+	@Override

+	public AbstractTeam getSuperclass() {

+		return (AbstractTeam) super.getSuperclass();

+	}

+	

+	/**

+	 * Record that this team uses the given accessId.

+	 * @param accessId

+	 */

+	public void recordAccessId(int accessId) {

+		this.highestAccessId = Math.max(this.highestAccessId, accessId);

+	}

+

+	public int getHighestAccessId() {

+		return highestAccessId;

+	}

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/Binding.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/Binding.java
new file mode 100644
index 0000000..852e176
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/Binding.java
@@ -0,0 +1,165 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode;

+

+import org.eclipse.objectteams.otredyn.runtime.IBinding;

+

+/**

+ * This class represents a callin or decapsulation binding

+ * @author Oliver Frank

+ */

+public class Binding implements Comparable<Binding>, IBinding {

+	

+	/** The callin modifier 'before' */

+	public static final int BEFORE = 1;

+	/** The callin modifier 'replace' */

+	public static final int REPLACE = 2;

+	/** The callin modifier 'after' */

+	public static final int AFTER = 3;

+	

+	AbstractBoundClass teamClass;

+	private String callinLabel;

+	private String boundClass;

+	private String memberName;

+	private String memberSignature;

+	private String declaringBaseClassName;

+	private int callinModifier;

+	private int callinId;

+	private IBinding.BindingType type;

+	private boolean isHandleCovariantReturn;

+	

+	public IBinding.BindingType getType() {

+		return type;

+	}

+

+	/**

+	 * Create a callin binding.

+	 */

+	public Binding(AbstractBoundClass teamClass,

+			String roleClassName, String callinLabel, String boundClassName, 

+			String memberName, String memberSignature, String declaringBaseClassName, 

+			int callinModifier, int callinId, boolean handleCovariantReturn) 

+	{

+		this.teamClass = teamClass;

+		this.callinLabel = callinLabel;

+		this.boundClass = boundClassName;

+		this.memberName = memberName;

+		this.memberSignature = memberSignature;

+		this.declaringBaseClassName = declaringBaseClassName;

+		this.callinModifier = callinModifier;

+		this.callinId = callinId;

+		this.type = IBinding.BindingType.CALLIN_BINDING;

+		this.isHandleCovariantReturn = handleCovariantReturn;

+	}

+

+	/**

+	 * Create a method or field access binding (decapsulation).

+	 */

+	public Binding(AbstractBoundClass teamClass,

+			String boundClassName, 

+			String memberName, String memberSignature, int callinId, IBinding.BindingType type) 

+	{

+		this.teamClass = teamClass;

+		this.boundClass = boundClassName;

+		this.memberName = memberName;

+		this.memberSignature = memberSignature;

+		this.callinId = callinId;

+		this.type = type;

+	}

+

+	public String getBoundClass() {

+		return boundClass;

+	}

+	

+	public String getMemberName() {

+		return memberName;

+	}

+

+	public String getMemberSignature() {

+		return memberSignature;

+	}

+

+	public int getCallinId() {

+		return callinId;

+	}

+

+	public boolean isHandleCovariantReturn() {

+		return this.isHandleCovariantReturn;

+	}

+	

+	public String getDeclaringBaseClassName() {

+		return this.declaringBaseClassName;

+	}

+

+	@Override

+	public boolean equals(Object obj) {

+		Binding other = (Binding) obj;

+		return boundClass.equals(other.boundClass)

+				&& memberName.equals(other.memberName)

+				&& memberSignature.equals(other.memberSignature)

+				&& type == other.type && callinId == other.callinId;

+	}

+	

+	public int compareTo(Binding other) {

+		// ordering strategy for callin bindings:

+		// - first criterion: callinModifier: before/after have higher priority than replace.

+		// - second criterion: precedence (only relevant among callins of the same callin modifier).

+		// the set AbstractTeam.bindings is sorted low-to-high.

+		// then TeamManager.handleTeamStateChange processes all bindings from low-to-high

+		// inserting each at the front of the list of active teams, such that last added

+		// will indeed have highest priority, which is in line with ordering by activation time.

+		int compare = 0;

+		if (this.callinLabel == null || other.callinLabel == null) {

+			// at least one binding is a decaps binding

+			if (this.callinLabel != null)

+				return 1;

+			else if (other.callinLabel != null)

+				return -1;

+		} else {

+			if (this.callinModifier != other.callinModifier) {

+				// replace has lower priority than before/after:

+				if (this.callinModifier == REPLACE)

+					return -1;

+				else if (other.callinModifier == REPLACE)

+					return 1;

+			}

+			// the following comparison respects precedence:

+			compare = this.teamClass.compare(this.callinLabel, other.callinLabel);

+			if (compare != 0)

+				return compare;

+		}

+		return (boundClass + memberName + memberSignature).compareTo(other.boundClass + other.memberName + other.memberSignature);

+	}

+

+	@Override

+	public String toString() {

+		StringBuffer buf = new StringBuffer();

+		switch (this.type) {

+		case CALLIN_BINDING: buf.append("callin: ");break;

+		case METHOD_ACCESS: buf.append("callout: ");break;

+		case FIELD_ACCESS: buf.append("callout-to-field: ");break;

+		}

+		buf.append('{');

+		buf.append(this.callinId);

+		buf.append("} ");

+		buf.append(this.boundClass);

+		buf.append('.');

+		buf.append(this.memberName);

+		buf.append(this.memberSignature);

+		return buf.toString();

+	}

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/BytecodeProviderFactory.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/BytecodeProviderFactory.java
new file mode 100644
index 0000000..6f9a2b6
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/BytecodeProviderFactory.java
@@ -0,0 +1,35 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode;

+

+/**

+ * This class creates and provides a singleton instance of

+ * IBytecodeProvider. 

+ * Actually it returns a instance of InMemeoryBytecodeProvider.

+ * In the future, this class should decides (e.g. by a system property), 

+ * which BytecodeProvider should be used   

+ * @author Oliver Frank

+ */

+public class BytecodeProviderFactory {

+	private static IBytecodeProvider instance;

+	public static synchronized IBytecodeProvider getBytecodeProvider() {

+		if (instance == null) {

+			instance = new InMemoryBytecodeProvider();

+		}

+		return instance;

+	}

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/ClassRepository.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/ClassRepository.java
new file mode 100644
index 0000000..48bff21
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/ClassRepository.java
@@ -0,0 +1,193 @@
+/**********************************************************************
+ * This file is part of "Object Teams Dynamic Runtime Environment"
+ * 
+ * Copyright 2009, 2012 Oliver Frank and others.
+ * 
+ * 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:
+ *		Oliver Frank - Initial API and implementation
+ *		Stephan Herrmann - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otredyn.bytecode;
+
+import java.util.HashMap;
+import java.util.IdentityHashMap;
+import java.util.Map;
+
+import org.eclipse.objectteams.otredyn.bytecode.asm.AsmClassRepository;
+import org.eclipse.objectteams.otredyn.runtime.IClassRepository;
+import org.eclipse.objectteams.otredyn.runtime.TeamManager;
+
+/**
+ * This class creates and provides instances of
+ * AbstractBoundClass and AbstractTeam. It is the only
+ * instance that should do this. It is a singelton, thats
+ * why the constructor should not called directly.
+ * The instance is provided by getInstance. 
+ * @author Oliver Frank
+ */
+public abstract class ClassRepository implements IClassRepository {
+	private static ClassRepository instance;
+	
+	protected ClassRepository() {
+		
+	}
+	
+	/**
+	 * Returns a singleton instance of the ClassRepository.
+	 * @return
+	 */
+	public static synchronized ClassRepository getInstance() {
+		if (instance == null) {
+			instance = new AsmClassRepository();
+			TeamManager.setup(instance);
+		}
+		
+		return instance;
+	}
+	
+	protected static final String ANONYMOUS_SUBCLASS_NAME = "AnonymousSubclass";
+	
+	private Map<String, AbstractTeam> boundClassMap = new HashMap<String, AbstractTeam>();
+	private Map<AbstractBoundClass, AbstractBoundClass> anonymousSubclassMap = new IdentityHashMap<AbstractBoundClass, AbstractBoundClass>();
+	
+	/**
+	 * Returns a instance of AbstractBoundClass for the
+	 * given FQN and id. If there is no instance it
+	 * is created. The class have not to be loaded to get
+	 * an instance of AbstractBoundClass representing this class.
+	 * It guarantees, that it returns always the same 
+	 * instance for the same id. More formally:
+	 * if id1.equals(id2) then getBoundClass(..., id1) == getBoundClass(id2) 
+	 * @param className the name of the class
+	 * @param id a globally unique identifier for the class 
+	 * @return
+	 */
+	public synchronized AbstractBoundClass getBoundClass(String className, String id, ClassLoader loader) {
+		AbstractTeam clazz = boundClassMap.get(id);
+		if (clazz == null) {
+			clazz = createClass(className, id, BytecodeProviderFactory.getBytecodeProvider(), loader);
+			boundClassMap.put(id, clazz);
+		}
+		
+		return clazz;
+	}
+	
+	/**
+	 * Returns a instance of AbstractBoundClass for the
+	 * given FQN and id and sets the bytecode for this class. 
+	 * If there is no instance it is created. 
+	 * This class should be called while loading the class.
+	 * It guarantees, that it returns always the same 
+	 * instance for the same id. More formally:
+	 * if id1.equals(id2) then getBoundClass(..., id1) == getBoundClass(..., id2) 
+	 * @param className the name of the class
+	 * @param id a globally unique identifier for the class 
+	 * @return
+	 */
+	public synchronized AbstractBoundClass getBoundClass(String className, String id, byte[] classBytes, ClassLoader loader) 
+	{
+		AbstractTeam clazz = boundClassMap.get(id);
+		// set the bytecode in the BytecodeProvider
+		IBytecodeProvider bytecodeProvider = BytecodeProviderFactory.getBytecodeProvider();
+		bytecodeProvider.setBytecode(id, classBytes);
+		if (clazz == null) {
+			clazz = createClass(className, id, bytecodeProvider, loader);
+		} 
+		
+		boundClassMap.put(id, clazz);
+
+		clazz.setLoaded();
+		
+		return clazz;
+	}
+
+	/**
+	 * This method links a class with its superclass.
+	 * It checks if the superclass was already loaded.
+	 * If it was already loaded it merges this class with
+	 * the anonymous subclass of its superclass
+	 * @param clazz the subclass
+	 */
+	public void linkClassWithSuperclass(AbstractBoundClass clazz) {
+		// FIXME(SH): also link with tsuper classes??
+		AbstractBoundClass superclass = clazz.getSuperclass();
+		AbstractBoundClass anonymousSubclass = null;
+		if (superclass != null) {
+			anonymousSubclass = anonymousSubclassMap.get(superclass);
+		}
+		
+		//Is there an anonmous subclass, that corresponds with this class
+		if (anonymousSubclass != null) {
+			//Yes, so merge the tasks
+			AbstractBoundClass newAnonymousSubclass = createClass(ANONYMOUS_SUBCLASS_NAME, 
+															      ANONYMOUS_SUBCLASS_NAME, 
+															      BytecodeProviderFactory.getBytecodeProvider(),
+															      clazz.getClassLoader());
+			superclass.removeSubclass(anonymousSubclass);
+			superclass.addSubclass(newAnonymousSubclass);
+			superclass.addSubclass(clazz);
+			newAnonymousSubclass.mergeTasks(anonymousSubclass);
+			clazz.mergeTasks(anonymousSubclass);
+			anonymousSubclass.performWiringTasks(superclass, clazz);
+			anonymousSubclassMap.put(superclass, newAnonymousSubclass);
+		}
+	}
+
+	/**
+	 * Returns a instance of AbstractTeam for the
+	 * given FQN and id. If there is no instance it
+	 * is created. 
+	 * It guarantees, that it returns always the same 
+	 * instance for the same id. More formally:
+	 * if id1.equals(id2) then getTeam(..., id1) == getTeam(..., id2).
+	 * This method should only be called, if it is known
+	 * that the name identifies a team and not a class.
+	 * Otherwise call getBoundClass().isTeam() to check this. 
+	 * @param teamName the name of the team
+	 * @param id a globally unique identifier for the team 
+	 * @return
+	 */
+	public AbstractTeam getTeam(String teamName, String id, ClassLoader loader) {
+		return (AbstractTeam) getBoundClass(teamName, id, loader);
+	}
+	
+	/**
+	 * Returns a instance of AbstractBoundClass representing
+	 * a anonymous subclass. A anonymous subclass stands for all subclasses,
+	 * that are not known yet and stores the WeavingTasks inherited 
+	 * from the superclass. This class could not have got direct bindings.
+	 * If a real subclass of its superclass is loaded all WeavingTasks are
+	 * merged with the real subclass 
+	 * @param abstractBoundClass
+	 * @return
+	 */
+	protected AbstractBoundClass getAnonymousSubclass(
+			AbstractBoundClass abstractBoundClass) {
+		AbstractBoundClass anonymousSubclass = anonymousSubclassMap.get(abstractBoundClass);
+		if (anonymousSubclass == null) {
+			anonymousSubclass = createClass(ANONYMOUS_SUBCLASS_NAME, 
+										    ANONYMOUS_SUBCLASS_NAME, 
+										    BytecodeProviderFactory.getBytecodeProvider(),
+										    abstractBoundClass.getClassLoader());
+			anonymousSubclass.setSuperClassName(abstractBoundClass.getName());
+			anonymousSubclassMap.put((AbstractTeam) abstractBoundClass, anonymousSubclass);
+		}
+		return anonymousSubclass;
+	}
+	
+	/**
+	 * Creates a instance of AbstractBoundClass and AbstracTeam
+	 * @param name
+	 * @param id
+	 * @param bytecodeProvider
+	 * @return
+	 */
+	protected abstract AbstractTeam createClass(String name, String id, IBytecodeProvider bytecodeProvider, ClassLoader loader);
+}
diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/Field.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/Field.java
new file mode 100644
index 0000000..617d209
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/Field.java
@@ -0,0 +1,46 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode;

+

+import org.eclipse.objectteams.otredyn.runtime.IBoundClass;

+

+/**

+ * Represents a field of a class

+ * @author Oliver Frank

+ */

+public class Field extends Member {

+

+	public Field(String name, String signature) {

+		super(name, signature);

+	}

+	

+	public Field(String name, String signature, boolean isStatic, int accessFlags) {

+		super(name, signature, isStatic, accessFlags);

+	}

+

+	/**

+	 * Returns a globally unique id for the field

+	 * @param clazz

+	 * @return 

+	 */

+	@Override

+	public int getId(IBoundClass clazz) {

+		String key = null;

+		key = clazz.getId() + getName() + getSignature();

+		return getId(key);

+	}

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/IBytecodeProvider.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/IBytecodeProvider.java
new file mode 100644
index 0000000..216a1f4
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/IBytecodeProvider.java
@@ -0,0 +1,43 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode;

+

+/**

+ * Interface for classes, that provide bytecode for other classes

+ * @author Oliver Frank

+ */

+public interface IBytecodeProvider {

+	/**

+	 * Returns the bytecode of the class with the given id.

+	 * Attention: This may be an expensive operation 

+	 * (e.g. if the bytecode must be read from the hard disk).

+	 * @param classId

+	 * @return the bytecode of the class or null, if the class

+	 * was not loaded yet. 

+	 */

+	public byte[] getBytecode(String classId);

+	

+	/**

+	 * Sets the bytecode of the class with the given id

+	 * in the BytecodeProvider

+	 * Attention: This may be an expensive operation 

+	 * (e.g. if the bytecode is written to the hard disk).

+	 * @param classId

+	 * @param bytecode

+	 */

+	public void setBytecode(String classId, byte[] bytecode);

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/IRedefineStrategy.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/IRedefineStrategy.java
new file mode 100644
index 0000000..fd06f87
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/IRedefineStrategy.java
@@ -0,0 +1,35 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode;

+

+import java.lang.instrument.UnmodifiableClassException;

+

+/**

+ * Classes that implements this interface can redefine classes at runtime.

+ * @author Oliver Frank

+ */

+public interface IRedefineStrategy {

+	

+	/**

+	 * Redefines a class at runtime. 

+	 * @param clazz the existing class instance

+	 * @param bytecode the new bytecode for this class 

+	 * @throws ClassNotFoundException the class was not loaded yet

+	 * @throws UnmodifiableClassException it is impossible to redefine the class

+	 */

+	public void redefine(Class<?> clazz, byte[] bytecode) throws ClassNotFoundException, UnmodifiableClassException;

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/InMemoryBytecodeProvider.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/InMemoryBytecodeProvider.java
new file mode 100644
index 0000000..57e9bb7
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/InMemoryBytecodeProvider.java
@@ -0,0 +1,51 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode;

+

+import java.util.HashMap;

+import java.util.Map;

+

+/**

+ * This class is an implementaion of IBytecodeProvider

+ * It keeps the bytecode of all classes in memory.

+ * @author Oliver Frank

+ */

+public class InMemoryBytecodeProvider implements IBytecodeProvider {

+

+	private Map<String, byte[]> bytecodeMap = new HashMap<String, byte[]>();

+	

+	/**

+	 * Returns the bytecode of a class with the given id.

+	 * In this implementation, this is not an expensive operation. 

+	 * @return the bytecode of the class or null, if the class

+	 * was not loaded yet.

+	 */

+	public byte[] getBytecode(String className) {

+		return bytecodeMap.get(className);

+	}

+

+	/**

+	 * Sets the bytecode of the class with the given id

+	 * in the BytecodeProvider

+	 * In this implementation, this is not an expensive operation.

+	 * @param classId

+	 * @param bytecode

+	 */

+	public void setBytecode(String className, byte[] bytecode) {

+		bytecodeMap.put(className, bytecode);

+	}

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/Member.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/Member.java
new file mode 100644
index 0000000..a017daf
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/Member.java
@@ -0,0 +1,95 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode;

+

+import java.util.HashMap;

+import java.util.Map;

+

+import org.eclipse.objectteams.otredyn.runtime.IBoundClass;

+import org.eclipse.objectteams.otredyn.runtime.IMember;

+import org.objectweb.asm.Opcodes;

+

+/**

+ * Represents a member of a class.

+ * This class abstract. Instances of this class can only be created

+ * as {@link Field} or {@link Method}.

+ * @author Oliver Frank

+ */

+public abstract class Member implements IMember {

+	

+	private static Map<String, Integer> idMap = new HashMap<String, Integer>();

+	private static int currentId = 0;

+	

+	private String name;

+	private String signature;

+	private boolean isStatic;

+	private int accessFlags;

+

+	public Member(String name, String signature) {

+		this.name = name;

+		this.signature = signature;

+	}

+

+	public Member(String name, String signature, boolean isStatic, int accessFlags) {

+		this(name, signature);

+		this.isStatic = isStatic;

+		this.accessFlags = accessFlags;

+	}

+

+	public boolean isStatic() {

+		return isStatic;

+	}

+

+	public String getName() {

+		return name;

+	}

+

+	public String getSignature() {

+		return signature;

+	}

+

+	public void setStatic(boolean isStatic) {

+		this.isStatic = isStatic;

+	}

+	

+	public boolean isPrivate() {

+		return (this.accessFlags & Opcodes.ACC_PRIVATE) != 0;

+	}

+	

+	public int getAccessFlags() {

+		return this.accessFlags;

+	}

+	

+	/**

+	 * Returns a globally unique id for a given key.

+	 * @param key

+	 * @return

+	 */

+	protected int getId(String key) {

+		Integer id = idMap.get(key);

+		if (id == null) {

+			synchronized (idMap) {

+				idMap.put(key, currentId);

+				return currentId++;

+			}

+		}

+

+		return id;

+	}

+	

+	public abstract int getId(IBoundClass clazz);

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/Method.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/Method.java
new file mode 100644
index 0000000..b988f51
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/Method.java
@@ -0,0 +1,64 @@
+/**********************************************************************
+ * This file is part of "Object Teams Dynamic Runtime Environment"
+ * 
+ * Copyright 2009, 2012 Oliver Frank and others.
+ * 
+ * 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:
+ *		Oliver Frank - Initial API and implementation
+ *		Stephan Herrmann - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otredyn.bytecode;
+
+import org.eclipse.objectteams.otredyn.runtime.IBoundClass;
+import org.eclipse.objectteams.otredyn.runtime.IMethod;
+
+
+/**
+ * 
+ */
+public class Method extends Member implements IMethod {
+	
+	private boolean implemented;
+
+	public Method(String name, String signature) {
+		super(name, signature);
+	}
+
+	public Method(String name, String signature, boolean isStatic, int accessFlags) {
+		super(name, signature, isStatic, accessFlags);
+	}
+
+	public boolean isImplemented() {
+		return implemented;
+	}
+
+	public void setImplemented(boolean implemented) {
+		this.implemented = implemented;
+	}
+	
+	/**
+	 * Returns a globally unique id for the method
+	 * @param clazz
+	 * @return 
+	 */
+	@Override
+	public int getId(IBoundClass clazz) {
+		String key = null;
+		// special treatment of private conflicts with test415_nonexistingBaseMethod3i
+		// see also AbstractBoundClass.handleTaskList()
+		if (/*isPrivate() ||*/ isStatic()) {
+			key = clazz.getId() + getName() + getSignature();
+		} else {
+			key = getName() + getSignature();
+		}
+		
+		return getId(key);
+	}
+}
diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/OtreRedefineStrategy.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/OtreRedefineStrategy.java
new file mode 100644
index 0000000..7f854cf
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/OtreRedefineStrategy.java
@@ -0,0 +1,36 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode;

+

+import java.lang.instrument.ClassDefinition;

+import java.lang.instrument.UnmodifiableClassException;

+

+import org.eclipse.objectteams.otredyn.transformer.jplis.otreAgent;

+

+/**

+ * This implementation of {@link IRedefineStrategy} uses the

+ * JPLIS agent {@link otreAgent} to redefine classes.

+ * @author Oliver Frank

+ */

+public class OtreRedefineStrategy implements IRedefineStrategy {

+

+	public void redefine(Class<?> clazz, byte[] bytecode) throws ClassNotFoundException, UnmodifiableClassException {

+		ClassDefinition arr_cd[] = { new ClassDefinition(clazz, bytecode) };

+		otreAgent.getInstrumentation().redefineClasses(arr_cd);

+	}

+

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/RedefineStrategyFactory.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/RedefineStrategyFactory.java
new file mode 100644
index 0000000..93860b0
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/RedefineStrategyFactory.java
@@ -0,0 +1,37 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode;

+

+/**

+ * Provides a singleton instance of {@link IRedefineStrategy}.

+ * If no instance was set, this class returns the {@link OtreRedefineStrategy} 

+ * @author Oliver Frank

+ */

+public class RedefineStrategyFactory {

+	private static IRedefineStrategy redefineStrategy;

+

+	public static IRedefineStrategy getRedefineStrategy() {

+		if (redefineStrategy == null) {

+			redefineStrategy = new OtreRedefineStrategy();

+		}

+		return redefineStrategy;

+	}

+

+	public static void setRedefineStrategy(IRedefineStrategy redefineStrategy) {

+		RedefineStrategyFactory.redefineStrategy = redefineStrategy;

+	}

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/Types.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/Types.java
new file mode 100644
index 0000000..ed2435b
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/Types.java
@@ -0,0 +1,139 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode;

+

+/**

+ * Helper class to handle type strings used in the bytecode

+ * @author Oliver Frank

+ */

+public abstract class Types {

+	public final static int ACCESS_PACKAGE = 0; // class, field, method

+	public final static int ACCESS_PUBLIC = 1; // class, field, method

+	public final static int ACCESS_PRIVATE = 2; // class, field, method

+	public final static int ACCESS_PROTECTED = 4; // class, field, method

+	public final static int ACCESS_STATIC = 8; // field, method

+	public final static int TEAM  = 0x8000;

+	public final static int ROLE_FLAG = 2; // within OTClassFlags attribute

+    

+	public static final String VOID = "V";

+

+	public static final String BOOLEAN = "Z";

+

+	public static final String CHAR = "C";

+

+	public static final String BYTE = "B";

+

+	public static final String SHORT = "S";

+

+	public static final String INT = "I";

+

+	public static final String FLOAT = "F";

+

+	public static final String LONG = "J";

+

+	public static final String DOUBLE = "D";

+

+	private static final String ARRAY = "[";

+

+	public static String getAsArrayType(String className) {

+		if (className.length() == 1) {

+			return ARRAY + className;

+		}

+		

+		return ARRAY + "L" + className;

+	}

+	

+	public static String getAsType(String type) {

+		return "L" + type;

+	}

+	

+	public static String getAsType(Class<?> clazz) {

+		String type = null;

+		if (clazz.isPrimitive()) {

+			String name = clazz.getName();

+			if (name.compareTo("void") == 0) {

+				type = VOID;

+			} else if (name.compareTo("boolean") == 0) {

+				type = BOOLEAN;

+			} else if (name.compareTo("char") == 0) {

+				type = CHAR;

+			} else if (name.compareTo("byte") == 0) {

+				type = BYTE;

+			} else if (name.compareTo("short") == 0) {

+				type = SHORT;

+			} else if (name.compareTo("int") == 0) {

+				type = INT;

+			} else if (name.compareTo("float") == 0) {

+				type = FLOAT;

+			} else if (name.compareTo("long") == 0) {

+				type = LONG;

+			} else if (name.compareTo("double") == 0) {

+				type = DOUBLE;

+			}

+		} else {

+			type = clazz.getName().replace('.', '/');

+			if (!clazz.isArray()) {

+				type = "L" + type;

+			}

+		}

+		

+		return type;

+	}

+	

+	public static String getTypeStringForMethod(String returnType, String[] paramTypes) {

+		String result = "(";

+		if (paramTypes != null) {

+			for (String paramType : paramTypes) {

+				result += paramType;

+				if (paramType.length() > 2) {

+					result += ";";

+				}

+			}

+		}

+		result += ")" + returnType;

+		if (returnType.length() > 2) {

+			result += ";";

+		}

+		return result;

+	}

+	

+	public static String getTypeStringForMethod(Class<?> returnType, Class<?>[] paramTypes) {

+		String result = "(";

+		if (paramTypes != null) {

+			for (Class<?> paramType : paramTypes) {

+				String paramTypeString = getAsType(paramType);

+				result += paramTypeString;

+				if (!paramType.isPrimitive() && !paramType.isArray()) {

+					result += ";";

+				}

+			}

+		}

+		String returnTypeString = getAsType(returnType);

+		

+		result += ")" + returnTypeString;

+		if (!returnType.isPrimitive() && !returnType.isArray()) {

+			result += ";";

+		}

+		return result;

+	}

+	

+	public static String getTypeStringForField(String type) {

+		return type + ";";

+	}

+	

+	

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AbstractCreateDispatchCodeAdapter.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AbstractCreateDispatchCodeAdapter.java
new file mode 100644
index 0000000..449222e
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AbstractCreateDispatchCodeAdapter.java
@@ -0,0 +1,154 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode.asm;

+

+import org.eclipse.objectteams.otredyn.transformer.names.ClassNames;

+import org.eclipse.objectteams.otredyn.transformer.names.ConstantMembers;

+import org.objectweb.asm.Opcodes;

+import org.objectweb.asm.Type;

+import org.objectweb.asm.tree.AbstractInsnNode;

+import org.objectweb.asm.tree.InsnList;

+import org.objectweb.asm.tree.InsnNode;

+import org.objectweb.asm.tree.IntInsnNode;

+import org.objectweb.asm.tree.JumpInsnNode;

+import org.objectweb.asm.tree.LabelNode;

+import org.objectweb.asm.tree.MethodInsnNode;

+import org.objectweb.asm.tree.MethodNode;

+import org.objectweb.asm.tree.TypeInsnNode;

+

+/**

+ * Create the code for the dispatch from a base class to the teams. <br/> <br/>

+ * The code was generated as follows: <br/>

+ * <code>

+ * switch (boundMethodId) { // this was generated in CreateSwitchAdapter <br/>

+ * ... <br/>

+ * case (...): // this was generated in concrete implementations <br/> 

+ *             // of this abstract class <br/>

+ *     Teams[] teams = TeamManager.getTeams(joinpointId) <br/><br/>

+ *     if (teams == null) { <br/>

+ *         break; <br/>

+ *     } <br/>

+ *     <br/>

+ *     Team t = teams[0]; <br/>

+ *     int[] callinIds = TeamManager.getCallinIds(joinpointId); <br/>

+ *     Object[] args = {arg1, ... , argn};

+ *     return team._OT$callAllBindings(this, teams, 0, callinIds, boundMethodId, args);

+ * } <br/>

+ * </code>

+ * @author Oliver Frank

+ */

+public abstract class AbstractCreateDispatchCodeAdapter extends

+		AbstractTransformableClassNode {

+

+	private boolean isStatic;

+

+	public AbstractCreateDispatchCodeAdapter(boolean isStatic) {

+		this.isStatic = isStatic;

+	}

+

+	private Type[] args;

+

+	protected InsnList getDispatchCode(MethodNode method, int joinPointId,

+			int boundMethodId) {

+		InsnList instructions = new InsnList();

+

+		// teams = TeamManager.getTeams(joinpointId)

+		instructions.add(createLoadIntConstant(joinPointId));

+

+		instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC,

+				ClassNames.TEAM_MANAGER_SLASH, ConstantMembers.getTeams.getName(),

+				ConstantMembers.getTeams.getSignature()));

+		

+		instructions.add(createInstructionsToCheackTeams(method));

+		

+		// get the first team

+		instructions.add(new InsnNode(Opcodes.DUP));

+		instructions.add(new InsnNode(Opcodes.ICONST_0));

+		instructions.add(new InsnNode(Opcodes.AALOAD));

+		instructions.add(new InsnNode(Opcodes.SWAP));

+		if (isStatic) {

+			instructions.add(new InsnNode(Opcodes.ACONST_NULL));

+		} else {

+			// put "this" on the stack and cast it to IBoundBase

+			instructions.add(new IntInsnNode(Opcodes.ALOAD, 0));

+			instructions.add(new TypeInsnNode(Opcodes.CHECKCAST,

+					ClassNames.I_BOUND_BASE_SLASH));

+		}

+		instructions.add(new InsnNode(Opcodes.SWAP));

+		// start index

+		instructions.add(new InsnNode(Opcodes.ICONST_0));

+

+		// TeamManager.getCallinIds(joinpointId)

+		instructions.add(createLoadIntConstant(joinPointId));

+

+		instructions

+				.add(new MethodInsnNode(Opcodes.INVOKESTATIC,

+						ClassNames.TEAM_MANAGER_SLASH,

+						ConstantMembers.getCallinIds.getName(),

+						ConstantMembers.getCallinIds.getSignature()));

+

+		instructions.add(createLoadIntConstant(boundMethodId));

+		args = Type.getArgumentTypes(method.desc);

+

+		// box the arguments

+		instructions.add(getBoxedArguments(args));

+

+		instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE,

+				ClassNames.ITEAM_SLASH, ConstantMembers.callAllBindingsTeam

+						.getName(), ConstantMembers.callAllBindingsTeam

+						.getSignature()));

+

+		Type returnType = Type.getReturnType(method.desc);

+		instructions.add(getUnboxingInstructionsForReturnValue(returnType));

+

+		return instructions;

+	}

+	

+	protected InsnList createInstructionsToCheackTeams(MethodNode method) {

+		// if (teams == null) {

+		// 		break;

+		// }

+		InsnList instructions = new InsnList();

+		instructions.add(new InsnNode(Opcodes.DUP));

+		LabelNode label = new LabelNode();

+		instructions.add(new JumpInsnNode(Opcodes.IFNONNULL, label));

+		instructions.add(new InsnNode(Opcodes.POP));

+		instructions.add(new JumpInsnNode(Opcodes.GOTO, findBreakLabel(method.instructions)));

+		instructions.add(label);

+		return instructions;

+	}

+

+	private LabelNode findBreakLabel(InsnList instructions) {

+		for (int i = instructions.size() - 1; i >= 0; i--) {

+			AbstractInsnNode node = instructions.get(i);

+			if (node.getType() == AbstractInsnNode.LABEL) {

+				return (LabelNode) node;

+			}

+		}

+		throw new RuntimeException("Can't find break label to create dispatch code");

+	}

+

+	protected abstract InsnList getBoxedArguments(Type[] args);

+

+	protected int getMaxLocals() {

+		return args.length + 1;

+	}

+

+	protected int getMaxStack() {

+		return 10;

+	}

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AbstractTransformableClassNode.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AbstractTransformableClassNode.java
new file mode 100644
index 0000000..e964657
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AbstractTransformableClassNode.java
@@ -0,0 +1,272 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode.asm;

+

+import java.util.List;

+import java.util.ListIterator;

+

+import org.eclipse.objectteams.otredyn.bytecode.Method;

+import org.eclipse.objectteams.otredyn.transformer.names.ClassNames;

+import org.objectweb.asm.Opcodes;

+import org.objectweb.asm.Type;

+import org.objectweb.asm.tree.AbstractInsnNode;

+import org.objectweb.asm.tree.ClassNode;

+import org.objectweb.asm.tree.FieldInsnNode;

+import org.objectweb.asm.tree.InsnList;

+import org.objectweb.asm.tree.InsnNode;

+import org.objectweb.asm.tree.IntInsnNode;

+import org.objectweb.asm.tree.LabelNode;

+import org.objectweb.asm.tree.LdcInsnNode;

+import org.objectweb.asm.tree.LookupSwitchInsnNode;

+import org.objectweb.asm.tree.MethodInsnNode;

+import org.objectweb.asm.tree.MethodNode;

+import org.objectweb.asm.tree.TypeInsnNode;

+

+/**

+ * Every class, that wants to manipulate the bytecode of a class

+ * with the ASM Trea API, have to inherit from this class and do

+ * the transformations in the method transform().

+ * Additionally the class provides util methods to

+ * manipulate the bytecode 

+ * @author Oliver Frank

+ */

+public abstract class AbstractTransformableClassNode extends ClassNode {

+	

+	/**

+	 * Returns instructions, that are needed to pack all arguments of a method

+	 * in an {@link Object} Array

+	 * @param args The Types of the arguments

+	 * @param isStatic is this method static or not

+	 * @return

+	 */

+	protected InsnList getBoxingInstructions(Type[] args, boolean isStatic) {

+		int firstArgIndex = 1;

+		if (isStatic) {

+			firstArgIndex = 0;

+		}

+		InsnList instructions = new InsnList();

+		instructions.add(createLoadIntConstant(args.length));

+		instructions.add(new TypeInsnNode(Opcodes.ANEWARRAY,

+				ClassNames.OBJECT_SLASH));

+		for (int i=0, slot=0; i < args.length; slot += args[i++].getSize()) {

+			instructions.add(new InsnNode(Opcodes.DUP));

+			instructions.add(createLoadIntConstant(i));

+			instructions.add(new IntInsnNode(args[i].getOpcode(Opcodes.ILOAD),

+					slot + firstArgIndex));

+			if (args[i].getSort() != Type.OBJECT

+					&& args[i].getSort() != Type.ARRAY) {

+				instructions.add(AsmTypeHelper

+						.getBoxingInstructionForType(args[i]));

+			}

+			instructions.add(new InsnNode(Opcodes.AASTORE));

+		}

+

+		return instructions;

+	}

+

+	/**

+	 * Returns the instructions, that are needed to convert 

+	 * a return value of the type {@link Object} to the real type

+	 * @param returnType the real type

+	 * @return

+	 */

+	protected InsnList getUnboxingInstructionsForReturnValue(Type returnType) {

+		InsnList instructions = new InsnList();

+		switch (returnType.getSort()) {

+		case Type.VOID:

+			instructions.add(new InsnNode(Opcodes.POP));

+			instructions.add(new InsnNode(Opcodes.RETURN));

+			break;

+		case Type.ARRAY: // fallthrough

+		case Type.OBJECT:

+			instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, returnType

+					.getInternalName()));

+			instructions.add(new InsnNode(Opcodes.ARETURN));

+			break;

+		default:

+			String objectType = AsmTypeHelper.getObjectType(returnType);

+			instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, objectType));

+			instructions.add(AsmTypeHelper.getUnboxingInstructionForType(

+					returnType, objectType));

+			instructions

+					.add(new InsnNode(returnType.getOpcode(Opcodes.IRETURN)));

+		}

+		return instructions;

+	}

+

+	/**

+	 * Adds a new Label to an existing switch statement

+	 * @param instructions the instructions, in which the switch statement is defined

+	 * @param newInstructions the instructions of the new label

+	 * @param labelIndex the index of the label

+	 */

+	@SuppressWarnings("unchecked")

+	protected void addNewLabelToSwitch(InsnList instructions,

+			InsnList newInstructions, int labelIndex) {

+		ListIterator<AbstractInsnNode> iter = instructions.iterator();

+		LookupSwitchInsnNode lSwitch = null;

+		while (iter.hasNext()) {

+			AbstractInsnNode node = (AbstractInsnNode) iter.next();

+			if (node.getType() == AbstractInsnNode.LOOKUPSWITCH_INSN) {

+				lSwitch = (LookupSwitchInsnNode) node;

+				LabelNode label = new LabelNode();

+				boolean labelAdded = false;

+				for (int i = 0; i < lSwitch.keys.size(); i++) {

+					Integer key = (Integer) lSwitch.keys.get(i);

+					if (key >= labelIndex) {

+						lSwitch.keys.add(i, labelIndex);

+						lSwitch.labels.add(i, label);

+						labelAdded = true;

+						break;

+					}

+				}

+				if (!labelAdded) {

+					lSwitch.labels.add(label);

+					lSwitch.keys.add(labelIndex);

+				}

+				boolean foundDefLabel = false;

+				AbstractInsnNode prevNode = node;

+				while (iter.hasNext()) {

+					node = (AbstractInsnNode) iter.next();

+					if (node.getType() == AbstractInsnNode.LABEL) {

+						if (!foundDefLabel) {

+							foundDefLabel = true;

+						} else {

+							break;

+						}

+					}

+					prevNode = node;

+				}

+				instructions.insert(prevNode, label);

+				instructions.insert(label, newInstructions);

+			}	

+		}

+		if (lSwitch == null) {

+			throw new RuntimeException("No switch statement found.");

+		}

+	}

+

+	/**

+	 * Returns a {@link MethodNode} for a given {@link Method} instance

+	 * @param method

+	 * @return the {@link MethodNode} or null if there is no such method

+	 */

+	@SuppressWarnings("unchecked")

+	protected MethodNode getMethod(Method method) {

+		List<MethodNode> methodList = methods;

+		for (MethodNode methodNode : methodList) {

+			if (methodNode.name.compareTo(method.getName()) == 0

+					&& methodNode.desc.compareTo(method.getSignature()) == 0) {

+				return methodNode;

+			}

+		}

+

+		return null;

+	}

+

+	/**

+	 * This method could be used to generate debug outputs in the generated code in the form: <br>

+	 * <code>

+	 * Sytsem.out.println(message);

+	 * </code>

+	 * @param message

+	 * @return

+	 */

+	protected InsnList getInstructionsForDebugOutput(String message) {

+		InsnList instructions = new InsnList();

+		instructions.add(new FieldInsnNode(Opcodes.GETSTATIC,

+				"java/lang/System", "out", "Ljava/io/PrintStream;"));

+		instructions.add(new LdcInsnNode(message));

+		instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,

+				"java/io/PrintStream", "println", "(Ljava/lang/String;)V"));

+		return instructions;

+	}

+	

+	/**

+	 * Adds instructions to put all arguments of a method on the stack.

+	 * @param instructions

+	 * @param args

+	 * @param isStatic

+	 */

+	protected void addInstructionsForLoadArguments(InsnList instructions, Type[] args, boolean isStatic) {

+		int firstArgIndex = 1;

+		if (isStatic) {

+			firstArgIndex = 0;

+		}

+		// put "this" on the stack for an non-static method

+		if (!isStatic) {

+			instructions.add(new IntInsnNode(Opcodes.ALOAD, 0));

+		}

+		for (int i=0, slot=firstArgIndex; i < args.length; slot+=args[i++].getSize()) {

+			instructions.add(new IntInsnNode(args[i].getOpcode(Opcodes.ILOAD),

+					slot));

+		}

+	}

+	

+	/**

+	 * Replace all return statements in the given instructions with new 

+	 * statements that convert the real return value to {@link Object}

+	 * and return this new {@link Object}

+	 * 

+	 * @param instructions

+	 * @param returnType

+	 */

+	@SuppressWarnings("unchecked")

+	protected void replaceReturn(InsnList instructions, Type returnType) {

+		if (returnType.getSort() != Type.OBJECT &&

+				returnType.getSort() != Type.ARRAY &&

+				returnType.getSort() != Type.VOID) {

+			ListIterator<AbstractInsnNode> orgMethodIter = instructions.iterator();

+			while (orgMethodIter.hasNext()) {

+				AbstractInsnNode orgMethodNode = orgMethodIter.next();

+				if (orgMethodNode.getOpcode() == returnType.getOpcode(Opcodes.IRETURN)) {

+					instructions.remove(orgMethodNode);

+					instructions.add(AsmTypeHelper.getBoxingInstructionForType(returnType));

+					instructions.add(new InsnNode(Opcodes.ARETURN));

+				}

+			}

+		} else if (returnType.getSort() == Type.VOID) {

+			ListIterator<AbstractInsnNode> orgMethodIter = instructions.iterator();

+			while (orgMethodIter.hasNext()) {

+				AbstractInsnNode orgMethodNode = orgMethodIter.next();

+				if (orgMethodNode.getOpcode() == Opcodes.RETURN) {

+					instructions.remove(orgMethodNode);

+				}

+			}

+			instructions.add(new InsnNode(Opcodes.ACONST_NULL));

+			instructions.add(new InsnNode(Opcodes.ARETURN));

+		}

+	}

+

+	/**

+	 * Create an instruction for loading an integer constant,

+	 * using the most compact possible format. 

+	 */

+	protected AbstractInsnNode createLoadIntConstant(int constant) {

+		if (constant <= 5)

+			return new InsnNode(Opcodes.ICONST_0+constant);

+		else if (constant < Byte.MAX_VALUE)

+			return new IntInsnNode(Opcodes.BIPUSH, constant);

+		else

+			return new LdcInsnNode(constant);

+	}

+	/**

+	 * In this method, concrete Implementations of this class

+	 * can manipulate the bytecode

+	 */

+	protected abstract void transform();

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AddEmptyMethodAdapter.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AddEmptyMethodAdapter.java
new file mode 100644
index 0000000..56a2a55
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AddEmptyMethodAdapter.java
@@ -0,0 +1,95 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode.asm;

+

+import org.objectweb.asm.ClassAdapter;

+import org.objectweb.asm.ClassVisitor;

+import org.objectweb.asm.MethodVisitor;

+import org.objectweb.asm.Opcodes;

+import org.objectweb.asm.Type;

+

+/**

+ * This class adds an method only with a return statement

+ * to the bytecode of a class with the ASM Core API  

+ * @author Oliver Frank

+ */

+class AddEmptyMethodAdapter extends ClassAdapter {

+

+	private int access;

+	private String name;

+	private String desc;

+	private String signature;

+	private String[] exceptions;

+	private int maxLocals;

+

+	public AddEmptyMethodAdapter(ClassVisitor cv, String name, int access,

+			String desc, String[] exceptions, String signature,

+			int maxLocals) {

+		super(cv);

+		this.access = access;

+		this.desc = desc;

+		this.exceptions = exceptions;

+		this.name = name;

+		this.signature = signature;

+		this.maxLocals = maxLocals;

+	}

+

+	@Override

+	public void visitEnd() {

+		MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);

+		if ((this.access & Opcodes.ACC_ABSTRACT) != 0) {

+			mv.visitEnd();

+			return;

+		}

+		mv.visitCode();

+		Type returnType = Type.getReturnType(this.desc);

+		switch (returnType.getSort()) {

+		case Type.VOID:

+			mv.visitInsn(Opcodes.RETURN);

+			break;

+		case Type.INT:

+        case Type.BOOLEAN:

+        case Type.CHAR:

+        case Type.BYTE:

+        case Type.SHORT:

+			mv.visitInsn(Opcodes.ICONST_1);

+			mv.visitInsn(Opcodes.IRETURN);

+			break;

+        case Type.FLOAT:

+			mv.visitInsn(Opcodes.FCONST_1);

+			mv.visitInsn(Opcodes.FRETURN);

+			break;

+        case Type.LONG:

+			mv.visitInsn(Opcodes.LCONST_1);

+			mv.visitInsn(Opcodes.LRETURN);

+			break;

+        case Type.DOUBLE:

+		case Type.OBJECT:

+		case Type.ARRAY:

+			mv.visitInsn(Opcodes.ACONST_NULL);

+			mv.visitInsn(Opcodes.ARETURN);

+			break;

+		}

+		mv.visitMaxs(1, maxLocals);

+		mv.visitEnd();

+	}

+	

+	@Override

+	public MethodVisitor visitMethod(int arg0, String arg1, String arg2, String arg3, String[] arg4) {

+		return null; // also consider other visitors

+	}

+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AddFieldAdapter.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AddFieldAdapter.java
new file mode 100644
index 0000000..cd1141e
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AddFieldAdapter.java
@@ -0,0 +1,52 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode.asm;

+

+import org.objectweb.asm.ClassAdapter;

+import org.objectweb.asm.ClassVisitor;

+import org.objectweb.asm.FieldVisitor;

+import org.objectweb.asm.MethodVisitor;

+

+/**

+ * Adds an field to the bytecode of a class

+ * @author Oliver Frank

+ */

+class AddFieldAdapter extends ClassAdapter {

+

+	private int access;

+	private String name;

+	private String desc;

+

+	public AddFieldAdapter(ClassVisitor cv, String name, int access,

+			String desc) {

+		super(cv);

+		this.access = access;

+		this.desc = desc;

+		this.name = name;

+	}

+

+	@Override

+	public void visitEnd() {

+		FieldVisitor fv = cv.visitField(access, name, desc, null, null);

+		fv.visitEnd();

+	}

+		

+	@Override

+	public MethodVisitor visitMethod(int arg0, String arg1, String arg2, String arg3, String[] arg4) {

+		return null; // also consider other visitors

+	}

+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AddInterfaceAdapter.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AddInterfaceAdapter.java
new file mode 100644
index 0000000..7115028
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AddInterfaceAdapter.java
@@ -0,0 +1,49 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode.asm;

+

+import org.objectweb.asm.ClassAdapter;

+import org.objectweb.asm.ClassVisitor;

+import org.objectweb.asm.MethodVisitor;

+

+/**

+ * Adds an interface to the bytecode of a class

+ * @author Oliver Frank

+ *

+ */

+public class AddInterfaceAdapter extends ClassAdapter{

+	private String interfaceName;

+	

+	public AddInterfaceAdapter(ClassVisitor cv, String interfaceName) {

+		super(cv);

+		this.interfaceName = interfaceName;

+	}

+

+	@Override

+	public void visit(int version, int access, String name, String signature,

+			String superName, String[] interfaces) {

+		String[] newInterfaces = new String[interfaces.length + 1];

+		System.arraycopy(interfaces, 0, newInterfaces, 0, interfaces.length);

+		newInterfaces[interfaces.length] = interfaceName;

+		super.visit(version, access, name, signature, superName, newInterfaces);

+	}

+	

+	@Override

+	public MethodVisitor visitMethod(int arg0, String arg1, String arg2, String arg3, String[] arg4) {

+		return null; // also consider other visitors

+	}

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmBoundClass.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmBoundClass.java
new file mode 100644
index 0000000..31afa82
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmBoundClass.java
@@ -0,0 +1,163 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode.asm;

+

+import org.eclipse.objectteams.otredyn.bytecode.AbstractBoundClass;

+import org.eclipse.objectteams.otredyn.bytecode.AbstractTeam;

+import org.eclipse.objectteams.otredyn.bytecode.Binding;

+import org.eclipse.objectteams.otredyn.bytecode.IBytecodeProvider;

+import org.objectweb.asm.ClassReader;

+

+/**

+ * This class implements the bytecode parsing for {@link AbstractBoundClass}.

+ * It parses the bytecode with ASM.

+ * @author Oliver Frank

+ */

+abstract class AsmBoundClass extends AbstractTeam {

+

+	private boolean parsed;

+	private IBytecodeProvider bytecodeProvider;

+	

+	/**

+	 * just a temporary cache for the bytecode

+	 */

+	private byte[] bytecode;

+	

+	/**

+	 * ordered list of qualified callin labels

+	 */

+	public String[] precedences;

+

+	protected AsmBoundClass(String name, String id, IBytecodeProvider bytecodeProvider, ClassLoader loader) {

+		super(name, id, loader);

+		this.bytecodeProvider = bytecodeProvider;

+	}

+

+	/**

+	 * Parses the bytecode of a class and uses the set/add... Methods (e.g. addMethod)

+	 * of {@link AbstractBoundClass} to set the information

+	 */

+	@Override

+	protected synchronized void parseBytecode() {

+		if (parsed) {

+			// Already parsed, nothing to do

+			return;

+		}

+		

+		bytecode = bytecodeProvider.getBytecode(getId());

+		if (bytecode == null) {

+			//Class is not loaded yet.

+			return;

+		}

+		

+		// Don't parse another time

+		parsed = true;

+		AsmClassVisitor cv = new AsmClassVisitor(this);

+		ClassReader cr = null;

+		cr = new ClassReader(bytecode);

+		

+		cr.accept(cv, Attributes.attributes, 0);

+		

+		//release the bytecode

+		bytecode = null;

+	}

+	

+	/**

+	 * Returns the bytecode of this class and cache it temporary.

+	 * This method is only needed, if getBytecode of the {@link IBytecodeProvider}

+	 * is an expensive operation.

+	 * @return

+	 */

+	protected byte[] allocateAndGetBytecode() {

+		if (bytecode == null) {

+			bytecode = getBytecode();

+		}

+		return bytecode;

+	}

+	

+	/**

+	 * Get the bytecode directly from the {@link IBytecodeProvider}.

+	 * This method can be used, if getBytecode of the {@link IBytecodeProvider}

+	 * is not an expensive operation.

+	 * @return 

+	 */

+	@Override

+	public byte[] getBytecode() {

+		return bytecodeProvider.getBytecode(getId());

+	}

+	

+	/**

+	 * Releases the bytecode, if it's cached, an set it in the {@link IBytecodeProvider}

+	 */

+	protected void releaseBytecode() {

+		bytecodeProvider.setBytecode(getId(), bytecode);

+		bytecode = null;

+	}

+	

+	/**

+	 * Returns the {@link IBytecodeProvider} used for this class

+	 * @return

+	 */

+	protected IBytecodeProvider getBytecodeProvider() {

+		return bytecodeProvider;

+	}

+	

+	/**

+	 * Sets the bytecode. 

+	 * If the bytecode is temporary cached, the cache is used.

+	 * Otherwise this method give the bytecode directly to the {@link IBytecodeProvider}

+	 * @param bytecode

+	 */

+	protected void setBytecode(byte[] bytecode) {

+		//Is the bytecode temporary cached?

+		if (this.bytecode == null) {

+			// no, then save the bytecode directly in the bytecode provider

+			bytecodeProvider.setBytecode(getId(), bytecode);

+		} else {

+			// yes, then use the cache

+			this.bytecode = bytecode;

+		}

+	}

+	

+	public int compare(String callinLabel1, String callinLabel2) {

+		boolean label1Seen = false, label2Seen = false;

+		if (this.precedences != null) {

+			for (String label : this.precedences) {

+				if (label.equals(callinLabel1)) {

+					if (label2Seen)

+						return -1; // saw two then one: one has lower priority than two

+					label1Seen = true;

+				} else if (label.equals(callinLabel2)) {

+					if (label1Seen)

+						return 1; // saw one then two: one has higher priority than two

+					label2Seen = true;

+				}

+			}

+		}

+		AbstractBoundClass enclosingClass = getEnclosingClass();

+		if (enclosingClass != null) {

+			String singleName = getInternalName();

+			int pos = singleName.lastIndexOf('$');

+			singleName = singleName.substring(pos+1);

+			if (singleName.startsWith("__OT__"))

+				singleName = singleName.substring("__OT__".length());

+			// check for precedence at outer level:

+			return enclosingClass.compare(singleName+'.'+callinLabel1, singleName+'.'+callinLabel2);

+		}

+		return callinLabel1.compareTo(callinLabel2);

+	}

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmClassRepository.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmClassRepository.java
new file mode 100644
index 0000000..2b062ad
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmClassRepository.java
@@ -0,0 +1,35 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode.asm;

+

+import org.eclipse.objectteams.otredyn.bytecode.AbstractTeam;

+import org.eclipse.objectteams.otredyn.bytecode.ClassRepository;

+import org.eclipse.objectteams.otredyn.bytecode.IBytecodeProvider;

+

+

+/**

+ * Creates Instances of {@link AsmWritableBoundClass} as {@link AbstractTeam}

+ * @author Oliver Frank

+ */

+public class AsmClassRepository extends ClassRepository {

+

+	

+	@Override

+	protected AbstractTeam createClass(String name, String id, IBytecodeProvider bytecodeProvider, ClassLoader loader) {

+		return new AsmWritableBoundClass(name, id, bytecodeProvider, loader);

+	}

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmClassVisitor.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmClassVisitor.java
new file mode 100644
index 0000000..a54d420
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmClassVisitor.java
@@ -0,0 +1,130 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode.asm;

+

+import org.eclipse.objectteams.otredyn.bytecode.Binding;

+import org.eclipse.objectteams.otredyn.bytecode.Types;

+import org.eclipse.objectteams.otredyn.bytecode.asm.Attributes.CallinBindingsAttribute;

+import org.eclipse.objectteams.otredyn.bytecode.asm.Attributes.OTClassFlagsAttribute;

+import org.eclipse.objectteams.otredyn.bytecode.asm.Attributes.CallinBindingsAttribute.MultiBinding;

+import org.eclipse.objectteams.otredyn.bytecode.asm.Attributes.CallinPrecedenceAttribute;

+import org.eclipse.objectteams.otredyn.bytecode.asm.Attributes.OTSpecialAccessAttribute;

+import org.objectweb.asm.AnnotationVisitor;

+import org.objectweb.asm.Attribute;

+import org.objectweb.asm.FieldVisitor;

+import org.objectweb.asm.MethodVisitor;

+import org.objectweb.asm.Opcodes;

+import org.objectweb.asm.commons.EmptyVisitor;

+

+/**

+ * This class is used to parse the bytecode of a class.

+ * It sets the informations, that are parsed, in the {@link AsmBoundClass}

+ * @author Oliver Frank

+ */

+class AsmClassVisitor extends EmptyVisitor {

+

+	private AsmBoundClass clazz;

+	

+	public AsmClassVisitor(AsmBoundClass clazz) {

+		this.clazz = clazz;

+	}

+	

+	/**

+	 * Parses common information about the class.

+	 */

+	@Override

+	public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {

+			clazz.setSuperClassName(superName);

+			clazz.setTeam((access & Types.TEAM) != 0);

+			clazz.setInterface((access & Opcodes.ACC_INTERFACE) != 0);

+			clazz.setVisibility((access & (Opcodes.ACC_PRIVATE|Opcodes.ACC_PROTECTED|Opcodes.ACC_PUBLIC)));

+	}

+	

+	/**

+	 * Parses the methods of the class

+	 */

+	@Override

+	public MethodVisitor visitMethod(int access, final String name, final String desc, String signature, String[] exceptions) {

+		clazz.addMethod(name, desc, (access & Opcodes.ACC_STATIC) != 0, (access & (Opcodes.ACC_PUBLIC|Opcodes.ACC_PROTECTED|Opcodes.ACC_PRIVATE)));

+		if (clazz.isTeam() || clazz.isRole())

+			// check for method annotation ImplicitTeamActivation:

+			return new EmptyVisitor() {

+				@Override

+				public AnnotationVisitor visitAnnotation(String annDesc, boolean visible) {

+					if (annDesc.equals(AddImplicitActivationAdapter.ANNOTATION_IMPLICIT_ACTIVATION))

+						clazz.registerMethodForImplicitActivation(name+desc);

+					return super.visitAnnotation(annDesc, visible);

+				}

+			};

+		return super.visitMethod(access, name, desc, signature, exceptions);

+	}

+	

+	/**

+	 * Parses the fields of the class

+	 */

+	@Override

+	public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {

+		clazz.addField(name, desc, (access & Opcodes.ACC_STATIC) != 0, (access & (Opcodes.ACC_PUBLIC|Opcodes.ACC_PROTECTED|Opcodes.ACC_PRIVATE)));

+		return super.visitField(access, name, desc, signature, value);

+	}

+	

+	/**

+	 * Parses the class file attributes of a class.

+	 * This is only needed, if the class is a team.

+	 */

+	@Override

+	public void visitAttribute(Attribute attribute) {

+		if (attribute.type.equals(Attributes.ATTRIBUTE_OT_DYN_CALLIN_BINDINGS)) {

+			CallinBindingsAttribute attr = (CallinBindingsAttribute) attribute;

+			MultiBinding[] multiBindings = attr.getBindings();

+			for (int i=multiBindings.length-1; i>=0; i--) { // reverse loop to ensure proper overwriting:

+				String roleClassName = multiBindings[i].getRoleClassName();

+				String callinLabel = multiBindings[i].getCallinLabel();

+				String baseClassName = multiBindings[i].getBaseClassName();

+				String[] baseMethodNames = multiBindings[i].getBaseMethodNames();

+				String[] baseMethodSignatures = multiBindings[i].getBaseMethodSignatures();

+				String[] declaringBaseClassNames = multiBindings[i].getDeclaringBaseClassName();

+				int callinModifier = multiBindings[i].getCallinModifier();

+				int[] callinIds = multiBindings[i].getCallinIds();

+				boolean handleCovariantReturn = multiBindings[i].isHandleCovariantReturn();

+				for (int j = 0; j < baseMethodNames.length; j++) {

+					Binding binding = new Binding(clazz, roleClassName, callinLabel, baseClassName, 

+												  baseMethodNames[j], baseMethodSignatures[j], declaringBaseClassNames[j],

+												  callinModifier, callinIds[j], handleCovariantReturn);

+					clazz.addBinding(binding);

+				}

+			}

+		} else if (attribute.type.equals(Attributes.ATTRIBUTE_CALLIN_PRECEDENCE)) {

+			CallinPrecedenceAttribute attr = (CallinPrecedenceAttribute)attribute;

+			clazz.precedences = attr.labels;

+		} else if (attribute.type.equals(Attributes.ATTRIBUTE_OT_CLASS_FLAGS)) {

+			clazz.setOTClassFlags(((OTClassFlagsAttribute)attribute).flags);

+		} else if (attribute.type.equals(Attributes.ATTRIBUTE_OT_SPECIAL_ACCESS)) {

+			((OTSpecialAccessAttribute)attribute).registerAt(clazz);

+		}

+	}

+	

+	/**

+	 * check for class annotation ImplicitTeamActivation:

+	 */

+	@Override

+	public AnnotationVisitor visitAnnotation(String desc, boolean visible) {

+		if (desc.equals(AddImplicitActivationAdapter.ANNOTATION_IMPLICIT_ACTIVATION))

+			clazz.enableImplicitActivation();

+		return super.visitAnnotation(desc, visible);

+	}

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmTypeHelper.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmTypeHelper.java
new file mode 100644
index 0000000..5af508d
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmTypeHelper.java
@@ -0,0 +1,79 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode.asm;

+

+import org.objectweb.asm.Opcodes;

+import org.objectweb.asm.Type;

+import org.objectweb.asm.tree.AbstractInsnNode;

+import org.objectweb.asm.tree.InsnNode;

+import org.objectweb.asm.tree.MethodInsnNode;

+

+/**

+ * Asm specific helper class to handle type strings used in the bytecode

+ * @author Oliver Frank

+ */

+class AsmTypeHelper {

+	public static AbstractInsnNode getUnboxingInstructionForType(Type primitiveType, String objectType) {

+		String methodName = primitiveType.getClassName() + "Value";

+		String desc = Type.getMethodDescriptor(primitiveType, new Type[] {});

+		

+		return new MethodInsnNode(Opcodes.INVOKEVIRTUAL, objectType, methodName, desc);

+	}

+

+	public static String getObjectType(Type primitiveType) {

+		String className = null;

+		switch (primitiveType.getSort()) {

+		case Type.BOOLEAN:

+			className = "Boolean";

+			break;

+		case Type.BYTE:

+			className = "Byte";

+			break;

+		case Type.CHAR:

+			className = "Character";

+			break;

+		case Type.DOUBLE:

+			className = "Double";

+			break;

+		case Type.FLOAT:

+			className = "Float";

+			break;

+		case Type.INT:

+			className = "Integer";

+			break;

+		case Type.LONG:

+			className = "Long";

+			break;

+		case Type.SHORT:

+			className = "Short";

+			break;

+		default:

+			return null;

+		}

+		className = "java/lang/" + className; 

+		return className;

+	}

+	

+	public static AbstractInsnNode getBoxingInstructionForType(Type type) {

+		String className = getObjectType(type);

+		if (className == null)

+			return new InsnNode(Opcodes.NOP);

+		

+		String desc = Type.getMethodDescriptor(Type.getObjectType(className), new Type[] {type});

+		return new MethodInsnNode(Opcodes.INVOKESTATIC, className, "valueOf", desc);

+	}

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmWritableBoundClass.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmWritableBoundClass.java
new file mode 100644
index 0000000..6943344
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmWritableBoundClass.java
@@ -0,0 +1,432 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode.asm;

+

+import java.io.File;

+import java.io.FileOutputStream;

+import java.util.ArrayList;

+import java.util.List;

+

+import org.eclipse.objectteams.otredyn.bytecode.AbstractBoundClass;

+import org.eclipse.objectteams.otredyn.bytecode.Field;

+import org.eclipse.objectteams.otredyn.bytecode.IBytecodeProvider;

+import org.eclipse.objectteams.otredyn.bytecode.Method;

+import org.eclipse.objectteams.otredyn.bytecode.RedefineStrategyFactory;

+import org.eclipse.objectteams.otredyn.bytecode.Types;

+import org.eclipse.objectteams.otredyn.runtime.TeamManager;

+import org.eclipse.objectteams.otredyn.transformer.names.ClassNames;

+import org.eclipse.objectteams.otredyn.transformer.names.ConstantMembers;

+import org.objectweb.asm.ClassReader;

+import org.objectweb.asm.ClassWriter;

+import org.objectweb.asm.Opcodes;

+import org.objectweb.asm.Type;

+

+/**

+ * This class implements the bytecode manipulating part of {@link AbstractBoundClass}.

+ * It uses ASM to manipulate the bytecode.

+ * @author Oliver Frank

+ */

+class AsmWritableBoundClass extends AsmBoundClass {

+	private static boolean dumping = false;

+

+    static {

+        if(System.getProperty("ot.dump")!=null)

+            dumping = true;

+    }

+    

+	private ClassWriter writer;

+	private MultiClassAdapter multiAdapter;

+	private ClassReader reader;

+	private boolean isTransformed;

+	private boolean isTransformedForMemberAccess;

+	private boolean isTransformedStatic;

+	private List<AbstractTransformableClassNode> nodes;

+	private boolean isFirstTransformation = true;

+

+	private boolean isTransformationActive;

+

+	protected AsmWritableBoundClass(String name, String id, IBytecodeProvider bytecodeProvider, ClassLoader loader) {

+		super(name, id, bytecodeProvider, loader);

+	}

+	

+	/**

+	 * Adds a field to the class

+	 * 

+	 * @param field defines name and type of the field

+	 * @param access access flags for the field

+	 * @see AddFieldAdapter

+	 */

+	private void addField(Field field, int access) {

+		assert (isTransformationActive) : "No transformation active";

+		String desc = field.getSignature();

+		multiAdapter.addVisitor(new AddFieldAdapter(writer, field.getName(), access, desc));

+	}

+

+	/**

+	 * Adds an empty method to the class

+	 * @param method

+	 * @param access

+	 * @param signature

+	 * @param exceptions

+	 * @see AddEmptyMethodAdapter

+	 */

+	private void addEmptyMethod(Method method, int access, String signature, String[] exceptions) {

+		assert (isTransformationActive) : "No transformation active";

+		String desc = method.getSignature();

+		Type[] args = Type.getArgumentTypes(desc);

+		multiAdapter.addVisitor(new AddEmptyMethodAdapter(writer, method.getName(),

+				access, desc, exceptions, signature, args.length + 1));

+	}

+

+	/**

+	 * Adds an interface to the class

+	 * @see AddInterfaceAdapter

+	 * @param name

+	 */

+	private void addInterface(String name) {

+		assert (isTransformationActive) : "No transformation active";

+		multiAdapter.setToplevelVisitor(new AddInterfaceAdapter(writer, name));

+	}

+

+	/**

+	 * This method must be called before any transformation

+	 * can be done. It makes it possible to collect all transformations

+	 * and transform the bytecode only one time at the end.

+	 */

+	@Override

+	protected void startTransformation() {

+		

+		reader = new ClassReader(allocateAndGetBytecode());

+

+		writer = new ClassWriter(reader, 0);

+		multiAdapter = new MultiClassAdapter(writer);

+		nodes = new ArrayList<AbstractTransformableClassNode>();

+		isTransformationActive = true;

+	}

+	

+	/**

+	 * Is the class manipulated right now.

+	 */

+	@Override

+	public boolean isTransformationActive() {

+		return isTransformationActive;

+	}

+

+	/**

+	 * Executes all pending transformations.

+	 */

+	@Override

+	protected void endTransformation() {

+		assert (isTransformationActive) : "No transformation active";

+		// //TODO (ofra): Do everything in one transformation

+		// Do all transformation with the Core API of ASM

+		reader.accept(multiAdapter, ClassReader.SKIP_FRAMES);

+		setBytecode(writer.toByteArray());

+		//Do all transformations with the Tree API of ASM

+		for (AbstractTransformableClassNode node : nodes) {

+			reader = new ClassReader(allocateAndGetBytecode());

+			reader.accept(node, ClassReader.SKIP_FRAMES);

+			node.transform();

+			writer = new ClassWriter(reader, 0);

+			node.accept(writer);

+			setBytecode(writer.toByteArray());

+		}

+		

+		dump();

+		reader = null;

+		writer = null;

+		multiAdapter = null;

+		nodes = null;

+		//Check, if this is the first transformation for this class

+		if (!this.isFirstTransformation) {

+			// It is not the first transformation, so redefine the class

+			try {

+				redefine();

+			} catch (Throwable t) {

+//				t.printStackTrace(System.out);

+				// if redefinition failed (ClassCircularity?) install a runnable for deferred redefinition:

+				final Runnable previousTask = TeamManager.pendingTasks.get();

+				TeamManager.pendingTasks.set(new Runnable() {

+					public void run() {

+						if (previousTask != null)

+							previousTask.run();

+						redefine();

+					}

+					@Override

+					public String toString() {

+						return "Retry "+AsmWritableBoundClass.this.toString();

+					}

+				});

+			}

+		}

+		isTransformationActive = false;

+		isFirstTransformation = false;

+		releaseBytecode();

+	}

+

+	/**

+	 * Creates the dispatch code in the original method.

+	 * @see CreateDispatchCodeInOrgMethodAdapter

+	 */

+	@Override

+	protected void createDispatchCodeInOrgMethod(Method boundMethod,

+			int joinPointId, int boundMethodId) {

+		assert (isTransformationActive) : "No transformation active";

+		nodes.add(new CreateDispatchCodeInOrgMethodAdapter(boundMethod,

+				joinPointId, boundMethodId));

+	}

+

+	/**

+	 * Creates the dispatch code in the method callAllBindings.

+	 * @see CreateDispatchCodeInCallAllBindingsAdapter

+	 */

+	@Override

+	protected void createDispatchCodeInCallAllBindings(int joinpointId,

+			int boundMethodId) {

+		assert (isTransformationActive) : "No transformation active";

+		nodes.add(new CreateDispatchCodeInCallAllBindingsAdapter(joinpointId,

+				boundMethodId));

+	}

+

+	/**

+	 * Moves the code of the original method to callOrig or callOrigStatic.

+	 * @see MoveCodeToCallOrigAdapter

+	 */

+	@Override

+	protected void moveCodeToCallOrig(Method boundMethod, int boundMethodId) {

+		assert (isTransformationActive) : "No transformation active";

+		nodes.add(new MoveCodeToCallOrigAdapter(this, boundMethod, boundMethodId));

+	}

+	

+	/**

+	 * Creates a super call in callOrig.

+	 * @see CreateSuperCallInCallOrigAdapter

+	 */

+	@Override

+	protected void createSuperCallInCallOrig(int joinpointId) {

+		assert (isTransformationActive) : "No transformation active";

+		nodes.add(new CreateSuperCallInCallOrigAdapter(

+				getInternalSuperClassName(), joinpointId));

+

+	}

+

+	/**

+	 * Creates a call of callAllBindings in the original method.

+	 * @see CreateCallAllBindingsCallInOrgMethod

+	 */

+	@Override

+	protected void createCallAllBindingsCallInOrgMethod(Method boundMethod,

+			int boundMethodId, boolean needToAddMethod) {

+		assert (isTransformationActive) : "No transformation active";

+		if (needToAddMethod) {

+			String desc = boundMethod.getSignature();

+			Type[] args = Type.getArgumentTypes(desc);

+			multiAdapter.addVisitor(new AddEmptyMethodAdapter(writer, boundMethod.getName(),

+					boundMethod.getAccessFlags(), desc, null, boundMethod.getSignature(), args.length+1/*maxLocals*/));

+		}

+		nodes.add(new CreateCallAllBindingsCallInOrgMethod(boundMethod,

+				boundMethodId));

+

+	}

+

+	/**

+	 * Prepares a the class for a decapsulation of one of its methods

+	 */

+	@Override

+	protected void weaveMethodAccess(Method method, int accessId) {

+		nodes.add(new CreateMethodAccessAdapter(method, accessId));

+

+	}

+

+	/**

+	 * Prepares a the class for a decapsulation of one of its fields

+	 */

+	@Override

+	protected void weaveFieldAccess(Field field, int accessId) {

+		nodes.add(new CreateFieldAccessAdapter(field, accessId));

+

+	}

+

+	/**

+	 * Write the bytecode in the directory ./otdyn to the hard disk, 

+	 * if the system property "ot.dump" is set.

+	 */

+	private void dump() {

+		if (!dumping)

+			return;

+		

+		FileOutputStream fos = null;

+		try {

+			String name = getName();

+			int index = name.indexOf('/');

+			if (index == -1)

+				index = name.indexOf('.');

+			File dir = new File("otdyn");

+			if (!dir.exists())

+				dir.mkdir();

+			String filename = "otdyn/" + name.substring(index + 1) + ".class";

+			fos = new FileOutputStream(filename);

+			fos.write(allocateAndGetBytecode());

+			fos.close();

+		} catch (Exception e) {

+			// TODO (ofra): Log error while dumping

+			e.printStackTrace();

+		} 

+	}

+

+	private int n = 0; // counts dump files for this class

+	public void dump(byte[] bytecode, String postfix) {

+		if (!dumping)

+			return;

+

+		FileOutputStream fos = null;

+		try {

+			String name = getName();

+			int index = name.indexOf('/');

+			if (index == -1)

+				index = name.indexOf('.');

+			File dir = new File("otdyn");

+			if (!dir.exists())

+				dir.mkdir();

+			String filename = "otdyn/" + name.substring(index + 1) + postfix+".#"+(n++);

+			fos = new FileOutputStream(filename);

+			fos.write(bytecode);

+			fos.close();

+		} catch (Exception e) {

+			// TODO (ofra): Log error while dumping

+			e.printStackTrace();

+		}

+	}

+

+	/**

+	 * Redefines the class

+	 */

+	private void redefine() {

+		try {

+			Class<?> clazz = this.loader.loadClass(this.getName()); // boot classes may have null classloader, can't be redefined anyway?

+			byte[] bytecode = allocateAndGetBytecode();

+			dump(bytecode, "redef");

+			RedefineStrategyFactory.getRedefineStrategy().redefine(clazz, bytecode);

+		} catch (Throwable t) {

+			throw new RuntimeException("Error occured while dynamically redefining class " + getName()+"\n"+t.getMessage(), t);

+		}

+	}

+

+	/**

+	 * Do all transformations needed at load time

+	 */

+	@Override

+	protected void prepareAsPossibleBaseClass() {

+		if (!isFirstTransformation)

+			return;

+

+		addInterface(ClassNames.I_BOUND_BASE_SLASH);

+		

+		int methodModifiers = Types.ACCESS_PUBLIC;

+		if (isInterface())

+			methodModifiers |= Opcodes.ACC_ABSTRACT;

+		

+		if (!isInterface())

+			addField(ConstantMembers.roleSet, Types.ACCESS_PUBLIC);

+		

+		addEmptyMethod(ConstantMembers.callOrig, methodModifiers, null, null);

+		addEmptyMethod(ConstantMembers.callAllBindingsClient, methodModifiers, null, null);

+		

+		// the methods callOrigStatic and accessStatic have to already exist to call it in a concrete team

+		if (!isInterface()) {

+			addEmptyMethod(getCallOrigStatic(), Types.ACCESS_PUBLIC + Types.ACCESS_STATIC, null, null);

+			addEmptyMethod(ConstantMembers.accessStatic, Types.ACCESS_PUBLIC + Types.ACCESS_STATIC, null, null);

+		}

+		

+		addEmptyMethod(ConstantMembers.access, methodModifiers, null, null);

+		addEmptyMethod(ConstantMembers.addOrRemoveRole, methodModifiers, null, null);

+		

+		if (!isInterface())

+			multiAdapter.addVisitor(new AddAfterClassLoadingHook(this.writer, this));

+	}

+

+	/** Get the suitable variant of _OT$callOrigStatic, respecting synth args for static role methods. */

+	Method getCallOrigStatic() {

+		if (isRole())

+			return ConstantMembers.callOrigStaticRoleVersion(getEnclosingClassName());

+		else

+			return ConstantMembers.callOrigStatic;

+	}

+

+	/**

+	 * Prepares the class for implicit team activation by adding appropriate calls to

+	 * _OT$implicitlyActivate(), _OT$implicitlyDeactivate() into all relevant methods.

+	 */

+	@Override

+	protected void prepareTeamActivation() {

+		if (!isFirstTransformation || isInterface())

+			return;

+		if (isTeam() || isRole())

+			multiAdapter.addVisitor(new AddImplicitActivationAdapter(this.writer, this));

+		AddGlobalTeamActivationAdapter.checkAddVisitor(this.multiAdapter, this.writer);

+	}

+

+	/**

+	 * Prepares the methods callAllBindings and callOrig with an empty

+	 * switch statement

+	 */

+	@Override

+	protected void prepareForFirstTransformation() {

+		if (!isTransformed && !isInterface()) {

+			nodes.add(new CreateSwitchAdapter(ConstantMembers.callOrig));

+			nodes.add(new CreateSwitchForCallAllBindingsNode());

+			nodes.add(new CreateAddRemoveRoleMethod());

+			isTransformed = true;

+		}

+	}

+

+	/**

+	 * Prepares the method callOrigStatic with an empty

+	 * switch statement

+	 */

+	@Override

+	protected void prepareForFirstStaticTransformation() {

+		if (!isTransformedStatic && !isInterface()) {

+			nodes.add(new CreateSwitchAdapter(getCallOrigStatic(), isRole()));

+			isTransformedStatic = true;

+		}

+	}

+

+	/**

+	 * Prepares the methods access and accessStatic with an empty

+	 * switch statement

+	 */

+	@Override

+	protected void prepareForFirstMemberAccess() {

+		if (!isTransformedForMemberAccess && !isInterface()) {

+			nodes.add(new CreateSwitchForAccessAdapter(ConstantMembers.access,

+					getInternalSuperClassName(), this));

+			nodes.add(new CreateSwitchForAccessAdapter(ConstantMembers.accessStatic,

+					getInternalSuperClassName(), this));

+			isTransformedForMemberAccess = true;

+		}

+

+	}

+

+	/**

+	 * Was the class already transformed?

+	 */

+	@Override

+	protected boolean isFirstTransformation() {

+		return isFirstTransformation;

+	}

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/Attributes.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/Attributes.java
new file mode 100644
index 0000000..4c56ef3
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/Attributes.java
@@ -0,0 +1,340 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode.asm;

+

+import java.util.ArrayList;

+import java.util.List;

+

+import org.eclipse.objectteams.otredyn.bytecode.AbstractBoundClass;

+import org.eclipse.objectteams.otredyn.bytecode.Binding;

+import org.eclipse.objectteams.otredyn.bytecode.ClassRepository;

+import org.eclipse.objectteams.otredyn.runtime.ClassIdentifierProviderFactory;

+import org.eclipse.objectteams.otredyn.runtime.IBinding;

+import org.eclipse.objectteams.otredyn.runtime.IClassIdentifierProvider;

+import org.objectweb.asm.Attribute;

+import org.objectweb.asm.ClassReader;

+import org.objectweb.asm.Label;

+

+/**

+ * This class contains all classes representing OT/J class file attributes

+ * @author Oliver Frank

+ */

+abstract class Attributes {

+	protected final static String ATTRIBUTE_OT_DYN_CALLIN_BINDINGS="OTDynCallinBindings";

+	protected final static String ATTRIBUTE_CALLIN_PRECEDENCE = "CallinPrecedence";

+	protected final static String ATTRIBUTE_OT_CLASS_FLAGS = "OTClassFlags";

+	protected final static String ATTRIBUTE_OT_SPECIAL_ACCESS = "OTSpecialAccess";

+

+	protected final static Attribute[] attributes = { 

+		new CallinBindingsAttribute(0),

+		new CallinPrecedenceAttribute(0),

+		new OTClassFlagsAttribute(0),

+		new OTSpecialAccessAttribute()

+	};

+	

+	protected static class CallinBindingsAttribute extends Attribute {

+		static final short COVARIANT_BASE_RETURN = 8;

+

+		/** Represents all base method bindings of one callin binding. */

+		protected static class MultiBinding {

+			private String   roleClassName;

+			private String   callinLabel;

+			private String   baseClassName;

+			private String[] baseMethodNames;

+			private String[] baseMethodSignatures;

+			private String[] declaringBaseClassNames;

+			private int      callinModifier;

+			private int[]    callinIds;

+			private boolean  isHandleCovariantReturn;

+			MultiBinding(String roleName, String callinLabel,

+						 String baseClassName, 

+						 String[] baseMethodNames, String[] baseMethodSignatures, String[] declaringBaseClassNames,

+						 int callinModifier, int[] callinIds, boolean handleCovariantReturn) 

+			{

+				this.roleClassName = roleName;

+				this.callinLabel = callinLabel;

+				this.baseClassName = baseClassName;

+				this.baseMethodNames = baseMethodNames;

+				this.baseMethodSignatures = baseMethodSignatures;

+				this.declaringBaseClassNames = declaringBaseClassNames;

+				this.callinModifier = callinModifier;

+				this.callinIds = callinIds;

+				this.isHandleCovariantReturn = handleCovariantReturn;

+			}

+			protected String getRoleClassName() {

+				return roleClassName;

+			}

+

+			protected String getBaseClassName() {

+				return baseClassName;

+			}

+

+			protected String[] getBaseMethodNames() {

+				return baseMethodNames;

+			}

+

+			protected String[] getBaseMethodSignatures() {

+				return baseMethodSignatures;

+			}

+			

+			protected int getCallinModifier() {

+				return this.callinModifier;

+			}

+

+			protected int[] getCallinIds() {

+				return callinIds;

+			}

+

+			protected String getCallinLabel() {

+				return callinLabel;

+			}

+			public boolean isHandleCovariantReturn() {

+				return this. isHandleCovariantReturn;

+			}

+			public String[] getDeclaringBaseClassName() {

+				return this.declaringBaseClassNames;

+			}

+		}

+		

+		private MultiBinding[] bindings;

+

+		public CallinBindingsAttribute(int bindingsCount) {

+			super(ATTRIBUTE_OT_DYN_CALLIN_BINDINGS);

+			this.bindings = new MultiBinding[bindingsCount];

+		}

+		

+		private void addBinding(int i, String roleName, String callinLabel,

+				                String baseClassName, 

+				                String[] baseMethodNames, String[] baseMethodSignatures, String[] declaringBaseClassNames,

+				                String callinModifierName, int[] callinIds, boolean handleCovariantReturn) {

+			int callinModifier = 0;

+			if ("before".equals(callinModifierName))

+				callinModifier = Binding.BEFORE;

+			else if ("after".equals(callinModifierName))

+				callinModifier = Binding.AFTER;

+			else

+				callinModifier = Binding.REPLACE;

+			this.bindings[i] = new MultiBinding(roleName, callinLabel,

+					                            baseClassName, 

+					                            baseMethodNames, baseMethodSignatures, declaringBaseClassNames,

+					                            callinModifier, callinIds, handleCovariantReturn);

+		}

+		

+		@Override

+		protected Attribute read(ClassReader cr, int off, int len,

+				char[] buf, int codeOff, Label[] labels) 

+		{

+			int bindingsCount = cr.readShort(off);							off += 2;

+			CallinBindingsAttribute attr = new CallinBindingsAttribute(bindingsCount);

+			for (int i = 0; i < bindingsCount; i++) {

+				String roleName					= cr.readUTF8(off, buf);	off += 2;

+				String callinLabel				= cr.readUTF8(off, buf);	off += 2;

+				/* skip roleSelector, roleSignature */						off += 4;

+				String callinModifier			= cr.readUTF8(off, buf);	off += 2;

+				int flags						= cr.readByte(off);			off += 1;

+				String baseClassName 			= cr.readUTF8(off, buf);	off += 2;

+				/* skip filename & lineNumber & lineOffset */				off += 6;

+				int baseMethodsCount 			= cr.readShort(off);		off += 2;

+				String[] baseMethodNames 		= new String[baseMethodsCount];

+				String[] baseMethodSignatures 	= new String[baseMethodsCount];

+				String[] declaringBaseClassNames 	= new String[baseMethodsCount];

+				int[] callinIds = new int[baseMethodsCount];

+				for (int m = 0; m < baseMethodsCount; m++) {

+					String baseMethodName 		= cr.readUTF8(off, buf);	off += 2;

+					String baseMethodSignature 	= cr.readUTF8(off, buf);	off += 2;

+					String declaringBaseClass 	= cr.readUTF8(off, buf);	off += 2;

+					int callinId				= cr.readInt(off);			off += 4;

+					baseMethodNames[m] 			= baseMethodName;

+					baseMethodSignatures[m]		= baseMethodSignature;

+					declaringBaseClassNames[m]  = declaringBaseClass;

+					callinIds[m] 				= callinId;

+					/* skip baseFlags & translationFlags */					off += 3;

+				}

+				attr.addBinding(i, roleName, callinLabel,

+								baseClassName,

+								baseMethodNames, baseMethodSignatures, declaringBaseClassNames,

+								callinModifier, callinIds, ((flags & COVARIANT_BASE_RETURN) != 0));

+			}

+			return attr;

+		}

+		

+		public MultiBinding[] getBindings() {

+			return this.bindings;

+		}

+		

+		@Override

+		public String toString() {

+			StringBuffer buf = new StringBuffer();

+			for (MultiBinding binding : this.bindings) {

+				buf.append(binding.getBaseClassName());

+				int[] callinIds = binding.getCallinIds();

+				String[] baseMethodNames = binding.getBaseMethodNames();

+				String[] baseMethodSignatures = binding.getBaseMethodSignatures();

+				for (int i=0; i<callinIds.length; i++) {

+					buf.append("\n\t{");

+					buf.append(callinIds[i]);

+					buf.append("} ");

+					buf.append(baseMethodNames[i]);

+					buf.append(baseMethodSignatures[i]);

+				}				

+			}

+			return buf.toString();

+		}

+	}

+	protected static class CallinPrecedenceAttribute extends Attribute {

+		String[] labels;

+		public CallinPrecedenceAttribute(int elementCount) {

+			super(ATTRIBUTE_CALLIN_PRECEDENCE);

+			this.labels = new String[elementCount];

+		}

+		@Override

+		protected Attribute read(ClassReader cr, int off, int len,

+				char[] buf, int codeOff, Label[] labels) 

+		{

+			int elementCount = cr.readShort(off);		off += 2;

+			CallinPrecedenceAttribute attr = new CallinPrecedenceAttribute(elementCount);

+			for (int i = 0; i < elementCount; i++) {

+				attr.labels[i] = cr.readUTF8(off, buf);	off += 2;

+			}

+			return attr;

+		}

+	}

+	protected static class OTClassFlagsAttribute extends Attribute {

+		int flags;

+		protected OTClassFlagsAttribute(int flags) {

+			super(ATTRIBUTE_OT_CLASS_FLAGS);

+			this.flags = flags;

+		}

+		@Override

+		protected Attribute read(ClassReader cr, int off, int len, char[] buf,

+				int codeOff, Label[] labels) 

+		{

+			return new OTClassFlagsAttribute(cr.readUnsignedShort(off));			

+		}

+	}

+	protected static class OTSpecialAccessAttribute extends Attribute {

+		class DecapsField {

+			String accessMode;

+			boolean isStatic;

+			String baseclass, name, desc;

+			public int accessId;

+			public DecapsField(String baseclass, String name, String desc, int accessId, String accessMode, boolean isStatic) {

+				this.baseclass = baseclass;

+				this.name = name;

+				this.desc = desc;

+				this.accessId = accessId;

+				this.accessMode = accessMode;

+				this.isStatic = isStatic;

+			}

+		}

+		class DecapsMethod {

+			String baseclass, name, desc;

+			int id;

+			boolean isStatic;

+			DecapsMethod(String baseclass, String name, String desc, int id, boolean isStatic) {

+				this.baseclass = baseclass;

+				this.name = name;

+				this.desc = desc;

+				this.id = id;

+				this.isStatic = isStatic;

+			}

+		}

+		private static final int DECAPSULATION_METHOD_ACCESS= 4; // kinds are disjoint from those used by the old OTRE

+		private static final int CALLOUT_FIELD_ACCESS = 5;

+		private static final int SUPER_METHOD_ACCESS = 6;

+

+		List<DecapsMethod> methods = new ArrayList<DecapsMethod>();

+		List<DecapsField> fields = new ArrayList<DecapsField>();

+		

+		protected OTSpecialAccessAttribute() {

+			super(ATTRIBUTE_OT_SPECIAL_ACCESS);

+		}

+		@Override

+		protected Attribute read(ClassReader cr, int off, int len, char[] buf,

+				int codeOff, Label[] labels) 

+		{

+			OTSpecialAccessAttribute attr = new OTSpecialAccessAttribute();

+			int size = cr.readUnsignedShort(off); 			off+=2;

+			for (int i=0; i<size; i++) {

+				int kind = cr.readByte(off++);

+				switch (kind) {

+				case DECAPSULATION_METHOD_ACCESS:

+					attr.readMethodAccess(cr, off, buf);	off+=6;

+					break;

+				case CALLOUT_FIELD_ACCESS:

+					attr.readFieldAccess(cr, off, buf); 	off+=8;

+				default:

+					// FIXME(SH): handle!

+				}

+			}

+			return attr;

+		}

+		private void readMethodAccess(ClassReader cr, int off, char[] buf) {

+			String className   = cr.readUTF8(off, buf);

+			String encodedName = cr.readUTF8(off+2, buf);

+			String methodDesc  = cr.readUTF8(off+4, buf);

+			int id = cr.readUnsignedShort(off+6);

+			boolean isStatic = false;

+			String baseClass;

+			String methodName;

+			int pos = encodedName.indexOf('?');

+			if (pos == -1) {

+				pos = encodedName.indexOf('!');

+				isStatic = true;

+			}

+			baseClass = encodedName.substring(0, pos);

+			methodName = encodedName.substring(pos+1);

+			this.methods.add(new DecapsMethod(baseClass, methodName, methodDesc, id, isStatic));

+		}

+		private void readFieldAccess(ClassReader cr, int off, char[] buf) {

+			int accessId = cr.readByte(off);

+			int flags = cr.readByte(off+1);

+			String className   = cr.readUTF8(off+2, buf);

+			String fieldName = cr.readUTF8(off+4, buf);

+			String fieldDesc  = cr.readUTF8(off+6, buf);

+			boolean isStatic = (flags & 2) != 0;

+			String accessMode = (flags & 1) == 1 ? "set" : "get";

+			this.fields.add(new DecapsField(className, fieldName, fieldDesc, accessId, accessMode, isStatic));

+		}

+		public void registerAt(AsmBoundClass clazz) {

+			ClassRepository repo = ClassRepository.getInstance();

+			IClassIdentifierProvider provider = ClassIdentifierProviderFactory.getClassIdentifierProvider();

+

+			for (DecapsMethod dMethod : this.methods) {

+				// FIXME(SH): the following may need adaptation for OT/Equinox or other multi-classloader settings:

+				// bypassing the identifier provider (we don't have a Class<?> yet):

+				// String boundClassIdentifier = provider.getBoundClassIdentifier(clazz, dMethod.baseclass);

+				AbstractBoundClass baseclass = repo.getBoundClass(dMethod.baseclass, dMethod.baseclass.replace('.', '/'), clazz.getClassLoader());

+				// register the target method:

+				baseclass.getMethod(dMethod.name, dMethod.desc, false/*covariantReturn*/, dMethod.isStatic);

+				clazz.recordAccessId(dMethod.id);

+				clazz.addBinding(new Binding(clazz, dMethod.baseclass, dMethod.name, dMethod.desc, dMethod.id, IBinding.BindingType.METHOD_ACCESS));

+			}

+

+			for (DecapsField dField: this.fields) {

+				// FIXME(SH): the following may need adaptation for OT/Equinox or other multi-classloader settings:

+				// bypassing the identifier provider (we don't have a Class<?> yet):

+				// String boundClassIdentifier = provider.getBoundClassIdentifier(clazz, dMethod.baseclass);

+				AbstractBoundClass baseclass = repo.getBoundClass(dField.baseclass, dField.baseclass.replace('.', '/'), clazz.getClassLoader());

+				// register the target field:

+				baseclass.getField(dField.name, dField.desc);

+				clazz.recordAccessId(dField.accessId);

+				clazz.addBinding(new Binding(clazz, dField.baseclass, dField.name, dField.desc, dField.accessId, IBinding.BindingType.FIELD_ACCESS));

+			}

+		}

+	}

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateCallAllBindingsCallInOrgMethod.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateCallAllBindingsCallInOrgMethod.java
new file mode 100644
index 0000000..bb067c4
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateCallAllBindingsCallInOrgMethod.java
@@ -0,0 +1,146 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode.asm;

+

+import org.eclipse.objectteams.otredyn.bytecode.Method;

+import org.eclipse.objectteams.otredyn.transformer.names.ClassNames;

+import org.eclipse.objectteams.otredyn.transformer.names.ConstantMembers;

+import org.objectweb.asm.Opcodes;

+import org.objectweb.asm.Type;

+import org.objectweb.asm.tree.InsnList;

+import org.objectweb.asm.tree.InsnNode;

+import org.objectweb.asm.tree.IntInsnNode;

+import org.objectweb.asm.tree.LabelNode;

+import org.objectweb.asm.tree.MethodInsnNode;

+import org.objectweb.asm.tree.MethodNode;

+import org.objectweb.asm.tree.TryCatchBlockNode;

+

+/**

+ * This class creates and adds the instructions, that are needed 

+ * to call the method callAllBindings to a method.<br/> <br/>

+ * The instructions looks as follows:<br/>

+ * <code>

+ * Object[] args = {args1, ..., argsn};<br/>

+ * this.callAllBindings(boundMethodId, args);

+ * </code>

+ * @author Oliver Frank

+ */

+public class CreateCallAllBindingsCallInOrgMethod extends

+		AbstractTransformableClassNode {

+

+	private Method orgMethod;

+	private int boundMethodId;

+

+	public CreateCallAllBindingsCallInOrgMethod(Method orgMethod,

+			int boundMethodId) {

+		this.orgMethod = orgMethod;

+		this.boundMethodId = boundMethodId;

+	}

+

+	@Override

+	public void transform() {

+		MethodNode method = getMethod(orgMethod);

+		method.instructions.clear();

+

+		// start of try-block:

+		LabelNode start = new LabelNode();

+		method.instructions.add(start);

+

+		// put this on the stack

+		method.instructions.add(new IntInsnNode(Opcodes.ALOAD, 0));

+		// put boundMethodId on the stack

+		method.instructions.add(createLoadIntConstant(boundMethodId));

+		Type[] args = Type.getArgumentTypes(method.desc);

+		// box the arguments

+		method.instructions.add(getBoxingInstructions(args, false));

+

+		// this.callAllBindings(boundMethodId, args);

+		method.instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,

+				this.name, ConstantMembers.callAllBindingsClient.getName(),

+				ConstantMembers.callAllBindingsClient.getSignature()));

+		Type returnType = Type.getReturnType(method.desc);

+		method.instructions

+				.add(getUnboxingInstructionsForReturnValue(returnType));

+

+		// catch and unwrap SneakyException:

+		addCatchSneakyException(method, start);

+

+		int localSlots = 0;

+		int maxArgSize = 1;

+		for (Type type : args) {

+			int size = type.getSize();

+			localSlots += size;

+			if (size == 2)

+				maxArgSize = 2;

+		}

+		method.maxStack = args.length > 0 ? 5+maxArgSize : 3;

+		method.maxLocals = localSlots+1;

+	}

+

+	@SuppressWarnings("unchecked") // access to raw type List in ASM

+	void addCatchSneakyException(MethodNode method, LabelNode start) {

+		method.tryCatchBlocks.add(getCatchBlock(method.instructions, start, orgMethod));

+	}

+

+	TryCatchBlockNode getCatchBlock(InsnList instructions, LabelNode start, Method method) {

+		// end (exclusive) of try-block

+		LabelNode end = new LabelNode();

+		instructions.add(end);

+

+		// catch (SneakyException e) { e.rethrow(); }

+		LabelNode catchSneaky = new LabelNode();

+		instructions.add(catchSneaky);

+		instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, ClassNames.SNEAKY_EXCEPTION_SLASH, ClassNames.RETHROW_SELECTOR, ClassNames.RETHROW_SIGNATURE));

+		

+		// never reached, just to please the verifier:

+		Type returnType = Type.getReturnType(method.getSignature());

+		instructions.add(getReturnInsn(returnType));

+		return new TryCatchBlockNode(start, end, catchSneaky, ClassNames.SNEAKY_EXCEPTION_SLASH);

+	}

+

+	protected InsnList getReturnInsn(Type returnType) {

+		InsnList instructions = new InsnList();

+		switch (returnType.getSort()) {

+		case Type.VOID:

+			instructions.add(new InsnNode(Opcodes.RETURN));

+			break;

+		case Type.ARRAY:

+		case Type.OBJECT:

+			instructions.add(new InsnNode(Opcodes.ACONST_NULL));

+			instructions.add(new InsnNode(Opcodes.ARETURN));

+			break;

+		case Type.BOOLEAN:

+		case Type.CHAR:

+		case Type.BYTE:

+		case Type.INT:

+		case Type.SHORT:

+		case Type.LONG:

+			instructions.add(new InsnNode(Opcodes.ICONST_0));

+			instructions.add(new InsnNode(Opcodes.IRETURN));

+			break;

+		case Type.DOUBLE:

+			instructions.add(new InsnNode(Opcodes.DCONST_0));

+			instructions.add(new InsnNode(Opcodes.DRETURN));

+			break;

+		case Type.FLOAT:

+			instructions.add(new InsnNode(Opcodes.FCONST_0));

+			instructions.add(new InsnNode(Opcodes.FRETURN));

+			break;

+		}

+		return instructions;

+	}

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateDispatchCodeInCallAllBindingsAdapter.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateDispatchCodeInCallAllBindingsAdapter.java
new file mode 100644
index 0000000..9b49160
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateDispatchCodeInCallAllBindingsAdapter.java
@@ -0,0 +1,76 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode.asm;

+

+import org.eclipse.objectteams.otredyn.transformer.names.ConstantMembers;

+import org.objectweb.asm.Opcodes;

+import org.objectweb.asm.Type;

+import org.objectweb.asm.tree.InsnList;

+import org.objectweb.asm.tree.IntInsnNode;

+import org.objectweb.asm.tree.MethodNode;

+

+/**

+ * Create the code for the dispatch from a base class to the teams 

+ * in the method callAllBindings. <br/> <br/>

+ * The code was generated as follows: <br/>

+ * <code>

+ * switch (boundMethodId) { // this was generated in CreateSwitchAdapter <br/>

+ * ... <br/>

+ * case (boundMethodId): <br/>

+ *     Teams[] teams = TeamManager.getTeams(joinpointId) <br/>

+ *     if (teams == null) { <br/>

+ *         break; <br/>

+ *     } <br/>

+ *     <br/>

+ *     Team t = teams[0]; <br/>

+ *     int[] callinIds = TeamManager.getCallinIds(joinpointId); <br/>

+ *     Object[] args = {arg1, ... , argn};

+ *     return team._OT$callAllBindings(this, teams, 0, callinIds, boundMethodId, args);

+ * } <br/>

+ * </code>

+ * @author Oliver Frank

+ */

+public class CreateDispatchCodeInCallAllBindingsAdapter extends

+		AbstractCreateDispatchCodeAdapter {

+

+	private int joinpointId;

+	private int boundMethodId;

+	

+	public CreateDispatchCodeInCallAllBindingsAdapter(int joinpointId,

+			int boundMethodId) {

+		super(false);

+		this.joinpointId = joinpointId;

+		this.boundMethodId = boundMethodId;

+	}

+

+	@Override

+	public void transform() {

+		MethodNode callAllBindings = getMethod(ConstantMembers.callAllBindingsClient);

+		InsnList instructions = getDispatchCode(callAllBindings, joinpointId, boundMethodId);  

+		addNewLabelToSwitch(callAllBindings.instructions, instructions, boundMethodId);

+		callAllBindings.maxStack = getMaxStack();

+		callAllBindings.maxLocals = getMaxLocals();

+	}

+

+	@Override

+	protected InsnList getBoxedArguments(Type[] args) {

+		InsnList instructions = new InsnList();

+		instructions.add(new IntInsnNode(Opcodes.ALOAD, 2));

+		return instructions;

+	}

+

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateDispatchCodeInOrgMethodAdapter.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateDispatchCodeInOrgMethodAdapter.java
new file mode 100644
index 0000000..27e8cbe
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateDispatchCodeInOrgMethodAdapter.java
@@ -0,0 +1,100 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode.asm;

+

+import org.eclipse.objectteams.otredyn.bytecode.Method;

+import org.eclipse.objectteams.otredyn.transformer.names.ConstantMembers;

+import org.objectweb.asm.Opcodes;

+import org.objectweb.asm.Type;

+import org.objectweb.asm.tree.InsnList;

+import org.objectweb.asm.tree.InsnNode;

+import org.objectweb.asm.tree.JumpInsnNode;

+import org.objectweb.asm.tree.LabelNode;

+import org.objectweb.asm.tree.MethodInsnNode;

+import org.objectweb.asm.tree.MethodNode;

+

+/**

+ * Create the code for the dispatch from a base class to the teams 

+ * in the original method. <br/> <br/>

+ * The code was generated as follows: <br/>

+ * <code>

+ *     Teams[] teams = TeamManager.getTeams(joinpointId) <br/>

+ *     if (teams == null) { <br/>

+ *         Object args[] = {arg1, ..., argn}; <br/>

+ *         return callOrig(boundMethodId, args); <br/>

+ *     } <br/>

+ *     <br/>

+ *     Team t = teams[0]; <br/>

+ *     int[] callinIds = TeamManager.getCallinIds(joinpointId); <br/>

+ *     Object[] args = {arg1, ... , argn};

+ *     return team._OT$callAllBindings(this, teams, 0, callinIds, boundMethodId, args);

+ * } <br/>

+ * </code>

+ * @author Oliver Frank

+ */

+public class CreateDispatchCodeInOrgMethodAdapter extends

+		AbstractCreateDispatchCodeAdapter {

+	private Method method;

+	private int joinPointId;

+	private int boundMethodId;

+	

+	public CreateDispatchCodeInOrgMethodAdapter(Method method, int joinPointId, int boundMethodId) {

+		super(true);

+		this.method = method;

+		this.joinPointId = joinPointId;

+		this.boundMethodId = boundMethodId;

+	}

+

+	@Override

+	public void transform() {

+		MethodNode orgMethod = getMethod(method);

+		

+		orgMethod.instructions.clear();

+		orgMethod.instructions.add(getDispatchCode(orgMethod, joinPointId, boundMethodId));

+		orgMethod.maxStack = getMaxStack();

+		orgMethod.maxLocals = getMaxLocals();

+	}

+

+	@Override

+	protected InsnList getBoxedArguments(Type[] args) {

+		return getBoxingInstructions(args, true);

+	}

+

+	@Override

+	protected InsnList createInstructionsToCheackTeams(MethodNode method) {

+		InsnList instructions = new InsnList();

+		instructions.add(new InsnNode(Opcodes.DUP));

+		LabelNode label = new LabelNode();

+		//if (teams == null) {

+		instructions.add(new JumpInsnNode(Opcodes.IFNONNULL, label));

+		instructions.add(new InsnNode(Opcodes.POP));

+		//put the boundMethodId on the stack

+		instructions.add(createLoadIntConstant(boundMethodId));

+		Type[] args = Type.getArgumentTypes(method.desc);

+		// box the arguments

+		instructions.add(getBoxingInstructions(args, (method.access & Opcodes.ACC_STATIC) != 0));

+		//callOrigStatic(boundMethodId, args);

+		instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, name, ConstantMembers.callOrigStatic.getName(), ConstantMembers.callOrigStatic.getSignature()));

+		Type returnType = Type.getReturnType(method.desc);

+		instructions

+				.add(getUnboxingInstructionsForReturnValue(returnType));

+		instructions.add(label);

+

+		return instructions;

+	}

+	

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateFieldAccessAdapter.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateFieldAccessAdapter.java
new file mode 100644
index 0000000..2b240e3
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateFieldAccessAdapter.java
@@ -0,0 +1,130 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode.asm;

+

+import org.eclipse.objectteams.otredyn.bytecode.Field;

+import org.eclipse.objectteams.otredyn.bytecode.Method;

+import org.eclipse.objectteams.otredyn.transformer.names.ConstantMembers;

+import org.objectweb.asm.Opcodes;

+import org.objectweb.asm.Type;

+import org.objectweb.asm.tree.FieldInsnNode;

+import org.objectweb.asm.tree.InsnList;

+import org.objectweb.asm.tree.InsnNode;

+import org.objectweb.asm.tree.IntInsnNode;

+import org.objectweb.asm.tree.JumpInsnNode;

+import org.objectweb.asm.tree.LabelNode;

+import org.objectweb.asm.tree.MethodNode;

+import org.objectweb.asm.tree.TypeInsnNode;

+

+/**

+ * Creates and adds the instructions,

+ * that are needed to access a not visible field from the team

+ * in the method access or accessStatic as follows:<br/> <br/>

+ * case (memberId) { // generated by CreateSwitchForAccessAdapter <br/>

+ *     if (opKind == 0) { <br/>

+ *         return field; <br/>

+ *     } else { <br/>

+ *         field = args[0]; <br/>

+ *     } <br/>

+ *     break; <br/>

+ * }

+ * 

+ * @author Oliver Frank

+ */

+public class CreateFieldAccessAdapter extends AbstractTransformableClassNode {

+

+	private Field field;

+	private int accessId;

+	private Method access;

+	private int firstArgIndex;

+

+	public CreateFieldAccessAdapter(Field field, int accessId) {

+		this.field = field;

+		this.accessId = accessId;

+		if (field.isStatic()) {

+			access = ConstantMembers.accessStatic;

+			firstArgIndex = 0;

+		} else {

+			access = ConstantMembers.access;

+			firstArgIndex = 1;

+		}

+	}

+

+	@Override

+	public void transform() {

+

+		InsnList instructions = new InsnList();

+		// put accessId on the stack

+		instructions.add(new IntInsnNode(Opcodes.ILOAD, firstArgIndex + 1));

+		// read or write access

+		LabelNode writeAccess = new LabelNode();

+		instructions.add(new JumpInsnNode(Opcodes.IFNE, writeAccess));

+		// read access

+		if (field.isStatic()) {

+			// get value of field

+			instructions.add(new FieldInsnNode(Opcodes.GETSTATIC, name, field

+					.getName(), field.getSignature()));

+		} else {

+			// put "this" on the stack

+			instructions.add(new IntInsnNode(Opcodes.ALOAD, 0));

+			// get value of field

+			instructions.add(new FieldInsnNode(Opcodes.GETFIELD, name, field

+					.getName(), field.getSignature()));

+		}

+

+		//box value as "Object"

+		Type type = Type.getType(field.getSignature());

+		instructions.add(AsmTypeHelper.getBoxingInstructionForType(type));

+		instructions.add(new InsnNode(Opcodes.ARETURN));

+		

+		//write access

+		instructions.add(writeAccess);

+		//put "args" on the stack 

+		instructions.add(new IntInsnNode(Opcodes.ALOAD, firstArgIndex + 2));

+		//get the first element of "args"

+		instructions.add(new InsnNode(Opcodes.ICONST_0));

+		instructions.add(new InsnNode(Opcodes.AALOAD));

+		//unbox it

+		if (type.getSort() != Type.ARRAY && type.getSort() != Type.OBJECT) {

+			String objectType = AsmTypeHelper.getObjectType(type);

+			instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, objectType));

+			instructions.add(AsmTypeHelper.getUnboxingInstructionForType(type, objectType));

+		} else {

+			instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, type.getInternalName()));

+		}

+		

+		if (field.isStatic()) {

+			//save value in field

+			instructions.add(new FieldInsnNode(Opcodes.PUTSTATIC, name, field.getName(), field.getSignature()));

+		} else {

+			//put "this" on the stack

+			instructions.add(new IntInsnNode(Opcodes.ALOAD, 0));

+			instructions.add(new InsnNode(Opcodes.SWAP));

+			//save value in field

+			instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, name, field.getName(), field.getSignature()));

+		}

+		

+		//dummy return 

+		instructions.add(new InsnNode(Opcodes.ACONST_NULL));

+		instructions.add(new InsnNode(Opcodes.ARETURN));

+		

+		//add the instructions to a new label in the existing switch

+		MethodNode method = getMethod(access);

+		addNewLabelToSwitch(method.instructions, instructions, accessId);

+	}

+

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateMethodAccessAdapter.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateMethodAccessAdapter.java
new file mode 100644
index 0000000..acd1005
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateMethodAccessAdapter.java
@@ -0,0 +1,121 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode.asm;

+

+import org.eclipse.objectteams.otredyn.bytecode.Method;

+import org.eclipse.objectteams.otredyn.transformer.names.ConstantMembers;

+import org.objectweb.asm.Opcodes;

+import org.objectweb.asm.Type;

+import org.objectweb.asm.tree.InsnList;

+import org.objectweb.asm.tree.InsnNode;

+import org.objectweb.asm.tree.IntInsnNode;

+import org.objectweb.asm.tree.MethodInsnNode;

+import org.objectweb.asm.tree.MethodNode;

+import org.objectweb.asm.tree.TypeInsnNode;

+

+/**

+ * Creates and adds the instructions,

+ * that are needed to access a not visible method from the team

+ * in the method access or accessStatic as follows:<br/> <br/>

+ * case (memberId) { // generated by CreateSwitchForAccessAdapter <br/>

+ *     return orgMethod(args[0], ..., args[args.length]); <br/>

+ * }

+ * 

+ * @author Oliver Frank

+ */

+public class CreateMethodAccessAdapter extends AbstractTransformableClassNode {

+	private Method method;

+	private int accessId;

+	private Method access;

+	private int firstArgIndex;

+

+	public CreateMethodAccessAdapter(Method method, int accessId) {

+		this.method = method;

+		this.accessId = accessId;

+		if (method.isStatic()) {

+			access = ConstantMembers.accessStatic;

+			firstArgIndex = 0;

+		} else {

+			access = ConstantMembers.access;

+			firstArgIndex = 1;

+		}

+	}

+	

+	@Override

+	public void transform() {

+		MethodNode methodNode = getMethod(method);

+		InsnList instructions = new InsnList();

+		

+		//put "this" on the stack for a non-static method 

+		if (!method.isStatic()) {

+			instructions.add(new IntInsnNode(Opcodes.ALOAD, 0));

+		}

+		

+		//Unbox arguments

+		Type[] args = Type.getArgumentTypes(methodNode.desc);

+		

+		if (args.length > 0) {

+			instructions.add(new IntInsnNode(Opcodes.ALOAD, firstArgIndex + 2));

+			

+			

+			for (int i = 0; i < args.length; i++) {

+				if (i < args.length - 1) {

+					instructions.add(new InsnNode(Opcodes.DUP));

+				}

+				instructions.add(createLoadIntConstant(i));

+				instructions.add(new InsnNode(Opcodes.AALOAD));

+				Type arg = args[i];

+				if (arg.getSort() != Type.ARRAY && arg.getSort() != Type.OBJECT) {

+					String objectType = AsmTypeHelper.getObjectType(arg);

+					instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, objectType));

+					instructions.add(AsmTypeHelper.getUnboxingInstructionForType(arg, objectType));

+				} else {

+					instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, arg.getInternalName()));

+				}

+			}

+		}

+		

+		//call original method

+		int opcode = Opcodes.INVOKEVIRTUAL;

+		if (method.isStatic()) {

+			opcode = Opcodes.INVOKESTATIC;

+		}

+		instructions.add(new MethodInsnNode(opcode, name, method.getName(), method.getSignature()));

+		

+		

+		//box return value

+		Type returnType = Type.getReturnType(methodNode.desc);

+

+		if (returnType.getSort() != Type.OBJECT &&

+				returnType.getSort() != Type.ARRAY &&

+				returnType.getSort() != Type.VOID) {

+			

+				instructions.add(AsmTypeHelper.getBoxingInstructionForType(returnType));

+				instructions.add(new InsnNode(Opcodes.ARETURN));

+		} else if (returnType.getSort() == Type.VOID) {

+			instructions.add(new InsnNode(Opcodes.ACONST_NULL));

+			instructions.add(new InsnNode(Opcodes.ARETURN));

+		} else {

+			instructions.add(new InsnNode(Opcodes.ARETURN));

+		}

+		

+		//add the instructions to a new label in the existing switch

+		MethodNode access = getMethod(this.access);

+		addNewLabelToSwitch(access.instructions, instructions, accessId);

+	}

+

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateSuperCallInCallOrigAdapter.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateSuperCallInCallOrigAdapter.java
new file mode 100644
index 0000000..e81bf82
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateSuperCallInCallOrigAdapter.java
@@ -0,0 +1,58 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode.asm;

+

+import org.eclipse.objectteams.otredyn.transformer.names.ConstantMembers;

+import org.objectweb.asm.Opcodes;

+import org.objectweb.asm.Type;

+import org.objectweb.asm.tree.InsnList;

+import org.objectweb.asm.tree.InsnNode;

+import org.objectweb.asm.tree.MethodInsnNode;

+import org.objectweb.asm.tree.MethodNode;

+

+/**

+ * This class creates the instructions, that are needed

+ * to call super.callOrig(boundMethodId, args)

+ * @author Oliver Frank

+ */

+public class CreateSuperCallInCallOrigAdapter extends AbstractTransformableClassNode {

+

+	private int joinpointId;

+	private String superClassName;

+

+	public CreateSuperCallInCallOrigAdapter(String superClassName,

+			int joinpointId) {

+		this.superClassName = superClassName;

+		this.joinpointId = joinpointId;

+	}

+

+	@Override

+	public void transform() {

+		MethodNode callOrig = getMethod(ConstantMembers.callOrig);

+		InsnList instructions = new InsnList();

+		

+		Type[] args = Type.getArgumentTypes(callOrig.desc);

+		addInstructionsForLoadArguments(instructions, args, false);

+

+		instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL,

+				superClassName, ConstantMembers.callOrig.getName(),

+				ConstantMembers.callOrig.getSignature()));

+		instructions.add(new InsnNode(Opcodes.ARETURN));

+		addNewLabelToSwitch(callOrig.instructions, instructions, joinpointId);

+		callOrig.maxStack = Math.max(callOrig.maxStack, args.length + 1);

+	}

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateSwitchAdapter.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateSwitchAdapter.java
new file mode 100644
index 0000000..dbbabcf
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateSwitchAdapter.java
@@ -0,0 +1,112 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode.asm;

+

+import org.eclipse.objectteams.otredyn.bytecode.Method;

+import org.objectweb.asm.Opcodes;

+import org.objectweb.asm.tree.InsnNode;

+import org.objectweb.asm.tree.IntInsnNode;

+import org.objectweb.asm.tree.LabelNode;

+import org.objectweb.asm.tree.LookupSwitchInsnNode;

+import org.objectweb.asm.tree.MethodNode;

+

+/**

+ * This class creates an empty switch statement in a method.

+ * @author Oliver Frank

+ */

+public class CreateSwitchAdapter extends AbstractTransformableClassNode {

+	private Method method;

+

+	private int firstArgIndex;

+

+	public CreateSwitchAdapter(Method method) {

+		this.method = method;

+		if (method.isStatic()) {

+			firstArgIndex = 0;

+		} else {

+			firstArgIndex = 1;

+		}

+	}

+

+	public CreateSwitchAdapter(Method method, boolean isRoleMethod) {

+		this.method = method;

+		if (method.isStatic()) {

+			if (isRoleMethod)

+				firstArgIndex = 2;

+			else

+				firstArgIndex = 0;

+		} else {

+			firstArgIndex = 1;

+		}

+	}

+	

+	@Override

+	public void transform() {

+		MethodNode methodNode = getMethod(method);

+		if (methodNode == null) return; // doesn't exist, don't transform

+		methodNode.instructions.clear();

+		

+		addPreSwitchInstructions(methodNode);

+		

+		LabelNode def = new LabelNode();

+		LookupSwitchInsnNode switchNode = new LookupSwitchInsnNode(def, new int[0], new LabelNode[0]);

+		

+		methodNode.instructions.add(switchNode);

+		methodNode.instructions.add(def);

+		addInstructionForDefaultLabel(methodNode);

+		

+		addPostSwitchInstructions(methodNode);

+		methodNode.maxStack = getMaxStack();

+	}

+	

+	/**

+	 * Adds instructions after the switch statement

+	 * @param method

+	 */

+	protected void addPostSwitchInstructions(MethodNode method) {

+	}

+

+	/**

+	 * Adds instructions before the switch statement.

+	 * @param method

+	 */

+	protected void addPreSwitchInstructions(MethodNode method) {

+		method.instructions.add(new IntInsnNode(Opcodes.ILOAD, firstArgIndex));

+	}

+	

+	/**

+	 * Adds instructions for the default label.

+	 * @param method

+	 */

+	protected void addInstructionForDefaultLabel(MethodNode method) {

+		method.instructions.add(new InsnNode(Opcodes.ACONST_NULL));

+		method.instructions.add(new InsnNode(Opcodes.ARETURN));

+	}

+	

+	protected int getMaxStack() {

+		return 1;

+	}

+	

+	protected int getFirstArgIndex() {

+		return firstArgIndex;

+	}

+	

+	protected Method getMethod() {

+		return method;

+	}

+

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateSwitchForAccessAdapter.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateSwitchForAccessAdapter.java
new file mode 100644
index 0000000..adebbf2
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateSwitchForAccessAdapter.java
@@ -0,0 +1,100 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode.asm;

+

+import org.eclipse.objectteams.otredyn.bytecode.AbstractBoundClass;

+import org.eclipse.objectteams.otredyn.bytecode.Method;

+import org.eclipse.objectteams.otredyn.transformer.names.ClassNames;

+import org.eclipse.objectteams.otredyn.transformer.names.ConstantMembers;

+import org.objectweb.asm.Opcodes;

+import org.objectweb.asm.Type;

+import org.objectweb.asm.tree.InsnNode;

+import org.objectweb.asm.tree.IntInsnNode;

+import org.objectweb.asm.tree.LdcInsnNode;

+import org.objectweb.asm.tree.MethodInsnNode;

+import org.objectweb.asm.tree.MethodNode;

+import org.objectweb.asm.tree.TypeInsnNode;

+

+/**

+ * Initially prepares the method access or accessStatic as follows: <br/><br/>

+ * <code>

+ * int memberId = TeamManager.getMemberId(accessId, caller);<br/>

+ * switch (memberId) {<br/>

+ * default:<br/>

+ *     return super.access(accessId, opKind, args, caller);<br/> 

+ * }<br/>

+ * </code>

+ * @author Oliver Frank

+ */

+public class CreateSwitchForAccessAdapter extends CreateSwitchAdapter {

+

+	private String superClassName;

+	private AbstractBoundClass clazz;

+	public CreateSwitchForAccessAdapter(Method method, String superClassName, AbstractBoundClass clazz) {

+		super(method);

+		this.superClassName = superClassName;

+		this.clazz = clazz;

+	}

+

+	@Override

+	protected void addPreSwitchInstructions(MethodNode method) {

+		// put "accessId" on the stack

+		method.instructions.add(new IntInsnNode(Opcodes.ILOAD,

+				getFirstArgIndex()));

+		// put "caller".getClass() on the stack

+		method.instructions.add(new IntInsnNode(Opcodes.ALOAD,

+				getFirstArgIndex() + 3));

+		method.instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;"));

+		// call "getMemberId(accessId, callerClass)

+		method.instructions

+				.add(new MethodInsnNode(Opcodes.INVOKESTATIC,

+						ClassNames.TEAM_MANAGER_SLASH,

+						ConstantMembers.getMemberId.getName(),

+						ConstantMembers.getMemberId.getSignature()));

+	}

+	

+	@Override

+	protected void addInstructionForDefaultLabel(MethodNode method) {

+		if (superClassName.equals("java/lang/Object")) {

+			method.instructions.add(new TypeInsnNode(Opcodes.NEW, "org/objectteams/NoSuchMethodError"));

+			method.instructions.add(new InsnNode(Opcodes.DUP));

+			method.instructions.add(new IntInsnNode(Opcodes.ILOAD, getFirstArgIndex())); // accessId

+			method.instructions.add(new LdcInsnNode(clazz.getName()));					 // current class

+			method.instructions.add(new LdcInsnNode("decapsulating access"));			 // access reason

+			method.instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "org/objectteams/NoSuchMethodError", "<init>", "(ILjava/lang/String;Ljava/lang/String;)V"));

+			method.instructions.add(new InsnNode(Opcodes.ATHROW));

+		} else {

+			Type[] args = Type.getArgumentTypes(method.desc);

+			addInstructionsForLoadArguments(method.instructions, args, getMethod().isStatic());

+	

+			int opcode = Opcodes.INVOKESPECIAL;

+			if (getMethod().isStatic()) {

+				opcode = Opcodes.INVOKESTATIC;

+			}

+			method.instructions.add(new MethodInsnNode(opcode,

+					superClassName, getMethod().getName(),

+					getMethod().getSignature()));

+			method.instructions.add(new InsnNode(Opcodes.ARETURN));

+		}

+	}

+	

+	@Override

+	protected int getMaxStack() {

+		return 5;

+	}

+

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateSwitchForCallAllBindingsNode.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateSwitchForCallAllBindingsNode.java
new file mode 100644
index 0000000..f8a850a
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateSwitchForCallAllBindingsNode.java
@@ -0,0 +1,77 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode.asm;

+

+import org.eclipse.objectteams.otredyn.transformer.names.ConstantMembers;

+import org.objectweb.asm.Opcodes;

+import org.objectweb.asm.Type;

+import org.objectweb.asm.tree.InsnNode;

+import org.objectweb.asm.tree.IntInsnNode;

+import org.objectweb.asm.tree.JumpInsnNode;

+import org.objectweb.asm.tree.LabelNode;

+import org.objectweb.asm.tree.MethodInsnNode;

+import org.objectweb.asm.tree.MethodNode;

+

+/**

+ * Initially prepares the method callAllBindings as follows: <br/><br/>

+ * <code>

+ * switch (boundMethodId) {<br/>

+ * default:<br/>

+ *     break;<br/> 

+ * }<br/>

+ * <br/>

+ * return callOrig(boundMethodId, args);<br/>

+ * </code>

+ * @author Oliver Frank

+ */

+public class CreateSwitchForCallAllBindingsNode extends CreateSwitchAdapter {

+	private Type[] args;

+	private LabelNode gotoLabel;

+	

+	public CreateSwitchForCallAllBindingsNode() {

+		super(ConstantMembers.callAllBindingsClient);

+	}

+	

+	@Override

+	protected void addInstructionForDefaultLabel(MethodNode method) {

+		gotoLabel = new LabelNode();

+		method.instructions.add(new JumpInsnNode(Opcodes.GOTO, gotoLabel));

+	}

+	

+	@Override

+	protected void addPostSwitchInstructions(MethodNode method) {

+		method.instructions.add(gotoLabel);

+		method.instructions.add(new IntInsnNode(Opcodes.ALOAD, 0));

+		

+		args = Type.getArgumentTypes(method.desc);

+		int length = args.length;

+		for (int i = 0; i < length; i++) {

+			Type arg = args[i]; 

+			method.instructions.add(new IntInsnNode(arg.getOpcode(Opcodes.ILOAD), i + 1));

+		}

+		

+		// return callOrig(boundMethodId, args);

+		method.instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, name, ConstantMembers.callOrig.getName(), ConstantMembers.callOrig.getSignature()));

+		method.instructions.add(new InsnNode(Opcodes.ARETURN));

+	}

+	

+	@Override

+	protected int getMaxStack() {

+		return args.length + 1;

+	}

+

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/MoveCodeToCallOrigAdapter.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/MoveCodeToCallOrigAdapter.java
new file mode 100644
index 0000000..8438da8
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/MoveCodeToCallOrigAdapter.java
@@ -0,0 +1,109 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode.asm;

+

+import org.eclipse.objectteams.otredyn.bytecode.Method;

+import org.eclipse.objectteams.otredyn.transformer.names.ConstantMembers;

+import org.objectweb.asm.Opcodes;

+import org.objectweb.asm.Type;

+import org.objectweb.asm.tree.InsnList;

+import org.objectweb.asm.tree.InsnNode;

+import org.objectweb.asm.tree.IntInsnNode;

+import org.objectweb.asm.tree.MethodNode;

+import org.objectweb.asm.tree.TypeInsnNode;

+

+

+

+/**

+ * This class moves the code of a method to callOrig. 

+ * @author Oliver Frank

+ */

+public class MoveCodeToCallOrigAdapter extends AbstractTransformableClassNode {

+	private Method method;

+	private int boundMethodId;

+	private int firstArgIndex; // slot index of the first argument (0 (static) or 1 (non-static))

+	private int argOffset; // used to skip synth args if the callOrig method itself is a statid role method

+	private Method callOrig;

+	

+	public MoveCodeToCallOrigAdapter(AsmWritableBoundClass clazz, Method method, int boundMethodId) {

+		this.method = method;

+		this.boundMethodId = boundMethodId;

+		if (method.isStatic()) {

+			firstArgIndex = 0;

+			argOffset = clazz.isRole() ? 2 : 0;

+			callOrig = clazz.getCallOrigStatic();

+		} else {

+			firstArgIndex = 1;

+			callOrig = ConstantMembers.callOrig;

+		}

+	}

+	

+	public void transform() {

+		MethodNode orgMethod = getMethod(method);

+		MethodNode callOrig = getMethod(this.callOrig);

+		

+		Type returnType = Type.getReturnType(orgMethod.desc);

+		

+		

+				

+		InsnList newInstructions = new InsnList();

+		

+		

+		//Unboxing arguments

+		Type[] args = Type.getArgumentTypes(orgMethod.desc);

+		

+		if (args.length > 0) {

+			newInstructions.add(new IntInsnNode(Opcodes.ALOAD, firstArgIndex + argOffset + 1));

+			

+			int slot = firstArgIndex + argOffset;

+			for (int i = argOffset; i < args.length; i++) {

+				if (i < args.length - 1) {

+					newInstructions.add(new InsnNode(Opcodes.DUP));

+				}

+				newInstructions.add(createLoadIntConstant(i));

+				newInstructions.add(new InsnNode(Opcodes.AALOAD));

+				Type arg = args[i];

+				if (arg.getSort() != Type.ARRAY && arg.getSort() != Type.OBJECT) {

+					String objectType = AsmTypeHelper.getObjectType(arg);

+					newInstructions.add(new TypeInsnNode(Opcodes.CHECKCAST, objectType));

+					newInstructions.add(AsmTypeHelper.getUnboxingInstructionForType(arg, objectType));

+				} else {

+					newInstructions.add(new TypeInsnNode(Opcodes.CHECKCAST, arg.getInternalName()));

+				}

+				

+				newInstructions.add(new IntInsnNode(args[i].getOpcode(Opcodes.ISTORE), slot));

+				slot += arg.getSize();

+			}

+		}

+		

+		// replace return of the original method with areturn and box the result value if needed

+		replaceReturn(orgMethod.instructions, returnType);

+		

+		newInstructions.add(orgMethod.instructions);

+		

+		addNewLabelToSwitch(callOrig.instructions, newInstructions, boundMethodId);

+		

+		// a minimum stacksize of 3 is neede to box the arguments

+		callOrig.maxStack = Math.max(Math.max(callOrig.maxStack, orgMethod.maxStack), 3);

+		

+		// we have to increment the max. stack size, because we have to put NULL on the stack

+		if (returnType.getSort() == Type.VOID) {

+			callOrig.maxStack += 1;

+		}

+		callOrig.maxLocals = Math.max(callOrig.maxLocals, orgMethod.maxLocals);

+	}

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/MultiClassAdapter.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/MultiClassAdapter.java
new file mode 100644
index 0000000..0b0bcda
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/MultiClassAdapter.java
@@ -0,0 +1,78 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.bytecode.asm;

+

+import java.util.ArrayList;

+import java.util.List;

+

+import org.objectweb.asm.ClassAdapter;

+import org.objectweb.asm.ClassVisitor;

+import org.objectweb.asm.MethodVisitor;

+

+/**

+ * This class is needed to make it possible, that many 

+ * ClassAdpters can manipulate the bytecode in one run.

+ * It just delegates all method calls to the concrete Adapters.

+ * @author Oliver Frank

+ */

+class MultiClassAdapter extends ClassAdapter {

+

+	private List<ClassVisitor> visitors;

+	private ClassVisitor toplevelVisitor;

+	

+	public MultiClassAdapter(ClassVisitor v) {

+		super(v);

+		this.visitors = new ArrayList<ClassVisitor>();

+	}

+

+	public void addVisitor(ClassVisitor v) {

+		visitors.add(v);

+	}

+	

+	/** We only support one visitor to intercept the toplevel class definition. */

+	public void setToplevelVisitor(ClassVisitor v) {

+		this.toplevelVisitor = v;

+	}

+	

+	@Override

+	public void visit(int version, int access, String name, String signature,

+			String superName, String[] interfaces) {

+		if (this.toplevelVisitor != null)

+			this.toplevelVisitor.visit(version, access, name, signature, superName, interfaces);

+		else

+			super.visit(version, access, name, signature, superName, interfaces);

+	}

+	@Override

+	public void visitEnd() {

+		for (ClassVisitor visitor : visitors) {

+			visitor.visitEnd();

+		}

+	}

+	

+	@Override

+	public MethodVisitor visitMethod(int access, String name, String desc,

+			String signature, String[] exceptions) {

+		MethodVisitor result = null;

+		for (ClassVisitor visitor : visitors) {

+			result = visitor.visitMethod(access, name, desc, signature, exceptions);

+			if (result != null) {

+				return result;

+			}

+		}

+		return super.visitMethod(access, name, desc, signature, exceptions);

+	}

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/runtime/ClassIdentifierProviderFactory.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/runtime/ClassIdentifierProviderFactory.java
new file mode 100644
index 0000000..c9e8cbe
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/runtime/ClassIdentifierProviderFactory.java
@@ -0,0 +1,38 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.runtime;

+

+/**

+ * Provides a singleton instance of {@link IClassIdentifierProvider}.

+ * If no instance is set, this class uses the {@link DefaultClassIdentifierProvider}.

+ * @author Oliver Frank

+ */

+public class ClassIdentifierProviderFactory {

+	private static IClassIdentifierProvider instance;

+	

+	public static void setClassIdentifierProvider(IClassIdentifierProvider provider) {

+		instance = provider;

+	}

+	

+	public static IClassIdentifierProvider getClassIdentifierProvider() {

+		if (instance == null) {

+			instance = new DefaultClassIdentifierProvider();

+		}

+		

+		return instance;

+	}

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/runtime/DefaultClassIdentifierProvider.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/runtime/DefaultClassIdentifierProvider.java
new file mode 100644
index 0000000..91b10a4
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/runtime/DefaultClassIdentifierProvider.java
@@ -0,0 +1,38 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.runtime;

+

+/**

+ * Default implementation of {@link IClassIdentifierProvider}, that just 

+ * returns the class name as identifier. This implementation could be used

+ * in a standard java context.

+ * @author Oliver Frank

+ */

+public class DefaultClassIdentifierProvider implements IClassIdentifierProvider {

+

+	public String getBoundClassIdentifier(Class<?> teem, String boundClassname) {

+		return boundClassname;

+	}

+

+	public String getSuperclassIdentifier(String classId, String superclassName) {

+		return superclassName;

+	}

+

+	public String getClassIdentifier(Class<?> clazz) {

+		return clazz.getName().replace('.', '/');

+	}

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/runtime/IClassIdentifierProvider.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/runtime/IClassIdentifierProvider.java
new file mode 100644
index 0000000..e1fb9a6
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/runtime/IClassIdentifierProvider.java
@@ -0,0 +1,47 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.runtime;

+

+/**

+ * This class provides globally unique identifiers for all classes.

+ * @author Oliver Frank

+ */

+public interface IClassIdentifierProvider {

+	/**

+	 * Returns a globally unique identifier for a base class of a given team.

+	 * @param teem

+	 * @param boundClassname

+	 * @return

+	 */

+	public String getBoundClassIdentifier(Class<?> teem, String boundClassname);

+

+	/**

+	 * Returns a globally unique identifier for a superclass of the class

+	 * with the given id.

+	 * @param classId

+	 * @param superclassName

+	 * @return

+	 */

+	public String getSuperclassIdentifier(String classId, String superclassName);

+	

+	/**

+	 * Returns a globally unique identifier for a class.

+	 * @param clazz

+	 * @return

+	 */

+	public String getClassIdentifier(Class<?> clazz);

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/runtime/TeamManager.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/runtime/TeamManager.java
new file mode 100644
index 0000000..cfab9fb
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/runtime/TeamManager.java
@@ -0,0 +1,342 @@
+/**********************************************************************
+ * This file is part of "Object Teams Dynamic Runtime Environment"
+ * 
+ * Copyright 2009, 2012 Oliver Frank and others.
+ * 
+ * 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:
+ *		Oliver Frank - Initial API and implementation
+ *		Stephan Herrmann - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otredyn.runtime;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.objectteams.otredyn.bytecode.AbstractBoundClass;
+import org.objectteams.ITeam;
+
+/**
+ * This class administrates the the active teams and their
+ * callin ids for all joinpoints.
+ * Teams have to register/unregister themselves at this class, 
+ * while their activation/deactivation.
+ * The generated client code can call methods of this class to
+ * get the active teams and callin ids.
+ * @author Oliver Frank
+ *
+ */
+public class TeamManager {
+	
+	public static enum TeamStateChange {
+			REGISTER,
+			UNREGISTER
+		}
+	//	void handleTeamStateChange(ITeam t, TeamStateChange stateChange) ;
+	private static List<List<ITeam>> _teams = new ArrayList<List<ITeam>>();
+	private static List<List<Integer>> _callinIds = new ArrayList<List<Integer>>();
+	private static Map<String, Integer> joinpointMap = new HashMap<String, Integer>();
+	private static Map<Class<?>, List<Integer>> accessIdMap = new HashMap<Class<?>, List<Integer>>();
+	private static int currentJoinpointId = 0;
+	// map all original joinpoints to their inherited versions in subclasses
+	private static Map<Integer,List<Integer>> joinpointToSubJoinpoints = new HashMap<Integer, List<Integer>>();
+	private static IClassRepository classRepository;
+
+	public static void setup(IClassRepository repo) {
+		classRepository = repo;
+	}
+
+	/**
+	 * Returns all active teams for joinpoint.
+	 * This method is intended to be called by 
+	 * generated client code.
+	 * @param joinpointId
+	 * @return all active teams for the joinpoint or null
+	 * if there are no active teams
+	 */
+	public static ITeam[] getTeams(int joinpointId) {
+		List<ITeam> teams = _teams.get(joinpointId);
+		if (teams.size() == 0) {
+			return null;
+		}
+		return teams.toArray(new ITeam[teams.size()]);
+	}
+
+	/**
+	 * Returns all callin ids for the active teams and the joinpoint.
+	 * This method is intended to be called by 
+	 * generated client code.
+	 * @param joinpointId
+	 * @return the callin ids for the joinpoint or null
+	 * if there are no active teams
+	 */
+	public static int[] getCallinIds(int joinpointId) {
+		List<Integer> callinIds = _callinIds.get(joinpointId);
+		if (callinIds.size() == 0) {
+			return null;
+		}
+		int[] result = new int[callinIds.size()];
+		int i = 0;
+		for (Integer callinId : callinIds) {
+			result[i] = callinId;
+			i++;
+		}
+		return result;
+	}
+
+	/**
+	 * Returns the member id for a given team and a access id 
+	 * used in this team.
+	 * This method is intended to be called by 
+	 * generated client code.
+	 * @param accessId
+	 * @param Team
+	 * @return
+	 */
+	public static int getMemberId(int accessId, Class<? extends ITeam> teamClass) {
+		return accessIdMap.get(teamClass).get(accessId);
+	}
+
+	/**
+	 * Returns and possibly creates a globally unique id for a
+	 * joinpoint identifier. Additionally it prepares the 
+	 * structures needed to store the teams and callin ids for a joinpoint.
+	 * @param joinpointIdentifier
+	 * @return a joinpoint id
+	 */
+	public synchronized static int getJoinpointId(String joinpointIdentifier) {
+		Integer joinpointId = getExistingJoinpointId(joinpointIdentifier);
+		if (joinpointId == null) {
+			joinpointMap.put(joinpointIdentifier, currentJoinpointId);
+			List<ITeam> teams = new ArrayList<ITeam>();
+			_teams.add(teams);
+			List<Integer> callinIds = new ArrayList<Integer>();
+			_callinIds.add(callinIds);
+			return currentJoinpointId++;
+		}
+		return joinpointId;
+	}
+	
+	/**
+	 * Returns an existing globally unique joinpoint id
+	 * for a joinpoint identifier 
+	 * @param joinpointIdentifier
+	 * @return the joinpoint id or null if a joinpoint id
+	 * doesn't exist for this joinpoint identifier
+	 */
+	private static Integer getExistingJoinpointId(String joinpointIdentifier) {
+		return joinpointMap.get(joinpointIdentifier);
+	}
+
+	/**
+	 * Handles registration and unregistration of teams.
+	 * Stores the team and the ids dependend on the joinpoints and
+	 * tell the {@link AbstractBoundClass} representing the base classes
+	 * of the team, that there is new Binding
+	 * @param t
+	 * @param stateChange
+	 */
+	public static void handleTeamStateChange(ITeam t, TeamManager.TeamStateChange stateChange) {
+		IClassIdentifierProvider provider = ClassIdentifierProviderFactory.getClassIdentifierProvider();
+		Class<? extends ITeam> teamClass = t.getClass();
+		String teamId = provider.getClassIdentifier(teamClass);
+		IBoundTeam teem = classRepository.getTeam(teamClass.getName(), teamId, teamClass.getClassLoader());
+
+		for (IBinding binding : teem.getBindings()) {
+			String boundClassName = binding.getBoundClass();
+			String boundClassIdentifier = provider.getBoundClassIdentifier(teamClass, boundClassName);
+			// FIXME(SH): the following may need adaptation for OT/Equinox or other multi-classloader settings:
+			IBoundClass boundClass = classRepository.getBoundClass(boundClassName.replace('/', '.'), boundClassIdentifier, teamClass.getClassLoader());
+			// FIXME(SH): if boundClass is a role we need to find tsub roles, too!
+			switch (binding.getType()) {
+			case CALLIN_BINDING:
+				IMethod method = boundClass.getMethod(binding.getMemberName(), binding.getMemberSignature(), binding.isHandleCovariantReturn());
+				int joinpointId = getJoinpointId(boundClass
+						.getMethodIdentifier(method));
+				synchronized (method) {
+					changeTeamsForJoinpoint(t, binding.getCallinId(), joinpointId, stateChange);
+					List<Integer> subJoinpoints = joinpointToSubJoinpoints.get(joinpointId);
+					if (subJoinpoints != null)
+						for (Integer subJoinpoint : subJoinpoints)
+							changeTeamsForJoinpoint(t, binding.getCallinId(), subJoinpoint, stateChange);
+				}
+				boundClass.handleAddingOfBinding(binding); // TODO(SH): more lazy
+				break;
+			}
+			
+		}
+	}
+	public static void handleTeamLoaded(Class<? extends ITeam> teamClass) {
+		if (teamClass != null)
+			handleDecapsulation(teamClass);
+		performPendingTask();
+	}
+	private static void handleDecapsulation(Class<? extends ITeam> teamClass) {
+		IClassIdentifierProvider provider = ClassIdentifierProviderFactory.getClassIdentifierProvider();
+		String teamId = provider.getClassIdentifier(teamClass);
+		IBoundTeam teem = classRepository.getTeam(teamClass.getName(), teamId, teamClass.getClassLoader());
+
+		for (IBinding binding : teem.getBindings()) {
+			String boundClassName = binding.getBoundClass();
+			String boundClassIdentifier = provider.getBoundClassIdentifier(teamClass, boundClassName.replace('.', '/'));
+			// FIXME(SH): the following may need adaptation for OT/Equinox or other multi-classloader settings:
+			IBoundClass boundClass = classRepository.getBoundClass(boundClassName.replace('/', '.'), boundClassIdentifier, teamClass.getClassLoader());
+
+			switch (binding.getType()) {
+			case FIELD_ACCESS: // fallthrough
+			case METHOD_ACCESS:
+				IMember member = null;
+				if (binding.getType() == IBinding.BindingType.FIELD_ACCESS) {
+					member = boundClass.getField(binding.getMemberName(),
+							binding.getMemberSignature());
+				} else {
+					member = boundClass.getMethod(binding.getMemberName(), binding.getMemberSignature(), false/*covariantReturn*/);
+				}
+				
+				int memberId = member.getId(boundClass);
+				synchronized (member) {
+					addAccessIds(teamClass, teem, binding.getCallinId(), memberId);
+				}
+				boundClass.handleAddingOfBinding(binding);
+				break;
+			}
+		}
+	}
+	/**
+	 * Stores the access ids of a team and the corresponding member ids
+	 * @param t
+	 * @param teem
+	 * @param accessId
+	 * @param memberId
+	 * @param stateChange
+	 */
+	private static void addAccessIds(Class<? extends ITeam> clazz, IBoundTeam teem, int accessId, int memberId) {
+		List<Integer> accessIds = accessIdMap.get(clazz);
+		if (accessIds == null) {
+			int highestAccessId = teem.getHighestAccessId() + 1;
+			accessIds = new ArrayList<Integer>(highestAccessId);
+			for (int i = 0; i <= highestAccessId; i++) {
+				accessIds.add(0);
+			}
+			accessIdMap.put(clazz, accessIds);
+		}
+		accessIds.set(accessId, memberId);
+	}
+
+	/**
+	 * Stores or removes the team
+	 * @param t
+	 * @param callinId
+	 * @param joinpointId
+	 * @param stateChange
+	 */
+	private static void changeTeamsForJoinpoint(ITeam t, int callinId, int joinpointId, TeamManager.TeamStateChange stateChange) {
+		switch (stateChange) {
+		case REGISTER:
+			List<ITeam> teams = _teams.get(joinpointId);
+			teams.add(0, t);
+			List<Integer> callinIds = _callinIds.get(joinpointId);
+			callinIds.add(0, callinId);
+			break;
+		case UNREGISTER:
+			teams = _teams.get(joinpointId);
+			callinIds = _callinIds.get(joinpointId);
+			
+			int index = teams.indexOf(t);
+			while (index > -1) {
+				teams.remove(index);
+				callinIds.remove(index);
+				index = teams.indexOf(t);
+			}
+			break;
+		default: throw new RuntimeException("Unknown team state change: " + stateChange.name());
+		}
+	}
+
+	/**
+	 * Merge the teams and callin ids of two joinpoints into the second.
+	 * This is used so that activating teams for the second joinpoint (subclass)
+	 * will include the effect of activation of the former (superclass).
+	 * @param superClass
+	 * @param subClass
+	 * @param superMethod
+	 * @param subMethod
+	 */
+	public static void mergeJoinpoints(IBoundClass superClass,
+			IBoundClass subClass, final IMethod superMethod, IMethod subMethod, final boolean handleCovariantReturn) {
+		if (subClass.isAnonymous()) {
+			// destClass is a placeholder, schedule real merging for when a real subclass gets wired:
+			subClass.addWiringTask(new ISubclassWiringTask() {
+				public void wire(IBoundClass superClass, IBoundClass subClass) {
+					IMethod subMethod = subClass.getMethod(superMethod.getName(), superMethod.getSignature(),
+														   handleCovariantReturn);
+					mergeJoinpoints(superClass, subClass, superMethod, subMethod, handleCovariantReturn);
+				}
+			});
+			return;
+		}
+		synchronized (subClass) {
+			Integer superJoinpointId = getJoinpointId(superClass.getMethodIdentifier(superMethod));
+			if (superJoinpointId != null) {
+				int subJoinpointId = getJoinpointId(subClass.getMethodIdentifier(subMethod));
+				
+				List<Integer> subJoinpoints = joinpointToSubJoinpoints.get(superJoinpointId);
+				if (subJoinpoints == null) {
+					subJoinpoints = new ArrayList<Integer>();
+					joinpointToSubJoinpoints.put(superJoinpointId, subJoinpoints);
+				}
+				// already processed?
+				if (!subJoinpoints.contains(subJoinpointId)) {
+					subJoinpoints.add(subJoinpointId);
+					applyJoinpointMerge(superJoinpointId, subJoinpointId);
+				}
+			}
+		}
+	}
+
+	private synchronized static void applyJoinpointMerge(Integer srcJoinpointId, int destJoinpointId) {
+		List<ITeam> teams = _teams.get(destJoinpointId);
+		List<Integer> callinIds = _callinIds.get(destJoinpointId);
+		List<ITeam> srcTeams = _teams.get(srcJoinpointId);
+		List<Integer> srcCallins = _callinIds.get(srcJoinpointId);
+		for (int s=0; s<srcTeams.size(); s++) {
+			int d = 0; // FIXME(SH): find insertion index based on activation priority!!
+			teams.add(d, srcTeams.get(s));
+			callinIds.add(0, srcCallins.get(s));
+		}
+		_teams.set(destJoinpointId, teams);
+		_callinIds.set(destJoinpointId, callinIds);
+	}
+	
+	/** 
+	 * A "mailbox" for pending tasks (per thread). 
+	 * The weaver stores redefinition tasks here that failed because the class
+	 * was in a state between load-time transformation and definition.
+	 */
+	public static ThreadLocal<Runnable> pendingTasks = new ThreadLocal<Runnable>();
+	/**
+	 * Perform any tasks that are pending for this thread: redefinitions of a class 
+	 * that was in a state between load-time transformation and definition.
+	 */
+	public static void performPendingTask() {
+		Runnable task = pendingTasks.get();
+		if (task != null) {
+//			System.out.println("pending "+task);
+			pendingTasks.set(null);
+			try {
+				task.run();
+			} catch (Throwable t) {
+				System.err.println(t+" because "+t.getCause());
+				pendingTasks.set(task); // no success try later ??
+			}
+		}
+	}
+}
diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/transformer/names/ClassNames.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/transformer/names/ClassNames.java
new file mode 100644
index 0000000..a4bb5b7
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/transformer/names/ClassNames.java
@@ -0,0 +1,49 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.transformer.names;

+

+import java.util.HashSet;

+import java.util.List;

+

+import org.eclipse.objectteams.otredyn.runtime.TeamManager;

+import org.objectteams.IBoundBase;

+import org.objectteams.ITeam;

+import org.objectteams.ImplicitTeamActivation;

+import org.objectteams.SneakyException;

+import org.objectteams.Team;

+

+/**

+ * Container for class names used in the bytecode manipulating classes

+ * @author Oliver Frank

+ */

+public abstract class ClassNames {

+	public final static String I_BOUND_BASE_SLASH = IBoundBase.class.getName().replace('.', '/');

+	public final static String OBJECT_SLASH = Object.class.getName().replace('.', '/');

+	public final static String CLASS_SLASH = Class.class.getName().replace('.', '/');

+	public final static String I_BOUND_BASE_DOT = IBoundBase.class.getName();

+	public final static String TEAM_MANAGER_SLASH = TeamManager.class.getName().replace('.', '/');

+	public final static String ITEAM_SLASH = ITeam.class.getName().replace('.', '/');

+	public final static String TEAM_SLASH = Team.class.getName().replace('.', '/');

+	public final static String LIST_SLASH = List.class.getName().replace('.', '/');

+	public final static String HASH_SET_SLASH = HashSet.class.getName().replace('.', '/');

+	public final static String IMPLICIT_ACTIVATION = ImplicitTeamActivation.class.getName().replace('.', '/');

+

+	public static final String SNEAKY_EXCEPTION_SLASH = SneakyException.class.getName().replace('.', '/');

+	// member of SneakyException:

+	public static final String RETHROW_SELECTOR = "rethrow";

+	public static final String RETHROW_SIGNATURE = "()V"; 

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/transformer/names/ConstantMembers.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/transformer/names/ConstantMembers.java
new file mode 100644
index 0000000..72eec73
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/transformer/names/ConstantMembers.java
@@ -0,0 +1,123 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.transformer.names;

+

+import org.eclipse.objectteams.otredyn.bytecode.Field;

+import org.eclipse.objectteams.otredyn.bytecode.Method;

+import org.eclipse.objectteams.otredyn.bytecode.Types;

+import org.objectweb.asm.Opcodes;

+

+

+

+/**

+ * Container for methods used in the bytecode manipulating classes

+ * @author Oliver Frank

+ */

+public abstract class ConstantMembers {

+	

+	// predefined field:

+	public static final String OT_ROLE_SET = "_OT$roleSet";

+	public static final String HASH_SET_FIELD_TYPE = Types 

+	.getTypeStringForField(Types.getAsType(ClassNames.HASH_SET_SLASH));

+	public static final Field roleSet = new Field(OT_ROLE_SET, HASH_SET_FIELD_TYPE);

+	

+	// predefined methods

+	public static final Method callOrig = new Method("_OT$callOrig", Types

+			.getTypeStringForMethod(Types.getAsType(ClassNames.OBJECT_SLASH),

+					new String[] { Types.INT,

+							Types.getAsArrayType(ClassNames.OBJECT_SLASH) }));

+

+	public static final Method callOrigStatic = new Method(

+			"_OT$callOrigStatic",

+			Types.getTypeStringForMethod(Types

+					.getAsType(ClassNames.OBJECT_SLASH), new String[] {

+					Types.INT, Types.getAsArrayType(ClassNames.OBJECT_SLASH) }),

+			true, Opcodes.ACC_PUBLIC);

+

+	// this method's signature actually depends on the enclosing team class

+	// used when generating callOrigStatic method into a role class

+	// which needs two synthetic arguments.

+	public static Method callOrigStaticRoleVersion(String teamClass) {

+		return  new Method(

+			"_OT$callOrigStatic",

+			Types.getTypeStringForMethod(

+					Types.getAsType(ClassNames.OBJECT_SLASH), 

+					new String[] {

+						Types.INT,

+						Types.getAsType(teamClass),

+						Types.INT, 

+						Types.getAsArrayType(ClassNames.OBJECT_SLASH) 

+					}),

+			true, Opcodes.ACC_PUBLIC);

+	}

+

+	public static final Method callAllBindingsClient = new Method(

+			"callAllBindings", Types.getTypeStringForMethod(Types

+					.getAsType(ClassNames.OBJECT_SLASH), new String[] {

+					Types.INT, Types.getAsArrayType(ClassNames.OBJECT_SLASH) }));

+

+	public static final Method callAllBindingsTeam = new Method(

+			"_OT$callAllBindings", Types.getTypeStringForMethod(Types

+					.getAsType(ClassNames.OBJECT_SLASH), new String[] {

+					Types.getAsType(ClassNames.I_BOUND_BASE_SLASH),

+					Types.getAsArrayType(ClassNames.ITEAM_SLASH), Types.INT,

+					Types.getAsArrayType(Types.INT), Types.INT,

+					Types.getAsArrayType(ClassNames.OBJECT_SLASH) }));

+

+	public static final Method access = new Method("_OT$access", Types

+			.getTypeStringForMethod(Types.getAsType(ClassNames.OBJECT_SLASH),

+					new String[] { Types.INT, Types.INT,

+							Types.getAsArrayType(ClassNames.OBJECT_SLASH),

+							Types.getAsType(ClassNames.ITEAM_SLASH) }));

+

+	public static final Method accessStatic = new Method("_OT$accessStatic", Types

+			.getTypeStringForMethod(Types.getAsType(ClassNames.OBJECT_SLASH),

+					new String[] { Types.INT, Types.INT,

+							Types.getAsArrayType(ClassNames.OBJECT_SLASH),

+							Types.getAsType(ClassNames.ITEAM_SLASH) }), true, Opcodes.ACC_PUBLIC);

+

+	public static final Method getTeams = new Method("getTeams", Types

+			.getTypeStringForMethod(

+					Types.getAsArrayType(ClassNames.ITEAM_SLASH),

+					new String[] { Types.INT }));

+

+	public static final Method getCallinIds = new Method("getCallinIds", Types

+			.getTypeStringForMethod(Types.getAsArrayType(Types.INT),

+					new String[] { Types.INT }));

+

+	public static final Method getMemberId = new Method("getMemberId", Types

+			.getTypeStringForMethod(Types.INT, new String[] { Types.INT,

+					Types.getAsType(ClassNames.CLASS_SLASH) }));

+	

+	public static final Method addOrRemoveRole = new Method("_OT$addOrRemoveRole", Types

+			.getTypeStringForMethod(Types.VOID, new String[] { Types.getAsType(ClassNames.OBJECT_SLASH), Types.BOOLEAN }));

+

+	public static boolean isReflectiveOTMethod(String methodName, String methodDescriptor) {

+		if ((methodName.equals("hasRole") && methodDescriptor.equals("(Ljava/lang/Object;)Z"))

+				|| (methodName.equals("hasRole") && methodDescriptor.equals("(Ljava/lang/Object;Ljava/lang/Class;)Z"))

+				|| (methodName.equals("getRole") && methodDescriptor.equals("(Ljava/lang/Object;)Ljava/lang/Object;"))

+				|| (methodName.equals("getRole") && methodDescriptor.equals("(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;"))

+				|| (methodName.equals("getAllRoles") && methodDescriptor.equals("()[Ljava/lang/Object;"))

+				|| (methodName.equals("getAllRoles") && methodDescriptor.equals("(Ljava/lang/Class;)[Ljava/lang/Object;"))

+				|| (methodName.equals("unregisterRole") && methodDescriptor.equals("(Ljava/lang/Object;)V"))

+				|| (methodName.equals("unregisterRole") && methodDescriptor.equals("(Ljava/lang/Object;Ljava/lang/Class;)V"))

+		   )

+			return true;

+		return false;

+	}

+

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/util/ArrayUtil.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/util/ArrayUtil.java
new file mode 100644
index 0000000..7f3b841
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/util/ArrayUtil.java
@@ -0,0 +1,47 @@
+/**********************************************************************

+ * This file is part of "Object Teams Dynamic Runtime Environment"

+ * 

+ * Copyright 2009, 2012 Oliver Frank and others.

+ * 

+ * 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:

+ *		Oliver Frank - Initial API and implementation

+ *		Stephan Herrmann - Initial API and implementation

+ **********************************************************************/

+package org.eclipse.objectteams.otredyn.util;

+

+

+public abstract class ArrayUtil {

+	

+	public static String[] stringArrayPrepend(String[] array,String item) {

+		

+		if (array == null) {

+			return new String[] { item } ;

+		}

+		

+		int arr_len = array.length;

+		String [] new_arr = new String[array.length+1];

+		System.arraycopy(array,0,new_arr,1,arr_len);

+		new_arr[0] = item;

+		return new_arr;

+	}

+	

+	public static String[] stringArrayAppend(String[] array,String item) {

+		

+		if (array == null) {

+			return new String[] { item } ;

+		}

+		

+		int arr_len = array.length;

+		String [] new_arr = new String[array.length+1];

+		System.arraycopy(array,0,new_arr,0,arr_len);

+		new_arr[arr_len] = item;

+		return new_arr;

+	}

+}

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/objectteams/IBoundBase.java b/plugins/org.eclipse.objectteams.otredyn/src/org/objectteams/IBoundBase.java
new file mode 100644
index 0000000..afc892a
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/objectteams/IBoundBase.java
@@ -0,0 +1,42 @@
+/**********************************************************************
+ * This file is part of "Object Teams Dynamic Runtime Environment"
+ *
+ * Copyright 2007, 2012 Berlin Institute of Technology, Germany, and others.
+ *
+ * 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:
+ *		Berlin Institute of Technology - Initial API and implementation
+ * 		Oliver Frank - Initial API and Implementation
+ **********************************************************************/
+package org.objectteams;
+
+/** Super type for all bound base classes. Purely internal class, not intended for client use. */
+public interface IBoundBase {
+
+	/**
+	 * Call a bound base method identified by its ID.
+	 * @param boundMethod_id globally unique ID of a bound base method
+	 * @param args           packed arguments (incl. boxing)
+	 * @return               (possibly boxed) result of the bound base method.
+	 */
+	Object _OT$callOrig(int boundMethod_id, Object[] args);
+
+	/**
+	 * Provides access to fields and methods of a base class
+	 * that have package, protected or private visbility
+	 * @param accessId Unique identifier in the class for the field or method
+	 * @param opKind 0 for read access, 1 for write access. only used for fields
+	 * @param args arguments for a method
+	 * @return
+	 */
+	Object _OT$access(int accessId, int opKind, Object[] args, Team caller);
+
+	/** Method to be used by generated code, only (lifting constructor & unregisterRole()). */
+	void _OT$addOrRemoveRole(Object aRole, boolean adding);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/objectteams/Team.java b/plugins/org.eclipse.objectteams.otredyn/src/org/objectteams/Team.java
new file mode 100644
index 0000000..b59aaea
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/objectteams/Team.java
@@ -0,0 +1,655 @@
+/**********************************************************************
+ * This file is part of "Object Teams Dynamic Runtime Environment"
+ *
+ * Copyright 2002, 2012 Berlin Institute of Technology, Germany, and others.
+ *
+ * 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:
+ *		Berlin Institute of Technology - Initial API and implementation
+ * 		Oliver Frank - Initial API and Implementation
+ **********************************************************************/
+package org.objectteams;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.WeakHashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+
+import org.eclipse.objectteams.otredyn.runtime.TeamManager;
+
+
+/**
+ *  This is the root class of all team definitions.
+ *  Any class with the <tt>team</tt> modifier implicitly
+ *  inherits from this class.
+ *
+ */
+public /* team */ class Team implements ITeam {
+	// Technical note: comments starting with //$Debug are intended
+	// for a standalone tool that generates an interface
+	// which the debugger needs in order to know about line numbers in this class.
+
+	/*
+	 *  Synchronization: This class supports two levels of synchronization:
+	 *  <ul>
+	 *  <li>Fields of <code>Team</code> are synchronized
+	 *      using <code>this</code> as the monitor.
+	 *  <li>Those calls that (un)register a team at its base classes are synchronized
+	 *      via <code>registrationLock</code>
+	 *  </ul>
+	 *  This allows releasing the lock on <code>this</code> before calling to the base class.
+	 *  Note, that the synchronized portion of each initial-wrapper is also synchronized
+	 *  (against <code>_OT$addTeam/_OT$removeTeam</code>) and that it calls back to
+	 *  the registered teams (method <code>isActive()</code>).
+	 *  Without <code>registrationLock</code> this situation could easily deadlock:
+	 *  Thread1: <pre>t.activate() -> Base._OT$addTeam()</pre>: owns t, waits for Base.
+	 *  Thread2: <pre>b.bm() (initial wrapper) -> t.isActive()</pre>: owns Base, waits for t.
+	 */
+
+	/**
+	 * Internal field used by the runtime to install a lifting participant if one is configured.
+	 */
+	public static ILiftingParticipant _OT$liftingParticipant = null;
+
+	/**
+	 * Default constructor for debugging purpose.
+	 */
+	public Team() {} //$Debug(TeamConstructor)
+
+	/*
+	 * manual copy-inheritance of a role interface from ITeam.
+	 */
+	public interface ILowerable extends ITeam.ILowerable {}
+
+	/*
+	 * manual copy-inheritance of a role interface from ITeam.
+	 */
+	public interface IConfined extends ITeam.IConfined {}
+
+	/**
+	 *  Special role type that<ul>
+	 * <li> does not extend java.lang.Object
+	 * <li> may not leak references outside the team.
+	 * </ul>
+	 */
+	protected interface Confined {
+		/* internal method needed for cast and instanceof
+		 * (this method will be generated for role classes) */
+		ITeam _OT$getTeam();
+	}
+
+    /**
+     * This class would have been generated by the OT-compiler.
+     * Don't explicitly use it in client code!
+     */
+    protected class __OT__Confined implements Confined {
+		// internal method needed for cast and instanceof
+    	public ITeam _OT$getTeam() {
+    		return Team.this; //$Debug(ConfinedGetTeam)
+    	}
+    }
+
+	/**
+	 *  Internal function for identifying a Team.
+	 *  Should not be called by client code.
+	 */
+	public int _OT$getID () {return -1;}
+
+    /**
+	 * The constant <code>ALL_THREADS</code> is used for global team (de-)activation.
+	 */
+	public static final Thread ALL_THREADS = new Thread();
+
+	private static final int _OT$UNREGISTERED = 0;
+	private static final int _OT$REGISTERED = 1;
+	private  int _OT$registrationState = _OT$UNREGISTERED;
+
+	private boolean _OT$globalActive = false;
+
+	private ThreadLocal<Integer> _OT$implicitActivationsPerThread = new ThreadLocal<Integer>() {
+		@Override
+		protected synchronized Integer initialValue() {
+			return Integer.valueOf(0);
+		}
+	};
+
+	private boolean _OT$lazyGlobalActiveFlag = false;
+
+	/**
+	 * <code>_OT$activatedThreads</code> contains all threads for which this team instance is active.
+	 * key		= activated thread
+	 * value 	= Boolean(true) for explicit activation | Boolean(false) for implicit activation.
+	 */
+	private WeakHashMap<Thread, Boolean> _OT$activatedThreads = new WeakHashMap<Thread, Boolean>();
+
+	/** This lock is used to protect activate/deactivate methods <strong>including</strong>
+	 *  the calls to doRegistration/doUnregistration.
+	 */
+	private Object _OT$registrationLock= new Object();
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public void activate() {
+		activate(Thread.currentThread());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public void deactivate() {
+		deactivate(Thread.currentThread());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public void activate(Thread thread) {
+		// acquire both locks to avoid incomplete execution:
+		synchronized (this._OT$registrationLock) {
+			synchronized (this) {
+				if (thread.equals(ALL_THREADS)) {
+					_OT$globalActive = true;
+					_OT$lazyGlobalActiveFlag = true;
+					TeamThreadManager.addGlobalActiveTeam(this);
+				} else { // activation only for 'thread':
+					// register 'thread' as active:
+					_OT$activatedThreads.put(thread, Boolean.TRUE);
+				}
+			} // release this before calling synchronized base class methods
+			doRegistration(); //$Debug(ActivateMethod)
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public void deactivate(Thread thread) {
+		// acquire both locks to avoid incomplete execution:
+		synchronized (this._OT$registrationLock) {
+			boolean shouldUnregister= false;
+			synchronized(this) {
+				if (thread.equals(ALL_THREADS)) {
+					_OT$globalActive = false;
+					TeamThreadManager.removeGlobalActiveTeam(this);
+					// unregister all threads:
+					_OT$activatedThreads.clear();
+					shouldUnregister= true;
+				} else { // deactivation only for 'thread':
+					if (_OT$lazyGlobalActiveFlag) {
+						// be eager now: activate for all (other) threads:
+						_OT$activateForAllThreads();
+					}
+					// deactivate for 'thread', no longer active:
+					_OT$activatedThreads.remove(thread);
+					if (!_OT$lazyGlobalActiveFlag  && _OT$activatedThreads.isEmpty()) {
+						shouldUnregister= true;
+					}
+				}
+				_OT$lazyGlobalActiveFlag = false;
+			} // release this before calling synchronized base class methods
+			if (shouldUnregister) 		//$Debug(DeactivateMethod)
+				doUnregistration();
+		}
+	}
+
+	public void deactivateForEndedThread(Thread thread) {
+		synchronized (_OT$registrationLock) {
+			boolean shouldUnregister= false;
+			synchronized (this) {
+				_OT$activatedThreads.remove(thread);
+				if (!_OT$lazyGlobalActiveFlag  && _OT$activatedThreads.isEmpty())
+					shouldUnregister= true;
+			}
+			if (shouldUnregister)
+				doUnregistration();
+		}
+	}
+
+	private void _OT$activateForAllThreads() {
+		HashSet threads = TeamThreadManager.getExistingThreads();
+		Iterator it = threads.iterator();
+		while (it.hasNext()) {
+			Thread a_thread = (Thread) it.next();
+			activate(a_thread); // use smaller activate version (no ALL_THREADS, no registerAtBases,...
+		}
+	}
+
+	/**
+	 * This method is used for implicit activation in team-level methods.
+	 * Implicit activation only applies to the current thread.
+	 * Don't call it from client code.
+	 */
+	public void _OT$implicitlyActivate() {
+		synchronized (this._OT$registrationLock) {
+			boolean shouldRegister= false;
+			synchronized (this) {
+				// this method is used for debugging purpose (team monitor)
+				Thread currentThread = Thread.currentThread();
+				if (!_OT$activatedThreads.containsKey(currentThread)) {
+					// register 'thread' as active:
+					_OT$activatedThreads.put(currentThread, Boolean.FALSE);
+					shouldRegister= true;
+				}
+				//	increment thread local implicit activation counter:
+				int implActCount = (_OT$implicitActivationsPerThread.get()).intValue();
+				_OT$implicitActivationsPerThread.set(Integer.valueOf(implActCount + 1 ));
+			}
+			if (shouldRegister) //$Debug(ImplicitActivateMethod)
+				doRegistration();
+		}
+	}
+
+	/**
+	 * This method is used for implicitly deactivation in team-level methods.
+	 * It respects explicit activation changes and nested calls to team-level methods.
+	 * Implicit deactivation only applies to the current thread.
+	 * Don't call it from client code.
+	 */
+	public void _OT$implicitlyDeactivate() {
+		synchronized (this._OT$registrationLock) {
+			boolean shouldUnregister= false;
+			synchronized(this) {
+				// this method is used for debugging purpose (team monitor)
+				Thread currentThread = Thread.currentThread();
+				boolean explicitlyActivated = false;
+				if (_OT$activatedThreads.containsKey(currentThread)) {
+					explicitlyActivated = ((Boolean) _OT$activatedThreads.get(currentThread)).booleanValue();
+				}
+				if (!explicitlyActivated
+						&& !_OT$lazyGlobalActiveFlag // no explicit activation overriding the implicit one
+						&& ((_OT$implicitActivationsPerThread.get()).intValue() == 1))  // this is the last implicit activation
+				{
+					_OT$activatedThreads.remove(currentThread);
+					if (_OT$activatedThreads.isEmpty()) // there are not other threads for which this theam is active
+					{
+						shouldUnregister= true;
+					}
+				}
+				// decrement thread local implicit activaion counter:
+				int implActCount = (_OT$implicitActivationsPerThread.get()).intValue();
+				_OT$implicitActivationsPerThread.set(Integer.valueOf(implActCount - 1));
+			}
+			if (shouldUnregister) //$Debug(ImplicitDeactivateMethod)
+				doUnregistration();
+		}
+	}
+
+	/**
+	 * Define whether per-thread activation of this team should be inheritable
+	 * such that the team will be activated automatically for any new threads
+	 * that are spawned from a thread for which the team is already active at that time.
+	 *
+	 * @param inheritable whether or not activation should be inheritable to new threads
+	 */
+	public void setInheritableActivation(boolean inheritable) {
+		if (inheritable)
+			TeamThreadManager.registerTeamForActivationInheritance(this);
+		else
+			TeamThreadManager.unRegisterTeamForActivationInheritance(this);
+	}
+
+	// not API (for use by the TeamThreadManager)
+	public boolean internalIsActiveSpecificallyFor(Thread t) {
+		return this._OT$activatedThreads.containsKey(t);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public final boolean isActive() {
+		return isActive(Thread.currentThread());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public final boolean isActive(Thread thread) {
+		if (thread.equals(ALL_THREADS)) {
+			return _OT$globalActive;
+		}
+		if (_OT$lazyGlobalActiveFlag) {
+				return true;
+		} else {
+			//if (!TeamThreadManager.getExistingThreads().contains(thread)) { // this thread is already finished!
+			if (!thread.isAlive()) { // this thread is already finished!
+				throw new IllegalThreadStateException("Called 'isActive(...)' for a thread which is no longer running!");
+			}
+			return _OT$activatedThreads.containsKey(thread);
+		}
+	}
+
+// ***** for restoring the activation state after a within block:	---->*****
+	private static final int _OT$INACTIVE = 0;
+	private static final int _OT$IMPLICIT_ACTIVE = 1;
+	private static final int _OT$EXPLICIT_ACTIVE = 2;
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public synchronized int _OT$saveActivationState() {
+		int old_state = _OT$INACTIVE;
+		if (_OT$lazyGlobalActiveFlag) {
+			old_state = _OT$EXPLICIT_ACTIVE;
+		} else {
+			Thread current_thread = Thread.currentThread();
+			if (_OT$activatedThreads.containsKey(current_thread)) {
+				old_state = _OT$IMPLICIT_ACTIVE;
+				if (((Boolean)_OT$activatedThreads.get(current_thread)).booleanValue()) {
+					old_state = _OT$EXPLICIT_ACTIVE;
+				}
+			}
+		}
+		return old_state;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public void _OT$restoreActivationState(int old_state) {
+		synchronized (_OT$registrationLock) {
+			if (old_state == _OT$INACTIVE) // team was inactive before:
+				deactivate();
+			else { // team was active before: has to be reactivated:
+				boolean explicit = (old_state == _OT$EXPLICIT_ACTIVE);
+				synchronized (this) {
+					_OT$activatedThreads.put(Thread.currentThread(), Boolean.valueOf(explicit));
+				}
+				doRegistration();
+			}
+		}
+	}
+//	 ***** <----for restoring the activation state after a within block.	*****
+
+
+	private void doRegistration() {
+		if (_OT$registrationState == _OT$UNREGISTERED) {
+			// register the team at the TeamManager
+			TeamManager.handleTeamStateChange(this, TeamManager.TeamStateChange.REGISTER);
+			_OT$registrationState = _OT$REGISTERED;
+		}
+	}
+
+	private void doUnregistration() {
+		if (_OT$registrationState == _OT$REGISTERED) {
+			// unregister the team at the TeamManager
+			TeamManager.handleTeamStateChange(this, TeamManager.TeamStateChange.UNREGISTER);
+			_OT$registrationState = _OT$UNREGISTERED;
+		}
+	}
+
+	/**
+	 * This method will be implemented by generated code in subteams.
+	 * It registers the team at every base playing one of its roles.
+	 * Don't call it from client code.
+	 */
+	public void _OT$registerAtBases() {}
+
+	/**
+	 * This method will be implemented by generated code in subteams.
+	 * It unregisters the team from every base playing one of its roles.
+	 * Don't call it from client code.
+	 */
+	public void _OT$unregisterFromBases() {}
+
+	//public int _OT$activationState = -1; // TODO: remove usage of  this from generated code
+
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean hasRole(Object aBase) {
+		// overriding method to be generated by the compiler for each team with bound roles.
+		return false;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean hasRole(Object aBase, Class<?> roleType) throws IllegalArgumentException {
+		// overriding method to be generated by the compiler for each team with bound roles.
+		throw new IllegalArgumentException("No such bound role type in this team: "+roleType.getName());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Object getRole(Object aBase) {
+		// overriding method to be generated by the compiler for each team with bound roles.
+		return null;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public <T> T getRole(Object aBase, Class<T> roleType) throws IllegalArgumentException {
+		// overriding method to be generated by the compiler for each team with bound roles.
+		return null;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Object[] getAllRoles() {
+		// overriding method to be generated by the compiler for each team with bound roles.
+		return new Object[0];
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public <T> T[] getAllRoles(Class<T> roleType) throws IllegalArgumentException {
+		// overriding method to be generated by the compiler for each team with bound roles.
+		throw new IllegalArgumentException("Class org.objectteams.Team has no bound roles.");
+	}
+
+	/** Internal variable to be set from generated code. */
+	private boolean _OT$isExecutingCallin = false;
+
+	/**
+	 * Method only for internal use by generated code.
+	 */
+	public boolean _OT$setExecutingCallin(boolean newFlag) {
+		boolean oldVal = _OT$isExecutingCallin;
+		_OT$isExecutingCallin = newFlag;
+		return oldVal;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean isExecutingCallin() {
+		return _OT$isExecutingCallin;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public void unregisterRole(Object aRole) {
+		// overriding method to be generated by the compiler for each team with bound roles.
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public void unregisterRole(Object aRole, Class<?> roleType) throws IllegalArgumentException {
+		// overriding method to be generated by the compiler for each team with bound roles.
+	}
+
+	@Override
+	protected void finalize() throws Throwable {
+		// nop, hook for the debugger
+		@SuppressWarnings("unused")
+		int i= 2+3; // Note: body must not be empty for debuggger to be able to stop.
+	} // $Debug(FinalizeMethod)
+
+	/**
+	 * If a serializable team wishes to persist its global activation status it must
+	 * call this method from its writeObject() method and correspondingly call
+	 * {@link #readGlobalActivationState(ObjectInputStream)} from its readObject().
+	 */
+	protected void writeGlobalActivationState(ObjectOutputStream out) throws IOException {
+		out.writeBoolean(this._OT$globalActive);
+	}
+	/**
+	 * If a serializable team wishes to persist its global activation status it must
+	 * call this method from its readObject() method and correspondingly call
+	 * {@link #writeGlobalActivationState(ObjectOutputStream)} from its writeObject().
+	 * If a team is restored that was globally active when serialized, it will be activated
+	 * correspondingly during deserialization when this method is called.
+	 */
+	protected void readGlobalActivationState(ObjectInputStream in) throws IOException {
+		this._OT$globalActive = in.readBoolean();
+		if (this._OT$globalActive) {
+			this._OT$lazyGlobalActiveFlag = true;
+			this.doRegistration();
+		}
+	}
+	/**
+	 * Serializable teams must invoke this method once from their readObject() method
+	 * in order to re-initialize internal data structures.
+	 */
+	protected void restore() { /* empty; implementation will be generated for each serializable sub-class. */ }
+	/**
+	 * Serializable teams must invoke this method from their readObject() method
+	 * for each role that has been retrieved and shall be re-registered for this team.
+	 */
+	protected void restoreRole(Class<?> clazz, Object role) { /* empty; implementation will be generated for each serializable sub-class. */ }
+
+	/**
+	 * This method is the first part of the new chaining wrapper.
+	 * It should be called from the generated client code.
+	 *
+	 * @param baze the current base object
+	 * @param teams the current team objects
+	 * @param idx the index of the current team in teams
+	 * @param callinIds an array of ids, that are unique in the team
+	 *                  for a base method in a base class
+	 * @param boundMethodId an unique id for a base method in the base class.
+	 *                      This id is needed for a base call.
+	 * @param args packed arguments.
+	 * @return possibly boxed result
+	 */
+	public Object _OT$callAllBindings(IBoundBase baze, ITeam[] teams,int idx,int[] callinIds, int boundMethodId, Object[] args)
+	{
+
+
+		this._OT$callBefore(baze, callinIds[idx], boundMethodId, args);
+
+		Object res = this._OT$callReplace(baze, teams, idx, callinIds, boundMethodId, args);
+
+		this._OT$callAfter(baze, callinIds[idx], boundMethodId, args, res); // make result available to param mappings!
+
+		return res;
+	}
+
+	/**
+	 * This method calls the next team or a base method,
+	 * if there are no more active teams for a joinpoint
+	 *
+	 * @param baze the current base object
+	 * @param teams the current base object
+	 * @param idx the index of the current team in teams, also points into callinIds, i.e., both lists run synchroneously.
+	 * @param callinIds an array of ids, that are unique in the team
+	 *                  for a base method in a base class
+	 * @param boundMethodId an unique id for a base method in the base class.
+	 *                      This id is needed for a base call.
+	 * @param args original packed arguments.
+	 * @param baseCallArgs packed arguments as provided to the base call.
+	 * @return possibly boxed result
+	 */
+	public Object _OT$callNext(IBoundBase baze, ITeam[] teams, int idx, int[] callinIds, int boundMethodId, Object[] args, Object[] baseCallArgs)
+	{
+//System.out.println("callNext idx="+idx);
+//for (Team t : teams)
+//	System.out.println("team="+t);
+		// Are there still active teams?
+		if (idx+1 < teams.length) {
+			// Yes, so call the next team/callin
+			return teams[idx+1]._OT$callAllBindings(baze, teams, idx+1, callinIds, boundMethodId, args);
+		} else {
+			//No, call the base method
+			if (baze == null) {
+				//handle base call to a static base method
+				return teams[idx]._OT$callOrigStatic(callinIds[idx], boundMethodId, args);
+			} else {
+//System.out.println("callOrig: "+boundMethodId);
+				return baze._OT$callOrig(boundMethodId, args);
+//Object result = baze.callOrig(boundMethodId, args);
+//System.out.println("->"+result);
+//return result;
+			}
+		}
+	}
+
+	/**
+	 * Executes all before callins for a given callin id.
+	 * Must be overridden by a team, if the team gets replace callins.
+	 *
+	 * @param baze the current base object
+	 * @param callinId the current callin id
+	 * @param boundMethodId an unique id for a base method in the base class.
+	 *                      This id is needed for a base call.
+	 * @param args packed arguments.
+	 * @return possibly boxed result
+	 */
+	public void _OT$callBefore(IBoundBase baze, int callinId, int boundMethodId, Object[] args) {
+		// nop; override with code from before callin bindings.
+	}
+
+	/**
+	 * Executes all after callins for a given callin id.
+	 * Must be overridden by a team, if the team gets replace callins.
+	 *
+	 * @param baze the current base object
+	 * @param callinId the current callin id
+	 * @param boundMethodId an unique id for a base method in the base class.
+	 *                      This id is needed for a base call.
+	 * @param args packed arguments.
+	 * @param result the result of the base method. Could be used by after callins
+	 */
+	public void _OT$callAfter(IBoundBase baze, int callinId, int boundMethodId, Object[] args, Object result) {
+		// nop; override with code from after callin bindings.
+	}
+
+	/**
+	 * Execute replace callins of the team for the current callin id.
+	 * Must be overridden by a team, if the team has got replace callins.
+	 *
+	 * @param baze the current base object
+	 * @param teams the current base object
+	 * @param idx the index of the current team in teams
+	 * @param callinIds an array of ids, that are unique in the team
+	 *                  for a base method in a base class
+	 * @param boundMethodId an unique id for a base method in the base class.
+	 *                      This id is needed for a base call.
+	 * @param args packed arguments.
+	 * @return possibly boxed result
+	 */
+	public Object _OT$callReplace(IBoundBase baze, ITeam[] teams, int idx, int[] callinIds, int boundMethodId, Object[] args) {
+		// default; override with code from replace callin bindings.
+		return _OT$callNext(baze, teams, idx, callinIds, boundMethodId, args, null);
+	}
+
+	/**
+	 * Calls the method callOrigStatic of a concrete class dependend on the
+	 * given callin id.
+	 * Must be overridden in a team, if the team has got base calls
+	 * to static base methods
+	 * @param callinId
+	 * @param boundMethodId
+	 * @param args
+	 * @return
+	 */
+	public Object _OT$callOrigStatic(int callinId, int boundMethodId, Object[] args) {
+		return null;
+	}
+}