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