From 3d397966eb3be9a8bdd5c205da571ca8c60a1f8e Mon Sep 17 00:00:00 2001 From: Peter Palaga Date: Wed, 29 Jul 2020 15:19:14 +0200 Subject: [PATCH] Fix #40 Cannot clean on Windows as long as mvnd keeps a plugin from the tree loaded --- .../org/apache/maven/cli/DaemonMavenCli.java | 4 +- .../fuse/mvnd/plugin/CliPluginRealmCache.java | 56 +++++++++++++++++++ .../fuse/mvnd/it/ModuleAndPluginNativeIT.java | 2 +- 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/daemon/src/main/java/org/apache/maven/cli/DaemonMavenCli.java b/daemon/src/main/java/org/apache/maven/cli/DaemonMavenCli.java index 41038e31..74a5f0f2 100644 --- a/daemon/src/main/java/org/apache/maven/cli/DaemonMavenCli.java +++ b/daemon/src/main/java/org/apache/maven/cli/DaemonMavenCli.java @@ -416,13 +416,14 @@ public class DaemonMavenCli { // } final CoreExports exports = new CoreExports(containerRealm, exportedArtifacts, exportedPackages); + final CliPluginRealmCache realmCache = new CliPluginRealmCache(); container = new DefaultPlexusContainer(cc, new AbstractModule() { @Override protected void configure() { bind(ILoggerFactory.class).toInstance(slf4jLoggerFactory); bind(CoreExports.class).toInstance(exports); - bind(PluginRealmCache.class).toInstance(new CliPluginRealmCache()); + bind(PluginRealmCache.class).toInstance(realmCache); } }); @@ -440,6 +441,7 @@ public class DaemonMavenCli { // container.getLoggerManager().setThresholds( cliRequest.request.getLoggingLevel() ); eventSpyDispatcher = container.lookup(EventSpyDispatcher.class); + eventSpyDispatcher.getEventSpies().add(realmCache.asEventSpy()); maven = container.lookup(Maven.class); diff --git a/daemon/src/main/java/org/jboss/fuse/mvnd/plugin/CliPluginRealmCache.java b/daemon/src/main/java/org/jboss/fuse/mvnd/plugin/CliPluginRealmCache.java index 57ee458f..386f8c3f 100644 --- a/daemon/src/main/java/org/jboss/fuse/mvnd/plugin/CliPluginRealmCache.java +++ b/daemon/src/main/java/org/jboss/fuse/mvnd/plugin/CliPluginRealmCache.java @@ -20,9 +20,12 @@ package org.jboss.fuse.mvnd.plugin; import java.io.File; import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.nio.file.StandardWatchEventKinds; import java.nio.file.WatchEvent; import java.nio.file.WatchEvent.Kind; @@ -32,6 +35,7 @@ import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.FileTime; import java.util.ArrayList; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -45,6 +49,9 @@ import javax.inject.Named; import javax.inject.Singleton; import org.apache.maven.RepositoryUtils; import org.apache.maven.artifact.Artifact; +import org.apache.maven.eventspy.EventSpy; +import org.apache.maven.execution.MavenExecutionRequest; +import org.apache.maven.execution.MavenExecutionResult; import org.apache.maven.model.Plugin; import org.apache.maven.plugin.PluginRealmCache; import org.apache.maven.project.MavenProject; @@ -427,6 +434,51 @@ public class CliPluginRealmCache private static final Logger log = LoggerFactory.getLogger(CliPluginRealmCache.class); protected final Map cache = new ConcurrentHashMap<>(); private final RecordValidator watcher; + private final EventSpy eventSpy = new EventSpy() { + + private Path multiModuleProjectDirectory; + + @Override + public void onEvent(Object event) throws Exception { + try { + if (event instanceof MavenExecutionRequest) { + /* Store the multiModuleProjectDirectory path */ + multiModuleProjectDirectory = ((MavenExecutionRequest) event).getMultiModuleProjectDirectory().toPath() + .toRealPath(); + } else if (event instanceof MavenExecutionResult) { + /* Evict the entries refering to jars under multiModuleProjectDirectory */ + final Iterator> i = cache.entrySet().iterator(); + while (i.hasNext()) { + final Entry entry = i.next(); + final ValidableCacheRecord record = entry.getValue(); + for (URL url : record.getRealm().getURLs()) { + if (url.getProtocol().equals("file")) { + final Path path = Paths.get(url.toURI()).toRealPath(); + if (path.startsWith(multiModuleProjectDirectory)) { + log.debug( + "Removing PluginRealmCache entry {} because it refers to an artifact in the build tree {}", + entry.getKey(), path); + record.dispose(); + i.remove(); + break; + } + } + } + } + } + } catch (Exception e) { + log.warn("Could not notify CliPluginRealmCache", e); + } + } + + @Override + public void init(Context context) throws Exception { + } + + @Override + public void close() throws Exception { + } + }; public CliPluginRealmCache() { this.watcher = System.getProperty("os.name").toLowerCase().contains("mac") @@ -488,4 +540,8 @@ public class CliPluginRealmCache flush(); } + public EventSpy asEventSpy() { + return eventSpy; + } + } diff --git a/integration-tests/src/test/java/org/jboss/fuse/mvnd/it/ModuleAndPluginNativeIT.java b/integration-tests/src/test/java/org/jboss/fuse/mvnd/it/ModuleAndPluginNativeIT.java index 0c127b23..7bc01fa3 100644 --- a/integration-tests/src/test/java/org/jboss/fuse/mvnd/it/ModuleAndPluginNativeIT.java +++ b/integration-tests/src/test/java/org/jboss/fuse/mvnd/it/ModuleAndPluginNativeIT.java @@ -74,7 +74,7 @@ public class ModuleAndPluginNativeIT { final ClientOutput output = Mockito.mock(ClientOutput.class); client.execute(output, - // "clean", workaround for https://github.com/mvndaemon/mvnd/issues/40 + "clean", "install", "-e", "-Dmvnd.log.level=DEBUG").assertSuccess(); Assertions.assertThat(helloPath).exists();