Bug 511841 - AdapterManager.getAdapter can return wrong type

Added explicit type check for the values returned by IAdapterFactory
instances. If the return value does not match the adapter type, throw
AssertionFailedException with enough information who provided that
faulty adapter.

Change-Id: Ib527a7920250622055f93bb26855b2f52cc45743
Signed-off-by: Andrey Loskutov <loskutov@gmx.de>
diff --git a/bundles/org.eclipse.equinox.common/src/org/eclipse/core/internal/runtime/AdapterManager.java b/bundles/org.eclipse.equinox.common/src/org/eclipse/core/internal/runtime/AdapterManager.java
index 07909a1..ba4a053 100644
--- a/bundles/org.eclipse.equinox.common/src/org/eclipse/core/internal/runtime/AdapterManager.java
+++ b/bundles/org.eclipse.equinox.common/src/org/eclipse/core/internal/runtime/AdapterManager.java
@@ -288,13 +288,25 @@
 	public <T> T getAdapter(Object adaptable, Class<T> adapterType) {
 		Assert.isNotNull(adaptable);
 		Assert.isNotNull(adapterType);
-		IAdapterFactory factory = getFactories(adaptable.getClass()).get(adapterType.getName());
+		String adapterTypeName = adapterType.getName();
+		IAdapterFactory factory = getFactories(adaptable.getClass()).get(adapterTypeName);
 		T result = null;
-		if (factory != null)
+		if (factory != null) {
 			result = factory.getAdapter(adaptable, adapterType);
-		if (result == null && adapterType.isInstance(adaptable))
+		}
+		if (result == null && adapterType.isInstance(adaptable)) {
 			return (T) adaptable;
-		return result;
+		}
+		if (result == null || adapterType.isInstance(result)) {
+			return result;
+		}
+		// Here we have a result which does not match the expected type.
+		// Throwing an exception here allows us to identify the violating factory.
+		// If we don't do this, clients will just see CCE without any idea who
+		// supplied the wrong adapter
+		throw new AssertionFailedException("Adapter factory " //$NON-NLS-1$
+				+ factory + " returned " + result.getClass().getName() //$NON-NLS-1$
+				+ " that is not an instance of " + adapterTypeName); //$NON-NLS-1$
 	}
 
 	@Override
diff --git a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/adapter/AdapterFactoryProxy.java b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/adapter/AdapterFactoryProxy.java
index bcee1f6..6ba89e7 100644
--- a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/adapter/AdapterFactoryProxy.java
+++ b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/adapter/AdapterFactoryProxy.java
@@ -151,4 +151,18 @@
 		String msg = NLS.bind(RegistryMessages.adapters_badAdapterFactory, element.getContributor().getName());
 		RuntimeLog.log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, 0, msg, null));
 	}
+
+	public String toString() {
+		StringBuffer sb = new StringBuffer();
+		sb.append("AdapterFactoryProxy [contributor: "); //$NON-NLS-1$
+		sb.append(element.getContributor());
+		sb.append(", adaptableType: "); //$NON-NLS-1$
+		sb.append(getAdaptableType());
+		if (factory != null) {
+			sb.append(", factory: "); //$NON-NLS-1$
+			sb.append(factory);
+		}
+		sb.append("]"); //$NON-NLS-1$
+		return sb.toString();
+	}
 }