From d32c2a288753921b989bb1d75fb5244fffb2bc72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Sun, 30 Jun 2024 08:10:32 +0200 Subject: [PATCH] Allow interfacing with other adapter frameworks by using a proxy While the Eclipse Adapter Framework is very powerful it currently does not allow to interface with other adaption techniques (e.g. OSGi Converter Specification). This adds a new way to adapt a class of objects to a proxy that then is asked for further adaption. --- .../eclipse/core/runtime/AdapterProxy.java | 58 +++++++++++++++++++ .../org/eclipse/core/runtime/Adapters.java | 7 +++ 2 files changed, 65 insertions(+) create mode 100644 bundles/org.eclipse.equinox.common/src/org/eclipse/core/runtime/AdapterProxy.java diff --git a/bundles/org.eclipse.equinox.common/src/org/eclipse/core/runtime/AdapterProxy.java b/bundles/org.eclipse.equinox.common/src/org/eclipse/core/runtime/AdapterProxy.java new file mode 100644 index 00000000000..0bb9274214f --- /dev/null +++ b/bundles/org.eclipse.equinox.common/src/org/eclipse/core/runtime/AdapterProxy.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2025 Christoph Läubrich and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.runtime; + +import org.osgi.annotation.versioning.ConsumerType; + +/** + *

+ * An {@link AdapterProxy} can be used to interface the Eclipse Adapter + * Framework with other techniques. To do so one has to provide a generic + * {@link IAdapterFactory} that adapts this other frameworks objects to the + * {@link AdapterProxy} interface, then as a last resort, the Eclipse Adapter + * Framework will ask this proxy as if the original object would have + * implemented {@link IAdaptable}. + *

+ *

+ * One example is the OSGi Converter + * Specification that allows to adapt/convert objects in an extensible way, + * therefore it is not possible to register a "classic" {@link IAdapterFactory} + * because the types that are probably convertible are unknown in advance. Also + * the objects itself can't be made to implement the {@link IAdaptable} + * interface. An implementation then might look like this: + *

+ * + *
+ * @Component
+ * @AdapterTypes(adaptableClass = Object.class, adapterNames = AdapterProxy.class)
+ * public class OSGiConverterProxyFactory implements IAdapterFactory {
+ * 
+ * 	@Reference
+ * 	private Converter converter;
+ * 
+ * 	public  T getAdapter(Object adaptableObject, Class adapterType) {
+ * 		Converting converting = converter.convert(adaptableObject);
+ * 		return converting.to(adapterType);
+ * 	}
+ * 
+ * }
+ * 
+ * + * @since 3.20 + */ +@ConsumerType +public interface AdapterProxy extends IAdaptable { + // This is a specialized type that do not define any methods +} diff --git a/bundles/org.eclipse.equinox.common/src/org/eclipse/core/runtime/Adapters.java b/bundles/org.eclipse.equinox.common/src/org/eclipse/core/runtime/Adapters.java index a3268aa0c40..51f9e9b0593 100644 --- a/bundles/org.eclipse.equinox.common/src/org/eclipse/core/runtime/Adapters.java +++ b/bundles/org.eclipse.equinox.common/src/org/eclipse/core/runtime/Adapters.java @@ -82,6 +82,13 @@ public static T adapt(Object sourceObject, Class adapter, boolean allowAc String adapterId = adapter.getName(); Object result = queryAdapterManager(sourceObject, adapterId, allowActivation); + if (result == null) { + // Last resort, this object is maybe using a different adaption technique + if (queryAdapterManager(sourceObject, AdapterProxy.class.getName(), + allowActivation) instanceof AdapterProxy proxy) { + result = proxy.getAdapter(adapter); + } + } if (result != null) { // Sanity-check if (!adapter.isInstance(result)) {