Bug 559165 - deadlock triggered by classloading triggered by
TransformerPlugin.acquireLog()
diff --git a/features/org.eclipse.objectteams.otequinox.feature/feature.xml b/features/org.eclipse.objectteams.otequinox.feature/feature.xml
index 139f628..cbad16d 100644
--- a/features/org.eclipse.objectteams.otequinox.feature/feature.xml
+++ b/features/org.eclipse.objectteams.otequinox.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.objectteams.otequinox"
       label="%featureName"
-      version="2.7.6.qualifier"
+      version="2.7.7.qualifier"
       provider-name="%providerName"
       plugin="org.eclipse.objectteams.otequinox"
       colocation-affinity="org.eclipse.rcp">
diff --git a/plugins/org.eclipse.objectteams.otequinox/META-INF/MANIFEST.MF b/plugins/org.eclipse.objectteams.otequinox/META-INF/MANIFEST.MF
index 5335561..c470289 100644
--- a/plugins/org.eclipse.objectteams.otequinox/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.objectteams.otequinox/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.objectteams.otequinox;singleton:=true
 Automatic-Module-Name: org.eclipse.objectteams.otequinox
-Bundle-Version: 2.7.6.qualifier
+Bundle-Version: 2.7.7.qualifier
 Bundle-Activator: org.eclipse.objectteams.otequinox.TransformerPlugin
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
diff --git a/plugins/org.eclipse.objectteams.otequinox/META-INF/p2.inf b/plugins/org.eclipse.objectteams.otequinox/META-INF/p2.inf
index 4abb4df..8f90ced 100644
--- a/plugins/org.eclipse.objectteams.otequinox/META-INF/p2.inf
+++ b/plugins/org.eclipse.objectteams.otequinox/META-INF/p2.inf
@@ -4,11 +4,11 @@
 
 
 units.0.id = org.eclipse.objectteams.otequinox.configuration
-units.0.version = 2.7.6.$qualifier$
+units.0.version = 2.7.7.$qualifier$
 
 units.0.hostRequirements.0.namespace=osgi.bundle
 units.0.hostRequirements.0.name=org.eclipse.objectteams.otequinox
-units.0.hostRequirements.0.range=[2.7.6,3.0.0)
+units.0.hostRequirements.0.range=[2.7.7,3.0.0)
 units.0.hostRequirements.1.namespace = org.eclipse.equinox.p2.eclipse.type
 units.0.hostRequirements.1.name = bundle
 units.0.hostRequirements.1.range = [1.0.0,2.0.0)
@@ -17,7 +17,7 @@
 units.0.properties.0.value = true
 units.0.requires.0.namespace = osgi.bundle
 units.0.requires.0.name = org.eclipse.objectteams.otequinox
-units.0.requires.0.range = [2.7.6,3.0.0)
+units.0.requires.0.range = [2.7.7,3.0.0)
 
 units.0.requires.1.namespace = org.eclipse.equinox.p2.eclipse.type
 units.0.requires.1.name = bundle
@@ -26,7 +26,7 @@
 
 units.0.provides.0.namespace = org.eclipse.equinox.p2.iu
 units.0.provides.0.name = org.eclipse.objectteams.otequinox.configuration
-units.0.provides.0.version = 2.7.6.$qualifier$
+units.0.provides.0.version = 2.7.7.$qualifier$
 
 units.0.instructions.install=\
 	installBundle(bundle:${artifact})
diff --git a/plugins/org.eclipse.objectteams.otequinox/about.ini b/plugins/org.eclipse.objectteams.otequinox/about.ini
index 4d7289a..0938d54 100644
--- a/plugins/org.eclipse.objectteams.otequinox/about.ini
+++ b/plugins/org.eclipse.objectteams.otequinox/about.ini
@@ -1,10 +1,10 @@
 aboutText=Object Teams -- Equinox integration (OT/Equinox)\n\
 \n\
-Version: 2.7.6\n\
+Version: 2.7.7\n\
 \n\
-Part of Eclipse SimRel 2019-12\n\
+Part of Eclipse SimRel 2020-03\n\
 \n\
-(c) Copyright Technical University Berlin and others, 2005, 2019\n\
+(c) Copyright Technical University Berlin and others, 2005, 2020\n\
 Visit http://www.eclipse.org/objectteams\n\
 \n\
 
diff --git a/plugins/org.eclipse.objectteams.otequinox/annotations/plugins/org/eclipse/equinox/log/ExtendedLogService.eea b/plugins/org.eclipse.objectteams.otequinox/annotations/plugins/org/eclipse/equinox/log/ExtendedLogService.eea
new file mode 100644
index 0000000..3f532a3
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otequinox/annotations/plugins/org/eclipse/equinox/log/ExtendedLogService.eea
@@ -0,0 +1,4 @@
+class org/eclipse/equinox/log/ExtendedLogService
+getLogger
+ (Lorg/osgi/framework/Bundle;Ljava/lang/String;)Lorg/eclipse/equinox/log/Logger;
+ (Lorg/osgi/framework/Bundle;Ljava/lang/String;)L1org/eclipse/equinox/log/Logger;
diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/LoggerBridge.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/LoggerBridge.java
new file mode 100644
index 0000000..939fe94
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/LoggerBridge.java
@@ -0,0 +1,80 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ * 
+ * Copyright 2020 GK Software SE
+ *  
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Please visit http://www.objectteams.org for updates and contact.
+ * 
+ * Contributors:
+ * 	Stephan Herrmann - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.internal.osgi.weaving;
+
+import java.util.ArrayList;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.equinox.log.Logger;
+import org.eclipse.osgi.framework.log.FrameworkLogEntry;
+import org.osgi.service.log.LogService;
+
+/**
+ * Utility to bridge from IStatus logging to {@link Logger}.
+ */
+public class LoggerBridge {
+	
+	public static void log(Logger logger, IStatus status) {
+		logger.log(LoggerBridge.getLog(status), LoggerBridge.getLevel(status), status.getMessage(), status.getException());
+	}
+
+	// --- copied from org.eclipse.core.internal.runtime.PlatformLogWriter.getLog(IStatus): ---
+
+	public static final String EQUINOX_LOGGER_NAME = "org.eclipse.equinox.logger"; //$NON-NLS-1$
+
+	static FrameworkLogEntry getLog(IStatus status) {
+		Throwable t = status.getException();
+		ArrayList<FrameworkLogEntry> childlist = new ArrayList<>();
+
+		int stackCode = t instanceof CoreException ? 1 : 0;
+		// ensure a substatus inside a CoreException is properly logged 
+		if (stackCode == 1) {
+			IStatus coreStatus = ((CoreException) t).getStatus();
+			if (coreStatus != null) {
+				childlist.add(getLog(coreStatus));
+			}
+		}
+
+		if (status.isMultiStatus()) {
+			IStatus[] children = status.getChildren();
+			for (IStatus child : children) {
+				childlist.add(getLog(child));
+			}
+		}
+
+		FrameworkLogEntry[] children = childlist.size() == 0 ? null : childlist.toArray(new FrameworkLogEntry[childlist.size()]);
+
+		return new FrameworkLogEntry(status, status.getPlugin(), status.getSeverity(), status.getCode(), status.getMessage(), stackCode, t, children);
+	}
+
+	@SuppressWarnings("deprecation")
+	public static int getLevel(IStatus status) {
+		switch (status.getSeverity()) {
+			case IStatus.ERROR :
+				return LogService.LOG_ERROR;
+			case IStatus.WARNING :
+				return LogService.LOG_WARNING;
+			case IStatus.INFO :
+				return LogService.LOG_INFO;
+			case IStatus.OK :
+				return LogService.LOG_DEBUG;
+			case IStatus.CANCEL :
+			default :
+				return 32; // unknown
+		}
+	}
+}
diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/TransformerPlugin.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/TransformerPlugin.java
index ffa20a4..2727ef2 100644
--- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/TransformerPlugin.java
+++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/TransformerPlugin.java
@@ -1,7 +1,7 @@
 /**********************************************************************
  * This file is part of "Object Teams Development Tooling"-Software
  * 
- * Copyright 2013, 2015 GK Software AG
+ * Copyright 2013, 2020 GK Software SE
  *  
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
@@ -25,22 +25,22 @@
 import java.util.List;
 import java.util.Map;
 
-import org.eclipse.core.internal.runtime.PlatformLogWriter;
 import org.eclipse.core.runtime.FileLocator;
 import org.eclipse.core.runtime.IExtensionRegistry;
-import org.eclipse.core.runtime.ILog;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.equinox.log.ExtendedLogReaderService;
 import org.eclipse.equinox.log.ExtendedLogService;
 import org.eclipse.equinox.log.LogFilter;
 import org.eclipse.equinox.log.Logger;
+import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.objectteams.internal.osgi.weaving.AspectBinding;
 import org.eclipse.objectteams.internal.osgi.weaving.AspectBindingRegistry;
 import org.eclipse.objectteams.internal.osgi.weaving.AspectPermissionManager;
 import org.eclipse.objectteams.internal.osgi.weaving.DelegatingTransformer.OTAgentNotInstalled;
+import org.eclipse.objectteams.internal.osgi.weaving.LoggerBridge;
 import org.eclipse.objectteams.internal.osgi.weaving.OTWeavingHook;
 import org.eclipse.objectteams.otre.ClassLoaderAccess;
 import org.objectteams.Team;
@@ -74,10 +74,10 @@
 
 		AspectBindingRegistry aspectBindingRegistry;
 		@Nullable AspectPermissionManager aspectPermissionManager;
-		ILog log;
+		Logger log;
 		List<Team> teamInstances = new ArrayList<>();
 		
-		public InitializedPlugin(AspectBindingRegistry aspectBindingRegistry, @Nullable AspectPermissionManager permissionManager, ILog log) {
+		public InitializedPlugin(AspectBindingRegistry aspectBindingRegistry, @Nullable AspectPermissionManager permissionManager, Logger log) {
 			this.aspectBindingRegistry = aspectBindingRegistry;
 			this.aspectPermissionManager = permissionManager;
 			this.log = log;
@@ -116,7 +116,12 @@
 				result[i] = aspectBindings.get(i).aspectPlugin;
 			return result;
 		}
+
+		public void log(IStatus status) {
+			LoggerBridge.log(this.log, status);
+		}
 	}
+
 	private static @Nullable InitializedPlugin plugin;
 	/**
 	 * Single point of access: either we get a fully initialized instance, or ISE is thrown.
@@ -188,15 +193,14 @@
 			otWeavingHook.activate(bundleContext, extensionService);
 		} catch (OTAgentNotInstalled e) {
 			registration.unregister();
-			ILog log = acquireLog(bundleContext);
-			log.log(new Status(IStatus.ERROR,
+			Logger log = acquireLog(bundleContext);
+			LoggerBridge.log(log, new Status(IStatus.ERROR,
 					bundleContext.getBundle().getSymbolicName(), 
 					"Error activating OT/Equinox: "+e.getMessage()));
 		}
 	}
 
-	@SuppressWarnings("restriction")
-	private static ILog acquireLog(BundleContext bundleContext) {
+	private static Logger acquireLog(BundleContext bundleContext) {
 		setupLoggerContext(bundleContext);
 		ServiceTracker<ExtendedLogService,ExtendedLogService> tracker
 				= new ServiceTracker<ExtendedLogService,ExtendedLogService>(bundleContext, ExtendedLogService.class, null);
@@ -204,14 +208,13 @@
 		ExtendedLogService logService = tracker.getService();
 		Bundle bundle = bundleContext.getBundle();
 		Logger logger = logService.getLogger(bundle, OTEQUINOX_LOGGER_NAME);
-		org.eclipse.core.internal.runtime.Log result = new org.eclipse.core.internal.runtime.Log(bundle, logger);
 
 		ServiceTracker<ExtendedLogReaderService, ExtendedLogReaderService> logReaderTracker 
 				= new ServiceTracker<ExtendedLogReaderService,ExtendedLogReaderService>(bundleContext, ExtendedLogReaderService.class.getName(), null);
 		logReaderTracker.open();
 		ExtendedLogReaderService logReader = logReaderTracker.getService();
 
-		final Logger equinoxLogger = logService.getLogger(bundle, org.eclipse.core.internal.runtime.PlatformLogWriter.EQUINOX_LOGGER_NAME);
+		final Logger equinoxLogger = logService.getLogger(bundle, LoggerBridge.EQUINOX_LOGGER_NAME);
 
 		// listen to log events from our logger and asynchronously dispatch them to the equinox logger
 		logReader.addLogListener(
@@ -228,15 +231,14 @@
 				}
 			}
 		);
-		return result;
+		return logger;
 	}
 
 	private static void setupLoggerContext(BundleContext bundleContext) {
 		String bundleSymbolicName = bundleContext.getBundle().getSymbolicName();
 		
 		Status dummyStatus = new Status(WARN_LEVEL, bundleSymbolicName, "no message");
-		@SuppressWarnings("restriction")
-		LogLevel logLevel = LogLevel.values()[PlatformLogWriter.getLevel(dummyStatus)];
+		LogLevel logLevel = LogLevel.values()[LoggerBridge.getLevel(dummyStatus)];
 		Map<String,LogLevel> levels = new HashMap<>();
 		levels.put(OTEQUINOX_LOGGER_NAME, logLevel);
 
@@ -289,7 +291,7 @@
 		Status status = new Status(IStatus.ERROR, TRANSFORMER_PLUGIN_ID, msg, ex);
 		final InitializedPlugin plugin = TransformerPlugin.plugin;
 		if (plugin != null) {
-			plugin.log.log(status);
+			plugin.log(status);
 		} else {
 			System.err.println(msg);
 			ex.printStackTrace();
@@ -309,7 +311,7 @@
 			Status status = new Status(level, TRANSFORMER_PLUGIN_ID, "OT/Equinox: "+msg);
 			final InitializedPlugin plugin = TransformerPlugin.plugin;
 			if (plugin != null) {
-				plugin.log.log(status);
+				plugin.log(status);
 			} else {
 				synchronized(TransformerPlugin.class) {
 					pendingLogEntries.add(status);
@@ -327,10 +329,10 @@
 			copy = pendingLogEntries;
 			pendingLogEntries = new ArrayList<>();
 		}
-		for (IStatus status : copy) {
+		for (@NonNull IStatus status : copy) { // TODO: declare copy as List<@NonNull IStatus>
 			final InitializedPlugin plugin = TransformerPlugin.plugin;
 			if (plugin != null) {
-				plugin.log.log(status);
+				plugin.log(status);
 			} else {
 				if (status.getCode() == IStatus.ERROR)
 					System.err.println(status.getMessage());
diff --git a/releng/map/otdt.map.in b/releng/map/otdt.map.in
index 3e7700d..b4c505b 100644
--- a/releng/map/otdt.map.in
+++ b/releng/map/otdt.map.in
@@ -4,7 +4,7 @@
 feature@org.eclipse.objectteams.otdt=GIT,repo=git://git.eclipse.org/gitroot/objectteams/org.eclipse.objectteams.git,path=features/org.eclipse.objectteams.otdt.feature

 feature@org.eclipse.objectteams.otdt.source.feature=GIT,repo=git://git.eclipse.org/gitroot/objectteams/org.eclipse.objectteams.git,path=features/org.eclipse.objectteams.otdt.source.feature

 feature@org.eclipse.objectteams.otdt.core.patch=GIT,repo=git://git.eclipse.org/gitroot/objectteams/org.eclipse.objectteams.git,path=features/org.eclipse.objectteams.otdt.core.patch

-feature@org.eclipse.objectteams.otequinox=GIT,repo=git://git.eclipse.org/gitroot/objectteams/org.eclipse.objectteams.git,path=features/org.eclipse.objectteams.otequinox.feature,tag=builds/201912111741

+feature@org.eclipse.objectteams.otequinox=GIT,repo=git://git.eclipse.org/gitroot/objectteams/org.eclipse.objectteams.git,path=features/org.eclipse.objectteams.otequinox.feature

 feature@org.eclipse.objectteams.otequinox.otre=GIT,repo=git://git.eclipse.org/gitroot/objectteams/org.eclipse.objectteams.git,path=features/org.eclipse.objectteams.otequinox.otre.feature,tag=builds/201809081701

 feature@org.eclipse.objectteams.otequinox.turbo=GIT,repo=git://git.eclipse.org/gitroot/objectteams/org.eclipse.objectteams.git,path=features/org.eclipse.objectteams.otequinox.turbo.feature,tag=builds/201506091717

 

@@ -24,7 +24,7 @@
 plugin@org.eclipse.objectteams.otre=GIT,repo=git://git.eclipse.org/gitroot/objectteams/org.eclipse.objectteams.git,path=plugins/org.eclipse.objectteams.otre,tag=builds/201806120901

 plugin@org.eclipse.objectteams.otredyn=GIT,repo=git://git.eclipse.org/gitroot/objectteams/org.eclipse.objectteams.git,path=plugins/org.eclipse.objectteams.otredyn,tag=builds/201912111741

 !the following is also referenced in otdt.doc/buildDoc.xml (plugin-name without version):

-plugin@org.eclipse.objectteams.otequinox=GIT,repo=git://git.eclipse.org/gitroot/objectteams/org.eclipse.objectteams.git,path=plugins/org.eclipse.objectteams.otequinox,tag=builds/201912111741

+plugin@org.eclipse.objectteams.otequinox=GIT,repo=git://git.eclipse.org/gitroot/objectteams/org.eclipse.objectteams.git,path=plugins/org.eclipse.objectteams.otequinox

 fragment@org.eclipse.objectteams.otequinox.turbo=GIT,repo=git://git.eclipse.org/gitroot/objectteams/org.eclipse.objectteams.git,path=plugins/org.eclipse.objectteams.otequinox.turbo,tag=builds/201506091717

 plugin@org.eclipse.objectteams.eclipse.monitor=GIT,repo=git://git.eclipse.org/gitroot/objectteams/org.eclipse.objectteams.git,path=plugins/org.eclipse.objectteams.eclipse.monitor,tag=builds/201606070956