diff --git a/update/org.eclipse.update.configurator.tests/META-INF/MANIFEST.MF b/update/org.eclipse.update.configurator.tests/META-INF/MANIFEST.MF index 8055e8a6da0..dc96ac8a45c 100644 --- a/update/org.eclipse.update.configurator.tests/META-INF/MANIFEST.MF +++ b/update/org.eclipse.update.configurator.tests/META-INF/MANIFEST.MF @@ -14,4 +14,5 @@ Export-Package: org.eclipse.update.configurator.tests, org.eclipse.update.internal.configurator.tests Eclipse-BundleShape: dir Import-Package: org.junit.jupiter.api;version="[5.14.0,6.0.0)", + org.junit.jupiter.api.io;version="[5.14.0,6.0.0)", org.junit.platform.suite.api;version="[1.14.0,2.0.0)" diff --git a/update/org.eclipse.update.configurator.tests/src/org/eclipse/update/configurator/tests/AutomatedConfiguratorSuite.java b/update/org.eclipse.update.configurator.tests/src/org/eclipse/update/configurator/tests/AutomatedConfiguratorSuite.java index f0f8abd84fd..6c6e2cbaf54 100644 --- a/update/org.eclipse.update.configurator.tests/src/org/eclipse/update/configurator/tests/AutomatedConfiguratorSuite.java +++ b/update/org.eclipse.update.configurator.tests/src/org/eclipse/update/configurator/tests/AutomatedConfiguratorSuite.java @@ -14,6 +14,7 @@ package org.eclipse.update.configurator.tests; import org.eclipse.update.internal.configurator.tests.FeatureEntryTests; +import org.eclipse.update.internal.configurator.tests.SiteEntryTests; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.Suite; @@ -25,6 +26,7 @@ @Suite @SelectClasses({ // FeatureEntryTests.class, // + SiteEntryTests.class, // }) public class AutomatedConfiguratorSuite { diff --git a/update/org.eclipse.update.configurator.tests/src/org/eclipse/update/internal/configurator/tests/SiteEntryTests.java b/update/org.eclipse.update.configurator.tests/src/org/eclipse/update/internal/configurator/tests/SiteEntryTests.java new file mode 100644 index 00000000000..f50599aa16a --- /dev/null +++ b/update/org.eclipse.update.configurator.tests/src/org/eclipse/update/internal/configurator/tests/SiteEntryTests.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright (c) 2026 Lars Vogel 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: + * Lars Vogel - initial API and implementation + *******************************************************************************/ +package org.eclipse.update.internal.configurator.tests; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.jar.Attributes; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; + +import org.eclipse.update.internal.configurator.Configuration; +import org.eclipse.update.internal.configurator.FeatureEntry; +import org.eclipse.update.internal.configurator.PluginEntry; +import org.eclipse.update.internal.configurator.SiteEntry; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +@SuppressWarnings("restriction") +public class SiteEntryTests { + + @TempDir + Path siteRoot; + + @Test + public void testLoadFromDiskDetectsFeaturesWithoutScanningPlugins() throws Exception { + createFeature("test.feature", "1.0.0"); + Path pluginJar = createPluginJar("test.plugin", "1.0.0"); + + SiteEntry site = createSite(); + site.loadFromDisk(0); + + FeatureEntry[] features = site.getFeatureEntries(); + assertEquals(1, features.length); + assertEquals("test.feature", features[0].getFeatureIdentifier()); + + // the jar is untouched so far, deleting it now leaves an eager scan nothing to have found + Files.delete(pluginJar); + assertEquals(0, site.getAllPluginEntries().length); + } + + @Test + public void testPluginsAreDetectedOnFirstAccess() throws Exception { + createFeature("test.feature", "1.0.0"); + createPluginJar("test.plugin", "1.0.0"); + + SiteEntry site = createSite(); + site.loadFromDisk(0); + + PluginEntry[] plugins = site.getAllPluginEntries(); + assertEquals(1, plugins.length); + assertEquals("test.plugin", plugins[0].getPluginIdentifier()); + assertEquals("1.0.0", plugins[0].getPluginVersion()); + } + + private SiteEntry createSite() throws Exception { + SiteEntry site = new SiteEntry(siteRoot.toUri().toURL()); + site.setConfig(new Configuration()); + return site; + } + + private void createFeature(String id, String version) throws Exception { + Path featureDir = Files.createDirectories(siteRoot.resolve("features").resolve(id + "_" + version)); + Files.writeString(featureDir.resolve("feature.xml"), "\n" // + + "\n"); + } + + private Path createPluginJar(String id, String version) throws Exception { + Path pluginsDir = Files.createDirectories(siteRoot.resolve("plugins")); + Path jar = pluginsDir.resolve(id + "_" + version + ".jar"); + Manifest manifest = new Manifest(); + Attributes attributes = manifest.getMainAttributes(); + attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0"); + attributes.putValue("Bundle-ManifestVersion", "2"); + attributes.putValue("Bundle-SymbolicName", id); + attributes.putValue("Bundle-Version", version); + try (OutputStream out = Files.newOutputStream(jar); JarOutputStream jarOut = new JarOutputStream(out, manifest)) { + // the manifest written by the stream is all the detection needs + } + return jar; + } +} diff --git a/update/org.eclipse.update.configurator/src/org/eclipse/update/internal/configurator/SiteEntry.java b/update/org.eclipse.update.configurator/src/org/eclipse/update/internal/configurator/SiteEntry.java index 26661f79aa8..9761210ed74 100644 --- a/update/org.eclipse.update.configurator/src/org/eclipse/update/internal/configurator/SiteEntry.java +++ b/update/org.eclipse.update.configurator/src/org/eclipse/update/internal/configurator/SiteEntry.java @@ -674,7 +674,7 @@ public void loadFromDisk(long lastChange) throws CoreException{ featuresChangeStamp = lastChange; pluginsChangeStamp = lastChange; detectFeatures(); - detectPlugins(); + // plugins are detected on first access, the scan opens every jar on the site } /**