diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/ProcessorContext.java b/maven-model-builder/src/main/java/org/apache/maven/model/ProcessorContext.java index bde6969c72..ae42762ac7 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/ProcessorContext.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/ProcessorContext.java @@ -28,6 +28,8 @@ import org.apache.maven.model.inheritance.DefaultInheritanceAssembler; import org.apache.maven.model.inheritance.InheritanceAssembler; +import org.apache.maven.model.management.DefaultManagementInjector; +import org.apache.maven.model.management.ManagementInjector; import org.apache.maven.model.processors.BuildProcessor; import org.apache.maven.model.processors.CiManagementProcessor; import org.apache.maven.model.processors.ContributorsProcessor; @@ -288,6 +290,8 @@ private static void addPlugin(Build build, String id) p1.setArtifactId(id); build.addPlugin(p1); } + + private static ManagementInjector managementInjector = new DefaultManagementInjector(); public static Model processManagementNodes(Model target) throws IOException @@ -296,6 +300,12 @@ public static Model processManagementNodes(Model target) // plugin.setArtifactId("maven-compiler-plugin"); // target.getBuild().addPlugin(plugin); // Dependency Management + managementInjector.injectManagement( target ); + if ( true ) + { + return target; + } + DependencyManagementProcessor depProc = new DependencyManagementProcessor(); if ( target.getDependencyManagement() != null ) { diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultManagementInjector.java b/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultManagementInjector.java new file mode 100644 index 0000000000..3cab35addb --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultManagementInjector.java @@ -0,0 +1,192 @@ +package org.apache.maven.model.management; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.apache.maven.model.Build; +import org.apache.maven.model.Dependency; +import org.apache.maven.model.DependencyManagement; +import org.apache.maven.model.Exclusion; +import org.apache.maven.model.Model; +import org.apache.maven.model.Plugin; +import org.apache.maven.model.PluginContainer; +import org.apache.maven.model.PluginExecution; +import org.apache.maven.model.PluginManagement; +import org.apache.maven.model.merge.MavenModelMerger; +import org.codehaus.plexus.component.annotations.Component; + +/** + * Handles injection of plugin/dependency management into the model. + * + * @author Benjamin Bentmann + */ +@Component( role = ManagementInjector.class ) +public class DefaultManagementInjector + implements ManagementInjector +{ + + private ManagementModelMerger merger = new ManagementModelMerger(); + + public void injectManagement( Model model ) + { + merger.mergeManagedDependencies( model ); + merger.mergeManagedBuildPlugins( model ); + } + + private static class ManagementModelMerger + extends MavenModelMerger + { + + public void mergeManagedBuildPlugins( Model model ) + { + Build build = model.getBuild(); + if ( build != null ) + { + PluginManagement pluginManagement = build.getPluginManagement(); + if ( pluginManagement != null ) + { + mergePluginContainer_Plugins( build, pluginManagement, false, Collections.emptyMap() ); + } + } + } + + @Override + protected void mergePluginContainer_Plugins( PluginContainer target, PluginContainer source, + boolean sourceDominant, Map context ) + { + List src = source.getPlugins(); + if ( !src.isEmpty() ) + { + List tgt = target.getPlugins(); + + Map managedPlugins = new LinkedHashMap( src.size() * 2 ); + + for ( Iterator it = src.iterator(); it.hasNext(); ) + { + Plugin element = it.next(); + Object key = getPluginKey( element ); + managedPlugins.put( key, element ); + } + + for ( Iterator it = tgt.iterator(); it.hasNext(); ) + { + Plugin element = it.next(); + Object key = getPluginKey( element ); + Plugin managedPlugin = managedPlugins.get( key ); + if ( managedPlugin != null ) + { + mergePlugin( element, managedPlugin, sourceDominant, context ); + } + } + } + } + + @Override + protected void mergePlugin_Executions( Plugin target, Plugin source, boolean sourceDominant, + Map context ) + { + List src = source.getExecutions(); + if ( !src.isEmpty() ) + { + List tgt = target.getExecutions(); + + Map merged = + new LinkedHashMap( ( src.size() + tgt.size() ) * 2 ); + + for ( Iterator it = src.iterator(); it.hasNext(); ) + { + PluginExecution element = it.next(); + Object key = getPluginExecutionKey( element ); + PluginExecution clone = new PluginExecution(); + mergePluginExecution( clone, element, true, context ); + merged.put( key, clone ); + } + + for ( Iterator it = tgt.iterator(); it.hasNext(); ) + { + PluginExecution element = it.next(); + Object key = getPluginExecutionKey( element ); + PluginExecution existing = merged.get( key ); + if ( existing != null ) + { + mergePluginExecution( element, existing, sourceDominant, context ); + } + merged.put( key, element ); + } + + target.setExecutions( new ArrayList( merged.values() ) ); + } + } + + public void mergeManagedDependencies( Model model ) + { + DependencyManagement dependencyManagement = model.getDependencyManagement(); + if ( dependencyManagement != null ) + { + Map dependencies = new HashMap(); + Map context = Collections.emptyMap(); + + for ( Dependency dependency : model.getDependencies() ) + { + Object key = getDependencyKey( dependency ); + dependencies.put( key, dependency ); + } + + for ( Dependency managedDependency : dependencyManagement.getDependencies() ) + { + Object key = getDependencyKey( managedDependency ); + Dependency dependency = dependencies.get( key ); + if ( dependency != null ) + { + mergeDependency( dependency, managedDependency, false, context ); + } + } + } + } + + @Override + protected void mergeDependency_Exclusions( Dependency target, Dependency source, boolean sourceDominant, + Map context ) + { + List tgt = target.getExclusions(); + if ( tgt.isEmpty() ) + { + List src = source.getExclusions(); + + for ( Iterator it = src.iterator(); it.hasNext(); ) + { + Exclusion element = it.next(); + Exclusion clone = new Exclusion(); + mergeExclusion( clone, element, true, context ); + target.addExclusion( clone ); + } + } + } + + } + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/management/ManagementInjector.java b/maven-model-builder/src/main/java/org/apache/maven/model/management/ManagementInjector.java new file mode 100644 index 0000000000..d9343e05d6 --- /dev/null +++ b/maven-model-builder/src/main/java/org/apache/maven/model/management/ManagementInjector.java @@ -0,0 +1,40 @@ +package org.apache.maven.model.management; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.model.Model; + +/** + * Handles injection of plugin/dependency management into the model. + * + * @author Benjamin Bentmann + */ +public interface ManagementInjector +{ + + /** + * Merges default values from the plugin and/or dependency management sections of the given model into itself. + * + * @param child The model into which to merge the values specified by its management sections, must not be + * null. + */ + void injectManagement( Model child ); + +} diff --git a/maven-model/src/main/java/org/apache/maven/model/merge/ModelMerger.java b/maven-model/src/main/java/org/apache/maven/model/merge/ModelMerger.java index b0cc24d86c..7a373951f5 100644 --- a/maven-model/src/main/java/org/apache/maven/model/merge/ModelMerger.java +++ b/maven-model/src/main/java/org/apache/maven/model/merge/ModelMerger.java @@ -38,6 +38,7 @@ import org.apache.maven.model.DeploymentRepository; import org.apache.maven.model.Developer; import org.apache.maven.model.DistributionManagement; +import org.apache.maven.model.Exclusion; import org.apache.maven.model.Extension; import org.apache.maven.model.FileSet; import org.apache.maven.model.IssueManagement; @@ -1031,6 +1032,183 @@ protected void mergeRepositoryPolicy_ChecksumPolicy( RepositoryPolicy target, Re protected void mergeDependency( Dependency target, Dependency source, boolean sourceDominant, Map context ) { + mergeDependency_GroupId( target, source, sourceDominant, context ); + mergeDependency_ArtifactId( target, source, sourceDominant, context ); + mergeDependency_Version( target, source, sourceDominant, context ); + mergeDependency_Type( target, source, sourceDominant, context ); + mergeDependency_Classifier( target, source, sourceDominant, context ); + mergeDependency_Scope( target, source, sourceDominant, context ); + mergeDependency_SystemPath( target, source, sourceDominant, context ); + mergeDependency_Optional( target, source, sourceDominant, context ); + mergeDependency_Exclusions( target, source, sourceDominant, context ); + } + + protected void mergeDependency_GroupId( Dependency target, Dependency source, boolean sourceDominant, + Map context ) + { + String src = source.getGroupId(); + if ( src != null ) + { + if ( sourceDominant || target.getGroupId() == null ) + { + target.setGroupId( src ); + } + } + } + + protected void mergeDependency_ArtifactId( Dependency target, Dependency source, boolean sourceDominant, + Map context ) + { + String src = source.getArtifactId(); + if ( src != null ) + { + if ( sourceDominant || target.getArtifactId() == null ) + { + target.setArtifactId( src ); + } + } + } + + protected void mergeDependency_Version( Dependency target, Dependency source, boolean sourceDominant, + Map context ) + { + String src = source.getVersion(); + if ( src != null ) + { + if ( sourceDominant || target.getVersion() == null ) + { + target.setVersion( src ); + } + } + } + + protected void mergeDependency_Type( Dependency target, Dependency source, boolean sourceDominant, + Map context ) + { + String src = source.getType(); + if ( src != null ) + { + if ( sourceDominant || target.getType() == null ) + { + target.setType( src ); + } + } + } + + protected void mergeDependency_Classifier( Dependency target, Dependency source, boolean sourceDominant, + Map context ) + { + String src = source.getClassifier(); + if ( src != null ) + { + if ( sourceDominant || target.getClassifier() == null ) + { + target.setClassifier( src ); + } + } + } + + protected void mergeDependency_Scope( Dependency target, Dependency source, boolean sourceDominant, + Map context ) + { + String src = source.getScope(); + if ( src != null ) + { + if ( sourceDominant || target.getScope() == null ) + { + target.setScope( src ); + } + } + } + + protected void mergeDependency_SystemPath( Dependency target, Dependency source, boolean sourceDominant, + Map context ) + { + String src = source.getSystemPath(); + if ( src != null ) + { + if ( sourceDominant || target.getSystemPath() == null ) + { + target.setSystemPath( src ); + } + } + } + + protected void mergeDependency_Optional( Dependency target, Dependency source, boolean sourceDominant, + Map context ) + { + String src = source.getOptional(); + if ( src != null ) + { + if ( sourceDominant || target.getOptional() == null ) + { + target.setOptional( src ); + } + } + } + + protected void mergeDependency_Exclusions( Dependency target, Dependency source, boolean sourceDominant, + Map context ) + { + List src = source.getExclusions(); + if ( !src.isEmpty() ) + { + List tgt = target.getExclusions(); + + Map merged = new LinkedHashMap( ( src.size() + tgt.size() ) * 2 ); + + for ( Iterator it = tgt.iterator(); it.hasNext(); ) + { + Exclusion element = it.next(); + Object key = getExclusionKey( element ); + merged.put( key, element ); + } + + for ( Iterator it = src.iterator(); it.hasNext(); ) + { + Exclusion element = it.next(); + Object key = getExclusionKey( element ); + if ( sourceDominant || !merged.containsKey( key ) ) + { + merged.put( key, element ); + } + } + + target.setExclusions( new ArrayList( merged.values() ) ); + } + } + + protected void mergeExclusion( Exclusion target, Exclusion source, boolean sourceDominant, + Map context ) + { + mergeExclusion_GroupId( target, source, sourceDominant, context ); + mergeExclusion_ArtifactId( target, source, sourceDominant, context ); + } + + protected void mergeExclusion_GroupId( Exclusion target, Exclusion source, boolean sourceDominant, + Map context ) + { + String src = source.getGroupId(); + if ( src != null ) + { + if ( sourceDominant || target.getGroupId() == null ) + { + target.setGroupId( src ); + } + } + } + + protected void mergeExclusion_ArtifactId( Exclusion target, Exclusion source, boolean sourceDominant, + Map context ) + { + String src = source.getArtifactId(); + if ( src != null ) + { + if ( sourceDominant || target.getArtifactId() == null ) + { + target.setArtifactId( src ); + } + } } protected void mergeReporting( Reporting target, Reporting source, boolean sourceDominant, @@ -2295,6 +2473,7 @@ protected void mergePlugin_Executions( Plugin target, Plugin source, boolean sou if ( !src.isEmpty() ) { List tgt = target.getExecutions(); + Map merged = new LinkedHashMap( ( src.size() + tgt.size() ) * 2 ); @@ -2596,4 +2775,9 @@ protected Object getExtensionKey( Extension object ) return object; } + protected Object getExclusionKey( Exclusion object ) + { + return object.getGroupId() + ':' + object.getArtifactId(); + } + }