diff options
author | Stephan Herrmann | 2010-07-22 22:09:37 +0000 |
---|---|---|
committer | Stephan Herrmann | 2010-07-22 22:09:37 +0000 |
commit | 9a06c38edca4e454a99e6ab52188201654353ccb (patch) | |
tree | 9ed25fcafa7c4e82683a7fdf5bc8ded186666971 /othersrc | |
parent | 368dbb02c7f2143f6d6249d36600acd1099dba25 (diff) | |
download | org.eclipse.objectteams-9a06c38edca4e454a99e6ab52188201654353ccb.tar.gz org.eclipse.objectteams-9a06c38edca4e454a99e6ab52188201654353ccb.tar.xz org.eclipse.objectteams-9a06c38edca4e454a99e6ab52188201654353ccb.zip |
Project is no longer needed, content was moved to plugins/org.eclipse.objectteams.runtime
Diffstat (limited to 'othersrc')
54 files changed, 0 insertions, 13646 deletions
diff --git a/othersrc/OTRE/.classpath b/othersrc/OTRE/.classpath deleted file mode 100644 index 3532c7495..000000000 --- a/othersrc/OTRE/.classpath +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<classpath> - <classpathentry kind="src" path="src"/> - <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/> - <classpathentry combineaccessrules="false" kind="src" path="/org.apache.bcel"/> - <classpathentry kind="output" path="bin"/> -</classpath> diff --git a/othersrc/OTRE/.project b/othersrc/OTRE/.project deleted file mode 100644 index 9f6b8319b..000000000 --- a/othersrc/OTRE/.project +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<projectDescription> - <name>OTRE</name> - <comment></comment> - <projects> - </projects> - <buildSpec> - <buildCommand> - <name>org.eclipse.jdt.core.javabuilder</name> - <arguments> - </arguments> - </buildCommand> - </buildSpec> - <natures> - <nature>org.eclipse.jdt.core.javanature</nature> - </natures> -</projectDescription> diff --git a/othersrc/OTRE/.settings/org.eclipse.jdt.core.prefs b/othersrc/OTRE/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 1aa712415..000000000 --- a/othersrc/OTRE/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,70 +0,0 @@ -#Thu Sep 18 21:57:35 CEST 2008 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.5 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=error -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.5 diff --git a/othersrc/OTRE/MANIFEST.MF b/othersrc/OTRE/MANIFEST.MF deleted file mode 100644 index c759b23fd..000000000 --- a/othersrc/OTRE/MANIFEST.MF +++ /dev/null @@ -1,5 +0,0 @@ -Manifest-Version: 1.0
-Premain-Class: org.eclipse.objectteams.otre.jplis.otreAgent
-Can-Redefine-Classes: true
-Built-By: resix
-
diff --git a/othersrc/OTRE/about.html b/othersrc/OTRE/about.html deleted file mode 100644 index 47048bd42..000000000 --- a/othersrc/OTRE/about.html +++ /dev/null @@ -1,28 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml"> -<head> -<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/> -<title>About</title> -</head> -<body lang="EN-US"> -<h2>About This Content</h2> - -<p>Feb 3, 2010</p> -<h3>License</h3> - -<p>The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise -indicated below, the Content is provided to you under the terms and conditions of the -Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available -at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>. -For purposes of the EPL, "Program" will mean the Content.</p> - -<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is -being redistributed by another party ("Redistributor") and different terms and conditions may -apply to your use of any object code in the Content. Check the Redistributor's license that was -provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise -indicated below, the terms and conditions of the EPL still apply to any source code in the Content -and such source code may be obtained at <a href="http://www.eclipse.org">http://www.eclipse.org</a>.</p> - -</body> -</html>
\ No newline at end of file diff --git a/othersrc/OTRE/otre-src-jar.jardesc b/othersrc/OTRE/otre-src-jar.jardesc deleted file mode 100644 index 755677629..000000000 --- a/othersrc/OTRE/otre-src-jar.jardesc +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<jardesc> - <jar path="org.eclipse.objectteams.runtime/lib/otre.jar"/> - <options buildIfNeeded="true" compress="true" descriptionLocation="/OTRE/otre-src-jar.jardesc" exportErrors="false" exportWarnings="true" includeDirectoryEntries="false" overwrite="true" saveDescription="true" storeRefactorings="false" useSourceFolders="false"/> - <storedRefactorings deprecationInfo="true" structuralOnly="false"/> - <selectedProjects/> - <manifest generateManifest="true" manifestLocation="" manifestVersion="1.0" reuseManifest="false" saveManifest="false" usesManifest="true"> - <sealing sealJar="false"> - <packagesToSeal/> - <packagesToUnSeal/> - </sealing> - </manifest> - <selectedElements exportClassFiles="false" exportJavaFiles="true" exportOutputFolder="true"> - <javaElement handleIdentifier="=OTRE/src"/> - </selectedElements> -</jardesc> diff --git a/othersrc/OTRE/otre_agent.jardesc b/othersrc/OTRE/otre_agent.jardesc deleted file mode 100644 index cf1515f36..000000000 --- a/othersrc/OTRE/otre_agent.jardesc +++ /dev/null @@ -1,14 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<jardesc> - <jar path="org.eclipse.objectteams.otdt/lib/otre_agent.jar"/> - <options overwrite="false" compress="true" exportErrors="false" exportWarnings="true" saveDescription="true" descriptionLocation="/OTRE/otre_agent.jardesc" useSourceFolders="false" buildIfNeeded="true"/> - <manifest manifestVersion="1.0" usesManifest="true" reuseManifest="false" saveManifest="false" generateManifest="false" manifestLocation="/OTRE/MANIFEST.MF"> - <sealing sealJar="false"> - <packagesToSeal/> - <packagesToUnSeal/> - </sealing> - </manifest> - <selectedElements exportClassFiles="true" exportOutputFolder="false" exportJavaFiles="false"> - <javaElement handleIdentifier="=OTRE/src<org.eclipse.objectteams.otre.jplis{otreAgent.java"/> - </selectedElements> -</jardesc> diff --git a/othersrc/OTRE/otre_min.jardesc b/othersrc/OTRE/otre_min.jardesc deleted file mode 100644 index 9eded8f00..000000000 --- a/othersrc/OTRE/otre_min.jardesc +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<jardesc> - <jar path="org.eclipse.objectteams.otdt/lib/otre_min.jar"/> - <options buildIfNeeded="true" compress="true" descriptionLocation="/OTRE/otre_min.jardesc" exportErrors="false" exportWarnings="true" includeDirectoryEntries="false" overwrite="true" saveDescription="true" storeRefactorings="false" useSourceFolders="false"/> - <storedRefactorings deprecationInfo="true" structuralOnly="false"/> - <selectedProjects/> - <manifest generateManifest="false" manifestLocation="/OTRE/MANIFEST.MF" manifestVersion="1.0" reuseManifest="false" saveManifest="false" usesManifest="true"> - <sealing sealJar="false"> - <packagesToSeal/> - <packagesToUnSeal/> - </sealing> - </manifest> - <selectedElements exportClassFiles="true" exportJavaFiles="false" exportOutputFolder="false"> - <javaElement handleIdentifier="=OTRE/src<org.objectteams"/> - </selectedElements> -</jardesc> diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/BaseCallRedirection.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/BaseCallRedirection.java deleted file mode 100644 index 9766c82bd..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/BaseCallRedirection.java +++ /dev/null @@ -1,1455 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2002-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: BaseCallRedirection.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre; - -import org.apache.bcel.classfile.*; -import org.apache.bcel.generic.*; -import org.apache.bcel.*; - -import java.util.*; - -import org.eclipse.objectteams.otre.util.*; - -/** - * for callin-role-methods with recursive method-calls (base calls) we add a - * method with extendend signature. - * Within the extendend method recursive calls are replaced by the corresponding - * (chaining)base-call.<p> - * For example: - * <pre> - * callin m1() { m1(); } --> - * callin m1(Team _OT$teams[], int _OT$teamIDs[], - * int _OT$idx, int _OT$baseMethTag){ - * liftToRole(b1._OT$m1$chain(Team _OT$teams[], - * int _OT$teamIDs[], - * int _OT$idx, - * int _OT$baseMethTag)); - * } - * </pre> - * - * @version $Id: BaseCallRedirection.java 23408 2010-02-03 18:07:35Z stephan $ - * @author Christine Hundt - * @author Stephan Herrmann - */ -public class BaseCallRedirection extends ObjectTeamsTransformation { - - static class IHPair { - private InstructionHandle _ih1, _ih2; - public IHPair (InstructionHandle ih1, InstructionHandle ih2) { - _ih1 = ih1; - _ih2 = ih2; - } - public InstructionHandle fst() {return _ih1; } - public InstructionHandle snd() {return _ih2; } - } - - public BaseCallRedirection(ClassLoader loader, SharedState state) { - super(loader, state); - } - - /** - * @param ce - * @param cg - */ - public void doTransformInterface(ClassEnhancer ce, ClassGen cg) { - factory = new InstructionFactory(cg); - String class_name = cg.getClassName(); - - if (state.interfaceTransformedClasses.contains(class_name)) { - return; //already transformed! - } - - ConstantPoolGen cpg = cg.getConstantPool(); - checkReadClassAttributes(ce, cg, class_name, cpg); - - if (!CallinBindingManager.isRole(class_name)) { - return; - } - - if (!cg.isInterface()) { - Set<String> boundBaseMethods = CallinBindingManager.getBoundRoleMethods(class_name); - addBaseCallSurrogatesForReplaceBindings(ce, boundBaseMethods, cg); - } - - Method[] methods = cg.getMethods(); - for (int i=0; i<methods.length; i++) { - Method m = methods[i]; - String method_name = m.getName(); - String method_signature = m.getSignature(); - - if (candidateForImplicitActivation(m, cg, cpg)) { // TODO: check the other preconditions, like not abstact etc. - cg.replaceMethod(m, genImplicitActivation(m, class_name, cpg, true)); - } - - if (!isCallin(m, cg)) - continue; - if (logging) printLogMessage(method_name + " in " + class_name - + " IS A CALLIN-METHOD!"); - if (method_name.startsWith(OT_PREFIX)) { - method_name = revertToOriginalName(method_name); - if (logging) printLogMessage("Reverted tsuper name to " + method_name); - } - // code SHOULD contain at least one base call. - if(logging) printLogMessage("----->will add another method " + method_name - + " with enhanced signature"); - -//{SH: retrench signature because otherwise the binding will not be found, -// as a result an empty basecall surrogate will be generated leading to repetetive methods... -// TODO(SH) is this the proper way to retrench?? - String enhancedPrefix = "([Lorg/objectteams/Team;[IIII[Ljava/lang/Object;"; - if (method_signature.startsWith(enhancedPrefix)) - method_signature = "("+method_signature.substring(enhancedPrefix.length()); -// SH} - - boolean roleMethodIsBound = CallinBindingManager.roleMethodHasBinding(class_name, - method_name, - method_signature); - - //if (mbs.isEmpty()) { - if (!roleMethodIsBound) { - if (logging) printLogMessage("callin method " + method_name - + " was not bound in this class!!!"); - } - MethodGen baseCallSurrogate = null; - if (!IS_COMPILER_13X_PLUS) { // since 1.3.0 this part is legacy: - if (!roleMethodIsBound && !methodHasCallinFlags(m, cg, OVERRIDING) && !m.isStatic()) { - // method not bound in current class and doesn't inherit a base call surrogate - baseCallSurrogate = generateEmptyBaseCallSurrogate(cg, m); - } - if (baseCallSurrogate != null) - ce.addMethod(baseCallSurrogate.getMethod(), cg); - } - - } - state.interfaceTransformedClasses.add(class_name); - } - - /** - * Generates an "empty" base call surrogate method, which just throws an 'Error'. - * This method should normaly never be called, but overwritten in a subclass. - * It has to be generated just for the wellformedness of the class file. - * @param cg - * @param m - * @param mbs - * @param baseClassName - * @return - */ - private MethodGen generateEmptyBaseCallSurrogate(ClassGen cg, Method m/*, List mbs*/) { - if (m.getName().startsWith(OT_PREFIX)) - return null; // ot-internal methods don't need this? - - ConstantPoolGen cpg = cg.getConstantPool(); - String class_name = cg.getClassName(); - MethodGen mg = newMethodGen(m, class_name, cpg); - - if (isTSuperWrapper(mg)) { - // tsuper wrapper do not need base call surrogates - return null; - } - - // role method already was enhanced by compiler - Type[] enhancedArgumentTypes = mg.getArgumentTypes(); - if (IS_COMPILER_GREATER_123) { - // add super flag between enhancement and real arguments: - int len = enhancedArgumentTypes.length; - Type[] newArgumentTypes = new Type[len+1]; - System.arraycopy(enhancedArgumentTypes, 0, newArgumentTypes, 0, EXTRA_ARGS); - newArgumentTypes[EXTRA_ARGS] = Type.BOOLEAN; - System.arraycopy(enhancedArgumentTypes, EXTRA_ARGS, newArgumentTypes, EXTRA_ARGS+1, len-EXTRA_ARGS); - enhancedArgumentTypes = newArgumentTypes; - } - Type enhancedReturnType = mg.getReturnType(); - -// {SH: interface method has no argument names? generate dummy names: - String[] argumentNames = new String[enhancedArgumentTypes.length]; - for (int i = 0; i < argumentNames.length; i++) { - argumentNames[i] = "arg"+i; - } - - // role method already was enhanced by compiler: - String[] enhancedArgumentNames = argumentNames; -// } - InstructionList il = new InstructionList(); - //int accessFlags = m.getAccessFlags(); - int accessFlags = Constants.ACC_PROTECTED; // no unanticipated calls possible - -// {SH: interface methods must be public abstract: - if (cg.isInterface()) - accessFlags = Constants.ACC_ABSTRACT|Constants.ACC_PUBLIC; -// } - - MethodGen baseCallSurrogate = new MethodGen(accessFlags, - enhancedReturnType, - enhancedArgumentTypes, - enhancedArgumentNames, - getBaseCallSurrogateName(m.getName(), m.isStatic(), class_name /*genRoleInterfaceName(class_name)*/), - class_name, - il, cpg); -// {SH: no code for interface method: - if (!cg.isInterface()) { - // orig: - if (logging) - printLogMessage("Exception has to be thrown!"); - - createThrowInternalError(cpg, il, new InstructionList(new PUSH(cpg, "Binding-Error: base-call impossible!"))); - - il.append(InstructionFactory.createNull(enhancedReturnType)); - il.append(InstructionFactory.createReturn(enhancedReturnType)); - - if (debugging) - baseCallSurrogate.addLineNumber(il.getStart(), STEP_OVER_LINENUMBER); - } -// } - - il.setPositions(); - baseCallSurrogate.removeNOPs(); - baseCallSurrogate.setMaxStack(); - baseCallSurrogate.setMaxLocals(); - return baseCallSurrogate; - } - - /** - * @param mg - * @return - */ - private static boolean isTSuperWrapper(MethodGen mg) { - Type[] argTypes = mg.getArgumentTypes(); - if (argTypes.length == 0) { - return false; // no tsuper marker interface argument existing - } - String lastArgument = (argTypes[argTypes.length - 1]).toString(); - return lastArgument.contains(OTDT_PREFIX); - } - - /** - * Adds base call surrogate method for all role method bindings in the current role class. - * Thereby method bindings which are defined in super roles are accumulated and - * considered as well. - * @param ce the ClassEnhancer to which the new method has to be added - * @param boundRoleMethods the bound methods of the role class - * @param cg the ClassGen for the role class - */ - private void addBaseCallSurrogatesForReplaceBindings(ClassEnhancer ce, Set<String> boundRoleMethods, ClassGen cg) - { - Iterator<String> it = boundRoleMethods.iterator(); - while (it.hasNext()) { - String nameAndSignature = it.next(); - int dotIndex = nameAndSignature.indexOf('.'); - String methodName = nameAndSignature.substring(0, dotIndex); - String methodSignature = nameAndSignature.substring(dotIndex + 1); - List<MethodBinding> mbs = CallinBindingManager.getBindingsForRoleMethod(cg.getClassName(), - methodName, - methodSignature); - MethodBinding anyMethodBinding = mbs.get(0); - if (!anyMethodBinding.isReplace()) { - continue; - } - mbs.addAll(CallinBindingManager.getInheritedRoleMethodBindings(cg.getClassName(), - methodName, - methodSignature)); - - if (anyMethodBinding.hasStaticRoleMethod()) - continue; // base call surrogates for static methods are generated within the enclosing team class - // TODO: remove this check as soon as static replace method bindings are no longer in 'CallinMethodMappings' - MethodGen baseCallSurrogate = genBaseCallSurrogate(cg, mbs); - ce.addOrReplaceMethod(baseCallSurrogate.getMethod(), cg); - } - } - - /** - * Generates base call surrogate method for the role method for which the method bindings 'mbs' are. - * Thereby a switch-case for each bound base method is generated. - * This method is only for nonstatic role methods. Base call surrogates for static methods - * are generated within the enclosing team class - * @param cg the ClassGen for the role class - * @param mbs the method bindings for one role method - * @param baseClassName the name of the base class - */ - MethodGen genBaseCallSurrogate(ClassGen cg, List<MethodBinding> mbs) { - - //baseClassName would not be needed here, if I could find out the root-base-class-type... - ConstantPoolGen cpg = cg.getConstantPool(); - String class_name = cg.getClassName(); - - MethodBinding anyBindingForRoleMethod = mbs.get(0); - String baseClassName = anyBindingForRoleMethod.getRootBoundBase(); - String roleMethodSignature = anyBindingForRoleMethod.getRoleMethodSignature(); - - Type[] enhancedArgumentTypes; - { - Type[] argTypesTail = Type.getArgumentTypes(roleMethodSignature); - if (IS_COMPILER_GREATER_123) { - // add super flag between enhancement and real arguments: - int len = argTypesTail.length; - System.arraycopy(argTypesTail, 0, argTypesTail=new Type[len+1], 1, len); - argTypesTail[0] = Type.BOOLEAN; - } - enhancedArgumentTypes = enhanceArgumentTypes(argTypesTail); - } - Type enhancedReturnType = generalizeReturnType(Type.getReturnType(roleMethodSignature)); - String methodName = anyBindingForRoleMethod.getRoleMethodName(); - InstructionList il = new InstructionList(); - int accessFlags = Constants.ACC_PROTECTED; - - MethodGen baseCallSurrogate = new MethodGen(accessFlags, - enhancedReturnType, - enhancedArgumentTypes, - null, // no explicit names - getBaseCallSurrogateName(methodName, false, - genRoleInterfaceName(class_name)), - class_name, - il, cpg); - - ObjectType baseClass = new ObjectType(baseClassName); - ObjectType outerClass; - { - String outerClassName = getOuterClassName(class_name); - outerClass = new ObjectType(outerClassName); - } - - LocalVariableGen otResult = null; - - otResult = baseCallSurrogate.addLocalVariable("_OT$result", - enhancedReturnType, null, null); - - il.insert(InstructionFactory.createStore(enhancedReturnType, - otResult.getIndex())); - il.insert(new ACONST_NULL()); - il.setPositions(); // about to retrieve instruction handles. - - if (logging) printLogMessage("base-call switch has to be inserted!"); - InstructionList loading = new InstructionList(); - loading.append(InstructionFactory.createThis()); - int index = 1; - for (int i = 0; i < enhancedArgumentTypes.length; i++) { - loading.append(InstructionFactory.createLoad(enhancedArgumentTypes[i],index)); - index += enhancedArgumentTypes[i].getSize(); - } - - Type[] argumentTypes = Type.getArgumentTypes(roleMethodSignature); - Type returnType = Type.getReturnType(roleMethodSignature); - - if (debugging) { - baseCallSurrogate.addLineNumber(il.getStart(), STEP_OVER_LINENUMBER); - } - - boolean generateSuperAccess = false; - List<SuperMethodDescriptor> superAccesses = IS_COMPILER_GREATER_123 ? CallinBindingManager.getSuperAccesses(baseClassName) : null; - if (superAccesses != null) { - outer: for (SuperMethodDescriptor superMethod : superAccesses) { - for (MethodBinding methodBinding : mbs) { - if ( superMethod.methodName.equals(methodBinding.getBaseMethodName()) - && superMethod.signature.equals(methodBinding.getBaseMethodSignature())) - { - generateSuperAccess = true; - break outer; - } - } - } - } - - BranchInstruction ifSuper = new IFEQ(null); - GotoInstruction skipElse = new GOTO(null); - if (generateSuperAccess) { - // gen: if (isSuperAccess) { _OT$base._OT$m$super(args); } else ... - il.append(InstructionFactory.createLoad(Type.BOOLEAN, EXTRA_ARGS+1)); // last synthetic arg is super-flag - il.append(ifSuper); - il.append(genBaseCallSwitch(cpg, mbs, baseCallSurrogate, - argumentTypes, - outerClass, baseClass, - returnType, - otResult, loading, true)); - il.append(skipElse); - } - InstructionList - basecall = genBaseCallSwitch(cpg, mbs, baseCallSurrogate, - argumentTypes, - outerClass, baseClass, - returnType, - otResult, loading, false); - InstructionHandle callStart = basecall.getStart(); // store handle before append eats the list - il.append(basecall); - if (generateSuperAccess) { - ifSuper.setTarget(callStart); - skipElse.setTarget(il.append(new NOP())); - } - - il.append(InstructionFactory.createLoad(enhancedReturnType, otResult.getIndex())); - il.append(InstructionFactory.createReturn(enhancedReturnType)); - - il.setPositions(); - baseCallSurrogate.removeNOPs(); - baseCallSurrogate.setMaxStack(); - baseCallSurrogate.setMaxLocals(); - return baseCallSurrogate; - } - -/* - Type findBaseFieldType(JavaClass c, ConstantPoolGen cpg) { - Field[] fields = c.getFields(); - for (int l=0; l<fields.length; l++) { - Field f = fields[l]; - if (f.getName().equals(BASE)) { - FieldGen fg = new FieldGen(f, cpg); - return fg.getType(); - } - } - JavaClass superClass = Repository.lookupClass(c.getSuperclassName()); - // BCEL bug: super class of "Object" is "Object": - //System.err.println("Superclass of "+ c.getClassName()+" is " +c.getSuperclassName()); - if (!superClass.getClassName().equals("java.lang.Object")) { - return findBaseFieldType(superClass, cpg); - } - return null; - }*/ - - /** - * Iterate through the instructions of a callin method. - * <ul> - * <li>Adjust local variable instructions due to inserted extra arguments. - * <li>Replace base-calls and calls to activate. - * </ul> - * @param cg - * @param m - * @param mbs List<MethodBinding> - * @return MethodGen - */ - MethodGen replaceBaseCalls(ClassGen cg, Method m, List<MethodBinding> mbs) { - - int indexOffset = m.isStatic() ? -1 : 0; // argument indices are decremented for static methods, - // because of the missing 'this' - - ConstantPoolGen cpg = cg.getConstantPool(); - String class_name = cg.getClassName(); - String method_name = m.getName(); - - MethodGen mg = newMethodGen(m, class_name, cpg); - - Type[] argumentTypes = mg.getArgumentTypes(); - Type returnType = mg.getReturnType(); - - Type[] enhancedArgumentTypes = enhanceArgumentTypes(mg.getArgumentTypes()); -// {SH abstract methods may not have argument names?? - String[] argumentNames; - if (m.isAbstract()) { - argumentNames = new String[argumentTypes.length]; - int index = 0; - for (int i = 0; i < argumentNames.length; i++) { - argumentNames[i] = "arg" + index/* i */; - index += argumentTypes[i].getSize(); - } - -/* -// load regular arguments: - int index = 1; - for (int i=0; i<argTypes.length; i++) { - il.append(InstructionFactory.createLoad(argTypes[i],index)); - index += argTypes[i].getSize(); - } -//*/ - - } else { - argumentNames = mg.getArgumentNames(); - } - String[] enhancedArgumentNames = enhanceArgumentNames(argumentNames); -// orig: String[] enhancedArgumentNames = enhanceArgumentNames(mg.getArgumentNames()); -// SH} - - Type enhancedMethodReturnType = generalizeReturnType(m.getSignature()); - -// {SH instruction list may be null for abstract method -// orig: InstructionList il = mg.getInstructionList().copy(); - InstructionList il = mg.getInstructionList(); - if (il != null) - il = il.copy(); - else - il = new InstructionList(); -// SH} - - MethodGen enhancedMethod = new MethodGen(m.getAccessFlags(), - enhancedMethodReturnType, - enhancedArgumentTypes, - enhancedArgumentNames, - method_name, class_name, - il, cpg); - //not needed??: - // or not?????? - copyLocalVariables(mg, enhancedMethod); - copyLineNumbers(mg, enhancedMethod); - - boolean returnValueAdded = (returnType == Type.VOID) - && (enhancedMethodReturnType != Type.VOID); - - // all exception handlers of this method, which have to be updated later. - CodeExceptionGen [] handlers = copyExceptionHandlers(mg, enhancedMethod, il); - // list of instruction handles (old and new) that are replaced in the sequel - ArrayList<IHPair> replacedInstructions = new ArrayList<IHPair>(); // of IHPair; - // set of instruction handles which signal TargetLostException during delete(). - HashSet<InstructionHandle> targetLost = new HashSet<InstructionHandle>(); // of InstructionHandle - - // create LocalVariable Object _OT$result: - LocalVariableGen otResult = null; - - int slot = mg.getMaxLocals() + EXTRA_ARGS-indexOffset; - otResult = enhancedMethod.addLocalVariable("_OT$result", enhancedMethodReturnType, - slot, null, null); - - // subtract EXTRA_ARGS since this offset will be added again below. - il.insert(InstructionFactory.createStore(enhancedMethodReturnType, - otResult.getIndex() - EXTRA_ARGS)); - - il.insert(new ACONST_NULL()); - il.setPositions(); // about to retrieve instruction handles. - - InstructionHandle[] ihs = il.getInstructionHandles(); - //printLogMessage("every call of base." + method_name + "(...) will be replaced by " - // + liftMethodName + BASE + "."+baseChainMethodName+"(...))"); - - int actInstruction = 0; - int offset = EXTRA_ARGS; - while (actInstruction < ihs.length) { - Instruction act_instruction = ihs[actInstruction].getInstruction(); -/****************************** variable index adaption: **********************************/ - if(act_instruction instanceof LocalVariableInstruction) { - // add offset to the index of every variable load or store instruction, - // because of the inserted EXTRA_ARGS arguments: - LocalVariableInstruction localVariableInstruction = (LocalVariableInstruction) act_instruction; - if (localVariableInstruction.getIndex() != 0 || (enhancedMethod.isStatic())) { // 'this' stays at index 0 - if (localVariableInstruction instanceof StoreInstruction) { - localVariableInstruction = - InstructionFactory.createStore(localVariableInstruction.getType(cpg), - offset+localVariableInstruction.getIndex()); - } else if (localVariableInstruction instanceof LoadInstruction) { - localVariableInstruction = - InstructionFactory.createLoad(localVariableInstruction.getType(cpg), - offset+localVariableInstruction.getIndex()); - } else if (localVariableInstruction instanceof IINC) { - localVariableInstruction.setIndex(offset+localVariableInstruction.getIndex()); - // TODO: check, if this is enough for all kinds of LocalVariableInstructions - // and if there are more instructions which use variable indizes!! - } - ihs[actInstruction].setInstruction(localVariableInstruction); - } - } else if (act_instruction instanceof RET) { - RET ret = (RET)act_instruction; - if (ret.getIndex() != 0) - ihs[actInstruction].setInstruction(new RET(offset + ret.getIndex())); - -/*************************** "super"- & "tsuper"-call enhancement: **********************************/ - } else if (super_or_tsuper_instruction(act_instruction, method_name, cpg) ) { - - InvokeInstruction ii = (InvokeInstruction)act_instruction; - InstructionHandle next = ihs[actInstruction+1]; - InstructionList changedArea; - InstructionHandle[] delim = new InstructionHandle[2]; - int stackDepth = computeArgumentStackDepth(cpg, ii); - InstructionList loading = pruneLoading(il, ihs, actInstruction, - stackDepth, cpg, - targetLost, delim, true); - if (loading == null) { - actInstruction++; - continue; - } - - changedArea = genEnhancedSuperCall(cpg, ii, enhancedMethod, loading); - if (returnValueAdded) { - changedArea.append(InstructionFactory.createStore( - enhancedMethodReturnType, otResult.getIndex())); - } else { - InstructionHandle ih = adjustValue(changedArea, changedArea.getEnd(), enhancedMethodReturnType, returnType); - if (debugging && ih != null) - mg.addLineNumber(ih, STEP_OVER_LINENUMBER); - } - replacedInstructions.add(new IHPair(delim[0], changedArea.getStart())); - replacedInstructions.add(new IHPair(delim[1], changedArea.getEnd())); - - il.insert(next, changedArea); - actInstruction++; - continue; - -/*************************** "activate" substitution and base-call generation: ************/ - //} else if (act_instruction instanceof INVOKEVIRTUAL) { - // INVOKEVIRTUAL iv = (INVOKEVIRTUAL)act_instruction; - } else if (act_instruction instanceof InvokeInstruction) { - InvokeInstruction iv = (InvokeInstruction)act_instruction; - String iv_name = iv.getName(cpg); - - // FIXME(SH): is this still needed? - // - activate is commented-out, - // - base call is now generated by the compiler. - if(!(iv_name.equals(method_name) || - iv_name.equals("activate"))) - { - actInstruction++; - continue; - } - InstructionHandle next = ihs[actInstruction+1]; - InstructionList changedArea; - InstructionHandle[] delim = new InstructionHandle[2]; - /* - if (iv_name.equals("activate")) { - // blank original invokevirtual: - ihs[actInstruction].setInstruction(new NOP()); - Type [] ivArgTypes = iv.getArgumentTypes(cpg); - int activateArgCount = ivArgTypes.length; - InstructionList loading = null; - if (activateArgCount == 1) - loading = pruneLoading (il, ihs, actInstruction, - ivArgTypes[0].getSize(), cpg, - targetLost, delim, false); - changedArea = enhanceActivateCall(factory, cpg, loading, iv); - if (activateArgCount == 1) { - replacedInstructions.add(new IHPair(delim[0], - changedArea.getStart())); - replacedInstructions.add(new IHPair(delim[1], - changedArea.getEnd())); - } - } else*/ { // base call: - int stackDepth = computeArgumentStackDepth(cpg, iv); - boolean deleteThis = true; - - if(enhancedMethod.isStatic()) - deleteThis = false; - - /* - if (iv.getOpcode()==Constants.INVOKESTATIC) - deleteThis = false; - */ - InstructionList loading = pruneLoading(il, ihs, actInstruction, - stackDepth, cpg, - targetLost, delim, /*true*/deleteThis); - //System.err.println(loading); - if (loading == null) { - actInstruction++; - continue; - } - - // insert call of base-call surrogate method: - String roleInterfaceName = genRoleInterfaceName(cg.getClassName()); - - String calleeClassName = null; - if(m.isStatic()) { - calleeClassName = extractTeamName(roleInterfaceName); - } - changedArea = genBaseCallSurrogateCall(cpg, iv, enhancedMethod, loading, extractRoleName(roleInterfaceName), calleeClassName); - - if (returnValueAdded) { - changedArea.append(InstructionFactory.createStore(enhancedMethodReturnType, - otResult.getIndex())); - } else { - InstructionHandle ih = adjustValue(changedArea, changedArea.getEnd(), enhancedMethodReturnType, returnType); - if (debugging && ih != null) - mg.addLineNumber(ih, STEP_OVER_LINENUMBER); - } - replacedInstructions.add(new IHPair(delim[0], changedArea.getStart())); - replacedInstructions.add(new IHPair(delim[1], changedArea.getEnd())); - - } // if (activate or base call) - - il.insert(next, changedArea); - - -/*************************** "return" enhancements: ************/ - } else if (act_instruction instanceof ReturnInstruction) { - // replace return statement by result preparation and a new return statement - // construct back to front, to keep the insertion position! - InstructionHandle oldReturn = ihs[actInstruction]; - InstructionHandle replacedPos = oldReturn; - il.append(oldReturn, InstructionFactory.createReturn(enhancedMethodReturnType)); - if (returnValueAdded) { - // load ot_result: - oldReturn.setInstruction(InstructionFactory.createLoad(enhancedMethodReturnType, - otResult.getIndex())); - } else { - oldReturn.setInstruction(new NOP()); - replacedPos = - adjustValue(il, oldReturn, returnType, enhancedMethodReturnType); - if (debugging && replacedPos != null) - mg.addLineNumber(replacedPos, STEP_OVER_LINENUMBER); - } - if (replacedPos != null) - replacedInstructions.add(new IHPair(oldReturn, replacedPos)); - } // conditional over instruction types - actInstruction++; - } //end while - - // tidy: - checkUpdate(handlers, replacedInstructions, targetLost); - enhancedMethod.removeNOPs(); - il.setPositions(); - enhancedMethod.setMaxStack(); - enhancedMethod.setMaxLocals(); - - return enhancedMethod; - } - - /** - * Given an invokevirtual compute the space its arguments use on the stack. - * @param cpg - * @param iv - * @return int stack size. - */ - static int computeArgumentStackDepth(ConstantPoolGen cpg, InvokeInstruction ii) { - Type [] iiargs = ii.getArgumentTypes(cpg); - int depth=0; - for (int i=0; i<iiargs.length; i++) - depth += iiargs[i].getSize(); - return depth; - } - - /** - * Copy all local variables from <tt>src</tt> to <tt>dest</tt>. - * While doing so, increment their index by EXTRA_ARGS. - */ - static void copyLocalVariables(MethodGen src, MethodGen dest) { - Type[] argumentTypes = src.getArgumentTypes(); - LocalVariableGen[] lvgs = src.getLocalVariables(); - for (int l=argumentTypes.length; l<lvgs.length; l++) { - LocalVariableGen lvg = lvgs[l]; - if (lvg.getIndex() > 0) { - dest.addLocalVariable(lvg.getName(), - lvg.getType(), - lvg.getIndex()+(EXTRA_ARGS+1), // +1????? - null, null); - //System.err.println("adding:" +src.getClassName() +" "+src.getName()+" "+lvg.getName() +" " + lvg.getType() +" "+ (lvg.getIndex()+(EXTRA_ARGS+1))); - } - } - } - /** Copy all line numbers from <tt>src</tt> to <tt>dest</tt>. */ - static void copyLineNumbers(MethodGen src, MethodGen dest) { - InstructionList il_dest = dest.getInstructionList(); - il_dest.setPositions(); - LineNumberGen[] src_lng = src.getLineNumbers(); - for (int i=0; i<src_lng.length; i++) { - int position = src_lng[i].getInstruction().getPosition(); - InstructionHandle ih = il_dest.findHandle(position); - dest.addLineNumber(ih, src_lng[i].getSourceLine()); - } - } - /** - * Prune a invokevirtual portion from a given instruction list. - * Note, that arguments don't include 'this', which is not pruned but blanked - * (need to keep as possible jump target). - * @param il the source list - * @param ihs array of handles of this list - * @param idx points to a invokevirtual that shall be removed - * @param stackDepth size of the called method's arguments on the stack. - * This is how deep we need to cut into the stack. - * @param cpg - * @param targetLost set of lost InstructionHandles to be filled - * @param delim array of two handles, which should be filled with start and end of - * the pruned region. - * @param blankThis should the 'this' call target be overwritten? - * @return InstructionList a copy of the original value loading. - */ - static InstructionList pruneLoading (InstructionList il, InstructionHandle[] ihs, int idx, - int stackDepth, ConstantPoolGen cpg, - HashSet<InstructionHandle> targetLost, InstructionHandle[] delim, - boolean blankThis) - { - InstructionList nlist = new InstructionList(); - InstructionHandle start = ihs[idx]; - InstructionHandle end = ihs[idx--]; - while (stackDepth > 0) { - start = ihs[idx--]; - Instruction instr = start.getInstruction(); - stackDepth -= stackDiff(instr, cpg); - nlist.insert(instr); - } - if (blankThis) { - if (!isALoad0(ihs[idx].getInstruction())) - return null; - ihs[idx].setInstruction(new NOP()); // keep as jump target but delete 'this' - } - delim[0] = start; - delim[1] = end; - safeDelete(il, start, end, targetLost); - return nlist; - } - - static boolean isALoad0(Instruction i) { - if (!(i instanceof ALOAD)) return false; - return ((ALOAD)i).getIndex() == 0; - } - - /** Get the lenght of the longest base method signature in mbs. - * @param mbs List of {@link MethodBinding MethodBinding} - */ -// static int getMaxBaseArgLen (List mbs) { -// int max=0; -// Iterator it = mbs.iterator(); -// while (it.hasNext()) { -// MethodBinding mb = (MethodBinding)it.next(); -// String sign = mb.getBaseMethodSignature(); -// int len = Type.getArgumentTypes(sign).length; -// if (len>max) max = len; -// } -// return max; -// } - - /** - * Generate a dispatching switch statement which calls the proper base method. - * @param cpg - * @param mbs list of MethodBinding that applies to this callin method - * @param enhancedMethod the enhanced callin method - * @param roleArgumentTypes arg types of the callin method - * @param outerClass the Team - * @param baseClass the base bound to this role - * @param returnType the return type of the original callin method - * @param otResult the local variable storing the base call result - * @param loading an instruction list holding the original instructions for - * loading parameters - * @return InstructionList the complete replacement implementing the base call. - */ - InstructionList genBaseCallSwitch (ConstantPoolGen cpg, - List<MethodBinding> mbs, MethodGen enhancedMethod, - Type[] roleArgumentTypes, - ObjectType outerClass, ObjectType baseClass, - Type returnType, LocalVariableGen otResult, - InstructionList loading, - boolean isSuperAccess) - { - - String className = enhancedMethod.getClassName(); - Type enhancedMethodReturnType = enhancedMethod.getReturnType(); - boolean callinHasReturnValue = returnType != Type.VOID; - - InstructionList il = new InstructionList(); - - // Setup a variable which holds the result of this base call. - // This variabel is local to this segment of code and used only - // to transport this result out off the switch statement. - int localResult = -1; - LocalVariableGen lg = null; - if (callinHasReturnValue) { - lg = enhancedMethod.addLocalVariable("_OT$tmpResult", returnType, - null, null); - localResult = lg.getIndex(); - il.append(InstructionFactory.createNull (returnType)); - il.append(InstructionFactory.createStore(returnType, localResult)); - } - - // ---- Prepare the switch: ---- - InstructionHandle switchStart = il.append - (InstructionFactory.createLoad(Type.INT, BASE_METH_ARG)); - // generated: _OT$baseMethTag - - removeDuplicatedBaseMethodTags(mbs); - - // one break for each case clause - int numberOfCases = mbs.size(); - GOTO[] breaks = new GOTO[numberOfCases]; - for (int i=0; i<numberOfCases; i++) - breaks[i] = new GOTO(null); - - int[] matches = new int[numberOfCases]; - InstructionHandle[] targets = new InstructionHandle[numberOfCases]; - int caseCounter = 0; - - Iterator<MethodBinding> it = mbs.iterator(); - while (it.hasNext()) { - - MethodBinding mb = it.next(); - - String wrapperName = mb.getWrapperName(); - int[] paramPositions = CallinBindingManager.getParamPositions(outerClass.getClassName(), - wrapperName); - if (logging) printLogMessage("param pos(" + wrapperName + ")=" + paramPositions); - - matches[caseCounter] = CallinBindingManager.getBaseCallTag(mb.getBaseClassName(), - mb.getBaseMethodName(), - mb.getBaseMethodSignature()); - InstructionHandle nextBranch = il.append(new NOP()); - - short invocationKind = isSuperAccess - ? Constants.INVOKESTATIC - : Constants.INVOKEVIRTUAL; - - String boundBaseClassName = mb.getBaseClassName(); - if (boundBaseClassName.indexOf(OTDT_PREFIX) != -1) { - // if base is a role class, switch now to the interface part to support base-side implicit inheritance: - boundBaseClassName = ObjectTeamsTransformation.genRoleInterfaceName(boundBaseClassName); - invocationKind = Constants.INVOKEINTERFACE; - } - String baseMethodName = mb.getBaseMethodName(); - String baseMethodSignature = mb.getBaseMethodSignature(); - Type[] baseMethodArgumentTypes = Type.getArgumentTypes(baseMethodSignature); - Type baseMethodReturnType = Type.getReturnType (baseMethodSignature); - - String baseChainMethodName; - Type baseChainReturnType; - Type[] enhancedBaseArgumentTypes; - if (isSuperAccess) { - baseChainMethodName = OT_PREFIX+baseMethodName+"$super"; - baseChainReturnType = returnType; - // base arguments are un-enhanced but have a leading base instance: - int len = baseMethodArgumentTypes.length; - System.arraycopy(baseMethodArgumentTypes, 0, enhancedBaseArgumentTypes=new Type[len+1], 1, len); - enhancedBaseArgumentTypes[0] = baseClass; - } else { - baseChainMethodName = genChainMethName(baseMethodName); - baseChainReturnType = object; // ALWAYS - enhancedBaseArgumentTypes = enhanceArgumentTypes(baseMethodArgumentTypes); - } - - // --- call target: --- - - // if base class type is a role type _OT$base field has role interface type: - { - String baseClassName = baseClass.toString(); - if (baseClassName.indexOf(OTDT_PREFIX) != -1) { - baseClass = new ObjectType(ObjectTeamsTransformation.genRoleInterfaceName(baseClassName)); - if(logging) printLogMessage(baseClassName + " --> " + ObjectTeamsTransformation.genRoleInterfaceName(baseClassName)); - } - } - - // load '_OT$base' field: - InstructionHandle baseCallLine = il.append(InstructionFactory.createThis()); - il.append(factory.createFieldAccess(className, BASE, baseClass, Constants.GETFIELD)); - - if (!baseClass.getClassName().equals(boundBaseClassName)) { - // playedBy has been refined in the sub role; - // create a cast to the sub base class: - il.append(factory.createCast(baseClass, new ObjectType(boundBaseClassName))); - } - - // --- load arguments of the new method: --- - // (letters refer to document parameter-passing.odg) - - // (u) generate extra arguments (indices are equal at role and base): - if (!isSuperAccess) - for (int idx = 0; idx < EXTRA_ARGS; idx++) - il.append(InstructionFactory.createLoad(enhancedMethod.getArgumentTypes()[idx], - idx+1/*translating non-static*/)); - - // (v)(w)(x) split loading sequence and transfer source-level arguments - // (includes reverse-application of parameter mappings): - - // Start at EXTRA_ARGS, because one set of enhancement has already been loaded, - // except when doing super access which only has one extra arg: base instance. - int start = isSuperAccess ? 1 : EXTRA_ARGS; - il.append(translateLoads(splitLoading(cpg, - loading.copy(), - roleArgumentTypes), - enhancedMethod.getArgumentTypes(), - enhancedBaseArgumentTypes, - paramPositions, - extractTeamName(enhancedMethod.getClassName()), - className, - new BaseMethodInfo(mb.baseMethodIsCallin(), false/*static*/, mb.getTranslationFlags()), - start, - cpg)); - // --- done loading --- - - // invoke the chaining method of the base class (base-call!): - il.append(factory.createInvoke(boundBaseClassName, - baseChainMethodName, - baseChainReturnType, - enhancedBaseArgumentTypes, - invocationKind - )); - - boolean resultLiftingNecessary = ((mb.getTranslationFlags()&1)!=0); - - if (resultLiftingNecessary) { // call the static lift-method: - // STATIC_PARTS_OK: in role: lift method call -//TODO: lift method args! - String liftMethodName = mb.getLiftMethodName(); - Type liftMethodReturnType = Type.getReturnType(mb.getLiftMethodSignature()); - Type[] liftMethodArgs = Type.getArgumentTypes(mb.getLiftMethodSignature()); - - il.append(factory.createCast(baseChainReturnType, baseMethodReturnType)); - il.append(InstructionFactory.createThis()); - - int nestingDepth = countOccurrences(className, '$') -1; - il.append(factory.createGetField(className, "this$" + nestingDepth, outerClass )); - - il.append(new SWAP()); // -> .., this$0, (BaseType)result - //il.append(new ICONST(LIFT_ARG_RES)); - - il.append(factory.createInvoke(outerClass.getClassName(), - liftMethodName, - liftMethodReturnType, - liftMethodArgs, - Constants.INVOKEVIRTUAL)); - } - - InstructionHandle afterBaseCallLine = il.append(new NOP()); - - if (baseChainReturnType != Type.VOID) { - // adjust the return value to the type expected by the WRAPPER: - il.append(new DUP()); // keep for adjustment below - if (!resultLiftingNecessary) - adjustValue(il, null, baseChainReturnType, enhancedMethodReturnType); - il.append(InstructionFactory.createStore(enhancedMethodReturnType, - otResult.getIndex())); // store "globally" - // this store is needed to tunnel unused results through the callin. - - // adjust the return value to the type expected by the ORIGINAL CALLIN: - adjustValue(il, null, baseChainReturnType, returnType); - if (callinHasReturnValue) - il.append(InstructionFactory.createStore(returnType, localResult)); // store "locally" - // this store is useful for callins which make use of the result. - } - - targets[caseCounter] = nextBranch; - il.append(breaks[caseCounter]); - // generated: break; - - caseCounter++; - - if (debugging) { - enhancedMethod.addLineNumber(baseCallLine, STEP_INTO_LINENUMBER); - enhancedMethod.addLineNumber(afterBaseCallLine, STEP_OVER_LINENUMBER); - } - } - // Default case: throw an exception reporting the situation: - // create: String msg = ("Unhandled base-call case!"+base_method_tag) - InstructionList messagePush = new InstructionList(); - messagePush.append(factory.createNew(OTConstants.STRING_BUFFER_NAME)); - messagePush.append(new DUP()); - messagePush.append(factory.createInvoke(OTConstants.STRING_BUFFER_NAME, Constants.CONSTRUCTOR_NAME, Type.VOID, new Type[0], Constants.INVOKESPECIAL)); - messagePush.append(new PUSH(cpg, "Unhandled base-call case: ")); - messagePush.append(factory.createInvoke(OTConstants.STRING_BUFFER_NAME, "append", Type.STRINGBUFFER, new Type[]{Type.STRING}, Constants.INVOKEVIRTUAL)); - messagePush.append(InstructionFactory.createLoad(Type.INT, BASE_METH_ARG)); - messagePush.append(factory.createInvoke(OTConstants.STRING_BUFFER_NAME, "append", Type.STRINGBUFFER, new Type[]{Type.INT}, Constants.INVOKEVIRTUAL)); - messagePush.append(factory.createInvoke(OTConstants.STRING_BUFFER_NAME, "toString", Type.STRING, new Type[0], Constants.INVOKEVIRTUAL)); - // create: throw new OTREInternalError(msg) - InstructionHandle defaultCase = createThrowInternalError(cpg, il, messagePush); - - InstructionHandle afterSwitch = il.append(new NOP()); // all breaks point here. - - il.append(switchStart, createLookupSwitch(matches, targets, breaks, - defaultCase, afterSwitch)); - - // retrieve locally stored result: - if (callinHasReturnValue) { - il.append(InstructionFactory.createLoad(returnType, localResult)); - lg.setStart(il.getStart()); // restrict local variable to this segment. - lg.setEnd(il.getEnd()); - } - - return il; - } - - /** - * Removes duplicated method bindings with the same base call tag from the list, to avoid duplicated - * cases in the base call surrogate-switch. - * @param mbs - */ - private static void removeDuplicatedBaseMethodTags(List<MethodBinding> mbs) { - if (mbs.size() < 2) // nothing to remove - return; - - MethodBinding[] mbArray = mbs.toArray(new MethodBinding[mbs.size()]); - - Comparator<MethodBinding> baseCallTagComparator = new Comparator<MethodBinding>() { - public int compare(MethodBinding firstMB, MethodBinding secondMB) { - int firstBaseTag = CallinBindingManager.getBaseCallTag(firstMB.getBaseClassName(), - firstMB.getBaseMethodName(), - firstMB.getBaseMethodSignature()); - int secondBaseTag = CallinBindingManager.getBaseCallTag(secondMB.getBaseClassName(), - secondMB.getBaseMethodName(), - secondMB.getBaseMethodSignature()); - - if (firstBaseTag < secondBaseTag) - return -1; - if (firstBaseTag > secondBaseTag) - return 1; - return 0; - } - }; - Arrays.sort(mbArray, baseCallTagComparator); - for (int i = 0; i + 1 < mbArray.length; i++) { - if (baseCallTagComparator.compare(mbArray[i], mbArray[i + 1]) == 0) { - mbs.remove(mbArray[i + 1]); - } - } - } - - - /** - * @param className - * @return - */ - private static String extractTeamName(String roleClassName) { - int lastDollarIndex = roleClassName.lastIndexOf('$'); - return roleClassName.substring(0, lastDollarIndex); - } - - /** - * @param className - * @return - */ - private static String extractRoleName(String roleClassName) { - int lastDollarIndex = roleClassName.lastIndexOf('$'); - return roleClassName.substring(lastDollarIndex+1, roleClassName.length()); - } - - /** - * FIXME(SH): obsolete! - * @param baseMethodReturnType - * @param returnType - * @return - */ -// private static boolean returnTypeCompatible(Type from, Type to) { -// System.out.println("test for " + from + "->" + to); -// if (from.equals(to)) -// return true; -// if (from instanceof ObjectType && to instanceof ObjectType) {// how to handle compatible basic types?? -// ObjectType otFrom = (ObjectType) from; -// ObjectType otTo = (ObjectType) to; -// if (otFrom.subclassOf(otTo)) -// return true; -// } -// return false; -// } - - /** - * Copy all exception handlers of a method. - * @param source the method from where to copy - * @param dest the method where to copy to - * @param il instructions of `dest' which must still have the same positions - * as the instructions in `source'. - * @return an array of handler generators, which still has to be maintained, - * whenever instructions are replaced in the methods instruction list. - */ - static CodeExceptionGen[] copyExceptionHandlers(MethodGen source, - MethodGen dest, - InstructionList il) { - il.setPositions(); // needed to retrieve handles by position. - CodeExceptionGen[] excGens = source.getExceptionHandlers(); - CodeExceptionGen[] newGens = new CodeExceptionGen[excGens.length]; - if ((excGens != null) && excGens.length > 0) { - for (int hcount=0; hcount<excGens.length; hcount++) { - CodeExceptionGen excGen = excGens[hcount]; - InstructionHandle excStart = il.findHandle(excGen.getStartPC().getPosition()); - InstructionHandle excEnd = il.findHandle(excGen.getEndPC().getPosition()); - InstructionHandle excHandler = il.findHandle(excGen.getHandlerPC().getPosition()); - ObjectType catchType = excGen.getCatchType(); - newGens[hcount] = - dest.addExceptionHandler(excStart, excEnd, excHandler, catchType); - } - } - return newGens; - } - - /** - * Update the positions of all exception handlers. - * @param handlers the handlers of this method. - * @param replaced a pair of InstructionHandles, the first is replaced by the second. - */ - static void updateHandlers (CodeExceptionGen[] handlers, IHPair replaced) { - InstructionHandle old = replaced.fst(); - InstructionHandle neu = replaced.snd(); - for (int i=0; i<handlers.length; i++) { - // System.out.println("handler "+handlers[i]); - if (handlers[i].containsTarget(old) && (old != neu)) { - // System.out.println("update "+old+"->"+neu); - handlers[i].updateTarget(old, neu); - } - } - } - - /** - * Delete a range of instructions, whithout throwing TargetLostException. - * @param il the list to delete from - * @param start handle to first instruction to delete. - * @param end handle to last instruction to delete. - * @param collect a set of InstructionHandle which are still targeted. - */ - static void safeDelete(InstructionList il, - InstructionHandle start, InstructionHandle end, - HashSet<InstructionHandle> collect) - { - try { - il.delete(start, end); - } catch(TargetLostException e) { - // System.out.print("Loosing:"+e+" "); - InstructionHandle [] targets = e.getTargets(); - for (int tcount = 0; tcount < targets.length; tcount++) { - collect.add(targets[tcount]); - // System.out.println(targets[tcount]+"!!"); - } - } - } - - /** - * Update all exceptions handlers with respect to all instructions that were replaced. - * Check that this covers all instruction handles in 'lost'. - * @param handles the exception handlers of this method. - * @param replacedList list of IHPairs describing what has been modified. - * @param lost set of instruction handles that were still referred to when - * they were deleted. All these handles should be updated. - */ - static void checkUpdate(CodeExceptionGen[] handlers, ArrayList<IHPair> replacedList, HashSet<InstructionHandle> lost) { - // System.out.println("Update "+replacedList+"/"+lost); - Iterator<IHPair> iter = replacedList.iterator(); - while (iter.hasNext()) { - IHPair replaced = iter.next(); - updateHandlers(handlers, replaced); - lost.remove(replaced.fst()); - } - if (!lost.isEmpty()) { - System.err.println("Warning: "+lost.size()+" target(s) lost: "); - Iterator<InstructionHandle> it = lost.iterator(); - while (it.hasNext()) - System.out.println(it.next()); - } - } - - /** - * While adding extra args to an activate call: - * <ul> - * <li>Check whether an activationLevel was passed (single argument) - * <li>if so, insert the loading sequence for that expression. - * <li>also the return differs (void or int), should however be - * consistent between plain and enhanced version. - * <li>decrement "idx" so this team is the currently active in the chain. - * </ul> - * @param factory - * @param cpg - * @param loading sequence, which loads "level" argument, else null. - * @param iv the invokevirtual for "activate", used to inspect the - * original signature. - * @return the full sequence for loading the arguments, but not the - * call target (because that's the enclosing team and is kept - * unmodified in the original instruction list). - */ -// static InstructionList enhanceActivateCall (final InstructionFactory factory, -// ConstantPoolGen cpg, -// InstructionList loading, -// INVOKEVIRTUAL iv) { -// InstructionList changedArea = new InstructionList(); -// -// // load arguments of the new method: -// int index = 1; -// Type[] enhancedArgumentTypes = enhanceArgumentTypes(iv.getArgumentTypes(cpg), -// 0, false, false); -// Type returnType = Type.VOID; -// int kount = enhancedArgumentTypes.length; -// if (iv.getArgumentTypes(cpg).length == 1) { -// kount--; // "level" loaded separately via 'loading' -// returnType = Type.INT; -// } -// -// for (int k=0; k<kount; k++) { -// changedArea.append(InstructionFactory.createLoad(enhancedArgumentTypes[k], index)); -// index += enhancedArgumentTypes[k].getSize(); -// } -// if (loading != null) -// changedArea.append(loading); -// -// // invoke the overloaded activate method: -// changedArea.append(factory.createInvoke("org.objectteams.Team", -// "activate", -// returnType, -// enhancedArgumentTypes, -// Constants.INVOKEVIRTUAL)); -// -// // generate: idx--; -// changedArea.append(InstructionFactory.createLoad(Type.INT, IDX_ARG)); -// changedArea.append(new ICONST(1)); -// changedArea.append(new ISUB()); -// changedArea.append(InstructionFactory.createStore(Type.INT, IDX_ARG)); -// -// return changedArea; -// } - - /** - * Generates the instructions to call the enhanced version of the 'super' respectively 'tsuper' - * call in a role method. - * @param cpg the constant pool - * @param ii the original invoke instruction - * @param enhancedMethod the enhanced role method - * @param loading the originally loaded arguments - * @return the instruction list containing the method call ingredients - */ - @SuppressWarnings("deprecation") // ii.getClassName() is deprecated - InstructionList genEnhancedSuperCall(ConstantPoolGen cpg, InvokeInstruction ii, - MethodGen enhancedMethod, InstructionList loading) - { - Type returnType = enhancedMethod.getReturnType(); - //Type[] argTypes = enhancedMethod.getArgumentTypes(); - Type[] argTypes = enhanceArgumentTypes(ii.getArgumentTypes(cpg)); - InstructionList il = new InstructionList(); - - il.append(InstructionFactory.createThis()); - // load all additional arguments of the enhanced method (first EXTRA_ARGS): - int index = 1; - for (int i=0; i<EXTRA_ARGS; i++) { - il.append(InstructionFactory.createLoad(argTypes[i],index)); - index += argTypes[i].getSize(); - } - // load arguments of the originally call: - il.append(loading); - - // call super.<enhancedMethod>: - short kind=0; - if (ii instanceof INVOKESPECIAL) - kind = Constants.INVOKESPECIAL; - else - kind = Constants.INVOKEVIRTUAL; - - il.append(factory.createInvoke(ii.getClassName(cpg), // deprecated but we're safe because we have not array here (super/tsuper call) - ii.getMethodName(cpg), - returnType, - argTypes, - kind)); - return il; - } - - /** - * Generates the instructions to call the base call surrogate method. - * @param cpg the constant pool - * @param iv the original invoke instruction - * @param enhancedMethod the enhanced role method - * @param loading the originally loaded arguments - * @return the instruction list containing the method call ingredients - */ - @SuppressWarnings("deprecation") // iv.getClassName is deprecated - InstructionList genBaseCallSurrogateCall(ConstantPoolGen cpg, InvokeInstruction/*INVOKEVIRTUAL*/ iv, - MethodGen enhancedMethod, InstructionList loading, - String roleClassName, String calleeClassName) //JU: added String roleClassName and teamClassName to the method signature - { - int indexOffset = enhancedMethod.isStatic()?-1:0; // argument indexes are decremented for static methods, - // because of the missing 'this' - // for static methods callee is 'null' -> substitute by current class (JU) - if(calleeClassName == null) { - calleeClassName = iv.getClassName(cpg); // deprecated but we're safe because we have not array here (activate() call) - } - - Type returnType = enhancedMethod.getReturnType(); - //Type[] argTypes = enhancedMethod.getArgumentTypes(); - Type[] argTypes = enhanceArgumentTypes(iv.getArgumentTypes(cpg)); - InstructionList il = new InstructionList(); - - String methodName = getBaseCallSurrogateName(enhancedMethod.getName(), - enhancedMethod.isStatic(), - roleClassName); - short invokeKind; - - if (!enhancedMethod.isStatic()) { - il.append(InstructionFactory.createThis()); - invokeKind = Constants.INVOKEVIRTUAL; - - } else { // role method is static: - invokeKind = Constants.INVOKESTATIC; - } - - // load all additional arguments of the enhanced method (first EXTRA_ARGS): - int index = 1; - for (int i = 0; i < argTypes.length; i++) { - if(i < EXTRA_ARGS){ // skip original arguments - il.append(InstructionFactory.createLoad(argTypes[i], index+indexOffset)); - } - //calculate the next index - index += argTypes[i].getSize(); - } - // load arguments of the originally call: - il.append(loading); - - // call _OT$<enhancedMethod>$base(): - il.append(factory.createInvoke(calleeClassName, - methodName, - returnType, - argTypes, - invokeKind/*Constants.INVOKEVIRTUAL*/)); - return il; - } - - - /** - * Checks, if a given instuction is a super or a tsuper call - * @param instr the instruction to check - * @param method_name the name of the method from wich the 'inst' came - * @param cpg the constant pool - * @return true, if 'inst' is a super or tsuper call - */ - private static boolean super_or_tsuper_instruction(Instruction instr, String method_name, ConstantPoolGen cpg) { - if (isTSuperCall(instr, method_name, cpg)) - return true; - if (isSuperCall(instr, method_name, cpg)) - return true; - return false; - } - - private static boolean isTSuperCall(Instruction instr, String method_name, ConstantPoolGen cpg) { - if (instr instanceof INVOKEVIRTUAL) { - INVOKEVIRTUAL iv = (INVOKEVIRTUAL)instr; - String iv_name = iv.getName(cpg); - Type[] argTypes = iv.getArgumentTypes(cpg); - if (argTypes.length<1) // no tsuper marker interface parameter! - return false; - String lastArgument = (argTypes[argTypes.length-1]).toString(); - if (iv_name.equals(method_name) && (lastArgument.indexOf(TSUPER_PREFIX)!=-1)) { - // if iv == <method_name>(..., TSuper__OT__<SuperTeamName>) --> - if(logging) printLogMessage("tsuper-call to " + iv_name + " has to be enhanced!"); - return true; - } - } - return false; - } - - private static boolean isSuperCall(Instruction instr, String method_name, ConstantPoolGen cpg) { - if (instr instanceof INVOKESPECIAL) { - INVOKESPECIAL is = (INVOKESPECIAL)instr; - String is_name = is.getName(cpg); - - if(is_name.equals(method_name)) { - if(logging) printLogMessage("super-call to " + is_name + " has to be enhanced!"); - return true; - } - } - return false; - } - - /** - * Generates the base call surrogate name for a given method name. - * @param method_name the name of the role method - * @param staticFlag - * @param roleClassName the name of the role method - * @return the base call surrogate name - */ - private static String getBaseCallSurrogateName(String method_name, boolean staticFlag, String roleClassName) { - //JU: for static methods the role class name should be inserted - if(staticFlag) { - return OT_PREFIX+roleClassName+"$"+method_name+"$base"; - } - return OT_PREFIX+method_name+"$base"; - } - - /** - * Reverts a method name to its original by returning the substring after the last '$' - * until the end. - * @param method_name method name to be adjusted - * @return the original method name - */ - private static String revertToOriginalName(String method_name) { - int p = method_name.lastIndexOf('$'); - return method_name.substring(p + 1); - } - -/* - * (non-Javadoc) - * - * @see org.eclipse.objectteams.otre.common.ObjectTeamsTransformation#doTransformCode(org.apache.bcel.generic.ClassGen) - */ - public void doTransformCode(ClassGen cg) { - // nothing to do - } -} diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/BaseMethodTransformation.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/BaseMethodTransformation.java deleted file mode 100644 index d6f4aba6f..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/BaseMethodTransformation.java +++ /dev/null @@ -1,1907 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2002-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: BaseMethodTransformation.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre; - -import static org.eclipse.objectteams.otre.StaticSliceBaseTransformation._OT_ACTIVE_TEAMS; -import static org.eclipse.objectteams.otre.StaticSliceBaseTransformation._OT_ACTIVE_TEAM_IDS; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.StringTokenizer; -import java.util.Map.Entry; - -import org.eclipse.objectteams.otre.util.CallinBindingManager; -import org.eclipse.objectteams.otre.util.DebugUtil; -import org.eclipse.objectteams.otre.util.ListValueHashMap; -import org.eclipse.objectteams.otre.util.MethodBinding; -import org.eclipse.objectteams.otre.util.TeamIdDispenser; - -import org.apache.bcel.Constants; -import org.apache.bcel.classfile.Field; -import org.apache.bcel.classfile.LineNumber; -import org.apache.bcel.classfile.LineNumberTable; -import org.apache.bcel.classfile.Method; -import org.apache.bcel.generic.AASTORE; -import org.apache.bcel.generic.ACONST_NULL; -import org.apache.bcel.generic.ALOAD; -import org.apache.bcel.generic.ANEWARRAY; -import org.apache.bcel.generic.ARRAYLENGTH; -import org.apache.bcel.generic.ATHROW; -import org.apache.bcel.generic.ArrayType; -import org.apache.bcel.generic.BasicType; -import org.apache.bcel.generic.BranchInstruction; -import org.apache.bcel.generic.ClassGen; -import org.apache.bcel.generic.ConstantPoolGen; -import org.apache.bcel.generic.DUP; -import org.apache.bcel.generic.DUP_X1; -import org.apache.bcel.generic.FieldGen; -import org.apache.bcel.generic.GOTO; -import org.apache.bcel.generic.IADD; -import org.apache.bcel.generic.ICONST; - -import org.apache.bcel.generic.IFNE; -import org.apache.bcel.generic.IFNONNULL; -import org.apache.bcel.generic.IF_ICMPLT; -import org.apache.bcel.generic.IINC; -import org.apache.bcel.generic.INVOKESPECIAL; -import org.apache.bcel.generic.Instruction; -import org.apache.bcel.generic.InstructionConstants; -import org.apache.bcel.generic.InstructionFactory; -import org.apache.bcel.generic.InstructionHandle; -import org.apache.bcel.generic.InstructionList; -import org.apache.bcel.generic.InvokeInstruction; -import org.apache.bcel.generic.LDC; -import org.apache.bcel.generic.LocalVariableGen; -import org.apache.bcel.generic.MONITOREXIT; -import org.apache.bcel.generic.MethodGen; -import org.apache.bcel.generic.NOP; -import org.apache.bcel.generic.ObjectType; -import org.apache.bcel.generic.POP; -import org.apache.bcel.generic.PUSH; -import org.apache.bcel.generic.TABLESWITCH; -import org.apache.bcel.generic.Type; - - -/** - * Insert dispatch code into base methods affected by callin bindings. <p> - * If a loaded class contains binding declarations (transmitted by attributes) - * these are stored for further determination of necessity for base-method-transforming. - * Classes for which a callin binding exists will be transformed: - * (base-class)methods <i>m()</i> which are changed by a callin will be copied to - * <tt>_OT$<i>m</i>$orig()</tt>. - * Hereafter the original method <i>m()</i> will be transformend depending on the - * callin-modifier: - * <ul> - * <li> replace: only the (role-)callin-method is called - * <li> after: first the original-method <tt>_OT$<i>m</i>$orig()</tt> is called and - * then the callin-method - * <li> before: first the the callin-method is called and then original-method - * <tt>_OT$<i>m</i>$orig()</tt> - * </ul> - * - * @version $Id: BaseMethodTransformation.java 23408 2010-02-03 18:07:35Z stephan $ - * @author Christine Hundt - * @author Stephan Herrmann - */ - -public class BaseMethodTransformation - extends ObjectTeamsTransformation -{ - // configurability for stepping behavior of the chaining wrapper: - private static boolean SHOW_ORIG_CALL = true; - private static boolean SHOW_RECURSIVE_CALL = true; - private static boolean SHOW_ROLE_CALL = true; - static { - String callinStepping = System.getProperty("ot.debug.callin.stepping"); - if (callinStepping != null) { - SHOW_ORIG_CALL = SHOW_RECURSIVE_CALL = SHOW_ROLE_CALL = false; - StringTokenizer tokens = new StringTokenizer(callinStepping, ","); - while (tokens.hasMoreTokens()) { - String token = tokens.nextToken(); - if ("orig".equals(token)) - SHOW_ORIG_CALL = true; - else if ("recurse".equals(token)) - SHOW_RECURSIVE_CALL = true; - else if ("role".equals(token)) - SHOW_ROLE_CALL = true; - } - } - } - - // method of o.o.Team: - private static final String IS_ACTIVE = "isActive"; //$NON-NLS-1$ - - private final static int NORESULT = -1; - - // methods awaiting statements as an initial wrapper: - private HashSet<String/*methodName*/> pendingInitialWrappers; - // methods awaiting a super call to an existing initial wrapper: - private HashSet<String/*methodName*/> pendingSuperDelegationWrappers; - - public boolean useReflection = false; - - public BaseMethodTransformation(ClassLoader loader, SharedState state) { - super(loader, state); - } - /** - * The code transformer only replaces the original code with - * the initial wrapper. - */ - public void doTransformCode(ClassGen cg) { - factory = new InstructionFactory(cg); - ConstantPoolGen cpg = cg.getConstantPool(); - String class_name = cg.getClassName(); - - Method[] methods = cg.getMethods(); - for (int i=0; i<methods.length; i++) { - Method m = methods[i]; - //if (m.isNative()) - // continue; - if (m.isVolatile()) - continue; // don't touch bridge methods - - String method_name = m.getName(); - - if (CallinBindingManager.isBoundBaseClass(class_name) - && !CallinBindingManager.hasBoundBaseParent(class_name) - && method_name.equals(Constants.CONSTRUCTOR_NAME)) - { - addToConstructor(m, getInitializedRoleSet(cg.getClassName(), false), cg, cpg); - continue; - } - - String method_signature = m.getSignature(); - - if (state.interfaceTransformedClasses.contains(class_name)) { - if (pendingInitialWrappers.contains(method_name + '.' + method_signature)) - cg.replaceMethod(m, m = generateInitialWrapper(m, class_name, cg.getMajor(), cpg)); - else if (pendingSuperDelegationWrappers.contains(method_name + '.' + method_signature)) - cg.replaceMethod(m, m = generateSuperCall(m, cg, cpg)); - - Method replacement = checkReplaceWickedSuper(class_name, m, cpg); - if (replacement != null) - cg.replaceMethod(m, replacement); - } - } - } - - /* - * If a base method m1 has a super-call super.m2() and if that method m2 is callin-bound - * we currently bypass aspect dispatch to avoid infinite recursions. - */ - private Method checkReplaceWickedSuper(String className, Method m, ConstantPoolGen cpg) - { - if (m.isAbstract() || m.isNative()) - return null; - MethodGen mg = newMethodGen(m, className, cpg); - String method_name = m.getName(); - InstructionHandle[] ihs = mg.getInstructionList().getInstructionHandles(); - boolean found = false; - for (InstructionHandle ih : ihs) { - if (ih.getInstruction() instanceof INVOKESPECIAL) { - Instruction actInstruction = ih.getInstruction(); - INVOKESPECIAL is = (INVOKESPECIAL)actInstruction; - String is_name = is.getName(cpg); - if ( !is_name.equals(method_name) // not same method - && !is_name.equals("<init>")) // not ctor call - { - @SuppressWarnings("deprecation") // type of is (invokespecial) cannot be array type - String superClassName = is.getClassName(cpg); - if ( !superClassName.equals(className) // not private method of same class - && CallinBindingManager.isBoundBaseMethod( // target method is callin-affected - superClassName, - is_name, - is.getSignature(cpg))) - { - found = true; - if(logging) printLogMessage("wicked super-call to " + is_name //$NON-NLS-1$ - + " has to be redirected to the orig-version!"); //$NON-NLS-1$ - ih.setInstruction(factory.createInvoke(superClassName, - "_OT$"+is_name+"$orig", - is.getReturnType(cpg), - is.getArgumentTypes(cpg), - Constants.INVOKESPECIAL)); - } - } - } - } - if (found) - return mg.getMethod(); - return null; - } - - /** - * Main entry for this transformer. - */ - public void doTransformInterface(ClassEnhancer ce, ClassGen cg) { - String class_name = cg.getClassName(); - //SourceMapGeneration sourceMapGen = new SourceMapGeneration(cg); - - ConstantPoolGen cpg = cg.getConstantPool(); - factory = new InstructionFactory(cg); - if (CallinBindingManager.isBoundBaseClass(class_name) && !cg.isInterface()) { - // TODO: where to add the role set infrastructure, if only an interface is bound? Implementing classes? - if (cg.containsField(OTConstants.ROLE_SET) == null && !CallinBindingManager.hasBoundBaseParent(class_name)) { - ce.addField(generateRoleSet(cpg, class_name), cg); - ce.addMethod(generateAddRole(cpg, class_name), cg); - ce.addMethod(generateRemoveRole(cpg, class_name), cg); - ce.addImplements(OTConstants.IBOUND_BASE, cg); - } - } - - if (pendingInitialWrappers == null) - pendingInitialWrappers = new HashSet<String>(); - if (pendingSuperDelegationWrappers == null) - pendingSuperDelegationWrappers = new HashSet<String>(); - - - checkReadClassAttributes(ce, cg, class_name, cpg); - - //JU: change the class modifier to 'public' if decapsulation required - if(CallinBindingManager.checkBaseClassModifierChange(class_name) && !cg.isPublic()) { - cg.setAccessFlags(makePublicFlags(cg.getAccessFlags())); - } - - Collection<MethodBinding> inheritedBindings = CallinBindingManager.getInheritedCallinBindings(class_name); - -// if (inheritedSigns!=null && !inheritedSigns.isEmpty()) { -// Iterator itx = inheritedSigns.iterator(); -// while (itx.hasNext()) { -// System.err.print(class_name+" : "); -// String[] next = (String[])itx.next(); -// System.err.println(next[0] +" " +next[1]) ; -// } -// } - /* - String[] interfaceNames = cg.getInterfaceNames(); - Collection interfaceInheritedSigns = new LinkedList(); - //System.err.println("searching inherited bindings for: "+class_name); - for (int i=0; i<interfaceNames.length;i++) { - if (!interfaceNames[i].equals(class_name)) - interfaceInheritedSigns.addAll(CallinBindingManager.getInterfaceInheritedCallinBindings(interfaceNames[i])); - }*/ - /* - if (!interfaceInheritedSigns.isEmpty()) { - System.err.println("BMT: searching inherited bindings for: "+class_name); - for (Iterator iterator = interfaceInheritedSigns.iterator(); iterator.hasNext();) { - String[] element = (String[]) iterator.next(); - System.err.println(element[0]+element[1]); - } - }*/ - //inheritedSigns.addAll(interfaceInheritedSigns); - - // if class is already transformed by this transformer - /* - if (interfaceTransformedClasses.contains(class_name)) - continue; - */ - - if(cg.isInterface()) { - // may need to add an interface version of the chaining wrapper, to be called for a base-call - int lastDollar = class_name.lastIndexOf('$'); - if (lastDollar != -1) { - // try inserting __OT__ to last type name segment - String roleClassName = class_name.substring(0, lastDollar+1)+"__OT__"+class_name.substring(lastDollar+1); - if (CallinBindingManager.isBoundBaseClass(roleClassName)) { - Method[] methods = cg.getMethods(); - for (int i=0; i<methods.length; i++) { - Method m = methods[i]; - if (m.isVolatile()) // bridge method! - continue; - String method_name = m.getName(); - String signature = m.getSignature(); - Collection<MethodBinding> bindingsForMethod = CallinBindingManager . - getBindingForBaseMethod(roleClassName, method_name, signature); - if (bindingsForMethod!= null) { - MethodGen chainGen = generateChainingWrapper(class_name, cpg, - m.getAccessFlags()|Constants.ACC_ABSTRACT, method_name, signature, null/*argumentNames*/); - if (cg.containsMethod(chainGen.getName(), chainGen.getSignature()) == null) - ce.addMethod(chainGen.getMethod(), cg); - } - } - } - } - - //CallinBindingManager.addBoundBaseInterface(class_name); // <- this is to late, implementing class may be loaded before!! - return; // No transfomations neccessary for interfaces. - } - - boolean haveDirectCallin = - CallinBindingManager.isBoundBaseClass(class_name); - // IMPLICIT_INHERITANCE - if (inheritedBindings.size() == 0 && !haveDirectCallin /*&& interfaceInheritedSigns.size()==0*/) { - if(logging) printLogMessage("\nCallins: nothing to do for class " + class_name); //$NON-NLS-1$ - return; // nothing to do - } - - if(logging) printLogMessage("\nCallin bindings may be changing class " //$NON-NLS-1$ - + class_name + ':'); - - // A field to optimize class-literal in initial wrapper: - if (cg.getMajor() < 49) {// pre 1.5? - if (cg.containsField(OTConstants.SELF_CLASS) == null) - ce.addField(new FieldGen(Constants.ACC_PROTECTED|Constants.ACC_STATIC, - classType, - OTConstants.SELF_CLASS, - cpg) - .getField(), - cg); - } - - Method[] methods = cg.getMethods(); - for (int i=0; i<methods.length; i++) { - Method m = methods[i]; - if (m.isVolatile()) // bridge method! - continue; - String method_name = m.getName(); - String method_signature = m.getSignature(); - - Collection<MethodBinding> bindingsForMethod = null; - // IMPLICIT_INHERITANCE - if (haveDirectCallin) - bindingsForMethod = CallinBindingManager . - getBindingForBaseMethod(class_name, method_name, m.getSignature()); - - //JU: added the following statement to determine overridden static base methods - //Collection inheritedCallinBindings = CallinBindingManager.getInheritedCallinBindings(class_name); - //CH: removed it again, because it is the same as 'inheritedSigns'! - - MethodGen mg = null; - int firstLine = STEP_OVER_LINENUMBER; - /*if (bindingsForMethod != null || containsSign(inheritedSigns, m)*/ /*|| containsSign(interfaceInheritedSigns, m)*/ //) { - MethodBinding inheritedBinding = matchingBinding(inheritedBindings, m, false); - String method_key = method_name+'.'+method_signature; - if (bindingsForMethod != null || (inheritedBinding != null && !m.isStatic() && !m.isPrivate())) { - - mg = newMethodGen(m, class_name, cpg); - Method orig_method; - - String name_orig = genOrigMethName(method_name); - if (cg.containsMethod(name_orig, m.getSignature())!=null) { - continue;// method was already copied to orig-version! - } - - if (debugging) - firstLine = findFirstLineNumber(m); - - mg.setName(name_orig); - - // TODO(SH): store this match, or keep previous? - if (matchingBinding(inheritedBindings, m, true) != null) // this method was adapted in a super class - replaceSuperCalls(mg, method_name, cpg); - - orig_method = mg.getMethod(); - ce.addMethod(orig_method, cg); - if(logging) printLogMessage("Method " + method_name + " was backuped as " //$NON-NLS-1$ //$NON-NLS-2$ - + name_orig + '.'); - - if (inheritedBinding != null) { - if (method_signature.equals(inheritedBinding.getBaseMethodSignature())) - pendingSuperDelegationWrappers.add(method_key); - else // override with covariant return: at the VM-level this is a *new* method, need a new initial wrapper - pendingInitialWrappers.add(method_key); - } - } - - /*if (bindingsForMethod != null || (containsSign(inheritedSigns,m) && m.isStatic())*/ /*|| containsSign(interfaceInheritedSigns, m)*/ //) { - //CH: changed 'inheritedCallinBindings' to 'inheritedSigns', because it was the same. - if (bindingsForMethod != null) { - //add method '_OT$<method_name>$chain' : - mg = getConcretMethodGen(m, class_name, cpg); - MethodGen chainGen = generateChainingWrapper(class_name, cpg, - mg.getAccessFlags(), method_name, method_signature, mg.getArgumentNames()); - Method chain = generateChainingWrapperBody(class_name, cg, cpg, - mg, method_name, method_signature, chainGen, firstLine); - - if (cg.containsMethod(chain.getName(), chain.getSignature()) == null) - ce.addMethod(chain, cg); - - pendingInitialWrappers.add(method_key); - pendingSuperDelegationWrappers.remove(method_key); // might have prematurely added this above - } - if (mg == null) - if (logging) printLogMessage("No method binding (direct or inherited) found for " //$NON-NLS-1$ - + method_name); - } - state.interfaceTransformedClasses.add(class_name); - } - - private int findFirstLineNumber(Method m) { - LineNumberTable lnt = m.getLineNumberTable(); - if (lnt != null && lnt.getTableLength() > 0) { - LineNumber[] lineNumberTable = lnt.getLineNumberTable(); - for (int i=0; i<lineNumberTable.length; i++) { - int lineNumber = lineNumberTable[i].getLineNumber(); - if (lineNumber != OTConstants.STEP_OVER_LINENUMBER) - return lineNumber; - } - return lineNumberTable[0].getLineNumber(); - } - return STEP_OVER_LINENUMBER; // make it a valid line number - } - - /** - * "super"-calls in callin bound base methods have to be redirected to the _OT$...$orig version, if the - * super-method is bound (and thus renamed to _OT$..$orig) too. - * - * @param orig_method the copied method - * @param method_name the prior name of the copied method - * @param cpg the corresponding constang pool - */ - private void replaceSuperCalls(MethodGen orig_method, String method_name, ConstantPoolGen cpg) { - // search for super calls: - InstructionList il = orig_method.getInstructionList(); - InstructionHandle[] ihs = il.getInstructionHandles(); - int actInstrIndex = 0; - while (actInstrIndex < ihs.length) { - if (ihs[actInstrIndex].getInstruction() instanceof INVOKESPECIAL) { - Instruction actInstruction = ihs[actInstrIndex].getInstruction(); - INVOKESPECIAL is = (INVOKESPECIAL)actInstruction; - String is_name = is.getName(cpg); - if(is_name.equals(method_name)) { - @SuppressWarnings("deprecation") // type if is (invokespecial) cannot be array type - String superClassName = is.getClassName(cpg); - if(logging) printLogMessage("super-call to " + is_name //$NON-NLS-1$ - + " has to be redirected to the orig-version!"); //$NON-NLS-1$ - // generate and set an instruction calling the orig-version of the super method: - InvokeInstruction superOrigCall = factory.createInvoke(superClassName, - orig_method.getName(), - orig_method.getReturnType(), - orig_method.getArgumentTypes(), - Constants.INVOKESPECIAL); - ihs[actInstrIndex].setInstruction(superOrigCall); - } - } - actInstrIndex++; - } - // redirect them ( change called method name to _OT$..$orig ) if super-method has been renamed: - // --> - } - - /** - * Is method `m' contained in `baseMethodBindings'? - * @param nameSigns list of MethodBinding - * @param m - * @param strict if true covariance must not be considered - * @return the matching binding from baseMethodBindings or null. - */ - static MethodBinding matchingBinding (Collection<MethodBinding> baseMethodBindings, Method m, boolean strict) - { - for (MethodBinding binding: baseMethodBindings) - if (binding.matchesMethod(m.getName(), m.getSignature(), strict)) - return binding; - - return null; - } - - /** - * Get a MethodGen for `m'. - * If `m' is abstract setup a new concrete method. - */ - static MethodGen getConcretMethodGen (Method m, String class_name, ConstantPoolGen cpg) { - MethodGen mg; - String signature = m.getSignature(); - Type[] argTypes = Type.getArgumentTypes(signature); - if (m.isAbstract()) { - Type returnType = Type.getReturnType(signature); - InstructionList il = new InstructionList(); - il.append(new NOP()); - mg = new MethodGen(m.getAccessFlags()&~Constants.ACC_ABSTRACT, - returnType, argTypes, - null, // names are unknown - m.getName(), class_name, - il, cpg); - } else { - mg = wipeMethod(m, class_name, cpg); - } - if (debugging) { - mg.removeLocalVariables(); - int slot = 0; - // create local variable table for "this" and arguments: - if (!m.isAbstract()) - mg.addLocalVariable("this", new ObjectType(class_name), slot++, null, null); - for (int i=0; i<argTypes.length; i++) - mg.addLocalVariable("arg"+i, argTypes[i], slot++, null, null); - mg.setMaxLocals(); - } - return mg; - } - - /** - * Generate the initial wrapper for the passed mehtod. - * It binds callin dispatch to Team-unaware client code. - * @param m the original method - * @param class_name the name of the appropriate class - * @param major - * @param cpg the ConstantPoolGen of the class - * @return the generated method - */ - private Method generateInitialWrapper(Method m, - String class_name, - int major, - ConstantPoolGen cpg) - { - MethodGen mg = getConcretMethodGen(m, class_name, cpg); - - String method_name = m.getName(); - Type returnType = mg.getReturnType(); - Type chainReturnType = object; - Type[] argTypes = mg.getArgumentTypes(); - - String name_chain = genChainMethName(method_name); - - InstructionList il = mg.getInstructionList(); - - InstructionHandle startSynchronized; - InstructionHandle chainCall; - int monitor; - // start generating - { - LocalVariableGen lg; // used for several local variables - - // Team[] _OT$teams; - int teams; - lg = mg.addLocalVariable(TEAMS, teamArray, null, null); - teams = lg.getIndex(); - - // synchronized (TopMostBoundBaseClass.class) { - Pair<Integer,InstructionHandle> monitorResult = addClassMonitorEnter(mg, il, CallinBindingManager.getTopmostBoundBase(class_name), major, cpg); - monitor = monitorResult.first; - if (debugging) - // no natural lines in this method: step-over until chain call, which has step-into: debugging => addLineNumber - mg.addLineNumber(monitorResult.second, STEP_OVER_LINENUMBER); - - // _OT$teams= new Teams[_OT$activeTeams.length]; - startSynchronized= // begin area protected by exception handler - il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.GETSTATIC)); - il.append(InstructionConstants.ARRAYLENGTH); - il.append((Instruction)factory.createNewArray(teamType, (short) 1)); - il.append(InstructionFactory.createStore(Type.OBJECT, teams)); - - // _OT$teamIDs=new int[_OT$activeTeamIDs.length]; - int teamIDs; - lg = mg.addLocalVariable(TEAMIDS, intArray, null, null); - teamIDs = lg.getIndex(); - il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAM_IDS, intArray, Constants.GETSTATIC)); - il.append(InstructionConstants.ARRAYLENGTH); - il.append((Instruction)factory.createNewArray(Type.INT, (short) 1)); - il.append(InstructionFactory.createStore(Type.OBJECT, teamIDs)); - - // for (int i=0; i<_OT$activeTeams.length; ... - int for_index; - lg = mg.addLocalVariable("i", Type.INT, null, null); //$NON-NLS-1$ - for_index = lg.getIndex(); - il.append(new PUSH(cpg, 0)); - il.append(InstructionFactory.createStore(Type.INT, for_index)); - InstructionHandle for_start = - il.append(InstructionFactory.createLoad(Type.INT, for_index)); - il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.GETSTATIC)); - il.append(InstructionConstants.ARRAYLENGTH); - BranchInstruction if_loop_finished = - InstructionFactory.createBranchInstruction(Constants.IF_ICMPGE, null); - il.append(if_loop_finished); - - // if (!_OT$activeTeams[i].isActive()) { - il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.GETSTATIC)); - il.append(InstructionFactory.createLoad(Type.INT, for_index)); - il.append(InstructionConstants.AALOAD); - il.append(factory.createInvoke(OTConstants.teamName, IS_ACTIVE, Type.BOOLEAN, Type.NO_ARGS, Constants.INVOKEINTERFACE)); - BranchInstruction if_team_isactive = - InstructionFactory.createBranchInstruction(Constants.IFNE, null); - il.append(if_team_isactive); - - // invalidate activation of current team: - // _OT$teams[i]= null; - il.append(InstructionFactory.createLoad(Type.OBJECT, teams)); - il.append(InstructionFactory.createLoad(Type.INT, for_index)); - il.append(InstructionConstants.ACONST_NULL); - il.append(InstructionConstants.AASTORE); - - // _OT$teamIDs[i]= -1; - il.append(InstructionFactory.createLoad(Type.OBJECT, teamIDs)); - il.append(InstructionFactory.createLoad(Type.INT, for_index)); - il.append(new PUSH(cpg, -1)); - il.append(InstructionConstants.IASTORE); - BranchInstruction goto_continue = - InstructionFactory.createBranchInstruction(Constants.GOTO, null); - il.append(goto_continue); - - // } else { adopt activation of current team: - // _OT$teams[i]= _OT$activeTeams[i]; - InstructionHandle adopt_activation = - il.append(InstructionFactory.createLoad(Type.OBJECT, teams)); - il.append(InstructionFactory.createLoad(Type.INT, for_index)); - il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.GETSTATIC)); - il.append(InstructionFactory.createLoad(Type.INT, for_index)); - il.append(InstructionConstants.AALOAD); - il.append(InstructionConstants.AASTORE); - - // _OT$teamIDs[i]= _OT$activeTeamIDs[i]; - il.append(InstructionFactory.createLoad(Type.OBJECT, teamIDs)); - il.append(InstructionFactory.createLoad(Type.INT, for_index)); - il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAM_IDS, intArray, Constants.GETSTATIC)); - il.append(InstructionFactory.createLoad(Type.INT, for_index)); - il.append(InstructionConstants.IALOAD); - il.append(InstructionConstants.IASTORE); - - // closing the above for: i++ and jump back: - InstructionHandle do_continue = - il.append(new IINC(for_index, 1)); - il.append(InstructionFactory.createBranchInstruction(Constants.GOTO, for_start)); - - // link jump instructions to their targets: - InstructionHandle loop_finished = il.append(new NOP()); // synthetic jump target - if_loop_finished.setTarget(loop_finished); - if_team_isactive.setTarget(adopt_activation); - goto_continue.setTarget(do_continue); - - // No more access to array fields, release monitor: - il.append(InstructionFactory.createLoad(Type.OBJECT, monitor)); - il.append(new MONITOREXIT()); - - // load special arguments: - if(!m.isStatic()) { // "this" cannot be accessed by static methods - chainCall= il.append(InstructionFactory.createThis()); // this - } else { - chainCall= il.append(new NOP()); - } - - if (debugging) - mg.addLineNumber(chainCall, STEP_INTO_LINENUMBER); - // ih now points to end of area protected by exception handler - - il.append(InstructionFactory.createLoad(teamArray, teams)); // _OT$teams - il.append(InstructionFactory.createLoad(intArray, teamIDs)); // _OT$teamIDs - il.append(new ICONST(0)); // _OT$idx = 0 - il.append(new ICONST(0)); // _OT$bindIdx = 0 - il.append(new ICONST(-1)); // _OT$baseMethTag is unused here - il.append(new ACONST_NULL()); // _OT$unusedArgs = null - } - - - // load regular arguments: - int index = m.isStatic()?0:1; - // chaining wrapper is always public, so never user INVOKESPECIAL: - short invocationKind = m.isStatic()?Constants.INVOKESTATIC:Constants.INVOKEVIRTUAL; - - for (int i=0; i<argTypes.length; i++) { - il.append(InstructionFactory.createLoad(argTypes[i],index)); - index += argTypes[i].getSize(); - } - // - il.append(factory.createInvoke(class_name, name_chain, - chainReturnType, - enhanceArgumentTypes(argTypes), - invocationKind)); - // generated invoke: _OT$<method_name>$chain (a1,.. aN) - - - adjustValue(il, null, chainReturnType, returnType); - il.append(InstructionFactory.createReturn(returnType)); - - // handler for exception within synchronized: - LocalVariableGen ex= mg.addLocalVariable("exceptionInSynchronized", Type.THROWABLE, il.getEnd(), null); //$NON-NLS-1$ - InstructionHandle handler= - il.append(InstructionFactory.createStore(Type.THROWABLE, ex.getIndex())); - il.append(InstructionFactory.createLoad(Type.OBJECT, monitor)); - il.append(new MONITOREXIT()); - il.append(InstructionFactory.createLoad(Type.THROWABLE, ex.getIndex())); - il.append(new ATHROW()); - mg.addExceptionHandler(startSynchronized, chainCall, handler, Type.THROWABLE); - - // tidy: - mg.setMaxStack(); - mg.setMaxLocals(); - Method generatedMethod = mg.getMethod(); - il.dispose(); - return generatedMethod; - } - - /** - * Generate a version of the passed method which only calls its super method - * (which will eventually call an initial-wrapper in a directly bound class). - * @param m the original method - * @param cg the ClassGen of the appropriate class - * @param cpg the ConstantPoolGen of the class - * @return the generated method - */ - Method generateSuperCall (Method m, - ClassGen cg, - ConstantPoolGen cpg) - { - short invocationKind = m.isStatic() ? Constants.INVOKESTATIC : Constants.INVOKESPECIAL; - MethodGen mg = getConcretMethodGen(m, cg.getClassName(), cpg); - - String method_name = m.getName(); - Type returnType = mg.getReturnType(); - Type[] argTypes = mg.getArgumentTypes(); - InstructionList il = mg.getInstructionList(); - - if(logging) printLogMessage("\nReplacing with call to super: " + method_name); //$NON-NLS-1$ - // start generating - if(!m.isStatic()){ //JU - il.append(InstructionFactory.createThis()); - } - int index = 1; - for (int i=0; i<argTypes.length; i++) { - il.append(InstructionFactory.createLoad(argTypes[i],index)); - index += argTypes[i].getSize(); - } - il.append(factory.createInvoke(cg.getSuperclassName(), method_name, - returnType, argTypes, - invocationKind)); - il.append(InstructionFactory.createReturn(returnType)); - // generated invoke: return super.<method_name> (a1,.. aN) - - // tidy: - mg.setMaxStack(); - mg.setMaxLocals(); - Method generatedMethod = mg.getMethod(); - il.dispose(); - return generatedMethod; - } - - - /** - * Generate a chaining wrapper for the original method described by the passed arguments. - * @param class_name the name of the appropriate class - * @param cpg the ConstantPoolGen of the class - * @param accessFlags raw flags of the method to add, visibility will however be ignored/set to public inside - * @param method_name the name of the original method - * @param method_signature the signature of the original method - * @param argumentNames source level argument names, may be null - * @return an new method with an empty instruction list - */ - MethodGen generateChainingWrapper(String class_name, - ConstantPoolGen cpg, - int accessFlags, - String method_name, - String method_signature, - String[] argumentNames) - { - Type[] argumentTypes = Type.getArgumentTypes(method_signature); - if (argumentNames == null) { - argumentNames = new String[argumentTypes.length]; - for (int i = 0; i < argumentNames.length; i++) - argumentNames[i] = "arg"+i; - } - return new MethodGen(makePublicFlags(accessFlags), // the chaining wrapper has to be 'public' because it will be called by base calls: - object, // ALWAYS! - enhanceArgumentTypes(argumentTypes), - enhanceArgumentNames(argumentNames), - genChainMethName(method_name), - class_name, - new InstructionList(), - cpg); - } - - /** - * Create the instructions for the chaining wrapper, which includes dispatch code - * and the termination condition for the recursion. - * @param class_name - * @param cg - * @param cpg - * @param mg - * @param method_name - * @param method_signature - * @param chainMethod - * @param firstLine - * @return - */ - Method generateChainingWrapperBody(String class_name, - ClassGen cg, - ConstantPoolGen cpg, - MethodGen mg, - String method_name, - String method_signature, - MethodGen chainMethod, - int firstLine) - { - Type origReturnType = mg.getReturnType(); - Type[] argumentTypes = mg.getArgumentTypes(); - Type enhancedReturnType = chainMethod.getReturnType(); - InstructionList il = chainMethod.getInstructionList(); - - // All chaining calls return an Object. - // Need to store this in a local variable to keep the stack - // balanced, because each section (before, replace, after) - // is guarded by its own exception handler, and they don't - // like pending objects on the stack. - InstructionHandle ih; - int result, ot_team; - { - LocalVariableGen lg = - chainMethod.addLocalVariable("_OT$result", enhancedReturnType, //$NON-NLS-1$ - null, null); - result = lg.getIndex(); - ih = il.append(InstructionFactory.createNull(enhancedReturnType)); - if (debugging) - chainMethod.addLineNumber(ih, STEP_OVER_LINENUMBER); - lg.setStart(il.append(InstructionFactory.createStore(enhancedReturnType, result))); - // generated: RType _OT$result = null; - - lg = chainMethod.addLocalVariable("_OT$team", teamType, null, null); //$NON-NLS-1$ - ot_team = lg.getIndex(); - // generated: Team _OT$team; - } - - int indexOffset = chainMethod.isStatic() ? -1 : 0; // argument indizes are decremented for static methods, - // because of the missing 'this' - short invocationKind = getInvocationType(mg); - - il.append(InstructionFactory.createLoad(Type.INT, IDX_ARG + indexOffset)); - il.append(InstructionFactory.createLoad(teamArray, TEAMS_ARG + indexOffset)); - il.append(new ARRAYLENGTH()); - IF_ICMPLT recursionNotYetTerminated = new IF_ICMPLT(null); - il.append(recursionNotYetTerminated); - // generated: if (_OT$teams.length < _OT$idx) { - - - // load arguments: - if (!chainMethod.isStatic()) { - ih = il.append(InstructionFactory.createThis()); - } else { - ih = il.append(new NOP()); - } - if (debugging) - chainMethod.addLineNumber(ih, SHOW_ORIG_CALL ? firstLine : STEP_INTO_LINENUMBER); // show orig call at method header ("dispatching") - - int index = EXTRA_ARGS + 1; - for (int i = 0; i < argumentTypes.length; i++) { - il.append(InstructionFactory.createLoad(argumentTypes[i], index + indexOffset)); - index += argumentTypes[i].getSize(); - } - // - il.append(factory.createInvoke(class_name, genOrigMethName(method_name), - origReturnType, argumentTypes, - invocationKind)); - // generated: this._OT$<method_name>$orig (a1,.., aN) for nonstatic case - // _OT$<method_name>$orig (a1,.., aN) for static case - - if (debugging) - chainMethod.addLineNumber(il.append(new NOP()), STEP_OVER_LINENUMBER); - - adjustValue(il, null, origReturnType, enhancedReturnType); - il.append(InstructionFactory.createReturn(enhancedReturnType)); - // generated: return _OT$result; - - ih = il.append(new NOP()); - recursionNotYetTerminated.setTarget(ih); - // generated: ; (end of the if part) - - il.append(InstructionFactory.createLoad(teamArray, TEAMS_ARG + indexOffset)); - il.append(InstructionFactory.createLoad(Type.INT, IDX_ARG + indexOffset)); - il.append(InstructionFactory.createArrayLoad(teamType)); - il.append(InstructionFactory.createStore(teamType, ot_team)); - // generated: _OT$team = _OT$teams[_OT$idx]; - - // --------------------------------------------- - createDispatchCode(chainMethod, il, - class_name, method_name, - method_signature, result, ot_team, cg, firstLine); - // --------------------------------------------- - - ih = il.append(InstructionFactory.createLoad(enhancedReturnType, result)); - il.append(InstructionFactory.createReturn(enhancedReturnType)); - // generated: return _OT$result; - if (debugging) - chainMethod.addLineNumber(ih, STEP_OVER_LINENUMBER); - - // tidy: - chainMethod.removeNOPs(); - try { // [SH]: overcautious: I once saw this CCE with no clue, why it happened :( - chainMethod.setMaxStack(); - } catch (ClassCastException cce) { - System.err.println(chainMethod); - cce.printStackTrace(); - } - chainMethod.setMaxLocals(); - //chainMethod.removeNOPs(); - Method generated = chainMethod.getMethod(); - il.dispose(); - return generated; - } - - private short getInvocationType(MethodGen chainMethod) { - if (chainMethod.isStatic()) - return Constants.INVOKESTATIC; - if (chainMethod.isPrivate()) - return Constants.INVOKESPECIAL; - else - return Constants.INVOKEVIRTUAL; - } - - /** - * @param i - * @return - */ - private static int makePublicFlags(int flags) { - if ((flags & Constants.ACC_PUBLIC) != 0) { - return flags; - } - if ((flags & Constants.ACC_PRIVATE) != 0) { - flags &= ~Constants.ACC_PRIVATE; - } else if ((flags & Constants.ACC_PROTECTED) != 0) { - flags &= ~Constants.ACC_PROTECTED; - } - flags |= Constants.ACC_PUBLIC; - return flags; - } - - /** - * Generate the dispatch code by which a chaining wrapper invokes the - * callin method(s). - * This consists of three switch blocks: before, replace, after. - * @param chainMethod the chaining wrapper method - * @param il the InstructionList of the chaining wrapper - * @param class_name the name of the appropriate class - * @param method_name the name of the original method - * @param method_signature the signature of the original method - * @param result the index of the '_OT$result' variable - * @param ot_team the index of the variable containing the team currently processed by the chaining wrapper - * @param cg the ClassGen of the appropriate class - * @param firstLine the first real source line of this method - */ - void createDispatchCode(MethodGen chainMethod, InstructionList il, - String class_name, String method_name, - String method_signature, int result, int ot_team, ClassGen cg, int firstLine) - { - - // get bindings for actually modified methods and sort them by callin-modifier: - // modifier -> ArrayList<MethodBinding> - HashMap<String, ArrayList<MethodBinding>> sortedMethodBindings = new HashMap<String, ArrayList<MethodBinding>>(); - Collection<MethodBinding> callinsForMethod; - callinsForMethod = CallinBindingManager.getBindingForBaseMethod(class_name, - method_name, method_signature); - //System.err.println(class_name +" : "+callinsForMethod); - List<MethodBinding> inheritedMethodBindings = CallinBindingManager.getInheritedBaseMethodBindings(class_name, method_name, method_signature); - //System.err.println(inheritedMethodBindings); - - //-------------------------------------------------------------------------------------------- - //JU: initialize callinsForMethod for overridden static base methods (begin) -// if(chainMethod.isStatic()){ -// if(callinsForMethod == null) { -// callinsForMethod = new LinkedList(); -// } -// -// Collection classesDefBindingsToStaticMethods = CallinBindingManager.getInheritedCallinBindingsForStaticMethods(class_name, method_name, method_signature); -// Iterator classesIt = classesDefBindingsToStaticMethods.iterator(); -// while(classesIt.hasNext()){ -// String superClassName = (String) classesIt.next(); -// Collection callinsFromSuperClasses = CallinBindingManager.getBindingForBaseMethod(superClassName, method_name, method_signature); -// callinsForMethod.addAll(callinsFromSuperClasses); -// } -// } - //JU: (end) - //---------------------------------------------------------------------------------------------- - if (!chainMethod.isStatic()) - callinsForMethod.addAll(inheritedMethodBindings); - - /* - String[] interfaceNames = cg.getInterfaceNames(); - Collection interfaceInheritedMethodBindings = new LinkedList(); - for (int i=0; i<interfaceNames.length;i++) { - if (!interfaceNames[i].equals(class_name)) - interfaceInheritedMethodBindings.addAll( - CallinBindingManager.getInterfaceInheritedMethodBindings(method_name, - method_signature, - interfaceNames[i])); - } - - if (callinsForMethod == null) - callinsForMethod = new LinkedList(); - - callinsForMethod.addAll(interfaceInheritedMethodBindings); - */ - ListValueHashMap<MethodBinding> beforeBindings = new ListValueHashMap<MethodBinding>(); - ListValueHashMap<MethodBinding> replaceBindings = new ListValueHashMap<MethodBinding>(); - ListValueHashMap<MethodBinding> afterBindings = new ListValueHashMap<MethodBinding>(); - - Iterator<MethodBinding> it = callinsForMethod.iterator(); - while (it.hasNext()) { - MethodBinding methodBinding = it.next(); - //sourceMapGen.addSourceMapInfo(methodBinding); - String modifier = methodBinding.getModifier(); - ArrayList<MethodBinding> bindings = sortedMethodBindings.get(modifier); - if (bindings == null) { - bindings = new ArrayList<MethodBinding>(); - sortedMethodBindings.put(modifier, bindings); - } - bindings.add(methodBinding); - // ----> added for predecedence purpose: - String teamName = methodBinding.getTeamClassName(); - if (modifier.equals("before")) { //$NON-NLS-1$ - beforeBindings.put(teamName, methodBinding); - } else if (modifier.equals("replace")) { //$NON-NLS-1$ - replaceBindings.put(teamName, methodBinding); - } else if (modifier.equals("after")) { //$NON-NLS-1$ - afterBindings.put(teamName, methodBinding); - } - // <--- - } - - // if any team has multiple bindings, we need to insert additional checks to avoid duplicate - // invocation of before/after causes during recursion. - boolean useBindingIdx = false; - for (LinkedList<MethodBinding> perTeamMethods : replaceBindings.valueSet()) - if (perTeamMethods.size() > 1) { - useBindingIdx = true; - break; - } - - /****************************************************************************/ - // before callin : - if (sortedMethodBindings.containsKey("before")) { //$NON-NLS-1$ - if(logging) printLogMessage("before bindings will be applied..."); //$NON-NLS-1$ - il.append(createSwitch( - beforeBindings, - chainMethod, ot_team, - NORESULT, firstLine, cg.getMajor(), useBindingIdx)); - if(logging) printLogMessage("before bindings: " //$NON-NLS-1$ - + sortedMethodBindings.get("before")); //$NON-NLS-1$ - } - /****************************************************************************/ - // replacement callin or direct recursion : - if (sortedMethodBindings.containsKey("replace")) { //$NON-NLS-1$ - if(logging) printLogMessage("recursive call and replace bindings will be applied..."); //$NON-NLS-1$ - il.append(createSwitch( - replaceBindings, - chainMethod, ot_team, - result, firstLine, cg.getMajor(), useBindingIdx)); - if(logging) printLogMessage("replace bindings: " //$NON-NLS-1$ - + sortedMethodBindings.get("replace")); //$NON-NLS-1$ - } else { - if(logging) printLogMessage("recursive chain-method call will be done..."); //$NON-NLS-1$ - // recursive call: - - createRecursiveCall(il, chainMethod, result, 1, 0, method_name, method_signature, firstLine); - } - /****************************************************************************/ - // after callin : - if (sortedMethodBindings.containsKey("after")) { //$NON-NLS-1$ - if(logging) printLogMessage("after bindings will be applied..."); //$NON-NLS-1$ - il.append(createSwitch( - afterBindings, - chainMethod, ot_team, - /*NORESULT*/result, firstLine, cg.getMajor(), useBindingIdx)); - if(logging) printLogMessage("after bindings: " //$NON-NLS-1$ - + sortedMethodBindings.get("after")); //$NON-NLS-1$ - } - } - - /** - * Create a switch statement which contains one case for each MethodBinding - * in a given list. - * The switch block is furthermore wrapped in a try-catch block. - * Herein all {@link org.objectteams.LiftingVetoException LiftingVetoException} - * are caught, and possibly reported (if Dot.log.lift ist set). - * @param methodBindings hash map of team names to 'MethodBinding' lists - * @param mg method being generated. - * @param ot_team index of local variable <tt>_OT$team</tt> - * @param ot_result index of local variable <tt>_OT$result</tt> - */ - private InstructionList createSwitch(ListValueHashMap<MethodBinding> methodBindings, MethodGen mg, - int ot_team, int ot_result, - int firstLine, - int major, - boolean useBindingIdx) - { - InstructionList il = new InstructionList(); - - boolean handlesReplacement = false; - - int indexOffset = mg.isStatic()?-1:0; // argument indizes are decremented for static methods, - // because of the missing 'this' - - // load value to be switched: - il.append(InstructionFactory.createLoad(intArray, TEAMIDS_ARG+indexOffset)); - il.append(InstructionFactory.createLoad(Type.INT, IDX_ARG+indexOffset)); - InstructionHandle switchStart = il.append(InstructionFactory.createArrayLoad(Type.INT)); - // generated: _OT$teamIDs[_OT$idx] - - int numberOfCases = methodBindings.size(); - - // one break for each case clause - GOTO[] breaks = new GOTO[numberOfCases]; - for (int i = 0; i < numberOfCases; i++) - breaks[i] = new GOTO(null); - - int[] matches = new int[numberOfCases]; - InstructionHandle[] targets = new InstructionHandle[numberOfCases]; - - int caseCounter = 0; - - List<MethodBinding> methodBindingsForTeam = null; - MethodBinding mb = null; - Iterator <Entry<String, LinkedList<MethodBinding>>> teamIterator = methodBindings.entrySet().iterator(); - while (teamIterator.hasNext()) { - Entry<String, LinkedList<MethodBinding>> entry = teamIterator.next(); - String teamName = entry.getKey(); - methodBindingsForTeam = CallinBindingManager.sortMethodBindings(entry.getValue(), teamName); - //System.out.println(methodBindings.get(teamName)); - - /*MethodBinding*/ mb = methodBindingsForTeam.get(0); - - matches[caseCounter] = TeamIdDispenser.getTeamId(teamName); - InstructionHandle nextBranch = il.append(new NOP()); - - // generate (_OT$teamID == teamId) branch here: - - // ========== create Cases: ========== - if (mb.isReplace()) { // distinct treatment of replacement: - handlesReplacement = true; - createReplaceCase(mg, il, - teamName, methodBindingsForTeam, - ot_result, ot_team, major, firstLine); - } else { // before or after callin: - BranchInstruction ifBindingIdx = null; - if (useBindingIdx) { - // only if bindingIdx == 0 - il.append(InstructionFactory.createLoad(Type.INT, BIND_IDX_ARG+indexOffset)); - ifBindingIdx= new IFNE(null); - il.append(ifBindingIdx); - } - createBeforeAfterCase(mg, il, teamName, - methodBindingsForTeam, ot_result, ot_team, major, firstLine); - if (useBindingIdx) { - ifBindingIdx.setTarget(il.append(new NOP())); - } - } - - // =================================== - - targets[caseCounter] = nextBranch; - /*InstructionHandle break_instr =*/ il.append(breaks[caseCounter]); - // generated: break; - - caseCounter++; - } // end of while - - // generate default branch here: - InstructionHandle defaultBranch = il.append(new NOP()); - if (handlesReplacement) - createRecursiveCall(il, mg, ot_result, 1, 0, mb.getBaseMethodName(), mb.getBaseMethodSignature(), firstLine); - - InstructionHandle afterSwitch = il.append(new NOP()); // all breaks point here. - - // ===== assemble the switch ==== - il.append(switchStart, - createLookupSwitch(matches, targets, breaks, - defaultBranch, afterSwitch) - ); - // ============================== - - // wrap everything in a try {} catch (LiftingVetoException e) {..} - InstructionHandle endTry = il.getEnd(); - - GOTO skipHdlr = null; - skipHdlr = new GOTO(null); - il.append(skipHdlr); - // generated: goto normal exit - - InstructionHandle hdlr = il.append(new NOP()); - il.append(DebugUtil.createReportExc(factory)); - - // catch: proceed with recursion if caught in a replace call - if (handlesReplacement) - createRecursiveCall(il, mg, ot_result, 1, 0, mb.getBaseMethodName(), mb.getBaseMethodSignature(), firstLine); - - mg.addExceptionHandler(il.getStart(), endTry, hdlr, liftingVeto); - - InstructionHandle nop = il.append(new NOP()); - skipHdlr.setTarget(nop); - - return il; - } - - /** Create the recursice call of this chaining method. - * @param il insert the call into this list. - * @param mg this chaining method - * @param ot_result stack index of the _OT$result variable or NORESULT. - * @param idx_offset TODO - * @param bindIdx_offset TODO - * @param methodName TODO - * @param methodSignature TODO - */ - void createRecursiveCall (InstructionList il, - MethodGen mg, - int ot_result, int idx_offset, int bindIdx_offset, String methodName, String methodSignature, int firstLine) - { - InstructionHandle ih = !mg.isStatic() - ? il.append(InstructionFactory.createThis()) - : il.append(new NOP()); - if (debugging) - mg.addLineNumber(ih, SHOW_RECURSIVE_CALL ? firstLine : STEP_INTO_LINENUMBER); // show recursive call at method header ("dispatching") - - Type[] argTypes = mg.getArgumentTypes(); - Type returnType = mg.getReturnType(); - short invocationKind = getInvocationType(mg); - - // arguments: no adjustment except idx++. - int index = 1; - int indexOffset = mg.isStatic()?-1:0; // argument indizes are decremented for static methods, - // because of the missing 'this' - for (int i=0; i<argTypes.length; i++) { - il.append(InstructionFactory.createLoad(argTypes[i], index+indexOffset)); - if (index == OTConstants.IDX_ARG && idx_offset != 0) { // _OT$idx has to be incremented (adding idx_offset) - il.append(new ICONST(idx_offset)); - il.append(new IADD()); - } else if (index == OTConstants.BIND_IDX_ARG) { // _OT$bindIdx has to be incremented (adding bindIdx_offset) - if (bindIdx_offset == 0) { // bindArg argument has to be set to '0' - il.append(new POP()); // remove loaded _OT$bindIdx - il.append(new ICONST(0)); // replace it by '0' - } else { - il.append(new ICONST(bindIdx_offset)); - il.append(new IADD()); - } - } - index += argTypes[i].getSize(); - } - il.append(factory.createInvoke(mg.getClassName(), mg.getName(), - returnType, argTypes, - invocationKind)); - - il.append(InstructionFactory.createStore(returnType, ot_result)); - - // _OT$result = _OT$<method_name>$chain(_OT$teams, _OT$teamIDs, _OT$idx+1, - // a1, .., aN); - if (debugging) - mg.addLineNumber(il.append(new NOP()), STEP_OVER_LINENUMBER); - } - - - /** - * Create a block for a before or after callin as a case with a surrounding switch. - * @param mg TODO - * @param il InstructionList being assembled. - * @param teamClassName name of a Team which has a callin to this method. - * @param sortedMBList MethodBindings describing the callins (already processed by CallinBindingManager.sortMethodBindings) - * @param ot_result index of local variable <tt>_OT$result</tt>. - * @param ot_team index of local variable <tt>_OT$team</tt>.l - * @param major - * @param firstLine the first real source line of this method - */ - void createBeforeAfterCase(MethodGen mg, - InstructionList il, String teamClassName, - List<MethodBinding> sortedMBList, int ot_result, int ot_team, - int major, int firstLine) - { - - MethodBinding mb = sortedMBList.get(0); - ConstantPoolGen cpg = mg.getConstantPool(); - - // after bindings are processed back-to-front: - if (mb.isAfter()) { - List<MethodBinding> reverse = new ArrayList<MethodBinding>(sortedMBList.size()); - for(int i=sortedMBList.size()-1; i>=0; i--) - reverse.add(sortedMBList.get(i)); - sortedMBList = reverse; - } - - Iterator<MethodBinding> it = sortedMBList.iterator(); - while (it.hasNext()) { - /*MethodBinding nextMethodBinding*/mb = it.next(); - - String baseMethodSignature = mb.getBaseMethodSignature(); - Type[] baseArgTypes = Type.getArgumentTypes(baseMethodSignature); - Type baseReturnType = Type.getReturnType(baseMethodSignature); - - Type[] wrapperArgTypes = Type.getArgumentTypes(mb.getWrapperSignature()); - int argsLen = wrapperArgTypes.length - 1; // don't count base arg. - - il.append(InstructionFactory.createLoad(teamType, ot_team)); - - int packedArgPos = 0; - InstructionHandle argArray = null; - if (useReflection) { - il.append(factory.createInvoke("java.lang.Object", "getClass", classType, new Type[0], Constants.INVOKEVIRTUAL)); - il.append(new LDC(cpg.addString(mb.getWrapperName()))); - pushTypeArray(il, wrapperArgTypes, major, cpg); - il.append(factory.createInvoke("java.lang.Class", "getMethod", methodType, OTConstants.getMethodSignature, Constants.INVOKEVIRTUAL)); - - il.append(InstructionFactory.createLoad(teamType, ot_team)); - // generated: - // _OT$team.getClass().getMethod(<wrapperName>, <wrapper sign>) - // _OT$team - argArray = il.append(new ANEWARRAY(cpg.addClass(object))); - - } else { - il.append(factory.createCast(teamType, new ObjectType(teamClassName))); - // generated: (<TeamClass>)_OT$team - } - - // first argument: base object: - packedArgPos = checkPackValue0(il, useReflection, packedArgPos, cpg); - { - if (!mg.isStatic()) - il.append(InstructionFactory.createThis()); - else - il.append(InstructionFactory.createNull(Type.OBJECT)); // no base object - } - checkPackValue1(il, useReflection, Type.OBJECT); - - // second argument: base result (if appropriate) - if ( mb.isAfter() && !baseReturnType.equals(Type.VOID)) { // after callin wrapper get the base method result as second argument - packedArgPos = checkPackValue0(il, useReflection, packedArgPos, cpg); - { - il.append(InstructionFactory.createLoad(object, ot_result)); - adjustValue(il, null, object, baseReturnType); - argsLen --; // the second (result) arg is also not part of the arg list - } - checkPackValue1(il, useReflection, baseReturnType); - } - - // ------- load regular args: -------- - - // stack positions for load instructions (one-based for non-statics, since 0 == this) - int stackIndex = EXTRA_ARGS + (mg.isStatic() ? 0 : 1); - // where within baseArgTypes do source arguments start? - int firstArg = 0; - - if (mb.baseMethodIsCallin()) { - // skip enhancement of this callin method (lower role). - firstArg += EXTRA_ARGS; - stackIndex += EXTRA_ARGS; - argsLen += EXTRA_ARGS; - } - for (int i = firstArg; i < argsLen; i++) { - if(logging) printLogMessage("loading " + baseArgTypes[i].toString()); //$NON-NLS-1$ - - packedArgPos = checkPackValue0(il, useReflection, packedArgPos, cpg); - { - il.append(InstructionFactory.createLoad(baseArgTypes[i],stackIndex)); - } - checkPackValue1(il, useReflection, baseArgTypes[i]); - - stackIndex += baseArgTypes[i].getSize(); - } - - InstructionHandle callinCall; - if (useReflection) { - // this information was missing above: - il.insert(argArray, createIntegerPush(cpg, packedArgPos)); - - callinCall = il.append(factory.createInvoke("java.lang.reflect.Method", "invoke", object, new Type[]{object, objectArray}, Constants.INVOKEVIRTUAL)); - il.append(new POP()); // before/after wrappers return void - } else { - callinCall = il.append(factory.createInvoke(teamClassName, - mb.getWrapperName(), - Type.VOID, wrapperArgTypes, - Constants.INVOKEVIRTUAL)); - } - if (debugging) { - mg.addLineNumber(callinCall, SHOW_ROLE_CALL ? firstLine : STEP_INTO_LINENUMBER); // show role call at method header ("dispatching") - mg.addLineNumber(il.append(new NOP()), STEP_OVER_LINENUMBER); - } - } - } - - /* this and the next method serve as a bracket for all pushes that may or may not require - * packing in an array, the array must already exist on the stack. */ - private int checkPackValue0(InstructionList il, boolean doPack, int argCount, ConstantPoolGen cpg) { - if (doPack) { - il.append(new DUP()); - il.append(createIntegerPush(cpg, argCount)); - return argCount+1; - } else { - return argCount; - } - } - private void checkPackValue1(InstructionList il, boolean doPack, Type argType) { - if (doPack) { - if (argType instanceof BasicType) - il.append(createBoxing((BasicType)argType)); - il.append(new AASTORE()); - } - } - /* Push an array of Class representing the signature given by argTypes. */ - private void pushTypeArray(InstructionList il, Type[] argTypes, int major, ConstantPoolGen cpg) { - il.append(createIntegerPush(cpg, argTypes.length)); - il.append(new ANEWARRAY(cpg.addClass(classType))); - for (int i=0; i<argTypes.length; i++) { - Type type = argTypes[i]; - il.append(new DUP()); - il.append(createIntegerPush(cpg, i)); - if (type instanceof BasicType) { - il.append(factory.createFieldAccess(toObjectTypeName((BasicType)type), "TYPE", classType, Constants.GETSTATIC)); - } else if (type instanceof ObjectType) { - appendClassLiteral(il, ((ObjectType)type).getClassName(), major, cpg); - } else if (type instanceof ArrayType) { - String prefix = ""; - while (type instanceof ArrayType) { - prefix += '['; - type = ((ArrayType)type).getElementType(); - } - String elemTypeName = null; - if (type instanceof ObjectType) - elemTypeName = "L"+((ObjectType)type).getClassName()+';'; - else if (type instanceof BasicType) - elemTypeName = ((BasicType)type).getSignature(); - appendClassLiteral(il, prefix+elemTypeName, major, cpg); - } else { - throw new OTREInternalError("unsupported type in signature "+type); - } - il.append(new AASTORE()); - } - } - - /** - * Create a block for a replace callin as a case within a surrounding switch. If there are multiple bindings from the - * same team to this base method, the bindings are sorted according to the precedence list of this team. - * @param mg base method being generated. - * @param il instruction list being assembled. - * @param teamClassName name of a Team which has a callin to this method. - * @param sortedMBList MethodBindings describing the callins (already processed by CallinBindingManager.sortMethodBindings) - * @param ot_result index of a local variable <tt>_OT$result</tt>. - * @param ot_team index of local variable <tt>_OT$team</tt>. - * @param major class file version - */ - void createReplaceCase(MethodGen mg, InstructionList il, - String teamClassName, List<MethodBinding> sortedMBList, - int ot_result, int ot_team, int major, int firstLine) - { - - int indexOffset = mg.isStatic() ? -1 : 0; // argument indizes are decremented for static methods, - // because of the missing 'this' - boolean multipleBindings = sortedMBList.size() > 1; - - LocalVariableGen unused_args_lg = mg.addLocalVariable(UNUSED, objectArray, null, null); - int unused_args = unused_args_lg.getIndex(); - unused_args_lg.setStart(il.append(new NOP())); - if (multipleBindings) { - InstructionList addition = new InstructionList(); - // load value to be switched: - - InstructionHandle switchStart = addition.append(InstructionFactory.createLoad(Type.INT, BIND_IDX_ARG+indexOffset)); - // loaded _OT$bindIdx - - int numberOfCases = sortedMBList.size(); - - // one break for each case clause - GOTO[] breaks = new GOTO[numberOfCases]; - for (int i=0; i<numberOfCases; i++) - breaks[i] = new GOTO(null); - - int[] matches = new int[numberOfCases]; - InstructionHandle[] targets = new InstructionHandle[numberOfCases]; - - int caseCounter = 0; - Iterator<MethodBinding> mbIterator = sortedMBList.iterator(); - MethodBinding mb = null; // safe because loop will definitely be entered (mbList.size() > 1) - while (mbIterator.hasNext()) { - mb = mbIterator.next(); - matches[caseCounter] = caseCounter; - InstructionHandle nextBranch = addition.append(new NOP()); - // ========== create Cases: =========== - addition.append(createSingleReplaceCallin(mg, teamClassName, mb, ot_result, ot_team, unused_args, multipleBindings, mg.isStatic(), major, firstLine)); - // ============================== - targets[caseCounter] = nextBranch; - /*InstructionHandle break_instr =*/ addition.append(breaks[caseCounter]); - // generated: break; - caseCounter++; - } - // ========== create default: =========== - InstructionHandle defaultBranch = addition.append(new NOP()); - createRecursiveCall(addition, mg, ot_result, 1, 0, mb.getBaseMethodName(), mb.getBaseMethodSignature(), firstLine); - // ============================== - - InstructionHandle afterSwitch = addition.append(new NOP()); // all breaks point here. - - for (int i=0; i<numberOfCases; i++) - breaks[i].setTarget(afterSwitch); - - addition.append(switchStart, new TABLESWITCH(matches, targets, defaultBranch)); - // wrap everything in a try {} catch (LiftingVetoException e) {..} - InstructionHandle endTry = addition.getEnd(); - - GOTO skipHdlr = null; - skipHdlr = new GOTO(null); - addition.append(skipHdlr); - // generated: goto normal exit - - InstructionHandle hdlr = addition.append(new NOP()); - addition.append(DebugUtil.createReportExc(factory)); - - // ========== create catch instructions: =========== - createRecursiveCall(addition, mg, ot_result, 0, 1, mb.getBaseMethodName(), mb.getBaseMethodSignature(), firstLine); - // ===================================== - mg.addExceptionHandler(addition.getStart(), endTry, hdlr, liftingVeto); - - InstructionHandle nop = addition.append(new NOP()); - skipHdlr.setTarget(nop); - il.append(addition); - } else { // only a single replace callin: - MethodBinding mb = sortedMBList.get(0); // default, if only one binding exists - il.append(createSingleReplaceCallin(mg, teamClassName, mb, ot_result, ot_team, unused_args, multipleBindings, mg.isStatic(), major, firstLine)); - } - unused_args_lg.setEnd(il.getEnd()); - } - - /** - * Creates a single replace callin call. - * - * @param mg base method being generated. - * @param connectorClassName name of a Team which has a callin to this method. - * @param mb the 'MethodBinding' for this callin. - * @param ot_result index of a local variable <tt>_OT$result</tt>. - * @param ot_team index of local variable <tt>_OT$team</tt>. - * @param unused_args index of local variable <tt>_OT$unused_args</tt>. - * @param multipleBindings flag indicating if there are multiple bindings in this case - * @param staticBaseMethod TODO - * @param major class file version - * @param firstLine first real source line number of this method - * @return instruction list for the callin call - */ - private InstructionList createSingleReplaceCallin(MethodGen mg, String connectorClassName, MethodBinding mb, int ot_result, int ot_team, int unused_args, boolean multipleBindings, boolean staticBaseMethod, int major, int firstLine) - { - // Sequence of values to load is (letters refer to document parameter-passing.odg): - // (f) _OT$team: call target for invoking the callin-wrapper - // (g) baseObject: this or null - // (h) enhancement: [Team[IIII[Object; - // idxs are being manipulated here, - // unusedArgs[] is allocated and filled with - // (i) - (int,Team) if current method is static role method. - // (j) - enhancement arguments, if current method is callin method - // (k) regular arguments. - - // ------------------------------------------ - // prepare Types: - // ------------------------------------------ - Type[] chainArgTypes = mg.getArgumentTypes(); - Type[] baseArgTypes = Type.getArgumentTypes(mb.getBaseMethodSignature()); - Type[] roleArgTypes = Type.getArgumentTypes(mb.getRoleMethodSignature()); - roleArgTypes = enhanceArgumentTypes(roleArgTypes); - String wrapperName = mb.getWrapperName(); - Type wrapperReturnType = Type.getReturnType(mb.getWrapperSignature()); - - Type[] wrapperArgTypes = Type.getArgumentTypes(mb.getWrapperSignature()); - - // calculate return type: - Type chainReturnType = mg.getReturnType(); - - ConstantPoolGen cpg = mg.getConstantPool(); - InstructionList il = new InstructionList(); - // (f): - il.append(InstructionFactory.createLoad(teamType, ot_team)); - - int packedArgPos = 0; - InstructionHandle argArray = null; - if (useReflection) { - il.append(factory.createInvoke("java.lang.Object", "getClass", classType, new Type[0], Constants.INVOKEVIRTUAL)); - il.append(new LDC(cpg.addString(mb.getWrapperName()))); - pushTypeArray(il, wrapperArgTypes, major, cpg); - il.append(factory.createInvoke("java.lang.Class", "getMethod", methodType, OTConstants.getMethodSignature, Constants.INVOKEVIRTUAL)); - - il.append(InstructionFactory.createLoad(teamType, ot_team)); - // generated: - // _OT$team.getClass().getMethod(<wrapperName>, <wrapper sign>) - // _OT$team - argArray = il.append(new ANEWARRAY(cpg.addClass(object))); - } else { - il.append(factory.createCast(teamType, new ObjectType(connectorClassName))); - // generated: (<TeamClass>)_OT$team - } - - // (g): - packedArgPos = checkPackValue0(il, useReflection, packedArgPos, cpg); - { - if(!staticBaseMethod) - il.append(InstructionFactory.createThis()); - else - il.append(InstructionFactory.createNull(Type.OBJECT)); // no base object - } - checkPackValue1(il, useReflection, Type.OBJECT); - - // ---------------------------------------- - // (h) Load Extra Arguments: - // ---------------------------------------- - int staticOffset = staticBaseMethod?-1:0; // argument indizes are decremented for static methods, - // because of the missing 'this' - // first 4 extra arguments: _OT$teams, _OT$teamIDs, _OT$idx, _OT$bindIdx - for (int i=0; i<4; i++) { // If this is called only once _OT$idx has to be incremented, else _OT$bindIdx has to be incremented - packedArgPos = checkPackValue0(il, useReflection, packedArgPos, cpg); - { - il.append(InstructionFactory.createLoad(chainArgTypes[i], i+1+staticOffset)); - if (!multipleBindings && i+1+staticOffset == OTConstants.IDX_ARG+staticOffset) {// _OT$idx++: - il.append(new ICONST(1)); - il.append(new IADD()); - } else if (multipleBindings && i+1+staticOffset == OTConstants.BIND_IDX_ARG+staticOffset) {// _OT$bindIdx: - il.append(new ICONST(1)); - il.append(new IADD()); - } - } - checkPackValue1(il, useReflection, chainArgTypes[i]); - } - // _OT$baseMethTag: - int base_meth_tag = CallinBindingManager.getBaseCallTag(mb.getBaseClassName(), - mb.getBaseMethodName(), - mb.getBaseMethodSignature()); -// //JU: added this if-statement (begin) ---------------------------------------------- -// if(staticBaseMethod && !mg.getClassName().equals(mb.getBaseClassName())){ -// //the method binding is a dummy -> the callin wrapper is performed -// //with an invalid base method tag value -> an exception will be thrown -// base_meth_tag = INVALID_BASE_METHOD_TAG; -// } -// //JU (end) -------------------------------------------------------------------------- - - packedArgPos = checkPackValue0(il, useReflection, packedArgPos, cpg); - { - il.append(createIntegerPush(cpg, base_meth_tag)); - } - checkPackValue1(il, useReflection, Type.INT); - - // collect regular args first, insert into il later: - InstructionList regularArgs = new InstructionList(); - - // put "new Object[]" on stack, later containing unused arguments: - packedArgPos = checkPackValue0(il, useReflection, packedArgPos, cpg); - { - il.append(createIntegerPush(cpg, baseArgTypes.length)); - // enough space to hold ALL base arguments - // Note that the callin wrapper may add more elements to this array. - il.append((Instruction)factory.createNewArray(object, (short)1)); - il.append(InstructionFactory.createStore(objectArray, unused_args)); - // generated: _OT$unusedArgs = new Object[<n_base_args>]; - - // ---------------------------------------- - // handle more arguments: load regular ones, store unused arguments into the array: - // ---------------------------------------- - int unusedArgsIdx = 0; // index into Object[]. - - int stackIdx = EXTRA_ARGS + 1 + staticOffset; // one-based, since 0 == this (unless static) - int regularArgsStart = EXTRA_ARGS; - boolean baseIsStaticCallin = mb.baseMethodIsCallin() && staticBaseMethod; - if (baseIsStaticCallin) { - // (i) need these synthetic arguments up-front: "int dummy, Team enclosingTeam" - storeUnusedArg(il, unused_args, 0, // constant - new ICONST(0), - Type.INT, - cpg); - storeUnusedArg(il, unused_args, 1, // constant - new ALOAD(regularArgsStart+1), - OTConstants.teamType, - cpg); - - // consumed first two parameters into unusedArgs: - regularArgsStart+=2; - stackIdx += 2; - unusedArgsIdx += 2; - } - for (int i=regularArgsStart; i<chainArgTypes.length; i++) { - Type argType = chainArgTypes[i]; - Instruction loadingInstruction = InstructionFactory.createLoad(argType, stackIdx); - if (isRegularArg(i, mb.baseMethodIsCallin(), staticBaseMethod)) { - // (k) collect loading instruction, for appending after _OT$unusedArgs. - packedArgPos = checkPackValue0(regularArgs, useReflection, packedArgPos, cpg); - { - regularArgs.append(loadingInstruction); - } - checkPackValue0(regularArgs, useReflection, packedArgPos, cpg); - } else { - // (j) store unused arg - storeUnusedArg(il, unused_args, unusedArgsIdx++, loadingInstruction, argType, cpg); - // generated: _OT$unusedArgs[<unusedArgsIdx>] = maybeBox(a<index>); - } - stackIdx += argType.getSize(); - } - il.append(InstructionFactory.createLoad(objectArray, unused_args)); - } - checkPackValue1(il, useReflection, objectArray); - - // (k) insert previously assembled load-sequence: - il.append(regularArgs); - - // ============= INVOKEVIRTUAL (wrapper) ============= - InstructionHandle callinCall; - if (useReflection) { - // this information was missing above: - il.insert(argArray, createIntegerPush(cpg, packedArgPos)); - - callinCall = il.append(factory.createInvoke("java.lang.reflect.Method", "invoke", object, new Type[]{object, objectArray}, Constants.INVOKEVIRTUAL)); - wrapperReturnType = Type.OBJECT; - } else { - callinCall = il.append(factory.createInvoke(connectorClassName, wrapperName, - wrapperReturnType, - wrapperArgTypes, - Constants.INVOKEVIRTUAL)); - } - if (debugging) { - mg.addLineNumber(callinCall, SHOW_ROLE_CALL ? firstLine : STEP_INTO_LINENUMBER); // show role call at method header ("dispatching") - mg.addLineNumber(il.append(new NOP()), STEP_OVER_LINENUMBER); - } - - adjustValue(il, null, wrapperReturnType, chainReturnType); - il.append(InstructionFactory.createStore(chainReturnType, ot_result)); - - return il; - } - - /** - * Store an unused value (loaded by pushInstruction) into _OT$unusedArgs - */ - private void storeUnusedArg(InstructionList il, - int unused_args, - int arrayIndex, - Instruction pushInstruction, - Type argType, - ConstantPoolGen cpg) - { - il.append(InstructionFactory.createLoad(objectArray, unused_args)); - il.append(createIntegerPush(cpg, arrayIndex)); - il.append(pushInstruction); - if (argType instanceof BasicType) - il.append(createBoxing((BasicType)argType)); - il.append(InstructionFactory.createArrayStore(objectArray)); - } - - /** - * Is the parameter at position idx mapped (by paramPositions or implicitly)? - * Cut off head: - * - (int,Team) if present (static role method) - * - enhancement (possible twice) - * @param idx parameter index of enhanced signature - */ - static boolean isRegularArg (int idx, boolean baseIsCallin, boolean baseIsStatic) { - if (baseIsCallin && baseIsStatic) // FIXME(SH): should be baseIsRole instead of baseIsCallin! - idx -= 2; - int firstVisible = EXTRA_ARGS + (baseIsCallin?EXTRA_ARGS:0); // skip one or two enhancements - return idx >= firstVisible; - } - - /** - * Given an argument of type <tt>actual</tt>, must - * we use type <tt>formal</tt> in signatures, - * because it is a supertype of <tt>actual</tt>? - */ - static Type checkWiden (Type actual, Type formal) { - if (!actual.equals(formal) - && actual instanceof ObjectType - && formal instanceof ObjectType) - { - ObjectType actualObj = (ObjectType)actual; - ObjectType formalObj = (ObjectType)formal; - if (RepositoryAccess.safeSubclassOf(actualObj, formalObj)) - return formalObj; - } - return actual; - } - - /** - * Create an instruction list for initializing the role set field on-demand. - * @param valueRequired should the role set be on the stack after this sequence? - * @param cg the ClassGen of the appropriate class - */ - private InstructionList getInitializedRoleSet(String class_name, boolean valueRequired) {; - InstructionList il = new InstructionList(); - - // try to retrieve existing set: - il.append(new ALOAD(0)); - il.append(factory.createGetField(class_name, OTConstants.ROLE_SET, OTConstants.roleSetType)); - if (valueRequired) - il.append(new DUP()); // a spare value to keep on the stack if successful - - // if (roleSet == null) .. - IFNONNULL branch = new IFNONNULL(null); - il.append(branch); - - // conditionally create the set: - if (valueRequired) - il.append(new POP()); // remove useless "null", replace with DUP_X1 below - il.append(new ALOAD(0)); - il.append(factory.createNew(OTConstants.roleSetType)); - il.append(new DUP()); - il.append(factory.createInvoke(OTConstants.roleSetType.getClassName(), - Constants.CONSTRUCTOR_NAME, - Type.VOID, - Type.NO_ARGS, - Constants.INVOKESPECIAL)); - if (valueRequired) - il.append(new DUP_X1()); // push below pending "this" - - // store in the field: - il.append(factory.createPutField(class_name, OTConstants.ROLE_SET, OTConstants.roleSetType)); - - // endif - branch.setTarget(il.append(new NOP())); - return il; - } - - /** - * Generates the field '_OT$roleSet' which is used to store the added roles. - * @param cpg the ClassGen of the appropriate class - * @param class_name the name of the class - * @return the generated field - */ - private Field generateRoleSet(ConstantPoolGen cpg, String class_name) { - FieldGen fg = new FieldGen(Constants.ACC_PROTECTED|Constants.ACC_TRANSIENT, - OTConstants.roleSetType, - OTConstants.ROLE_SET, - cpg); - return fg.getField(); - } - - /** - * Generates the method 'public void _OT$addRole(Object role)' which adds the passed object - * to the role set of this base class. - * @param cpg the ClassGen of the appropriate class - * @param class_name the name of the class - * @return the generated method - */ - private Method generateAddRole(ConstantPoolGen cpg, String class_name) { - - InstructionList il = new InstructionList(); - MethodGen mg = new MethodGen(Constants.ACC_PUBLIC, - Type.VOID, - new Type[] { Type.OBJECT }, - new String[] {"role"}, - OTConstants.ADD_ROLE, class_name, - il, cpg); - - il.append(getInitializedRoleSet(class_name, /*valueRequired*/true)); - - il.append(InstructionFactory.createLoad(Type.OBJECT, 1)); - il.append(factory.createInvoke(OTConstants.roleSetType.getClassName(), - "add", - Type.BOOLEAN, - new Type[] {Type.OBJECT}, - Constants.INVOKEVIRTUAL)); - il.append(new POP()); - il.append(InstructionFactory.createReturn(Type.VOID)); - mg.removeNOPs(); - mg.setMaxStack(); - mg.setMaxLocals(2); - return mg.getMethod(); - } - - /** - * Generates the method 'public void _OT$removeRole(Object role)' which removes the passed object - * from the role set of this base class. - * @param cpg the ClassGen of the appropriate class - * @param class_name the name of the class - * @return the generated method - */ - private Method generateRemoveRole(ConstantPoolGen cpg, String class_name) { - - InstructionList il = new InstructionList(); - MethodGen mg = new MethodGen(Constants.ACC_PUBLIC, - Type.VOID, - new Type[] { Type.OBJECT }, - new String[] {"role"}, - OTConstants.REMOVE_ROLE, class_name, - il, cpg); - il.append(new ALOAD(0)); - il.append(factory.createGetField(class_name, OTConstants.ROLE_SET, OTConstants.roleSetType)); - il.append(InstructionFactory.createLoad(Type.OBJECT, 1)); - il.append(factory.createInvoke(OTConstants.roleSetType.getClassName(), - "remove", - Type.BOOLEAN, - new Type[] {Type.OBJECT}, - Constants.INVOKEVIRTUAL)); - il.append(new POP()); - il.append(InstructionFactory.createReturn(Type.VOID)); - mg.removeNOPs(); - mg.setMaxStack(2); - mg.setMaxLocals(2); - return mg.getMethod(); - } - -} diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/ClassEnhancer.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/ClassEnhancer.java deleted file mode 100644 index ce12bb706..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/ClassEnhancer.java +++ /dev/null @@ -1,79 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2005-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: ClassEnhancer.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre; - -import org.apache.bcel.classfile.Field; -import org.apache.bcel.classfile.Method; -import org.apache.bcel.generic.ClassGen; -import org.apache.bcel.generic.ConstantPoolGen; - - - -/** - * This interface is used to abstract from the BCEL external transformations. - * - * @author Christine Hundt - * @author Juergen Widiker - * @author Stephan Herrmann - */ -public interface ClassEnhancer { - - /** - * Adds the interface 'interfaceName' to the implements clause of class 'cg'. - */ - public void addImplements(String interfaceName, ClassGen cg); - - /** - * Adds the method 'm' to the class represented by 'cg'. - * @param m the method to be added - * @param cg the ClassGen of the appropriate class - */ - void addMethod(Method m, ClassGen cg); - - /** - * Adds method 'm' to the class 'cg' or, if a method with the - * same name and signature already exists, replace that method. - * @param method - * @param cg - */ - void addOrReplaceMethod(Method method, ClassGen cg); - - /** - * Adds the field 'f' to the class represented by 'cg'. - * @param f - * @param cg - */ - void addField(Field f, ClassGen cg); - - /** - * Loads the class named 'className'. - * @param className the name of the class to be loaded - * @param client the transformer on behalf of which we are called, can be used to call checkReadClassAttributes. - */ - void loadClass(String className, ObjectTeamsTransformation client); - - /** - * Decapsulation of the method 'm'. This means that the access modifier of this method is set to 'public'. - * @param m the name of the method to be decapsulated - * @param className the name of the belonging class - * @param packageName the name of the belonging package - * @param cpg the ConstantPoolGen of the class - */ - void decapsulateMethod(Method m, ClassGen cg, String packageName, ConstantPoolGen cpg); - - -} diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/Decapsulation.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/Decapsulation.java deleted file mode 100644 index 8442cbdfd..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/Decapsulation.java +++ /dev/null @@ -1,417 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2003, 2009 Technical University Berlin, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: Decapsulation.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Technical University Berlin - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre; - -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; - -import org.eclipse.objectteams.otre.util.CallinBindingManager; -import org.eclipse.objectteams.otre.util.FieldDescriptor; -import org.eclipse.objectteams.otre.util.SuperMethodDescriptor; - -import org.apache.bcel.Constants; -import org.apache.bcel.classfile.Method; -import org.apache.bcel.generic.ClassGen; -import org.apache.bcel.generic.ConstantPoolGen; -import org.apache.bcel.generic.InstructionFactory; -import org.apache.bcel.generic.InstructionList; -import org.apache.bcel.generic.MethodGen; -import org.apache.bcel.generic.ObjectType; -import org.apache.bcel.generic.Type; - -/** - * For each base method that is bound by callout and has - * insufficient visibility, the visibility is set to public. - * Check whether the affected base class resides in a sealed package. - * In that case dissallow decapsulation by throwing an IllegalAccessError. - * - * @version $Id: Decapsulation.java 23408 2010-02-03 18:07:35Z stephan $ - * @author Stephan Herrmann - */ -public class Decapsulation - extends ObjectTeamsTransformation - implements Constants -{ - -// HashSet modifiedPackages = new HashSet(); - - public static class SharedState extends ObjectTeamsTransformation.SharedState { - private HashSet<String/*callout accessed fields*/> generatedFieldCalloutAccessors = new HashSet<String>(); - private HashSet<String/*super-accessed methods (sign)*/> generatedSuperAccessors = new HashSet<String>(); - } - @Override - SharedState state() { - return (SharedState)this.state; - } - - public Decapsulation(ClassLoader loader, SharedState state) { - super(loader, state); - // FIXME(SH): can we ever release this transformer and its state? - synchronized(ObjectTeamsTransformation.reentrentTransformations) { - ObjectTeamsTransformation.reentrentTransformations.add(this); - } - } - - /** - * Main entry for this transformer. - */ -// @SuppressWarnings("unchecked") - public void doTransformInterface(ClassEnhancer ce, ClassGen cg) { - String class_name = cg.getClassName(); - ConstantPoolGen cpg = cg.getConstantPool(); - - // if class is already transformed by this transformer - if (state.interfaceTransformedClasses.contains(class_name)) - return; - - checkReadClassAttributes(ce, cg, class_name, cpg); - - // next step starts to transform, so record this class now. - state.interfaceTransformedClasses.add(class_name); - - generateFieldAccessForCallout(ce, cg, class_name, cpg); - - generateSuperAccessors(ce, cg, class_name, cpg); - - HashSet<String> calloutBindings = CallinBindingManager.getCalloutBindings(class_name); - - if (calloutBindings == null) { - if(logging) printLogMessage("\nClass " + class_name - + " requires no callout adjustment."); - return; - } - - if(logging) printLogMessage("\nCallout bindings might be changing class " - + class_name + ":"); - - HashSet<String> oldStyleBinding = new HashSet<String>(); - - // try new style decapsulation first (since 1.2.8): - for (String calloutBinding : calloutBindings) { - DecapsulationDescriptor desc = new DecapsulationDescriptor(); - if (!desc.decode(calloutBinding, cg)) - oldStyleBinding.add(calloutBinding); // old style attribute - else if (!desc.existsAlready) - ce.addMethod(desc.generate(class_name, cpg), cg); - } - - if (oldStyleBinding.isEmpty()) return; - - // --> follows: old style decapsulation for remaining bindings: - int pos = class_name.lastIndexOf('.'); - String package_name = "NO_PACKAGE"; - if (pos != -1) - package_name = class_name.substring(0,pos); - - Method[] methods = cg.getMethods(); - for (int i = 0; i < methods.length; i++) { - Method m = methods[i]; - String method_name = m.getName(); - - boolean requiresAdjustment = CallinBindingManager. - requiresCalloutAdjustment(oldStyleBinding, - method_name, - m.getSignature()); - - if (requiresAdjustment) { - ce.decapsulateMethod(m, cg, package_name, cpg); - } - } - } - class DecapsulationDescriptor { - short invokeKind; - String targetClass; - String methodName; - String methodSign; - Type returnType; - Type[] args; - String accessorName; - - boolean existsAlready; - - /** - * new style encoding is - * targetClassName ('!' | '?') methodName '.' methodSign - */ - boolean decode(String encodedBinding, ClassGen cg) { - int sepPos = encodedBinding.indexOf('!'); - if (sepPos != -1) { // static method: - invokeKind = INVOKESTATIC; - } else { - sepPos = encodedBinding.indexOf('?'); - if (sepPos != -1) { - invokeKind = INVOKEVIRTUAL; - } else { - return false; // old style - } - } - targetClass = encodedBinding.substring(0, sepPos); - int sigPos = encodedBinding.indexOf('(', sepPos); - methodName = encodedBinding.substring(sepPos+1, sigPos); - methodSign = encodedBinding.substring(sigPos); - - returnType = Type.getReturnType(methodSign); - args = Type.getArgumentTypes(methodSign); - - accessorName = "_OT$decaps$"+methodName; - existsAlready = cg.containsMethod(accessorName, methodSign) != null; - if (invokeKind == INVOKEVIRTUAL) { - Method existing = cg.containsMethod(methodName, methodSign); - if (existing != null && existing.isPrivate()) - invokeKind = INVOKESPECIAL; // accessing private - } - - return true; - } - Method generate(String currentClass, ConstantPoolGen cpg) { - InstructionList il = new InstructionList(); - int instanceOffset = 0; - short flags = Constants.ACC_PUBLIC; - if (invokeKind != INVOKESTATIC) { - instanceOffset=1; - il.append(InstructionFactory.createThis()); - } else { - flags |= Constants.ACC_STATIC; - } - int pos= 0; - for (int i = 0; i < args.length; i++) { - il.append(InstructionFactory.createLoad(args[i], pos+instanceOffset)); - pos += args[i].getSize(); - } - il.append(new InstructionFactory(cpg).createInvoke(targetClass, methodName, returnType, args, invokeKind)); - il.append(InstructionFactory.createReturn(returnType)); - MethodGen newMethod = new MethodGen(flags, returnType, args, /*argNames*/null, accessorName, currentClass, il, cpg); - newMethod.setMaxLocals(); - newMethod.setMaxStack(); - return newMethod.getMethod(); - } - } - - /** - * Generates getter and setter methods for all fields of the class 'class_name' which are accessed via callout. - * Informations are received via attributs (CallinBindingManager). - * @param cg the ClassGen of the appropriate class - * @param class_name the name of the class - * @param cpg the ConstantPoolGen of the class - * @param es the ExtensionSet to add the new access methods - */ - private void generateFieldAccessForCallout(ClassEnhancer ce, ClassGen cg, String class_name, ConstantPoolGen cpg) { - InstructionFactory factory = null; - - HashSet<String> addedAccessMethods = state().generatedFieldCalloutAccessors; - - List<FieldDescriptor> getter = CallinBindingManager.getCalloutGetFields(class_name); - if (getter != null) { - factory = new InstructionFactory(cg); - Iterator<FieldDescriptor> it = getter.iterator(); - while (it.hasNext()) { - FieldDescriptor fd = it.next(); - String key = "get_" + class_name +"." + fd.getFieldName() + fd.getFieldSignature(); - if (logging) - printLogMessage("Generating getter method "+key); - if (addedAccessMethods == null) - addedAccessMethods = new HashSet<String>(); - if (addedAccessMethods.contains(key)) - continue; // this getter has already been created - ce.addMethod(generateGetter(cpg, class_name, fd, factory), cg); - addedAccessMethods.add(key); - } - } - - List<FieldDescriptor> setter = CallinBindingManager.getCalloutSetFields(class_name); - if (setter != null) { - if (factory == null) - factory = new InstructionFactory(cg); - Iterator<FieldDescriptor> it = setter.iterator(); - while (it.hasNext()) { - FieldDescriptor fd = it.next(); - String key = "set_"+ class_name +"." + fd.getFieldName()+fd.getFieldSignature(); - if (logging) - printLogMessage("Generating setter method "+key); - if (addedAccessMethods == null) - addedAccessMethods = new HashSet<String>(); - if (addedAccessMethods.contains(key)) - continue; // this setter has already been created - ce.addMethod(generateSetter(cpg, class_name, fd, factory), cg); - addedAccessMethods.add(key); - } - } - } - - - /** - * Generates a getter method for the field described by 'fd' in the class 'class_name'. - * @param cpg the ConstantPoolGen of the class - * @param class_name the name of the class - * @param fd the FieldDescriptor describing the affected field - * @param factory an InstructionFactory for this class - * @return the generated getter method - */ - private Method generateGetter(ConstantPoolGen cpg, String class_name, FieldDescriptor fd, InstructionFactory factory) { - String fieldName = fd.getFieldName(); - Type fieldType = Type.getType(fd.getFieldSignature()); - Type baseType = new ObjectType(class_name); - - InstructionList il = new InstructionList(); - String[] argumentNames; - Type[] argumentTypes; - if (fd.isStaticField()) { - argumentNames = new String[0]; - argumentTypes = new Type[0]; - } else { - argumentNames = new String[] {"base_obj"}; - argumentTypes = new Type[] {baseType}; - } - MethodGen mg = new MethodGen((Constants.ACC_PUBLIC|Constants.ACC_STATIC), - fieldType, - argumentTypes, - argumentNames, - OT_PREFIX+"get$"+fieldName, - class_name, - il, cpg); - if (!fd.isStaticField()) - il.append(InstructionFactory.createLoad(baseType, 0)); // first argument is at slot 0 in static methods - short fieldKind = fd.isStaticField()?Constants.GETSTATIC:Constants.GETFIELD; - il.append(factory.createFieldAccess(class_name, fieldName, fieldType, fieldKind)); - il.append(InstructionFactory.createReturn(fieldType)); - - mg.removeNOPs(); - mg.setMaxStack(); - mg.setMaxLocals(); - return mg.getMethod(); - } - - - /** - * Generates a setter method for the field described by 'fd' in the class 'class_name'. - * @param cpg the ConstantPoolGen of the class - * @param class_name the name of the class - * @param fd the FieldDescriptor describing the affected field - * @param factory an InstructionFactory for this class - * @return the generated getter method - */ - private Method generateSetter(ConstantPoolGen cpg, String class_name, FieldDescriptor fd, InstructionFactory factory ) { - String fieldName = fd.getFieldName(); - Type fieldType = Type.getType(fd.getFieldSignature()); - Type baseType = new ObjectType(class_name); - - Type[] argumentTypes; - String[] argumentNames; - if (fd.isStaticField()) { - argumentTypes = new Type[] { fieldType}; - argumentNames = new String[] {"new_value"}; - } else { - argumentTypes = new Type[] {baseType, fieldType}; - argumentNames = new String[] {"base_obj", "new_value"}; - } - - InstructionList il = new InstructionList(); - MethodGen mg = new MethodGen((Constants.ACC_PUBLIC|Constants.ACC_STATIC), - Type.VOID, - argumentTypes, - argumentNames, - OT_PREFIX+"set$"+fieldName, - class_name, - il, cpg); - - int argumentPosition; // position for the argument holding the new field value. - if (!fd.isStaticField()) { - il.append(InstructionFactory.createLoad(baseType, 0)); // first argument is at slot 0 in static methods - argumentPosition = 1; - } else { - argumentPosition = 0; - } - il.append(InstructionFactory.createLoad(fieldType, argumentPosition)); - short fieldKind = fd.isStaticField()?Constants.PUTSTATIC:Constants.PUTFIELD; - il.append(factory.createFieldAccess(class_name, fieldName, fieldType, fieldKind)); - il.append(InstructionFactory.createReturn(Type.VOID)); - - mg.removeNOPs(); - mg.setMaxStack(); - mg.setMaxLocals(); - return mg.getMethod(); - } - - private void generateSuperAccessors(ClassEnhancer ce, ClassGen cg, String class_name, ConstantPoolGen cpg) { - InstructionFactory factory = null; - - HashSet<String> addedAccessMethods = state().generatedSuperAccessors; - - List<SuperMethodDescriptor> methods = CallinBindingManager.getSuperAccesses(class_name); - if (methods != null) { - factory = new InstructionFactory(cg); - for (SuperMethodDescriptor superMethod : methods) { - String key = superMethod.methodName+'.'+superMethod.signature; - if (logging) - printLogMessage("Generating super access method "+key); - if (addedAccessMethods == null) - addedAccessMethods = new HashSet<String>(); - if (addedAccessMethods.contains(key)) - continue; // this accessor has already been created - ce.addMethod(generateSuperAccessor(cpg, class_name, superMethod, factory), cg); - addedAccessMethods.add(key); - } - } - } - - private Method generateSuperAccessor(ConstantPoolGen cpg, String className, SuperMethodDescriptor superMethod, InstructionFactory factory) - { - int endPos = superMethod.signature.indexOf(')'); - String segment = superMethod.signature.substring(1, endPos); - String[] typeNames = (segment.length() > 0) ? segment.split(",") : new String[0]; - Type[] argTypes = new Type[typeNames.length]; - for (int i = 0; i < argTypes.length; i++) - argTypes[i] = Type.getType(typeNames[i]); - - int index = superMethod.signature.lastIndexOf(')') + 1; - Type returnType = Type.getType(superMethod.signature.substring(index)); - - Type baseType = new ObjectType(className); - Type[] wrapperTypes = new Type[argTypes.length+1]; - System.arraycopy(argTypes, 0, wrapperTypes, 1, argTypes.length); - wrapperTypes[0] = baseType; - String[] argNames = new String[wrapperTypes.length]; - for (int i = 0; i < argNames.length; i++) { - argNames[i] = "arg"+i; - } - InstructionList il = new InstructionList(); - MethodGen mg = new MethodGen((Constants.ACC_PUBLIC|Constants.ACC_STATIC), - returnType, - wrapperTypes, - argNames, - OT_PREFIX+superMethod.methodName+"$super", - className, - il, cpg); - il.append(InstructionFactory.createLoad(baseType, 0)); // first argument is base instance - for (int i = 0; i < argTypes.length; i++) - il.append(InstructionFactory.createLoad(argTypes[i], i+1)); - - // if super method is also callin bound directly invoke the orig-version - // (to avoid that BaseMethodTransformation.checkReplaceWickedSuper() has to rewrite this code again): - String methodName = (CallinBindingManager.isBoundBaseMethod(superMethod.superClass, superMethod.methodName, superMethod.signature)) - ? genOrigMethName(superMethod.methodName) - : superMethod.methodName; - - il.append(factory.createInvoke(superMethod.superClass, methodName, returnType, argTypes, INVOKESPECIAL)); - il.append(InstructionFactory.createReturn(returnType)); - mg.setMaxStack(); - mg.setMaxLocals(); - return mg.getMethod(); - } - -} diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/LiftingParticipantTransformation.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/LiftingParticipantTransformation.java deleted file mode 100644 index e43204c57..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/LiftingParticipantTransformation.java +++ /dev/null @@ -1,182 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2009 Stephan Herrmann - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: LiftingParticipantTransformation.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Stephan Herrmann - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre; - - -import java.lang.reflect.Field; - -import org.objectteams.Team; - -import org.apache.bcel.Constants; -import org.apache.bcel.classfile.Method; -import org.apache.bcel.generic.ALOAD; -import org.apache.bcel.generic.BranchInstruction; -import org.apache.bcel.generic.ClassGen; -import org.apache.bcel.generic.ConstantPoolGen; -import org.apache.bcel.generic.DUP; -import org.apache.bcel.generic.GOTO; -import org.apache.bcel.generic.IFNULL; -import org.apache.bcel.generic.INVOKESPECIAL; -import org.apache.bcel.generic.InstructionFactory; -import org.apache.bcel.generic.InstructionHandle; -import org.apache.bcel.generic.InstructionList; -import org.apache.bcel.generic.LDC; -import org.apache.bcel.generic.MethodGen; -import org.apache.bcel.generic.NEW; -import org.apache.bcel.generic.NOP; -import org.apache.bcel.generic.ObjectType; -import org.apache.bcel.generic.POP; -import org.apache.bcel.generic.Type; - -/** - * If the property ot.lifting.participant is set transform all lift methods and insert - * static calls to createRole(Team,Object,String)Object; to the registered lifting participant - * before creating a new role. If createRole returns non-null then that value is taken - * as the new role, otherwise lifting proceeds as normal, i.e., normally creates a new role. - * - * @author stephan - * @since 1.3.1 - */ -public class LiftingParticipantTransformation extends ObjectTeamsTransformation { - - - private static String PARTICIPANT_NAME = System.getProperty("ot.lifting.participant"); - private static boolean checked = false; - - final private static String LIFT_PREFIX = "_OT$liftTo"; - - private static final String WRONG_ROLE_EXCEPTION = "org.objectteams.WrongRoleException"; - private static final String LIFTING_FAILED_EXCEPTION = "org.objectteams.LiftingFailedException"; - private static final String LIFTING_VETO_EXCEPTION = "org.objectteams.LiftingVetoException"; - - private static final ObjectType iLiftingParticipant = new ObjectType("org.objectteams.ILiftingParticipant"); - - private static final String CREATE_ROLE_METHOD = "createRole"; - private static final String LIFTING_PARTICIPANT_FIELD = "_OT$liftingParticipant"; - - public LiftingParticipantTransformation(ClassLoader loader, SharedState state) { super(loader, state); } - - public void doTransformCode(ClassGen cg) - { - if (!classNeedsTeamExtensions(cg)) return; - - synchronized (LiftingParticipantTransformation.class) { - try { - checkInitParticipant(); - } catch (Exception e) { - new IllegalArgumentException("Lifting participant "+PARTICIPANT_NAME+" is invalid.", e).printStackTrace(); - PARTICIPANT_NAME = null; - } - if (PARTICIPANT_NAME == null) - return; - } - - factory = new InstructionFactory(cg); - ConstantPoolGen cpg = cg.getConstantPool(); - String class_name = cg.getClassName(); - - // FIXME(SH): evaluate inclusion/exclusion filter per className - - Method[] methods = cg.getMethods(); - for (int i=0; i<methods.length; i++) { - Method m = methods[i]; - if (!m.getName().startsWith(LIFT_PREFIX)) - continue; - - cg.replaceMethod(m, m = weaveLiftingParticipant(m, class_name, cpg)); - } - } - - private void checkInitParticipant() throws Exception { - if (checked) return; - checked = true; - - Field participantField = Team.class.getField(LIFTING_PARTICIPANT_FIELD); - Object participant = participantField.get(null); - - if (PARTICIPANT_NAME != null) - { - // initialize from property "ot.lifting.participant" - if (participant != null) - throw new IllegalStateException("liftingParticipant already installed."); - // install a shared instance into class Team: - Class<?> participantClass = loader.loadClass(PARTICIPANT_NAME); - participantField.set(null, participantClass.newInstance()); - } - else if (participant != null) - { - // field was already initialized by a third party - - // fetch the class name to signal that transformations are needed. - PARTICIPANT_NAME = participant.getClass().getName(); - } - } - - private Method weaveLiftingParticipant(Method m, String className, ConstantPoolGen cpg) { - MethodGen mg = newMethodGen(m, className, cpg); - InstructionList il = mg.getInstructionList(); - InstructionHandle[] ihs = il.getInstructionHandles(); - for (int i=0; i<ihs.length; i++) { - InstructionHandle ih = ihs[i]; - if (ih.getInstruction() instanceof NEW) - { - NEW newInstr = (NEW) ih.getInstruction(); - Type newType = newInstr.getType(cpg); - String newTypeName = newType.toString(); - - // don't transform creation of these exceptions: - if (newTypeName.equals(LIFTING_FAILED_EXCEPTION)) continue; - if (newTypeName.equals(LIFTING_VETO_EXCEPTION)) continue; - if (newTypeName.equals(WRONG_ROLE_EXCEPTION)) continue; - - ih.setInstruction(new NOP()); // keep this handle for the enclosing switch - - InstructionList inset = new InstructionList(); - // fetch instance of lifting participant from Team._OT$liftingParticipant - inset.append(factory.createFieldAccess(teamClassType.getClassName(), - LIFTING_PARTICIPANT_FIELD, - iLiftingParticipant, - Constants.GETSTATIC)); - inset.append(new ALOAD(0)); // load the team - inset.append(new ALOAD(1)); // load the base - inset.append(new LDC(cpg.addString(newTypeName))); // load the role class name - inset.append(factory.createInvoke(iLiftingParticipant.getClassName(), // receiver type - CREATE_ROLE_METHOD, // method - object, // return type - new Type[] {teamType, object, string},// arg types - Constants.INVOKEINTERFACE)); - inset.append(new DUP()); // keep value after null-check - BranchInstruction isNull = new IFNULL(null); - inset.append(isNull); - inset.append(factory.createCast(object, newType)); - // let goto skip: 0: new R, 1: dup, 2: aload_0, 3: aload_1, (4: cast if needed), 4: o. 5: invokespecial<init> - int invokeOffset = 4; - if (!(ihs[i+invokeOffset].getInstruction() instanceof INVOKESPECIAL)) - invokeOffset++; - inset.append(new GOTO(ihs[i+invokeOffset+1])); // one past above sequence - - // continue here if null, i.e., perform the original new-instruction - InstructionHandle goOn = inset.append(new POP()); // discard dup'ed value from above - isNull.setTarget(goOn); - inset.append(newInstr); // re-insert deleted first instruction - - il.append(ih, inset); - } - } - return mg.getMethod(); - } -} diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/OTConstants.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/OTConstants.java deleted file mode 100644 index fb2acfa9e..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/OTConstants.java +++ /dev/null @@ -1,181 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2002-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: OTConstants.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre; - -import org.apache.bcel.generic.*; - - -/** - * Constants for the Object Teams Runtime Environment - * @author Christine Hundt - * @author Stephan Herrmann - */ -public interface OTConstants { - // ------------------------------------------ - // ---------- Types: ------------------------ - // ------------------------------------------ - /** Type <tt>java.lang.Object</tt> */ - ObjectType object = new ObjectType("java.lang.Object"); - /** Type <tt>java.lang.Object</tt> */ - ObjectType string = new ObjectType("java.lang.String"); - /** Type <tt>java.lang.Class</tt> */ - ObjectType classType = new ObjectType("java.lang.Class"); - /** Signature of java.lang.Class#getMethod(String, Class...) */ - public static final Type[] getMethodSignature = new Type[]{string, new ArrayType(classType, 1)}; - /** Type <tt>java.lang.reflect.Method</tt> */ - ObjectType methodType = new ObjectType("java.lang.reflect.Method"); - /** Type <tt>org.objectteams.Team</tt> */ - String teamName = "org.objectteams.ITeam"; - ObjectType teamType = new ObjectType(teamName); - String teamClassName = "org.objectteams.Team"; - ObjectType teamClassType = new ObjectType(teamClassName); - /** Type <tt>org.objectteams.LiftingVetoException</tt> */ - ObjectType liftingVeto = new ObjectType("org.objectteams.LiftingVetoException"); - /** Type <tt>org.eclipse.objectteams.otre.OTREInternalError</tt> */ - ObjectType internalError = new ObjectType("org.eclipse.objectteams.otre.OTREInternalError"); - /** Type <tt>org.objectteams.ResultNotProvidedError</tt> */ - ObjectType notProvidedError = new ObjectType("org.objectteams.ResultNotProvidedError"); - /** Type <tt>org.objectteams.UnsupportedFeatureException</tt> */ - ObjectType unsupportedFeature = new ObjectType("org.objectteams.UnsupportedFeatureException"); - - ObjectType threadType = new ObjectType("java.lang.Thread"); - - /** Type <tt>org.objectteams.Team[]</tt> */ - ArrayType teamArray = new ArrayType(teamType, 1); - /** Type <tt>int[]</tt> */ - ArrayType intArray = new ArrayType(Type.INT, 1); - /** Type <tt>java.lang.Object[]</tt> */ - ArrayType objectArray = new ArrayType(object, 1); - - ObjectType roleSetType = new ObjectType("java.util.HashSet"); - - ObjectType nullPointerException = new ObjectType("java.lang.NullPointerException"); - - String STRING_BUFFER_NAME = "java.lang.StringBuffer"; - - // ============ VERSION: ============== - public static final int OT_VERSION_MAJOR = 0; - public static final int OT_VERSION_MINOR = 8; - public static final int OT_REVISION = 18; - - // required compiler revision in the 0.9 stream: - public static final int OT09_REVISION = 26; - - // required compiler revision in the 1.0 stream: - public static final int OT10_REVISION = 0; - - // required compiler revision in the 1.1 stream: - public static final int OT11_REVISION = 0; - - // required compiler revision in the 1.2 stream: - public static final int OT12_REVISION = 0; - - // required compiler revision in the 1.3 stream: - public static final int OT13_REVISION = 0; - - // required compiler revision in the 1.4 stream: - public static final int OT14_REVISION = 1; - - // required compiler revision in the 1.5 stream: - public static final int OT15_REVISION = 0; - - // ------------------------------------------ - // ---------- Flags and Modifiers: ---------- - // ------------------------------------------ - /** Bytecode encoding of modifier <tt>team</tt> */ - final static int TEAM = 0x8000; - - // 'CallinFlags': - final static int OVERRIDING =1; // this role method is inherited from the super role - final static int WRAPPER =2; // this is a role method wrapper (in a team) - - // ------------------------------------------ - // ---------- Names: ------------------------ - // ------------------------------------------ - /** General prefix to mark all generated names. */ - final static String OT_PREFIX = "_OT$"; - /** Name of the base reference of roles. */ - final static String BASE = "_OT$base"; - /** Name of the getBase method of roles (ifc and class). */ - final static String GET_BASE = "_OT$getBase"; - /** Prefix for otdt. */ - final static String OTDT_PREFIX = "__OT__"; - /** Tsuper marker interface prefix. */ - final static String TSUPER_PREFIX = "TSuper__OT__"; - /** field for storing the class object in JVM < 5 */ - final static String SELF_CLASS = "_OT$self_class$"; - - // ----------------------------------------- - // ---------- Signature enhancement -------- - // ----------------------------------------- - - /** Name of synthetic parameter. */ - final static String TEAMS = "_OT$teams"; - /** Name of synthetic parameter. */ - final static String TEAMIDS = "_OT$teamIDs"; - /** Name of synthetic parameter. */ - final static String IDX = "_OT$idx"; - /** Name of synthetic parameter. */ - final static String BIND_IDX = "_OT$bindIdx"; - /** Name of synthetic parameter. */ - final static String UNUSED = "_OT$unusedArgs"; - /** Name of synthetic parameter. */ - final static String BASE_METH_TAG = "_OT$baseMethTag"; - - /** Number of extra arguments in enhanced signatures. */ - static final int EXTRA_ARGS = 6; - /** Position of generated argument. */ - static final int TEAMS_ARG = 1; - /** Position of generated argument. */ - static final int TEAMIDS_ARG = 2; - /** Position of generated argument. */ - static final int IDX_ARG = 3; - /** Position of generated argument. */ - static final int BIND_IDX_ARG = 4; - /** Position of generated argument. */ - static final int BASE_METH_ARG = 5; // ## really const? also UNUSED? - /** Position of generated argument. */ - static final int UNUSED_ARG = 6; - - // ---------- Features to prevent/aid garbage collection: ---------- - String ROLE_SET = OT_PREFIX + "roleSet"; // field HashSet _OT$roleSet; - String ADD_ROLE = OT_PREFIX + "addRole"; // method void _OT$addRole(Object) - String REMOVE_ROLE = OT_PREFIX + "removeRole"; // method void _OT$removeRole(Object) - - String IBOUND_BASE = "org.objectteams.IBoundBase"; // interface comprising the above methods. - - - // ----------------------------------------- - // ---------- Other constants -------- - // ----------------------------------------- - /** Marker for comment lines in the team config file. */ - static final String COMMENT_MARKER = "#"; - /** Constant for invalid base method tags (a method can not be relocated from a base call). */ - static final int INVALID_BASE_METHOD_TAG = -2; - - // -------------------------------------------------------------- - // ---------- Separator for static replace binding keys --------- - // -------------------------------------------------------------- - static final String STATIC_REPLACE_BINDING_SEPARATOR = ".."; - - // ------------------------------------------------------------------------------------ - // ---------- Linenumbers with more information. ---------------------- - // ---------- (semantic linenumber) For debugging purpose. ------ - // ------------------------------------------------------------------------------------ - static final int STEP_OVER_LINENUMBER = Short.MAX_VALUE *2; - static final int STEP_INTO_LINENUMBER = STEP_OVER_LINENUMBER - 1; -} diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/OTREInternalError.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/OTREInternalError.java deleted file mode 100644 index 04110e261..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/OTREInternalError.java +++ /dev/null @@ -1,62 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2003-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id$ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre; - -/** - * @author stephan - */ -public class OTREInternalError extends Error { - - /** - * - */ - private static final long serialVersionUID = 1L; - private static final String _bugmsg = - "An error occurred in the Object Teams runtime environment.\n"+ - "We would appreciate if you send a bug report to bugs@ObjectTeams.org.\n"+ - "Please include your program (if possible) and the following diagnostic\n"+ - "in your report. -- Thank you. The OT/J developers\n"; - /** - * - */ - public OTREInternalError() { - super(_bugmsg); - } - - /** - * @param message - */ - public OTREInternalError(String message) { - super(_bugmsg+message); - } - - /** - * @param cause - */ - public OTREInternalError(Throwable cause) { - super(_bugmsg+cause.toString()); - } - - /** - * @param message - * @param cause - */ - public OTREInternalError(String message, Throwable cause) { - super(_bugmsg+message+cause.toString()); - } - -} diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/ObjectTeamsTransformation.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/ObjectTeamsTransformation.java deleted file mode 100644 index b569a96fb..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/ObjectTeamsTransformation.java +++ /dev/null @@ -1,2266 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2002-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: ObjectTeamsTransformation.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre; - -import java.io.BufferedReader; -import java.io.FileInputStream; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; - -import org.eclipse.objectteams.otre.util.AnnotationHelper; -import org.eclipse.objectteams.otre.util.AttributeReadingGuard; -import org.eclipse.objectteams.otre.util.CallinBindingManager; -import org.eclipse.objectteams.otre.util.RoleBaseBinding; - -import org.apache.bcel.Constants; -import org.apache.bcel.classfile.Attribute; -import org.apache.bcel.classfile.Constant; -import org.apache.bcel.classfile.ConstantUtf8; -import org.apache.bcel.classfile.InnerClass; -import org.apache.bcel.classfile.InnerClasses; -import org.apache.bcel.classfile.JavaClass; -import org.apache.bcel.classfile.LineNumberTable; -import org.apache.bcel.classfile.Method; -import org.apache.bcel.classfile.StackMap; -import org.apache.bcel.classfile.Unknown; -import org.apache.bcel.generic.*; - -/** - * Superclass for all transformations in this package. - * This class and its subclasses does not directly depend on JPLIS. - * - * Contains common fields and methods. - * - * @author Christine Hundt - * @author Stephan Herrmann - */ -public abstract class ObjectTeamsTransformation - implements OTConstants -{ - - // ------------------------------------------ - // ---------- Flags: ------------------------ - // ------------------------------------------ - - /** Check whether <tt>flags</tt> denote a generated callin wrapper. */ - static boolean isCallinWrapper(Method m, ClassGen cg) { - return methodHasCallinFlags(m, cg, WRAPPER); - } - - /** Check whether <tt>flags</tt> denote a callin method from the source code. */ - static boolean isCallin(Method m, ClassGen cg) { - return (methodHasCallinFlags(m, cg, 0) && !isCallinWrapper(m, cg)); - } - - - // ------------------------------------------ - // ---------- Names: ------------------------ - // ------------------------------------------ - - /** Generate the name for a backup of a method. */ - static String genOrigMethName(String methName) { - return "_OT$" + methName + "$orig"; - } - - /** Generate the name for a chaining wrapper. */ - static String genChainMethName(String methName) { - return "_OT$" + methName + "$chain"; - } - - static ArrayList<ObjectTeamsTransformation> reentrentTransformations = new ArrayList<ObjectTeamsTransformation>(); - - /** Common factory for all tranformers. - * To be initialized once we get a class for transformation. */ - InstructionFactory factory; - - /** State shared among all instances that work for the same class loader. */ - public static class SharedState { - /** ArrayList of classes whose interfaces have already been transformed by this transformer/classloader combo. */ - ArrayList<String> interfaceTransformedClasses = new ArrayList<String>(); - } - /** Reference to the shared state of transformers. */ - final SharedState state; - - SharedState state() { - return state; - } - - /** Which class loader are we working for? */ - protected ClassLoader loader; - - public ObjectTeamsTransformation(ClassLoader loader, SharedState state) { - this.loader = loader; - this.state = state; - } - - // ------------------------------------------ - // ---------- Logging: ---------------------- - // ------------------------------------------ - /** Initialized from property <tt>ot.log</tt>. */ - static boolean logging = false; - - static { - if(System.getProperty("ot.log") != null) - logging = true; - } - - /** Print <tt>message</tt> only if <tt>logging</tt> is true. */ - public static void printLogMessage(String message) { - System.out.println(message); - } - - // ------------------------------------------ - // ---------- use the following file as config file for additional active teams: -------- - // ------------------------------------------ - /** Initialized from property <tt>ot.teamconfig</tt>. */ - - static String TEAM_CONFIG_FILE = null; - - static { - TEAM_CONFIG_FILE = System.getProperty("ot.teamconfig"); - } - - // ------------------------------------------ - // ---------- Compatibility with different compiler versions: -------- - // ------------------------------------------ - - // compiler 1.2.4 introduces isSuperAccess flag for basecall surrogate: - protected static boolean IS_COMPILER_GREATER_123 = false; - - protected static boolean IS_COMPILER_13X_PLUS = false; - - protected static boolean IS_COMPILER_14X_PLUS = false; - - // ------------------------------------------ - // ---------- This flag must currently be true for OT/Equinox: ---------------------- - // ------------------------------------------ - /** Initialized from property <tt>ot.equinox</tt>. */ - public static boolean WORKAROUND_REPOSITORY = false; - - static { - if(System.getProperty("ot.equinox") != null) - WORKAROUND_REPOSITORY = true; - } - - // ------------------------------------------ - // ---------- Debugging: ---------------------- - // ------------------------------------------ - /** Initialized from property <tt>ot.debug</tt>. */ - static boolean debugging = false; - - static { - if(System.getProperty("ot.debug") != null) - debugging = true; - } - - // ------------------------------------------------------- - // ---------- Modes for implicit team activateion -------- - // ------------------------------------------------------- - enum ImplicitActivationMode { NEVER, ANNOTATED, ALWAYS } - static ImplicitActivationMode implicitActivationMode = ImplicitActivationMode.ANNOTATED; - static { - String prop = System.getProperty("ot.implicit.team.activation"); - for (ImplicitActivationMode mode : ImplicitActivationMode.values()) { - if (mode.name().equals(prop)) { - implicitActivationMode = mode; - break; - } - } - } - - // ----------------------------------------- - // ---------- Signature enhancement -------- - // ----------------------------------------- - - /** - * Prepend hidden arguments to the signature. - * This methods only treats argument names. - * @see #enhanceArgumentTypes - * The arguments are: - * <dl> - * <dt><tt>Team[] _OT$teams</tt></dt> - * <dd>array of active Teams affecting the current base method. - * <dt><tt>int[] _OT$teamIDs</tt></dt> - * <dd>array of IDs of the above Teams. - * <dt><tt>int _OT$idx</tt></dt> - * <dd>index into above arrays: the Team currently being processed. - * <dt><tt>Object[] _OT$unusedArgs</tt></dt> - * <dd>array of arguments which are unused by the current role method. - * </dl> - * @param argumentNames array of original argument names. - * @return augmented array of argument names. - */ - static String[] enhanceArgumentNames(String[] argumentNames) { - return enhanceArgumentNames(argumentNames, 0); - } - - /** - * Prepend hidden arguments to the signature. - * This methods only treats argument names. - * @see #enhanceArgumentTypes - * The arguments are: - * <dl> - * <dt><tt>Team[] _OT$teams</tt></dt> - * <dd>array of active Teams affecting the current base method. - * <dt><tt>int[] _OT$teamIDs</tt></dt> - * <dd>array of IDs of the above Teams. - * <dt><tt>int _OT$idx</tt></dt> - * <dd>index into above arrays: the Team currently being processed. - * <dt><tt>Object[] _OT$unusedArgs</tt></dt> - * <dd>array of arguments which are unused by the current role method. - * </dl> - * @param argumentNames array of original argument names. - * @param idx position where new arguments should be inserted into - * <tt>originalArgumentTypes</tt>. - * @return augmented array of argument names. - */ - static String[] enhanceArgumentNames(String[] argumentNames, int idx) { - - String[] enhancedArgumentNames = - new String[argumentNames.length + EXTRA_ARGS]; - - for (int j=0; j<idx; j++) - enhancedArgumentNames[j] = argumentNames[j]; - - enhancedArgumentNames [idx + TEAMS_ARG - 1] = TEAMS; - enhancedArgumentNames [idx + TEAMIDS_ARG - 1] = TEAMIDS; - enhancedArgumentNames [idx + IDX_ARG - 1] = IDX; - enhancedArgumentNames [idx + BIND_IDX_ARG - 1] = BIND_IDX; - enhancedArgumentNames [idx + BASE_METH_ARG - 1] = BASE_METH_TAG; - enhancedArgumentNames [idx + UNUSED_ARG - 1] = UNUSED; - - for (int j = idx; j < argumentNames.length; j++) - enhancedArgumentNames[j + EXTRA_ARGS] = argumentNames[j]; - - return enhancedArgumentNames; - } - - /** - * @see #enhanceArgumentTypes(Type[]) - * @param signature String from which to extract the argument types. - * @return - */ - static Type[] enhanceArgumentTypes(String signature) { - Type[] types = Type.getArgumentTypes(signature); - return enhanceArgumentTypes(types); - } - - /** - * Prepend hidden arguments to the signature. - * This methods only treats argument types. - * @see #enhanceArgumentNames - * - * @param originalArgumentTypes array of original argument types. - * @return augmented array of argument names. - */ - static Type[] enhanceArgumentTypes(Type[] originalArgumentTypes) { - return enhanceArgumentTypes(originalArgumentTypes, 0, true); - } - - /** - * Prepend hidden arguments to the signature. - * This methods only treats argument types. - * @see #enhanceArgumentNames - * - * @param originalArgumentTypes array of original argument types. - * @param idx position where new arguments should be inserted into - * <tt>originalArgumentTypes</tt>. - * @param createUnused should the <tt>unusedArgs</tt> argument be created? - * @return augmented array of argument types. - */ - static Type[] enhanceArgumentTypes(Type[] originalArgumentTypes, - int idx, - boolean createUnused) - { - // creates enhanced argument type array: - // ..(a1,.., aN) -> ..(Team[], int[], int, Object[], a1, .., aN) - int offset = createUnused ? EXTRA_ARGS : EXTRA_ARGS-1; - - Type[] enhancedArgumentTypes = - new Type[originalArgumentTypes.length+offset]; - - for (int j=0; j<idx; j++) - enhancedArgumentTypes[j] = originalArgumentTypes[j]; - - enhancedArgumentTypes [idx+TEAMS_ARG - 1] = teamArray; - enhancedArgumentTypes [idx+TEAMIDS_ARG - 1] = intArray; - enhancedArgumentTypes [idx+IDX_ARG - 1] = Type.INT; - enhancedArgumentTypes [idx+BIND_IDX_ARG - 1] = Type.INT; - enhancedArgumentTypes [idx+BASE_METH_ARG - 1] = Type.INT; - if (createUnused) { - enhancedArgumentTypes [idx+UNUSED_ARG - 1] = objectArray; - } - - for (int j = idx; j < originalArgumentTypes.length; j++) - enhancedArgumentTypes[j + EXTRA_ARGS] = originalArgumentTypes[j]; - - return enhancedArgumentTypes; - } - - /** - * Remove the arguments previously added by - * {@link #enhanceArgumentTypes enhanceArgumentTypes}. - * - * @param enhancedArgumentTypes - * @param staticFlag - * @return - */ - // FIXME(SH): obsolete - public static Type[] _retrenchArgumentTypes(Type[] enhancedArgumentTypes, boolean staticFlag) { - // create retrenched argument type array: - // ..(Team[], int[], int, Object[], a1, .., aN) -> ..(a1,.., aN) - - int offset = staticFlag? -1 : 0; - - Type[] retrenchedArgumentTypes = - new Type[enhancedArgumentTypes.length - EXTRA_ARGS + offset]; - - for (int j = EXTRA_ARGS; j < enhancedArgumentTypes.length + offset; j++) - retrenchedArgumentTypes[j - EXTRA_ARGS] = enhancedArgumentTypes[j]; - - return retrenchedArgumentTypes; - } - - // --------------------------------------------------- - // ---------- further type and value conversions ----- - // --------------------------------------------------- - - /** - * @see #generalizeReturnType(Type) - * @param signature String from which to extract the return type. - */ - static Type generalizeReturnType (String signature) { - Type type = Type.getReturnType(signature); - return generalizeReturnType(type); - } - - /** - * Given a return type, determine a reference type to which this type can be - * converted. "Object" if type is VOID. - * - * @param type - * @return - */ - static Type generalizeReturnType (Type type) { - if (type instanceof ReferenceType) return type; - return object; - } - - /** - * Get the generalized return type from <tt>sign1</tt>, unless - * <tt>sing2</tt> has void return type. In the latter case return - * <tt>Object</tt>. - * - * @see #generalizeReturnType(Type) - * @param sign1 - * @param sign2 - * @return - */ - static Type generalizeReturnType (String sign1, String sign2) { - Type type = Type.getReturnType(sign2); - if (type == Type.VOID) return object; - return generalizeReturnType(sign1); - } - - /** - * Assuming a value of type <tt>oldType</tt> on the stack, convert it to a - * value of type <tt>newType</tt>. Changes instruction list <tt>il</tt> - * after position <tt>ih</tt> or at its end if <tt>ih</tt> is null. - * - * @param il - * @param ih - * @param oldType - * @param newType - * @return the first inserted instruction or null if no adjustment needed - */ - InstructionHandle adjustValue (InstructionList il, InstructionHandle ih, - Type oldType, Type newType) { - if (ih == null) - ih = il.getEnd(); - if (oldType.equals(newType)) - return null; - - if (newType == Type.VOID) - return il.append(ih, new POP()); - else if (oldType == Type.VOID) - return il.append(ih, InstructionFactory.ACONST_NULL); - else if (oldType instanceof BasicType) - return il.append(ih, createBoxing((BasicType)oldType)); - else if (newType instanceof BasicType) - return il.append(ih, createUnboxing((BasicType)newType)); - else - return il.append(ih, factory.createCast(oldType, newType)); - } - - // ------------------------------------------ - // ---------- (Un-)Boxing: ------------------ - // ------------------------------------------ - - /** - * Get the name of the class suitable for boxing <tt>basicType</tt>. - * - * @param basicType - * @return - */ - static String toObjectTypeName(BasicType basicType) { - String result = ""; - switch (basicType.getType()) { - case Constants.T_BOOLEAN : result = "java.lang.Boolean"; break; - case Constants.T_INT : result = "java.lang.Integer"; break; - case Constants.T_FLOAT : result = "java.lang.Float"; break; - case Constants.T_DOUBLE : result = "java.lang.Double"; break; - case Constants.T_SHORT : result = "java.lang.Short"; break; - case Constants.T_BYTE : result = "java.lang.Byte"; break; - case Constants.T_CHAR : result = "java.lang.Character"; break; - case Constants.T_LONG : result = "java.lang.Long"; break; - default: throw new Error("OTRE failure: Basic Type not supported!!"+basicType); - } - return result; - } - - /** - * Create the instructions needed for boxing a basic type value. The value - * is expected on the stack an will be replaced by the boxed value. - * - * @param basicType type of the value on the stack. - * @return an InstructionList containing the conversion instructions. - */ - InstructionList createBoxing(BasicType basicType) { - InstructionList il = new InstructionList(); - String boxedTypeName = toObjectTypeName(basicType); - // .., result - il.append(factory.createNew(boxedTypeName)); // .., result, box, - - if (basicType.equals(Type.DOUBLE) || basicType.equals(Type.LONG)) { - // 'double' and 'long' are category 2 computational type: - il.append(new DUP_X2()); // .., box, result, box - il.append(new DUP_X2()); // .., box, box, result, box - } else { - il.append(new DUP_X1()); // .., box, result, box - il.append(new DUP_X1()); // .., box, box, result, box - } - il.append(new POP()); // .., box, box, result - il.append(factory.createInvoke(boxedTypeName, - Constants.CONSTRUCTOR_NAME, - Type.VOID, - new Type[] { basicType }, - Constants.INVOKESPECIAL)); - return il; - } - - /** - * Create the instructions needed for unboxing a basic type value. The value - * is expected on the stack an will be replaced by the unboxed value. - * - * @param basicType expected type after unboxing. - * @return an InstructionList containing the conversion instructions. - */ - InstructionList createUnboxing(BasicType basicType) { - InstructionList il = new InstructionList(); - String boxedTypeName = toObjectTypeName(basicType); - il.append(factory.createCast(object, - new ObjectType(boxedTypeName))); - il.append(factory.createInvoke(boxedTypeName, - basicType.toString() + "Value", - basicType, - Type.NO_ARGS, - Constants.INVOKEVIRTUAL)); - return il; - } - - /** Push an integer constant using the most appropriate/compact instruction. */ - Instruction createIntegerPush(ConstantPoolGen cpg, int val) { - if (val <= 5) - return new ICONST(val); - if (val <= Byte.MAX_VALUE) - return new BIPUSH((byte)val); - if (val <= Short.MAX_VALUE) - return new SIPUSH((short)val); - return new LDC(cpg.addInteger(val)); - } - - /** - * Create a throwing instruction for an OTREInternalError. - * - * @param cpg - * @param il instruction list to generate into - * @param messagePush push sequence producing the exception message. - * @return handle to the first generated instruction - */ - InstructionHandle createThrowInternalError(ConstantPoolGen cpg, InstructionList il, InstructionList messagePush) { - InstructionHandle start = il.append(factory.createNew(OTConstants.internalError)); - il.append(new DUP()); - il.append(messagePush); - il.append(factory.createInvoke(OTConstants.internalError.getClassName(), - Constants.CONSTRUCTOR_NAME, - Type.VOID, - new Type[] { Type.STRING }, - Constants.INVOKESPECIAL)); - il.append(new ATHROW()); - return start; - } - - /** - * Create a lookswitch from its constituents. Since JVM 1.4 this requires - * sorting of matches. - * - * @param matches - * @param targets - * @param breaks an array of breaks (GOTOs) whose target will - * be updated to point to <tt>afterSwitch</tt> - * @param defaultBranch - * @param afterSwitch - * @return the generated instruction. - */ - static BranchInstruction createLookupSwitch (int[] matches, - InstructionHandle[] targets, - GOTO[] breaks, - InstructionHandle defaultBranch, - InstructionHandle afterSwitch) { - - int numberOfCases = matches.length; - for (int i = 0; i < numberOfCases; i++) - breaks[i].setTarget(afterSwitch); - - HashMap<Integer, InstructionHandle> match_target_mapping = new HashMap<Integer, InstructionHandle>(); - for (int i = 0; i < numberOfCases; i++) - match_target_mapping.put(Integer.valueOf(matches[i]), targets[i]); - - Arrays.sort(matches); - for (int i = 0; i < numberOfCases; i++) - targets[i] = match_target_mapping.get(Integer.valueOf(matches[i])); - - BranchInstruction inst = new LOOKUPSWITCH(matches, targets, defaultBranch); - return inst; - } - - - /** - * Read all byte code attributes for a given class. Side-Effect: depending - * on the Referenced-Team attribute, additional classes may be scheduled for - * loading. - * - * @param ce - * @param cg - * @param class_name - * @param cpg - */ - public void checkReadClassAttributes(ClassEnhancer ce, - ClassGen cg, - String class_name, - ConstantPoolGen cpg) - { - AttributeReadingGuard guard = AttributeReadingGuard.getInstanceForLoader(this.loader); - boolean addTeamInitializations = false; - List<String> classesToLoad; - synchronized (guard) { - if (!guard.iAmTheFirst(class_name)) - return; - if (AttributeReadingGuard.isFirstLoadedClass()) - addTeamInitializations = true; - // scan for attributes here, because this transformer is applied first: - Attribute[] attrsClass = cg.getAttributes(); - classesToLoad = scanClassOTAttributes(attrsClass, class_name, cpg, cg); - - guard.workDone(class_name); - } - if (addTeamInitializations) - addTeamInitializations(cg, ce); - - Iterator<String> it = classesToLoad.iterator(); - while (it.hasNext()) { - String next = it.next(); - if(logging) printLogMessage("Loading of class " + next + " will be forced now!"); - ce.loadClass(next, this); - } - - // scan for parameter bindings: - Method[] possibleRoleMethods = cg.getMethods(); - for (int i=0; i<possibleRoleMethods.length; i++) { - Method meth = possibleRoleMethods[i]; - Attribute[] attrsMethod = meth.getAttributes(); - scanMethodOTAttributes(attrsMethod, class_name, meth.getName(), cpg); - } - if(logging) printLogMessage(this.getClass().getName() - + " picked up the attributes for class " + class_name ); - } - - // --- helpers for adding line numbers at the front of a method --- - // unfortunately BCEL does not sort line numbers, but the debugger expects them sorted. - class Pair<F,S> { - F first; - S second; - Pair(F f, S s) { - this.first = f; - this.second = s; - } - } - @SuppressWarnings("unchecked") // can't declare array of generics - Pair<InstructionHandle, Integer>[] saveLineNumbers(MethodGen method, ConstantPoolGen cpg) { - LineNumberTable lnt = method.getLineNumberTable(cpg); - InstructionHandle[] ihs = method.getInstructionList().getInstructionHandles(); - Pair<InstructionHandle, Integer>[] oldLines = new Pair[lnt.getTableLength()]; - { - int cur = -1; - int n = 0; - for (int i=0; i<ihs.length; i++) { - int next = lnt.getSourceLine(ihs[i].getPosition()); - if (next > cur) // reached a new source line - oldLines[n++] = new Pair<InstructionHandle, Integer>(ihs[i], new Integer(next)); - cur = next; - } - } - return oldLines; - } - /** Append the saved line numbers to the end of the method's line number table. */ - void restoreLineNumbers(MethodGen method, Pair<InstructionHandle, Integer>[] oldLines) { - for (int i=0; i<oldLines.length; i++) { - if (oldLines[i] == null) - continue; - InstructionHandle ih = oldLines[i].first; - int line = oldLines[i].second.intValue(); - method.addLineNumber(ih, line); - } - } - - /** - * Adds team initialization for all teams in the config file. - * - * @param cg - * @param ce - */ - private void addTeamInitializations(ClassGen cg, ClassEnhancer ce) { - String main_class_name = cg.getClassName(); - ConstantPoolGen cpg = cg.getConstantPool(); - InstructionFactory factory = new InstructionFactory(cpg); - Method main = cg.containsMethod("main", "([Ljava/lang/String;)V"); - if (main == null) { - // JPLIS launching may intercept system classes before the custom main. - // reset the guard in order to retry with subsequent classes. - AttributeReadingGuard.reset(); - return; // no main method in the first loaded class... - } - - MethodGen mainMethod = newMethodGen(main, main_class_name, cpg); - InstructionList il = mainMethod.getInstructionList(); - - int startLine = -1; - Pair<InstructionHandle,Integer>[] oldLines = null; - if (debugging) { - LineNumberTable lnt = mainMethod.getLineNumberTable(cpg); - if (lnt != null) { - startLine = lnt.getSourceLine(0); - oldLines = saveLineNumbers(mainMethod, cpg); - } - } - - if (TEAM_CONFIG_FILE != null) { - - InstructionList teamInitializations = new InstructionList(); - List<String> teamsToInitialize = getTeamsFromConfigFile(); - Iterator<String> teamIt = teamsToInitialize.iterator(); - while (teamIt.hasNext()) { - String nextTeam = teamIt.next(); - JavaClass teamClass = null; - try { - teamClass = RepositoryAccess.lookupClass(nextTeam); - } catch (ClassNotFoundException cfne) { - System.err.println("Config error: Team class '"+nextTeam+ "' in config file '"+ TEAM_CONFIG_FILE+"' can not be found!"); - System.err.println("Main class = "+main_class_name+ - ", class loader = "+(this.loader!=null?this.loader.getClass().getName():"null")+ - ", transformer = "+this.getClass().getName()); - continue; - } - ClassGen teamClassGen = new ClassGen(teamClass); - if (teamClassGen.containsMethod(Constants.CONSTRUCTOR_NAME, "()V") == null) { - System.err.println("Activation failed: Team class '"+nextTeam+ "' has no default constuctor!"); - continue; - } - ce.loadClass(nextTeam, this); - if (logging) - printLogMessage("Adding initialization of team " + nextTeam - + " to main method of class " + main_class_name); - teamInitializations.append(factory.createNew(nextTeam)); - teamInitializations.append(new DUP()); - teamInitializations.append(factory.createInvoke(nextTeam, - Constants.CONSTRUCTOR_NAME, - Type.VOID, - Type.NO_ARGS, - Constants.INVOKESPECIAL)); - teamInitializations.append(factory.createGetStatic(OTConstants.teamClassName, - "ALL_THREADS", - OTConstants.threadType)); - teamInitializations.append(factory.createInvoke(nextTeam, - "activate", - Type.VOID, - new Type[] {OTConstants.threadType}, - Constants.INVOKEVIRTUAL)); - } - il.insert(teamInitializations); - } - // register main thread with TeamThreadManager: - InstructionHandle cursor; - cursor = il.insert(new ICONST(1)); // isMain=true - cursor = il.append(cursor, new ACONST_NULL()); // parent=null - cursor = il.append(cursor, factory.createInvoke("org.objectteams.TeamThreadManager", - "newThreadStarted", - Type.BOOLEAN, - new Type[]{Type.BOOLEAN, OTConstants.threadType}, - Constants.INVOKESTATIC)); - cursor = il.append(cursor, new POP()); // don't use boolean return - - il.setPositions(); - if (debugging && startLine > 0) { - mainMethod.removeLineNumbers(); // fresh start, to ensure correct order - mainMethod.addLineNumber(il.getStart(), startLine-1); // new number to the front - restoreLineNumbers(mainMethod, oldLines); // append old numbers - } - mainMethod.setInstructionList(il); - mainMethod.setMaxStack(); - mainMethod.setMaxLocals(); - - cg.replaceMethod(main, mainMethod.getMethod()); - } - - /** - * @return a list of teams in the team initialization config file - */ - private static List<String> getTeamsFromConfigFile() { - List<String> result = new LinkedList<String>(); - try { - FileInputStream fstream = new FileInputStream(TEAM_CONFIG_FILE); - BufferedReader in = new BufferedReader(new InputStreamReader(fstream)); - while (in.ready()) { - String nextLine = in.readLine(); - String nextTeam = nextLine.trim(); - if (nextTeam.startsWith(COMMENT_MARKER)) - continue; // this is a comment line - if (!nextTeam.equals("")) { - result.add(nextTeam.trim()); - } - } - in.close(); - } catch (Exception e) { - System.err.println("File input error: config file '" + TEAM_CONFIG_FILE + "' can not be found!"); - } - return result; - } - - // ------------------------------------------------------------------------------------------------- - // -------- store and return adapted bases for OT/Equinox -------------- - // this data is collected by scanClassOTAttributes and must be collected by the caller - // before processing the next class. - // ------------------------------------------------------------------------------------------------- - public HashSet<String> adaptedBases = new HashSet<String>(); - - /** Internal API for {@link org.eclipse.objectteams.otre.jplis.ObjectTeamsTransformer} */ - public Collection<String> fetchAdaptedBases() { - HashSet<String> result; - result = new HashSet<String>(adaptedBases); - adaptedBases.clear(); - return result; - } - - // ------------------------------------------------------------------------------------------------- - /** - * Container for base method properties - */ - public static class BaseMethodInfo { - private String baseClassName; - private String baseMethodName; - private String baseMethodSignature; - boolean isCallin; - private boolean isRoleMethod; - boolean isStatic; - private int[] parameterPositions; - int translationFlags; - - BaseMethodInfo(String base_class_name, String base_method_name, - String base_method_signature, boolean isCallin, - boolean isRoleMethod, boolean isStatic, - int[] parameter_positions, int translationFlags) - { - this.baseClassName = base_class_name; - this.baseMethodName = base_method_name; - this.baseMethodSignature = base_method_signature; - this.isCallin = isCallin; - this.isRoleMethod = isRoleMethod; - this.isStatic = isStatic; - this.parameterPositions = parameter_positions; - this.translationFlags = translationFlags; - } - /** Minimal version to pass some info into #translateLoads(): */ - BaseMethodInfo(boolean isCallin, boolean isStatic, int translationFlags) - { - this.isCallin = isCallin; - this.isStatic = isStatic; - this.translationFlags = translationFlags; - } - - public boolean isStaticRoleMethod() { - return this.isRoleMethod && this.isStatic; - } - - String getBaseClassName() { - return baseClassName; - } - - String getBaseMethodName() { - return baseMethodName; - } - - String getBaseMethodSignature() { - return baseMethodSignature; - } - - int[] getParameterPositions() { - return parameterPositions; - } - } - - /** - * Scan the Attributes found in the class class_name for binding attributes - * and registers them in the CallinBindingManager. - * - * @param attributes the Attributes to be examined - * @param class_name the name of the class where the Attributes were found - * @param cpg the classes ConstantPoolGen - * @return an ArrayList containing the names of classes which have - * to be loaded immediately - */ - ArrayList<String> scanClassOTAttributes(Attribute[] attributes, - String class_name, - ConstantPoolGen cpg, - ClassGen cg) - { - if(logging) printLogMessage("Inspecting " + class_name); - ArrayList<String> classesToLoad = new ArrayList<String>(); - String base_class_name = null; - for (int k=0; k<attributes.length; k++) { - Attribute actAttr = attributes[k]; - Unknown attr = isOTAttribute(actAttr); - - if (attr != null) { //this is a callin attribute - String attrName = attr.getName(); - if(logging) printLogMessage("CallinBindingAttribute: " + attrName); - byte[] indizes = attr.getBytes(); - int count = combineTwoBytes(indizes, 0); - int numberOfEntries=0; - String [] names; - if (attrName.equals("OTClassFlags")) { - int classFlags = combineTwoBytes(indizes, 0); - String flagsString = ""; - if ((classFlags & 1) != 0) { - flagsString = "team "; - // TODO: use this instead of team modifier - } - if ((classFlags & 2) != 0) { - flagsString += "role"; - CallinBindingManager.addRole(class_name); - } - if (logging) { - printLogMessage("OTClassFlags:"); - printLogMessage("\t" + flagsString); - } - } else if (attrName.equals("CallinRoleBaseBindings")) { - numberOfEntries = 2; - int i = 2; - int n = 2 * count * numberOfEntries; // n = count << 2; - names = new String[numberOfEntries]; - while (i <= n) { - i = scanStrings(names, indizes, i, cpg); - String role_name = names[0]; - String base_name = names[1]; - if(logging) printLogMessage("**** Binding: " + role_name - + " playedBy " + base_name); - - //set binding: - CallinBindingManager.addRoleBaseBinding(role_name, base_name, class_name); - CallinBindingManager.addTeamBaseRelation(class_name, base_name); - - // [OT/Equinox] store adapted bases: - adaptedBases.add(base_name); - - // super roles have to be loaded first for binding inheritance purpose: - // not necessary anymore? - //classesToLoad.addAll(getSuperRoles(role_name, attributes, cpg)); - // roles themselve have to be loaded too: - classesToLoad.add(role_name); - } - } else if (attrName.equals("BoundClassesHierarchy")) { - numberOfEntries = 2; - int i = 2; - int n = 2 * count * numberOfEntries; // n = count << 2; - names = new String[numberOfEntries]; - while (i <= n) { - i = scanStrings(names, indizes, i, cpg); - String sub_name = names[0]; - String super_name = names[1]; - - CallinBindingManager.addBoundSuperclassLink(sub_name, super_name); - if(logging)printLogMessage("**** super-class link: "+sub_name - +" -> "+super_name); - } - } else if (attrName.equals("CallinMethodMappings")) { - //numberOfEntries = 6; - int i = 2; - for (int n=0; n<count;n++) { - // JSR-045 support: - names = new String[1]; - i = scanStrings(names, indizes, i, cpg); - String binding_file_name = names[0]; - int binding_line_number = combineTwoBytes(indizes, i); - i += 2; - int binding_line_offset = combineTwoBytes(indizes, i); - i += 2; - boolean is_static_role_method = false; - boolean covariant_base_return= false; - // regular stuff: - numberOfEntries = 3; - names = new String[numberOfEntries]; - i = scanStrings(names, indizes, i, cpg); - String wrapper_name = null; - String wrapper_signature = null; - // first 3 names: - int index = 0; - - String binding_label = names[index++]; - String role_method_name = names[index++]; - String role_method_signature = names[index++]; - - { // a flag: - int flags = combineTwoBytes(indizes, i); - is_static_role_method = (flags & 1) != 0; - // flag value 4 is "inherited" - covariant_base_return = (flags & 8) != 0; - i+=2; - } - // 3 more names - numberOfEntries = 3; - names = new String[numberOfEntries]; - i = scanStrings(names, indizes, i, cpg); - index = 0; - //if (NEW_COMPILER_VERSION) - // static_role_method = see attribute - - String lift_method_name = names[index++]; - String lift_method_signature = names[index++]; - String binding_modifier = names[index++]; - - int base_len = combineTwoBytes(indizes, i); - i += 2; - - names = new String[4]; - for (int n_base = 0; n_base < base_len; n_base++) { - i = scanStrings(names, indizes, i, cpg); - String base_method_name = names[0]; - String base_method_signature = names[1]; - wrapper_name = names[2]; - wrapper_signature = names[3]; - - byte baseFlags = indizes[i++]; - boolean baseIsCallin = (baseFlags & 1) != 0; - boolean baseIsStatic = (baseFlags & 2) != 0; - int translationFlags = (combineTwoBytes(indizes, i)<<16) + combineTwoBytes(indizes, i+2); - i += 4; - - if(logging) { - printLogMessage("**** Binding: " + binding_label + ":" - + role_method_name + role_method_signature - + " <- " + binding_modifier + " " - + base_method_name + base_method_signature); - printLogMessage("**** Wrapper: " + wrapper_name - + wrapper_signature); - } - //set binding: - CallinBindingManager.addMethodBinding(class_name, - base_class_name, // previously read from PlayedBy attribute - binding_file_name, - binding_line_number, - binding_line_offset, - binding_label, - role_method_name, - role_method_signature, - is_static_role_method, - wrapper_name, - wrapper_signature, - binding_modifier, - base_method_name, - base_method_signature, - baseIsStatic, - baseIsCallin, - covariant_base_return, - translationFlags, - lift_method_name, - lift_method_signature); - - } - } - } else if (attrName.equals("OTSpecialAccess")) { - numberOfEntries = 3; - int i = 2; - for (int j = 0; j < count; j++) { - short kind = indizes[i++]; - switch (kind) { - case 1: // DecapsulatedMethodAccess - names = new String[numberOfEntries]; - i = scanStrings(names, indizes, i, cpg); - if(logging) printLogMessage("**** Callout: " + names[0] + "." - + names[1]+ " " + names[2]); - CallinBindingManager.addCalloutBinding(names[0], names[1], names[2]); - break; - case 2: // CalloutFieldAccess - short flags = indizes[i++]; - String accessMode = (flags & 1) == 1 ? "set" : "get"; - boolean isStaticField = (flags & 2) != 0; - names = new String[numberOfEntries]; - i = scanStrings(names, indizes, i, cpg); - if (logging) - printLogMessage("**** Callout bound field: " + accessMode+(isStaticField?" static ":" ") - + names[2]+ " " + names[1]); - CallinBindingManager.addCalloutBoundFileds(names[0], names[1], names[2], accessMode, isStaticField); - - synchronized(reentrentTransformations) { - for (ObjectTeamsTransformation transformation : reentrentTransformations) - transformation.state.interfaceTransformedClasses.remove(names[0]); - } - - break; - case 3: // SuperMethodAccess - numberOfEntries = 4; - names = new String[numberOfEntries]; - i = scanStrings(names, indizes, i, cpg); - if(logging) printLogMessage("**** SuperAccess: " + names[0] + "." - + names[2]+ names[3]+" superclass "+names[1]); - CallinBindingManager.addSuperAccess(names[0], names[1], names[2], names[3]); - break; - } - } - // adapted baseclasses (w/ or w/o decapsulation): - count = combineTwoBytes(indizes, i); - i += 2; - names = new String[1]; - for (int j=0; j<count; j++) { - i = scanStrings(names, indizes, i, cpg); - byte flag = indizes[i++]; - if (flag == 1) { - CallinBindingManager.addBaseClassForModifierChange(names[0]); - } else { - // [OT/Equinox]: store adapted bases: - adaptedBases.add(names[0]); - } - } - } else if (attrName.equals("ReferencedTeams")) { - numberOfEntries = 1; - int i = 2; - int n = 2 * count * numberOfEntries; // n = count << 1; - names = new String[numberOfEntries]; - while (i <= n) { - i = scanStrings(names, indizes, i, cpg); - String referenced_team = names[0]; - if(logging) printLogMessage("**** found ReferencedTeams: " + referenced_team); - classesToLoad.add(referenced_team); - - } - } else if (attrName.equals("PlayedBy")) { - names = new String[1]; - scanStrings(names, indizes, 0, cpg); - base_class_name = names[0]; - int langle = base_class_name.indexOf('<'); - if (langle > -1) // it's an anchored type p.T$R<@C.o.f>, cut off everything after and including '<'. - base_class_name = base_class_name.substring(0, langle-1); - if(logging) printLogMessage("**** found PlayedBy: " + base_class_name); - // base_class_name is stored for later use, when method bindings are found. - CallinBindingManager.addSuperRoleLink(cg.getClassName(), cg.getSuperclassName()); - // this information is NOT NEEDED at moment! - } else if (attrName.equals("OTCompilerVersion")) { - int encodedVersion = combineTwoBytes(indizes, 0); - int major = encodedVersion >>> 9; - int minor = (encodedVersion >>> 5) & 0xF; - int revision = encodedVersion & 0x1F; - if(logging) printLogMessage("**** class file was produced by compiler version " - + major + "." + minor + "." + revision + " ****"); - IS_COMPILER_GREATER_123 = false; // reset, may be updated below - // 1.5 stream: - if (major == 1 && minor == 5) { - if (revision < OT15_REVISION) { - if (class_name.startsWith(OTConstants.teamClassName)) - continue; // no specific byte codes in ooTeam and its inner classes. - throw new InternalError("OTRE: Class " + class_name + " has unsupported revision " + revision); - } - IS_COMPILER_GREATER_123 = true; - IS_COMPILER_13X_PLUS = true; - IS_COMPILER_14X_PLUS = true; - // 1.4 stream: - } else if (major == 1 && minor == 4) { - if (revision < OT14_REVISION) { - if (class_name.startsWith(OTConstants.teamClassName)) - continue; // no specific byte codes in ooTeam and its inner classes. - throw new InternalError("OTRE: Class " + class_name + " has unsupported revision " + revision); - } - IS_COMPILER_GREATER_123 = true; - IS_COMPILER_13X_PLUS = true; - IS_COMPILER_14X_PLUS = true; - // 1.3 stream: - } else if (major == 1 && minor == 3) { - if (revision < OT13_REVISION) { - if (class_name.startsWith(OTConstants.teamClassName)) - continue; // no specific byte codes in ooTeam and its inner classes. - throw new InternalError("OTRE: Class " + class_name + " has unsupported revision " + revision); - } - IS_COMPILER_GREATER_123 = true; - IS_COMPILER_13X_PLUS = true; - // 1.2 stream: - } else if (major == 1 && minor == 2) { - if (revision < OT12_REVISION) { - if (class_name.startsWith(OTConstants.teamClassName)) - continue; // no specific byte codes in ooTeam and its inner classes. - throw new InternalError("OTRE: Class " + class_name + " has unsupported revision " + revision); - } - if (revision > 3) - IS_COMPILER_GREATER_123 = true; - // 1.1 stream: - } else if (major == 1 && minor == 1) { - if (revision < OT11_REVISION) { - if (class_name.startsWith(OTConstants.teamClassName)) - continue; // no specific byte codes in ooTeam and its inner classes. - throw new InternalError("OTRE: Class " + class_name + " has unsupported revision " + revision); - } - // 1.0 stream: - } else if (major == 1 && minor == 0) { - if (revision < OT10_REVISION) { - if (class_name.startsWith(OTConstants.teamClassName)) - continue; // no specific byte codes in ooTeam and its inner classes. - throw new InternalError("OTRE: Class " + class_name + " has unsupported revision " + revision); - } - // 0.9 stream: - } else if (major == 0 && minor == 9) { - if (revision < OT09_REVISION) { - if (class_name.startsWith(OTConstants.teamClassName)) - continue; // no specific byte codes in ooTeam and its inner classes. - throw new InternalError("OTRE: Class " + class_name + " has unsupported revision " + revision); - } - // 0.8 stream (OBSOLETE!) - } else { - if (major != OT_VERSION_MAJOR) - throw new InternalError("OTRE: Class " + class_name + " has unsupported major version " + major); - if (minor != OT_VERSION_MINOR) - throw new InternalError("OTRE: Class " + class_name + " has unsupported minor version " + minor); - if (revision < OT_REVISION) - throw new InternalError("OTRE: Class " + class_name + " has unsupported revision " + revision); - } - } else if (attrName.equals("CallinPrecedence")) { - List<String> precedenceList = new LinkedList<String>(); - numberOfEntries = 1; - int i = 2; - int n = 2 * count * numberOfEntries; // n = count << 1; - names = new String[numberOfEntries]; - while (i <= n) { - i = scanStrings(names, indizes, i, cpg); - String binding_label = names[0]; - precedenceList.add(binding_label); - } - if(logging) printLogMessage("**** found precedence list for " + class_name + ": " - + precedenceList + " ****"); - CallinBindingManager.addPrecedenceList(precedenceList, class_name); - } - } - } - return classesToLoad; - } - - /** - * Read some strings from a byte array. - * @param entries Result array to be provided by caller. - * @param indizes buffer of read bytes to be provided by caller, - * consists if indizes into the constant pool - * @param i current index into indizes - * @param cpg the pool. - * @result updated value of <tt>i</tt>. - */ - public static int scanStrings(String[] entries, - byte[] indizes, - int i, - ConstantPoolGen cpg) - { - for (int j = 0; j < entries.length; j++) { - int nextIndex = combineTwoBytes(indizes, i); - ConstantUtf8 cons = (ConstantUtf8)cpg.getConstant(nextIndex); - String content = cons.getBytes(); - entries[j] = content; - i += 2; - } - return i; - } - - /** - * Scan the Attributes found in the method <tt>method_name</tt> for binding attributes - * and registers them in the {@link CallinBindingManager CallinBindingManager}. - * - * @param attributes the Attributes to be examined - * @param class_name the name of the class where the Attributes were found - * @param method_name the name of the method where the Attributes were found - * @param cpg - */ - static void scanMethodOTAttributes(Attribute[] attributes, - String class_name, - String method_name, - ConstantPoolGen cpg) - { - for (int k = 0; k < attributes.length; k++) { - Attribute actAttr = attributes[k]; - Unknown attr = isOTAttribute(actAttr); - if (attr != null) { //this is an OT attribute - String attrName = attr.getName(); - if(logging) printLogMessage("CallinBindingAttribute(" + method_name + ") :" - + attrName); - if (attrName.equals("CallinParamMappings")) { - byte[] indizes = attr.getBytes(); - int [] positions = null; - if (indizes == null) throw new RuntimeException("Unexpected null attr"); - int count = combineTwoBytes(indizes, 0); - positions = new int[count]; - int p = 2; - for (int i = 0; i < count; i++, p += 2) { - positions[i] = combineTwoBytes(indizes, p); - // System.out.println(" "+i+"<-"+positions[i]); - } - CallinBindingManager.addParameterBinding(class_name, - method_name, - positions); - // Here it is correct to use the (wrapper) method name without a signature, - // because for overloaded methods there are separate wrappers with unique (mangled) names. - } - } - } - } - - - /** - * Determines, if the given Attribute is a callin-attribute. - * - * @param attr the Attriute to be checked - * @return the Attribute casted to Unknown, for later use, if true - * null, if it is not a callin-attribute - */ - static Unknown isOTAttribute(Attribute attr) { - if (attr instanceof Unknown) { - Unknown unknown = (Unknown)attr; - String attrName = unknown.getName(); - if (attrName.equals("CallinRoleBaseBindings") || - attrName.equals("BoundClassesHierarchy") || - attrName.equals("CallinMethodMappings") || - attrName.equals("CallinParamMappings") || - attrName.equals("CallinFlags") || - attrName.equals("OTSpecialAccess") || - attrName.equals("WrappedRoleSignature") || - attrName.equals("WrappedBaseSignature") || - attrName.equals("ReferencedTeams") || - attrName.equals("PlayedBy") || - attrName.equals("Modifiers") || - attrName.equals("OTCompilerVersion") || - attrName.equals("OTClassFlags") || - attrName.equals("OTJoinPoints") || - attrName.equals("CallinPrecedence") || - attrName.equals("StaticReplaceBindings")) - { - return unknown; - } - } - return null; - } - - /** - * Combines two int's representing the higher and the lower part - * of a two byte number. - * - * @param first the first (higer?) byte - * @param second the second (lower?) byte - * @return the combined number - */ - public static int combineTwoBytes(byte [] indizes, int start) { - int first = indizes[start]; - int second = indizes[start + 1]; - int twoBytes = 0; - - twoBytes = twoBytes | (first & 0xff); - twoBytes = twoBytes << 8; - twoBytes = twoBytes | (second & 0xff); - return twoBytes; - } - - /** - * Returns a list of names of all super classes of class 'role_name' which are inner - * classes of the enclosing team, what are all super roles of the - * role 'role_name'. - * - * @param role_name the name of the role class - * @param attributes the attributes of the enclosing team class - * @param cpg the constant pool of the enclosing team class - * @return the list of super role names - */ - /* - private List getSuperRoles(String role_name, Attribute[] attributes, ConstantPoolGen cpg) { - LinkedList superRoleNames = new LinkedList(); - JavaClass[] super_classes = Repository.getSuperClasses(role_name); - if (super_classes.length < 2) {// extends only Object, or none? - return superRoleNames; - } - LinkedList innerClassNames = new LinkedList(); - for (int i=0; i<attributes.length; i++) { - Attribute actAttr = attributes[i]; - if (actAttr instanceof InnerClasses) { - InnerClass[] inners = ((InnerClasses)actAttr).getInnerClasses(); - for (int j=0; j<inners.length; j++) { - int name_index = inners[j].getInnerNameIndex(); - Constant name_c = cpg.getConstant(name_index); - String name = ((ConstantUtf8)name_c).getBytes(); - int outer_class_index = inners[j].getOuterClassIndex(); - Constant outer_c = cpg.getConstant(outer_class_index); - String outerName = ((ConstantClass)outer_c).getBytes(cpg.getConstantPool()); - outerName = outerName.replace('/', '.'); - innerClassNames.add(outerName + "$" +name); - } - } - } - for (int i=0; i<super_classes.length; i++) { - String superClassName = super_classes[i].getClassName(); - if (innerClassNames.contains(superClassName)) { - superRoleNames.addFirst(superClassName); - } - } - return superRoleNames; - }*/ - - /** Create a MethodGen and remove some unwanted code attributes (which would need special translation which we don't have) */ - protected static MethodGen newMethodGen(Method m, String class_name, ConstantPoolGen cp) { - MethodGen mg = new MethodGen(m, class_name, cp); - List<Attribute> attributesToRemove = new ArrayList<Attribute>(); - for (Attribute attr : mg.getCodeAttributes()) - if (attr instanceof Unknown || attr instanceof StackMap) - attributesToRemove.add(attr); - for (Attribute attr : attributesToRemove) - mg.removeCodeAttribute(attr); - return mg; - } - - /** - * Remove all contents of a method as preparation for adding a new implementation - * - * @param m The original method - * @param class_name The class containing the method - * @param cpg The class' constant pool - * @return An empty method generator with the same declaration as m - * and no implementation. - */ - protected static MethodGen wipeMethod(Method m, String class_name, ConstantPoolGen cpg) { - MethodGen mg; - mg = new MethodGen(m, class_name, cpg); - mg.getInstructionList().dispose(); //throw away the old implementation - mg.removeLineNumbers(); - mg.removeLocalVariables(); - mg.removeExceptionHandlers(); - mg.removeAttributes(); - mg.removeCodeAttributes(); - return mg; - } - - /** - * Add instructions of InstructionList il after the super constructor call of this constuctor. - * - * @param m the constructor method - * @param addedCode the InstructionList containing the instructions to be added - * @param cg the ClassGen - * @param cpg the constant pool - */ - static void addToConstructor(Method m, InstructionList addedCode, ClassGen cg, ConstantPoolGen cpg) { - String class_name = cg.getClassName(); - MethodGen mg = newMethodGen(m, class_name, cpg); - InstructionList il = mg.getInstructionList().copy(); - InstructionHandle[] ihs = il.getInstructionHandles(); - - MethodGen newConstructor = new MethodGen(mg.getAccessFlags(), - mg.getReturnType(), - mg.getArgumentTypes(), - mg.getArgumentNames(), - mg.getName(), - class_name, - il, - cpg ); - -//[SH:] - updateCopiedMethod(mg, il, ihs, newConstructor); -//[:HS] - - int stackDepth = 0; - int actInstrIndex = 0; - - boolean pauseStackCounting = false; - InstructionHandle gotoTarget = null; - - // skip everything up to and including super() or this() call - while (!((ihs[actInstrIndex].getInstruction() instanceof INVOKESPECIAL) - && (stackDepth - (ihs[actInstrIndex].getInstruction().consumeStack(cpg))) == 0)) { - - Instruction actInstruction = ihs[actInstrIndex].getInstruction(); - - if (gotoTarget != null && actInstruction.equals(gotoTarget.getInstruction())) { - pauseStackCounting = false; - gotoTarget = null; - } - - if (actInstruction instanceof GotoInstruction) { - GotoInstruction gotoInsruction = (GotoInstruction)actInstruction; - gotoTarget = gotoInsruction.getTarget(); - pauseStackCounting = true; - } - if (!pauseStackCounting) { - stackDepth -= actInstruction.consumeStack(cpg); - stackDepth += actInstruction.produceStack(cpg); - } - - actInstrIndex++; - } - - InstructionHandle ih = ihs[actInstrIndex]; - INVOKESPECIAL invoke = (INVOKESPECIAL)ih.getInstruction(); - String specialName = invoke.getName(cpg); - if (!specialName.equals(Constants.CONSTRUCTOR_NAME)) { - System.err.println("###ALERT: " + specialName); - return; - } - - if (logging) printLogMessage("Adding code to " + class_name + "." + m.getName()); - - // calculate the length of the added code BEFORE it is inserted into the instruction list: -//[SH:] extracted for adding further manipulation of addedCode: - int addedCodeLength = padCodeToAdd(addedCode); -//[:HS] - - InstructionHandle startOfAddedCode = il.append(ih, addedCode); - - il.setPositions(); - - newConstructor.setInstructionList(il); - newConstructor.setMaxStack(); - newConstructor.setMaxLocals(); -//[SH:] if an unused local variable was copied in updateCopiedMethod() -// we have to adjust max_locals, -// because unused locals are not found by setMaxLocals(). - newConstructor.setMaxLocals(Math.max(newConstructor.getMaxLocals(), mg.getMaxLocals())); -//[:HS] - - copyAndAdjustLineNumbers(mg, newConstructor, addedCodeLength, startOfAddedCode); - - cg.replaceMethod(m, newConstructor.getMethod()); - } - - /** - * Pads a given instruction list to multiples of 4 returning the padded length. - * Note that clients of this function must not call removeNOPs()! - * - * Rationale: - * switch instructions pad the lists of jmp targets to start at an offset % 4 == 0. - * In order to ensure that this padding will not change when inserting new bytes - * the added bytes have to be a multiple of 4. - */ - static int padCodeToAdd(InstructionList addedCode) { -//[orig:] - int addedCodeLength = 0; - Instruction[] instr = addedCode.getInstructions(); - for (int i = 0; i < instr.length; i++) { - addedCodeLength += instr[i].getLength(); - } -//[:giro] - while (addedCodeLength % 4 > 0) { - addedCode.append(new NOP()); - addedCodeLength++; - } - return addedCodeLength; - } - -//[SH:] helper methods for more complete method copying: - - /** After a method (incl. its instruction list) has been copied, - * we need to manually copy some more properties: - * + local variables - * + declared exceptions - * + exception handlers. - */ - static void updateCopiedMethod(MethodGen methodOrig, - InstructionList ilCopy, - InstructionHandle[] ihsCopy, - MethodGen methodCopy) - { - // local variables: - LocalVariableGen[] oldLocals = methodOrig.getLocalVariables(); - int argLen = methodOrig.getArgumentTypes().length; - if (!methodOrig.isStatic()) - argLen++; // this - if (oldLocals.length > argLen) { - InstructionList oldIL = methodOrig.getInstructionList(); - int maxLocals = methodOrig.getMaxLocals(); - for (int i = argLen; i<oldLocals.length; i++) { - LocalVariableGen var = oldLocals[i]; - LocalVariableGen newVar = - methodCopy.addLocalVariable(var.getName(), var.getType(), - mapIH(var.getStart(), oldIL, ihsCopy), - mapIH(var.getEnd(), oldIL, ihsCopy)); - newVar.setIndex(var.getIndex()); - // reset, addLocalVariable might have changed this. - methodCopy.setMaxLocals(maxLocals); - } - } - // declared exceptions: - BaseCallRedirection.copyExceptionHandlers(methodOrig, methodCopy, ilCopy); - // exception handlers: - for(String excName : methodOrig.getExceptions()) - methodCopy.addException(excName); - } - - static InstructionHandle mapIH(InstructionHandle alienIH, InstructionList oldIL, InstructionHandle[] newIHs) - { - int position = alienIH.getPosition(); - int[] newPositions = oldIL.getInstructionPositions(); - for (int i=0; i<newPositions.length; i++) { - if (newPositions[i] == position) - return newIHs[i]; - } - return null; - } -//[:HS] - - /** - * Copy all line numbers from <tt>src</tt> to <tt>dest</tt>. - * For bytecode instructions after the added code area an offset has to be added to the - * bytecode positions of the line numbers. - * If in debug modus (flag 'debugging') add 'STEP_OVER_LINENUMBER' for the added code. - * - * @param src The source method. - * @param dest The destination method. - * @param offset The offest to be added (the length of the added code list). - * @param startOfAddedCode InstructionHandle to the beginning of the added code. - */ - static void copyAndAdjustLineNumbers(MethodGen src, MethodGen dest, int offset, InstructionHandle startOfAddedCode) { - InstructionList il_dest = dest.getInstructionList(); - LineNumberGen[] src_lng = src.getLineNumbers(); - boolean addedCodeHasLineNumber = false; - - for (int i = 0; i < src_lng.length; i++) { - int position = src_lng[i].getInstruction().getPosition(); - if (position == startOfAddedCode.getPosition()) { // add the line number for added code here: - dest.addLineNumber(startOfAddedCode, STEP_OVER_LINENUMBER); - addedCodeHasLineNumber = true; - continue; - } - if (position >= startOfAddedCode.getPosition()) // move line numbers, because of inserted code (add offset) - position += offset; - InstructionHandle ih = il_dest.findHandle(position); - if (ih == null) { - System.err.println("Handle not found!"); - } else { - dest.addLineNumber(ih, src_lng[i].getSourceLine()); - } - } - if (!addedCodeHasLineNumber) { // no custom code after added code: add line number now: - dest.addLineNumber(startOfAddedCode, STEP_OVER_LINENUMBER); - } - } - - /** - * Test if a method has the given 'callin_flag'. - * - * @param m the method to search - * @param cg the ClassGen - * @param callin_flags the flags to check for; 0 means any callin flags - * @return true, if the method has the callin flag - */ - public static boolean methodHasCallinFlags(Method m, ClassGen cg, int callin_flags) { - boolean found = false; - Attribute[] attributes = m.getAttributes(); - for (int i = 0; i < attributes.length; i++) { - Attribute actAttr = attributes[i]; - if (!(actAttr instanceof Unknown)) - continue; - Unknown attr = (Unknown)actAttr; - if (!(attr.getName().equals("CallinFlags"))) - continue; - if (callin_flags == 0) - return true; - byte [] bytes = attr.getBytes(); - int flags = combineTwoBytes(bytes, 0); - if ((flags & callin_flags) != 0) { - if(logging) printLogMessage("Found CallinFlag " + callin_flags + " for " - + cg.getClassName() + "." + m.getName() + "."); - found = true; - } - } - return found; - } - - /** - * A team needs to get added the team specific part, if it is a non-abstract team and - * not the class org.objectteams.Team itself. - * - * @param cg the class to be tested - * @return true if this is a team which has to be extended - */ - protected static boolean classNeedsTeamExtensions(ClassGen cg) { - return ((cg.getAccessFlags() & OTConstants.TEAM) != 0) // must be a team - && ((cg.getAccessFlags() & Constants.ACC_ABSTRACT) == 0) // and non-abstract - && !(cg.getClassName().equals(OTConstants.teamClassName)); // and not o.o.Team itself. - } - - /** - * Generates the name of the implementing role for the given role interface name. - * (Inserts the '__OT__' marker.) - * - * @param roleName the role interface name - * @return the implementing role class name - */ - protected static String genImplementingRoleName(String roleName) { - int lastDollar = roleName.lastIndexOf('$'); - StringBuilder sb = new StringBuilder(roleName); - sb.insert(lastDollar + 1, OTDT_PREFIX); - return sb.toString(); - } - - /** - * Generates the name of the role interface the given role class is implementing. - *(Removes the '__OT__' marker.) - * - * @param roleName the role class name - * @return the implemented role interface - */ - public static String genRoleInterfaceName(String roleName) { - int lastDollar = roleName.lastIndexOf('$'); - StringBuilder sb = new StringBuilder(roleName); - sb.delete(lastDollar + 1, lastDollar + 1 + OTDT_PREFIX.length()); - return sb.toString(); - } - - protected static boolean isReflectiveOTMethod(String methodName, String methodSignature) { - if ((methodName.equals("hasRole") && methodSignature.equals("(Ljava/lang/Object;)Z")) - || (methodName.equals("hasRole") && methodSignature.equals("(Ljava/lang/Object;Ljava/lang/Class;)Z")) - || (methodName.equals("getRole") && methodSignature.equals("(Ljava/lang/Object;)Ljava/lang/Object;")) - || (methodName.equals("getRole") && methodSignature.equals("(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;")) - || (methodName.equals("getAllRoles") && methodSignature.equals("()[Ljava/lang/Object;")) - || (methodName.equals("getAllRoles") && methodSignature.equals("(Ljava/lang/Class;)[Ljava/lang/Object;")) - || (methodName.equals("unregisterRole") && methodSignature.equals("(Ljava/lang/Object;)V")) - || (methodName.equals("unregisterRole") && methodSignature.equals("(Ljava/lang/Object;Ljava/lang/Class;)V")) - ) - return true; - return false; - } - - /** - * Calculates the name of the outer class. - * - * @param className the full name of the inner class - * @return the name of the outer class - */ - public static String getOuterClassName(String className) { - int dollarIndex = className.lastIndexOf('$'); - if (dollarIndex == -1) // no outer class exists! - return null; - String outerClassName = className.substring(0, dollarIndex); - return outerClassName; - } - - /** - * @param m - * @param cg - * @return - */ - static boolean candidateForImplicitActivation(Method m, ClassGen cg, ConstantPoolGen cpg) { - if (!IS_COMPILER_14X_PLUS) - implicitActivationMode = ImplicitActivationMode.ALWAYS; - switch (implicitActivationMode) { - case NEVER: - return false; - case ANNOTATED : - if ( AnnotationHelper.containsImplicitActivationAttribute(m.getAttributes(), cpg) - || AnnotationHelper.containsImplicitActivationAttribute(cg.getAttributes(), cpg)) - return canImplicitlyActivate(m); - return false; - case ALWAYS: - if (!canImplicitlyActivate(m)) - return false; - - Attribute[] attributes = m.getAttributes(); - for(Attribute a : attributes) { - if (a instanceof Unknown) { - Unknown attr = (Unknown) a; - String attrName = attr.getName(); - if ("RoleClassMethodModifiers".equals(attrName)) { - byte[] bytes = attr.getBytes(); - int flags = combineTwoBytes(bytes, 0); - if (flags == 0 ||/* flags == 2 || */flags == 4) { - // 0: default, 2: private, 4: protected - return false; - } - } - } - } - if (!m.isPublic()) - return false; // m originally wasn't public - - String className = cg.getClassName(); - return !(CallinBindingManager.isRole(className) && cg.isProtected()); - default: - return false; // cannot happen switch is exhaustive. - } - } - - private static boolean canImplicitlyActivate(Method m) { - String methodName = m.getName(); - String methodSignature = m.getSignature(); - boolean isCandidate = - (!m.isAbstract()) && - (!m.isStatic()) && - (!methodName.startsWith(OT_PREFIX)) && - (!methodName.equals(Constants.CONSTRUCTOR_NAME)) && - (!(methodName.equals("activate") && methodSignature.equals("()V"))) && - (!(methodName.equals("deactivate") && methodSignature.equals("()V"))) && - (!isReflectiveOTMethod(m.getName(), methodSignature)); - return isCandidate; - } - - /** - * @param s - * @param c - * @return - */ - static int countOccurrences(String s, char c) { - int count = 0; - int idx = s.indexOf(c); - while (idx != -1) { - idx = s.indexOf(c, idx + 1); - count++; - } - return count; - } - - /** - * This method performs the changes for implicit Team activation. - * @param m a method for which implicit activation will be enabled. - * @param className the class name for 'm'. - * @param cpg the constant pool of the class 'className'. - * @param activateOuter true, if the surrounding team has to be activated - * @return - */ - Method genImplicitActivation(Method m, String className, ConstantPoolGen cpg, boolean activateOuter) { - String targetName = className; - int nestingDepth = 0; - ObjectType outerClass = null; - if (activateOuter) { - outerClass = new ObjectType(getOuterClassName(className)); - nestingDepth = countOccurrences(className, '$') - 1; - targetName = outerClass.getClassName(); - } - MethodGen mg = newMethodGen(m, className, cpg); - InstructionList il = mg.getInstructionList(); - InstructionList prefix = new InstructionList(); - InstructionHandle try_start = il.getStart(); - // ---> new implicit activation - prefix.append(InstructionFactory.createThis()); - if (activateOuter) {// this is for a role method: activate the outer team - // FIXME(SH): check replacing this$n with _OT$getTeam() - prefix.append(factory.createGetField(className, "this$" + nestingDepth, outerClass)); - } - prefix.append(factory.createInvoke(targetName, "_OT$implicitlyActivate", - Type.VOID, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); - // <-- new implicit activation - if (debugging) - mg.addLineNumber(prefix.getStart() , STEP_OVER_LINENUMBER); - il.insert(prefix); - - InstructionList postfix = new InstructionList(); - // ---> new implicit deactivation - postfix.append(InstructionFactory.createThis()); - if (activateOuter) {// this is for a role method: deactivate the outer team - postfix.append(factory.createGetField(className, "this$"+nestingDepth, outerClass)); - } - postfix.append(factory.createInvoke(targetName, - "_OT$implicitlyDeactivate", Type.VOID, Type.NO_ARGS, - Constants.INVOKEVIRTUAL)); - // <-- new implicit deactivation - - insertBeforeReturn(mg, il, postfix); - - /** - * **** add an exception handler which calls deactivate before throwing - * the exception (finaly-simulation): *** - */ - ObjectType throwable = new ObjectType("java.lang.Throwable"); - LocalVariableGen exception = mg.addLocalVariable( - "_OT$thrown_exception", throwable, null, null); - InstructionHandle try_end = il.getEnd(); - InstructionList postfix_ex = postfix.copy(); - if (debugging) - mg.addLineNumber(postfix_ex.getStart(), STEP_OVER_LINENUMBER); - postfix_ex.insert(InstructionFactory.createStore(throwable, exception - .getIndex())); - postfix_ex.append(InstructionFactory.createLoad(throwable, exception - .getIndex())); - postfix_ex.append(new ATHROW()); - InstructionHandle deactivation_handler = il.append(il.getEnd(), - postfix_ex); - mg.addExceptionHandler(try_start, try_end, deactivation_handler, - throwable); - /** ******************************************************************** */ - - mg.setInstructionList(il); - mg.setMaxLocals(); - mg.setMaxStack(); - - if (!debugging) - return mg.getMethod(); - - /* sorting the line numbers per start pc: */ - Method newMethod = mg.getMethod(); - MethodGen newMethodGen = new MethodGen(newMethod, className, cpg); - - LineNumberGen[] lineNumbers = newMethodGen.getLineNumbers(); - - newMethodGen.removeLineNumbers(); - - Arrays.sort(lineNumbers, new Comparator<LineNumberGen>() { - public int compare(LineNumberGen ln1, LineNumberGen ln2) { - int firstLineNumberPC = ln1.getLineNumber().getStartPC(); - int secondLineNumberPC = ln2.getLineNumber().getStartPC(); - - if (firstLineNumberPC < secondLineNumberPC) - return -1; - if (firstLineNumberPC > secondLineNumberPC) - return 1; - return 0; - } - }); - - for (int i = 0; i<lineNumbers.length; i++) { - newMethodGen.addLineNumber(lineNumbers[i].getInstruction(), lineNumbers[i].getSourceLine()); - } - - return newMethodGen.getMethod(); - } - - /** - * How many bytes does an instruction produce on the stack? - */ - static protected int stackDiff(Instruction instr, ConstantPoolGen cpg) { - return instr.produceStack(cpg) - instr.consumeStack(cpg); - } - - /** - * Split an instruction list that loads method arguments into - * one list for each argument. - * @param cpg - * @param src the original loading sequence (will be destroyed by this method). - * @param argumentTypes source-level argument types of the callin method. - * @return array of load sequences, same order as before but split into individual arguments. - */ - protected InstructionList[] splitLoading(ConstantPoolGen cpg, InstructionList src, Type[] argumentTypes) { - int len = argumentTypes.length; - InstructionList[] res = new InstructionList[len]; - // starting right _before_ an invoke instruction we loop backwards - // to find those values on the stack that would be passed to the method. - for (int idx = len-1; idx>=0; idx--) { - // new sub-list: - res[idx] = new InstructionList(); - // how many bytes to expect on the stack: - int expectedArgSize = argumentTypes[idx].getSize(); - // loop until we have a sequence that produces the expected number of bytes: - while (expectedArgSize > 0) { - InstructionHandle loadH = src.getEnd(); - Instruction load = loadH.getInstruction(); - expectedArgSize -= stackDiff(load, cpg); - try { - // transfer instruction from src to res[roleIdx]: - res[idx].insert(load); - src.delete(loadH); - } catch (TargetLostException e) { - throw new OTREInternalError(e); - } - } - } - return res; - } - - /** - * Translate the parameter loading of a base call to the correct sequence - * expected by the base chaining wrapper. - * Treats tunneled arguments but not current enhancement args. - * Tasks performed: - * <ul> - * <li>pick load sequences from <tt>splitLoad</tt> - * <li>extract unused args from Object[] - * <li>insert casting or lowering if needed. - * </ul> - * More documentation is found in document parameter-passing.odg. - * - * @param splitLoad one list of load instructions for each argument, ordered as found in the bytecode. - * @param enhancedRoleArgumentTypes enhanced role arguments - * @param enhancedBaseArgumentTypes arguments of the base chaining wrapper. - * @param parameterPosition encoded parameter mappings. - * @param teamName The name of the team containing the role class. - * @param enclosingRoleName enclosing role class or null for static replace/base-call. - * @param baseIsCallin is the base method a callin method? - * @param baseIsStaticRoleMethod is the base method a static role method? - * @param one byte for each parameter, signalling if lowering is required - * @return a complete loading sequence for all source-level and tunneled arguments - */ - protected InstructionList translateLoads(InstructionList[] splitLoad, - Type[] enhancedRoleArgumentTypes, - Type[] enhancedBaseArgumentTypes, - int[] parameterPositions, - String teamName, - String enclosingRoleName, - BaseMethodInfo baseMethod, - int start, - ConstantPoolGen cpg) - { - boolean isStatic = baseMethod.isStatic; - boolean baseIsStaticRoleMethod = baseMethod.isStaticRoleMethod(); - boolean baseIsCallin = baseMethod.isCallin; - int translationFlags = baseMethod.translationFlags; - - InstructionList il = new InstructionList(); - - // index into "Object[] _OT$unusedArgs" (points to first arg that has not yet been consumed): - int nextUnusedArg = 0; - // index into enhancedBaseArgumentTypes: - int baseIdx; - // source-level version of baseIdx, i.e., ignoring any enhanced arguments: - int baseSrcIdx; - // index into roleArgumentTypes: - int roleIdx; - // source-level version of roleIdx, i.e., ignoring any enhanced arguments: - int roleSrcIdx; - - // == Note: letters (u-x) below refer to document parameter-passing.odg. == - // Skip enhancements that are already loaded (given in start). - for (baseIdx = start; baseIdx < enhancedBaseArgumentTypes.length; baseIdx++) { - baseSrcIdx = baseIdx-start; // (u) skip first enhancement (already loaded) - if (baseIsStaticRoleMethod) - baseSrcIdx -= 2; // (v) not mapped but extracted from unusedArgs - if (baseIsCallin) - baseSrcIdx -= EXTRA_ARGS; // (w) not mapped but extracted from unusedArgs - - // value-dispatching: where to find this parameters? - if (baseSrcIdx < 0) { - // (v) or (w) - roleSrcIdx = -1; - } else { - // (x) merge arguments from unused and real: - int numAvailableRoleArgs = enhancedRoleArgumentTypes.length-EXTRA_ARGS; - if (!isStatic && IS_COMPILER_GREATER_123) - numAvailableRoleArgs--; // don't count isSuperAccess - roleSrcIdx = getMappedRolePosition(baseSrcIdx, parameterPositions, numAvailableRoleArgs); - } - - // got all information, fetch it now: - Type baseArgumentType = enhancedBaseArgumentTypes[baseIdx]; - if (roleSrcIdx == -1) { - // not mapped, retrieve from _OT$unusedArgs: - retrieveFromUnusedArg(il, nextUnusedArg++, baseArgumentType, cpg); - } else { - // mapped, fetch from splitLoad: - roleIdx = roleSrcIdx+EXTRA_ARGS; // role always has an additional set of enhancements - if (IS_COMPILER_GREATER_123 && !isStatic) roleIdx++; // (+ isSuperAccess) - Type roleArgumentType = enhancedRoleArgumentTypes[roleIdx]; - il.append(splitLoad[roleSrcIdx]); - if (!roleArgumentType.equals(baseArgumentType)) { - convertParamToBase(il, teamName, enclosingRoleName, roleArgumentType, baseArgumentType, - (translationFlags & (2<<baseSrcIdx)) != 0); - } - } - } - if (il.isEmpty()) - il.append(new NOP()); // ensure caller receives at least one instruction handle (for line number) - return il; - } - - /* Is the base arg identified by 'baseIdx' mapped to a role parameter? - * If so: which role position is it mapped to? - * If not: return -1 - */ - private int getMappedRolePosition(int baseSrcIdx, - int[] parameterPositions, - int numAvailableRoleArgs) - { - if (parameterPositions == null) { - if (baseSrcIdx < numAvailableRoleArgs) // as many as available ... - return baseSrcIdx; // in original order. - } else { - // search parameter mapping: - for (int i = 0; i < parameterPositions.length; i++) { - if (parameterPositions[i] == baseSrcIdx+1) // positions are one-based (base side) - return i; - } - } - return -1; - } - - /* Retrieve an unused (tunneled) argument from position 'unusedIdx' of the _OT$unusedArgs array. */ - private void retrieveFromUnusedArg(InstructionList il, - int unusedIdx, - Type baseArgumentType, - ConstantPoolGen cpg) - { - il.append(InstructionFactory.createLoad(objectArray, /*this*/1 + (UNUSED_ARG-1))); // 'UNUSED_ARG' is one-based - il.append(createIntegerPush(cpg, unusedIdx)); - il.append(InstructionFactory.createArrayLoad(objectArray)); - if (baseArgumentType instanceof BasicType) - il.append(createUnboxing((BasicType) baseArgumentType)); - else // ObjectTypes just have to be re-casted - il.append(factory.createCast(object, baseArgumentType)); - } - - /* May perform any of these conversions: casting, lowering, array-lowering. - * Conversion is generated into 'il'. - */ - private void convertParamToBase(InstructionList il, - String teamName, - String enclosingRoleName, - Type roleArgumentType, - Type baseArgumentType, - boolean loweringFlag) - { - if (roleArgumentType instanceof ObjectType - && baseArgumentType instanceof ObjectType) - { - if (loweringFlag) { - lowerObject(il, teamName, roleArgumentType, baseArgumentType); - } else { - if(logging) printLogMessage("Try to cast " + roleArgumentType + - " to " + baseArgumentType); - il.append(factory.createCast(roleArgumentType, - baseArgumentType)); - } - } else - if ( roleArgumentType instanceof BasicType - && baseArgumentType instanceof ObjectType) - { - il.append(createBoxing((BasicType)roleArgumentType)); - } else - if ( roleArgumentType instanceof ObjectType - && baseArgumentType instanceof BasicType) - { - il.append(createUnboxing((BasicType)baseArgumentType)); - } else - if ( roleArgumentType instanceof ArrayType - && baseArgumentType instanceof ArrayType) - { - lowerArray(il, teamName, enclosingRoleName, roleArgumentType, baseArgumentType); - } else { - throw new OTREInternalError("OTRE internal error:"+ - "No way to make types conform\n"+ - "role type "+roleArgumentType+ - " -> "+baseArgumentType); - } - } - - /* Lower one object from roleArgumentType to baseArgumentType. */ - private void lowerObject(InstructionList il, - String teamName, - Type roleArgumentType, - Type baseArgumentType) - { - String roleIfcName = ((ObjectType)roleArgumentType).getClassName(); - // use interface implementing role type for base-field access! - String roleClassName = ObjectTeamsTransformation.genImplementingRoleName(roleIfcName); - - int dollarIdx = roleClassName.lastIndexOf('$'); - if (dollarIdx == -1) { - throw new OTREInternalError("OTRE internal error:" + - "No way to make types conform\n" + - "role type " + roleArgumentType + - " -> " + baseArgumentType); - } - boolean isNested = dollarIdx != roleClassName.indexOf('$'); // is last == first? - String strengthenedRoleName = teamName + roleClassName.substring(dollarIdx); - - // baseArgumentType may be imprecise due to cast in param mapping, - // try a RBB instead to find the exact base type - RoleBaseBinding rbb = CallinBindingManager.getRoleBaseBinding(strengthenedRoleName); - if (rbb != null) - baseArgumentType = new ObjectType(rbb.getBaseClassName()); - - if (isNested) { - // cannot use field access here, because role strengthening would require resolved information - // so use the _OT$getBase() method instead: - short kind = (roleIfcName.lastIndexOf('$') == roleIfcName.lastIndexOf("$__OT__")) // last segment is roleclass? - ? Constants.INVOKEVIRTUAL - : Constants.INVOKEINTERFACE; - il.append(factory.createInvoke(roleIfcName, GET_BASE, baseArgumentType, new Type[0], kind)); - } else { - // access field via the role class: - il.append(factory.createCast(roleArgumentType, new ObjectType(strengthenedRoleName))); - - // optimized version directly accessing the field: - il.append(factory.createGetField(strengthenedRoleName, - BASE, - baseArgumentType)); - } - } - - /* Lower from roleArgumentType[] to baseArgumentType[]. */ - private void lowerArray(InstructionList il, String teamName, String enclosingRoleName, Type roleArgumentType, Type baseArgumentType) { - ArrayType array = (ArrayType)roleArgumentType; - String roleName =((ObjectType)array.getElementType()).getClassName(); - int dollarIdx = roleName.lastIndexOf('$'); - String pureRoleName = roleName.substring(dollarIdx + 1); - String transformMethodName = getArrayLoweringMethodName(pureRoleName, array.getDimensions()); - if (enclosingRoleName != null) { - // fetch team from enclosing role: - il.append(InstructionFactory.createThis()); - // FIXME(SH): is this$0 always correct (nesting!)?? - il.append(factory.createGetField(enclosingRoleName, "this$0", new ObjectType(teamName))); - } else { - // "this" is the team: - il.append(InstructionFactory.createThis()); - } - il.append(new SWAP()); // 'push' team instance below the role array - il.append(factory.createInvoke(teamName, - transformMethodName, - baseArgumentType, - new Type[]{roleArgumentType}, - Constants.INVOKEVIRTUAL)); - } - - private String getArrayLoweringMethodName(String roleName, int dimensions) { - return "_OT$transformArray" + roleName + "_OT$" + dimensions; - } - - public List<String> getInnerClassNames(ClassGen cg, ConstantPoolGen cpg) { - Attribute[] attributes = cg.getAttributes(); - LinkedList<String> innerClassNames = new LinkedList<String>(); - for (int i = 0; i < attributes.length; i++) { - Attribute actAttr = attributes[i]; - if (actAttr instanceof InnerClasses) { - InnerClass[] inners = ((InnerClasses)actAttr).getInnerClasses(); - for (int j=0; j<inners.length; j++) { - int name_index = inners[j].getInnerNameIndex(); - Constant name_c = cpg.getConstant(name_index); - String name = ((ConstantUtf8)name_c).getBytes(); - innerClassNames.add(name); - } - } - } - return innerClassNames; - } - - /** - * Create a monitor enter using a class literal - * @param mg target method to which a local variable is added which holds the monitor object - * @param il instruction list to append to - * @param class_name name of the class literal to use as monitor - * @param major major class file version, used to determine how to translate class literals - * @param cpg constant pool gen - * @return the slot index of the monitor local variable and the handle of the first generated instruction. - */ - protected Pair<Integer,InstructionHandle> addClassMonitorEnter(MethodGen mg, - InstructionList il, - String class_name, - int major, - ConstantPoolGen cpg) - { - int monitor; - InstructionHandle ih= - appendClassLiteral(il, class_name, major, cpg); - il.append(new DUP()); // for store and monitorenter - LocalVariableGen lg2= - mg.addLocalVariable("monitor", Type.OBJECT, il.getStart(), null); //$NON-NLS-1$ - monitor= lg2.getIndex(); - il.append(InstructionFactory.createStore(Type.OBJECT, monitor)); // for use by monitorexit - il.append(new MONITORENTER()); - return new Pair<Integer, InstructionHandle>(monitor, ih); - } - - /** - * Append an instruction sequence for loading the class literal for `class_name'. - * @param il instruction list to append to - * @param class_name class name of the class literal - * @param major java version as stored in the byte code. - * @param cpg for generating bytes - * @return the handle of the first instruction of the sequence. - */ - protected InstructionHandle appendClassLiteral(InstructionList il, - String class_name, - int major, - ConstantPoolGen cpg) - { - if (major >= 49) // java 5 - return il.append(new LDC(cpg.addClass(new ObjectType(class_name)))); - // pre java 5, do it the hard way: - // if (_OT$self_class$ != null) - InstructionHandle start= - il.append(factory.createFieldAccess(class_name, OTConstants.SELF_CLASS, classType, Constants.GETSTATIC)); - il.append(new DUP()); // keep a copy as a potential result - BranchInstruction checkLoaded= - InstructionFactory.createBranchInstruction(Constants.IFNONNULL, null); - il.append(checkLoaded); - il.append(new POP()); // discard null from above - // _OT$self_class$= Class.forName(<class_name>); // never fails, it is THIS class - il.append(new LDC(cpg.addString(class_name))); - il.append(factory.createInvoke("java.lang.Class", - "forName", - classType, - new Type[]{new ObjectType("java.lang.String")}, - Constants.INVOKESTATIC)); - il.append(new DUP()); // keep a copy as the result - il.append(factory.createFieldAccess(class_name, OTConstants.SELF_CLASS, classType, Constants.PUTSTATIC)); - - checkLoaded.setTarget(il.append(new NOP())); - return start; - } - - @SuppressWarnings("unchecked") - public static void insertBeforeReturn(MethodGen mg, InstructionList il, InstructionList insertion) { - // InstructionFinder is broken see https://issues.apache.org/bugzilla/show_bug.cgi?id=40044 - // which is fixed in r516724 (2007-03-10) but latest release bcel 5.2 is 6. June 2006. -// Iterator<InstructionHandle[]> ihIt = new InstructionFinder(il).search("ReturnInstruction"); -// while (ihIt.hasNext()) { -// InstructionHandle[] ihAr = ihIt.next(); -// InstructionList insertionCopy = insertion.copy(); -// if (debugging) -// mg.addLineNumber(insertionCopy.getStart(), STEP_OVER_LINENUMBER); -// InstructionHandle inserted = il.insert(ihAr[0], insertionCopy); // instruction lists can not be reused -// il.redirectBranches(ihAr[0], inserted);// SH: retarget all jumps that targeted at the return instruction -// } - Iterator<InstructionHandle>ihIt = il.iterator(); - while (ihIt.hasNext()) { - InstructionHandle ihAr = ihIt.next(); - if (!(ihAr.getInstruction() instanceof ReturnInstruction)) - continue; - InstructionList insertionCopy = insertion.copy(); - if (debugging) - mg.addLineNumber(insertionCopy.getStart(), STEP_OVER_LINENUMBER); - InstructionHandle inserted = il.insert(ihAr, insertionCopy); // instruction lists can not be reused - il.redirectBranches(ihAr, inserted);// SH: retarget all jumps that targeted at the return instruction - } - } -} diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/RepositoryAccess.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/RepositoryAccess.java deleted file mode 100644 index 4a249262d..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/RepositoryAccess.java +++ /dev/null @@ -1,125 +0,0 @@ -/********************************************************************** - * This file is part of "Object Teams Development Tooling"-Software - * - * Copyright 2010 Stephan Herrmann - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id$ - * - * Please visit http://www.eclipse.org/objectteams for updates and contact. - * - * Contributors: - * Stephan Herrmann - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre; - -import java.util.HashMap; - -import org.apache.bcel.Repository; -import org.apache.bcel.classfile.JavaClass; -import org.apache.bcel.generic.ObjectType; -import org.apache.bcel.util.ClassLoaderRepository; - -/** - * Provides a classloader aware access to one or more class repositories. - * All access methods are static, but context is passed by setting a per-thread - * current repository using {@link #setClassLoader(ClassLoader)}. - * @since 0.7.0 - */ -public class RepositoryAccess { - - /** One class repository per class loader. */ - private static HashMap<ClassLoader,ClassLoaderRepository> repositories = new HashMap<ClassLoader,ClassLoaderRepository>(); - /** One current repository per thread. */ - private static ThreadLocal<ClassLoaderRepository> currentRepository = new ThreadLocal<ClassLoaderRepository>(); - - /** - * Setup a repository for the given class loader and make it the current repository for the current thread. - * @param loader class loader, may be null - * @return the previously active class repository for this thread - */ - public static synchronized ClassLoaderRepository setClassLoader(ClassLoader loader) { - ClassLoaderRepository clr = null; - if (loader != null) { // avoid creating ClassLoaderRepository with null loader - clr = repositories.get(loader); - if (clr == null) - repositories.put(loader, clr = new ClassLoaderRepository(loader)); - } - ClassLoaderRepository prev = currentRepository.get(); - currentRepository.set(clr); - return prev; - } - - /** Reset the class repository for the current thread. */ - public static synchronized void resetRepository(ClassLoaderRepository repository) { - currentRepository.set(repository); - } - - public static JavaClass lookupClass(String className) - throws ClassNotFoundException - { - ClassLoaderRepository clr = currentRepository.get(); - if (clr != null) - return clr.loadClass(className); - return Repository.lookupClass(className); - } - - public static JavaClass[] getSuperClasses(String className) - throws ClassNotFoundException - { - ClassLoaderRepository clr = currentRepository.get(); - JavaClass jc; - if (clr != null) - jc = clr.loadClass(className); - else - jc = Repository.lookupClass(className); - return jc.getSuperClasses(); - } - - public static boolean implementationOf(String className, String ifcName) - throws ClassNotFoundException - { - ClassLoaderRepository clr = currentRepository.get(); - JavaClass jc, ifc; - if (clr != null) { - jc = clr.loadClass(className); - ifc= clr.loadClass(ifcName); - } else { - jc = Repository.lookupClass(className); - ifc= Repository.lookupClass(ifcName); - } - return jc.implementationOf(ifc); - } - - public static boolean safeSubclassOf(ObjectType subClass, ObjectType superClass) { - try { - String subClassName = subClass.getClassName(); - String superClassName = superClass.getClassName(); - return instanceOf(subClassName, superClassName); - } catch (ClassNotFoundException e) { - // consider classes as incommensurable if they can't both be loaded in the current class loader - return false; - } catch (ClassCircularityError e) { - // assume that circularity was caused by resolving framework classes during class loading - return false; - } - } - - protected static boolean instanceOf(String subClassName, String superClassName) - throws ClassNotFoundException - { - ClassLoaderRepository clr = currentRepository.get(); - JavaClass subJClass, superJClass; - if (clr != null) { - subJClass = clr.loadClass(subClassName); - superJClass= clr.loadClass(superClassName); - } else { - subJClass = Repository.lookupClass(subClassName); - superJClass= Repository.lookupClass(superClassName); - } - return subJClass.instanceOf(superJClass); - } -} diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/StaticSliceBaseTransformation.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/StaticSliceBaseTransformation.java deleted file mode 100644 index 5e5844f04..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/StaticSliceBaseTransformation.java +++ /dev/null @@ -1,756 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2002-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: StaticSliceBaseTransformation.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre; - -import org.apache.bcel.classfile.*; -import org.apache.bcel.generic.*; -import org.apache.bcel.*; - -import org.eclipse.objectteams.otre.util.*; - - -/** - * Adds to base classes with callin bindings what can be literally pasted in: - * - * Fields: - * protected static Team[] _OT$activeTeams; - * protected static int[] _OT$activeTeamIDs; - * Methods: - * public static void _OT$addTeam(Team team, in team_id) - * public static void _OT$removeTeam(Team team) - * Static initialization (adds clinit method, if not yet presented): - * _OT$activeTeams = new Team[0]; - * _OT$activeTeamIDs = new int[0]; - * - * - * @version $Id: StaticSliceBaseTransformation.java 23408 2010-02-03 18:07:35Z stephan $ - * @author Christine Hundt - * @author Stephan Herrmann - */ -public class StaticSliceBaseTransformation - extends ObjectTeamsTransformation -{ - static final String _OT_ACTIVE_TEAMS= "_OT$activeTeams"; //$NON-NLS-1$ - static final String _OT_ACTIVE_TEAM_IDS= "_OT$activeTeamIDs"; //$NON-NLS-1$ - - public StaticSliceBaseTransformation(ClassLoader loader, SharedState state) { super(loader, state); } - - public void doTransformCode(ClassGen cg) { - if (cg.isInterface()) - return; // can't add implementation - // IMPLICIT_INHERITANCE - - String class_name = cg.getClassName(); - if (!CallinBindingManager.isBoundBaseClass(class_name) - /*&& !CallinBindingManager.containsBoundBaseInterface(cg.getInterfaceNames())*/) - return; //only (base-)classes with callin bindings need this addition - /*// this only works if teams are only added at the root bound base class - if (CallinBindingManager.isBoundBaseClass(cg.getSuperclassName())) - continue; // team infrastructur already added by super class - */ - if (CallinBindingManager.hasBoundBaseParent(class_name)) - return; // team infrastructure already has been added to a super class - - ConstantPoolGen cpg = cg.getConstantPool(); - factory = new InstructionFactory(cpg); - addStaticInitializations(cg, cpg); - } - - /** - * @param ce - * @param cg - */ - public void doTransformInterface(ClassEnhancer ce, ClassGen cg) { - String class_name = cg.getClassName(); - ConstantPoolGen cpg = cg.getConstantPool(); - - checkReadClassAttributes(ce, cg, class_name, cpg); - - if (cg.isInterface()) - return; // can't add implementation - if (state.interfaceTransformedClasses.contains(class_name)) - return; // class has already been transformed by this transformer - // IMPLICIT_INHERITANCE - if (!CallinBindingManager.isBoundBaseClass(class_name) - /*&& !CallinBindingManager.containsBoundBaseInterface(cg.getInterfaceNames())*/) - return; //only (base-)classes with callin bindings need this addition - /*// this only works if teams are only added at the root bound base class - if (CallinBindingManager.isBoundBaseClass(cg.getSuperclassName())) - continue; // team infrastructur already added by super class - */ - if (CallinBindingManager.hasBoundBaseParent(class_name)) - return; // team infrastructure already has been added to a super class - if(logging) printLogMessage("StaticSliceBaseTransformer transforms "+ class_name); - - if(CallinBindingManager.isRole(class_name)) { - addImplicitSubclassNotificationInfrastructure(ce, cg); - } - - // addition of the fields '_OT$activeTeams' and '_OT$activeTeamIDs': - int accessFlags = Constants.ACC_PROTECTED | Constants.ACC_STATIC; - - FieldGen activeTeamsField = new FieldGen(accessFlags, teamArray, _OT_ACTIVE_TEAMS, cpg); - ce.addField(activeTeamsField.getField(), cg); - // generated global variable: protected static Team[] _OT$activeTeams; - - FieldGen activeTeamIDsField = new FieldGen(accessFlags, intArray, _OT_ACTIVE_TEAM_IDS, cpg); - ce.addField(activeTeamIDsField.getField(), cg); - // generated global variable: protected static int[] _OT$activeTeamIDs; - - factory = new InstructionFactory(cpg); - - // implementation of method '_OT$addTeam' - ce.addMethod(genAddTeam(class_name, cg.getMajor(), cpg).getMethod(), cg); - - // implementation of method '_OT$removeTeam': - ce.addMethod(genRemoveTeam(class_name, cg.getMajor(), cpg).getMethod(), cg); - - // implementation of the static class initialization method '<clinit>': - /* Adding static initializations requires the addition of the clinit method, if not yet presented. - * This requires synchronization with other transformers (TeamInterfaceImplementer) - * which may do the same this. This is done via 'TeamIdDispenser.clinitAdded(class_name)'. - */ - Method clinit = cg.containsMethod(Constants.STATIC_INITIALIZER_NAME, "()V"); - - if (clinit != null || TeamIdDispenser.clinitAdded(class_name, loader)) { - // the clinit-Method only has to be extended by the code transformation of this transformer - state.interfaceTransformedClasses.add(class_name); - return; - } - - InstructionList il = new InstructionList(); - MethodGen clinitMethod = new MethodGen(Constants.ACC_STATIC, - Type.VOID, - Type.NO_ARGS, - new String[] { }, - Constants.STATIC_INITIALIZER_NAME, class_name, - il, cpg); - - il.append(InstructionFactory.createReturn(Type.VOID)); - - clinitMethod.setMaxStack(); - clinitMethod.setMaxLocals(); - - ce.addMethod(clinitMethod.getMethod(), cg); - -/***********************************************************************************************************/ - il.dispose(); - state.interfaceTransformedClasses.add(class_name); - } - - /* Code to be generated: - public static void _OT$addTeam(Team team, int teamID) - { - int l; - // Second part of the "if" below: Avoid duplicate entry of the same team. - // Assumption (see r17473): this strategy assumes that a team instance - // can only be duplicated directly after the first registration. - // Reason: registerAtBases() calling addTeam() for multiple sub-bases - // which share the same _OT$activateTeams et al fields from a common super-base. - if((l = _OT$activeTeams.length) != 0 && _OT$activeTeams[0] == team) - { - return; - } else - { - Team newTeams[] = new Team[l + 1]; - int newTeamIDs[] = new int[l + 1]; - System.arraycopy(_OT$activeTeams, 0, newTeams, 1, l); - System.arraycopy(_OT$activeTeamIDs, 0, newTeamIDs, 1, l); - _OT$activeTeams = newTeams; - _OT$activeTeamIDs = newTeamIDs; - _OT$activeTeams[0] = team; - _OT$activeTeamIDs[0] = teamID; - return; - } - } - */ - private MethodGen genAddTeam(String class_name, int major, ConstantPoolGen cpg) { - LocalVariableGen lg; - InstructionList il; - il = new InstructionList(); - MethodGen addTeamMethod = new MethodGen(Constants.ACC_PUBLIC | Constants.ACC_STATIC | Constants.ACC_SYNCHRONIZED, - Type.VOID, - new Type[] { teamType, Type.INT }, - new String[] { "team", "teamID" }, - "_OT$addTeam", class_name, - il, cpg); - // synchronized (BaseClass.class) { - int monitor = addClassMonitorEnter(addTeamMethod, il, class_name, major, cpg).first; - - il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.GETSTATIC)); - il.append(new ARRAYLENGTH()); - lg = addTeamMethod.addLocalVariable("l", Type.INT, null, null); - int l = lg.getIndex(); - il.append(new DUP()); - lg.setStart(il.append(InstructionFactory.createStore(Type.INT, l))); - // generated: int l = _OT$activeTeams.length; - - // add duplication check: - BranchHandle emptyArray = - il.append(new IFEQ(null)); - il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.GETSTATIC)); - il.append(new ICONST(0)); - il.append(InstructionFactory.createArrayLoad(teamType)); - il.append(new ALOAD(0)); - BranchHandle noDuplication = - il.append(new IF_ACMPNE(null)); - GOTO earlyExit = new GOTO(null); - il.append(earlyExit); - InstructionHandle skipReturn = il.append(new NOP()); - emptyArray.setTarget(skipReturn); - noDuplication.setTarget(skipReturn); - // generated: if (l > 0 && _OT$activeTeams[0] == team ) return; - - lg = addTeamMethod.addLocalVariable("newTeams", teamArray, null, null); - int newTeams = lg.getIndex(); - il.append(InstructionFactory.createLoad(Type.INT, l)); - il.append(new ICONST(1)); - il.append(new IADD()); - il.append((Instruction)factory.createNewArray(teamType, (short)1)); - //this are very strange (but necessary!?) casts... - lg.setStart(il.append(InstructionFactory.createStore(teamArray, newTeams))); - // generated: Team[] newTeams = new Team[l+1]; - - lg = addTeamMethod.addLocalVariable("newTeamIDs", intArray, null, null); - int newTeamIDs = lg.getIndex(); - il.append(InstructionFactory.createLoad(Type.INT, l)); - il.append(new ICONST(1)); - il.append(new IADD()); - il.append((Instruction)factory.createNewArray(Type.INT, (short)1)); - //this are very strange (but necessary!?) casts... - lg.setStart(il.append(InstructionFactory.createStore(intArray, newTeamIDs))); - // generated: int[] newTeamIDs = new int[l+1]; - - il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.GETSTATIC)); - il.append(new ICONST(0)); - il.append(InstructionFactory.createLoad(teamArray, newTeams)); - il.append(new ICONST(1)); - il.append(InstructionFactory.createLoad(Type.INT, l)); - ObjectType object = new ObjectType("java.lang.Object"); - il.append(factory.createInvoke("java.lang.System", "arraycopy", - Type.VOID, - new Type[] {object, Type.INT, object, Type.INT, Type.INT }, - Constants.INVOKESTATIC)); - // generated: System.arraycopy(_OT$activeTeams, 0, newTeams, 1, l); - - il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAM_IDS, intArray, Constants.GETSTATIC)); - il.append(new ICONST(0)); - il.append(InstructionFactory.createLoad(intArray, newTeamIDs)); - il.append(new ICONST(1)); - il.append(InstructionFactory.createLoad(Type.INT, l)); - il.append(factory.createInvoke("java.lang.System", "arraycopy", - Type.VOID, - new Type[] {object, Type.INT, object, Type.INT, Type.INT }, - Constants.INVOKESTATIC)); - // generated: System.arraycopy(_OT$activeTeamIDs, 0, newTeamIDs, 1, l); - - il.append(InstructionFactory.createLoad(teamArray, newTeams)); - il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.PUTSTATIC)); - // generated: _OT$activeTeams = newTeams; - - il.append(InstructionFactory.createLoad(intArray, newTeamIDs)); - il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAM_IDS, intArray, Constants.PUTSTATIC)); - // generated: _OT$activeTeamIDs = newTeamIDs; - - il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.GETSTATIC)); - il.append(new ICONST(0)); - il.append(new ALOAD(0)); - il.append(InstructionFactory.createArrayStore(teamType)); - // generated: _OT$activeTeams[0] = team; - - il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAM_IDS, intArray, Constants.GETSTATIC)); - il.append(new ICONST(0)); - il.append(new ILOAD(1)); - il.append(InstructionFactory.createArrayStore(Type.INT)); - // generated: _OT$activeTeamIDs[0] = teamID; - - if (CallinBindingManager.isRole(class_name)) { - il.append(new ALOAD(0)); - il.append(new ILOAD(1)); - il.append(factory.createInvoke(class_name, "_OT$activateNotify", Type.VOID, new Type[] { teamType, Type.INT }, Constants.INVOKESTATIC)); - // generated: _OT$activateNotify(team, teamID); - } - - // No more access to array fields, release monitor: - InstructionHandle exitSequence = - il.append(InstructionFactory.createLoad(Type.OBJECT, monitor)); - il.append(new MONITOREXIT()); - earlyExit.setTarget(exitSequence); - - il.append(InstructionFactory.createReturn(Type.VOID)); - - addTeamMethod.setMaxStack(); - addTeamMethod.setMaxLocals(); - addTeamMethod.removeNOPs(); - return addTeamMethod; - } - - /* Code to be generated: - public static void _OT$removeTeam(Team team) - { - int l; - if((l = _OT$activeTeams.length) == 0) - return; - boolean found = false; - int newLen= l-1; - Team newTeams[] = new Team[newLen]; - int newTeamIDs[] = new int[newLen]; - for(int i = 0; i < l; i++) - if(!found) - { - if(_OT$activeTeams[i] == team) - { - found = true; - } else if (i<newLen) { // coded as: jump if (newLen<=i) - { - newTeams[i] = _OT$activeTeams[i]; - newTeamIDs[i] = _OT$activeTeamIDs[i]; - } - } else - { - newTeams[i - 1] = _OT$activeTeams[i]; - newTeamIDs[i - 1] = _OT$activeTeamIDs[i]; - } - - if(found) - { - _OT$activeTeams = newTeams; - _OT$activeTeamIDs = newTeamIDs; - } - } - */ - private MethodGen genRemoveTeam(String class_name, int major, ConstantPoolGen cpg) - { - LocalVariableGen lg; - InstructionList il; - int l; - BranchHandle emptyArray; - int newTeams; - int newTeamIDs; - il = new InstructionList(); - MethodGen removeTeamMethod = new MethodGen(Constants.ACC_PUBLIC | Constants.ACC_STATIC | Constants.ACC_SYNCHRONIZED, - Type.VOID, - new Type[] { teamType }, - new String[] { "team" }, - "_OT$removeTeam", class_name, - il, cpg); - - // synchronized (BaseClass.class) { - int monitor = addClassMonitorEnter(removeTeamMethod, il, class_name, major, cpg).first; - - il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.GETSTATIC)); - il.append(new ARRAYLENGTH()); - lg = removeTeamMethod.addLocalVariable("l", Type.INT, null, null); - //int l = lg.getIndex(); - l = lg.getIndex(); - il.append(new DUP()); - lg.setStart(il.append(InstructionFactory.createStore(Type.INT, l))); - // generated: int l = _OT$activeTeams.length; - - emptyArray = il.append(new IFNE(null)); - GOTO earlyExit = new GOTO(null); - il.append(earlyExit); - emptyArray.setTarget(il.append(new NOP())); - // generated: if (l == 0) return; - - lg = removeTeamMethod.addLocalVariable("found", Type.BOOLEAN, null, null); - int found = lg.getIndex(); - il.append(new ICONST(0)); - lg.setStart(il.append(InstructionFactory.createStore(Type.BOOLEAN, found))); - // generated: boolean found = false; - - lg = removeTeamMethod.addLocalVariable("newTeams", teamArray, null, null); - newTeams = lg.getIndex(); - il.append(InstructionFactory.createLoad(Type.INT, l)); - // [SH]: variable newLen - LocalVariableGen lgNewLen= removeTeamMethod.addLocalVariable("newLen", Type.INT, il.getEnd(), null); - il.append(new ICONST(1)); - il.append(new ISUB()); - // [SH] store for later use: - il.append(new DUP()); - il.append(InstructionFactory.createStore(Type.INT, lgNewLen.getIndex())); - // [HS] generated: "newLen= l-1;" - il.append((Instruction)factory.createNewArray(teamType, (short)1)); - lg.setStart(il.append(InstructionFactory.createStore(teamArray, newTeams))); - // generated: Team[] newTeams = new Team[newLen]; - - lg = removeTeamMethod.addLocalVariable("newTeamIDs", intArray, null, null); - //int newTeamIDs = lg.getIndex(); - newTeamIDs = lg.getIndex(); - //[SH]: - il.append(InstructionFactory.createLoad(Type.INT, lgNewLen.getIndex())); - il.append((Instruction)factory.createNewArray(Type.INT, (short)1)); - lg.setStart(il.append(InstructionFactory.createStore(intArray, newTeamIDs))); - // generated: int[] newTeamIDs = new int[newLen]; - - // start for-loop - lg = removeTeamMethod.addLocalVariable("i", Type.INT, null, null); - int loopCounter = lg.getIndex(); - il.append(new ICONST(0)); - lg.setStart(il.append(InstructionFactory.createStore(Type.INT, loopCounter))); - GOTO try_leave_loop = new GOTO(null); - il.append(try_leave_loop); - InstructionHandle i_lower_l = il.append(new NOP()); - // loop body: - il.append(InstructionFactory.createLoad(Type.BOOLEAN, found)); - IFNE already_found = new IFNE(null); - il.append(already_found); - - // outer if part: - il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.GETSTATIC)); - il.append(new ILOAD(loopCounter)); - il.append(InstructionFactory.createArrayLoad(teamType)); - il.append(new ALOAD(0)); //first parameter - IF_ACMPNE teams_not_equal = new IF_ACMPNE(null); - il.append(teams_not_equal); - - // inner if part: - il.append(new ICONST(1)); - il.append(InstructionFactory.createStore(Type.BOOLEAN, found)); - GOTO skip_outer_else_part = new GOTO(null); - il.append(skip_outer_else_part); - - // inner else part: - teams_not_equal.setTarget(il.append(new NOP())); - - // [SH] sanity check: - il.append(InstructionFactory.createLoad(Type.INT, lgNewLen.getIndex())); - il.append(new ILOAD(loopCounter)); - IF_ICMPLE if_len_le_i= new IF_ICMPLE(null); - il.append(if_len_le_i); - // [HS] generated: else if (!(newLen <= i)) { - il.append(new ALOAD(newTeams)); - il.append(new ILOAD(loopCounter)); - il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.GETSTATIC)); - il.append(new ILOAD(loopCounter)); - il.append(InstructionFactory.createArrayLoad(teamType)); - il.append(new AASTORE()); - // generated: newTeams[i] = _OT$activeTeams[i]; - - il.append(new ALOAD(newTeamIDs)); - il.append(new ILOAD(loopCounter)); - il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAM_IDS, intArray, Constants.GETSTATIC)); - il.append(new ILOAD(loopCounter)); - il.append(InstructionFactory.createArrayLoad(Type.INT)); - il.append(new IASTORE()); - // generated: newTeamIDs[i] = _OT$activeTeamIDs[i]; - - GOTO end_of_loop = new GOTO(null); - il.append(end_of_loop); - - // outer else part: - already_found.setTarget(il.append(new NOP())); - il.append(new ALOAD(newTeams)); - il.append(new ILOAD(loopCounter)); - il.append(new ICONST(1)); - il.append(new ISUB()); - il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.GETSTATIC)); - il.append(new ILOAD(loopCounter)); - il.append(InstructionFactory.createArrayLoad(teamType)); - il.append(new AASTORE()); - // generated: newTeams[i-1] = _OT$activeTeams[i]; - - il.append(new ALOAD(newTeamIDs)); - il.append(new ILOAD(loopCounter)); - il.append(new ICONST(1)); - il.append(new ISUB()); - il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAM_IDS, intArray, Constants.GETSTATIC)); - il.append(new ILOAD(loopCounter)); - il.append(InstructionFactory.createArrayLoad(Type.INT)); - il.append(new IASTORE()); - // generated: newTeamIDs[i-1] = _OT$activeTeamIDs[i]; - - skip_outer_else_part.setTarget(il.append(new NOP())); - // [SH] connect "else if" from above: - if_len_le_i.setTarget(il.getEnd()); - end_of_loop.setTarget(il.append(new IINC(loopCounter, 1))); - try_leave_loop.setTarget(il.append(InstructionFactory.createLoad(Type.INT, loopCounter))); - il.append(new ILOAD(l)); - il.append(new IF_ICMPLT(i_lower_l)); - // end for-loop - - il.append(InstructionFactory.createLoad(Type.BOOLEAN, found)); - BranchHandle notFound = il.append(new IFEQ(null)); - // generated: if (found) { - - il.append(InstructionFactory.createLoad(teamArray, newTeams)); - il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.PUTSTATIC)); - // generated: _OT$activeTeams = newTeams; - - il.append(InstructionFactory.createLoad(intArray, newTeamIDs)); - il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAM_IDS, intArray, Constants.PUTSTATIC)); - // generated: _OT$activeTeamIDs = newTeamIDs; - - if (CallinBindingManager.isRole(class_name)) { - il.append(new ALOAD(0)); - il.append(factory.createInvoke(class_name, "_OT$deactivateNotify", Type.VOID, new Type[] { teamType }, Constants.INVOKESTATIC)); - // generated: _OT$deactivateNotify(team); - } - - // No more access to array fields, release monitor: - InstructionHandle exitSequence = - il.append(InstructionFactory.createLoad(Type.OBJECT, monitor)); - il.append(new MONITOREXIT()); - earlyExit.setTarget(exitSequence); - notFound.setTarget(exitSequence); - - il.append(InstructionFactory.createReturn(Type.VOID)); - - removeTeamMethod.setMaxStack(); - removeTeamMethod.setMaxLocals(); - removeTeamMethod.removeNOPs(); - return removeTeamMethod; - } - - /** - * Add infrastructure for implicit subclasses to register and be notified. This 'observer' mechanism - * is necessary, because an implicit subclass does not inherit the addition/removal - * of a team at the implicit superclass. - * @param ce The ClassEnhancer object to add methods and fields. - * @param cg The ClassGen object representing the current class. - */ - private void addImplicitSubclassNotificationInfrastructure(ClassEnhancer ce, ClassGen cg) { - - ConstantPoolGen cpg = cg.getConstantPool(); - factory = new InstructionFactory(cpg); - String class_name = cg.getClassName(); - ObjectType linkedListType = new ObjectType("java.util.LinkedList"); - int accessFlags = Constants.ACC_PROTECTED | Constants.ACC_STATIC; - FieldGen teamRegistrationObserversField = new FieldGen(accessFlags, linkedListType, "_OT$teamRegistrationObservers", cpg); - ce.addField(teamRegistrationObserversField.getField(), cg); - -/***********************************************************************************************************/ - - InstructionList il = new InstructionList(); - - MethodGen observerRegistrationMethod = new MethodGen(Constants.ACC_PUBLIC | Constants.ACC_STATIC, - Type.VOID, - new Type[] { classType }, - new String[] { "implicitSubClass" }, - "_OT$registerObserver", class_name, - il, cpg); - - il.append(factory.createFieldAccess(class_name, "_OT$teamRegistrationObservers", linkedListType, Constants.GETSTATIC)); - il.append(InstructionFactory.createLoad(classType, 0)); - il.append(factory.createInvoke("java.util.LinkedList", "add", Type.BOOLEAN, new Type[] { Type.OBJECT }, Constants.INVOKEVIRTUAL)); - il.append(new POP()); - il.append(new RETURN()); - - observerRegistrationMethod.setMaxStack(2); - observerRegistrationMethod.setMaxLocals(); - - ce.addMethod(observerRegistrationMethod.getMethod(), cg); -/***********************************************************************************************************/ - il = new InstructionList(); - - MethodGen activateNotifyMethod = new MethodGen(Constants.ACC_PUBLIC | Constants.ACC_STATIC, - Type.VOID, - new Type[] { teamType, Type.INT }, - new String[] { "team", "teamID" }, - "_OT$activateNotify", class_name, - il, cpg); - - createNotifyMethodImplementation(activateNotifyMethod, cpg, class_name); - - ce.addMethod(activateNotifyMethod.getMethod(), cg); -/***********************************************************************************************************/ - il = new InstructionList(); - - MethodGen deactivateNotifyMethod = new MethodGen(Constants.ACC_PUBLIC | Constants.ACC_STATIC, - Type.VOID, - new Type[] { teamType }, - new String[] { "team" }, - "_OT$deactivateNotify", class_name, - il, cpg); - createNotifyMethodImplementation(deactivateNotifyMethod, cpg, class_name); - - ce.addMethod(deactivateNotifyMethod.getMethod(), cg); - } - - - /** - * Create implementation of methods '_OT$activateNotify' and _OT$deactivateNotify'. - * @param notifyMethod Method which has to be implemented. - * @param cpg Corresponding constant pool. - * @param class_name Name of the class for wich to implement the method. - */ - private void createNotifyMethodImplementation(MethodGen notifyMethod, ConstantPoolGen cpg, String class_name) { - boolean isActivateMethod = notifyMethod.getName().equals("_OT$activateNotify"); -// int methodArgs = isActivateMethod ? 2 : 1; - - int iteratorIdx = isActivateMethod ? 2 : 1; - int curClassIdx = isActivateMethod ? 3 : 2; - int anotherIdx1 = isActivateMethod ? 4 : 3; - int anotherIdx2 = isActivateMethod ? 5 : 4; - String methodToInvoke = isActivateMethod ? "_OT$addTeam" : "_OT$removeTeam"; - - InstructionList il = notifyMethod.getInstructionList(); - il.append(factory.createFieldAccess(class_name, "_OT$teamRegistrationObservers", new ObjectType("java.util.LinkedList"), Constants.GETSTATIC)); - BranchInstruction ifnonnull_3 = InstructionFactory.createBranchInstruction(Constants.IFNONNULL, null); - il.append(ifnonnull_3); - il.append(InstructionFactory.createReturn(Type.VOID)); - InstructionHandle ih_7 = il.append(factory.createFieldAccess(class_name, "_OT$teamRegistrationObservers", new ObjectType("java.util.LinkedList"), Constants.GETSTATIC)); - il.append(factory.createInvoke("java.util.LinkedList", "iterator", new ObjectType("java.util.Iterator"), Type.NO_ARGS, Constants.INVOKEVIRTUAL)); - il.append(InstructionFactory.createStore(Type.OBJECT,iteratorIdx)); - InstructionHandle ih_14 = il.append(InstructionFactory.createLoad(Type.OBJECT,iteratorIdx)); - il.append(factory.createInvoke("java.util.Iterator", "hasNext", Type.BOOLEAN, Type.NO_ARGS, Constants.INVOKEINTERFACE)); - BranchInstruction ifeq_20 = InstructionFactory.createBranchInstruction(Constants.IFEQ, null); - il.append(ifeq_20); - il.append(InstructionFactory.createLoad(Type.OBJECT,iteratorIdx)); - il.append(factory.createInvoke("java.util.Iterator", "next", Type.OBJECT, Type.NO_ARGS, Constants.INVOKEINTERFACE)); - il.append(factory.createCheckCast(classType)); - il.append(InstructionFactory.createStore(Type.OBJECT,curClassIdx)); - il.append(InstructionConstants.ACONST_NULL); - il.append(InstructionFactory.createStore(Type.OBJECT,anotherIdx1)); - InstructionHandle ih_36 = il.append(InstructionFactory.createLoad(Type.OBJECT,curClassIdx)); - il.append(new PUSH(cpg, methodToInvoke)); - il.append(new PUSH(cpg,iteratorIdx)); - il.append((Instruction)factory.createNewArray(classType, (short) 1)); - il.append(InstructionConstants.DUP); - - il.append(new PUSH(cpg, 0)); - il.append(new PUSH(cpg, OTConstants.teamName)); - il.append(factory.createInvoke("java.lang.Class", "forName", - classType, new Type[] { Type.STRING }, - Constants.INVOKESTATIC)); - - il.append(InstructionConstants.AASTORE); - if (isActivateMethod){ // add the integer argument: - il.append(InstructionConstants.DUP); - il.append(new PUSH(cpg, 1)); - il.append(factory.createFieldAccess("java.lang.Integer", "TYPE", classType, Constants.GETSTATIC)); - il.append(InstructionConstants.AASTORE); - } - il.append(factory.createInvoke("java.lang.Class", "getMethod", new ObjectType("java.lang.reflect.Method"), new Type[] { Type.STRING, new ArrayType(classType, 1) }, Constants.INVOKEVIRTUAL)); - InstructionHandle ih_76 = il.append(InstructionFactory.createStore(Type.OBJECT,anotherIdx1)); - BranchInstruction goto_78 = InstructionFactory.createBranchInstruction(Constants.GOTO, null); - il.append(goto_78); - InstructionHandle ih_81 = il.append(InstructionFactory.createStore(Type.OBJECT,anotherIdx2)); - il.append(factory.createFieldAccess("java.lang.System", "err", new ObjectType("java.io.PrintStream"), Constants.GETSTATIC)); - il.append(new PUSH(cpg, "activateNotifyMethod not found!")); - il.append(factory.createInvoke("java.io.PrintStream", "println", Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL)); - InstructionHandle ih_91 = il.append(InstructionFactory.createLoad(Type.OBJECT,anotherIdx1)); - BranchInstruction ifnull_93 = InstructionFactory.createBranchInstruction(Constants.IFNULL, null); - il.append(ifnull_93); - il.append(InstructionFactory.createLoad(Type.OBJECT,anotherIdx1)); - il.append(InstructionConstants.ACONST_NULL); - il.append(new PUSH(cpg,iteratorIdx)); - il.append((Instruction)factory.createNewArray(Type.OBJECT, (short) 1)); - il.append(InstructionConstants.DUP); - il.append(new PUSH(cpg, 0)); - il.append(InstructionFactory.createLoad(Type.OBJECT, 0)); - il.append(InstructionConstants.AASTORE); - - if (isActivateMethod) { // load the integer argument: - il.append(InstructionConstants.DUP); - il.append(new PUSH(cpg, 1)); - il.append(factory.createNew("java.lang.Integer")); - il.append(InstructionConstants.DUP); - il.append(InstructionFactory.createLoad(Type.INT, 1)); - il.append(factory.createInvoke("java.lang.Integer", Constants.CONSTRUCTOR_NAME, Type.VOID, new Type[] { Type.INT }, Constants.INVOKESPECIAL)); - il.append(InstructionConstants.AASTORE); - } - il.append(factory.createInvoke("java.lang.reflect.Method", "invoke", Type.OBJECT, new Type[] { Type.OBJECT, new ArrayType(Type.OBJECT, 1) }, Constants.INVOKEVIRTUAL)); - InstructionHandle ih_121 = il.append(InstructionConstants.POP); - InstructionHandle ih_122; - BranchInstruction goto_122 = InstructionFactory.createBranchInstruction(Constants.GOTO, ih_14); - ih_122 = il.append(goto_122); - InstructionHandle ih_125 = il.append(InstructionFactory.createStore(Type.OBJECT,anotherIdx2)); - il.append(factory.createFieldAccess("java.lang.System", "err", new ObjectType("java.io.PrintStream"), Constants.GETSTATIC)); - il.append(new PUSH(cpg, "Can not call activateNotifyMethod!")); - il.append(factory.createInvoke("java.io.PrintStream", "println", Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL)); - BranchInstruction goto_135 = InstructionFactory.createBranchInstruction(Constants.GOTO, ih_14); - il.append(goto_135); - InstructionHandle ih_138 = il.append(InstructionFactory.createStore(Type.OBJECT,anotherIdx2)); - il.append(factory.createFieldAccess("java.lang.System", "err", new ObjectType("java.io.PrintStream"), Constants.GETSTATIC)); - il.append(new PUSH(cpg, "InvocationTargetException")); - il.append(factory.createInvoke("java.io.PrintStream", "println", Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL)); - BranchInstruction goto_148 = InstructionFactory.createBranchInstruction(Constants.GOTO, ih_14); - il.append(goto_148); - InstructionHandle ih_151 = il.append(InstructionFactory.createReturn(Type.VOID)); - ifnonnull_3.setTarget(ih_7); - ifeq_20.setTarget(ih_151); - goto_78.setTarget(ih_91); - ifnull_93.setTarget(ih_122); - notifyMethod.addExceptionHandler(ih_36, ih_76, ih_81, new ObjectType("java.lang.NoSuchMethodException")); - notifyMethod.addExceptionHandler(ih_91, ih_121, ih_125, new ObjectType("java.lang.IllegalAccessException")); - notifyMethod.addExceptionHandler(ih_91, ih_121, ih_138, new ObjectType("java.lang.reflect.InvocationTargetException")); - - notifyMethod.setMaxStack(); - notifyMethod.setMaxLocals(); - } - - /** - * Adds initialization of the team array and the team index array to the static initializer of this class. - * If this base class is a role at the same time, then also add initialization of the observer list. - * @param cg The representation of the class. - * @param cpg The constant pool of the class. - */ - private void addStaticInitializations(ClassGen cg, ConstantPoolGen cpg) { - Method clinitMethod = cg.containsMethod(Constants.STATIC_INITIALIZER_NAME, "()V"); - /* The clinit method always exists at this moment, because it has been added - * by the interface transformer part of this transformer if necessary. - */ - MethodGen mg = newMethodGen(clinitMethod, cg.getClassName(), cpg); - InstructionList il = mg.getInstructionList(); - // add static initialization for added static fields at start of the <clinit> method: - il.insert(inizializeStaticFields(cg.getClassName())); - mg.setMaxStack(); - mg.setMaxLocals(); - Method newClinit = mg.getMethod(); - cg.replaceMethod(clinitMethod, newClinit); - il.dispose(); - // Reuse instruction handles - } - - /** - * @param class_name - * @return - */ - private InstructionList inizializeStaticFields(String class_name) { - // STATIC_PARTS_TODO : in base: static initialization of team fields - InstructionList il = new InstructionList(); - il.append(new ICONST(0)); - il.append((Instruction)factory.createNewArray(teamType, (short)1)); - //this are very strange (but necessary!?) casts... - il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.PUTSTATIC)); - //generated: _OT$activeTeams = new Team[0]; - - il.append(new ICONST(0)); - il.append((Instruction)factory.createNewArray(Type.INT, (short)1)); - //this are very strange (but necessary!?) casts... - il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAM_IDS, intArray, Constants.PUTSTATIC)); - //generated: _OT$activeTeamIDs = new int[0]; - - if (CallinBindingManager.isRole(class_name)) { - ObjectType linkedListType = new ObjectType("java.util.LinkedList"); - il.append(factory.createNew(linkedListType)); - il.append(new DUP()); - il.append(factory.createInvoke("java.util.LinkedList", - Constants.CONSTRUCTOR_NAME, - Type.VOID, Type.NO_ARGS, - Constants.INVOKESPECIAL)); - - il.append(factory.createFieldAccess(class_name, - "_OT$teamRegistrationObservers", - linkedListType, Constants.PUTSTATIC )); - - //generated: _OT$teamRegistrationObservers = new LinkedList(); - } - return il; - } -} diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/SubBoundBaseMethodRedefinition.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/SubBoundBaseMethodRedefinition.java deleted file mode 100644 index 1a0db28b4..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/SubBoundBaseMethodRedefinition.java +++ /dev/null @@ -1,174 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2002-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: SubBoundBaseMethodRedefinition.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre; - -import org.apache.bcel.classfile.*; -import org.apache.bcel.generic.*; -import org.apache.bcel.*; - -import java.util.*; - -import org.eclipse.objectteams.otre.util.*; - -/** - * Redefines inherited (and not redefined) base methods in subclasses with a - * call to the super method if they are bound for the subclass only. This is - * done in order to provide a place for the BaseMethodTransformer to weave in - * the callin code. - * - * @version $Id: SubBoundBaseMethodRedefinition.java 23408 2010-02-03 18:07:35Z stephan $ - * @author Christine Hundt - * @author Stephan Herrmann - */ - -public class SubBoundBaseMethodRedefinition - extends ObjectTeamsTransformation { - - public SubBoundBaseMethodRedefinition(ClassLoader loader, SharedState state) { super(loader, state); } - - /** - * Main entry for this transformer. - */ - public void doTransformInterface(ClassEnhancer ce, ClassGen cg) { - String class_name = cg.getClassName(); - ConstantPoolGen cpg = cg.getConstantPool(); - - factory = new InstructionFactory(cg); - - checkReadClassAttributes(ce, cg, class_name, cpg); - - // if class is already transformed by this transformer - if (state.interfaceTransformedClasses.contains(class_name)) { - return; - } - - List<MethodBinding> mbsForClass = CallinBindingManager - .getMethodBindingsForBaseClass(class_name); - if (mbsForClass.isEmpty()) { - return; // no bindings for this base class - } - - List<MethodBinding> inheritedBoundMethods = getInheritedBoundMethods(mbsForClass, cg); - - addSubBoundMethodRedefinitions(inheritedBoundMethods, ce, cg); - state.interfaceTransformedClasses.add(class_name); - } - - /** - * Adds redefinitions with calls to the super method to all methods - * contained in the 'inheritedBoundMethods' list. - * - * @param inheritedBoundMethods - * The list of method bindings for inherited methods. - * @param ce - * ClassEnhancer with the extension set of this class. - * @param cg - * The ClassGen object for the transformed class. - */ - private void addSubBoundMethodRedefinitions(List<MethodBinding> inheritedBoundMethods, - ClassEnhancer ce, ClassGen cg) { - List<String> alreadyAddedRedefinitions = new LinkedList<String>(); - - Iterator<MethodBinding> it = inheritedBoundMethods.iterator(); - while (it.hasNext()) { - MethodBinding mb = it.next(); - String baseMethodKey = mb.getBaseMethodName() + "." - + mb.getBaseMethodSignature(); - - if (alreadyAddedRedefinitions.contains(baseMethodKey)) { - continue; - } - Method m = genMethodRedefinition(mb, cg); - - ce.addMethod(m, cg); - if(logging) printLogMessage("Added " + baseMethodKey + " to " + cg.getClassName()); - alreadyAddedRedefinitions.add(baseMethodKey); - } - } - - /** - * Generates a (redefining) method, which just calls its super version. - * - * @param mb - * A method binding containing the method to be redefined. - * @param cg - * The ClassGen object for the transformed class. - * @return The generated method. - */ - private Method genMethodRedefinition(MethodBinding mb, ClassGen cg) { - boolean staticMethod = mb.hasStaticBaseMethod(); - short invocationKind = staticMethod ? Constants.INVOKESTATIC : Constants.INVOKESPECIAL; - - String methodName = mb.getBaseMethodName(); - String methodSignature = mb.getBaseMethodSignature(); - String className = mb.getBaseClassName(); - Type returnType = Type.getReturnType(methodSignature); - Type[] argTypes = Type.getArgumentTypes(methodSignature); - InstructionList il = new InstructionList(); - - int accFlags = Constants.ACC_PUBLIC; - if (staticMethod) { - accFlags = accFlags | Constants.ACC_STATIC; - } - MethodGen redefinition = new MethodGen(accFlags, returnType, argTypes, - null, methodName, className, il, - cg.getConstantPool()); - - if(!staticMethod){ - il.append(InstructionFactory.createThis()); - } - // load all arguments: - int index = 1; - for (int i = 0; i < argTypes.length; i++) { - il.append(InstructionFactory.createLoad(argTypes[i], index)); - index += argTypes[i].getSize(); - } - il.append(factory.createInvoke(cg.getSuperclassName(), methodName, - returnType, argTypes, invocationKind)); - il.append(InstructionFactory.createReturn(returnType)); - - redefinition.removeNOPs(); - il.setPositions(); - redefinition.setMaxStack(); - redefinition.setMaxLocals(); - return redefinition.getMethod(); - } - - /** - * Selects all method bindings from the 'mbsForClass' list which methods are - * inherited only (not defined in the class itself). - * - * @param mbsForClass - * The method bindings of the transformed class. - * @param cg - * The ClassGen object for the transformed class. - * @return A sublist of 'mbsForClass' containing all bindings for methods - * which are inherited only. - * - */ - private static List<MethodBinding> getInheritedBoundMethods(List<MethodBinding> mbsForClass, ClassGen cg) { - List<MethodBinding> inheritedBoundMethod = new LinkedList<MethodBinding>(); - Iterator<MethodBinding> it = mbsForClass.iterator(); - while (it.hasNext()) { - MethodBinding mb = it.next(); - if ((cg.containsMethod(mb.getBaseMethodName(), mb - .getBaseMethodSignature())) == null) - inheritedBoundMethod.add(mb); - } - return inheritedBoundMethod; - } -} diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/TeamInterfaceImplementation.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/TeamInterfaceImplementation.java deleted file mode 100644 index 8ce3abac3..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/TeamInterfaceImplementation.java +++ /dev/null @@ -1,1004 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2002-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: TeamInterfaceImplementation.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre; - -import org.apache.bcel.classfile.*; -import org.apache.bcel.generic.*; -import org.apache.bcel.*; - -import java.util.*; - -import org.eclipse.objectteams.otre.util.*; - -/** - * Adds the general Team infrastructure to team classes. - * - * Fields: public (static) final_OT$ID <- static if 'ot.no_static' ist set - * Methods: public int activate(int level) public int deactivate(int level) - * public int _OT$getID() Static initialization (adds clinit method, if not yet - * presented) OR to every constructor: <- if 'ot.no_static' is set _OT$ID = - * TeamIdDispenser.getTeamId(class_name) - * - * Enables implicit team activation for normal (user defined) public team-level - * methods. A call to 'activate' is woven at the beginning of the method. A call - * to 'deactivate' is woven before every return and at every thrown exception. - * - * @version $Id: TeamInterfaceImplementation.java 23408 2010-02-03 18:07:35Z stephan $ - * @author Christine Hundt - * @author Stephan Herrmann - */ -public class TeamInterfaceImplementation - extends ObjectTeamsTransformation { - - - public TeamInterfaceImplementation(ClassLoader loader, SharedState state) { - super(loader, state); - } - - /** - * @param cg - */ - public void doTransformCode(ClassGen cg) { - factory = new InstructionFactory(cg); - - if (!classNeedsTeamExtensions(cg)) { - return; - } - - ConstantPoolGen cpg = cg.getConstantPool(); - String class_name = cg.getClassName(); - genImplicitActivation(cg, cpg); - - InstructionList implicitSuperRoleRegistrations = genImplicitSuperRegistration(cg, cpg); - if (!implicitSuperRoleRegistrations.isEmpty()) { - // add implicitSuperRoleRegistrations to the static initializer: - Method clinitMethod = cg.containsMethod(Constants.STATIC_INITIALIZER_NAME, "()V"); - addToMethodStart(implicitSuperRoleRegistrations, clinitMethod, cg, cpg); - } - - if (CallinBindingManager.getBasesPerTeam(class_name) == null) { - return; // this team does not adapt any base class - } - - /** - * ******************* add initialization of the field '_OT$ID' to the static initializer : ****** - */ - int nextTeamId = TeamIdDispenser.getTeamId(class_name); - - /* - * The clinit method always exists at this moment, because it has - * been added by the interface transformer part of this transformer - * if necessary. - */ - addStaticInitializations(nextTeamId, cg, cpg); - } - - /** - * Add initialization of "_OT$ID" with 'nextTeamID' to the static - * initializer of this team class. - * - * @param nextTeamId - * the id which will be associated with the currently transformed - * team - * @param cg - * the ClassGen for the given team class - * @param cpg - * the constant pool ot the team - */ - private void addStaticInitializations(int nextTeamId, ClassGen cg, - ConstantPoolGen cpg) { - Method clinitMethod = cg.containsMethod( - Constants.STATIC_INITIALIZER_NAME, "()V"); - MethodGen mg = newMethodGen(clinitMethod, cg.getClassName(), cpg); - InstructionList il = mg.getInstructionList(); - - InstructionList addedInitialization = new InstructionList(); - addedInitialization.append(createIntegerPush(cpg, nextTeamId)); - addedInitialization.append(factory.createFieldAccess(cg.getClassName(), - "_OT$ID", Type.INT, Constants.PUTSTATIC)); - // generated: _OT$ID = <id dispensed by TeamIdDispenser>; - - // add static initialization for added static field at the beginning of - // the <clinit> method: - il.insert(addedInitialization); - mg.setMaxStack(); - mg.setMaxLocals(); - - Method newClinit = mg.getMethod(); - cg.replaceMethod(clinitMethod, newClinit); - - il.dispose(); // Reuse instruction handles - } - - /** - * For all roles in the current team which have tsuper versions: - * Generate instruction list containig calls to registration methods - * the implicit super roles. - * - * @param cg The ClassGen of the current team. - * @param cpg The constant pool of the current team. - * @return The instruction list containing the registration calls. - */ - private InstructionList genImplicitSuperRegistration(ClassGen cg, ConstantPoolGen cpg) { - InstructionList il = new InstructionList(); - List<String> inheritedRoleNames = getInheritedRoleNames(cg, cpg); - if (inheritedRoleNames.isEmpty()) - return il; // nothing to do - Iterator<String> iter = inheritedRoleNames.iterator(); - while (iter.hasNext()) { - String roleName = iter.next(); - String unqualifiedRoleName = roleName.substring(roleName.lastIndexOf('$') + 1); - if (CallinBindingManager.isBoundBaseAndRoleClass(roleName)) { - String potientialImplicitSuperRoleName = cg.getSuperclassName() + '$' + unqualifiedRoleName; - - if (!CallinBindingManager.isBoundBaseAndRoleClass(potientialImplicitSuperRoleName)) { - // Only bound base classes have the infrastructure for notifying - // implicit subclasses about team activation! - continue; - } - il.append(new PUSH(cpg, roleName)); - il.append(factory.createInvoke("java.lang.Class", "forName", - classType, new Type[] { Type.STRING }, - Constants.INVOKESTATIC)); - il.append(factory.createInvoke(potientialImplicitSuperRoleName, "_OT$registerObserver", - Type.VOID, new Type [] { classType }, - Constants.INVOKESTATIC)); - } - } - return il; - } - - public void doTransformInterface(ClassEnhancer ce, ClassGen cg) { - String class_name = cg.getClassName(); - ConstantPoolGen cpg = cg.getConstantPool(); - - checkReadClassAttributes(ce, cg, class_name, cpg); - - if (state.interfaceTransformedClasses.contains(class_name)) { - return; // class has already been transformed by this transformer - } - - if (!classNeedsTeamExtensions(cg)) { - return; - } - - factory = new InstructionFactory(cg); - - /** - * ********** empty implementation of the static class initialization method '<clinit>' *** - * NOTE: this is unnecessary in some cases, but checking is too complicated - */ - addStaticInitializer(cg, cpg, class_name, ce); - - List<String> handledBases = CallinBindingManager.getBasesPerTeam(class_name); - // TeamInterfaceImplementer only registers teams at bases, wich are part - // of a 'CallinRoleBaseBinding'-attribute of the team. - if (handledBases == null) { - return; // this team does not adapt any base class - } - - if(logging) printLogMessage("Adding the general Team infrastructure to " - + class_name); - - /** - * ******************* addition of the field '_OT$ID' - * ********************************** - */ - - int accessFlags = Constants.ACC_PUBLIC | Constants.ACC_FINAL | Constants.ACC_STATIC; - - FieldGen IDField = new FieldGen(accessFlags, Type.INT, "_OT$ID", cpg); - ce.addField(IDField.getField(), cg); - // generated global variable: public final static int _OT$ID; - - factory = new InstructionFactory(cpg); - InstructionList il; - - /** - * ******************* implementation of method '_OT$getID' - * ************************ - */ - - il = new InstructionList(); - MethodGen getIDMethod = new MethodGen(Constants.ACC_PUBLIC, Type.INT, - Type.NO_ARGS, new String[] {}, "_OT$getID", class_name, il, cpg); - - il.append(factory.createFieldAccess(class_name, "_OT$ID", Type.INT, - Constants.GETSTATIC)); - il.append(InstructionFactory.createReturn(Type.INT)); - - getIDMethod.setMaxStack(); - getIDMethod.setMaxLocals(); - - ce.addMethod(getIDMethod.getMethod(), cg); - - /** - * ***************** implementation of team (un)registration methods - * ********************** - */ - - ce.addMethod(generateTeamRegistrationMethod(cpg, class_name, - handledBases), cg); - - ce.addMethod(generateTeamUnregistrationMethod(cpg, class_name, - handledBases), cg); - - /** - * ***************** implementation of base call surrogtes for static methods - * ********************** - */ - Method [] base_call_surrogates = generateStaticBaseCallSurrogates(class_name, cpg, cg); - for(int i=0; i<base_call_surrogates.length;i++) { - // perhaps the compiler already generated an empty surrogate for an unbound super-role? - // (see X.1.5-otjld-callin-from-static-base-method-12a) - ce.addOrReplaceMethod(base_call_surrogates[i], cg); - } - - /** *************************************************************************** */ - - il.dispose(); - state.interfaceTransformedClasses.add(class_name); - } - - /** - * Add the given instruction list to the start of the givern method. - * @param additionalInstructions - * @param method - * @param cg - * @param cpg - */ - private void addToMethodStart(InstructionList additionalInstructions, Method method, ClassGen cg, ConstantPoolGen cpg) { - MethodGen mg = newMethodGen(method, cg.getClassName(), cpg); - InstructionList il = mg.getInstructionList(); - il.insert(additionalInstructions); - mg.setMaxStack(); - mg.setMaxLocals(); - - Method newMethod = mg.getMethod(); - cg.replaceMethod(method, newMethod); - il.dispose(); // Reuse instruction handles - } - - /** - * Generate the static initializer method 'clinit'. - * @param cpg The constant pool - * @param class_name The name of the class - * @param cg The ClassGen for the class - * @return The static initialier for this class - */ - void addStaticInitializer(ClassGen cg, ConstantPoolGen cpg, String class_name, ClassEnhancer ce) { - /* - * Adding static initializations requires the addition of the clinit - * method, if not yet presented. This requires synchronization with - * other transformers (TeamInterfaceImplementer) which may do the - * same this. This is done via 'TeamIdDispenser.clinitAdded(class_name)'. - */ - Method existingClinit = cg.containsMethod(Constants.STATIC_INITIALIZER_NAME, "()V"); - if (existingClinit == null && !TeamIdDispenser.clinitAdded(class_name, loader)) { - // otherwise the clinit-Method already exists and only has to be extended - // by the code transformation of this transformer - InstructionList il = new InstructionList(); - MethodGen clinitMethodGen = new MethodGen(Constants.ACC_STATIC, - Type.VOID, Type.NO_ARGS, new String[] {}, - Constants.STATIC_INITIALIZER_NAME, class_name, il, cpg); - - il.append(InstructionFactory.createReturn(Type.VOID)); - - clinitMethodGen.setMaxStack(); - clinitMethodGen.setMaxLocals(); - Method clinitMethod = clinitMethodGen.getMethod(); - ce.addMethod(clinitMethod, cg); - } - } - - /** - * Generates the ' _OT$registerAtBases()' method. This method registers the - * team at every adapted base class by calling the respective 'addTeam' - * method. - * - * @param cpg - * The ConstantPoolGen of the team class. - * @param class_name - * The name of the team class. - * @param handledBases - * The list of teams adapted by (roles of) this team. - * @return The generated 'activate' method. - */ - Method generateTeamRegistrationMethod(ConstantPoolGen cpg, - String class_name, List<String> handledBases) - { - InstructionList il = new InstructionList(); - MethodGen mg = new MethodGen(Constants.ACC_PUBLIC, Type.VOID, - Type.NO_ARGS, null, "_OT$registerAtBases", class_name, il, cpg); - - Iterator<String> it = handledBases.iterator(); - while (it.hasNext()) { - String actBase = it.next(); - //if (CallinBindingManager.hasBoundBaseParent(actBase)) - // continue; // team was already added to a super base class - // problem: bound base parent could be bound to another team class!!! - - //String boundBase = CallinBindingManager.getBoundBaseParent(actBase); - //if (boundBase != null && handledBases.contains(boundBase)) - // continue; - if (CallinBindingManager.teamAdaptsSuperBase(class_name, actBase)) - continue; - - InstructionHandle startTry = il.append(new ALOAD(0)); - - il.append(factory.createFieldAccess(class_name, "_OT$ID", Type.INT, - Constants.GETSTATIC)); - // Note: the method _OT$addTeam may be found in a super classes (topmostBoundBase), - // but we'll simply leave this lookup to the VM - il.append(factory.createInvoke(actBase, "_OT$addTeam", Type.VOID, - new Type[] { teamType, Type.INT }, Constants.INVOKESTATIC)); - // generated: <actBase>._OT$addTeam(this, _OT$ID); - - addNoSuchMethodErrorHandling(startTry, il.getEnd(), getErrorMessage(class_name, actBase, "Activation"), il, mg, cpg); - } - il.append(new RETURN()); - - mg.setMaxStack(); - mg.setMaxLocals(); - return mg.getMethod(); - } - - /** - * Direct inverse of generateTeamRegistrationMethod(..). Generates the ' - * _OT$unregisterFromBases' method. This method deregisters the team at - * every adapted base class by calling the respective 'removeTeam' method. - * - * @param cpg - * The ConstantPoolGen of the team class. - * @param class_name - * The name of the team class. - * @param handledBases - * The list of teams adapted by (roles of) this team. - * @return The generated 'deactivate' method. - */ - Method generateTeamUnregistrationMethod(ConstantPoolGen cpg, - String class_name, List<String> handledBases) { - - InstructionList il = new InstructionList(); - MethodGen mg = new MethodGen(Constants.ACC_PUBLIC, Type.VOID, - Type.NO_ARGS, null, "_OT$unregisterFromBases", class_name, il, - cpg); - - Iterator<String> it = handledBases.iterator(); - while (it.hasNext()) { - String actBase = it.next(); - //if (CallinBindingManager.hasBoundBaseParent(actBase)) - // continue; // team was only added to a super base class - // problem: bound base parent could be bound to another team class!!! - - // String boundBase = CallinBindingManager.getBoundBaseParent(actBase); - //if (boundBase != null && handledBases.contains(boundBase)) - // continue; - if (CallinBindingManager.teamAdaptsSuperBase(class_name, actBase)) - continue; - - InstructionHandle startTry = il.append(new ALOAD(0)); - - il.append(factory.createInvoke(actBase, "_OT$removeTeam", - Type.VOID, new Type[] { teamType }, Constants.INVOKESTATIC)); - // generated: <actBase>._OT$removeTeam(this, _OT$ID); - - addNoSuchMethodErrorHandling(startTry, il.getEnd(), getErrorMessage(class_name, actBase, "Deactivation"), il, mg, cpg); - } - il.append(new RETURN()); - - mg.setMaxStack(); - mg.setMaxLocals(); - return mg.getMethod(); - } - - private String getErrorMessage(String teamName, String baseName, String action) { - String errorMessage = action+" of team '" + teamName + "' failed! Callins of this team have NOT been WOVEN into base class '" + baseName + "'!\n" - + "This is probably caused by a loading order problem."; - return errorMessage; - } - - /** - * Adds an exception handler to the given method which catches 'java.lang.NoSuchMethodError's - * caused by missing team registration methods in base classes. Causes the throwing of an - * 'org.objectteams.UnsupportedFeatureException'. - * - * @param startTry handle to the start of the try block - * @param endTry handle to the end of the try block - * @param errorMessage the error message to be printed when throwing the exception - * @param il instruction list of the method - * @param mg MethodGen of the method - * @param cpg corresponding ConstantPoolGen - */ - private void addNoSuchMethodErrorHandling(InstructionHandle startTry, InstructionHandle endTry, - String errorMessage, InstructionList il, MethodGen mg, - ConstantPoolGen cpg) { - GOTO skipHdlr = null; - skipHdlr = new GOTO(null); - il.append(skipHdlr); - // generated: goto normal exit - - // throw away the expection reference: - InstructionHandle hdlr = il.append(new POP()); - - il.append(factory.createNew(OTConstants.unsupportedFeature)); - il.append(new DUP()); - il.append(new PUSH(cpg, errorMessage)); - il.append(factory.createInvoke(OTConstants.unsupportedFeature.getClassName(), - Constants.CONSTRUCTOR_NAME, - Type.VOID, - new Type[] { Type.STRING }, - Constants.INVOKESPECIAL)); - il.append(new ATHROW()); - - InstructionHandle nop = il.append(new NOP()); - skipHdlr.setTarget(nop); - mg.addExceptionHandler(startTry, endTry, hdlr, new ObjectType("java.lang.NoSuchMethodError")); - } - - /** - * Generate implicit Team activation for each "normal" public method. - * - * @param cg - * class for which methods are to be augmented. - * @param cpg - * the constant pool of the class 'cg'. - */ - void genImplicitActivation(ClassGen cg, ConstantPoolGen cpg) { - Method[] methods = cg.getMethods(); - for (int i = 0; i < methods.length; i++) { - Method m = methods[i]; - if (candidateForImplicitActivation(m, cg, cpg)) { - if(logging) printLogMessage("Adding implicit activation to " + m.getName()); - cg.replaceMethod(m, genImplicitActivation(m, cg.getClassName(), cpg, false)); - } - } - } - - /** - * Scans the team attribute StaticReplaceBinding and generates an array of base call surrogates - * - * @param class_name - * @param cpg - * @param cg - * @return - */ - private Method [] generateStaticBaseCallSurrogates(String class_name, ConstantPoolGen cpg, ClassGen cg){ - - Set<String> roleMethodKeys = new HashSet<String>(); - - //------------------------------------------------------------------------------------------ - // scan static replace bindings attributes - //------------------------------------------------------------------------------------------ - Attribute [] attributes = cg.getAttributes(); - for(int k=0; k<attributes.length; k++){ - - Unknown attr = isOTAttribute(attributes[k]); - if(attr == null) continue; - - if(attr.getName().equals("StaticReplaceBindings")) { - - byte[] indizes = attr.getBytes(); - int count = combineTwoBytes(indizes, 0); - int numberOfEntries=0; - String [] names; - numberOfEntries = 5; - int i = 2; - - for (int n=0; n<count;n++) { - names = new String[numberOfEntries]; - i = scanStrings(names, indizes, i, cpg); - int index = 0; - String role_name = names[index++]; - String role_method_name = names[index++]; - String role_method_signature = names[index++]; - String lift_method_name = names[index++]; - String lift_method_signature = names[index++]; - - String roleMethodKey = genRoleMethodKey(class_name, role_name, role_method_name, role_method_signature, lift_method_name, lift_method_signature); - roleMethodKeys.add(roleMethodKey); - - int base_len = combineTwoBytes(indizes, i); - BaseMethodInfo baseMethod; - i += 2; - names = new String[3]; - for (int n_base = 0; n_base < base_len; n_base++) { - int [] positions = null; - - i = scanStrings(names, indizes, i, cpg); - - int flags = indizes[i++]; - boolean baseIsCallin = (flags & 1) != 0; - boolean baseIsRoleMethod = (flags & 2) != 0; - boolean baseIsStatic = (flags & 4) != 0; - //parameter positions scanning - int pos_len = combineTwoBytes(indizes, i); - i+=2; - - if(pos_len > 0) { - positions = new int[pos_len]; - } - - for(int pos = 0; pos < pos_len; pos++){ - positions[pos] = combineTwoBytes(indizes,i); - i += 2; - } - int translationFlags = (combineTwoBytes(indizes, i)<<16) + combineTwoBytes(indizes, i+2); - i+=4; - baseMethod = new BaseMethodInfo(names[0], names[1], names[2], - baseIsCallin, baseIsRoleMethod, baseIsStatic, - positions, translationFlags); - - CallinBindingManager.assignBaseCallTag(names[0],names[1],names[2]); - CallinBindingManager.addStaticReplaceBindingForRoleMethod(roleMethodKey, baseMethod); - } - } - break; - } - } - - //------------------------------------------------------------------------------------------ - // generate base call surrogates - //------------------------------------------------------------------------------------------ - Iterator<String> roleMethodIter = roleMethodKeys.iterator(); - int count = roleMethodKeys.size(); - Method [] generatedSurrogates = new Method[count]; - - int j = 0; - - while(roleMethodIter.hasNext()) { - String roleMethodKey = roleMethodIter.next(); - LinkedList<BaseMethodInfo> baseMethods = CallinBindingManager.getStaticReplaceBindingsForRoleMethod(roleMethodKey); - - //split the key into team class name, role class name, role method name and role method signature - int firstPointIndex = roleMethodKey.indexOf(STATIC_REPLACE_BINDING_SEPARATOR); - int secondPointIndex = roleMethodKey.indexOf(STATIC_REPLACE_BINDING_SEPARATOR, firstPointIndex+1); - int thirdPointIndex = roleMethodKey.indexOf(STATIC_REPLACE_BINDING_SEPARATOR, secondPointIndex+1); - int fourthPointIndex = roleMethodKey.indexOf(STATIC_REPLACE_BINDING_SEPARATOR, thirdPointIndex+1); - int fifthPointIndex = roleMethodKey.indexOf(STATIC_REPLACE_BINDING_SEPARATOR, fourthPointIndex+1); - - String role_name = roleMethodKey.substring(firstPointIndex+2, secondPointIndex); - String role_method_name = roleMethodKey.substring(secondPointIndex+2, thirdPointIndex); - String role_method_signature = roleMethodKey.substring(thirdPointIndex+2, fourthPointIndex); - String lift_method_name = null; - String lift_method_signature = null; - // SH: without this check we get - // StringIndexOutOfBoundsException: String index out of range: -1 - // I hope this patch is correct.. - if ( fourthPointIndex + 2 <= fifthPointIndex - && fifthPointIndex + 2 < roleMethodKey.length()) - { - lift_method_name = roleMethodKey.substring(fourthPointIndex+2, fifthPointIndex); - lift_method_signature = roleMethodKey.substring(fifthPointIndex+2, roleMethodKey.length()); - } - - generatedSurrogates[j] = genBaseCallSurrogate(cg, role_name, role_method_name, - role_method_signature, - lift_method_name, lift_method_signature, baseMethods); - j++; - } - - return generatedSurrogates; - } - - /** - * Generates a base call surrogate for a given static role method - * @param cg - * @param role_name - * @param role_method_name - * @param role_method_signature - * @param lift_method_name - * @param lift_method_signature - * @param base_methods - * @return - */ - private Method genBaseCallSurrogate(ClassGen cg, - String role_name, - String role_method_name, - String role_method_signature, - String lift_method_name, - String lift_method_signature, - LinkedList<BaseMethodInfo> base_methods) - { - ConstantPoolGen cpg = cg.getConstantPool(); - String class_name = cg.getClassName(); - - if (base_methods.isEmpty()) { - return null; - } - Type[] enhancedArgumentTypes = enhanceArgumentTypes(Type.getArgumentTypes(role_method_signature)); - Type enhancedReturnType = generalizeReturnType(Type.getReturnType(role_method_signature)); - String[] enhancedArgumentNames = null; - InstructionList il = new InstructionList(); - int accessFlags = Constants.ACC_PROTECTED; - - MethodGen baseCallSurrogate = new MethodGen(accessFlags, - enhancedReturnType, - enhancedArgumentTypes, - enhancedArgumentNames, - getBaseCallSurrogateName(role_name, role_method_name), - class_name, - il, cpg); - - - LocalVariableGen otResult = null; - - /* - int slot = enhancedArgumentTypes.length+1; - otResult = baseCallSurrogate.addLocalVariable("_OT$result", - enhancedReturnType, - slot, null, null); - */ - otResult = baseCallSurrogate.addLocalVariable("_OT$result", - enhancedReturnType, null, null); - - il.insert(InstructionFactory.createStore(enhancedReturnType, - otResult.getIndex())); - il.insert(new ACONST_NULL()); - il.setPositions(); // about to retrieve instruction handles. - - if(logging) printLogMessage("base-call switch has to be inserted!"); - InstructionList loading = new InstructionList(); - loading.append(InstructionFactory.createThis()); - int index = 1; - for (int i = 0; i < enhancedArgumentTypes.length; i++) { - loading.append(InstructionFactory.createLoad(enhancedArgumentTypes[i],index)); - index += enhancedArgumentTypes[i].getSize(); - } - - Type[] argumentTypes = Type.getArgumentTypes(role_method_signature); - Type returnType = Type.getReturnType(role_method_signature); - - if (debugging) { - baseCallSurrogate.addLineNumber(il.getStart(), STEP_OVER_LINENUMBER); - } - - il.append(genBaseCallSwitch(cpg, base_methods, baseCallSurrogate, - argumentTypes, - returnType, - lift_method_name, - lift_method_signature, - otResult, loading, cg.getClassName())); - - il.append(InstructionFactory.createLoad(enhancedReturnType, otResult.getIndex())); - il.append(InstructionFactory.createReturn(enhancedReturnType)); - - il.setPositions(); - baseCallSurrogate.removeNOPs(); - baseCallSurrogate.setMaxStack(); - baseCallSurrogate.setMaxLocals(); - return baseCallSurrogate.getMethod(); - } - - private static String getBaseCallSurrogateName(String class_name, String method_name){ - // base call surrogate for static callin methods: - // name contains role class name and role method name, - // because its generated into the team. - return OT_PREFIX + class_name + "$" + method_name + "$base"; - } - - /** - * Generate a dispatching switch statement which calls the proper base method. - * @param cpg - * @param base_methods list of BaseMethodInfo that applies to this callin method - * @param enhancedMethod the enhanced callin method - * @param argumentTypes arg types of the callin method - * @param returnType the return type of the original callin method - * @param liftMethodSignature - * @param otResult the local variable storing the base call result - * @param loading an instruction list holding the original instructions for - * loading parameters - * @param teamName - * @param lift_method_name - * @return InstructionList the complete replacement implementing the base call. - */ - InstructionList genBaseCallSwitch (ConstantPoolGen cpg, - LinkedList<BaseMethodInfo> base_methods, MethodGen enhancedMethod, - Type[] argumentTypes, - Type returnType, String liftMethodName, String liftMethodSignature, - LocalVariableGen otResult, InstructionList loading, String teamName) - { - - short invocationKind = Constants.INVOKESTATIC; - - String className = enhancedMethod.getClassName(); - Type enhancedMethodReturnType = enhancedMethod.getReturnType(); - boolean callinHasReturnValue = returnType != Type.VOID; - - InstructionList il = new InstructionList(); - - // Setup a variable which holds the result of this base call. - // This variabel is local to this segment of code and used only - // to transport this result out off the switch statement. - int localResult = -1; - LocalVariableGen lg = null; - if (callinHasReturnValue) { - lg = enhancedMethod.addLocalVariable("_OT$tmpResult", returnType, - null, null); - localResult = lg.getIndex(); - il.append(InstructionFactory.createNull (returnType)); - il.append(InstructionFactory.createStore(returnType, localResult)); - } - - // ---- Prepare the switch: ---- - InstructionHandle switchStart = il.append - (InstructionFactory.createLoad(Type.INT, BASE_METH_ARG)); - // generated: _OT$baseMethTag - - //base_methods may contain duplicates! - //baseMethodTags is used to determine the number of cases without duplicates - HashSet<Integer> baseMethodTags = new HashSet<Integer>(); - Iterator<BaseMethodInfo> iter = base_methods.iterator(); - while(iter.hasNext()) { - BaseMethodInfo baseMethod = iter.next(); - //baseMethodTags.add(CallinBindingManager.getBaseCallTag( baseMethod.getBaseClassName(), - // baseMethod.getBaseMethodName(), - // baseMethod.getBaseMethodSignature())); - int baseMethodTag = CallinBindingManager.getBaseCallTag(baseMethod.getBaseClassName(), - baseMethod.getBaseMethodName(), - baseMethod.getBaseMethodSignature()); - baseMethodTags.add(Integer.valueOf(baseMethodTag)); - } - - // one break for each case clause - int numberOfCases = baseMethodTags.size(); - - GOTO[] breaks = new GOTO[numberOfCases]; - for (int i=0; i<numberOfCases; i++) - breaks[i] = new GOTO(null); - - int[] matches = new int[numberOfCases]; - InstructionHandle[] targets = new InstructionHandle[numberOfCases]; - int caseCounter = 0; - - //now baseMethodTags is used to store the handled tags - baseMethodTags.clear(); - - //JU: - Type[] enhancedMethodArguments = enhancedMethod.getArgumentTypes(); - Type[] enhancedArgumentsForBaseCall = new Type[enhancedMethodArguments.length - 1]; - System.arraycopy(enhancedMethodArguments, 0, - enhancedArgumentsForBaseCall, 0, - enhancedArgumentsForBaseCall.length); - - Iterator<BaseMethodInfo> it = base_methods.iterator(); - while (it.hasNext()) { - - BaseMethodInfo baseMethod = it.next(); - String baseClassName = baseMethod.getBaseClassName(); - String baseMethodName = baseMethod.getBaseMethodName(); - String baseMethodSignature = baseMethod.getBaseMethodSignature(); - int base_method_tag = CallinBindingManager.getBaseCallTag(baseClassName, baseMethodName, baseMethodSignature); - - //if the current baseMethod is a dulpicate: - // workaround for jdk 1.4: - Integer bmt = Integer.valueOf(base_method_tag); - //if(baseMethodTags.contains(base_method_tag)){ - if (baseMethodTags.contains(bmt)) { - continue; - } - - //baseMethodTags.add(base_method_tag); - baseMethodTags.add(bmt); - - int [] parameterPositions = baseMethod.getParameterPositions(); - int len = Type.getArgumentTypes(baseMethodSignature).length; - - // if the base method is a callin method as well, further enhance the signature: - if (baseMethod.isCallin) - len += EXTRA_ARGS; - - - matches[caseCounter] = CallinBindingManager.getBaseCallTag(baseClassName, baseMethodName, baseMethodSignature); - InstructionHandle nextBranch = il.append(new NOP()); - - Type[] baseMethodArgumentTypes = Type.getArgumentTypes(baseMethodSignature); - Type baseMethodReturnType = Type.getReturnType (baseMethodSignature); - String baseChainMethodName = genChainMethName(baseMethodName); - Type baseChainReturnType = object; // ALWAYS - Type[] enhancedBaseArgumentTypes = enhanceArgumentTypes(baseMethodArgumentTypes); - - boolean resultLiftingNecessary = false; - - // TODO (SH): if both types are ObjectType we should probably use subclassOf() ?? - // (don't lift if simple polymorphism suffices!) - //TODO: if the base method return type is a subtype of the role method return type no lifting has to take place!! is this allowed?? - //if (!returnTypeCompatible(baseMethodReturnType, returnType) && callinHasReturnValue) - if (/*!baseMethodReturnType.equals(object) &&*/ - !baseMethodReturnType.equals(returnType) - && !(baseMethodReturnType instanceof BasicType) // requires boxing not lifting - && !(returnType instanceof BasicType) // requires unboxing not lifting - && callinHasReturnValue) - { - resultLiftingNecessary = true; - } - - // --- load arguments of the new method: --- - // (letters refer to document parameter-passing.odg) - - // (u) generate extra arguments (indices are equal at role and base): - for (int idx = 0; idx < EXTRA_ARGS; idx++) - il.append(InstructionFactory.createLoad(enhancedMethodArguments[idx], - idx+1)); // first arg is "this" (enclosing team) - - // (v)(w)(x) split loading sequence and transfer source-level arguments - // (includes reverse-application of parameter mappings): - InstructionHandle baseCallLine = il.append(translateLoads(splitLoading(cpg, - loading.copy(), - argumentTypes), - enhancedMethodArguments, - enhancedBaseArgumentTypes, - parameterPositions, - teamName, - null, - baseMethod, - EXTRA_ARGS/*start*/, - cpg)); - // --- done loading --- - - // invoke the chaining method of the base class (base-call!): - il.append(factory.createInvoke(baseClassName, - baseChainMethodName, - baseChainReturnType, - enhancedBaseArgumentTypes, - invocationKind)); - - // FIXME(SH): if this assert holds, remove computing of resultLiftingNecessary above. - assert resultLiftingNecessary == ((baseMethod.translationFlags & 1) != 0); - - if (resultLiftingNecessary) { // call the lift-method: - Type[] liftMethodArgs = Type.getArgumentTypes(liftMethodSignature); - Type liftMethodReturnType = Type.getReturnType(liftMethodSignature); - - // cast result of base call: - il.append(factory.createCast(baseChainReturnType, baseMethodReturnType)); - - // load the team instance at which to call the lift method: - il.append(InstructionFactory.createThis()); - il.append(factory.createCast(object, new ObjectType(teamName))); - - // put them in correct order: - il.append(new SWAP()); // -> .., this$0, (BaseType)result - - il.append(factory.createInvoke(teamName, - liftMethodName, - liftMethodReturnType, - liftMethodArgs, - Constants.INVOKEVIRTUAL)); - } - - // adjust the return value to the type expected by the WRAPPER: - il.append(new DUP()); // keep for adjustment below - if (!resultLiftingNecessary) - adjustValue(il, null, baseChainReturnType, enhancedMethodReturnType); - il.append(InstructionFactory.createStore(enhancedMethodReturnType, - otResult.getIndex())); // store "globally" - // this store is needed to tunnel unused results through the callin. - - InstructionHandle afterBaseCallLine = il.append(new NOP()); - - // adjust the return value to the type expected by the ORIGINAL CALLIN: - adjustValue(il, null, baseChainReturnType, returnType); - if (callinHasReturnValue) { - il.append(InstructionFactory.createStore(returnType, localResult)); // store "locally" - } - // this store is useful for callins which make use of the result. - - targets[caseCounter] = nextBranch; - il.append(breaks[caseCounter]); - // generated: break; - - caseCounter++; - - if (debugging) { - enhancedMethod.addLineNumber(baseCallLine, STEP_INTO_LINENUMBER); - enhancedMethod.addLineNumber(afterBaseCallLine, STEP_OVER_LINENUMBER); - } - } - - //JU: added the follwing part (begin) ----------------------------------------------------- - InstructionHandle defaultBranch = il.append(new NOP()); - - if (logging) - printLogMessage("Exeption has to be thrown! Base-Call is impossible."); - - il.append(factory.createNew(OTConstants.unsupportedFeature)); - il.append(new DUP()); - // ## FIXME: fix otld$ - il.append(new PUSH(cpg, "Binding-Error: base-call from " + className + "." + enhancedMethod.getName() - + "impossible! This problem is documented in OTLD $XY.")); - il.append(factory.createInvoke(OTConstants.unsupportedFeature.getClassName(), - Constants.CONSTRUCTOR_NAME, - Type.VOID, - new Type[] { Type.STRING }, - Constants.INVOKESPECIAL)); - il.append(new ATHROW()); - //JU: (end) -------------------------------------------------------------------------------- - - InstructionHandle afterSwitch = il.append(new NOP()); // all breaks point here. - - il.append(switchStart, createLookupSwitch(matches, targets, breaks, - defaultBranch, afterSwitch)); - - // retrieve locally stored result: - if (callinHasReturnValue) { - il.append(InstructionFactory.createLoad(returnType, localResult)); - lg.setStart(il.getStart()); // restrict local variable to this segment. - lg.setEnd(il.getEnd()); - } - return il; - } - - /** - * Generates a key for the given role method parameters - * - * @param teamClassName - * @param roleClassName - * @param roleMethodName - * @param roleMethodSignature - * @param liftMethodSignature - * @return - */ - private static String genRoleMethodKey(String teamClassName, - String roleClassName, String roleMethodName, - String roleMethodSignature, String liftMethodName, - String liftMethodSignature) - { - StringBuilder roleMethodKey = new StringBuilder(64); - roleMethodKey.append(teamClassName); - roleMethodKey.append(STATIC_REPLACE_BINDING_SEPARATOR); - roleMethodKey.append(roleClassName); - roleMethodKey.append(STATIC_REPLACE_BINDING_SEPARATOR); - roleMethodKey.append(roleMethodName); - roleMethodKey.append(STATIC_REPLACE_BINDING_SEPARATOR); - roleMethodKey.append(roleMethodSignature); - roleMethodKey.append(STATIC_REPLACE_BINDING_SEPARATOR); - roleMethodKey.append(liftMethodName); - roleMethodKey.append(STATIC_REPLACE_BINDING_SEPARATOR); - roleMethodKey.append(liftMethodSignature); - return roleMethodKey.toString(); - } - - /** - * Read the InheritedRoles attribute and return the list of inherited roles. - * @param cg The ClassGen of the inspected class. - * @param cpg The constant pool of the instpected class. - * @return A list of inherited role names. - */ - private List<String> getInheritedRoleNames(ClassGen cg, ConstantPoolGen cpg) { - Attribute[] attributes = cg.getAttributes(); - LinkedList<String> inheritedRoleNames = new LinkedList<String>(); - for (int i = 0; i < attributes.length; i++) { - Attribute actAttr = attributes[i]; - if (actAttr instanceof Unknown) { - Unknown attr = (Unknown)actAttr; - byte[] indizes = attr.getBytes(); - int count = combineTwoBytes(indizes, 0); - if (attr.getName().equals("InheritedRoles")) { - int j = 2; - while (j<=2*count) { - String[] names = new String[1]; - j = scanStrings(names, indizes, j, cpg); - String inherited_role = names[0]; - inheritedRoleNames.add(inherited_role); - } - } - } - } - return inheritedRoleNames; - } -} diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/ThreadActivation.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/ThreadActivation.java deleted file mode 100644 index 983929721..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/ThreadActivation.java +++ /dev/null @@ -1,181 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2002-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: ThreadActivation.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre; - -import java.util.HashSet; - -import org.apache.bcel.classfile.*; -import org.apache.bcel.generic.*; -import org.apache.bcel.*; - -import static org.eclipse.objectteams.otre.ObjectTeamsTransformation.newMethodGen; - -/** - * This transformer inserts a notification call to the TeamThreadManager at the - * beginning of every run()-Method in Subtypes of java.lang.Thread or java.lang.Runnable. - * Thre TeamThreadManager then ensures the thread activation of the current thread - * for every global active team instance. - * - * @author Christine Hundt - * @author Stephan Herrmann - */ -public class ThreadActivation -{ - // name of a generated field that stores the thread which created a given runnable: - private static final String CREATION_THREAD = "_OT$creationThread"; - HashSet<String> transformableClasses = new HashSet<String>(); - - private boolean shouldTransform(ClassGen cg) { - Method runMethode = cg.containsMethod("run", "()V"); - if (runMethode == null || runMethode.isAbstract()) { - // this class contains no concrete run() method - return false; - } - String class_name = cg.getClassName(); - // check if this class is a subtype of Thread or Runnable: - try { - return RepositoryAccess.implementationOf(class_name, "java.lang.Runnable") || RepositoryAccess.instanceOf(class_name, "java.lang.Thread"); - } catch (ClassNotFoundException cfne) { - if (ObjectTeamsTransformation.WORKAROUND_REPOSITORY) { - return false; - } - else - throw new RuntimeException("Could not find class being loaded", cfne); // rethrow - } - } - public void doTransformInterface(ClassEnhancer enhancer, ClassGen cg) { - if (!shouldTransform(cg)) - return; - - // if class is already transformed by this transformer - if (this.transformableClasses.contains(cg.getClassName())) - return; - - this.transformableClasses.add(cg.getClassName()); - FieldGen field = new FieldGen(Constants.ACC_PRIVATE, OTConstants.threadType, CREATION_THREAD, cg.getConstantPool()); - enhancer.addField(field.getField(), cg); - } - /** - * - */ - public void doTransformCode(ClassGen cg) { - if (!this.transformableClasses.contains(cg.getClassName())) - return; - - this.transformableClasses.remove(cg.getClassName()); - - InstructionFactory factory = new InstructionFactory(cg); - - for (Method method : cg.getMethods()) { - MethodGen mg = isRootCtor(method, cg); - if (mg != null) - enhanceConstructor(cg, factory, method, mg); - } - - enhanceRunMethod(cg, factory); - } - private void enhanceRunMethod(ClassGen cg, InstructionFactory factory) { - String class_name = cg.getClassName(); - ConstantPoolGen cpg = cg.getConstantPool(); - - Method runMethode = cg.containsMethod("run", "()V"); // existence checked in transformInterface - - MethodGen mg = newMethodGen(runMethode, class_name, cpg); - InstructionList il = mg.getInstructionList(); - InstructionHandle try_start = il.getStart(); - - /** *** Insert a call to TeamThreadManager.newThreadStarted() at the beginning of the run() method: ****** */ - InstructionList threadActivation = new InstructionList(); - threadActivation.append(new ICONST(0)); // isMain = false - threadActivation.append(InstructionConstants.ALOAD_0); // parent=this._OT$creationThread; - threadActivation.append(factory.createFieldAccess(class_name, CREATION_THREAD, OTConstants.threadType, Constants.GETFIELD)); - threadActivation.append(factory.createInvoke("org.objectteams.TeamThreadManager", - "newThreadStarted", - Type.BOOLEAN, - new Type[]{Type.BOOLEAN, OTConstants.threadType}, - Constants.INVOKESTATIC)); - LocalVariableGen flag = mg.addLocalVariable("_OT$isThreadStart", Type.BOOLEAN, il.getStart(), il.getEnd()); - threadActivation.append(new ISTORE(flag.getIndex())); - il.insert(threadActivation); - - /** *** Insert a call to TeamThreadManager.threadEnded() before every return of the run() method: ******** */ - InstructionList threadDeactivation = new InstructionList(); - threadDeactivation.append(new ILOAD(flag.getIndex())); - BranchInstruction ifIsThreadStarted = new IFEQ(null); - threadDeactivation.append(ifIsThreadStarted); - threadDeactivation.append(factory.createInvoke("org.objectteams.TeamThreadManager", - "threadEnded", - Type.VOID, - Type.NO_ARGS, - Constants.INVOKESTATIC)); - ifIsThreadStarted.setTarget(threadDeactivation.append(new NOP())); - - ObjectTeamsTransformation.insertBeforeReturn(mg, il, threadDeactivation); - - /** **** Add an exception handler which calls TeamThreadManager.threadEnded() ***** - * ***** before throwing the exception (finaly-simulation): */ - ObjectType throwable = new ObjectType("java.lang.Throwable"); - LocalVariableGen exception = mg.addLocalVariable( - "_OT$thrown_exception", throwable, null, null); - InstructionHandle try_end = il.getEnd(); - InstructionList deactivation_ex = threadDeactivation.copy(); - deactivation_ex.insert(InstructionFactory.createStore(throwable, exception.getIndex())); - deactivation_ex.append(InstructionFactory.createLoad(throwable, exception.getIndex())); - deactivation_ex.append(new ATHROW()); - InstructionHandle deactivation_handler = il.append(il.getEnd(), deactivation_ex); - mg.addExceptionHandler(try_start, try_end, deactivation_handler, throwable); - /** ******************************************************************** */ - - mg.setMaxStack(); - mg.setMaxLocals(); - Method generatedMethod = mg.getMethod(); - cg.replaceMethod(runMethode, generatedMethod); - threadActivation.dispose(); - il.dispose(); - } - // is method a constructor that does not invoke another this()-ctor? - @SuppressWarnings("deprecation") - private MethodGen isRootCtor(Method method, ClassGen cg) { - if (!method.getName().equals("<init>")) - return null; - String className = cg.getClassName(); - ConstantPoolGen cpg = cg.getConstantPool(); - MethodGen mg = newMethodGen(method, className, cpg); - InstructionList il = mg.getInstructionList(); - InstructionHandle ih = il.getStart(); - while (ih != null && ih.getInstruction().getOpcode() != Constants.INVOKESPECIAL) { - ih = ih.getNext(); - } - if (ih == null) - return null; - if (((InvokeInstruction)ih.getInstruction()).getClassName(cpg).equals(className)) // unsafe due to object/array ambiguity, but we have no array (is an invokespecial!) - return null; // this-call - return mg; - } - // add statements to store the thread that created this runnable - private void enhanceConstructor(ClassGen cg, InstructionFactory factory, Method initMethod, MethodGen mg) { - String class_name = cg.getClassName(); - InstructionList il = mg.getInstructionList(); - il.insert(il.getEnd(), InstructionConstants.ALOAD_0); - il.insert(il.getEnd(), factory.createInvoke("java.lang.Thread", "currentThread", OTConstants.threadType, new Type[0], Constants.INVOKESTATIC)); - il.insert(il.getEnd(), factory.createFieldAccess(class_name, CREATION_THREAD, OTConstants.threadType, Constants.PUTFIELD)); - mg.setMaxStack(); - mg.setMaxLocals(); - cg.replaceMethod(initMethod, mg.getMethod()); - il.dispose(); - } -} diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/jplis/JPLISEnhancer.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/jplis/JPLISEnhancer.java deleted file mode 100644 index 10d2c7d00..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/jplis/JPLISEnhancer.java +++ /dev/null @@ -1,143 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2005-2008 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: JPLISEnhancer.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre.jplis; - - -import java.io.IOException; -import java.io.InputStream; - -import org.eclipse.objectteams.otre.ClassEnhancer; -import org.eclipse.objectteams.otre.OTREInternalError; -import org.eclipse.objectteams.otre.ObjectTeamsTransformation; - -import org.apache.bcel.Constants; -import org.apache.bcel.classfile.ClassParser; -import org.apache.bcel.classfile.Field; -import org.apache.bcel.classfile.Method; -import org.apache.bcel.classfile.Utility; -import org.apache.bcel.generic.ClassGen; -import org.apache.bcel.generic.ConstantPoolGen; -import org.apache.bcel.generic.MethodGen; - - -/** -* This class implements the ClassEnhancer interface with the JPLIS (Java5) specific behavior. -* -* @author Christine Hundt -* @author Juergen Widiker -* @author Stephan Herrmann -*/ - -public class JPLISEnhancer implements ClassEnhancer { - - private ClassLoader loader; - - public JPLISEnhancer(ClassGen cg, ClassLoader loader) { - this.loader = loader; - } - - /* (non-Javadoc) - * @see org.eclipse.objectteams.otre.ClassEnhancer#addImplements(java.lang.String, org.apache.bcel.generic.ClassGen) - */ - public void addImplements(String interfaceName, ClassGen cg) { - cg.addInterface(interfaceName); - } - - /* (non-Javadoc) - * @see org.eclipse.objectteams.otre.common.ClassEnhancer#addMethod(org.apache.bcel.classfile.Method, de.fub.bytecode.generic.ClassGen) - */ - public void addMethod(Method m, ClassGen cg) { - if (cg.containsMethod(m.getName(), m.getSignature()) != null) - new OTREInternalError("Warning: repetive adding of method " - + m.getName() + m.getSignature() - + " to class " + cg.getClassName()) - .printStackTrace(); - cg.addMethod(m); - } - - public void addOrReplaceMethod(Method method, ClassGen cg) { - Method existingMethod = cg.containsMethod(method.getName(), method.getSignature()); - if (existingMethod == null) - addMethod(method, cg); - else - cg.replaceMethod(existingMethod, method); - } - - /* (non-Javadoc) - * @see org.eclipse.objectteams.otre.common.ClassEnhancer#addField(org.apache.bcel.classfile.Field, de.fub.bytecode.generic.ClassGen) - */ - public void addField(Field f, ClassGen cg) { - if (cg.containsField(f.getName()) != null) - new OTREInternalError("Warning: repetitive adding of field " - + f.getName() + f.getSignature() - + " to class " + cg.getClassName()) - .printStackTrace(); - cg.addField(f); - } - - /* (non-Javadoc) - * @see org.eclipse.objectteams.otre.common.ClassEnhancer#loadClass(java.lang.String) - */ - public void loadClass(String className, ObjectTeamsTransformation client) { - // SH: no forced class loading within OT/Equinox - if(System.getProperty("ot.equinox") != null) - return; - try { - String binaryName = className.replace('.', '/'); - InputStream is = loader.getResourceAsStream(binaryName+".class"); - if (is != null) { - ClassGen cg = new ClassGen(new ClassParser(is, className).parse()); - client.checkReadClassAttributes(this, cg, className, cg.getConstantPool()); - } - } catch (IOException ex) { - ex.printStackTrace(); - } - } - - /* (non-Javadoc) - * @see org.eclipse.objectteams.otre.common.ClassEnhancer#decapsulateMethod(org.apache.bcel.classfile.Method, java.lang.String, de.fub.bytecode.generic.ConstantPoolGen) - */ - public void decapsulateMethod(Method m, ClassGen cg, String packageName, ConstantPoolGen cpg) { - String className = cg.getClassName(); - int flags = m.getAccessFlags(); - MethodGen mg = new MethodGen(m, className, cpg); // no need to remove attributes, code remains unchanged - - if ((flags & Constants.ACC_PUBLIC) == 0) { - int newFlags = flags; - newFlags &= ~(Constants.ACC_PROTECTED|Constants.ACC_PRIVATE); // clear old visibility - newFlags |= Constants.ACC_PUBLIC; // set new visibility - mg.setAccessFlags(newFlags); - if(System.getProperty("ot.log") != null) - ObjectTeamsTransformation.printLogMessage("Adjusting from " - + Utility.accessToString(flags) - + " to public:\n\t" - + className - + "." + m); - if (!packageName.equals("NO_PACKAGE")) - checkSeal(packageName, className); - } - cg.replaceMethod(m, mg.getMethod()); - } - - private static void checkSeal(String package_name, String class_name) { - Package pckg = Package.getPackage(package_name); - if ( (pckg != null) && pckg.isSealed()) - throw new IllegalAccessError( - "OT/J callout binding:\n" - +"Trying to break sealed "+pckg); - } -} diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/jplis/ObjectTeamsTransformer.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/jplis/ObjectTeamsTransformer.java deleted file mode 100644 index d0f5d05ac..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/jplis/ObjectTeamsTransformer.java +++ /dev/null @@ -1,272 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2005-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: ObjectTeamsTransformer.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre.jplis; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.lang.instrument.ClassFileTransformer; -import java.lang.instrument.IllegalClassFormatException; -import java.security.ProtectionDomain; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.bcel.classfile.ClassParser; -import org.apache.bcel.classfile.JavaClass; -import org.apache.bcel.generic.ClassGen; -import org.apache.bcel.util.ClassLoaderRepository; -import org.eclipse.objectteams.otre.BaseCallRedirection; -import org.eclipse.objectteams.otre.BaseMethodTransformation; -import org.eclipse.objectteams.otre.Decapsulation; -import org.eclipse.objectteams.otre.LiftingParticipantTransformation; -import org.eclipse.objectteams.otre.OTConstants; -import org.eclipse.objectteams.otre.ObjectTeamsTransformation; -import org.eclipse.objectteams.otre.RepositoryAccess; -import org.eclipse.objectteams.otre.StaticSliceBaseTransformation; -import org.eclipse.objectteams.otre.SubBoundBaseMethodRedefinition; -import org.eclipse.objectteams.otre.TeamInterfaceImplementation; -import org.eclipse.objectteams.otre.ThreadActivation; -import org.eclipse.objectteams.otre.util.AttributeReadingGuard; -import org.eclipse.objectteams.otre.util.CallinBindingManager; - - -/** - * Main entry into the OTRE when using JPLIS - * - * @author Christine Hundt - * @author Stephan Herrmann - */ -public class ObjectTeamsTransformer implements ClassFileTransformer { - - // force loading all transformer classes to reduce risk of deadlock in class loading. - static Class<?>[] transformerClasses = new Class<?>[] { - BaseCallRedirection.class, - BaseMethodTransformation.class, - Decapsulation.class, - LiftingParticipantTransformation.class, - StaticSliceBaseTransformation.class, - SubBoundBaseMethodRedefinition.class, - TeamInterfaceImplementation.class, - ThreadActivation.class - }; - - /** - * One instance of this class is used per class loader to ensure disjoint scopes. - */ - static class StateGroup { - ObjectTeamsTransformation.SharedState bcrState = new ObjectTeamsTransformation.SharedState(); - ObjectTeamsTransformation.SharedState bmtState = new ObjectTeamsTransformation.SharedState(); - Decapsulation.SharedState decState = new Decapsulation.SharedState(); - ObjectTeamsTransformation.SharedState lptState = new ObjectTeamsTransformation.SharedState(); - ObjectTeamsTransformation.SharedState ssbtState = new ObjectTeamsTransformation.SharedState(); - ObjectTeamsTransformation.SharedState sbbmrState = new ObjectTeamsTransformation.SharedState(); - ObjectTeamsTransformation.SharedState tiiState = new ObjectTeamsTransformation.SharedState(); - } - static Map<ClassLoader, StateGroup> states = new HashMap<ClassLoader, StateGroup>(); - - static boolean warmedUp = false; - /* - * (non-Javadoc) - * - * @see java.lang.instrument.ClassFileTransformer#transform(java.lang.ClassLoader, - * java.lang.String, java.lang.Class, java.security.ProtectionDomain, - * byte[]) - */ - public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, - ProtectionDomain protectionDomain, byte[] classfileBuffer) - throws IllegalClassFormatException - { - if (warmedUp) - return internalTransform(loader, className, classBeingRedefined, protectionDomain, classfileBuffer); - synchronized (loader) { - try { - return internalTransform(loader, className, classBeingRedefined, protectionDomain, classfileBuffer); - } finally { - warmedUp = true; - } - } - } - public byte[] internalTransform(ClassLoader loader, String className, Class<?> classBeingRedefined, - ProtectionDomain protectionDomain, byte[] classfileBuffer) - throws IllegalClassFormatException - { - if ( className.startsWith("org/eclipse/objectteams/otre") - || className.startsWith("org/apache/bcel") - || className.equals("java/util/LinkedHashMap$KeyIterator")) // saw class loading circularity caused by accessing this class - { - // skip OTRE and BCEL classes - return null; - } - if (classBeingRedefined != null) { - System.out.println("Redefinition!"); - return null; - } - - // state sharing among transformers: - StateGroup states = ObjectTeamsTransformer.states.get(loader); - if (states == null) - ObjectTeamsTransformer.states.put(loader, states = new StateGroup()); - // - // One fresh instance of each transformer for a given class: - // - BaseCallRedirection baseCallRedirection - = new BaseCallRedirection( loader, states.bcrState); - BaseMethodTransformation baseMethodTransformation - = new BaseMethodTransformation( loader, states.bmtState); - Decapsulation decapsulation - = new Decapsulation( loader, states.decState); - LiftingParticipantTransformation liftingParticipantTransformation - = new LiftingParticipantTransformation( loader, states.lptState); - StaticSliceBaseTransformation staticSliceBaseTransformation - = new StaticSliceBaseTransformation( loader, states.ssbtState); - SubBoundBaseMethodRedefinition subBoundBaseMethodRedefinition - = new SubBoundBaseMethodRedefinition( loader, states.sbbmrState); - TeamInterfaceImplementation teamInterfaceImplementation - = new TeamInterfaceImplementation( loader, states.tiiState); - ThreadActivation threadActivation - = new ThreadActivation(); - - // tell Repository about the class loader for improved lookupClass() - ClassLoaderRepository prevRepository = RepositoryAccess.setClassLoader(loader); - - InputStream is = new ByteArrayInputStream(classfileBuffer); - try { - JavaClass java_class = new ClassParser(is, className).parse(); - //Repository.addClass(java_class); - ClassGen cg = new ClassGen(java_class); - - JPLISEnhancer jpe = new JPLISEnhancer(cg, loader); - - Collection<String> adaptedBases; // [OT/Equinox] - // [OT/Equinox] remember the first transformation which holds adaptedBases - adaptedBases= setFirstTransformation(subBoundBaseMethodRedefinition); - // [OT/Equinox] if class has previously been transformed fetch the list of - // adapted bases from the CallinBindingManager instead of reading it now. - if ( (cg.getAccessFlags() & OTConstants.TEAM) != 0 - && !AttributeReadingGuard.getInstanceForLoader(loader).iAmTheFirst(cg.getClassName())) - { - List<String> basesOfTeam = CallinBindingManager.getBasesPerTeam(cg.getClassName()); - if (basesOfTeam != null) - adaptedBases.addAll(basesOfTeam); - } - subBoundBaseMethodRedefinition.doTransformInterface(jpe, cg); - baseCallRedirection.doTransformInterface(jpe, cg); - decapsulation.doTransformInterface(jpe, cg); - try { - baseMethodTransformation.useReflection = (loader == null); // bootstrap classes cannot be called directly - baseMethodTransformation.doTransformInterface(jpe, cg); - } catch (Throwable t) { - System.err.println("Error transforming class: "+cg.getClassName()); - t.printStackTrace(); - } - staticSliceBaseTransformation.doTransformInterface(jpe, cg); - teamInterfaceImplementation.doTransformInterface(jpe, cg); - -// subBoundBaseMethodRedefinition.doTransformInterface(jpe, cg); -// baseCallRedirection.doTransformInterface(jpe, cg); -// decapsulation.doTransformInterface(jpe, cg); -// baseMethodTransformation.doTransformInterface(jpe, cg); -// staticSliceBaseTransformation.doTransformInterface(jpe, cg); -// teamInterfaceImplementation.doTransformInterface(jpe, cg); - threadActivation.doTransformInterface(jpe, cg); - - -// baseCallRedirection.doTransformCode(cg); // empty method - baseMethodTransformation.doTransformCode(cg); - liftingParticipantTransformation.doTransformCode(cg); - staticSliceBaseTransformation.doTransformCode(cg); - teamInterfaceImplementation.doTransformCode(cg); - threadActivation.doTransformCode(cg); - - JavaClass new_java_class = cg.getJavaClass(); - if (dumping) { - new_java_class.dump("jplis_dump/" + className + ".class"); - } - return new_java_class.getBytes(); - } catch (IOException e) { - System.err.println("ClassFileTransformer could not parse class file buffer to JavaClass"); - e.printStackTrace(); - } catch (RuntimeException re) { - re.printStackTrace(); - throw re; - } finally { - // restore previous repository: - RepositoryAccess.resetRepository(prevRepository); - } - return null; - } - - /** - * External API (for OT/Equinox): - * Destructively fetch the set of adapted base classes - * recorded since the last call to this method. - * - * @return - */ - public Collection<String> fetchAdaptedBases() { - if (this.firstTransformation == null) - return null; - Collection<String>result= this.firstTransformation.fetchAdaptedBases(); - this.firstTransformation= null; - return result; - } - - /** - * External API (for OT/Equinox): - * Read the OT-Attributes of a class without loading the class. - * @throws IOException - * @throws ClassFormatError - */ - public void readOTAttributes(InputStream file, String fileName, ClassLoader loader) - throws ClassFormatError, IOException - { - ClassParser cp = new ClassParser(file, fileName); - ClassGen cg = new ClassGen(cp.parse()); - JPLISEnhancer jpe = new JPLISEnhancer(cg, /*loader (unused)*/null); - ClassLoaderRepository prevRepository = RepositoryAccess.setClassLoader(loader); - try { - setFirstTransformation(new ObjectTeamsTransformation(loader, null) {}); - firstTransformation.checkReadClassAttributes(jpe, cg, cg.getClassName(), cg.getConstantPool()); - } finally { - RepositoryAccess.resetRepository(prevRepository); - } - } - - // helper structure for above: - /* The first transformation performed holds the list of adapted bases. */ - private ObjectTeamsTransformation firstTransformation; - - /* @return the collection of adapted bases currently in use. */ - private Collection<String> setFirstTransformation(ObjectTeamsTransformation t) { - if (this.firstTransformation != null) - t.adaptedBases= this.firstTransformation.adaptedBases; // collect into existing - this.firstTransformation= t; - return t.adaptedBases; - } - - // ------------------------------------------ - // ---------- Class file dumping: ---------------------- - // ------------------------------------------ - /** Initialized from property <tt>ot.dump</tt>. */ - static boolean dumping = false; - static { - if(System.getProperty("ot.dump")!=null) - dumping = true; - } -} diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/jplis/otreAgent.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/jplis/otreAgent.java deleted file mode 100644 index ee6077f11..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/jplis/otreAgent.java +++ /dev/null @@ -1,48 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2005-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: otreAgent.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre.jplis; - -import java.lang.instrument.Instrumentation; - -/** -* -* @version $Id: otreAgent.java 23408 2010-02-03 18:07:35Z stephan $ -* @author Christine Hundt -*/ -public class otreAgent { - - private static Instrumentation instCopy; -// private static String optionsCopy; - - private static ObjectTeamsTransformer otTransformer; - - public static void premain(String options, Instrumentation inst) { - instCopy = inst; -// optionsCopy = options; - - // add all necessary transformers: - otTransformer = new ObjectTeamsTransformer(); - instCopy.addTransformer(otTransformer); - - /* All future class definitions will be seen by the transformer, - except definitions of classes upon which any registered transformer is dependent. */ - } - - public static Instrumentation getInstrumentation() { - return instCopy; - } -} diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/AnnotationHelper.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/AnnotationHelper.java deleted file mode 100644 index 0b45daae6..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/AnnotationHelper.java +++ /dev/null @@ -1,102 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2009 Stephan Herrmann - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id$ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Stephan Herrmann - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre.util; - -import org.eclipse.objectteams.otre.ObjectTeamsTransformation; -import org.objectteams.ImplicitTeamActivation; - -import org.apache.bcel.classfile.Attribute; -import org.apache.bcel.classfile.Unknown; -import org.apache.bcel.generic.ConstantPoolGen; - -/** - * Helper class for parsing / skipping runtime visible annotations. - * - * @author stephan - * @since 1.4.0 - */ -public class AnnotationHelper { - - /** - * Does any of the given attributes contain an {@link ImplicitTeamActivation} annotation? - * @param attrs attributes to inspect - * @param cpg constant pool for string lookup - * @return true if an {@link ImplicitTeamActivation} annotation was found. - */ - public static boolean containsImplicitActivationAttribute(Attribute[] attrs, ConstantPoolGen cpg) { - if (attrs != null) { - for (Attribute attr : attrs) { - if (attr instanceof Unknown && ((Unknown)attr).getName().equals("RuntimeVisibleAnnotations")) { - Unknown unknown = (Unknown) attr; - byte[] bytes = unknown.getBytes(); - int len = ObjectTeamsTransformation.combineTwoBytes(bytes, 0); - int i = 2; - String[] names = new String[1]; - for (int n=0; n<len; n++) { - i = ObjectTeamsTransformation.scanStrings(names, bytes, i, cpg); - if ("Lorg/objectteams/ImplicitTeamActivation;".equals(names[0])) - return true; - i = skipNameValuePairs(bytes, i, names[0], cpg); - } - } - } - } - return false; - } - - private static int skipNameValuePairs(byte[] bytes, int i, String typeName, ConstantPoolGen cpg) { - int numPairs = ObjectTeamsTransformation.combineTwoBytes(bytes, i); - i+=2; - for (int p=0; p<numPairs; p++) - i = skipElementValue(bytes, i+2 /*skip name*/, typeName, cpg); - return i; - } - - private static int skipElementValue(byte[] bytes, int i, String typeName, ConstantPoolGen cpg) { - short tag = bytes[i++]; - switch (tag) { - case 'B': // byte - case 'C': // char - case 'D': // double - case 'F': // float - case 'I': // int - case 'J': // long - case 'S': // short - case 'Z': // boolean - case 's': // String - case 'c': // Class - i+=2; break; - case 'e': // Enum constant - i+=4; break; - case '@': // Annotation - String[] typeName2 = new String[1]; - i = ObjectTeamsTransformation.scanStrings(typeName2, bytes, i, cpg); // nested annotation type - i = skipNameValuePairs(bytes, i, typeName2[0], cpg); - break; - case '[': // Array - int numArrayVals = ObjectTeamsTransformation.combineTwoBytes(bytes, i); - i+=2; - for (int j = 0; j < numArrayVals; j++) - i = skipElementValue(bytes, i, typeName, cpg); - break; - default: - throw new RuntimeException("Unexpected element value kind in annotation: " + typeName); - } - return i; - } - -} diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/AttributeReadingGuard.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/AttributeReadingGuard.java deleted file mode 100644 index 4d72e02d8..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/AttributeReadingGuard.java +++ /dev/null @@ -1,80 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2002-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: AttributeReadingGuard.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre.util; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - -/** - * @author Christine Hundt - * @author Stephan Herrmann - */ -public class AttributeReadingGuard { - - private static Map<ClassLoader, AttributeReadingGuard> instances = new HashMap<ClassLoader, AttributeReadingGuard>(); - private static AttributeReadingGuard defaultInstance = new AttributeReadingGuard(); - - private ArrayList<String> servedClasses = new ArrayList<String>(); - - // this one flag is really global (concerns the one main class of the application): - private static boolean firstLoaded = true; - - /** - * @param className - * @return - */ - public boolean iAmTheFirst(String className) { - return !this.servedClasses.contains(className); - } - - /** - * Processing the given class is done. - * @param className - */ - public void workDone(String className) { - this.servedClasses.add(className); - } - - /** - * @return whether this class is the first being loaded => possibly the main class. - */ - public static synchronized boolean isFirstLoadedClass() { - if (!firstLoaded) - return false; - firstLoaded = false; - return true; - } - - /** First loaded class has no main => it was a false alarm. */ - public static void reset() { - firstLoaded = true; - } - - /** - * Since actual data are stored in an instance, static methods need to retrieve the appropriate - * instance regarding the given class loader. - */ - public static AttributeReadingGuard getInstanceForLoader(ClassLoader loader) { - if (loader == null) - return defaultInstance; - - AttributeReadingGuard instance = instances.get(loader); - if (instance == null) - instances.put(loader, instance = new AttributeReadingGuard()); - return instance; - } -} diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/BoundClass.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/BoundClass.java deleted file mode 100644 index 63bbb979e..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/BoundClass.java +++ /dev/null @@ -1,80 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2004-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id$ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre.util; - -import java.util.HashSet; - -import org.apache.bcel.generic.ObjectType; - -/** - * @version $Id: BoundClass.java,v 1.8 2006-12-19 21:31:30 stephan Exp $ - * @author Christine Hundt - */ -public class BoundClass { - private String name; - - private BoundClass _super; - //private BoundClass _tsuper; - private HashSet<String> adaptingTeams = new HashSet<String>(); - - public BoundClass(String className, String teamName) { - name = className; - this.adaptingTeams.add(teamName); - _super = null; - } - - public String getName() { - return name; - } - - public boolean isAdaptedByTeam(String teamName) { - return this.adaptingTeams.contains(teamName); - } - - public void addAdaptingTeam(String teamName) { - this.adaptingTeams.add(teamName); - } - - public void setSuper(BoundClass superClass) { - _super = superClass; - } - - public BoundClass getSuper() { - return _super; - } - - public boolean isSubClassOf(String anotherClass) { - BoundClass superClass = _super; - while (superClass!=null) { - if (superClass.getName().equals(anotherClass)) { - return true; - } - superClass = superClass.getSuper(); - } - return false; - } - - public void updateSuper(BoundClass newSuperBaseClass, ObjectType newSuperBaseType) { - // FIXME(SH): implement ;-) - // test if newSuperBaseType is above or below _super. - // also check if tsupers (i.e., more than one super) must be treated as well. - } - -// public String toString() { -// return name; -// } -} diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/BoundMethod.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/BoundMethod.java deleted file mode 100644 index 4a4a8fbdc..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/BoundMethod.java +++ /dev/null @@ -1,48 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2004-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: BoundMethod.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre.util; - -/** - * @author Christine Hundt - * @version $Id: BoundMethod.java 23408 2010-02-03 18:07:35Z stephan $ - */ -public class BoundMethod { - private String name; - private String signature; - private boolean isCallin; - -// private MethodBinding binding; - - public BoundMethod(String methodName, String methodSignature, boolean isCallin, MethodBinding methodBinding) { - name = methodName; - signature = methodSignature; - this.isCallin = isCallin; -// binding = methodBinding; - } - - public String getName() { - return name; - } - - public String getSignature() { - return signature; - } - - public boolean getIsCallin() { - return this.isCallin; - } -} diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/CallinBindingManager.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/CallinBindingManager.java deleted file mode 100644 index 2ef71a958..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/CallinBindingManager.java +++ /dev/null @@ -1,1323 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2002-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: CallinBindingManager.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre.util; - -//import org.apache.bcel.generic.Type; // just for javadoc. -import org.apache.bcel.classfile.JavaClass; -import org.apache.bcel.generic.ObjectType; - -import org.eclipse.objectteams.otre.OTREInternalError; -import org.eclipse.objectteams.otre.ObjectTeamsTransformation; -import org.eclipse.objectteams.otre.RepositoryAccess; -import org.eclipse.objectteams.otre.ObjectTeamsTransformation.BaseMethodInfo; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; -import java.util.Map.Entry; - -/** - * @version $Id: CallinBindingManager.java 23408 2010-02-03 18:07:35Z stephan $ - * @author Christine Hundt - */ -@SuppressWarnings("nls") -public class CallinBindingManager { - // map of bindings for role classes: roleClassName -> RoleBaseBinding - private static HashMap<String, RoleBaseBinding> roleBindings = new HashMap<String, RoleBaseBinding>(); - - // map of bindings for base classes: baseClassName -> List[RoleBaseBinding] - private static ListValueHashMap<RoleBaseBinding> baseBindings = new ListValueHashMap<RoleBaseBinding>(); - - // maps a team to its handled bases: teamClassName -> List[BaseClassName] - private static ListValueHashMap<String> basesPerTeam = new ListValueHashMap<String>(); - - // maps a team to its contained roles: teamClassName -> List[RoleClassName] - private static ListValueHashMap<String> rolesPerTeam = new ListValueHashMap<String>(); - - /** - * Add super-link of the BoundRole object for the RoleBaseBinding of 'className' to 'superClassName'. - * @param className the name of the class for which to add the super-link - * @param superClassName the name of the super class to be linked - */ - public static void addSuperRoleLink(String className, String superClassName) { - if (!roleBindings.containsKey(superClassName)) - return; // no super role class stored! - RoleBaseBinding rbbSuper = roleBindings.get(superClassName); - RoleBaseBinding rbb = roleBindings.get(className); - // establish link from the role to its super role class: - rbb.getRoleClass().setSuper(rbbSuper.getRoleClass()); - } - - /** - * @param baseClassName - */ - private static void addSuperBaseLink(String teamClassName, String baseClassName, RoleBaseBinding rbb) - { - BoundClass baseClass = rbb.getBaseClass(); - ObjectType baseClassType = new ObjectType(baseClassName); - // clone the set for re-entrance: - Iterator<Entry<String, LinkedList<RoleBaseBinding>>> it = getBaseBindingsCloneIterator(); - while (it.hasNext()) { - Entry<String, LinkedList<RoleBaseBinding>> entry = it.next(); - String currentBaseClassName = entry.getKey(); - if (currentBaseClassName.equals(baseClassName)) continue; - ObjectType currentType = new ObjectType(currentBaseClassName); - // BoundClass objects are unique per base object, so just take the first binding: - BoundClass currentBaseClass = entry.getValue().getFirst().getBaseClass(); - if(RepositoryAccess.safeSubclassOf(baseClassType, currentType)) { - BoundClass rbbSuper = baseClass.getSuper(); - if (rbbSuper != null) { - if (rbbSuper.getName().equals(currentBaseClassName)) - continue; // no need for action: already set. - baseClass.updateSuper(currentBaseClass, currentType); - } - baseClass.setSuper(currentBaseClass); - } - else if (RepositoryAccess.safeSubclassOf(currentType, baseClassType)) { - BoundClass currentSuper = currentBaseClass.getSuper(); - // if sub base classes may be registered before super base class, - // this case has to be considered too: - if (currentSuper != null) { - if (currentSuper.getName().equals(baseClassName)) - continue; // no need for action: already set. - currentBaseClass.updateSuper(baseClass, baseClassType); - } - currentBaseClass.setSuper(baseClass); - } - } - } - - /** - * Declare role playedBy base. - * - * @param roleClassName the name of the played role class - * @param baseClassName the name of the playing base class - */ - public static void addRoleBaseBinding(String roleClassName, String baseClassName, String teamClassName) { - RoleBaseBinding rbb = roleBindings.get(roleClassName); - if (rbb == null) { - rbb = new RoleBaseBinding(roleClassName, baseClassName, teamClassName); - roleBindings.put(roleClassName, rbb); - } - addSuperBaseLink(teamClassName, baseClassName, rbb); - synchronized (baseBindings) { - baseBindings.put(baseClassName, rbb); - } - addTeamRoleRelation(teamClassName, roleClassName); - } - - /** - * @param teamClassName - * @param baseClassName - */ - public static void addTeamBaseRelation(String teamClassName, String baseClassName) { - JavaClass baseClass = null; - try { - baseClass = RepositoryAccess.lookupClass(baseClassName); - } catch (ClassNotFoundException e) { - // FIXME(SH): where to log? - e.printStackTrace(); - } - if (baseClass != null && baseClass.isInterface()) { - // TODO (SH): need to register with all implementing classes! - if (logging) { - ObjectTeamsTransformation.printLogMessage("*** Skipping base " + baseClassName + ": is an interface"); - ObjectTeamsTransformation.printLogMessage("Classses implementing the interface " + baseClassName + " have to be transformed!"); - } - addBoundBaseInterface(baseClassName); - } else { - List<String> bases = basesPerTeam.get(teamClassName); - if (bases==null || !bases.contains(baseClassName)) - basesPerTeam.put(teamClassName, baseClassName); - } - } - - /** - * @param teamClassName - * @return - */ - public static List<String> getBasesPerTeam(String teamClassName) { - // (PH): return empty list instead of null when team has no bases? - return basesPerTeam.get(teamClassName); - } - - /** - * @param teamClassName - * @param roleClassName - */ - public static void addTeamRoleRelation(String teamClassName, String roleClassName) { - List<String> roles = rolesPerTeam.get(teamClassName); - if (roles == null || !roles.contains(roleClassName)) - rolesPerTeam.put(teamClassName, roleClassName); - } - - /** - * @param teamClassName - * @return - */ - public static List<String> getRolePerTeam(String teamClassName) { - return rolesPerTeam.get(teamClassName); - } - - private static LinkedList<String> allRoles = new LinkedList<String>(); - - /** - * @param roleName - */ - public static void addRole(String roleName) { - allRoles.add(roleName); - } - - /** - * @param roleName - * @return - */ - public static boolean isRole(String roleName) { - return allRoles.contains(roleName); - } - - - /** - * Declare binding of a pair of methods. - * @param roleClassName - * @param bindingFileName TODO - * @param bindingLineNumber TODO - * @param bindingLineOffset TODO - * @param roleMethodName - * @param roleMethodSignature signature ready for interpretation by - * {@link Type org.apache.bcel.generic.Type} - * @param isStaticRoleMethod TODO - * @param modifier "before", "after" or "replace" - * @param baseMethodName - * @param baseMethodSignature - * @param isStaticBaseMethod is the base method static? - * @param baseIsCallin is the base method a callin method? - * @param translationFlags one bit for the result and for each argument indicating whether lifting/lowering is needed - * @param liftMethodName - * @param liftMethodSignature - */ - public static void addMethodBinding( - String roleClassName, String baseClassName, - String bindingFileName, int bindingLineNumber, int bindingLineOffset, - String bindingLabel, String roleMethodName, String roleMethodSignature, boolean isStaticRoleMethod, - String wrapperName, String wrapperSignature, String modifier, - String baseMethodName, String baseMethodSignature, - boolean isStaticBaseMethod, boolean baseIsCallin, boolean covariantBaseReturn, - int translationFlags, String liftMethodName, String liftMethodSignature) - { - RoleBaseBinding rbb = roleBindings.get(roleClassName); - if (rbb == null) { - // no binding found, create it now: - if (baseClassName == null) - throw new OTREInternalError("PlayedBy attribute must be read before method bindings."); - int lastDollar = roleClassName.lastIndexOf('$'); - String teamClassName = roleClassName.substring(0, lastDollar); - rbb = new RoleBaseBinding(roleClassName, baseClassName, teamClassName); - roleBindings.put(roleClassName, rbb); - } - //System.err.println(rbb.getRoleClass().getName()+"<-*->"+rbb.getBaseClass().getName()); - rbb.addMethodBinding(bindingFileName, bindingLineNumber, bindingLineOffset, - bindingLabel, roleMethodName, roleMethodSignature, isStaticRoleMethod, - wrapperName, wrapperSignature, modifier, - baseMethodName, baseMethodSignature, - isStaticBaseMethod, baseIsCallin, covariantBaseReturn, - translationFlags, - liftMethodName, liftMethodSignature); - - if (modifier.equals("replace")) - assignBaseCallTag(rbb.getBaseClassName(), baseMethodName, baseMethodSignature); - } - - /** - * Get all callin bindings for a given base method. - * @param className the base class - * @param methodName the base method - * @return Collection of <pre>MethodBinding</pre> - */ - public static Collection<MethodBinding> getBindingForBaseMethod(String baseClassName, String baseMethodName, String baseMethodSignature) - { - LinkedList<RoleBaseBinding> rbbList = baseBindings.get(baseClassName); - LinkedList<MethodBinding> resultList = new LinkedList<MethodBinding>(); - if (rbbList != null) { - Iterator<RoleBaseBinding> it = rbbList.iterator(); - while (it.hasNext()) { - RoleBaseBinding rbb = it.next(); - List<MethodBinding> mbs = rbb.getBaseMethodBindings(baseMethodName, baseMethodSignature); - if (mbs != null) - addFiltered(resultList, mbs, baseMethodName, baseMethodSignature); - } - } - // IMPLICIT_INHERITANCE - addFiltered(resultList, - getImplicitlyInheritedBaseMethodBindings(baseClassName, baseMethodName, baseMethodSignature), - baseMethodName, - baseMethodSignature); - if (resultList.isEmpty()) - return null; - return resultList; - } - /** variant of the above, optimized for computing only a boolean result instead of a complete list. */ - public static boolean isBoundBaseMethod(String baseClassName, String baseMethodName, String baseMethodSignature) - { - LinkedList<RoleBaseBinding> rbbList = baseBindings.get(baseClassName); - if (rbbList != null) { - for (RoleBaseBinding rbb : rbbList) { - List<MethodBinding> mbs = rbb.getBaseMethodBindings(baseMethodName, baseMethodSignature); - if (mbs != null) - for (MethodBinding mb : mbs) - if (mb.matchesMethod(baseMethodName, baseMethodSignature, /* strict */ true)) - return true; - } - } - // IMPLICIT_INHERITANCE - for (MethodBinding mb : getImplicitlyInheritedBaseMethodBindings(baseClassName, baseMethodName, baseMethodSignature)) - if (mb.matchesMethod(baseMethodName, baseMethodSignature, /* strict */ true)) - return true; - return false; - } - // add bindings from candidates to resultList, perhaps checking - // full signatures (i.e., if not covariantBaseReturn). - private static void addFiltered(Collection<MethodBinding> resultList, - Collection<MethodBinding> candidates, - String name, - String fullSignature) - { - for (MethodBinding methodBinding : candidates) - if (methodBinding.matchesMethod(name, fullSignature, /*strict*/false)) - resultList.add(methodBinding); - } - - /** - * Gets all implicitly inherited method bindings for the given base method. - * Note: the result can only contain elements for base classes which are - * roles at the same time! - * @param baseClassName the name of the base class - * @param baseMethodName the name of the base mehtod - * @param baseMethodSignature the descriptor or the base method signature - * @return a Collection with all implicitly inherited method bindings - */ - private static Collection<MethodBinding> getImplicitlyInheritedBaseMethodBindings(String baseClassName, String baseMethodName, String baseMethodSignature) { - List<MethodBinding> resultList = new LinkedList<MethodBinding>(); - - if (!isRole(baseClassName)) - return resultList; // only roles can have implicit super types - - Iterator<Entry<String, LinkedList<RoleBaseBinding>>> it = getBaseBindingsCloneIterator(); - - while (it.hasNext()) { - Entry<String, LinkedList<RoleBaseBinding>> entry = it.next(); - String have = entry.getKey(); - // look for true superClass (not same): - if (have.equals(baseClassName)) - continue; - if (isImplicitSubtype(baseClassName, have)) { - // now we have an implicit superClass: - if (logging) - ObjectTeamsTransformation.printLogMessage(baseClassName - + " implicitly inherits callin bindings from " + have); - // collect the signatures of all bound base methods: - List<RoleBaseBinding> rbbList = entry.getValue(); - if (rbbList != null) { - Iterator<RoleBaseBinding> rbb_it = rbbList.iterator(); - while (rbb_it.hasNext()) { - RoleBaseBinding rbb = rbb_it.next(); - List<MethodBinding> mbs = rbb.getBaseMethodBindings(baseMethodName, baseMethodSignature); - if (mbs != null) - resultList.addAll(mbs); - } - } - } - } - //if (!resultList.isEmpty()) - // System.err.println(resultList); - return resultList; - } - - /** - * Get all callin bindings that a given base class may inherit from its superclass. - * @param className - * @result list of MethodBinding - */ - public static Collection<MethodBinding> getInheritedCallinBindings (String className) { -/* - List classBindings = baseBindings.get(className); - if (classBindings!=null) { - // any RoleBaseBinding contains the corresponding BoundClass object for the super base: - RoleBaseBinding anyRBB = (RoleBaseBinding)classBindings.get(0); - // problem: if a sub base class is not explicitly bound to a role class no corresponding - // BoundClass object exists. How can we access the super bindings via the - // super-link?? - BoundClass bc = anyRBB.getBaseClass(); - //System.out.println("-----------"); - while (bc.getSuper()!=null) { - System.out.println(bc.getName()); - bc = bc.getSuper(); - } - //System.out.println("-----------"); - } -*/ - - List<MethodBinding> result = new LinkedList<MethodBinding>(); - ObjectType current = new ObjectType(className); - // clone for re-entrance: - Iterator<Entry<String, LinkedList<RoleBaseBinding>>> it= getBaseBindingsCloneIterator(); - while (it.hasNext()) { - Entry<String, LinkedList<RoleBaseBinding>> entry = it.next(); - String have = entry.getKey(); - // look for true superClass (not same): - if (have.equals(className)) continue; - ObjectType haveType = new ObjectType(have); - if (RepositoryAccess.safeSubclassOf(current, haveType)) { - // now we have a true superClass: - if (logging) - ObjectTeamsTransformation.printLogMessage(className - + " inherits callin bindings from " + have); - // collect the signatures of all bound base methods: - List<RoleBaseBinding> rbbList = entry.getValue(); - if (rbbList != null) { - Iterator<RoleBaseBinding> rbb_it = rbbList.iterator(); - while (rbb_it.hasNext()) { - RoleBaseBinding rbb = rbb_it.next(); - result.addAll(rbb.getBaseMethodBindings()); - } - } - } - } - return result; - } - - /** - * Get all super classes defining callin bindings that a given static base - * method may inherit. - * - * @author juerwid - * @param className - * @param methodName - * @param methodSignaturte - * @result list of <String[] {class_name}> - */ - public static Collection<String> getInheritedCallinBindingsForStaticMethods( - String className, String methodName, String methodSignature) - { - List<String> result = new LinkedList<String>(); - ObjectType current = new ObjectType(className); - // clone for re-entrance: - Iterator<Entry<String, LinkedList<RoleBaseBinding>>> it = getBaseBindingsCloneIterator(); - boolean getNextClass = false; - while (it.hasNext()) { - Entry<String,LinkedList<RoleBaseBinding>> entry = it.next(); - String have = entry.getKey(); - // look for true superClass (not same): - if (have.equals(className)) continue; - ObjectType haveType = new ObjectType(have); - if (RepositoryAccess.safeSubclassOf(current, haveType)) { - // now we have a true superClass: - if (logging) - ObjectTeamsTransformation.printLogMessage(className - + " inherits callin bindings from " + have); - // collect the signatures of all bound base methods: - LinkedList<RoleBaseBinding> rbbList = entry.getValue(); - if (rbbList != null) { - Iterator<RoleBaseBinding> rbb_it = rbbList.iterator(); - while (rbb_it.hasNext() && !getNextClass) { - RoleBaseBinding rbb = rbb_it.next(); - List<String[]> methods = rbb.getBaseSignatures(); - Iterator<String[]> methodsIter = methods.iterator(); - while(methodsIter.hasNext() && !getNextClass){ - String[] aMethod = methodsIter.next(); - if(methodName.equals(aMethod[0]) && methodSignature.equals(aMethod[1])){ - result.add(have); - getNextClass = true; - } - } - } - if(getNextClass){ - getNextClass = false; - continue; - } - } - } - } - return result; - } - - /** - * Checks if 'subType' is an implicit subtype of 'superType'. - * To be true the role name parts have to be equal and the - * team name parts have to be in a 'real' subtype relationship. - * - * @param subType the name of the potential subtype. - * @param superType the name of the potential supertype. - * @return true, if subType implicitly inherits from superType. - */ - private static boolean isImplicitSubtype(String subType, String superType) { - //System.err.println(subType +" -?-> " + superType); - int dollarIdxSub = subType.lastIndexOf('$'); - int dollarIdxSuper = superType.lastIndexOf('$'); - if (dollarIdxSub==-1 || dollarIdxSuper==-1) - return false; // no roles - String pureSubType = subType.substring(dollarIdxSub+1, subType.length()); - String pureSuperType = superType.substring(dollarIdxSuper+1, superType.length()); - if (!pureSubType.equals(pureSuperType)) - return false;// no identical role names - - String subTeamName = subType.substring(0, dollarIdxSub); - String superTeamName = superType.substring(0,dollarIdxSuper); - - ObjectType subTeamType = new ObjectType(subTeamName); - ObjectType superTeamType = new ObjectType(superTeamName); - if (RepositoryAccess.safeSubclassOf(subTeamType, superTeamType)) { - if (logging) - ObjectTeamsTransformation.printLogMessage(subType - + " implicitly inherits method bindings from " + superType); - //System.err.println(subType + " implicitly inherits method bindings from " + superType); - return true; - } - return false; // no inheritance relation between teams - } - - /** - * Get all inherited method bindings for a given base method, which are - * bindings declared for a super base class. - * - * the actual base class has additional bindings for this method! - * @param baseClassName the name of the role class - * @param baseMethodName the name of the role method - * @param baseMethodSignature the signature of the role method - * @result a List containing all inherited bindings for the role method - */ - public static List<MethodBinding> getInheritedBaseMethodBindings(String baseClassName, String baseMethodName, String baseMethodSignature) { - - List<MethodBinding> inheritedMethodBindings = new LinkedList<MethodBinding>(); - if (!isBoundBaseClass(baseClassName)) { - return inheritedMethodBindings; - } - LinkedList<RoleBaseBinding> baseBindingsForBase = baseBindings.get(baseClassName); - if (baseBindingsForBase == null) - return inheritedMethodBindings; - - Iterator<RoleBaseBinding> it = baseBindingsForBase.iterator(); - while (it.hasNext()) { - RoleBaseBinding rbb = it.next(); - BoundClass bc = rbb.getBaseClass(); - while (bc.getSuper() != null) { - bc = bc.getSuper(); - String superRoleName = bc.getName(); - Collection<MethodBinding> superRoleMethodBindings = CallinBindingManager.getBindingForBaseMethod( - superRoleName, - baseMethodName, - baseMethodSignature); - if (superRoleMethodBindings!=null) - inheritedMethodBindings.addAll(superRoleMethodBindings); - } - } - return inheritedMethodBindings; - } - - /** - * Get all inherited method bindings for a given role method, which are - * bindings declared in a super role class. The actual role class has - * additional bindings for this method! - * - * @param roleClassName the name of the role class - * @param roleMethodName the name of the role method - * @param roleMethodSignature the signature of the role method - * @result a List containing all inherited bindings for the role method - */ - public static List<MethodBinding> getInheritedRoleMethodBindings(String roleClassName, String roleMethodName, String roleMethodSignature) { - List<MethodBinding> inheritedMethodBindings = new LinkedList<MethodBinding>(); - if (!isBoundRoleClass(roleClassName)) { - return inheritedMethodBindings; - } - RoleBaseBinding rbb = roleBindings.get(roleClassName); - BoundClass bc = rbb.getRoleClass(); - while (bc.getSuper() != null) { - bc = bc.getSuper(); - String superRoleName = bc.getName(); - List<MethodBinding> superRoleMethodBindings = CallinBindingManager.getBindingsForRoleMethod( - superRoleName, - roleMethodName, - roleMethodSignature); - inheritedMethodBindings.addAll(superRoleMethodBindings); - } - return inheritedMethodBindings; - } - - /** - * All bindings for a given role method concerning its base class. - * - * @return List of MethodBinding - */ - public static List<MethodBinding> getBindingsForRoleMethod(String roleClassName, - String roleMethodName, String roleMethodSignature) - { - RoleBaseBinding rbb = roleBindings.get(roleClassName); - if (rbb==null) { - return new LinkedList<MethodBinding>(); - } - List<MethodBinding> roleMethodBindings = rbb.getRoleMethodBindings(roleMethodName, roleMethodSignature); - if (roleMethodBindings == null) { - return new LinkedList<MethodBinding>(); - } - return roleMethodBindings; - } - - /** - * @param className - * @return - */ - public static boolean isBoundBaseClass(String className) { - // and has at least one method binding? - boolean result = baseBindings.containsKey(className); - if (result || !isRole(className)) { - return result; - } - else {// bound implicit super class? - Iterator<String> it = getBaseBindingsKeyIterator(); - while (it.hasNext()) { - String have = it.next(); - // look for true superClass (not same): - if (have.equals(className)) - continue; - if (isImplicitSubtype(className, have)) - return true; - } - return result; - } - } - - /** - * @param className - * @return - */ - public static boolean isBoundBaseAndRoleClass(String className) { - // and has at least one method binding? - if (baseBindings.containsKey(className)) - return true; - // bound implicit super class? - Iterator<String> it = getBaseBindingsKeyIterator(); - while (it.hasNext()) { - String have = it.next(); - // look for true superClass (not same): - if (have.equals(className)) - continue; - if (isImplicitSubtype(className, have)) - return true; - } - return false; - } - - /** - * @param baseClassName - * @return - */ - public static boolean hasBoundBaseParent(String baseClassName) { - LinkedList<RoleBaseBinding> rbbList = baseBindings.get(baseClassName); - if (rbbList != null) { - Iterator<RoleBaseBinding> it = rbbList.iterator(); - while (it.hasNext()) { - RoleBaseBinding rbb = it.next(); - if (rbb.getBaseClass().getSuper()!=null) - return true; - } - } - // IMPLICIT_INHERITANCE - //if (isUnboundSubBase(baseClassName)) - // return true; - return false; - } - - - /** - * Returns the name of the topmost bound base class. - * - * @param baseClassName - * @return - */ - public static String getTopmostBoundBase(String baseClassName) { - LinkedList<RoleBaseBinding> rbbList = baseBindings.get(baseClassName); - if (rbbList != null) { - // assumption: EVERY BoundClass object has been connected to its bound super classes. - RoleBaseBinding anyRBB = rbbList.get(0); - BoundClass bc = anyRBB.getBaseClass(); - while (bc.getSuper() != null) { - bc = bc.getSuper(); - } - return bc.getName(); - } - return baseClassName; - } - - /** - * @param baseClassName - * @return - */ - public static String getBoundBaseParent(String baseClassName) { - LinkedList<RoleBaseBinding> rbbList = baseBindings.get(baseClassName); - if (rbbList != null) { - Iterator<RoleBaseBinding> it = rbbList.iterator(); - while (it.hasNext()) { - RoleBaseBinding rbb = it.next(); - BoundClass bc = rbb.getBaseClass().getSuper(); - if (bc!=null) - return bc.getName(); - } - } - // IMPLICIT_INHERITANCE - //if (isUnboundSubBase(baseClassName)) - // return true; - return null; - } - - /** - * @param teamClassName - * @param baseClassName - * @return - */ - public static boolean teamAdaptsSuperBase(String teamClassName, String baseClassName) { - LinkedList<RoleBaseBinding> rbbList = baseBindings.get(baseClassName); - if (rbbList != null && !rbbList.isEmpty()) { - RoleBaseBinding rbb = rbbList.getFirst(); // all entries refer to the same base class. - BoundClass bc = rbb.getBaseClass().getSuper(); - while (bc!=null) { - if (bc.isAdaptedByTeam(teamClassName)) - return true; - bc = bc.getSuper(); - } - } - return false; - } - - /** - * @param baseClassName - * @return - */ -// private static boolean isUnboundSubBase(String baseClassName) { -// ObjectType current = new ObjectType(baseClassName); -// if (!checkLookup(current.getClassName())) // TODO: workaround for classes loaded from special locations -// return false; -// Iterator /* String */ it = baseBindings.keySet().iterator(); -// while (it.hasNext()) { -// String have = (String)it.next(); -// // look for true superClass (not same): -// if (have.equals(baseClassName)) continue; -// ObjectType haveType = new ObjectType(have); -// //System.err.println(current + " : "+haveType); -// //System.err.println(org.apache.bcel.Repository.lookupClass(have)); -// if (!checkLookup(haveType.getClassName())) // TODO: workaround for classes loaded from special locations -// continue; -// if (current.subclassOf(haveType)) { -// return true; -// } -// } -// return false; -// } - - /** - * @param className - * @return - */ - public static boolean isBoundRoleClass(String className) { - return roleBindings.containsKey(className); - } - - /** - * @param className - * @return - */ - public static RoleBaseBinding getRoleBaseBinding(String roleClassName) { - return roleBindings.get(roleClassName); - } - - /** - * @param roleClassName - * @return - */ - public static List<MethodBinding> getMethodBindingsForRoleClass(String roleClassName) - { - RoleBaseBinding rbb = roleBindings.get(roleClassName); - return rbb.getRoleMethodBindings(); - } - - /** - * @param roleClassName - * @return - */ - public static Set<String> getBoundRoleMethods(String roleClassName) { - Set<String> roleMethodKeySet = new HashSet<String>(); - if (roleBindings.get(roleClassName) != null) { - RoleBaseBinding rbb = roleBindings.get(roleClassName); - roleMethodKeySet = rbb.getRoleMethodSignatures(); - } - return roleMethodKeySet; - } - - /** - * @param baseClassName - * @return - */ - public static List<MethodBinding> getMethodBindingsForBaseClass(String baseClassName) - { - LinkedList<RoleBaseBinding> rbbList = baseBindings.get(baseClassName); - LinkedList<MethodBinding> resultList = new LinkedList<MethodBinding>(); - if (rbbList != null) { - Iterator<RoleBaseBinding> it = rbbList.iterator(); - while (it.hasNext()) { - RoleBaseBinding rbb = it.next(); - resultList.addAll(rbb.getRoleMethodBindings()); - } - } - return resultList; - } - - // -------------------------------------------------- - // discriminate base methods by tag per callin - // -------------------------------------------------- - // baseClass.baseMeth.baseMethodSignature -> tag - private static HashMap<String, Integer> baseCallTags = new HashMap<String, Integer>(); - // -- follow access methods for baseCallTags: - - /** - * @param baseClass - * @param baseMeth - * @param baseMethodSignature - */ - public static void assignBaseCallTag (String baseClass, String baseMeth, - String baseMethodSignature) - { - // every base method bound by a replace callin gets an unique tag: - String key = baseClass+"."+baseMeth+"."+baseMethodSignature; - int tag = baseCallTags.size(); - if (!baseCallTags.containsKey(key)) - baseCallTags.put(key, Integer.valueOf(tag)); - } - - public static int getBaseCallTag (String base_class_name, - String base_method_name, - String base_method_signature) { - String key = base_class_name + "." + base_method_name - + "." + base_method_signature; - return baseCallTags.get(key).intValue(); - } - - // ---------------------------------------------- - // Map argument positions: - // ---------------------------------------------- - // teamName -> callinWrapperName -> int[] - private static HashMap<String, HashMap<String, int[]>> paramMappings = new HashMap<String, HashMap<String, int[]>>(); - // -- follow access methods for paramMappings: - - /** - * @param teamName - * @param methodWrapper - * @param positions - */ - public static void addParameterBinding (String teamName, - String methodWrapper, - int[] positions) { - HashMap<String, int[]> teamMap = paramMappings.get(teamName); - if (teamMap == null) { - teamMap = new HashMap<String, int[]>(); - paramMappings.put(teamName, teamMap); - } - teamMap.put(methodWrapper, positions); - } - - public static boolean hasParamMappings (String teamName, String methodWrapper) - { - HashMap<String,int[]> teamMap = paramMappings.get(teamName); - if (teamMap == null) return false; - return teamMap.containsKey(methodWrapper); - } - - /** Get parameter positions for the given team or any super team. */ - public static int[] getParamPositions (String teamName, String methodWrapper) - { - int[] positions = getExactParamPositions(teamName, methodWrapper); - if (positions != null) - return positions; - // inherit parameter mappings from super teams: -- >> - Iterator<String> superTeams = getSuperTeamsWithParamMappigs(teamName).iterator(); - while (superTeams.hasNext()) { - positions = getExactParamPositions(superTeams.next(), methodWrapper); - if (positions != null) // found (the!) parameter mapping - return positions; - } - return null; - } - /** Get parameter positions for exactly the given team (no super teams). */ - private static int[] getExactParamPositions(String teamName, String methodWrapper) { - HashMap<String,int[]>teamMap = paramMappings.get(teamName); - if (teamMap == null) - return null; - return teamMap.get(methodWrapper); - } - - private static List<String> getSuperTeamsWithParamMappigs(String teamName) { - LinkedList<String> result = new LinkedList<String>(); - try { - for (JavaClass superTeam : RepositoryAccess.getSuperClasses(teamName)) - if (paramMappings.get(superTeam.getClassName()) != null) - result.add(superTeam.getClassName()); - } catch (ClassNotFoundException e) { - // FIXME(SH): where to log to? - e.printStackTrace(); - // continue, just nothing added to result - } - return result; - } - - // ----------------------------------------------- - // callout bindings that require adjustment: - // ----------------------------------------------- - // baseClass -> HashSet (method_name+signature) - private static HashMap<String, HashSet<String>> calloutBindings = new HashMap<String, HashSet<String>>(); - - /** - * @param clazz - * @param meth - * @param sign - */ - public static void addCalloutBinding(String clazz, String meth, String sign) { - HashSet<String> bindings = calloutBindings.get(clazz); - if (bindings == null) { - bindings = new HashSet<String>(); - calloutBindings.put(clazz, bindings); - } - bindings.add(meth + sign); - } - - /** - * @param clazz - * @return - */ - public static HashSet<String> getCalloutBindings (String clazz) { - return calloutBindings.get(clazz); - } - - /** - * @param bindings - * @param method_name - * @param signature - * @return - */ - public static boolean requiresCalloutAdjustment(HashSet<String> bindings, - String method_name, - String signature) - { - return bindings.contains(method_name+signature); - } - - // ----------------------------------------------- - // callouts to base class fields are stored here for furher reading and get/set method generation: - // ----------------------------------------------- - private static ListValueHashMap<FieldDescriptor> calloutSetFields = new ListValueHashMap<FieldDescriptor>(); - private static ListValueHashMap<FieldDescriptor> calloutGetFields = new ListValueHashMap<FieldDescriptor>(); - - - /** - * @param roleClassName - * @param fieldName - * @param fieldSignature - * @param accessMode - * @param isStaticField - */ - public static void addCalloutBoundFileds(String baseClassName, String fieldName, - String fieldSignature, String accessMode, boolean isStaticField) - { - FieldDescriptor fd = new FieldDescriptor(fieldName, fieldSignature, isStaticField); - - if (accessMode.equals("get")) { - calloutGetFields.put(baseClassName, fd); - } else if (accessMode.equals("set")) { - calloutSetFields.put(baseClassName, fd); - } else { - throw new OTREInternalError("CalloutFieldAccess attribute contains wrong access mode: "+accessMode); - } - } - - /** - * @param baseClassName - * @return - */ - public static List<FieldDescriptor> getCalloutGetFields(String baseClassName) { - return calloutGetFields.get(baseClassName); - } - - /** - * @param baseClassName - * @return - */ - public static List<FieldDescriptor> getCalloutSetFields(String baseClassName) { - return calloutSetFields.get(baseClassName); - } - - // ----------------------------------------------- - // base calls to super methods via special accessor - // ----------------------------------------------- - private static ListValueHashMap<SuperMethodDescriptor> superMethods = new ListValueHashMap<SuperMethodDescriptor>(); - - public static void addSuperAccess(String baseClassName, String superClassName, String methodName, String signature) { - SuperMethodDescriptor superMethod = new SuperMethodDescriptor(methodName, baseClassName, superClassName, signature); - superMethods.put(baseClassName, superMethod); - } - public static List<SuperMethodDescriptor> getSuperAccesses(String class_name) { - return superMethods.get(class_name); - } - - // ----------------------------------------------- - // bound interfaces have to be registered, for implementing classes to inherit callin bindings: - // ----------------------------------------------- - private static List<String> boundBaseInterfaces = new LinkedList<String>(); - - /** - * @param baseInterfaceName The name of the bound base interface. - */ - public static void addBoundBaseInterface(String baseInterfaceName) { - if (!boundBaseInterfaces.contains(baseInterfaceName)) - boundBaseInterfaces.add(baseInterfaceName); - } - - /** - * @param interfaceName - * @return - */ - public static Collection<String[]> getInterfaceInheritedCallinBindings(String interfaceName) { - List<String[]> result = new LinkedList<String[]>(); - //System.err.println(interfaceName); - //System.err.println(boundBaseInterfaces); - if (boundBaseInterfaces.contains(interfaceName)) { - if (logging) - ObjectTeamsTransformation.printLogMessage(interfaceName - + " bequests callin bindings to implementing class"); - // collect the signatures of all bound base methods: - LinkedList<RoleBaseBinding> rbbList = baseBindings.get(interfaceName); - if (rbbList != null) { - Iterator<RoleBaseBinding> rbb_it = rbbList.iterator(); - while (rbb_it.hasNext()) { - RoleBaseBinding rbb = rbb_it.next(); - result.addAll(rbb.getBaseSignatures()); - - // System.err.println("inheriting binding: "+rbb); - } - } - } - return result; - } - - /** - * @param methodName - * @param methodSignature - * @param interfaceName - * @return - */ - public static Collection<MethodBinding> getInterfaceInheritedMethodBindings( - String methodName, String methodSignature, String interfaceName) { - List<MethodBinding> result = new LinkedList<MethodBinding>(); - if (boundBaseInterfaces.contains(interfaceName)) { - LinkedList<RoleBaseBinding> rbbList = baseBindings.get(interfaceName); - if (rbbList != null) { - Iterator<RoleBaseBinding> rbb_it = rbbList.iterator(); - while (rbb_it.hasNext()) { - RoleBaseBinding rbb = rbb_it.next(); - List<MethodBinding> mbs = rbb.getBaseMethodBindings(methodName, methodSignature); - if (mbs != null) - result.addAll(mbs); - } - } - } - return result; - } - - /** - * @param interfaceNames - * @return - */ - public static boolean containsBoundBaseInterface(String[] interfaceNames) { - for (int i = 0; i < interfaceNames.length; i++) { - if (boundBaseInterfaces.contains(interfaceNames[i])) - return true; - } - return false; - } - - // ----------------------------------------------- - // precedence can be set for a list of method bindings: - // ----------------------------------------------- - - private static ListValueHashMap<List<String>> precedencePerTeam = new ListValueHashMap<List<String>>(); - - /** - * Add a precedence list for the given team. - * @param precedenceList the list of binding labels defining their precedence - * @param teamName the name of the team for which the precedence list was defined - */ - public static void addPrecedenceList(List<String> precedenceList, String teamName) { - precedencePerTeam.put(teamName, precedenceList); - } - - /** - * Sorts the method binding list according to the given precedence for the team - * @param mbList the list of 'MethodBinding's to be sorted - * @param teamName the name of the corresponding team - * @return the sorted 'MethodBindig' list - */ - public static List<MethodBinding> sortMethodBindings(List<MethodBinding> mbList, String teamName) { - if (mbList.size() < 2) - return mbList; // nothing to sort - String outermostTeamName; - int dollarIdx = teamName.indexOf('$'); - if (dollarIdx > 0) - outermostTeamName = teamName.substring(0, dollarIdx); - else outermostTeamName = teamName; - - List<List<String>> precedenceList = precedencePerTeam.get(outermostTeamName); - if (precedenceList==null) { - // mbList has to be reduced by removing overridden bindings: - return removeOverridden(mbList); - } - - LinkedList<MethodBinding> sortedMethodBindings = new LinkedList<MethodBinding>(); - Iterator<List<String>> predIt = precedenceList.iterator(); - - while (predIt.hasNext()) { - List<String> plainList = predIt.next(); - Iterator<String> plainIt = plainList.iterator(); - - while (plainIt.hasNext()) { - boolean foundOne = false; - String label = plainIt.next(); - Iterator<MethodBinding> mbIter = mbList.iterator(); - List<MethodBinding> alreadySorted = new LinkedList<MethodBinding>(); - - while (mbIter.hasNext()) { - MethodBinding mb = mbIter.next(); - - if (mb.getQualifiedBindingLabel().equals(label)) { // mb exactly fits binding label: - alreadySorted.add(mb); - if (!foundOne) { - sortedMethodBindings.add(mb); - foundOne = true; - } else checkInheritance(sortedMethodBindings.getLast(), mb); - - } else if (mb.inheritsBindingLabel(label, teamName)) { // mb inherits binding label: - alreadySorted.add(mb); - if (!foundOne) { - sortedMethodBindings.add(mb); - foundOne = true; - } else {// maybe it is a subtype of the already added? - MethodBinding lastAdded = sortedMethodBindings.getLast(); - if (mb.overridesMethodBinding(lastAdded)) { - sortedMethodBindings.set(sortedMethodBindings.size()-1, mb); - foundOne = true; - } else checkInheritance(sortedMethodBindings.getLast(), mb); - } - } - } - if (foundOne) { - Iterator<MethodBinding> sortedIter = alreadySorted.iterator(); - while (sortedIter.hasNext()) { - MethodBinding mb = sortedIter.next(); - mbList.remove(mb); - } - } - } - } -// if (mbList.size() > 0) { -// System.err.println("ERROR: Unsortable method bindings: " + mbList +"!"); -// // assumption: all remaining method bindings are overridden! TODO: check assumption! -// } - return sortedMethodBindings; - } - - /** - * Removes overridden method bindings from the given list. Assumes that - * all bindings in the list are in a sub/super type relationship. - * @param mbList the method binding list - * @return the most specific method binding overriding all others - */ - private static List<MethodBinding> removeOverridden(List<MethodBinding> mbList) { - MethodBinding mostSpecificMB = mbList.get(0); - Iterator<MethodBinding> mbIter = mbList.iterator(); - while (mbIter.hasNext()) { - MethodBinding mb = mbIter.next(); - if (mb.overridesMethodBinding(mostSpecificMB)) { - mostSpecificMB = mb; - } else checkInheritance(mostSpecificMB, mb); - } - List<MethodBinding> resultList = new LinkedList<MethodBinding>(); - resultList.add(mostSpecificMB); - return resultList; - } - - /** - * Checks if 'subMB' 'inherits' from 'superMB'. Used to check if assumptions - * about the precedence lists are fulfilled. - * - * @param subMB the overriding method binding - * @param superMB the overridden method binding - */ - private static void checkInheritance(MethodBinding subMB, MethodBinding superMB) { - if (! (subMB.equals(superMB) || subMB.overridesMethodBinding(superMB))) { - //System.err.println("sub: " + subMB + "\n super: " + superMB); - throw new OTREInternalError("Wrong assumption! Broken precedence list possible."); - } - } - - // ------------------------------------------ - // ---------- Logging: ---------------------- - // ------------------------------------------ - /** Initialized from property <tt>ot.log</tt>. */ - static boolean logging = false; - /** Initialized from property <tt>otequinox.debug</tt> */ - static boolean OTEQUINOX_WARN = false; - static { - if(System.getProperty("ot.log") != null) - logging = true; - String warnlevel = System.getProperty("otequinox.debug"); - if (warnlevel != null) { - warnlevel = warnlevel.toUpperCase(); - if (warnlevel.startsWith("INFO") || warnlevel.equals("OK")) - OTEQUINOX_WARN = true; - } - } - - // ----------------------------------------------- - // static replace callin bindings have to be stored in the team, special treatment: - // ----------------------------------------------- - - // maps an implemented role method to its base methods: roleMethod -> List[baseMethod] // added by JU - private static ListValueHashMap<BaseMethodInfo> staticReplaceBindings = new ListValueHashMap<BaseMethodInfo>(); - - /** - * Adds a base method to its implemented role method (static replace bindings). - * - * @param roleMethodKey a string structured according team_class_ name.role_class_name.role_method_name.role_method_signature - * @param baseMethodInfo an Object contained base class name, base method name and base method signature - */ - public static void addStaticReplaceBindingForRoleMethod(String roleMethodKey, BaseMethodInfo baseMethodInfo) { - staticReplaceBindings.put(roleMethodKey, baseMethodInfo); - } - - /** - * Returns static method bindings for the given role method - * @param roleMethodKey - * @return - */ - public static LinkedList<BaseMethodInfo> getStaticReplaceBindingsForRoleMethod(String roleMethodKey) { - return staticReplaceBindings.get(roleMethodKey); - } - - /** - * @param roleClassName - * @param roleMethodName - * @param roleMethodSignature - * @return - */ - public static boolean roleMethodHasBinding(String roleClassName, String roleMethodName, String roleMethodSignature) { - RoleBaseBinding rbb = roleBindings.get(roleClassName); - if (rbb == null) { - return false; - } - return rbb.hasRoleMethodBinding(roleMethodName, roleMethodSignature); - } - - // ----------------------------------------------- - // access modifiers of some base classes have to be changed to 'public' (decapsulation) - // the names of these classes are stored in baseClassesForModifierChange - // ----------------------------------------------- - private static LinkedList<String> baseClassesForModifierChange = new LinkedList<String>(); - - /** - * Adds the given class name to the list of class names intended for decapsulation - * @param className - */ - public static void addBaseClassForModifierChange(String className){ - baseClassesForModifierChange.add(className); - } - - /** - * Checks whether a class name is contained in the list of classes intended for decapsulation - * @param className - * @return - */ - public static boolean checkBaseClassModifierChange(String className) { - Iterator<String> iter = baseClassesForModifierChange.iterator(); - while(iter.hasNext()) { - if(className.equals(iter.next())){ - return true; - } - } - return false; - } - - public static void addBoundSuperclassLink(String sub_name, String super_name) { - synchronized (baseBindings) { - bases: - for (RoleBaseBinding subBinding : baseBindings.getFlattenValues()) { - if (subBinding.getBaseClassName().equals(sub_name)) { - for (RoleBaseBinding superBinding : baseBindings.getFlattenValues()) { - if (subBinding == superBinding) continue; - if (superBinding.getBaseClassName().equals(super_name)) { - subBinding.getBaseClass().setSuper(superBinding.getBaseClass()); - break bases; - } - } - } - } - } - } - - /** Either retrieve an existing BoundClass for `className' are create a new one. - * If an existing one is used it is updated for the new adapting team. - */ - public static BoundClass getBoundBaseClass(String className, String teamClassName) { - for (RoleBaseBinding subBinding : baseBindings.getFlattenValues()) { - if (subBinding.getBaseClassName().equals(className)) { - BoundClass baseClass = subBinding.getBaseClass(); - baseClass.addAdaptingTeam(teamClassName); - return baseClass; - } - } - return new BoundClass(className, teamClassName); - } - - // ==== HELPERS FOR RE-ENTRANCE SAFETY: ==== - - private static Iterator<String> getBaseBindingsKeyIterator() { - synchronized (baseBindings) { - ArrayList<String> list = new ArrayList<String>(); - list.addAll(baseBindings.keySet()); - Iterator<String> it = list.iterator(); - return it; - } - } - - private static Iterator<Entry<String, LinkedList<RoleBaseBinding>>> getBaseBindingsCloneIterator() { - synchronized (baseBindings) { - ArrayList<Entry<String, LinkedList<RoleBaseBinding>>> list = new ArrayList<Entry<String,LinkedList<RoleBaseBinding>>>(); - list.addAll(baseBindings.entrySet()); - Iterator<Entry<String, LinkedList<RoleBaseBinding>>> it = list.iterator(); - return it; - } - } -} diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/DebugUtil.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/DebugUtil.java deleted file mode 100644 index c6e8d8072..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/DebugUtil.java +++ /dev/null @@ -1,155 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2003-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: DebugUtil.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre.util; - -import org.apache.bcel.generic.*; -import org.apache.bcel.Constants; -import java.util.Iterator; - -import org.eclipse.objectteams.otre.OTConstants; - -/** - * @author Stephan Herrmann - */ -@SuppressWarnings("nls") -public class DebugUtil { - - // ----------------------------------------- - // -------- Development utilities --------- - // ----------------------------------------- - - /** - * Creates an the instructions necessary to "System.out.println" - * the given string. - * - * @param cpg the constant pool of the class where this instructions - * will be inserted - * @param string the String to be printed - * @return an InstructionList containing the necessary instructions - */ - public static InstructionList createPrintln(ConstantPoolGen cpg, - InstructionFactory factory, - String string) - { - InstructionList il = new InstructionList(); - ObjectType p_stream = new ObjectType("java.io.PrintStream"); - - il.append(factory.createFieldAccess("java.lang.System", "out", - p_stream, - Constants.GETSTATIC)); - il.append(new PUSH(cpg, string + "\n")); - il.append(factory.createInvoke("java.io.PrintStream", "print", - Type.VOID, - new Type[] { Type.STRING }, - Constants.INVOKEVIRTUAL)); - return il; - } - - /** - * Create a <tt>System.out.println</tt> call for an <tt>Object</tt> - * argument. The argument is assumed to be on the stack and will not - * be consumed. - */ - public static InstructionList createPrintlnObj(InstructionFactory factory) { - InstructionList il = new InstructionList(); - ObjectType p_stream = new ObjectType("java.io.PrintStream"); - - il.append(new DUP()); - il.append(factory.createFieldAccess("java.lang.System", "out", - p_stream, - Constants.GETSTATIC)); - il.append(new SWAP()); - il.append(factory.createInvoke("java.io.PrintStream", "print", - Type.VOID, - new Type[] { OTConstants.object }, - Constants.INVOKEVIRTUAL)); - return il; - } - - /** - * Create a <tt>System.out.println</tt> call for an <tt>Exception</tt> - * argument. The argument is assumed to be on the stack and _will_ - * be consumed. This effect is however only performed, if - * the property ot.log.lift is set. - */ - public static InstructionList createReportExc(InstructionFactory factory) { - InstructionList il = new InstructionList(); - if (System.getProperty("ot.log.lift") == null) { - il.append(new POP()); - } else { - ObjectType p_stream = new ObjectType("java.io.PrintStream"); - - il.append(factory.createFieldAccess("java.lang.System", "out", - p_stream, - Constants.GETSTATIC)); - il.append(new SWAP()); - il.append(factory.createInvoke("java.io.PrintStream", "println", - Type.VOID, - new Type[] { OTConstants.object }, - Constants.INVOKEVIRTUAL)); - } - return il; - } - - /** - * Create a <tt>System.out.println</tt> call for an <tt>int</tt> - * argument. The argument is assumed to be on the stack and will not - * be consumed. - */ - public static InstructionList createPrintlnInt(InstructionFactory factory) { - InstructionList il = new InstructionList(); - ObjectType p_stream = new ObjectType("java.io.PrintStream"); - - il.append(new DUP()); - il.append(factory.createFieldAccess("java.lang.System", "out", - p_stream, - Constants.GETSTATIC)); - il.append(new SWAP()); - il.append(factory.createInvoke("java.io.PrintStream", "print", - Type.VOID, - new Type[] { Type.INT }, - Constants.INVOKEVIRTUAL)); - return il; - } - - public static InstructionList createPrintlnBool(ConstantPoolGen cp) { - InstructionList il= new InstructionList(); - int out = cp.addFieldref("java.lang.System", "out", - "Ljava/io/PrintStream;"); - int println = cp.addMethodref("java.io.PrintStream", "println", - "(Z)V"); - il.append(new DUP()); - il.append(new GETSTATIC(out)); - il.append(new SWAP()); - il.append(new INVOKEVIRTUAL(println)); - return il; - } - - @SuppressWarnings("unchecked") - public static void printIL (InstructionList il, ConstantPoolGen cpg) { - int off = 0; - Iterator<InstructionHandle> it = il.iterator(); - while(it.hasNext()) { - Instruction i = it.next().getInstruction(); - off += i.produceStack(cpg); - off -= i.consumeStack(cpg); - System.out.print(off); - System.out.println(" = "+i); - } - } - -} diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/FieldDescriptor.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/FieldDescriptor.java deleted file mode 100644 index 30a3dd026..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/FieldDescriptor.java +++ /dev/null @@ -1,53 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2004-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: FieldDescriptor.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre.util; - -/** - * @author resix - */ -public class FieldDescriptor { - private String fieldName; - private String fieldSignature; - private boolean isStaticField; - - public FieldDescriptor(String name, String signature, boolean is_static) { - fieldName = name; - fieldSignature = signature; - isStaticField = is_static; - } - - /** - * @return Returns the fieldName. - */ - public String getFieldName() { - return fieldName; - } - - /** - * @return Returns the fieldSignature. - */ - public String getFieldSignature() { - return fieldSignature; - } - - /** - * @return Returns the isStaticField. - */ - public boolean isStaticField() { - return isStaticField; - } -} diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/ListValueHashMap.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/ListValueHashMap.java deleted file mode 100644 index 8b7b463ed..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/ListValueHashMap.java +++ /dev/null @@ -1,103 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2004-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: ListValueHashMap.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre.util; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; -import java.util.Map.Entry; - -/** - * @author resix - */ -public class ListValueHashMap<ValueType> { - private HashMap<String, LinkedList<ValueType>> hashMap = new HashMap<String, LinkedList<ValueType>>(); - //redundant structure for faster access: - private LinkedList<ValueType> flattenValues = new LinkedList<ValueType>(); - - /** - * @param key - * @param value - */ - public void put(String key, ValueType value) { - LinkedList<ValueType> list; - if (!hashMap.containsKey(key)) { - list = new LinkedList<ValueType>(); - } else { - list = hashMap.get(key); - } - list.add(value); - hashMap.put(key, list); - flattenValues.add(value); - } - - /** - * @return - */ - public List<ValueType> getFlattenValues() { - return flattenValues; - } - - /** - * @param key - * @return - */ - public LinkedList<ValueType> get(String key) { - if (!hashMap.containsKey(key)) { - return null; - } - return hashMap.get(key); - } - - public boolean containsKey(Object o) { - return hashMap.containsKey(o); - } - - public Set<String> keySet() { - return hashMap.keySet(); - } - - public Set<Entry<String, LinkedList<ValueType>>> entrySet() { - return hashMap.entrySet(); - } - - public int size() { - return hashMap.size(); - } - - public String toString() { - StringBuilder result = new StringBuilder(32); - Iterator<Entry<String,LinkedList<ValueType>>> it = hashMap.entrySet().iterator(); - while (it.hasNext()) { - Entry<String,LinkedList<ValueType>> entry = it.next(); - result.append(entry.getKey()); - result.append(": "); - result.append(entry.getValue().toString()); - result.append("\n"); - } - if (result.length() == 0) - return super.toString(); - return result.toString(); - } - - public Collection<LinkedList<ValueType>> valueSet() { - return hashMap.values(); - } -} diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/MethodBinding.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/MethodBinding.java deleted file mode 100644 index ecc543659..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/MethodBinding.java +++ /dev/null @@ -1,395 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2002-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: MethodBinding.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre.util; - -import org.eclipse.objectteams.otre.OTConstants; - -/** - * @version $Id: MethodBinding.java 23408 2010-02-03 18:07:35Z stephan $ - * @author Christine Hundt - */ -public class MethodBinding { - - private String bindingFileName; - private int bindingLineNumber; - private int bindingLineOffset; - - private String bindingLabel; - - private BoundMethod baseMethod; - private BoundMethod roleMethod; - - private boolean isStaticBaseMethod; - private boolean isStaticRoleMethod; - private boolean covariantBaseReturn; - - private int translationFlags; - - private String wrapperName; - private String wrapperSignature; - - private String modifier; - private String liftMethodName; - private String liftMethodSignature; - - private String roleClassName; - - // back reference for the class binding containing this method binding. - private RoleBaseBinding classBinding; - - /** - * - */ - public MethodBinding() {} - - /** - * @param bindingFileName - * @param bindingLineNumber - * @param bindingLineOffest - * @param bindingLabel - * @param roleMethodName - * @param roleMethodSignature - * @param isStaticRoleMethod - * @param wrapperName - * @param wrapperSignature - * @param modifier - * @param baseMethodName - * @param baseMethodSignature - * @param isStaticBaseMethod - * @param baseIsCallin - * @param liftMethodName - * @param liftMethodSignature - * @param classBinding - */ - public MethodBinding( - String bindingFileName, int bindingLineNumber, int bindingLineOffest, - String bindingLabel, String roleMethodName, String roleMethodSignature, boolean isStaticRoleMethod, - String wrapperName, String wrapperSignature, String modifier, - String baseMethodName, String baseMethodSignature, - boolean isStaticBaseMethod, boolean baseIsCallin, boolean covariantBaseReturn, - int translationFlags, - String liftMethodName, String liftMethodSignature, RoleBaseBinding classBinding) - { - this.bindingFileName = bindingFileName; - this.bindingLineNumber = bindingLineNumber; - this.bindingLineOffset = bindingLineOffest; - - this.bindingLabel = bindingLabel; - roleMethod = new BoundMethod(roleMethodName, roleMethodSignature, false, this); - baseMethod = new BoundMethod(baseMethodName, baseMethodSignature, baseIsCallin, this); - // BoundMethod object for one method is not unique! - // but if it would be unique the 'binding' link would not be unique - this.isStaticRoleMethod = isStaticRoleMethod; - this.isStaticBaseMethod = isStaticBaseMethod; - this.covariantBaseReturn = covariantBaseReturn; - this.translationFlags = translationFlags; - this.wrapperName = wrapperName; - this.wrapperSignature = wrapperSignature; - this.modifier = modifier; - this.liftMethodName = liftMethodName; - this.liftMethodSignature = liftMethodSignature; - this.classBinding = classBinding; - this.roleClassName = classBinding.getRoleClassName(); - } - - /** - * @return - */ - public String getRoleClassName() { - return roleClassName; - } - - /** - * @return - */ - public String getBindingFileName() { - return bindingFileName; - } - - /** - * @return - */ - public int getBindingLineNumber() { - return bindingLineNumber; - } - - /** - * @return - */ - public int getBindingLineOffset() { - return bindingLineOffset; - } - - /** - * @return - */ - public String getBindingLabel() { - return bindingLabel; - } - - /** - * @return - */ - public String getQualifiedBindingLabel() { - String result = roleClassName; - // remove the outermost team (use the '$' to distinguish pack1.Team1$Role from Team1$__OT__Team2$Role): - result = result.substring(result.indexOf('$') + 1); - // replace "$" by "." in the role class name: - result = result.replace('$', '.'); - // remove "__OT__" prefixes in role class names: - result = result.replace(OTConstants.OTDT_PREFIX, ""); //$NON-NLS-1$ - // add the binding label and return: - return result + '.' + bindingLabel; - } - - /** - * @return - */ - public String getRoleMethodName() { - return roleMethod.getName(); - } - - /** - * @return - */ - public String getRoleMethodSignature() { - return roleMethod.getSignature(); - } - - /** - * @return - */ - public String getWrapperName() { - return wrapperName; - } - - /** - * @return - */ - public String getWrapperSignature() { - return wrapperSignature; - } - - /** - * @return - */ - public String getBaseClassName() { - return classBinding.getBaseClassName(); - } - - /** - * @return - */ - public String getBaseMethodName() { - return baseMethod.getName(); - } - - /** - * @return - */ - public String getBaseMethodSignature() { - return baseMethod.getSignature(); - } - - /** - * @return - */ - public boolean baseMethodIsCallin() { - return baseMethod.getIsCallin(); - } - - /** - * @return - */ - public String getModifier() { - return modifier; - } - - /** - * @return - */ - public boolean isReplace() { - return modifier.equals("replace"); - } - - /** - * @return - */ - public boolean isAfter() { - return modifier.equals("after"); - } - - /** - * @return - */ - public boolean isBefore() { - return modifier.equals("before"); - } - - /** - * @return Returns the liftMethodName. - */ - public String getLiftMethodName() { - return liftMethodName; - } - - /** - * @return Returns the liftMethodSignature. - */ - public String getLiftMethodSignature() { - return liftMethodSignature; - } - - /** - * @return Returns the corresponding class binding. - */ - public RoleBaseBinding getClassBinding() { - return classBinding; - } - - /** - * Returns the most super bound base class of the base class belonging to - * this MethodBinding. Note: only consider base classes bound by roles of - * the corresponding team! - * - * @return the most super bound base class - */ - public String getRootBoundBase() { - BoundClass bc = classBinding.getRoleClass(); - while (bc.getSuper() != null && CallinBindingManager.isBoundRoleClass(bc.getSuper().getName()) ) { - bc = bc.getSuper(); - } - RoleBaseBinding rbb = CallinBindingManager.getRoleBaseBinding(bc.getName()); - return rbb.getBaseClassName(); - } - - /** - * Returns the name of the team surrounding the role class of this binding. - * - * @return the name of the corresponding team - */ - public String getTeamClassName() { - int dollarIndex = roleClassName.lastIndexOf('$'); - // return everything before the last '$', because for nested teams there are more than one: - return roleClassName.substring(0, dollarIndex); - } - - /** - * @param anotherMB - * @return - */ - public boolean overridesMethodBinding(MethodBinding anotherMB) { - if (anotherMB == null) - return false; - if (!bindingLabel.equals(anotherMB.getBindingLabel())) - return false; - return classBinding.getRoleClass().isSubClassOf(anotherMB.getClassBinding().getRoleClassName()); - } - - /** - * @param bindingLabel - * @param teamName - * @return - */ - public boolean inheritsBindingLabel(String bindingLabel, String teamName) { - String prefix = teamName + "$__OT__"; - int dotIndex = bindingLabel.lastIndexOf('.'); - String classOfLabel = prefix + bindingLabel.substring(0, dotIndex); - if (!bindingLabel.substring(dotIndex + 1).equals(this.bindingLabel)) - return false; - - if (classBinding.getRoleClass().isSubClassOf(classOfLabel)) - return true; - return false; - } - - /** - * @param mb - * @return - */ - public boolean equals(MethodBinding mb) { - return roleMethod.getName().equals(mb.getRoleMethodName()) - && roleMethod.getSignature().equals(mb.getRoleMethodSignature()) - && classBinding.getBaseClassName().equals(mb.getBaseClassName()) - && baseMethod.getName().equals(mb.getBaseMethodName()) - && baseMethod.getSignature().equals(mb.getBaseMethodSignature()) - && modifier.equals(mb.getModifier()); - } - - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - public String toString() { - StringBuilder result = new StringBuilder(32); - result.append("\t"); - result.append(getQualifiedBindingLabel()); - result.append(": "); - result.append(roleMethod.getName()); - result.append(roleMethod.getSignature()); - result.append(" <-> "); - result.append(modifier); - result.append(" "); - result.append(baseMethod.getName()); - result.append(baseMethod.getSignature()); - if (this.covariantBaseReturn) - result.append('+'); - return result.toString(); - } - - /** - * @return - */ - public boolean hasStaticRoleMethod() { - return isStaticRoleMethod; - } - - /** - * @return - */ - public boolean hasStaticBaseMethod() { - return isStaticBaseMethod; - } - - public int getTranslationFlags() { - return this.translationFlags; - } - - /** For base methods provide a key without the trailing return type to cater for covariance. */ - static String getBaseMethodKey(String baseMethodName, String baseMethodSignature) { - int pos= baseMethodSignature.lastIndexOf(')'); - String baseMethodKey = baseMethodName + '.' + baseMethodSignature.substring(0, pos+1); - return baseMethodKey; - } - - /** - * Is the method specified by mName and mSig a match for this method binding? - * @param mName method name - * @param mSig full method signature - * @param strict if true covariance is not supported - */ - public boolean matchesMethod(String mName, String mSig, boolean strict) { - String baseMethodName = getBaseMethodName(); - String baseMethodSignature = getBaseMethodSignature(); - if (this.covariantBaseReturn && !strict) { - return getBaseMethodKey(mName, mSig).equals( - getBaseMethodKey(baseMethodName, baseMethodSignature)); - } else { - return mName.equals(baseMethodName) - && mSig.equals(baseMethodSignature); - } - } -} diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/RoleBaseBinding.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/RoleBaseBinding.java deleted file mode 100644 index 2a8c30b84..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/RoleBaseBinding.java +++ /dev/null @@ -1,228 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2002-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: RoleBaseBinding.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre.util; - -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; - -/** - * @version $Id: RoleBaseBinding.java 23408 2010-02-03 18:07:35Z stephan $ - * @author Christine Hundt - */ -public class RoleBaseBinding { - - private BoundClass roleClass; - private BoundClass baseClass; - - private ListValueHashMap<MethodBinding> roleMethodBindings = new ListValueHashMap<MethodBinding>(); - private ListValueHashMap<MethodBinding> baseMethodBindings = new ListValueHashMap<MethodBinding>(); - - /** - * - */ - public RoleBaseBinding() { - } - - /** - * @param _roleClassName - * @param _baseClassName - * @param teamClassName - */ - public RoleBaseBinding(String _roleClassName, String _baseClassName, String teamClassName) { - roleClass = new BoundClass(_roleClassName, teamClassName); - baseClass = CallinBindingManager.getBoundBaseClass(_baseClassName, teamClassName); - } - - /** - * @param bindingFileName - * @param bindingLineNumber - * @param bindingLineOffset - * @param bindingLabel - * @param roleMethodName - * @param roleMethodSignature - * @param isStaticRoleMethod - * @param wrapperName - * @param wrapperSignature - * @param modifier - * @param baseMethodName - * @param baseMethodSignature - * @param isStaticBaseMethod - * @param baseIsCallin - * @param translationFlags - * @param liftMethodName - * @param liftMethodSignature - */ - public void addMethodBinding( - String bindingFileName, int bindingLineNumber, int bindingLineOffset, - String bindingLabel, String roleMethodName, String roleMethodSignature, - boolean isStaticRoleMethod, String wrapperName, String wrapperSignature, String modifier, - String baseMethodName, String baseMethodSignature, - boolean isStaticBaseMethod, boolean baseIsCallin, boolean covariantBaseReturn, - int translationFlags, String liftMethodName, String liftMethodSignature) - { - MethodBinding mb = new MethodBinding(bindingFileName, bindingLineNumber, bindingLineOffset, - bindingLabel, roleMethodName, roleMethodSignature, isStaticRoleMethod, - wrapperName, wrapperSignature, modifier, - baseMethodName, baseMethodSignature, - isStaticBaseMethod, baseIsCallin, covariantBaseReturn, - translationFlags, - liftMethodName, - liftMethodSignature, this); - // TODO: check, if the key has to include the 'binding_label' - String baseMethodKey = MethodBinding.getBaseMethodKey(baseMethodName, baseMethodSignature); - String roleMethodKey = roleMethodName + '.' + roleMethodSignature; - roleMethodBindings.put(roleMethodKey, mb); - baseMethodBindings.put(baseMethodKey, mb); - } - - /** - * @return - */ - public List<MethodBinding> getBaseMethodBindings() { - return baseMethodBindings.getFlattenValues(); - } - - /** - * @param baseMethodName - * @param baseMethodSignature - * @return - */ - public List<MethodBinding> getBaseMethodBindings(String baseMethodName, String baseMethodSignature) { - String baseMethodKey = MethodBinding.getBaseMethodKey(baseMethodName, baseMethodSignature); - return baseMethodBindings.get(baseMethodKey); - } - - /** - * @return - */ - public List<MethodBinding> getRoleMethodBindings() { - return roleMethodBindings.getFlattenValues(); - } - - /** - * @param roleMethodName - * @param roleMethodSignature - * @return - */ - public List<MethodBinding> getRoleMethodBindings(String roleMethodName, String roleMethodSignature) { - String roleMethodKey = roleMethodName + '.' + roleMethodSignature; - return roleMethodBindings.get(roleMethodKey); - } - - /** - * @param roleMethodName - * @param roleMethodSignature - * @return - */ - public boolean hasRoleMethodBinding(String roleMethodName, String roleMethodSignature) { - String signatureWithoutReturnType = roleMethodSignature.substring(0, roleMethodSignature.lastIndexOf(')') + 1); - Set<String> bindingKeys = roleMethodBindings.keySet(); - Iterator<String> it = bindingKeys.iterator(); - while (it.hasNext()) { - String key = it.next(); - String keyWithoutReturnType = key.substring(0, key.lastIndexOf(')') + 1); - if (keyWithoutReturnType.equals(roleMethodName + '.' - + signatureWithoutReturnType)) - return true; - } - return false; - } - - public Set<String> getRoleMethodSignatures() { - return roleMethodBindings.keySet(); - } - - /** - * @return - */ - public BoundClass getRoleClass() { - return roleClass; - } - - /** - * @return - */ - public BoundClass getBaseClass() { - return baseClass; - } - - /** - * @return - */ - public String getRoleClassName() { - return roleClass.getName(); - } - - /** - * @return - */ - public String getBaseClassName() { - return baseClass.getName(); - } - - /** - * Collect all base method signatures for this role-base pair. - * @result List <String[] {name, signature}> - */ - public List<String[]> getBaseSignatures () { - List<String[]> result = new LinkedList<String[]>(); - List<MethodBinding> baseMethodBindingList = getBaseMethodBindings(); - Iterator<MethodBinding> it = baseMethodBindingList.iterator(); - while (it.hasNext()) { - MethodBinding mb = it.next(); - result.add(new String [] { - mb.getBaseMethodName(), - mb.getBaseMethodSignature() - }); - } - return result; - } - - /** - * @param rbb - * @return - */ - public boolean equals(RoleBaseBinding rbb) { - return roleClass.getName().equals(rbb.getRoleClassName()) - && baseClass.getName().equals(rbb.getBaseClassName()); - } - - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - public String toString() { - StringBuilder out = new StringBuilder(64); - out.append(roleClass.getName()); - out.append(" <-> "); - out.append(baseClass.getName()); - out.append("\nmethod bindings:\n"); - List<MethodBinding> mbsList = getBaseMethodBindings(); - Iterator<MethodBinding> it = mbsList.iterator(); - while (it.hasNext()) { - MethodBinding mb = it.next(); - out.append("\n"); - out.append(mb.getBaseMethodName()); - out.append("."); - out.append(mb.getBaseMethodSignature()); - out.append(":"); - out.append(mb.toString()); - } - return out.toString(); - } -} diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/SuperMethodDescriptor.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/SuperMethodDescriptor.java deleted file mode 100644 index 02b9c04de..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/SuperMethodDescriptor.java +++ /dev/null @@ -1,33 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2008 Technical University Berlin, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: SuperMethodDescriptor.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Technical University Berlin - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre.util; - -/** Representation of a base-super method call, requiring a special access method. */ -public class SuperMethodDescriptor { - public String methodName; - public String declaringClass; - public String superClass; - public String signature; - public SuperMethodDescriptor(String methodName, String declaringClass, - String superClass, String signature) { - super(); - this.methodName = methodName; - this.declaringClass = declaringClass; - this.superClass = superClass; - this.signature = signature; - } -} diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/TeamIdDispenser.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/TeamIdDispenser.java deleted file mode 100644 index 100a0a1da..000000000 --- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/util/TeamIdDispenser.java +++ /dev/null @@ -1,69 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2002-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: TeamIdDispenser.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.eclipse.objectteams.otre.util; -import java.util.*; - -public class TeamIdDispenser { - - private static Map<ClassLoader, TeamIdDispenser> instances = new HashMap<ClassLoader, TeamIdDispenser>(); - private static TeamIdDispenser defaultInstance = new TeamIdDispenser(); - - static int lastDispensedId = 0; - private static HashMap<String, Integer> teamIDs = new HashMap<String, Integer>(); - -// @SuppressWarnings("unchecked") - private static int produceNextTeamId(String team_name) { - lastDispensedId++; - Integer teamId = Integer.valueOf(lastDispensedId); - teamIDs.put(team_name, teamId); - return lastDispensedId; - } - - public static int getTeamId(String class_name) { - Integer teamId = teamIDs.get(class_name); - if (teamId != null) - // the team <class_name> already has a team-id assigned - return teamId.intValue(); - else return produceNextTeamId(class_name); - } - - // Data shared among different transformers of the same class loader: - // REFACTOR: move the following to a better place: - private ArrayList<String> clinitAddedClasses = new ArrayList<String>(); - public static boolean clinitAdded(String class_name, ClassLoader loader) { - TeamIdDispenser instance = getInstanceForLoader(loader); - if (instance.clinitAddedClasses.contains(class_name)) - return true; - - instance.clinitAddedClasses.add(class_name); - return false; - } - - /** - * Since actual data are stored in an instance, static methods need to retrieve the appropriate - * instance regarding the given class loader. - */ - private static TeamIdDispenser getInstanceForLoader(ClassLoader loader) { - if (loader == null) - return defaultInstance; - - TeamIdDispenser instance = instances.get(loader); - if (instance == null) - instances.put(loader, instance = new TeamIdDispenser()); - return instance; - } -} diff --git a/othersrc/OTRE/src/org/objectteams/DoublyWeakHashMap.java b/othersrc/OTRE/src/org/objectteams/DoublyWeakHashMap.java deleted file mode 100644 index 05a2f91fa..000000000 --- a/othersrc/OTRE/src/org/objectteams/DoublyWeakHashMap.java +++ /dev/null @@ -1,106 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2010 Stephan Herrmann. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id$ - * - * Please visit http://www.eclipse.org/objectteams for updates and contact. - * - * Contributors: - * Stephan Herrmann - Initial API and implementation - **********************************************************************/ -package org.objectteams; - -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; -import java.util.Set; -import java.util.WeakHashMap; - -/** - * This class defines hash maps where both key and value are weak references. - * It is implemented by delegating to a WeakHashMap and additionally - * wrapping the value in a WeakReference. - * - * @author stephan - * @since 0.7.0 - * @param <K> type of keys: a base class - * @param <V> type of values: a role class - */ -public class DoublyWeakHashMap<K,V> implements Map<K,V> { - - private WeakHashMap<K, WeakReference<V>> map; - - public DoublyWeakHashMap() { - this.map = new WeakHashMap<K, WeakReference<V>>(); - } - - public int size() { - return this.map.size(); - } - - public boolean isEmpty() { - return this.map.isEmpty(); - } - - // used from hasRole() and lifting (duplicate role check) - public boolean containsKey(Object key) { - return this.map.containsKey(key); - } - - public boolean containsValue(Object value) { - throw new UnsupportedFeatureException("Method containsValue is not implemented for internal class DoublyWeakHashMap."); - } - - // used from getRole() - public V get(Object key) { - WeakReference<V> valRef = this.map.get(key); - return valRef == null ? null : valRef.get(); - } - - // used from migrateToBase() and lifting constructor - public synchronized V put(K key, V value) { - this.map.put(key, new WeakReference<V>(value)); - return value; - } - - // used from unregisterRole(), migrateToBase() - public synchronized V remove(Object key) { - WeakReference<V> value = this.map.remove(key); - return (value == null) ? null : value.get(); - } - - public void putAll(Map<? extends K, ? extends V> t) { - for (Entry<? extends K, ? extends V> entry : t.entrySet()) - this.map.put(entry.getKey(), new WeakReference<V>(entry.getValue())); - } - - public void clear() { - this.map.clear(); - } - - public Set<K> keySet() { - return this.map.keySet(); - } - - // used from getAllRoles() et al. - public synchronized Collection<V> values() { - ArrayList<V> result = new ArrayList<V>(this.map.size()); - for (WeakReference<V> valRef : this.map.values()) { - V value = valRef.get(); - if (value != null) - result.add(value); - } - return result; - } - - public Set<java.util.Map.Entry<K, V>> entrySet() { - throw new UnsupportedFeatureException("Method entrySet is not implemented for internal class DoublyWeakHashMap."); - } -} diff --git a/othersrc/OTRE/src/org/objectteams/DuplicateRoleException.java b/othersrc/OTRE/src/org/objectteams/DuplicateRoleException.java deleted file mode 100644 index ae3e851a9..000000000 --- a/othersrc/OTRE/src/org/objectteams/DuplicateRoleException.java +++ /dev/null @@ -1,48 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2004-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: DuplicateRoleException.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.objectteams; - -/** - * Signal a violation of OTJLD 2.4.1(c). - * Also Team.getRole(Object) may throw a DuplicateRoleException if - * more than one role is found for the given base object - * (in that case those roles are found in different role-caches). - * - * - * @author stephan - * @version $Id: DuplicateRoleException.java 23408 2010-02-03 18:07:35Z stephan $ - */ -public class DuplicateRoleException extends RuntimeException { - - /** - * - */ - private static final long serialVersionUID = 1L; - - /** - * @param message - */ - public DuplicateRoleException(String roleClassName) { - super("Failed to create a role instance of type "+roleClassName+"\n"+ - "A role for the given base object already exists (OTJLD 2.4.1(c))."); - } - - public DuplicateRoleException(String roleName1, String roleName2) { - super("Ambiguous role instances: found a role in hierarchies "+ - roleName1+" and "+roleName2); - } -} diff --git a/othersrc/OTRE/src/org/objectteams/IBaseMigratable.java b/othersrc/OTRE/src/org/objectteams/IBaseMigratable.java deleted file mode 100644 index edc9202ba..000000000 --- a/othersrc/OTRE/src/org/objectteams/IBaseMigratable.java +++ /dev/null @@ -1,35 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2008 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: IBaseMigratable.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.objectteams; - -/** - * Marker interface: if a role declares to implement this interface - * the compiler will generate the method defined herein, and prepare - * the role so that the migration will indeed be possible. - * - * @author stephan - * @since 1.2.5 - */ -public interface IBaseMigratable { - /** - * Migrate the current role to the otherBase. - * - * @param otherBase new base that this role should adapt, must - * be of a valid base type for the current role. - */ - <B> void migrateToBase(B otherBase); -} diff --git a/othersrc/OTRE/src/org/objectteams/IBoundBase.java b/othersrc/OTRE/src/org/objectteams/IBoundBase.java deleted file mode 100644 index 9f196bf92..000000000 --- a/othersrc/OTRE/src/org/objectteams/IBoundBase.java +++ /dev/null @@ -1,28 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2007-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: IBoundBase.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.objectteams; - -/** - * Super type for all bound base classes. Purely internal class, not intended for client use. - * @author Stephan Herrmann - */ -public interface IBoundBase { - /** Method to be used by generated code, only (lifting constructor). */ - void _OT$addRole(Object aRole); - /** Method to be used by generated code, only (unregisterRole()). */ - void _OT$removeRole(Object aRole); -}
\ No newline at end of file diff --git a/othersrc/OTRE/src/org/objectteams/IConfined.java b/othersrc/OTRE/src/org/objectteams/IConfined.java deleted file mode 100644 index 8ead4b473..000000000 --- a/othersrc/OTRE/src/org/objectteams/IConfined.java +++ /dev/null @@ -1,24 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2004 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: IConfined.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.objectteams; - -/** - * Special interface that does not extend Object - * - * @author stephan - */ -public interface IConfined {}
\ No newline at end of file diff --git a/othersrc/OTRE/src/org/objectteams/ILiftingParticipant.java b/othersrc/OTRE/src/org/objectteams/ILiftingParticipant.java deleted file mode 100644 index 408d0873e..000000000 --- a/othersrc/OTRE/src/org/objectteams/ILiftingParticipant.java +++ /dev/null @@ -1,40 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2009 Stephan Herrmann - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: ILiftingParticipant.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Stephan Herrmann - Initial API and implementation - **********************************************************************/ -package org.objectteams; - -/** - * A lifting participant hooks into the lifting process. - * - * @author stephan - * @since 1.3.1 - */ -public interface ILiftingParticipant { - /** - * This method is called when lifting does not find a suitable role within the - * team's internal role cache. If this method returns a non-null value, - * this value is considered by the runtime as being the desired role - * (i.e., it must be castable to that role type), and no new role is created. - * If this method returns null, lifting proceeds as normal, i.e., - * a fresh role is created using the default lifting constructor. - * - * @param teamInstance - * @param baseInstance - * @param roleClassName - * @return either null or an instance of the class specified by roleClassName - */ - Object createRole(ITeam teamInstance, Object baseInstance, String roleClassName); -} diff --git a/othersrc/OTRE/src/org/objectteams/ITeam.java b/othersrc/OTRE/src/org/objectteams/ITeam.java deleted file mode 100644 index b77c5f092..000000000 --- a/othersrc/OTRE/src/org/objectteams/ITeam.java +++ /dev/null @@ -1,206 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2010 Stephan Herrmann. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: ITeam.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Stephan Herrmann - Initial API and implementation - **********************************************************************/ -package org.objectteams; - -/** - * Public interface of all team classes. - */ -public interface ITeam { - - /** - * Interface for all role classes that should allow explicit lowering. - * The interface provides a phantom method <pre><B> B lower()</pre> - * where B is the bound base class of the implementing role class. - * There is no need to implement the method lower, since this is done by the compiler. - */ - public interface ILowerable { - // internal method needed for cast and instanceof - ITeam _OT$getTeam(); - } - - /** - * This role interface has no properties not even those of java.lang.Object. - */ - public interface IConfined extends org.objectteams.IConfined { - // internal method needed for cast and instanceof - ITeam _OT$getTeam(); - } - - - /** - * Activates the team and therefore all of its callin bindings. - * This activation applies to the current thread only. - */ - public abstract void activate(); - - /** - * Deactivates the team and therefore all of its callin bindings. - * This deactivation applies to the current thread only. - */ - public abstract void deactivate(); - - /** - * Activates the team and therefore all of its callin bindings for passed thread. - * If the constant 'Team.ALL_THREADS' is passed, this activation globally applies to all threads. - */ - public abstract void activate(Thread thread); - - /** - * Deactivates the team and therefore all of its callin bindings for passed thread. - * If the constant 'Team.ALL_THREADS' is passed, this deactivation globally applies to all threads. - */ - public abstract void deactivate(Thread thread); - - /** - * Checks, if the team instance is active for the current thread. - * @return true, if the team is active, false else. - */ - public abstract boolean isActive(); - - /** - * Checks, if the team instance is active for the 'thread'. - * @param thread The thread for which to check activity. - * @return true, if the team is active for 'thread', false else. - */ - public abstract boolean isActive(Thread thread); - - /** - * Does given base object have a role in this team? - * This method will consider roles of any type. - * - * @param aBase any object, i.e., no checks are performed whether the base object's - * class is bound by any role class in this team. - * @return - */ - public abstract boolean hasRole(Object aBase); - - /** - * Does given base object have a role in this team? - * The role must be an instance of the specified role type. - * - * @param aBase any object, i.e., no checks are performed whether the base object's - * class is bound by any role class in this team. - * @param roleType Class instance specifying the required role type. - * TODO (SH): is it legal to pass an unbound role class? - * @throws IllegalArgumentException if <code>roleType</code> does not represent a member type of this team. - * @return - */ - public abstract boolean hasRole(Object aBase, Class<?> roleType) throws IllegalArgumentException; - - /** - * Retrieve a role for a given base object. - * If more than one role exists, a DuplicateRoleException is thrown. - * - * @param aBase - * @return - */ - public abstract Object getRole(Object aBase); - - /** - * Retrieve a role for a given base object. - * The role must be an instance of the specified role type. - * - * @param aBase any object, i.e., no checks are performed whether the base object's - * class is bound by any role class in this team. - * @param roleType Class instance specifying the required role type. - * @return - * @throws IllegalArgumentException if <code>roleType</code> does not represent a member type of this team. - */ - public abstract <T> T getRole(Object aBase, Class<T> roleType) throws IllegalArgumentException; - - /** - * Retrieve all bound roles registered in the current team. - * - * This method uses internal structures of weak references. - * For that reason it may return role instances which were about to be reclaimed - * by the garbage collector. - * If performance permits, it is thus advisable to always call System.gc() - * prior to calling getAllRoles() in order to achieve deterministic results - * - * @return a non-null array. - */ - public abstract Object[] getAllRoles(); - - /** - * Retrieve all bound roles registered in the current team that - * are instance of roleType or a subtype thereof. - * - * This method uses internal structures of weak references. - * For that reason it may return role instances which were about to be reclaimed - * by the garbage collector. - * If performance permits, it is thus advisable to always call System.gc() - * prior to calling getAllRoles() in order to achieve deterministic results - * - * @param roleType must be a top-most bound role of this team. - * @return a non-null array. - * @throws IllegalArgumentException if <code>roleType</code> does not represent a member type of this team. - */ - public abstract <T> T[] getAllRoles(Class<T> roleType) throws IllegalArgumentException; - - /** - * Query whether any role instance of this team instance is currently executing a - * method due to a callin binding. - * @return - */ - public abstract boolean isExecutingCallin(); - - /** - * Remove a role from the internal registry, which means that the role will no longer be - * considered during lifting. - * - * @param aRole - */ - public abstract void unregisterRole(Object aRole); - - /** - * Remove a role from the internal registry, which means that the role will no longer be - * considered during lifting. - * - * @param aRole - * @param roleType - * @throws IllegalArgumentException if <code>roleType</code> does not represent a member type of this team. - */ - public abstract void unregisterRole(Object aRole, Class<?> roleType) throws IllegalArgumentException; - - /** - * Not API. - * This method saves the activation state of the team for the current thread. - * If active, it also saves, if the activation was explicit or implicit. - * This method has to be called by the generated code when entering a within block, - * before the activation. - */ - public int _OT$saveActivationState(); - - /** - * Not API. - * This method restores the former saved activation state of the team for the current thread. - * If active, it also restores, if the activation was explicit or implicit. - * This method has to be called by the generated code when leaving a within block - * (in the finally block). - */ - public void _OT$restoreActivationState(int old_state); - - /** - * Not API, for use by TeamThreadManager, only. - */ - public boolean internalIsActiveSpecificallyFor(Thread t); - - /** - * Not API, for use by TeamThreadManager, only. - */ - public void deactivateForEndedThread(Thread thread); -}
\ No newline at end of file diff --git a/othersrc/OTRE/src/org/objectteams/ITeamMigratable.java b/othersrc/OTRE/src/org/objectteams/ITeamMigratable.java deleted file mode 100644 index 39be5661f..000000000 --- a/othersrc/OTRE/src/org/objectteams/ITeamMigratable.java +++ /dev/null @@ -1,36 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2008 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: ITeamMigratable.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.objectteams; - -/** - * Marker interface: if a role declares to implement this interface - * the compiler will generate the method defined herein, and prepare - * the role so that the migration will indeed be possible. - * Note, that a migratable role does not obey the family guarantee. - * - * @author stephan - * @since 1.2.5 - */ -public interface ITeamMigratable { - /** - * Migrate the current role to the otherTeam. - * - * @param otherTeam new team that should adopt this role - * @return the migrated (and re-typed) role (actually of type R<@otherTeam>). FIXME(SH) - */ - <R> R migrateToTeam(final ITeam otherTeam); -} diff --git a/othersrc/OTRE/src/org/objectteams/IllegalRoleCreationException.java b/othersrc/OTRE/src/org/objectteams/IllegalRoleCreationException.java deleted file mode 100644 index f745d739b..000000000 --- a/othersrc/OTRE/src/org/objectteams/IllegalRoleCreationException.java +++ /dev/null @@ -1,35 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2007-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: IllegalRoleCreationException.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.objectteams; - -/** - * Exception to be thrown when a bound role is being instantiated but - * the constructor does not assign a base object. - * - * @author stephan - */ -@SuppressWarnings("serial") -public class IllegalRoleCreationException extends RuntimeException { - public IllegalRoleCreationException() { - super(); - } - - @Override - public String getMessage() { - return "Cannot instantiate a bound role using a default constructor of its tsuper class"; - } -} diff --git a/othersrc/OTRE/src/org/objectteams/ImplicitTeamActivation.java b/othersrc/OTRE/src/org/objectteams/ImplicitTeamActivation.java deleted file mode 100644 index 09eda9679..000000000 --- a/othersrc/OTRE/src/org/objectteams/ImplicitTeamActivation.java +++ /dev/null @@ -1,45 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2009 Stephan Herrmann - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id$ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Stephan Herrmann - Initial API and implementation - **********************************************************************/ -package org.objectteams; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * This marker annotation enables implicit team activation for the annotated element: - * <ul> - * <li>If attached to a method the effect is that each call to this method implicitly - * activates the enclosing team.</li> - * <li>If attached to a class it has the same effect as annotating all contained methods.</li> - * </ul> - * See <a href="http://www.objectteams.org/def/1.3/s5.html#s5.3">OTJLD ยง 5.3</a>. - * <p> - * This annotation is only evaluated if the property <code>ot.implicit.team.activation</code> - * is set to the string <code>ANNOTATED</code>. - * </p> - * @author stephan - * @since 1.4.0 - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD, ElementType.TYPE}) -public @interface ImplicitTeamActivation { - /* no members, pure marker annotation. */ -} diff --git a/othersrc/OTRE/src/org/objectteams/LiftingFailedException.java b/othersrc/OTRE/src/org/objectteams/LiftingFailedException.java deleted file mode 100644 index 99f2dd279..000000000 --- a/othersrc/OTRE/src/org/objectteams/LiftingFailedException.java +++ /dev/null @@ -1,46 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2003-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: LiftingFailedException.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.objectteams; - -/** - * This exception signals that lifting failed due to unresolved - * binding ambiguity. - */ -public class LiftingFailedException extends RuntimeException { - /** - * - */ - private static final long serialVersionUID = 1L; - private Object base; - private String roleType; - - /** - * @param base the object that should be lifted - * @param roleType the name of the role type for which - * lifting was attempted. - */ - public LiftingFailedException(Object base, String roleType) { - this.base = base; - this.roleType = roleType; - } - - public String getMessage() { - return "\nFailed to lift '" + base + "' of " + base.getClass() - + " to type '" + roleType - + "'\n(See OT/J definition para. 2.3.4(c))."; - } -} diff --git a/othersrc/OTRE/src/org/objectteams/LiftingVetoException.java b/othersrc/OTRE/src/org/objectteams/LiftingVetoException.java deleted file mode 100644 index 3a9b83aea..000000000 --- a/othersrc/OTRE/src/org/objectteams/LiftingVetoException.java +++ /dev/null @@ -1,45 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2003-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: LiftingVetoException.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.objectteams; - -/** - * This exception is used by the language implementation - * to signal a failed lifting due to a guard predicate that evaluated to false. - * @author Stephan Herrmann - */ -public class LiftingVetoException extends RuntimeException { - /** - * - */ - private static final long serialVersionUID = 1L; - ITeam aTeam = null; - Object base = null; - - public LiftingVetoException(ITeam aTeam, Object base) { - this.aTeam = aTeam; - this.base = base; - } - - public LiftingVetoException() { - super(""); - } - - public String toString() { - return "Team " + aTeam + " refuses to lift " + base - + "\n(this exception should not be seen in applications)."; - } -} diff --git a/othersrc/OTRE/src/org/objectteams/ResultNotProvidedException.java b/othersrc/OTRE/src/org/objectteams/ResultNotProvidedException.java deleted file mode 100644 index b6baccbc5..000000000 --- a/othersrc/OTRE/src/org/objectteams/ResultNotProvidedException.java +++ /dev/null @@ -1,61 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2004-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: ResultNotProvidedException.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.objectteams; - -/** - * @author resix - */ -public class ResultNotProvidedException extends RuntimeException { - - /** - * - */ - private static final long serialVersionUID = 1L; - private static final String _bugmsg = - "\nNo base call executed! Result value was uninitialized!\n(see OT/J language definition para. 4.3(e))."; - - /** - * - */ - public ResultNotProvidedException() { - super(_bugmsg); - } - - /** - * @param message - */ - public ResultNotProvidedException(String message) { - super(_bugmsg + "\n" + message); - StackTraceElement[] ste = new StackTraceElement[0]; - setStackTrace(ste); - } - - /** - * @param cause - */ - public ResultNotProvidedException(Throwable cause) { - super(_bugmsg + cause.toString()); - } - - /** - * @param message - * @param cause - */ - public ResultNotProvidedException(String message, Throwable cause) { - super(_bugmsg + message/* +cause.toString() */); - } -} diff --git a/othersrc/OTRE/src/org/objectteams/RoleCastException.java b/othersrc/OTRE/src/org/objectteams/RoleCastException.java deleted file mode 100644 index f6608c944..000000000 --- a/othersrc/OTRE/src/org/objectteams/RoleCastException.java +++ /dev/null @@ -1,39 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2004-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: RoleCastException.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.objectteams; - -/** - * This exception is thrown if a cast to a role class fails due to - * different enclosing team instances. - * @author Stephan Herrmann - */ -public class RoleCastException extends ClassCastException { - - /** - * - */ - private static final long serialVersionUID = 1L; - private static final String MSG = - "Different enclosing team instances (see OT/J language definition para. 1.2.4(b))."; - - /* (non-Javadoc) - * @see java.lang.Throwable#getMessage() - */ - public String getMessage() { - return MSG; - } -}
\ No newline at end of file diff --git a/othersrc/OTRE/src/org/objectteams/Team.java b/othersrc/OTRE/src/org/objectteams/Team.java deleted file mode 100644 index 5feaccacf..000000000 --- a/othersrc/OTRE/src/org/objectteams/Team.java +++ /dev/null @@ -1,520 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2002-2007 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: Team.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.objectteams; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.HashSet; -import java.util.Iterator; -import java.util.WeakHashMap; - -/** - * This is the root class of all team definitions. - * Any class with the <tt>team</tt> modifier implicitly - * inherits from this class. - * - */ -public /* team */ class Team implements ITeam { - // Technical note: comments starting with //$Debug are intended - // for a standalone tool that generates an interface - // which the debugger needs in order to know about line numbers in this class. - - /* - * Synchronization: This class supports two levels of synchronization: - * <ul> - * <li>Fields of <code>Team</code> are synchronized - * using <code>this</code> as the monitor. - * <li>Those calls that (un)register a team at its base classes are synchronized - * via <code>registrationLock</code> - * </ul> - * This allows releasing the lock on <code>this</code> before calling to the base class. - * Note, that the synchronized portion of each initial-wrapper is also synchronized - * (against <code>_OT$addTeam/_OT$removeTeam</code>) and that it calls back to - * the registered teams (method <code>isActive()</code>). - * Without <code>registrationLock</code> this situation could easily deadlock: - * Thread1: <pre>t.activate() -> Base._OT$addTeam()</pre>: owns t, waits for Base. - * Thread2: <pre>b.bm() (initial wrapper) -> t.isActive()</pre>: owns Base, waits for t. - */ - - /** - * Internal field used by the runtime to install a lifting participant if one is configured. - */ - public static ILiftingParticipant _OT$liftingParticipant = null; - - /** - * Default constructor for debugging purpose. - */ - public Team() {} //$Debug(TeamConstructor) - - /* - * manual copy-inheritance of a role interface from ITeam. - */ - public interface ILowerable extends ITeam.ILowerable {} - - /* - * manual copy-inheritance of a role interface from ITeam. - */ - public interface IConfined extends ITeam.IConfined {} - - /** - * Special role type that<ul> - * <li> does not extend java.lang.Object - * <li> may not leak references outside the team. - * </ul> - */ - protected interface Confined { - /* internal method needed for cast and instanceof - * (this method will be generated for role classes) */ - ITeam _OT$getTeam(); - } - - /** - * This class would have been generated by the OT-compiler. - * Don't explicitly use it in client code! - */ - protected class __OT__Confined implements Confined { - // internal method needed for cast and instanceof - public ITeam _OT$getTeam() { - return Team.this; //$Debug(ConfinedGetTeam) - } - } - - /** - * Internal function for identifying a Team. - * Should not be called by client code. - */ - public int _OT$getID () {return -1;} - - /** - * The constant <code>ALL_THREADS</code> is used for global team (de-)activation. - */ - public static final Thread ALL_THREADS = new Thread(); - - private static final int _OT$UNREGISTERED = 0; - private static final int _OT$REGISTERED = 1; - private int _OT$registrationState = _OT$UNREGISTERED; - - private boolean _OT$globalActive = false; - - private ThreadLocal<Integer> _OT$implicitActivationsPerThread = new ThreadLocal<Integer>() { - protected synchronized Integer initialValue() { - return Integer.valueOf(0); - } - }; - - private boolean _OT$lazyGlobalActiveFlag = false; - - /** - * <code>_OT$activatedThreads</code> contains all threads for which this team instance is active. - * key = activated thread - * value = Boolean(true) for explicit activation | Boolean(false) for implicit activation. - */ - private WeakHashMap<Thread, Boolean> _OT$activatedThreads = new WeakHashMap<Thread, Boolean>(); - - /** This lock is used to protect activate/deactivate methods <strong>including</strong> - * the calls to doRegistration/doUnregistration. - */ - private Object _OT$registrationLock= new Object(); - - /** - * {@inheritDoc} - */ - public void activate() { - activate(Thread.currentThread()); - } - - /** - * {@inheritDoc} - */ - public void deactivate() { - deactivate(Thread.currentThread()); - } - - /** - * {@inheritDoc} - */ - public void activate(Thread thread) { - // acquire both locks to avoid incomplete execution: - synchronized (this._OT$registrationLock) { - synchronized (this) { - if (thread.equals(ALL_THREADS)) { - _OT$globalActive = true; - _OT$lazyGlobalActiveFlag = true; - TeamThreadManager.addGlobalActiveTeam(this); - } else { // activation only for 'thread': - // register 'thread' as active: - _OT$activatedThreads.put(thread, Boolean.TRUE); - } - } // release this before calling synchronized base class methods - doRegistration(); //$Debug(ActivateMethod) - } - } - - /** - * {@inheritDoc} - */ - public void deactivate(Thread thread) { - // acquire both locks to avoid incomplete execution: - synchronized (this._OT$registrationLock) { - boolean shouldUnregister= false; - synchronized(this) { - if (thread.equals(ALL_THREADS)) { - _OT$globalActive = false; - TeamThreadManager.removeGlobalActiveTeam(this); - // unregister all threads: - _OT$activatedThreads.clear(); - shouldUnregister= true; - } else { // deactivation only for 'thread': - if (_OT$lazyGlobalActiveFlag) { - // be eager now: activate for all (other) threads: - _OT$activateForAllThreads(); - } - // deactivate for 'thread', no longer active: - _OT$activatedThreads.remove(thread); - if (!_OT$lazyGlobalActiveFlag && _OT$activatedThreads.isEmpty()) { - shouldUnregister= true; - } - } - _OT$lazyGlobalActiveFlag = false; - } // release this before calling synchronized base class methods - if (shouldUnregister) //$Debug(DeactivateMethod) - doUnregistration(); - } - } - - public void deactivateForEndedThread(Thread thread) { - synchronized (_OT$registrationLock) { - boolean shouldUnregister= false; - synchronized (this) { - _OT$activatedThreads.remove(thread); - if (!_OT$lazyGlobalActiveFlag && _OT$activatedThreads.isEmpty()) - shouldUnregister= true; - } - if (shouldUnregister) - doUnregistration(); - } - } - - private void _OT$activateForAllThreads() { - HashSet threads = TeamThreadManager.getExistingThreads(); - Iterator it = threads.iterator(); - while (it.hasNext()) { - Thread a_thread = (Thread) it.next(); - activate(a_thread); // use smaller activate version (no ALL_THREADS, no registerAtBases,... - } - } - - /** - * This method is used for implicit activation in team-level methods. - * Implicit activation only applies to the current thread. - * Don't call it from client code. - */ - public void _OT$implicitlyActivate() { - synchronized (this._OT$registrationLock) { - boolean shouldRegister= false; - synchronized (this) { - // this method is used for debugging purpose (team monitor) - Thread currentThread = Thread.currentThread(); - if (!_OT$activatedThreads.containsKey(currentThread)) { - // register 'thread' as active: - _OT$activatedThreads.put(currentThread, Boolean.FALSE); - shouldRegister= true; - } - // increment thread local implicit activaion counter: - int implActCount = (_OT$implicitActivationsPerThread.get()).intValue(); - _OT$implicitActivationsPerThread.set(Integer.valueOf(implActCount + 1 )); - } - if (shouldRegister) //$Debug(ImplicitActivateMethod) - doRegistration(); - } - } - - /** - * This method is used for implicitly deactivation in team-level methods. - * It respects explicit activation changes and nested calls to team-level methods. - * Implicit deactivation only applies to the current thread. - * Don't call it from client code. - */ - public void _OT$implicitlyDeactivate() { - synchronized (this._OT$registrationLock) { - boolean shouldUnregister= false; - synchronized(this) { - // this method is used for debugging purpose (team monitor) - Thread currentThread = Thread.currentThread(); - boolean explicitlyActivated = false; - if (_OT$activatedThreads.containsKey(currentThread)) { - explicitlyActivated = ((Boolean) _OT$activatedThreads.get(currentThread)).booleanValue(); - } - if (!explicitlyActivated - && !_OT$lazyGlobalActiveFlag // no explicit activation overriding the implicit one - && ((_OT$implicitActivationsPerThread.get()).intValue() == 1)) // this is the last implicit activation - { - _OT$activatedThreads.remove(currentThread); - if (_OT$activatedThreads.isEmpty()) // there are not other threads for which this theam is active - { - shouldUnregister= true; - } - } - // decrement thread local implicit activaion counter: - int implActCount = (_OT$implicitActivationsPerThread.get()).intValue(); - _OT$implicitActivationsPerThread.set(Integer.valueOf(implActCount - 1)); - } - if (shouldUnregister) //$Debug(ImplicitDeactivateMethod) - doUnregistration(); - } - } - - /** - * Define whether per-thread activation of this team should be inheritable - * such that the team will be activated automatically for any new threads - * that are spawned from a thread for which the team is already active at that time. - * - * @param inheritable whether or not activation should be inheritable to new threads - */ - public void setInheritableActivation(boolean inheritable) { - if (inheritable) - TeamThreadManager.registerTeamForActivationInheritance(this); - else - TeamThreadManager.unRegisterTeamForActivationInheritance(this); - } - - // not API (for use by the TeamThreadManager) - public boolean internalIsActiveSpecificallyFor(Thread t) { - return this._OT$activatedThreads.containsKey(t); - } - - /** - * {@inheritDoc} - */ - public boolean isActive() { - return isActive(Thread.currentThread()); - } - - /** - * {@inheritDoc} - */ - public boolean isActive(Thread thread) { - if (thread.equals(ALL_THREADS)) { - return _OT$globalActive; - } - if (_OT$lazyGlobalActiveFlag) { - return true; - } else { - //if (!TeamThreadManager.getExistingThreads().contains(thread)) { // this thread is already finished! - if (!thread.isAlive()) { // this thread is already finished! - throw new IllegalThreadStateException("Called 'isActive(...)' for a thread which is no longer running!"); - } - return _OT$activatedThreads.containsKey(thread); - } - } - -// ***** for restoring the activation state after a within block: ---->***** - private static final int _OT$INACTIVE = 0; - private static final int _OT$IMPLICIT_ACTIVE = 1; - private static final int _OT$EXPLICIT_ACTIVE = 2; - - /** - * {@inheritDoc} - */ - public synchronized int _OT$saveActivationState() { - int old_state = _OT$INACTIVE; - if (_OT$lazyGlobalActiveFlag) { - old_state = _OT$EXPLICIT_ACTIVE; - } else { - Thread current_thread = Thread.currentThread(); - if (_OT$activatedThreads.containsKey(current_thread)) { - old_state = _OT$IMPLICIT_ACTIVE; - if (((Boolean)_OT$activatedThreads.get(current_thread)).booleanValue()) { - old_state = _OT$EXPLICIT_ACTIVE; - } - } - } - return old_state; - } - - /** - * {@inheritDoc} - */ - public void _OT$restoreActivationState(int old_state) { - synchronized (_OT$registrationLock) { - if (old_state == _OT$INACTIVE) // team was inactive before: - deactivate(); - else { // team was active before: has to be reactivated: - boolean explicit = (old_state == _OT$EXPLICIT_ACTIVE); - synchronized (this) { - _OT$activatedThreads.put(Thread.currentThread(), Boolean.valueOf(explicit)); - } - doRegistration(); - } - } - } -// ***** <----for restoring the activation state after a within block. ***** - - - private void doRegistration() { - if (_OT$registrationState == _OT$UNREGISTERED) { - _OT$registerAtBases(); - _OT$registrationState = _OT$REGISTERED; - } - } - - private void doUnregistration() { - if (_OT$registrationState == _OT$REGISTERED) { - _OT$unregisterFromBases(); - _OT$registrationState = _OT$UNREGISTERED; - } - } - - /** - * This method will be implemented by generated code in subteams. - * It registers the team at every base playing one of its roles. - * Don't call it from client code. - */ - public void _OT$registerAtBases() {} - - /** - * This method will be implemented by generated code in subteams. - * It unregisters the team from every base playing one of its roles. - * Don't call it from client code. - */ - public void _OT$unregisterFromBases() {} - - //public int _OT$activationState = -1; // TODO: remove usage of this from generated code - - - /** - * {@inheritDoc} - */ - public boolean hasRole(Object aBase) { - // overriding method to be generated by the compiler for each team with bound roles. - return false; - } - - /** - * {@inheritDoc} - */ - public boolean hasRole(Object aBase, Class<?> roleType) 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. */ } -} diff --git a/othersrc/OTRE/src/org/objectteams/TeamThreadManager.java b/othersrc/OTRE/src/org/objectteams/TeamThreadManager.java deleted file mode 100644 index debccb712..000000000 --- a/othersrc/OTRE/src/org/objectteams/TeamThreadManager.java +++ /dev/null @@ -1,121 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2006-2008 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: TeamThreadManager.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.objectteams; - -import java.util.HashSet; -import java.util.WeakHashMap; - - -/** - * This class is for internal use, only. - * - * Maintain information about existing threads as to manage - * team activation per thread vs. globally. - * - * @author Chistine Hundt - * @author Stephan Herrmann - */ -public class TeamThreadManager { - - private static Object token = new Object(); - - private static HashSet<ITeam> globalActiveTeams = new HashSet<ITeam>(); - private static WeakHashMap<ITeam,Object> teamsWithActivationInheritance = new WeakHashMap<ITeam,Object>(); - private static HashSet<Thread> existingThreads = new HashSet<Thread>(); - - public static boolean newThreadStarted(boolean isMain, Thread parent) { - Thread currentThread = Thread.currentThread(); - // already registered? - if (existingThreads.contains(currentThread)) - return false; - // workaround for application hang on Mac OS with Apple JVM: - if (System.getProperty("os.name").startsWith("Mac")) - if (currentThread.getName().equals("AWT-Shutdown")) - return false; - - ITeam[] globalTeams; - ITeam[] inheritableTeams; - synchronized (TeamThreadManager.class) { - existingThreads.add(currentThread); - if (isMain) { - for (Thread thread : fetchSystemThreads(currentThread)) - if (thread != null) - existingThreads.add(thread); - } - - globalTeams = globalActiveTeams.toArray(new ITeam[globalActiveTeams.size()]); - inheritableTeams = teamsWithActivationInheritance.keySet().toArray(new ITeam[teamsWithActivationInheritance.size()]); - } - // activate teams outside synchronized block: - for (ITeam t : globalTeams) - t.activate(currentThread); // small version? global -> already registered...! - if (parent != null) - for (ITeam t : inheritableTeams) - if (t.internalIsActiveSpecificallyFor(parent)) - t.activate(currentThread); // pass activation from parent to child thread - return true; - } - - /* Fetch all existing threads existing at this point in time. Result array is padded with nulls. */ - private static Thread[] fetchSystemThreads(Thread currentThread) { - ThreadGroup group = currentThread.getThreadGroup(); - { - ThreadGroup parentGroup; - while ((parentGroup= group.getParent()) != null) - group = parentGroup; - } - int size = group.activeCount(); - Thread[] allThreads; - do { - size += 2; - allThreads = new Thread[size]; - } while (group.enumerate(allThreads) == size); - return allThreads; - } - - public static void threadEnded() { - ITeam[] teamsToDeactivate = internalThreadEnded(); - // + remove per thread activation: - for (ITeam t : teamsToDeactivate) - //t.deactivate(Thread.currentThread()); // small version? - t.deactivateForEndedThread(Thread.currentThread()); - } - private synchronized static ITeam[] internalThreadEnded() { - existingThreads.remove(Thread.currentThread()); - // fetch all global active teams for deactivation: - return globalActiveTeams.toArray(new ITeam[globalActiveTeams.size()]); - } - - public synchronized static void addGlobalActiveTeam(ITeam t) { - globalActiveTeams.add(t); - } - - public synchronized static void removeGlobalActiveTeam(ITeam t) { - globalActiveTeams.remove(t); - } - - public static HashSet<Thread> getExistingThreads() { - return existingThreads; - } - public static void registerTeamForActivationInheritance(ITeam aTeam) { - teamsWithActivationInheritance.put(aTeam,token); - } - public static void unRegisterTeamForActivationInheritance(ITeam aTeam) { - teamsWithActivationInheritance.remove(aTeam); - } - -} diff --git a/othersrc/OTRE/src/org/objectteams/UnsupportedFeatureException.java b/othersrc/OTRE/src/org/objectteams/UnsupportedFeatureException.java deleted file mode 100644 index 9b1c1ffcf..000000000 --- a/othersrc/OTRE/src/org/objectteams/UnsupportedFeatureException.java +++ /dev/null @@ -1,60 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2004-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: UnsupportedFeatureException.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.objectteams; - -/** - * @author resix - */ -public class UnsupportedFeatureException extends RuntimeException { - - /** - * - */ - private static final long serialVersionUID = 1L; - private static final String _bugmsg = "\nThe program encountered an unsupported situation! "; - - /** - * - */ - public UnsupportedFeatureException() { - super(_bugmsg); - } - - /** - * @param message - */ - public UnsupportedFeatureException(String message) { - super(_bugmsg + "\n" + message); - StackTraceElement[] ste = new StackTraceElement[0]; - setStackTrace(ste); - } - - /** - * @param cause - */ - public UnsupportedFeatureException(Throwable cause) { - super(_bugmsg + cause.toString()); - } - - /** - * @param message - * @param cause - */ - public UnsupportedFeatureException(String message, Throwable cause) { - super(_bugmsg + message/*+cause.toString()*/); - } -} diff --git a/othersrc/OTRE/src/org/objectteams/WrongRoleException.java b/othersrc/OTRE/src/org/objectteams/WrongRoleException.java deleted file mode 100644 index ed76541e3..000000000 --- a/othersrc/OTRE/src/org/objectteams/WrongRoleException.java +++ /dev/null @@ -1,57 +0,0 @@ -/********************************************************************** - * This file is part of the "Object Teams Runtime Environment" - * - * Copyright 2003-2009 Berlin Institute of Technology, Germany. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * $Id: WrongRoleException.java 23408 2010-02-03 18:07:35Z stephan $ - * - * Please visit http://www.objectteams.org for updates and contact. - * - * Contributors: - * Berlin Institute of Technology - Initial API and implementation - **********************************************************************/ -package org.objectteams; - -/** - * This exception is thrown by the OT/J infra structure if a role for a given base object - * was requested during lifting, but a role with an incompatible type was already - * registered for that base object. Can only happen if a compile time warning occurred. - * @author Stephan Herrmann - */ -public class WrongRoleException extends RuntimeException { - /** - * - */ - private static final long serialVersionUID = 1L; - private Class<?> clazz; - private Object base; - private Object role; - - /** - * @param clazz - * @param base - * @param role - */ - public WrongRoleException (Class<?> clazz, Object base, Object role) { - this.clazz = clazz; - this.base = base; - this.role = role; - } - - public String getMessage() { - String baseClazz = base.getClass().getName(); - String roleClazz = role.getClass().getName(); - return "The compiler has warned you about ambiguous role bindings.\n" - + "Now lifting to " + clazz - + " fails with the following objects\n" - + "(see OT/J language definition para. 2.3.4(d)):\n" - + "Provided:\n Base object: " + base + "\n" + " Base type: " - + baseClazz + "\n" - + "Found in cache:\n Role object: " + role + "\n" - + " Role type: " + roleClazz; - } -} |