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.jdom2.JDOMException;
47 import org.jdom2.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.jdom2.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 throw new IOException( "Cannot parse the POM by JDOM while reading " + initialPomFile + ": "
233 + exc.getMessage(), exc );
234 }
235
236
237 if ( !pomFile.exists() && !pomFile.createNewFile() )
238 {
239 getLogger().warn( "Could not create new file \"" + pomFile.getPath() + "\" or the file already exists." );
240 }
241
242 try ( Writer outputStreamWriter = new OutputStreamWriter( new FileOutputStream( pomFile ), fileEncoding ) )
243 {
244
245 MavenJDOMWriter writer = new MavenJDOMWriter();
246
247 final String ls = System.lineSeparator();
248 Format form = Format.getRawFormat().setEncoding( fileEncoding ).setLineSeparator( ls );
249 writer.write( model, doc, outputStreamWriter, form );
250 }
251 catch ( FileNotFoundException e )
252 {
253 getLogger().debug( "Creating pom file " + pomFile );
254
255 try ( Writer pomWriter = new OutputStreamWriter( new FileOutputStream( pomFile ), fileEncoding ) )
256 {
257 MavenXpp3Writer writer = new MavenXpp3Writer();
258 writer.write( pomWriter, model );
259 }
260 }
261 }
262
263 private Map<String, Dependency> createDependencyMap( List<Dependency> dependencies )
264 {
265 Map<String, Dependency> dependencyMap = new HashMap<>();
266 for ( Dependency dependency : dependencies )
267 {
268 dependencyMap.put( dependency.getManagementKey(), dependency );
269 }
270
271 return dependencyMap;
272 }
273
274 private void mergeModelBuild( Model model, Model generatedModel )
275 {
276 if ( generatedModel.getBuild() != null )
277 {
278 if ( model.getBuild() == null )
279 {
280 model.setBuild( new Build() );
281 }
282
283 mergeBuildPlugins( model.getBuild(), generatedModel.getBuild() );
284 }
285 }
286
287 private void mergeProfiles( Model model, Model generatedModel )
288 {
289 List<Profile> generatedProfiles = generatedModel.getProfiles();
290 if ( generatedProfiles != null && generatedProfiles.size() > 0 )
291 {
292 List<Profile> modelProfiles = model.getProfiles();
293 Map<String, Profile> modelProfileIdMap = new HashMap<>();
294 if ( modelProfiles == null )
295 {
296 modelProfiles = new ArrayList<>();
297 model.setProfiles( modelProfiles );
298 }
299 else if ( modelProfiles.size() > 0 )
300 {
301
302 for ( Profile modelProfile : modelProfiles )
303 {
304 modelProfileIdMap.put( modelProfile.getId(), modelProfile );
305 }
306 }
307
308 for ( Profile generatedProfile : generatedProfiles )
309 {
310 String generatedProfileId = generatedProfile.getId();
311 if ( !modelProfileIdMap.containsKey( generatedProfileId ) )
312 {
313 model.addProfile( generatedProfile );
314 }
315 else
316 {
317 getLogger().warn( "Try to merge profiles with id " + generatedProfileId );
318 mergeModelBase( modelProfileIdMap.get( generatedProfileId ), generatedProfile );
319 mergeProfileBuild( modelProfileIdMap.get( generatedProfileId ), generatedProfile );
320 }
321 }
322 }
323 }
324
325 private void mergeProfileBuild( Profile modelProfile, Profile generatedProfile )
326 {
327 if ( generatedProfile.getBuild() != null )
328 {
329 if ( modelProfile.getBuild() == null )
330 {
331 modelProfile.setBuild( new Build() );
332 }
333 mergeBuildPlugins( modelProfile.getBuild(), generatedProfile.getBuild() );
334
335 }
336 }
337
338 private void mergeModelBase( ModelBase model, ModelBase generatedModel )
339 {
340
341 Map<String, Dependency> dependenciesByIds = createDependencyMap( model.getDependencies() );
342
343 Map<String, Dependency> generatedDependenciesByIds = createDependencyMap( generatedModel.getDependencies() );
344
345 for ( String generatedDependencyId : generatedDependenciesByIds.keySet() )
346 {
347 if ( !dependenciesByIds.containsKey( generatedDependencyId ) )
348 {
349 model.addDependency( generatedDependenciesByIds.get( generatedDependencyId ) );
350 }
351 else
352 {
353 getLogger().warn( "Can not override property: " + generatedDependencyId );
354 }
355
356
357 model.getProperties().putAll( generatedModel.getProperties() );
358
359
360 }
361 }
362
363 private void mergeReportPlugins( Model model, Model generatedModel )
364 {
365 if ( generatedModel.getReporting() != null )
366 {
367 if ( model.getReporting() == null )
368 {
369 model.setReporting( new Reporting() );
370 }
371
372 Map<String, ReportPlugin> reportPluginsByIds = model.getReporting().getReportPluginsAsMap();
373
374 Map<String, ReportPlugin> generatedReportPluginsByIds =
375 generatedModel.getReporting().getReportPluginsAsMap();
376
377 for ( String generatedReportPluginsId : generatedReportPluginsByIds.keySet() )
378 {
379 if ( !reportPluginsByIds.containsKey( generatedReportPluginsId ) )
380 {
381 model.getReporting().addPlugin( generatedReportPluginsByIds.get( generatedReportPluginsId ) );
382 }
383 else
384 {
385 getLogger().warn( "Can not override report: " + generatedReportPluginsId );
386 }
387 }
388 }
389 }
390
391 private void mergeBuildPlugins( BuildBase modelBuild, BuildBase generatedModelBuild )
392 {
393 Map<String, Plugin> pluginsByIds = modelBuild.getPluginsAsMap();
394
395 List<Plugin> generatedPlugins = generatedModelBuild.getPlugins();
396
397 for ( Plugin generatedPlugin : generatedPlugins )
398 {
399 String generatedPluginsId = generatedPlugin.getKey();
400
401 if ( !pluginsByIds.containsKey( generatedPluginsId ) )
402 {
403 modelBuild.addPlugin( generatedPlugin );
404 }
405 else
406 {
407 getLogger().info( "Try to merge plugin configuration of plugins with id: " + generatedPluginsId );
408 Plugin modelPlugin = pluginsByIds.get( generatedPluginsId );
409
410 modelPlugin.setConfiguration( Xpp3DomUtils.mergeXpp3Dom( (Xpp3Dom) generatedPlugin.getConfiguration(),
411 (Xpp3Dom) modelPlugin.getConfiguration() ) );
412 }
413 }
414 }
415 }