1   package org.apache.maven.model.inheritance;
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  import java.io.File;
23  import java.util.ArrayList;
24  import java.util.HashMap;
25  import java.util.LinkedHashMap;
26  import java.util.List;
27  import java.util.Map;
28  
29  import org.apache.maven.model.Model;
30  import org.apache.maven.model.Plugin;
31  import org.apache.maven.model.PluginContainer;
32  import org.apache.maven.model.ReportPlugin;
33  import org.apache.maven.model.Reporting;
34  import org.apache.maven.model.building.ModelBuildingRequest;
35  import org.apache.maven.model.building.ModelProblemCollector;
36  import org.apache.maven.model.merge.MavenModelMerger;
37  import org.codehaus.plexus.component.annotations.Component;
38  
39  
40  
41  
42  
43  
44  @Component( role = InheritanceAssembler.class )
45  public class DefaultInheritanceAssembler
46      implements InheritanceAssembler
47  {
48  
49      private InheritanceModelMerger merger = new InheritanceModelMerger();
50  
51      public void assembleModelInheritance( Model child, Model parent, ModelBuildingRequest request,
52                                            ModelProblemCollector problems )
53      {
54          Map<Object, Object> hints = new HashMap<Object, Object>();
55          hints.put( MavenModelMerger.CHILD_PATH_ADJUSTMENT, getChildPathAdjustment( child, parent ) );
56          merger.merge( child, parent, false, hints );
57      }
58  
59      
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77      private String getChildPathAdjustment( Model child, Model parent )
78      {
79          String adjustment = "";
80  
81          if ( parent != null )
82          {
83              String childName = child.getArtifactId();
84  
85              
86  
87  
88  
89  
90  
91              File childDirectory = child.getProjectDirectory();
92              if ( childDirectory != null )
93              {
94                  childName = childDirectory.getName();
95              }
96  
97              for ( String module : parent.getModules() )
98              {
99                  module = module.replace( '\\', '/' );
100 
101                 if ( module.regionMatches( true, module.length() - 4, ".xml", 0, 4 ) )
102                 {
103                     module = module.substring( 0, module.lastIndexOf( '/' ) + 1 );
104                 }
105 
106                 String moduleName = module;
107                 if ( moduleName.endsWith( "/" ) )
108                 {
109                     moduleName = moduleName.substring( 0, moduleName.length() - 1 );
110                 }
111 
112                 int lastSlash = moduleName.lastIndexOf( '/' );
113 
114                 moduleName = moduleName.substring( lastSlash + 1 );
115 
116                 if ( moduleName.equals( childName ) && lastSlash >= 0 )
117                 {
118                     adjustment = module.substring( 0, lastSlash );
119                     break;
120                 }
121             }
122         }
123 
124         return adjustment;
125     }
126 
127     protected static class InheritanceModelMerger
128         extends MavenModelMerger
129     {
130 
131         @Override
132         protected void mergePluginContainer_Plugins( PluginContainer target, PluginContainer source,
133                                                      boolean sourceDominant, Map<Object, Object> context )
134         {
135             List<Plugin> src = source.getPlugins();
136             if ( !src.isEmpty() )
137             {
138                 List<Plugin> tgt = target.getPlugins();
139                 Map<Object, Plugin> master = new LinkedHashMap<Object, Plugin>( src.size() * 2 );
140 
141                 for ( Plugin element : src )
142                 {
143                     if ( element.isInherited() || !element.getExecutions().isEmpty() )
144                     {
145                         
146                         Plugin plugin = new Plugin();
147                         plugin.setLocation( "", element.getLocation( "" ) );
148                         plugin.setGroupId( null );
149                         mergePlugin( plugin, element, sourceDominant, context );
150 
151                         Object key = getPluginKey( element );
152 
153                         master.put( key, plugin );
154                     }
155                 }
156 
157                 Map<Object, List<Plugin>> predecessors = new LinkedHashMap<Object, List<Plugin>>();
158                 List<Plugin> pending = new ArrayList<Plugin>();
159                 for ( Plugin element : tgt )
160                 {
161                     Object key = getPluginKey( element );
162                     Plugin existing = master.get( key );
163                     if ( existing != null )
164                     {
165                         mergePlugin( element, existing, sourceDominant, context );
166 
167                         master.put( key, element );
168 
169                         if ( !pending.isEmpty() )
170                         {
171                             predecessors.put( key, pending );
172                             pending = new ArrayList<Plugin>();
173                         }
174                     }
175                     else
176                     {
177                         pending.add( element );
178                     }
179                 }
180 
181                 List<Plugin> result = new ArrayList<Plugin>( src.size() + tgt.size() );
182                 for ( Map.Entry<Object, Plugin> entry : master.entrySet() )
183                 {
184                     List<Plugin> pre = predecessors.get( entry.getKey() );
185                     if ( pre != null )
186                     {
187                         result.addAll( pre );
188                     }
189                     result.add( entry.getValue() );
190                 }
191                 result.addAll( pending );
192 
193                 target.setPlugins( result );
194             }
195         }
196 
197         @Override
198         protected void mergePlugin( Plugin target, Plugin source, boolean sourceDominant, Map<Object, Object> context )
199         {
200             if ( source.isInherited() )
201             {
202                 mergeConfigurationContainer( target, source, sourceDominant, context );
203             }
204             mergePlugin_GroupId( target, source, sourceDominant, context );
205             mergePlugin_ArtifactId( target, source, sourceDominant, context );
206             mergePlugin_Version( target, source, sourceDominant, context );
207             mergePlugin_Extensions( target, source, sourceDominant, context );
208             mergePlugin_Dependencies( target, source, sourceDominant, context );
209             mergePlugin_Executions( target, source, sourceDominant, context );
210         }
211 
212         @Override
213         protected void mergeReporting_Plugins( Reporting target, Reporting source, boolean sourceDominant,
214                                                Map<Object, Object> context )
215         {
216             List<ReportPlugin> src = source.getPlugins();
217             if ( !src.isEmpty() )
218             {
219                 List<ReportPlugin> tgt = target.getPlugins();
220                 Map<Object, ReportPlugin> merged =
221                     new LinkedHashMap<Object, ReportPlugin>( ( src.size() + tgt.size() ) * 2 );
222 
223                 for ( ReportPlugin element :  src )
224                 {
225                     Object key = getReportPluginKey( element );
226                     if ( element.isInherited() )
227                     {
228                         
229                         ReportPlugin plugin = new ReportPlugin();
230                         plugin.setLocation( "", element.getLocation( "" ) );
231                         plugin.setGroupId( null );
232                         mergeReportPlugin( plugin, element, sourceDominant, context );
233 
234                         merged.put( key, plugin );
235                     }
236                 }
237 
238                 for ( ReportPlugin element : tgt )
239                 {
240                     Object key = getReportPluginKey( element );
241                     ReportPlugin existing = merged.get( key );
242                     if ( existing != null )
243                     {
244                         mergeReportPlugin( element, existing, sourceDominant, context );
245                     }
246                     merged.put( key, element );
247                 }
248 
249                 target.setPlugins( new ArrayList<ReportPlugin>( merged.values() ) );
250             }
251         }
252     }
253 
254 }