Bug 498925: NullPointerException in Config.delegateGetMethodBodies
- more bugfixes 
- redesign using t-w-r
- some clean-up
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/EnclosingMethodAttributeTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/EnclosingMethodAttributeTest.java
index 9c98cd4..d867707 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/EnclosingMethodAttributeTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/EnclosingMethodAttributeTest.java
@@ -22,6 +22,7 @@
 import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.objectteams.otdt.internal.core.compiler.control.Config;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.Dependencies;
 
 @SuppressWarnings({ "rawtypes" })
@@ -253,14 +254,12 @@
 				requestor,
 				getProblemFactory());
 //{ObjectTeams: avoid exceptions:
-	  Dependencies.setup(batchCompiler, batchCompiler.parser, batchCompiler.lookupEnvironment, true, false);
-	  try {
+	  try (Config config = Dependencies.setup(batchCompiler, batchCompiler.parser, batchCompiler.lookupEnvironment, true, false))
+	  {
 // orig:
 		ReferenceBinding binaryType = batchCompiler.lookupEnvironment.askForType(new char[][] {new char[0], "X$1".toCharArray()});
 		assertNotNull("Should not be null", binaryType);
 // :giro		
-	  } finally {
-		  Dependencies.release(batchCompiler);
 	  }
 // SH}
 	}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
index edc8b2f..1ec71a7 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
@@ -221,6 +221,7 @@
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CallinMappingDeclaration;
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CalloutMappingDeclaration;
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.MethodSpec;
+import org.eclipse.objectteams.otdt.internal.core.compiler.control.Config;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.Dependencies;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.ITranslationStates;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.StateHelper;
@@ -2036,8 +2037,8 @@
 						ImportReference importReference = imports[i];
 						if (importReference instanceof CompletionOnImportReference) {
 //{ObjectTeams: guard with setup/release, rely on Dependencies instead of manually invoking three steps:
-  						  try {
-							Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true);
+  						  try (Config config = Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true))
+  						  {
 // km(merge) }
 							this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
 							if ((this.unitScope = parsedUnit.scope) != null) {
@@ -2088,8 +2089,6 @@
 								}
 							}
 //{ObjectTeams:
-						  } finally {
-							Dependencies.release(this);
 						  }
 // km(merge) }
 							return;
@@ -2114,11 +2113,14 @@
 
 				if (parsedUnit.types != null) {
 //{ObjectTeams: guard this block by setup/release:
-					Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true);
+/* orig:
+					try {
+  :giro */
+					try (Config config = Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true))
+					{
 					// statements are explicitly requested for the completion position, other statements are not needed
 // orig:
 
-					try {
 						this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
 
 						if ((this.unitScope = parsedUnit.scope) != null) {
@@ -2174,11 +2176,6 @@
 									e.insideTypeAnnotation);
 						}
 					}
-//{ObjectTeams:
-				  finally {
-					Dependencies.release(this);
-				  }
-//SH}
 				}
 			}
 
@@ -2300,9 +2297,12 @@
 				}
 
 				if (compilationUnit.types != null) {
-					try {
 	//{ObjectTeams: guard with setup/release, rely on Dependencies instead of manually invoking three steps:
-							Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true);
+	/* orig:
+					try {
+	  :giro */
+					try (Config config = Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true))
+					{
 	//orig:
 						this.lookupEnvironment.buildTypeBindings(compilationUnit, null /*no access restriction*/);
 
@@ -2332,11 +2332,6 @@
 									e.insideTypeAnnotation);
 						}
 					}
-	//{ObjectTeams: moved here
-						finally {
-							Dependencies.release(this);
-						}
-	//km}
 				}
 				if(this.noProposal && this.problem != null) {
 					if(!contextAccepted) {
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/InternalExtendedCompletionContext.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/InternalExtendedCompletionContext.java
index a33d57e..671f494 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/InternalExtendedCompletionContext.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/InternalExtendedCompletionContext.java
@@ -340,10 +340,12 @@
 		CompilationUnitDeclaration previousUnitBeingCompleted = this.lookupEnvironment.unitBeingCompleted;
 		this.lookupEnvironment.unitBeingCompleted = this.compilationUnitDeclaration;
 //{ObjectTeams: protect call into the compiler
-		boolean useOwnConfig = !Config.hasConfig();
-		if (useOwnConfig) Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true);
-// orig:
+/* orig:
 		try {
+  :giro */
+		try (Config config = Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true))
+		{
+// orig:
 
 			SignatureWrapper wrapper = new SignatureWrapper(replacePackagesDot(typeSignature.toCharArray()));
 			// FIXME(stephan): do we interpret type annotations here?
@@ -353,9 +355,6 @@
 			assignableTypeBinding = null;
 		} finally {
 			this.lookupEnvironment.unitBeingCompleted = previousUnitBeingCompleted;
-// :giro
-			if (useOwnConfig) Dependencies.release(this);
-// SH}
 		}
 		return assignableTypeBinding;
 	}
@@ -381,10 +380,8 @@
 
 	public IJavaElement[] getVisibleElements(String typeSignature) {
 //{ObjectTeams: might call into the compiler (e.g., isCompatibleWith), so give at least minimal protection:
-	  boolean useOwnConfig = !Config.hasConfig();
-	  try {
-		if (useOwnConfig)
-			Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true);
+	  try (Config config = Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true))
+	  {
 // SH}
 		if (this.assistScope == null) return new IJavaElement[0];
 
@@ -466,9 +463,6 @@
 
 		return result;
 //{ObjectTeams: cleanup:
-	  } finally {
-		  if (useOwnConfig)
-			  Dependencies.release(this);
 	  }
 // SH}
 	}
@@ -940,10 +934,8 @@
 			ref = new QualifiedTypeReference(cn,new long[cn.length]);
 		}
 //{ObjectTeams: protect call into the compiler
-	  boolean useOwnConfig = !Config.hasConfig();
-	  try {
-		if (useOwnConfig)
-			Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true);
+	  try (Config config = Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true))
+	  {
 //orig:
 		switch (scope.kind) {
 			case Scope.METHOD_SCOPE :
@@ -955,9 +947,6 @@
 				break;
 		}
 // :giro
-	  } finally {
-		if (useOwnConfig)
-			Dependencies.release(this);
 	  }
 // SH}
 		if (guessedType != null && guessedType.isValidBinding()) {
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java
index 83777f1..6aa7dea 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java
@@ -115,6 +115,7 @@
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.AbstractMethodMappingDeclaration;
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.MethodSpec;
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.ParameterMapping;
+import org.eclipse.objectteams.otdt.internal.core.compiler.control.Config;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.Dependencies;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.ITranslationStates;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.StateHelper;
@@ -981,16 +982,19 @@
 		if (!checkSelection(source, selectionSourceStart, selectionSourceEnd)) {
 			return;
 		}
-//{ObjectTeams
-		Dependencies.setup(this, this.parser, this.lookupEnvironment, true, false);
-		// is "no strictDiet" correct here (SH)? see dietParse below.
-//SH}
 		if (DEBUG) {
 			System.out.print("SELECTION - Checked : \""); //$NON-NLS-1$
 			System.out.print(new String(source, this.actualSelectionStart, this.actualSelectionEnd-this.actualSelectionStart+1));
 			System.out.println('"');
 		}
+//{ObjectTeams
+/* orig:
 		try {
+  :giro */
+		try (Config config = Dependencies.setup(this, this.parser, this.lookupEnvironment, true, false))
+		{
+			// is "no strictDiet" correct here (SH)? see dietParse below.
+//SH}
 			this.acceptedAnswer = false;
 			CompilationResult result = new CompilationResult(sourceUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
 			CompilationUnitDeclaration parsedUnit =
@@ -1195,9 +1199,6 @@
 			Util.log(ex);
 //haebor}
 		} finally {
-//{ObjectTeams
-			Dependencies.release(this);
-// SH}
 			reset(true);
 		}
 	}
@@ -1766,9 +1767,9 @@
 				typeDeclaration.fields = new FieldDeclaration[] { field };
 
 //{ObjectTeams: rely on Dependencies for intermediate steps:
-				Dependencies.setup(this, this.parser, this.lookupEnvironment, true, false);
+			  try (Config config = Dependencies.setup(this, this.parser, this.lookupEnvironment, true, false))
 				// is no strictDiet correct here (SH)?
-			  try {
+			  {
 // orig:
 				// build bindings
 				this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
@@ -1799,9 +1800,6 @@
 				}
 //{ObjectTeams:
 			  }
-			  finally {
-			    Dependencies.release(this);
-			  }
 // SH}
 			}
 			if(this.noProposal && this.problem != null) {
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Engine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Engine.java
index a19d3ca..187dabd 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Engine.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Engine.java
@@ -36,6 +36,8 @@
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CallinMappingDeclaration;
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CalloutMappingDeclaration;
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.ParameterMapping;
+import org.eclipse.objectteams.otdt.internal.core.compiler.control.Config;
+import org.eclipse.objectteams.otdt.internal.core.compiler.control.Dependencies;
 
 public abstract class Engine implements ITypeRequestor {
 
@@ -95,6 +97,10 @@
 	 * secondary types defined in the same compilation unit).
 	 */
 	public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, AccessRestriction accessRestriction) {
+//{ObjectTeams:
+	  try (Config config = Dependencies.setup(this, getParser(), this.lookupEnvironment, true, false))
+	  {
+// SH}
 		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=479656
 		// In case of the requested type not being a member type (i.e. not being a top level type)
 		// we need to find the top level ones and use them for resolution
@@ -138,6 +144,9 @@
 			this.lookupEnvironment.buildTypeBindings(unit, accessRestriction);
 			this.lookupEnvironment.completeTypeBindings(unit, true);
 		}
+//{ObjectTeams: cleanup:
+	  }
+// SH}
 	}
 
 	public abstract AssistParser getParser();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
index 2863b92..30f810a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
@@ -489,13 +489,16 @@
 	 */
 	private void compile(ICompilationUnit[] sourceUnits, boolean lastRound) {
 		this.stats.startTime = System.currentTimeMillis();
+//{ObjectTeams:
+/* orig:
 		try {
+  :giro */
+		try (Config config = Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true, false))
+		{
+//carp}
 			// build and record parsed units
 			reportProgress(Messages.compilation_beginningToCompile);
 
-//{ObjectTeams:
-			Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true, false);
-//carp}
 			if (this.annotationProcessorManager == null) {
 				beginToCompile(sourceUnits);
 			} else {
@@ -1075,9 +1078,6 @@
 		this.unitsToProcess = null;
 		if (DebugRequestor != null) DebugRequestor.reset();
 		this.problemReporter.reset();
-//{ObjectTeams: free some references to enable garbage collection
-		Dependencies.release(this);
-// carp}
 	}
 
 	/**
@@ -1090,9 +1090,12 @@
 			boolean analyzeCode,
 			boolean generateCode) {
 
-		try {
 //{ObjectTeams:
-	        setupDependencies(verifyMethods, analyzeCode, generateCode);
+/* orig:
+		try {
+  :giro */
+	    try (Config config = setupDependencies(verifyMethods, analyzeCode, generateCode))
+	    {
 //SH}
 			if (unit == null) {
 				// build and record parsed units
@@ -1166,9 +1169,6 @@
 			this.handleInternalException(e, unit, null);
 			throw e; // rethrow
 		} finally {
-//{ObjectTeams:
-			Dependencies.release(this);
-// SH}
 			// leave this.lookupEnvironment.unitBeingCompleted set to the unit, until another unit is resolved
 			// other calls to dom can cause classpath errors to be detected, resulting in AbortCompilation exceptions
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
index 5d9ecc0..e11c267 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
@@ -905,20 +905,13 @@
 // NOT Public API
 public final Binding getImport(char[][] compoundName, boolean onDemand, boolean isStaticImport) {
 //{ObjectTeams: this method may be called in a Config-unaware context:
-  boolean createdConfig = false;
-  if (!Config.hasLookupEnvironment()) {
-	  createdConfig = true;
-	  Dependencies.setup(this, this.parser, environment(), false, true);
-  }
-  try {
-//SH}
+  try (Config config = Dependencies.setup(this, this.parser, environment(), false, true))
+  {
+// orig:
 	if (onDemand)
 		return findImport(compoundName, compoundName.length);
 	return findSingleImport(compoundName, Binding.TYPE | Binding.FIELD | Binding.METHOD, isStaticImport);
-//{ObjectTeams: cleanup:
-  } finally {
-	  if (createdConfig)
-		  Dependencies.release(this);
+// :giro
   }
 //SH}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
index 503776a..038bc89 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
@@ -3733,12 +3733,8 @@
 	// use CompilationUnitScope.getImport(char[][]) instead
 	public final Binding getTypeOrPackage(char[][] compoundName) {
 //{ObjectTeams: this method may be called in a Config-unaware context:
-	  boolean createdConfig = false;
-	  if (!Config.hasLookupEnvironment()) {
-		  createdConfig = true;
-		  Dependencies.setup(this, compilationUnitScope().parser, environment(), false, true);
-	  }
-	  try {
+	  try (Config config = Dependencies.setup(this, compilationUnitScope().parser, environment(), false, true))
+	  {
 // SH}
 		int nameLength = compoundName.length;
 		if (nameLength == 1) {
@@ -3800,9 +3796,6 @@
 		}
 		return qualifiedType;
 //{ObjectTeams: cleanup:
-	  } finally {
-		  if (createdConfig)
-			  Dependencies.release(this);
 	  }
 // SH}
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/core/compiler/ConfigHelper.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/core/compiler/ConfigHelper.java
index fccea6f..bfb8d97 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/core/compiler/ConfigHelper.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/core/compiler/ConfigHelper.java
@@ -29,14 +29,31 @@
 public class ConfigHelper {
 
 	/**
+	 * A resources that doesn't throw on {@link #close()}
+	 * @since 3.13 (OTDT 2.6)
+	 */
+	public interface IConfig extends AutoCloseable {
+		void close();
+	}
+
+	/**
+	 * @deprecated use {@link #checkCreateStubConfig2(Object)}
+	 */
+	@Deprecated
+	public static boolean checkCreateStubConfig(Object client) {
+		return checkCreateStubConfig2(client) != null;
+	}
+
+	/**
 	 * When no config has been prepared, create a stub config, which can
 	 * handle all boolean queries but throws InternalCompilerError when
 	 * attempting to access the lookupEnvironment or the parser.
+	 * @since 3.13 (OTDT 2.6)
 	 */
-	public static boolean checkCreateStubConfig(Object client) {
-		if (Config.hasConfig())
-			return false; // no need to create a stub.
-		Config newConfig = new Config() {
+	public static IConfig checkCreateStubConfig2(Object client) {
+		if (Config.hasConfig(client))
+			return null; // no need to create a stub.
+		Config newConfig = new Config(client, null, null) {
 			@Override
 			protected LookupEnvironment lookupEnvironment() {
 				throw new InternalCompilerError("Lookup Environment not configured"); //$NON-NLS-1$
@@ -47,13 +64,15 @@
 			}
 		};
 		Config.addConfig(newConfig);
-		return true;
+		return newConfig;
 	}
 
 	/**
 	 * Remove the config that has been registered for 'client'
 	 * @param client
+	 * @deprecated please use try-with-resources instead of manual removal of Configs
 	 */
+	@Deprecated
 	public static void removeConfig(Object client) {
 		Config.removeConfig(client);
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/control/Config.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/control/Config.java
index e62e9d6..6d12aef 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/control/Config.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/control/Config.java
@@ -36,6 +36,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
 import org.eclipse.jdt.internal.compiler.parser.Parser;
 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.objectteams.otdt.core.compiler.ConfigHelper;
 import org.eclipse.objectteams.otdt.core.exceptions.InternalCompilerError;
 
 
@@ -47,7 +48,7 @@
  *
  * We don't use ThreadLocal, since we do cleanup manually using release().
  */
-public class Config {
+public class Config implements ConfigHelper.IConfig {
 	
 	@SuppressWarnings("serial")
 	public static class NotConfiguredException extends RuntimeException {
@@ -64,10 +65,10 @@
 		}
 	}
 
-    WeakReference<Object> client;
-    Parser            parser;
-    Parser            plainParser; // alternate parser when client is a MatchLocator
-    LookupEnvironment lookupEnvironment;
+    WeakReference<Object> 	client;
+    public Parser         	parser;
+    Parser            		plainParser; // alternate parser when client is a MatchLocator
+    LookupEnvironment 		lookupEnvironment;
     public boolean verifyMethods;
     boolean analyzeCode;
     boolean generateCode;
@@ -120,6 +121,12 @@
 
 	static final WeakHashMap<Object, Config> configsByClient = new WeakHashMap<>();
 
+	public Config(Object client, Parser parser, LookupEnvironment environment) {
+		this.client = new WeakReference<>(client);
+		this.parser = parser;
+		this.lookupEnvironment = environment;
+	}
+
 	public static void addConfig(Config config)
 	{
 	    synchronized (_configs) {
@@ -138,8 +145,6 @@
 
 	        configStack.push(config);
 	    }
-	    if (config.client != null && config.client.get() != null)
-	    	configsByClient.put(config.client.get(), config);
 	}
 
 	/**
@@ -162,14 +167,13 @@
 		        configStack = new Stack<Config>();
 		        _configs.set(configStack);
 
-		        Config config = new Config();
-		    	config.client = new WeakReference<>(client);
+		        Config config = new Config(client, null, null);
 		    	configStack.push(config);
 		    	return null; // no old config
 		    } else {
 		        assert(!configStack.empty());
 		        Config existing = configStack.peek();
-		    	Config clone = new Config();
+		    	Config clone = new Config(client, existing.parser, existing.lookupEnvironment);
 		    	clone.castRequired = existing.castRequired;
 		    	clone.loweringRequired = existing.loweringRequired;
 		    	clone.loweringPossible = existing.loweringPossible;
@@ -229,7 +233,7 @@
 	public static Config getConfig() {
 		return getConfig(true);
 	}
-	public static Config getConfig(boolean logError)
+	private static Config getConfig(boolean logError)
 	{
 		if (_configs == null) {
 			InternalCompilerError.log("Dependencies has no _configs"); //$NON-NLS-1$
@@ -246,7 +250,7 @@
     	}
 	}
 	/** get the current config or null if not configured. */
-	public static Config safeGetConfig() {
+	private static Config safeGetConfig() {
 		if (_configs == null)
 			return null;
     	synchronized (_configs) {
@@ -262,28 +266,70 @@
 		if (_configs == null)
 			return false;
 	    synchronized(_configs) {
-	        return _configs.get() != null;
+	        Stack<Config> configStack = _configs.get();
+	        if (configStack == null)
+	        	return false;
+	        return !configStack.isEmpty();
 	    }
 	}
 
-	public static void addToThread(Config config) {
-		if (_configs == null) {
-			InternalCompilerError.log("Dependencies has no _configs"); //$NON-NLS-1$
-			return;
+	public static boolean hasConfig(Object client) {
+		Config config = safeGetConfig();
+		if (config == null)
+			return false;
+		return config.client.get() == client;
+	}
+	
+	static Config getOrCreateMatchingConfig(Object client, Parser parser, LookupEnvironment environment) {
+		Config config = safeGetConfig();
+		if (configMatchesRequest(config, client, parser, environment)) {
+			parser = config.parser;
+			environment = config.lookupEnvironment;
 		}
-    	synchronized (_configs) {
-    	    Stack<Config> configStack = _configs.get();
-			if (configStack != null) {
-				if (!configStack.isEmpty() && configStack.peek() == config)
-					return;
-			} else {
-				configStack = new Stack<>();
-				_configs.set(configStack);
+		if (parser == null || environment == null) {
+			config = configsByClient.get(client);
+			if (configMatchesRequest(config, client, parser, environment)) {
+				parser = config.parser;
+				environment = config.lookupEnvironment;
 			}
-			configStack.add(config);
-    	}
+		}
+		config = new Config(client, parser, environment);
+		configsByClient.put(client, config);
+		addConfig(config);
+		return config;
 	}
 
+	private static boolean configMatchesRequest(Config config, Object client, Parser parser,
+			LookupEnvironment environment) {
+		if (config == null)
+			return false;
+		if (config.client.get() != client)
+			return false;
+		if (config.parser != parser && parser != null)
+			return false;
+		if (config.lookupEnvironment != environment && environment != null)
+			return false;
+		return true;
+	}
+
+	@Override
+	public void close() {
+    	synchronized (_configs) {
+    	    Stack<Config> configStack = _configs.get();
+    	    assert(configStack != null);
+    	    if (configStack != null)
+    	    {
+    	        Config config = configStack.pop(); // remove Config
+    		    assert(config != null);
+    	        if (config != this) // bad balance of addConfig and removeConfig calls
+    	        {
+    	            assert(false);
+    	            configStack.push(config); // be defensive, put it back
+    	        }
+    	    }
+		}
+	}
+	
 	static boolean getVerifyMethods() {
 		return getConfig().verifyMethods;
 	}
@@ -379,7 +425,7 @@
 		synchronized(_configs) {
 			if (!hasConfig())
 				return false;
-			Config config = getConfig();
+			Config config = getConfig(false);
 			return (config != null) && (config.lookupEnvironment != null);
 		}
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/control/Dependencies.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/control/Dependencies.java
index 082a4bb..8a6fefb 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/control/Dependencies.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/control/Dependencies.java
@@ -20,7 +20,6 @@
 package org.eclipse.objectteams.otdt.internal.core.compiler.control;
 
 
-import java.lang.ref.WeakReference;
 import java.util.Iterator;
 
 import org.eclipse.jdt.internal.compiler.Compiler;
@@ -110,7 +109,7 @@
      * Configure the Dependencies module for use by a specific client.
 	 * @param client  the object invoking setup
 	 * @param parser
-	 * @param lookupEnvironment
+	 * @param environment
 	 * @param verifyMethods
 	 * @param analyzeCode
 	 * @param generateCode
@@ -121,7 +120,7 @@
     public static Config setup(
     		Object            client,
 			Parser			  parser,
-			LookupEnvironment lookupEnvironment,
+			LookupEnvironment environment,
 			boolean	          verifyMethods,
 			boolean           analyzeCode,
 			boolean           generateCode,
@@ -129,15 +128,7 @@
 			boolean           bundledCompleteTypeBindings,
 			boolean           strictDiet)
     {
-    	Config config = Config.configsByClient.get(client);
-    	if (config != null && (config.parser != null || parser == null)) {
-    		Config.addToThread(config);
-			return config;
-		}
-    	config = new Config();
-    	config.client = new WeakReference<>(client);
-    	config.parser = parser;
-    	config.lookupEnvironment = lookupEnvironment;
+    	Config config = Config.getOrCreateMatchingConfig(client, parser, environment);
     	config.verifyMethods = verifyMethods;
     	config.analyzeCode = analyzeCode;
     	config.generateCode = generateCode;
@@ -149,7 +140,6 @@
 //    	config.ex = new Exception("Dependencies.setup()");
 //    	config.ex.getStackTrace();
 
-    	Config.addConfig(config);
     	return config;
     }
 
@@ -161,14 +151,14 @@
      * @param buildFieldsAndMethods should bindings for fields and methods be built?
      * @param strictDiet are statements ever parsed or are we on a strict diet?
      */
-    public static void setup(
+    public static Config setup(
     		Object            client,
 			Parser			  parser,
 			LookupEnvironment lookupEnvironment,
 			boolean           buildFieldsAndMethods,
 			boolean           strictDiet)
     {
-    	Dependencies.setup(client, parser, lookupEnvironment, true, true, true,
+    	return Dependencies.setup(client, parser, lookupEnvironment, true, true, true,
     			buildFieldsAndMethods, false, strictDiet);
     }
 
@@ -181,7 +171,7 @@
      * @param bundledCompleteTypeBindings should completeTypeBindings try to treat all units at once?
      * @param strictDiet are statements ever parsed or are we on a strict diet?
      */
-    public static void setup(
+    public static Config setup(
     		Object            client,
 			Parser			  parser,
 			LookupEnvironment lookupEnvironment,
@@ -189,20 +179,10 @@
 			boolean           bundledCompleteTypeBindings,
 			boolean           strictDiet)
     {
-    	Dependencies.setup(client, parser, lookupEnvironment, true, true, true,
+    	return Dependencies.setup(client, parser, lookupEnvironment, true, true, true,
     			buildFieldsAndMethods, bundledCompleteTypeBindings, strictDiet);
     }
 
-
-	/**
-     * Release Dependencies configuration from a specific client.
-	 * @param client ensure that client actually configured the
-	 *   module from the same thread as currently executing.
-	 */
-	public static void release(Object client) {
-	    Config.removeConfig(client);
-	}
-
 	public static boolean isSetup() {
 	    return Config.hasConfig();
 	}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java
index f1892db..6653512 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java
@@ -70,6 +70,7 @@
 import org.eclipse.jdt.internal.core.util.BindingKeyResolver;
 import org.eclipse.jdt.internal.core.util.CommentRecorderParser;
 import org.eclipse.jdt.internal.core.util.DOMFinder;
+import org.eclipse.objectteams.otdt.internal.core.compiler.control.Config;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.Dependencies;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.ITranslationStates;
 
@@ -861,15 +862,18 @@
 		astRequestor.compilationUnitResolver = this;
 		this.bindingTables = new DefaultBindingResolver.BindingTables();
 		CompilationUnitDeclaration unit = null;
+//{ObjectTeams:
+/* orig:
 		try {
+  :giro */
+		try (Config config = Dependencies.setup(this, this.parser, this.lookupEnvironment,
+				true/*verify*/, !this.options.ignoreMethodBodies/*analyze*/, !this.options.ignoreMethodBodies/*generate*/,
+				true, true, false))
+		{
+// SH+KM}
 			int length = compilationUnits.length;
 			org.eclipse.jdt.internal.compiler.env.ICompilationUnit[] sourceUnits = new org.eclipse.jdt.internal.compiler.env.ICompilationUnit[length];
 			System.arraycopy(compilationUnits, 0, sourceUnits, 0, length);
-//{ObjectTeams:
-			Dependencies.setup(this, this.parser, this.lookupEnvironment,
-								true/*verify*/, !this.options.ignoreMethodBodies/*analyze*/, !this.options.ignoreMethodBodies/*generate*/,
-								true, true, false);
-// SH+KM}
 
 			beginToCompile(sourceUnits, bindingKeys);
 			// process all units (some more could be injected in the loop by the lookup environment)
@@ -968,9 +972,6 @@
 		} finally {
 			// disconnect ourselves from ast requestor
 			astRequestor.compilationUnitResolver = null;
-//{ObjectTeams: restore:
-            Dependencies.release(this);
-// SH+KM}
 		}
 	}
 
@@ -987,7 +988,15 @@
 		astRequestor.compilationUnitResolver = this;
 		this.bindingTables = new DefaultBindingResolver.BindingTables();
 		CompilationUnitDeclaration unit = null;
+//{ObjectTeams:
+/* orig:
 		try {
+  :giro */
+		try (Config config = Dependencies.setup(this, this.parser, this.lookupEnvironment,
+							true/*verify*/, !this.options.ignoreMethodBodies/*analyze*/, !this.options.ignoreMethodBodies/*generate*/,
+							true, true, false))
+		{
+//SH}
 			int length = sourceCompilationUnits.length;
 			org.eclipse.jdt.internal.compiler.env.ICompilationUnit[] sourceUnits = new org.eclipse.jdt.internal.compiler.env.ICompilationUnit[length];
 			int count = 0;
@@ -1007,11 +1016,6 @@
 				}
 				sourceUnits[count++] = new org.eclipse.jdt.internal.compiler.batch.CompilationUnit(contents, sourceUnitPath, encoding);
 			}
-//{ObjectTeams:
-			Dependencies.setup(this, this.parser, this.lookupEnvironment,
-								true/*verify*/, !this.options.ignoreMethodBodies/*analyze*/, !this.options.ignoreMethodBodies/*generate*/,
-								true, true, false);
-// SH}
 			beginToCompile(sourceUnits, bindingKeys);
 			// process all units (some more could be injected in the loop by the lookup environment)
 			for (int i = 0; i < this.totalUnits; i++) {
@@ -1109,9 +1113,6 @@
 		} finally {
 			// disconnect ourselves from ast requestor
 			astRequestor.compilationUnitResolver = null;
-//{ObjectTeams: restore:
-            Dependencies.release(this);
-// SH}
 		}
 	}
 
@@ -1157,11 +1158,14 @@
 			boolean analyzeCode,
 			boolean generateCode) {
 
+//{ObjectTeams:
+/* orig:
 		try {
 
-//{ObjectTeams:
-			Dependencies.setup(this, this.parser, this.lookupEnvironment,
-					verifyMethods, analyzeCode, generateCode, true, true, false);
+  :giro */
+		try (Config config = Dependencies.setup(this, this.parser, this.lookupEnvironment,
+				verifyMethods, analyzeCode, generateCode, true, true, false))
+		{
 // SH}
 			if (unit == null) {
 				// build and record parsed units
@@ -1277,9 +1281,6 @@
 			this.handleInternalException(e, unit, null);
 			throw e; // rethrow
 		} finally {
-//{ObjectTeams:
-			Dependencies.release(this);
-// SH}
 			// No reset is performed there anymore since,
 			// within the CodeAssist (or related tools),
 			// the compiler may be called *after* a call
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
index 6cf13a0..c504d6d 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
@@ -80,6 +80,7 @@
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.LiftingTypeReference;
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.MethodSpec;
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.TSuperMessageSend;
+import org.eclipse.objectteams.otdt.internal.core.compiler.control.Config;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.Dependencies;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.CallinCalloutBinding;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.CallinCalloutScope;
@@ -818,13 +819,11 @@
 					BlockScope blockScope = (BlockScope) this.astNodesToBlockScope.get(expression);
 					if (blockScope != null) {
 //{ObjectTeams: calling into the compiler needs dependencies configured:
-					  Dependencies.setup(this, blockScope.compilationUnitScope().parser, lookupEnvironment(), false, false, false, true, true, false);
-					  try {
+					  try (Config config = Dependencies.setup(this, blockScope.compilationUnitScope().parser, lookupEnvironment(), false, false, false, true, true, false))
+					  {
 // orig:
 						return this.getTypeBinding(thisReference.resolveType(blockScope));
 // :giro
-					  } finally {
-						  Dependencies.release(this);
 					  }
 // SH}
 					}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java
index 2b4efd1..7b140ca 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java
@@ -134,13 +134,11 @@
 		}
 		if (refType != null) {
 //{ObjectTeams: calling getAnnotations() requires Dependencies control:
-		  setupDependencies();
-		  try {
+		  try (Config config = setupDependencies())
+		  {
 // orig:
 			return this.annotations = resolveAnnotationBindings(refType.getAnnotations(), false);
 // :giro
-		  } finally {
-			Dependencies.release(this.resolver);
 		  }
 // SH}
 		}
@@ -148,8 +146,8 @@
 	}
 
 //{ObjectTeams: utilities for methods needing configured Dependencies:
-	void setupDependencies() {
-		setupDependencies(true, true, true, true, false, true);
+	Config setupDependencies() {
+		return setupDependencies(true, true, true, true, false, true);
 	}
 
 	Config setupDependencies(boolean	          verifyMethods,
@@ -297,15 +295,13 @@
 		if (this.fields != null) {
 			return this.fields;
 		}
-//{ObjectTeams: may need Dependencies:
-		boolean usesDependencies = false;
-// SH}
+//{ObjectTeams: may need Dependencies (when calling methods()):
+/* orig:
 		try {
-			if (isClass() || isInterface() || isEnum()) {
-//{ObjectTeams: calling methods() requires Dependencies control:
-				setupDependencies();
-				usesDependencies = true;
+  :giro */
+		try (Config config = setupDependencies()) {
 // SH}
+			if (isClass() || isInterface() || isEnum()) {
 				ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
 				FieldBinding[] fieldBindings = referenceBinding.availableFields(); // resilience
 				int length = fieldBindings.length;
@@ -341,12 +337,6 @@
 			 */
 			org.eclipse.jdt.internal.core.util.Util.log(e, "Could not retrieve declared fields"); //$NON-NLS-1$
 		}
-//{ObjectTeams: cleanup:
-		finally {
-			if (usesDependencies)
-				Dependencies.release(this.resolver);
-		}
-// SH}
 		return this.fields = NO_VARIABLE_BINDINGS;
 	}
 
@@ -360,15 +350,13 @@
 		if (this.methods != null) {
 			return this.methods;
 		}
-//{ObjectTeams: may need Dependencies:
-		boolean usesDependencies = false;
-// SH}
+//{ObjectTeams: may need Dependencies (when calling methods()):
+/* orig:
 		try {
-			if (isClass() || isInterface() || isEnum()) {
-//{ObjectTeams: calling methods() requires Dependencies control:
-				setupDependencies();
-				usesDependencies = true;
+  :giro */
+		try (Config config = setupDependencies()) {
 // SH}
+			if (isClass() || isInterface() || isEnum()) {
 				ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
 				org.eclipse.jdt.internal.compiler.lookup.MethodBinding[] internalMethods = referenceBinding.availableMethods(); // be resilient
 				int length = internalMethods.length;
@@ -407,12 +395,6 @@
 			 */
 			org.eclipse.jdt.internal.core.util.Util.log(e, "Could not retrieve declared methods"); //$NON-NLS-1$
 		}
-//{ObjectTeams: cleanup:
-		finally {
-			if (usesDependencies)
-				Dependencies.release(this.resolver);
-		}
-// SH}
 		return this.methods = NO_METHOD_BINDINGS;
 	}
 
@@ -586,19 +568,13 @@
 		if (this.binding == null || scope == null)
 			return null;
 //{ObjectTeams: protect with minimally configured Dependencies:
-		Config cfg = null;
-		if (!Dependencies.isSetup())
-			cfg = setupDependencies(true, false, false, true, false, true);
-	  try {
+	  try (Config cfg = setupDependencies(true, false, false, true, false, true)) {
 // orig:
 		MethodBinding sam = this.binding.getSingleAbstractMethod(scope, true);
 		if (sam == null || !sam.isValidBinding())
 			return null;
 		return this.resolver.getMethodBinding(sam);
 // :giro
-	  } finally {
-		  if (cfg != null)
-			  Dependencies.release(this.resolver);
 	  }
 // SH}
 	}
@@ -621,10 +597,8 @@
 		ReferenceBinding[] internalInterfaces = null;
 //{ObjectTeams: protect with minimally configured Dependencies:
 // see Bug 352605 - Eclipse is reporting "Could not retrieve superclass" every few minutes
-		Config cfg = null;
-		if (!Dependencies.isSetup())
-			cfg = setupDependencies(false, false, false, false, false, true);
-	  try {
+	  try (Config cfg = setupDependencies(false, false, false, false, false, true))
+	  {
 // - continued at bottom of method - SH}
 		try {
 			internalInterfaces = referenceBinding.superInterfaces();
@@ -687,10 +661,7 @@
 			return this.interfaces = newInterfaces;
 		}
 		return this.interfaces = NO_TYPE_BINDINGS;
-//{ObjectTeams: conclude try-finally from above
-	  } finally {
-		if (cfg != null)
-			Dependencies.release(this.resolver);
+//{ObjectTeams: conclude try-with-resources from above
 	  }
 // SH}	
 	}
@@ -1055,16 +1026,11 @@
 		try {
 //{ObjectTeams: protect with minimally configured Dependencies:
 // see Bug 352605 - Eclipse is reporting "Could not retrieve superclass" every few minutes
-		  Config cfg = null;
-		  if (!Dependencies.isSetup())
-			cfg = setupDependencies(false, false, false, false, false, true);
-		  try {
+		  try (Config cfg = setupDependencies(false, false, false, false, false, true))
+		  {
 // orig:
 			superclass = ((ReferenceBinding)this.binding).superclass();
 // :giro
-		  } finally {
-			if (cfg != null)
-				Dependencies.release(this.resolver);
 		  }
 // SH}
 		} catch (RuntimeException e) {
@@ -1497,18 +1463,12 @@
 	    if (! this.binding.isRole())
 			return null;
 	    ReferenceBinding roleBinding = (ReferenceBinding) this.binding;
-	    Config cfg = null;
-	    if (!Dependencies.isSetup())
-	    	cfg = setupDependencies(false, false, false, false, false, true);
-	    try {
+	    try (Config cfg = setupDependencies(false, false, false, false, false, true)) {
 		    ReferenceBinding baseclass = roleBinding.baseclass();
 		    if (baseclass == null) {
 				return null;
 			}
 		    return this.resolver.getTypeBinding(baseclass);
-	    } finally {
-	    	if (cfg != null)
-	    		Dependencies.release(this.resolver);
 	    }
 	}
 //	ira+SH}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java
index d9f8c87..6c3d873 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java
@@ -131,19 +131,12 @@
 
 			if (unit != null) {
 //{ObjectTeams: controlled by Dependencies:
-			  boolean newDependencySetup= false;
-			  try {
-				if (!Dependencies.isSetup()) {
-					newDependencySetup= true;
-					Dependencies.setup(this, this.parser, this.lookupEnvironment, true, false);
-				}
+			  try (Config config = Dependencies.setup(this, this.parser, this.lookupEnvironment, true, false))
+			  {
 // orig:  Note(SH): this will redirect:
 				this.lookupEnvironment.buildTypeBindings(unit, accessRestriction);
 				this.lookupEnvironment.completeTypeBindings(unit);
 // :giro
-			  } finally {
-				if (newDependencySetup)
-					Dependencies.release(this);
 			  }
 // SH}
 			}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java
index ca63d1c..7ed556c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java
@@ -74,6 +74,7 @@
 import org.eclipse.objectteams.otdt.core.OTModelManager;
 import org.eclipse.objectteams.otdt.core.TypeHelper;
 import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
+import org.eclipse.objectteams.otdt.internal.core.compiler.control.Config;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.Dependencies;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.ITranslationStates;
 
@@ -755,16 +756,12 @@
  */
 public void resolve(IGenericType suppliedType) {
 //{ObjectTeams: conditional setup
-    boolean dependenciesSetup = false;
-//carp}
-
+/* orig:    
 	try {
+  :giro */
+	try (Config config = Dependencies.setup(this, null, this.lookupEnvironment, true, false))
+	{
 		if (suppliedType.isBinaryType()) {
-//{ObjectTeams: setup here, other branch does it in resolve(Openable[]..)
-			// for binary types we need little processing only ...
-			Dependencies.setup(this, null, this.lookupEnvironment, true, false);
-			dependenciesSetup = true;
-// SH}
 			BinaryTypeBinding binaryTypeBinding = this.lookupEnvironment.cacheBinaryType((IBinaryType) suppliedType, false/*don't need field and method (bug 125067)*/, null /*no access restriction*/);
 			remember(suppliedType, binaryTypeBinding);
 			// We still need to add superclasses and superinterfaces bindings (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53095)
@@ -803,10 +800,6 @@
 		}
 	} catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
 	} finally {
-//{ObjectTeams: cleanup
-	    if (dependenciesSetup)
-	        Dependencies.release(this);
-//SH}
 		reset();
 	}
 }
@@ -825,11 +818,14 @@
  * @param monitor
  */
 public void resolve(Openable[] openables, HashSet localTypes, IProgressMonitor monitor) {
-//{ObjectTeams: conditional setup
-    boolean dependenciesSetup = false;
-//carp}
 	SubMonitor subMonitor = SubMonitor.convert(monitor, 3);
+//{ObjectTeams: setup Dependencies
+/* orig:
 	try {
+  :giro */
+	try (Config config = Dependencies.setup(this, null, this.lookupEnvironment, true/*build constructor only*/, true))
+	{
+//carp}
 		int openablesLength = openables.length;
 		CompilationUnitDeclaration[] parsedUnits = new CompilationUnitDeclaration[openablesLength];
 		boolean[] hasLocalType = new boolean[openablesLength];
@@ -851,11 +847,10 @@
 		subMonitor.split(1);
 		// build type bindings
 		Parser parser = new Parser(this.lookupEnvironment.problemReporter, true);
+//{ObjectTeams: complete the configuration:
+		config.parser = parser;
+// SH}
 		final boolean isJava8 = this.options.sourceLevel >= ClassFileConstants.JDK1_8;
-//{ObjectTeams: setup Dependencies
-		Dependencies.setup(this, parser, this.lookupEnvironment, true/*build constructor only*/, true);
-		dependenciesSetup = true;
-//carp}
 
 		for (int i = 0; i < openablesLength; i++) {
 			Openable openable = openables[i];
@@ -1053,10 +1048,6 @@
 		if (TypeHierarchy.DEBUG)
 			e.printStackTrace();
 	} finally {
-//{ObjectTeams: cleanup
-	    if (dependenciesSetup)
-	        Dependencies.release(this);
-//SH}
 		reset();
 	}
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexer.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexer.java
index 451231e..51859d7 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexer.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexer.java
@@ -55,6 +55,7 @@
 import org.eclipse.jdt.internal.core.search.matching.IndexBasedJavaSearchEnvironment;
 import org.eclipse.jdt.internal.core.search.matching.MethodPattern;
 import org.eclipse.jdt.internal.core.search.processing.JobManager;
+import org.eclipse.objectteams.otdt.internal.core.compiler.control.Config;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.Dependencies;
 
 /**
@@ -172,19 +173,14 @@
 			this.lookupEnvironment = new LookupEnvironment(this, this.options, problemReporter, nameEnvironment);
 			reduceParseTree(this.cud);
 //{ObjectTeams: need Dependencies configured:
-		  boolean depsConfigured = Dependencies.isSetup();
-		  try {
-			if (!depsConfigured)
-				Dependencies.setup(this, this.basicParser, this.lookupEnvironment, true, false);
+		  try (Config config = Dependencies.setup(this, this.basicParser, this.lookupEnvironment, true, false))
+		  {
 // orig:
 			this.lookupEnvironment.buildTypeBindings(this.cud, null);
 			this.lookupEnvironment.completeTypeBindings();
 			this.cud.scope.faultInTypes();
 			this.cud.resolve();
 // :giro
-		  } finally {
-			  if (!depsConfigured)
-				  Dependencies.release(this);
 		  }
 // SH}
 		} catch (Exception e) {
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java
index 1630f54..b82733a 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java
@@ -99,6 +99,7 @@
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CallinMappingDeclaration;
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CalloutMappingDeclaration;
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.PrecedenceDeclaration;
+import org.eclipse.objectteams.otdt.internal.core.compiler.control.Config;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.Dependencies;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.ITranslationStates;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.StateHelper;
@@ -395,10 +396,13 @@
 public void accept(ICompilationUnit sourceUnit, AccessRestriction accessRestriction) {
 	// Switch the current policy and compilation result for this unit to the requested one.
 	CompilationResult unitResult = new CompilationResult(sourceUnit, 1, 1, this.options.maxProblemsPerUnit);
-	try {
 //{ObjectTeams: setup Dependencies for the other parser etc.
-	    Dependencies.setup(this, basicParser(), this.lookupEnvironment, true, true);
-	    // strictDiet since we will only dietParse and not even go beyond STATE_BINDINGS_COMPLETED
+/* orig:
+	try {
+:giro */
+	try (Config config = Dependencies.setup(this, basicParser(), this.lookupEnvironment, true, true))
+	{
+	// strictDiet since we will only dietParse and not even go beyond STATE_BINDINGS_COMPLETED
 //carp}
 		CompilationUnitDeclaration parsedUnit = basicParser().dietParse(sourceUnit, unitResult);
 //{ObjectTeams: never try to get this unit's method bodies:
@@ -415,11 +419,6 @@
 			throw e; // want to abort enclosing request to compile
 		}
 	}
-//{ObjectTeams:
-	finally {
-		Dependencies.release(this);
-	}
-//carp}
 	// Display unit error in debug mode
 	if (BasicSearchEngine.VERBOSE) {
 		if (unitResult.problemCount > 0) {
@@ -1318,11 +1317,13 @@
 	boolean bindingsWereCreated = mustResolve;
 
 //{ObjectTeams: setup Dependencies
-    Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true, true);
-    // is strictDiet correct here? (SH).
+/* orig:
+	try {
+:giro */
+	try (Config config = Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true, true)) // is strictDiet correct here? (SH).
+	{
 //carp}
 
-	try {
 //{ObjectTeams: by sorting short compound names to the front we force to
 //              analyze teams before their role files, thus avoiding to #accept()
 //              these role files which could later case duplicate type errors
@@ -1398,11 +1399,6 @@
 	} catch (AbortCompilation e) {
 		bindingsWereCreated = false;
 	}
-//{ObjectTeams:
-	finally {
-	    Dependencies.release(this);
-	}
-//carp}
 
 	if (!mustResolve) {
 		return;
@@ -1922,16 +1918,16 @@
 		throw new OperationCanceledException();
 
 //{ObjectTeams: LookupEnvironment.buildTypeBindings needs this context:
-	boolean useDependencies = false;
-	if (   mustResolve 
-	    || (this.patternLocator.mayBeGeneric && possibleMatch.nodeSet.mustResolve))
+/* orig:
+	try {
+:giro */
+	try (Config config = (   mustResolve 
+						  || (this.patternLocator.mayBeGeneric && possibleMatch.nodeSet.mustResolve))
+		? Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true)
+		: null) 
 	{
-		Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true);
-		useDependencies = true;
-	}
 //SH}
 	
-	try {
 		if (BasicSearchEngine.VERBOSE)
 			System.out.println("Parsing " + possibleMatch.openable.toStringWithAncestors()); //$NON-NLS-1$
 
@@ -1966,10 +1962,6 @@
 		}
 	} finally {
 		this.parser.nodeSet = null;
-//{ObjectTeams:
-		if (useDependencies)
-			Dependencies.release(this);
-// SH}	
 	}
 	return true;
 }
@@ -1979,9 +1971,12 @@
 protected void process(PossibleMatch possibleMatch, boolean bindingsWereCreated) throws CoreException {
 	this.currentPossibleMatch = possibleMatch;
 	CompilationUnitDeclaration unit = possibleMatch.parsedUnit;
-	try {
 //{ObjectTeams: guard with setup/release
-		Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true);
+/* orig:
+	try {
+  :giro */
+	try (Config config = Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true))
+	{
 		// is strictDiet correct here?
 		if (bindingsWereCreated && unit.state.getState() < ITranslationStates.STATE_BINDINGS_BUILT)
 		    StateHelper.setStateRecursive(unit, ITranslationStates.STATE_BINDINGS_BUILT, true);
@@ -2058,9 +2053,6 @@
 	} finally {
 		this.lookupEnvironment.unitBeingCompleted = null;
 		this.currentPossibleMatch = null;
-//{ObjectTeams
-		Dependencies.release(this);
-//carp}
 	}
 }
 protected void purgeMethodStatements(TypeDeclaration type, boolean checkEachMethod) {
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeNamesCollector.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeNamesCollector.java
index 68ceb69..3bd424b 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeNamesCollector.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeNamesCollector.java
@@ -31,6 +31,7 @@
 import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
 import org.eclipse.jdt.internal.core.util.ASTNodeFinder;
 import org.eclipse.jdt.internal.core.util.Util;
+import org.eclipse.objectteams.otdt.internal.core.compiler.control.Config;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.Dependencies;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.ITranslationStates;
 
@@ -144,9 +145,9 @@
 			this.locator.basicParser().parse(sourceUnit, compilationResult);
 	if (unit != null) {
 //{ObjectTeams: let Dependencies control the processing
-		Dependencies.setup(this, this.locator.basicParser(), this.locator.lookupEnvironment,
-				 /*buildFieldsAndMethods*/!isTopLevelOrMember, isTopLevelOrMember);
-		try {
+	  try (Config config = Dependencies.setup(this, this.locator.basicParser(), this.locator.lookupEnvironment,
+				 /*buildFieldsAndMethods*/!isTopLevelOrMember, isTopLevelOrMember))
+	  {
 // orig:
 		this.locator.lookupEnvironment.buildTypeBindings(unit, null /*no access restriction*/);
 		this.locator.lookupEnvironment.completeTypeBindings(unit, !isTopLevelOrMember);
@@ -156,11 +157,8 @@
 //			unit.resolve();
 // :giro			
 				Dependencies.ensureState(unit, ITranslationStates.STATE_RESOLVED);
-			} 
-		} finally {
-				Dependencies.release(this);
-	
 		}
+	  }
 // SH}			
 	}
 	return unit;
diff --git a/plugins/org.eclipse.objectteams.otdt.jdt.ui/src/org/eclipse/objectteams/otdt/internal/ui/assist/OTQuickFixes.java b/plugins/org.eclipse.objectteams.otdt.jdt.ui/src/org/eclipse/objectteams/otdt/internal/ui/assist/OTQuickFixes.java
index 0e2c8b1..432997f 100644
--- a/plugins/org.eclipse.objectteams.otdt.jdt.ui/src/org/eclipse/objectteams/otdt/internal/ui/assist/OTQuickFixes.java
+++ b/plugins/org.eclipse.objectteams.otdt.jdt.ui/src/org/eclipse/objectteams/otdt/internal/ui/assist/OTQuickFixes.java
@@ -18,6 +18,7 @@
 
 import static org.eclipse.objectteams.otdt.ui.ImageConstants.CALLINMETHOD_IMG;
 
+import java.io.Closeable;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Hashtable;
@@ -278,12 +279,9 @@
 	 */
 	protected class JavaCorrectionProcessor playedBy JavaCorrectionProcessor {
 		callin static IStatus guardDependencies() {
-			boolean hasConfig = ConfigHelper.checkCreateStubConfig(OTQuickFixes.this);
-			try {
+			try (ConfigHelper.IConfig config = ConfigHelper.checkCreateStubConfig2(OTQuickFixes.this))
+			{
 				return base.guardDependencies();
-			} finally {
-				if (hasConfig)
-					ConfigHelper.removeConfig(OTQuickFixes.this);
 			}
 		}
 		guardDependencies <- replace collectProposals;
diff --git a/testplugins/org.eclipse.objectteams.otdt.tests/.classpath b/testplugins/org.eclipse.objectteams.otdt.tests/.classpath
index 1f62ec0..984c253 100644
--- a/testplugins/org.eclipse.objectteams.otdt.tests/.classpath
+++ b/testplugins/org.eclipse.objectteams.otdt.tests/.classpath
@@ -8,7 +8,7 @@
 	<classpathentry kind="src" path="formatter"/>
 	<classpathentry kind="src" path="otjld"/>
 	<classpathentry kind="con" path="OTRE"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="src" path="selection"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
diff --git a/testplugins/org.eclipse.objectteams.otdt.tests/.settings/org.eclipse.jdt.core.prefs b/testplugins/org.eclipse.objectteams.otdt.tests/.settings/org.eclipse.jdt.core.prefs
index be3d547..25e483e 100644
--- a/testplugins/org.eclipse.objectteams.otdt.tests/.settings/org.eclipse.jdt.core.prefs
+++ b/testplugins/org.eclipse.objectteams.otdt.tests/.settings/org.eclipse.jdt.core.prefs
@@ -6,9 +6,10 @@
 org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.compliance=1.7
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -97,4 +98,4 @@
 org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.compiler.source=1.5
+org.eclipse.jdt.core.compiler.source=1.7
diff --git a/testplugins/org.eclipse.objectteams.otdt.tests/META-INF/MANIFEST.MF b/testplugins/org.eclipse.objectteams.otdt.tests/META-INF/MANIFEST.MF
index 43f34ad..18459be 100644
--- a/testplugins/org.eclipse.objectteams.otdt.tests/META-INF/MANIFEST.MF
+++ b/testplugins/org.eclipse.objectteams.otdt.tests/META-INF/MANIFEST.MF
@@ -53,5 +53,5 @@
  org.eclipse.text,
  org.eclipse.jdt.core.tests.model,
  org.eclipse.objectteams.otequinox
-Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Bundle-RequiredExecutionEnvironment: JavaSE-1.7
 Bundle-ActivationPolicy: lazy
diff --git a/testplugins/org.eclipse.objectteams.otdt.tests/model/org/eclipse/objectteams/otdt/tests/otmodel/OTReconcilerTests.java b/testplugins/org.eclipse.objectteams.otdt.tests/model/org/eclipse/objectteams/otdt/tests/otmodel/OTReconcilerTests.java
index 1b1f346..885cda2 100644
--- a/testplugins/org.eclipse.objectteams.otdt.tests/model/org/eclipse/objectteams/otdt/tests/otmodel/OTReconcilerTests.java
+++ b/testplugins/org.eclipse.objectteams.otdt.tests/model/org/eclipse/objectteams/otdt/tests/otmodel/OTReconcilerTests.java
@@ -66,6 +66,7 @@
 import org.eclipse.objectteams.otdt.core.OTModelManager;
 import org.eclipse.objectteams.otdt.core.ext.OTDTPlugin;
 import org.eclipse.objectteams.otdt.core.ext.OTREContainer;
+import org.eclipse.objectteams.otdt.internal.core.compiler.control.Config;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.Dependencies;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.ITranslationStates;
 import org.eclipse.text.edits.DeleteEdit;
@@ -829,18 +830,13 @@
 
 			if (unit != null) {
 	//{ObjectTeams: controlled by Dependencies:
-			  boolean newDependencySetup= false;
-			  try {
-				if (!Dependencies.isSetup()) {
-					newDependencySetup= true;
-					Dependencies.setup(this, this.parser, this.lookupEnvironment, true, false);
-				}
+			  try (Config config = Dependencies.setup(this, this.parser, this.lookupEnvironment, true, false))
+			  {
 				// Note(SH): this will redirect:
+// orig:
 				this.lookupEnvironment.buildTypeBindings(unit, accessRestriction);
 				this.lookupEnvironment.completeTypeBindings(unit);
-			  } finally {
-				if (newDependencySetup)
-					Dependencies.release(this);
+// :giro
 			  }
 	// SH}
 			}
@@ -857,8 +853,10 @@
 					compilerOptions, 
 					problemReporter.problemFactory);
 		
-		Dependencies.setup(this, parser, compiler.lookupEnvironment, true, false);
-		Dependencies.ensureState(parsedUnit, state);
+		try (Config config = Dependencies.setup(this, parser, compiler.lookupEnvironment, true, false))
+		{
+			Dependencies.ensureState(parsedUnit, state);
+		}
 	}
 	
 	public void testAnchoredType03() throws CoreException, InterruptedException {