diff --git a/bundles/org.eclipse.equinox.common/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.common/META-INF/MANIFEST.MF
index 47c4a0c9639..407924c2836 100644
--- a/bundles/org.eclipse.equinox.common/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.common/META-INF/MANIFEST.MF
@@ -16,6 +16,7 @@ Export-Package: org.eclipse.core.internal.boot;x-friends:="org.eclipse.core.reso
org.eclipse.equinox.security",
org.eclipse.core.runtime;common=split;version="3.7.0";mandatory:=common,
org.eclipse.core.text;version="3.13.0",
+ org.eclipse.equinox.common.identity;x-internal:=true,
org.eclipse.equinox.events;version="1.0.0"
Bundle-Vendor: %providerName
Bundle-Activator: org.eclipse.core.internal.runtime.Activator
diff --git a/bundles/org.eclipse.equinox.common/src/org/eclipse/equinox/common/identity/BundleIdentity.java b/bundles/org.eclipse.equinox.common/src/org/eclipse/equinox/common/identity/BundleIdentity.java
new file mode 100644
index 00000000000..d2991747065
--- /dev/null
+++ b/bundles/org.eclipse.equinox.common/src/org/eclipse/equinox/common/identity/BundleIdentity.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2024 ArSysOp.
+ *
+ * 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:
+ * Alexander Fedorov (ArSysOp) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.common.identity;
+
+/**
+ *
+ * Bundle-SymbolicName to be used as qualifier
+ *
+ * @see BundleIdentityRecord
+ * @see ContributionIdentity
+ */
+public interface BundleIdentity {
+
+ /**
+ * Bundle-SymbolicName value
+ *
+ * @return bundle symbolic name
+ */
+ String symbolic();
+
+}
diff --git a/bundles/org.eclipse.equinox.common/src/org/eclipse/equinox/common/identity/BundleIdentityRecord.java b/bundles/org.eclipse.equinox.common/src/org/eclipse/equinox/common/identity/BundleIdentityRecord.java
new file mode 100644
index 00000000000..5a331315bd7
--- /dev/null
+++ b/bundles/org.eclipse.equinox.common/src/org/eclipse/equinox/common/identity/BundleIdentityRecord.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2024 ArSysOp.
+ *
+ * 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:
+ * Alexander Fedorov (ArSysOp) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.common.identity;
+
+/**
+ * Default implementation for {@link BundleIdentity}
+ */
+public record BundleIdentityRecord(String symbolic) implements BundleIdentity {
+
+}
diff --git a/bundles/org.eclipse.equinox.common/src/org/eclipse/equinox/common/identity/ContributionIdentity.java b/bundles/org.eclipse.equinox.common/src/org/eclipse/equinox/common/identity/ContributionIdentity.java
new file mode 100644
index 00000000000..d7752adf8a2
--- /dev/null
+++ b/bundles/org.eclipse.equinox.common/src/org/eclipse/equinox/common/identity/ContributionIdentity.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2024 ArSysOp.
+ *
+ * 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:
+ * Alexander Fedorov (ArSysOp) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.common.identity;
+
+/**
+ *
+ * Identifies string in a manifest like plugin.xml that should
+ * match string in another manifest or in Java code
+ */
+public interface ContributionIdentity {
+
+ /**
+ * Required to match historical contributions defined by a key only
+ */
+ BundleIdentity HISTORICAL = new BundleIdentity() {
+
+ @Override
+ public String symbolic() {
+ return ""; //$NON-NLS-1$
+ }
+ };
+
+ /**
+ * The identity of contributing bundle, typically a part of
+ * {@link ContributionIdentity#id()}
+ *
+ * @return contributing bundle identity
+ */
+ BundleIdentity bundle();
+
+ /**
+ * The key of contribution, typically a part of
+ * {@link ContributionIdentity#id()}
+ *
+ * @return key of contribution
+ */
+ String key();
+
+ /**
+ * Full qualified id of this contribution, typically contains both
+ * {@link BundleIdentity#symbolic()} and {@link ContributionIdentity#key()}
+ *
+ * @return full qualified id
+ */
+ String id();
+
+}
diff --git a/bundles/org.eclipse.equinox.common/src/org/eclipse/equinox/common/identity/CreateResourceUrl.java b/bundles/org.eclipse.equinox.common/src/org/eclipse/equinox/common/identity/CreateResourceUrl.java
new file mode 100644
index 00000000000..bf82bca6c4f
--- /dev/null
+++ b/bundles/org.eclipse.equinox.common/src/org/eclipse/equinox/common/identity/CreateResourceUrl.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2024 ArSysOp.
+ *
+ * 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:
+ * Alexander Fedorov (ArSysOp) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.common.identity;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.MissingResourceException;
+import java.util.Objects;
+
+/**
+ * Provides an URL with "platform" schema to be used for resource access.
+ *
+ * ImageIdentity EXAMPLE + * ImageRegistry registry + * registry.put(EXAMPLE.id(), ImageDescriptor.createFromURL(new CreateResourceUrl(EXAMPLE).get())); + * ... + * Image image = registry.get(EXAMPLE.id()); + * * + *+ * + * EMF usage: + * + *
+ * ImageIdentity EXAMPLE
+ *
+ * public Object getImage(Object object) {
+ * return overlayImage(object, new CreateResourceUrl(EXAMPLE).get());
+ * }
+ *
+ *
+ */
+public final class CreateResourceUrl {
+
+ private final String raw;
+
+ public CreateResourceUrl(ResourceUrl identity) {
+ this(identity.url());
+ }
+
+ public CreateResourceUrl(String raw) {
+ this.raw = Objects.requireNonNull(raw);
+ }
+
+ /**
+ * Returns an {@link URL} to access given {@link ResourceUrl}
+ *
+ * @return {@link URL} to access resource
+ * @throws MissingResourceException in case of malformed URL
+ */
+ public URL get() throws MissingResourceException {
+ try {
+ return new URL(raw);
+ } catch (MalformedURLException e) {
+ throw new MissingResourceException("Invalid resource url specification", getClass().getName(), raw); //$NON-NLS-1$
+ }
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.common/src/org/eclipse/equinox/common/identity/ImageIdentity.java b/bundles/org.eclipse.equinox.common/src/org/eclipse/equinox/common/identity/ImageIdentity.java
new file mode 100644
index 00000000000..d11a4192124
--- /dev/null
+++ b/bundles/org.eclipse.equinox.common/src/org/eclipse/equinox/common/identity/ImageIdentity.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2024 ArSysOp.
+ *
+ * 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:
+ * Alexander Fedorov (ArSysOp) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.common.identity;
+
+/**
+ * Identify an image for further reuse in
+ *
+ * public static final ImageIdentity EXAMPLE = new ImageIdentityRecord(//
+ * new BundleIdentityRecord("org.examples.resources"), //
+ * "icons/full/obj16/example.png", //
+ * "example");
+ *
+ *
+ */
+public record ImageIdentityRecord(BundleIdentity bundle, String path, String key) implements ImageIdentity {
+
+ @Override
+ public String id() {
+ return bundle.symbolic() + ".image." + key; //$NON-NLS-1$
+ }
+
+ @Override
+ public String url() {
+ return "platform:/plugin/" + bundle.symbolic() + "/$nl$/" + path; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.common/src/org/eclipse/equinox/common/identity/ResourceUrl.java b/bundles/org.eclipse.equinox.common/src/org/eclipse/equinox/common/identity/ResourceUrl.java
new file mode 100644
index 00000000000..fda9143ae7c
--- /dev/null
+++ b/bundles/org.eclipse.equinox.common/src/org/eclipse/equinox/common/identity/ResourceUrl.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2024 ArSysOp.
+ *
+ * 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:
+ * Alexander Fedorov (ArSysOp) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.common.identity;
+
+/**
+ * Allows to work with resources (like images) from headless code
+ *
+ * @see ImageIdentity
+ *
+ */
+public interface ResourceUrl {
+
+ /**
+ * An URL to access the resource, most probably with "platform" schema
+ *
+ * @return an URL to access the resource
+ */
+ String url();
+
+}