Merge pull request #4630 from sdedic/maven/lifecycle-participants

Allow to disable warning for specific lifecycle participants.
diff --git a/enterprise/micronaut/nbproject/project.xml b/enterprise/micronaut/nbproject/project.xml
index e548c58..b6fbd84 100644
--- a/enterprise/micronaut/nbproject/project.xml
+++ b/enterprise/micronaut/nbproject/project.xml
@@ -74,7 +74,7 @@
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>2</release-version>
-                        <specification-version>2.154</specification-version>
+                        <specification-version>2.156</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
diff --git a/enterprise/micronaut/src/org/netbeans/modules/micronaut/resources/layer.xml b/enterprise/micronaut/src/org/netbeans/modules/micronaut/resources/layer.xml
index c69d3bb..e542a83 100644
--- a/enterprise/micronaut/src/org/netbeans/modules/micronaut/resources/layer.xml
+++ b/enterprise/micronaut/src/org/netbeans/modules/micronaut/resources/layer.xml
@@ -59,6 +59,14 @@
                     </file>
                 </folder>
             </folder>
+            <folder name="LifecycleParticipants">
+                <folder name="org.graalvm.buildtools.maven.NativeExtension">
+                    <attr name="ignoreOnModelLoad" boolvalue="true"/>
+                </folder>
+                <folder name="io.micronaut.build.testresources.TestResourcesLifecycleExtension">
+                    <attr name="ignoreOnModelLoad" boolvalue="true"/>
+                </folder>
+            </folder>
         </folder>
     </folder>
     <folder name="Templates">
diff --git a/java/maven/apichanges.xml b/java/maven/apichanges.xml
index 7335b70..3b2f5a3 100644
--- a/java/maven/apichanges.xml
+++ b/java/maven/apichanges.xml
@@ -83,6 +83,19 @@
     <!-- ACTUAL CHANGES BEGIN HERE: -->
 
     <changes>
+        <change id="lifecycle-white-list">
+            <api name="general"/>
+            <summary>LifecycleParticipants can be ignored</summary>
+            <version major="2" minor="156"/>
+            <date day="9" month="9" year="2022"/>
+            <author login="sdedic"/>
+            <compatibility addition="yes" semantic="compatible"/>
+            <description>
+                NetBeans warns if a project / plugin provides AbstractLifecycleParticipants that
+                can reconfigure the project after load. Now some harmless ones can be whitelisted
+                so they do not produce warning / project problem. See <a href="@TOP@/architecture-summary.html#layer-LifecycleParticipants">LifecycleParticipants</a>.
+            </description>
+        </change>
         <change id="evaluated-project">
             <api name="general"/>
             <summary>Project model can be customized for specific action or usage</summary>
diff --git a/java/maven/arch.xml b/java/maven/arch.xml
index 8827e43..90197a0 100644
--- a/java/maven/arch.xml
+++ b/java/maven/arch.xml
@@ -140,6 +140,14 @@
        It's content is expected to be <code>Action</code> instances.
      </p>
     </api>
+    <api group="layer" name="LifecycleParticipants" type="export" category="official">
+     <p>
+         A module can disable warning for a custom lifecycle participant by creating a <b>folder</b> in 
+         <code>Projects/org-netbeans-modules-maven/LifecycleParticipant</code>. Currently single boolean attribute,
+         <code>ignoreOnModelLoad</code> is supported, which suppresses project problem and warning about
+         the custom participant. The participant's code does not run after project load.         
+     </p>
+    </api>
 
     <api group="layer" name="MavenArchetypes" type="export" category="official">
      <p>
diff --git a/java/maven/nbproject/project.properties b/java/maven/nbproject/project.properties
index b835cee..eaeea26 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.155
+spec.version.base: 2.156
 
 # The CPExtender test fails in library processing (not randomly) since NetBeans 8.2; disabling.
 test.excludes=**/CPExtenderTest.class
diff --git a/java/maven/src/org/netbeans/modules/maven/layer.xml b/java/maven/src/org/netbeans/modules/maven/layer.xml
index 013037a..b23427b 100644
--- a/java/maven/src/org/netbeans/modules/maven/layer.xml
+++ b/java/maven/src/org/netbeans/modules/maven/layer.xml
@@ -170,6 +170,12 @@
                     <attr name="position" intvalue="3200"/>
                 </file>
             </folder>
+            <folder name="LifecycleParticipants">
+                <!-- Lifecycle participant classes with special handling; folders with attributes -->
+                <folder name="org.sonatype.nexus.maven.staging.deploy.DeployLifecycleParticipant">
+                    <attr name="ignoreOnModelLoad" boolvalue="true"/>
+                </folder>
+            </folder>
             <file name="nbactions.xml" url="nbactions.xml"/>
         </folder>
     </folder>
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 4029d8b..65b5660 100644
--- a/java/maven/src/org/netbeans/modules/maven/modelcache/MavenProjectCache.java
+++ b/java/maven/src/org/netbeans/modules/maven/modelcache/MavenProjectCache.java
@@ -25,12 +25,10 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
-import java.util.Set;
 import java.util.WeakHashMap;
 import java.util.function.BiConsumer;
 import java.util.logging.Level;
@@ -45,6 +43,7 @@
 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.NbMavenProject;
 import org.netbeans.modules.maven.api.execute.RunConfig;
 import org.netbeans.modules.maven.configurations.M2Configuration;
 import org.netbeans.modules.maven.embedder.EmbedderFactory;
@@ -68,9 +67,15 @@
     private static final String CONTEXT_EXECUTION_RESULT = "NB_Execution_Result";
     private static final String CONTEXT_PARTICIPANTS = "NB_AbstractParticipant_Present";
     
-    private static final Set<String> PARTICIPANT_WHITELIST = new HashSet<String>(Arrays.asList(new String[] {
-        "org.sonatype.nexus.maven.staging.deploy.DeployLifecycleParticipant"
-    }));
+    /**
+     * Folder with module-configurable whitelist of lifecycle participants. Currently only 'ignore' can be specified.
+     */
+    private static final String LIFECYCLE_PARTICIPANT_PREFIX = "Projects/" + NbMavenProject.TYPE + "/LifecycleParticipants/"; // NOI18N
+    
+    /**
+     * Attribute that specifies the lifecycle participant should be silently ignored on model load.
+     */
+    private static final String ATTR_IGNORE_ON_LOAD = "ignoreOnModelLoad"; // NOI18N
     
     //File is referenced during lifetime of the Project. FileObject cannot be used as with rename it changes value@!!!
     private static final Map<File, WeakReference<MavenProject>> file2Project = new WeakHashMap<File, WeakReference<MavenProject>>();
@@ -151,6 +156,12 @@
         return loadOriginalMavenProject(pomFile, null, null);
     }
     
+    private static boolean isLifecycleParticipatnIgnored(AbstractMavenLifecycleParticipant instance) {
+        String n = instance.getClass().getName();
+        FileObject check = FileUtil.getConfigFile(LIFECYCLE_PARTICIPANT_PREFIX + n);
+        return check != null && check.getAttribute(ATTR_IGNORE_ON_LOAD) == Boolean.TRUE;
+    }
+    
     private static @NonNull MavenProject loadOriginalMavenProject(final File pomFile, ProjectActionContext ctx, RunConfig runConf) {
         long startLoading = System.currentTimeMillis();
         MavenEmbedder projectEmbedder = EmbedderFactory.getProjectEmbedder();
@@ -283,11 +294,11 @@
 //                            } else {
                                 List<String> parts = new ArrayList<String>();
                                 for (AbstractMavenLifecycleParticipant part : lookup) {
-                                    String name = part.getClass().getName();
-                                    if (PARTICIPANT_WHITELIST.contains(name)) {
+                                    if (isLifecycleParticipatnIgnored(part)) {
                                         //#204898 create a whitelist of known not harmful participants that can be just ignored
                                         continue;
                                     }
+                                    String name = part.getClass().getName();
                                     parts.add(name);
                                 }
                                 if (parts.size() > 0) {