1 package org.apache.maven.archetype.common;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.archetype.common.util.Format;
23 import org.apache.maven.archetype.common.util.PomUtils;
24 import org.apache.maven.archetype.exception.InvalidPackaging;
25 import org.apache.maven.archetype.old.ArchetypeTemplateProcessingException;
26 import org.apache.maven.model.Build;
27 import org.apache.maven.model.BuildBase;
28 import org.apache.maven.model.Dependency;
29 import org.apache.maven.model.Model;
30 import org.apache.maven.model.ModelBase;
31 import org.apache.maven.model.Parent;
32 import org.apache.maven.model.Plugin;
33 import org.apache.maven.model.Profile;
34 import org.apache.maven.model.ReportPlugin;
35 import org.apache.maven.model.Reporting;
36 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
37 import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
38 import org.codehaus.plexus.component.annotations.Component;
39 import org.codehaus.plexus.logging.AbstractLogEnabled;
40 import org.codehaus.plexus.util.FileUtils;
41 import org.codehaus.plexus.util.ReaderFactory;
42 import org.codehaus.plexus.util.StringUtils;
43 import org.codehaus.plexus.util.xml.Xpp3Dom;
44 import org.codehaus.plexus.util.xml.Xpp3DomUtils;
45 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
46 import org.jdom.JDOMException;
47 import org.jdom.input.SAXBuilder;
48 import org.xml.sax.SAXException;
49
50 import javax.xml.parsers.ParserConfigurationException;
51 import javax.xml.transform.TransformerException;
52 import java.io.File;
53 import java.io.FileInputStream;
54 import java.io.FileNotFoundException;
55 import java.io.FileOutputStream;
56 import java.io.IOException;
57 import java.io.InputStream;
58 import java.io.OutputStreamWriter;
59 import java.io.Reader;
60 import java.io.StringWriter;
61 import java.io.Writer;
62 import java.util.ArrayList;
63 import java.util.HashMap;
64 import java.util.List;
65 import java.util.Map;
66
67 @Component( role = PomManager.class )
68 public class DefaultPomManager
69 extends AbstractLogEnabled
70 implements PomManager
71 {
72 @Override
73 public void addModule( File pom, String artifactId ) throws IOException, ParserConfigurationException,
74 TransformerException, SAXException, InvalidPackaging, ArchetypeTemplateProcessingException
75 {
76 StringWriter out = new StringWriter();
77 boolean found = PomUtils.addNewModule( artifactId, ReaderFactory.newXmlReader( pom ), out );
78 if ( found )
79 {
80 FileUtils.fileWrite( pom.getAbsolutePath(), out.toString() );
81 }
82 }
83
84 @Override
85 public void addParent( File pom, File parentPom )
86 throws IOException, XmlPullParserException
87 {
88 Model generatedModel = readPom( pom );
89 if ( null != generatedModel.getParent() )
90 {
91 getLogger().info( "Parent element not overwritten in " + pom );
92 return;
93 }
94
95 Model parentModel = readPom( parentPom );
96
97 Parent parent = new Parent();
98 parent.setGroupId( parentModel.getGroupId() );
99 if ( parent.getGroupId() == null )
100 {
101 parent.setGroupId( parentModel.getParent().getGroupId() );
102 }
103 parent.setArtifactId( parentModel.getArtifactId() );
104 parent.setVersion( parentModel.getVersion() );
105 if ( parent.getVersion() == null )
106 {
107 parent.setVersion( parentModel.getParent().getVersion() );
108 }
109 generatedModel.setParent( parent );
110
111 writePom( generatedModel, pom, pom );
112 }
113
114 @Override
115 public void mergePoms( File pom, File temporaryPom )
116 throws IOException, XmlPullParserException
117 {
118 Model model = readPom( pom );
119 Model generatedModel = readPom( temporaryPom );
120
121 model.getProperties().putAll( generatedModel.getProperties() );
122
123 mergeModelBase( model, generatedModel );
124 mergeModelBuild( model, generatedModel );
125 mergeProfiles( model, generatedModel );
126 mergeReportPlugins( model, generatedModel );
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189 writePom( model, pom, pom );
190 }
191
192 @Override
193 public Model readPom( final File pomFile )
194 throws IOException, XmlPullParserException
195 {
196 try ( Reader pomReader = ReaderFactory.newXmlReader( pomFile ) )
197 {
198 MavenXpp3Reader reader = new MavenXpp3Reader();
199
200 return reader.read( pomReader );
201 }
202 }
203
204
205 @Override
206 public Model readPom( InputStream pomStream )
207 throws IOException, XmlPullParserException
208 {
209 try ( Reader pomReader = ReaderFactory.newXmlReader( pomStream ) )
210 {
211 MavenXpp3Reader reader = new MavenXpp3Reader();
212
213 return reader.read( pomReader );
214 }
215 }
216
217 @Override
218 public void writePom( final Model model, final File pomFile, final File initialPomFile )
219 throws IOException
220 {
221 String fileEncoding =
222 StringUtils.isEmpty( model.getModelEncoding() ) ? "UTF-8" : model.getModelEncoding();
223
224 org.jdom.Document doc;
225 try ( InputStream inputStream = new FileInputStream( initialPomFile ) )
226 {
227 SAXBuilder builder = new SAXBuilder();
228 doc = builder.build( inputStream );
229 }
230 catch ( JDOMException exc )
231 {
232 IOException ioe = new IOException( "Cannot parse the POM by JDOM while reading " + initialPomFile + ": "
233 + exc.getMessage() );
234 ioe.initCause( exc );
235 throw ioe;
236 }
237
238 try ( Writer outputStreamWriter = new OutputStreamWriter( new FileOutputStream( pomFile ), fileEncoding ) )
239 {
240
241 MavenJDOMWriter writer = new MavenJDOMWriter();
242
243 final String ls = System.lineSeparator();
244 Format form = Format.getRawFormat().setEncoding( fileEncoding ).setLineSeparator( ls );
245 writer.write( model, doc, outputStreamWriter, form );
246 }
247 catch ( FileNotFoundException e )
248 {
249 getLogger().debug( "Creating pom file " + pomFile );
250
251 try ( Writer pomWriter = new OutputStreamWriter( new FileOutputStream( pomFile ), fileEncoding ) )
252 {
253 MavenXpp3Writer writer = new MavenXpp3Writer();
254 writer.write( pomWriter, model );
255 }
256 }
257 }
258
259 private Map<String, Dependency> createDependencyMap( List<Dependency> dependencies )
260 {
261 Map<String, Dependency> dependencyMap = new HashMap<>();
262 for ( Dependency dependency : dependencies )
263 {
264 dependencyMap.put( dependency.getManagementKey(), dependency );
265 }
266
267 return dependencyMap;
268 }
269
270 private void mergeModelBuild( Model model, Model generatedModel )
271 {
272 if ( generatedModel.getBuild() != null )
273 {
274 if ( model.getBuild() == null )
275 {
276 model.setBuild( new Build() );
277 }
278
279 mergeBuildPlugins( model.getBuild(), generatedModel.getBuild() );
280 }
281 }
282
283 private void mergeProfiles( Model model, Model generatedModel )
284 {
285 List<Profile> generatedProfiles = generatedModel.getProfiles();
286 if ( generatedProfiles != null && generatedProfiles.size() > 0 )
287 {
288 List<Profile> modelProfiles = model.getProfiles();
289 Map<String, Profile> modelProfileIdMap = new HashMap<>();
290 if ( modelProfiles == null )
291 {
292 modelProfiles = new ArrayList<>();
293 model.setProfiles( modelProfiles );
294 }
295 else if ( modelProfiles.size() > 0 )
296 {
297
298 for ( Profile modelProfile : modelProfiles )
299 {
300 modelProfileIdMap.put( modelProfile.getId(), modelProfile );
301 }
302 }
303
304 for ( Profile generatedProfile : generatedProfiles )
305 {
306 String generatedProfileId = generatedProfile.getId();
307 if ( !modelProfileIdMap.containsKey( generatedProfileId ) )
308 {
309 model.addProfile( generatedProfile );
310 }
311 else
312 {
313 getLogger().warn( "Try to merge profiles with id " + generatedProfileId );
314 mergeModelBase( modelProfileIdMap.get( generatedProfileId ), generatedProfile );
315 mergeProfileBuild( modelProfileIdMap.get( generatedProfileId ), generatedProfile );
316 }
317 }
318 }
319 }
320
321 private void mergeProfileBuild( Profile modelProfile, Profile generatedProfile )
322 {
323 if ( generatedProfile.getBuild() != null )
324 {
325 if ( modelProfile.getBuild() == null )
326 {
327 modelProfile.setBuild( new Build() );
328 }
329 mergeBuildPlugins( modelProfile.getBuild(), generatedProfile.getBuild() );
330
331 }
332 }
333
334 private void mergeModelBase( ModelBase model, ModelBase generatedModel )
335 {
336
337 Map<String, Dependency> dependenciesByIds = createDependencyMap( model.getDependencies() );
338
339 Map<String, Dependency> generatedDependenciesByIds = createDependencyMap( generatedModel.getDependencies() );
340
341 for ( String generatedDependencyId : generatedDependenciesByIds.keySet() )
342 {
343 if ( !dependenciesByIds.containsKey( generatedDependencyId ) )
344 {
345 model.addDependency( generatedDependenciesByIds.get( generatedDependencyId ) );
346 }
347 else
348 {
349 getLogger().warn( "Can not override property: " + generatedDependencyId );
350 }
351
352
353 model.getProperties().putAll( generatedModel.getProperties() );
354
355
356 }
357 }
358
359 private void mergeReportPlugins( Model model, Model generatedModel )
360 {
361 if ( generatedModel.getReporting() != null )
362 {
363 if ( model.getReporting() == null )
364 {
365 model.setReporting( new Reporting() );
366 }
367
368 Map<String, ReportPlugin> reportPluginsByIds = model.getReporting().getReportPluginsAsMap();
369
370 Map<String, ReportPlugin> generatedReportPluginsByIds =
371 generatedModel.getReporting().getReportPluginsAsMap();
372
373 for ( String generatedReportPluginsId : generatedReportPluginsByIds.keySet() )
374 {
375 if ( !reportPluginsByIds.containsKey( generatedReportPluginsId ) )
376 {
377 model.getReporting().addPlugin( generatedReportPluginsByIds.get( generatedReportPluginsId ) );
378 }
379 else
380 {
381 getLogger().warn( "Can not override report: " + generatedReportPluginsId );
382 }
383 }
384 }
385 }
386
387 private void mergeBuildPlugins( BuildBase modelBuild, BuildBase generatedModelBuild )
388 {
389 Map<String, Plugin> pluginsByIds = modelBuild.getPluginsAsMap();
390
391 List<Plugin> generatedPlugins = generatedModelBuild.getPlugins();
392
393 for ( Plugin generatedPlugin : generatedPlugins )
394 {
395 String generatedPluginsId = generatedPlugin.getKey();
396
397 if ( !pluginsByIds.containsKey( generatedPluginsId ) )
398 {
399 modelBuild.addPlugin( generatedPlugin );
400 }
401 else
402 {
403 getLogger().info( "Try to merge plugin configuration of plugins with id: " + generatedPluginsId );
404 Plugin modelPlugin = pluginsByIds.get( generatedPluginsId );
405
406 modelPlugin.setConfiguration( Xpp3DomUtils.mergeXpp3Dom( (Xpp3Dom) generatedPlugin.getConfiguration(),
407 (Xpp3Dom) modelPlugin.getConfiguration() ) );
408 }
409 }
410 }
411 }