Allow to customize project models for actions.
diff --git a/java/maven/apichanges.xml b/java/maven/apichanges.xml
index 4616ee1..7335b70 100644
--- a/java/maven/apichanges.xml
+++ b/java/maven/apichanges.xml
@@ -83,6 +83,20 @@
<!-- ACTUAL CHANGES BEGIN HERE: -->
<changes>
+ <change id="evaluated-project">
+ <api name="general"/>
+ <summary>Project model can be customized for specific action or usage</summary>
+ <version major="2" minor="155"/>
+ <date day="10" month="8" year="2022"/>
+ <author login="sdedic"/>
+ <compatibility addition="yes" semantic="compatible"/>
+ <description>
+ Project state can be inspected with respect to an intended action to be run or used, and possible
+ customized properties or profiles. This allows clients to more precisely follow customizations in
+ the project file and/or action mapping that would be applied when actually using project actions.
+ </description>
+ <class package="org.netbeans.modules.maven.api" name="NbMavenProject"/>
+ </change>
<change id="plugin.conf.paths">
<api name="general"/>
<summary>Added helper method to get artifact paths from build plugin configurations.</summary>
diff --git a/java/maven/nbproject/project.properties b/java/maven/nbproject/project.properties
index d787680..b835cee 100644
--- a/java/maven/nbproject/project.properties
+++ b/java/maven/nbproject/project.properties
@@ -22,7 +22,7 @@
javadoc.arch=${basedir}/arch.xml
javahelp.hs=maven.hs
extra.module.files=maven-nblib/
-spec.version.base: 2.154
+spec.version.base: 2.155
# The CPExtender test fails in library processing (not randomly) since NetBeans 8.2; disabling.
test.excludes=**/CPExtenderTest.class
diff --git a/java/maven/nbproject/project.xml b/java/maven/nbproject/project.xml
index e848bd1..df8df16 100644
--- a/java/maven/nbproject/project.xml
+++ b/java/maven/nbproject/project.xml
@@ -316,7 +316,7 @@
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
- <specification-version>1.80</specification-version>
+ <specification-version>1.89</specification-version>
</run-dependency>
</dependency>
<dependency>
diff --git a/java/maven/src/org/netbeans/modules/maven/NbMavenProjectImpl.java b/java/maven/src/org/netbeans/modules/maven/NbMavenProjectImpl.java
index 1d303f0..fe895eb 100644
--- a/java/maven/src/org/netbeans/modules/maven/NbMavenProjectImpl.java
+++ b/java/maven/src/org/netbeans/modules/maven/NbMavenProjectImpl.java
@@ -43,6 +43,7 @@
import java.util.Map;
import java.util.Properties;
import java.util.Set;
+import java.util.WeakHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
@@ -69,12 +70,14 @@
import org.netbeans.api.annotations.common.NullUnknown;
import org.netbeans.api.java.project.classpath.ProjectClassPathModifier;
import org.netbeans.api.project.Project;
+import org.netbeans.api.project.ProjectActionContext;
import org.netbeans.api.queries.VisibilityQuery;
import org.netbeans.modules.maven.api.Constants;
import org.netbeans.modules.maven.api.FileUtilities;
import org.netbeans.modules.maven.api.NbMavenProject;
import org.netbeans.modules.maven.api.PluginPropertyUtils;
import org.netbeans.modules.maven.api.execute.ActiveJ2SEPlatformProvider;
+import org.netbeans.modules.maven.api.execute.RunConfig;
import org.netbeans.modules.maven.configurations.M2ConfigProvider;
import org.netbeans.modules.maven.configurations.M2Configuration;
import org.netbeans.modules.maven.configurations.ProjectProfileHandlerImpl;
@@ -82,6 +85,7 @@
import org.netbeans.modules.maven.debug.MavenJPDAStart;
import org.netbeans.modules.maven.embedder.EmbedderFactory;
import org.netbeans.modules.maven.embedder.MavenEmbedder;
+import org.netbeans.modules.maven.execute.ActionToGoalUtils;
import org.netbeans.modules.maven.modelcache.MavenProjectCache;
import org.netbeans.modules.maven.options.MavenSettings;
import org.netbeans.modules.maven.problems.ProblemReporterImpl;
@@ -139,6 +143,7 @@
if (hardReferencingMavenProject) {
hardRefProject = prj;
}
+ projectVariants.clear();
}
ACCESSOR.doFireReload(watcher);
}
@@ -424,6 +429,48 @@
}
/**
+ * Variants of the projects, possibly other than the ones with the
+ * <b>active configuration</b>
+ */
+ private Map<ProjectActionContext, Reference<MavenProject>> projectVariants = new WeakHashMap<>();
+
+ public @NonNull MavenProject getEvaluatedProject(ProjectActionContext ctx) {
+ if (ctx == null) {
+ return getOriginalMavenProject();
+ }
+ ProjectActionContext stripped =
+ ProjectActionContext.newBuilder(ctx.getProject())
+ .withProfiles(ctx.getProfiles())
+ .withProperties(ctx.getProperties())
+ .context();
+ MavenProject result;
+
+ synchronized (this) {
+ Reference<MavenProject> ref = projectVariants.get(stripped);
+ if (ref != null) {
+ result = ref.get();
+ if (result != null) {
+ return result;
+ } else {
+ projectVariants.remove(stripped);
+ }
+ }
+ }
+ RunConfig runConf = null;
+ if (ctx != null && ctx.getProjectAction() != null) {
+ runConf = ActionToGoalUtils.createRunConfig(ctx.getProjectAction(), this, ctx.getConfiguration(), Lookup.EMPTY);
+ }
+ MavenProject newproject = MavenProjectCache.loadMavenProject(this.getPOMFile(), ctx, runConf);
+ synchronized (this) {
+ Reference<MavenProject> ref = projectVariants.get(stripped);
+ if (ref == null || ref.get() == null) {
+ projectVariants.put(stripped, new SoftReference<>(newproject));
+ }
+ }
+ return newproject;
+ }
+
+ /**
* a marginally unreliable, non blocking method for figuring if the model is loaded or not.
* @return
*/
diff --git a/java/maven/src/org/netbeans/modules/maven/api/NbMavenProject.java b/java/maven/src/org/netbeans/modules/maven/api/NbMavenProject.java
index f90deaf..ecb87cc 100644
--- a/java/maven/src/org/netbeans/modules/maven/api/NbMavenProject.java
+++ b/java/maven/src/org/netbeans/modules/maven/api/NbMavenProject.java
@@ -44,6 +44,7 @@
import org.netbeans.api.progress.aggregate.BasicAggregateProgressFactory;
import org.netbeans.api.progress.aggregate.ProgressContributor;
import org.netbeans.api.project.Project;
+import org.netbeans.api.project.ProjectActionContext;
import org.netbeans.modules.maven.NbMavenProjectImpl;
import static org.netbeans.modules.maven.api.Bundle.*;
import org.netbeans.modules.maven.embedder.EmbedderFactory;
@@ -287,6 +288,22 @@
}
/**
+ * Returns a project evaluated for a certain purpose. The while {@link #getMavenProject}
+ * works with the <b>active configuration</b> and does not apply any action-specific properties,
+ * this method tries to apply mappings, configurations, etc when loading the project model.
+ * <p>
+ * Note that loading an evaluated project may take significant time (comparable to loading
+ * the base project itself). The implementation might optimize if the passed context does not
+ * prescribe different profiles, properties etc than have been used for the default model.
+ *
+ * @param context the loading context
+ * @return evaluated project
+ */
+ public @NonNull MavenProject getEvaluatedProject(ProjectActionContext context) {
+ return project.getEvaluatedProject(context);
+ }
+
+ /**
* a marginally unreliable, non blocking method for figuring if the model is loaded or not.
* @return
*/
diff --git a/java/maven/src/org/netbeans/modules/maven/modelcache/MavenProjectCache.java b/java/maven/src/org/netbeans/modules/maven/modelcache/MavenProjectCache.java
index 8b507d5..4029d8b 100644
--- a/java/maven/src/org/netbeans/modules/maven/modelcache/MavenProjectCache.java
+++ b/java/maven/src/org/netbeans/modules/maven/modelcache/MavenProjectCache.java
@@ -43,11 +43,14 @@
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.api.project.ProjectActionContext;
import org.netbeans.modules.maven.M2AuxilaryConfigImpl;
+import org.netbeans.modules.maven.api.execute.RunConfig;
import org.netbeans.modules.maven.configurations.M2Configuration;
import org.netbeans.modules.maven.embedder.EmbedderFactory;
import org.netbeans.modules.maven.embedder.MavenEmbedder;
import org.netbeans.spi.project.AuxiliaryConfiguration;
+import org.netbeans.spi.project.ProjectConfiguration;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.Mutex;
@@ -113,6 +116,14 @@
return mp;
}
+ public static MavenProject loadMavenProject(final File pomFile, ProjectActionContext context, RunConfig runConf) {
+ if (context == null) {
+ return getMavenProject(pomFile, true);
+ } else {
+ return loadOriginalMavenProject(pomFile, context, runConf);
+ }
+ }
+
public static MavenExecutionResult getExecutionResult(MavenProject project) {
return (MavenExecutionResult) project.getContextValue(CONTEXT_EXECUTION_RESULT);
}
@@ -137,6 +148,10 @@
+ "Please file a bug report with details about your project and the IDE's log file.\n\n"
})
private static @NonNull MavenProject loadOriginalMavenProject(final File pomFile) {
+ return loadOriginalMavenProject(pomFile, null, null);
+ }
+
+ private static @NonNull MavenProject loadOriginalMavenProject(final File pomFile, ProjectActionContext ctx, RunConfig runConf) {
long startLoading = System.currentTimeMillis();
MavenEmbedder projectEmbedder = EmbedderFactory.getProjectEmbedder();
MavenProject newproject = null;
@@ -147,7 +162,16 @@
}
AuxiliaryConfiguration aux = new M2AuxilaryConfigImpl(projectDir, false);
ActiveConfigurationProvider config = new ActiveConfigurationProvider(projectDir, aux);
- M2Configuration active = config.getActiveConfiguration();
+ M2Configuration active;
+
+ active = config.getActiveConfiguration();
+ if (ctx != null && ctx.getConfiguration() != null) {
+ ProjectConfiguration cfg = ctx.getConfiguration();
+ if (cfg instanceof M2Configuration) {
+ active = (M2Configuration)cfg;
+ }
+ }
+
MavenExecutionResult res = null;
try {
List<String> mavenConfigOpts = Collections.emptyList();
@@ -174,6 +198,12 @@
addActiveProfiles.accept(opt, "--activate-profiles=");
}
}
+ if (runConf != null) {
+ req.addActiveProfiles(runConf.getActivatedProfiles());
+ }
+ if (ctx != null && ctx.getProfiles() != null) {
+ req.addActiveProfiles(new ArrayList<>(ctx.getProfiles()));
+ }
req.setPom(pomFile);
req.setNoSnapshotUpdates(true);
@@ -208,6 +238,17 @@
}
}
uprops.putAll(createUserPropsForProjectLoading(active.getProperties()));
+ if (ctx != null && ctx.getProperties() != null) {
+ for (String k : ctx.getProperties().keySet()) {
+ uprops.setProperty(k, ctx.getProperties().get(k));
+ }
+ }
+ if (runConf != null && runConf.getProperties() != null) {
+ Map<? extends String, ? extends String> props = runConf.getProperties();
+ for (String k : props.keySet()) {
+ uprops.setProperty(k, props.get(k));
+ }
+ }
req.setUserProperties(uprops);
res = projectEmbedder.readProjectWithDependencies(req, true);
newproject = res.getProject();