This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven.git


The following commit(s) were added to refs/heads/master by this push:
     new 52d453caf9 Complete Packaging in v4 api (#1451)
52d453caf9 is described below

commit 52d453caf92c939d758eada2d4bff393e3d91380
Author: Guillaume Nodet <gno...@gmail.com>
AuthorDate: Mon Mar 25 10:56:37 2024 +0100

    Complete Packaging in v4 api (#1451)
---
 .../main/java/org/apache/maven/api/Packaging.java  |  12 +-
 .../apache/maven/api/spi/PackagingProvider.java}   |  38 +-----
 .../internal/impl/DefaultPackagingRegistry.java    | 142 +++++++++++++++++++--
 3 files changed, 146 insertions(+), 46 deletions(-)

diff --git 
a/api/maven-api-core/src/main/java/org/apache/maven/api/Packaging.java 
b/api/maven-api-core/src/main/java/org/apache/maven/api/Packaging.java
index b64d1e0705..37d3ed61c8 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/Packaging.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Packaging.java
@@ -21,6 +21,7 @@ package org.apache.maven.api;
 import org.apache.maven.api.annotations.Experimental;
 import org.apache.maven.api.annotations.Immutable;
 import org.apache.maven.api.annotations.Nonnull;
+import org.apache.maven.api.model.PluginContainer;
 
 /**
  * Interface representing a Maven project packaging.
@@ -44,12 +45,19 @@ public interface Packaging extends ExtensibleEnum {
      */
     @Nonnull
     default Language language() {
-        return getType().getLanguage();
+        return type().getLanguage();
     }
 
     /**
      * The type of main artifact produced by this packaging.
      */
     @Nonnull
-    Type getType();
+    Type type();
+
+    /**
+     * Returns the binding to use specifically for this packaging.
+     * This will be merged to the default packaging definition.
+     */
+    @Nonnull
+    PluginContainer plugins();
 }
diff --git 
a/api/maven-api-core/src/main/java/org/apache/maven/api/Packaging.java 
b/api/maven-api-spi/src/main/java/org/apache/maven/api/spi/PackagingProvider.java
similarity index 53%
copy from api/maven-api-core/src/main/java/org/apache/maven/api/Packaging.java
copy to 
api/maven-api-spi/src/main/java/org/apache/maven/api/spi/PackagingProvider.java
index b64d1e0705..b1ef5b5e13 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/Packaging.java
+++ 
b/api/maven-api-spi/src/main/java/org/apache/maven/api/spi/PackagingProvider.java
@@ -16,40 +16,12 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.api;
+package org.apache.maven.api.spi;
 
+import org.apache.maven.api.Packaging;
+import org.apache.maven.api.annotations.Consumer;
 import org.apache.maven.api.annotations.Experimental;
-import org.apache.maven.api.annotations.Immutable;
-import org.apache.maven.api.annotations.Nonnull;
 
-/**
- * Interface representing a Maven project packaging.
- * <p>
- * TODO: define how to plug in new packaging definitions using the SPI.
- *   the packaging are currently defined by Maven 3 {@code 
Provider<LifecycleMapping>}
- *
- * @since 4.0.0
- */
 @Experimental
-@Immutable
-public interface Packaging extends ExtensibleEnum {
-    /**
-     * The packaging id.
-     */
-    @Nonnull
-    String id();
-
-    /**
-     * The language of this packaging.
-     */
-    @Nonnull
-    default Language language() {
-        return getType().getLanguage();
-    }
-
-    /**
-     * The type of main artifact produced by this packaging.
-     */
-    @Nonnull
-    Type getType();
-}
+@Consumer
+public interface PackagingProvider extends ExtensibleEnumProvider<Packaging> {}
diff --git 
a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultPackagingRegistry.java
 
b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultPackagingRegistry.java
index 2a5b8a63b5..4f1b9c4ed0 100644
--- 
a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultPackagingRegistry.java
+++ 
b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultPackagingRegistry.java
@@ -22,27 +22,53 @@ import javax.inject.Inject;
 import javax.inject.Named;
 import javax.inject.Singleton;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 import org.apache.maven.api.Packaging;
 import org.apache.maven.api.Type;
+import org.apache.maven.api.model.Dependency;
+import org.apache.maven.api.model.InputLocation;
+import org.apache.maven.api.model.InputSource;
+import org.apache.maven.api.model.Plugin;
+import org.apache.maven.api.model.PluginContainer;
+import org.apache.maven.api.model.PluginExecution;
 import org.apache.maven.api.services.PackagingRegistry;
 import org.apache.maven.api.services.TypeRegistry;
+import org.apache.maven.api.spi.PackagingProvider;
+import org.apache.maven.lifecycle.internal.DefaultLifecyclePluginAnalyzer;
 import org.apache.maven.lifecycle.mapping.LifecycleMapping;
+import org.apache.maven.lifecycle.mapping.LifecycleMojo;
+import org.apache.maven.lifecycle.mapping.LifecyclePhase;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * TODO: this is session scoped as SPI can contribute.
  */
 @Named
 @Singleton
-public class DefaultPackagingRegistry implements PackagingRegistry {
+public class DefaultPackagingRegistry
+        extends 
ExtensibleEnumRegistries.DefaultExtensibleEnumRegistry<Packaging, 
PackagingProvider>
+        implements PackagingRegistry {
+
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(DefaultPackagingRegistry.class);
+
     private final Map<String, LifecycleMapping> lifecycleMappings;
 
     private final TypeRegistry typeRegistry;
 
     @Inject
-    public DefaultPackagingRegistry(Map<String, LifecycleMapping> 
lifecycleMappings, TypeRegistry typeRegistry) {
+    public DefaultPackagingRegistry(
+            Map<String, LifecycleMapping> lifecycleMappings,
+            TypeRegistry typeRegistry,
+            List<PackagingProvider> providers) {
+        super(providers);
         this.lifecycleMappings = lifecycleMappings;
         this.typeRegistry = typeRegistry;
     }
@@ -57,17 +83,111 @@ public class DefaultPackagingRegistry implements 
PackagingRegistry {
         if (type == null) {
             return Optional.empty();
         }
+        return Optional.of(new DefaultPackaging(id, type, 
getPlugins(lifecycleMapping)));
+    }
 
-        return Optional.of(new Packaging() {
-            @Override
-            public String id() {
-                return id;
-            }
+    private PluginContainer getPlugins(LifecycleMapping lifecycleMapping) {
+        Map<String, Plugin> plugins = new HashMap<>();
+        lifecycleMapping.getLifecycles().forEach((id, lifecycle) -> lifecycle
+                .getLifecyclePhases()
+                .forEach((phase, lifecyclePhase) -> 
parseLifecyclePhaseDefinitions(plugins, phase, lifecyclePhase)));
+        return PluginContainer.newBuilder().plugins(plugins.values()).build();
+    }
+
+    private void parseLifecyclePhaseDefinitions(Map<String, Plugin> plugins, 
String phase, LifecyclePhase goals) {
+        InputSource inputSource =
+                new 
InputSource(DefaultLifecyclePluginAnalyzer.DEFAULTLIFECYCLEBINDINGS_MODELID, 
null);
+        InputLocation location = new InputLocation(-1, -1, inputSource, 0);
+
+        List<LifecycleMojo> mojos = goals.getMojos();
+        if (mojos != null) {
+            for (int i = 0; i < mojos.size(); i++) {
+                LifecycleMojo mojo = mojos.get(i);
+
+                // Compute goal coordinates
+                String groupId, artifactId, version, goal;
+                String[] p = mojo.getGoal().trim().split(":");
+                if (p.length == 3) {
+                    // <groupId>:<artifactId>:<goal>
+                    groupId = p[0];
+                    artifactId = p[1];
+                    version = null;
+                    goal = p[2];
+                } else if (p.length == 4) {
+                    // <groupId>:<artifactId>:<version>:<goal>
+                    groupId = p[0];
+                    artifactId = p[1];
+                    version = p[2];
+                    goal = p[3];
+                } else {
+                    // invalid
+                    LOGGER.warn(
+                            "Ignored invalid goal specification '{}' from 
lifecycle mapping for phase {}",
+                            mojo.getGoal(),
+                            phase);
+                    continue;
+                }
+
+                String key = groupId + ":" + artifactId;
+
+                // Build plugin
+                List<PluginExecution> execs = new ArrayList<>();
+                List<Dependency> deps = new ArrayList<>();
 
-            @Override
-            public Type getType() {
-                return type;
+                Plugin existing = plugins.get(key);
+                if (existing != null) {
+                    if (version == null) {
+                        version = existing.getVersion();
+                    }
+                    execs.addAll(existing.getExecutions());
+                    deps.addAll(existing.getDependencies());
+                }
+
+                PluginExecution execution = PluginExecution.newBuilder()
+                        .id(getExecutionId(existing, goal))
+                        .priority(i - mojos.size())
+                        .phase(phase)
+                        .goals(List.of(goal))
+                        .configuration(mojo.getConfiguration())
+                        .location("", location)
+                        .location("id", location)
+                        .location("phase", location)
+                        .location("goals", location)
+                        .build();
+                execs.add(execution);
+
+                if (mojo.getDependencies() != null) {
+                    mojo.getDependencies().forEach(d -> 
deps.add(d.getDelegate()));
+                }
+
+                Plugin plugin = Plugin.newBuilder()
+                        .groupId(groupId)
+                        .artifactId(artifactId)
+                        .version(version)
+                        .location("", location)
+                        .location("groupId", location)
+                        .location("artifactId", location)
+                        .location("version", location)
+                        .executions(execs)
+                        .dependencies(deps)
+                        .build();
+
+                plugins.put(key, plugin);
             }
-        });
+        }
     }
+
+    private static String getExecutionId(Plugin plugin, String goal) {
+        Set<String> existingIds = plugin != null
+                ? 
plugin.getExecutions().stream().map(PluginExecution::getId).collect(Collectors.toSet())
+                : Set.of();
+        String base = "default-" + goal;
+        String id = base;
+        for (int index = 1; existingIds.contains(id); index++) {
+            id = base + '-' + index;
+        }
+        return id;
+    }
+
+    private record DefaultPackaging(String id, Type type, PluginContainer 
plugins) implements Packaging {}
 }

Reply via email to