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.exception.InvalidPackaging;
24 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
25 import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
26 import org.apache.maven.model.Model;
27 import org.apache.maven.model.Parent;
28 import org.apache.maven.model.Dependency;
29 import org.apache.maven.model.Build;
30 import org.apache.maven.model.Profile;
31 import org.apache.maven.model.ModelBase;
32 import org.apache.maven.model.Reporting;
33 import org.apache.maven.model.ReportPlugin;
34 import org.apache.maven.model.BuildBase;
35 import org.apache.maven.model.Plugin;
36 import org.codehaus.plexus.logging.AbstractLogEnabled;
37 import org.codehaus.plexus.util.FileUtils;
38 import org.codehaus.plexus.util.IOUtil;
39 import org.codehaus.plexus.util.ReaderFactory;
40 import org.codehaus.plexus.util.StringUtils;
41 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
42 import org.codehaus.plexus.util.xml.Xpp3DomUtils;
43 import org.codehaus.plexus.util.xml.Xpp3Dom;
44 import org.dom4j.Document;
45 import org.dom4j.DocumentException;
46 import org.dom4j.Element;
47 import org.dom4j.Node;
48 import org.dom4j.io.SAXReader;
49 import org.dom4j.io.XMLWriter;
50 import org.jdom.JDOMException;
51 import org.jdom.input.SAXBuilder;
52
53 import java.io.File;
54 import java.io.FileInputStream;
55 import java.io.FileNotFoundException;
56 import java.io.FileOutputStream;
57 import java.io.IOException;
58 import java.io.InputStream;
59 import java.io.OutputStreamWriter;
60 import java.io.Reader;
61 import java.io.StringWriter;
62 import java.io.Writer;
63 import java.util.ArrayList;
64 import java.util.HashMap;
65 import java.util.Iterator;
66 import java.util.List;
67 import java.util.Map;
68
69
70 public class DefaultPomManager
71 extends AbstractLogEnabled
72 implements PomManager
73 {
74 public void addModule( File pom, String artifactId )
75 throws IOException, XmlPullParserException, DocumentException, InvalidPackaging
76 {
77 boolean found = false;
78
79 StringWriter writer = new StringWriter();
80 Reader fileReader = null;
81
82 try
83 {
84 fileReader = ReaderFactory.newXmlReader( pom );
85
86 SAXReader reader = new SAXReader();
87 Document document = reader.read( fileReader );
88 Element project = document.getRootElement();
89
90 String packaging = null;
91 Element packagingElement = project.element( "packaging" );
92 if ( packagingElement != null )
93 {
94 packaging = packagingElement.getStringValue();
95 }
96 if ( !"pom".equals( packaging ) )
97 {
98 throw new InvalidPackaging(
99 "Unable to add module to the current project as it is not of packaging type 'pom'"
100 );
101 }
102
103 Element modules = project.element( "modules" );
104 if ( modules == null )
105 {
106 modules = project.addText( " " ).addElement( "modules" );
107 modules.setText( "\n " );
108 project.addText( "\n" );
109 }
110
111 for ( @SuppressWarnings( "unchecked" )
112 Iterator<Element> i = modules.elementIterator( "module" ); i.hasNext() && !found; )
113 {
114 Element module = i.next();
115 if ( module.getText().equals( artifactId ) )
116 {
117 found = true;
118 }
119 }
120 if ( !found )
121 {
122 Node lastTextNode = null;
123 for ( @SuppressWarnings( "unchecked" )
124 Iterator<Node> i = modules.nodeIterator(); i.hasNext(); )
125 {
126 Node node = i.next();
127 if ( node.getNodeType() == Node.ELEMENT_NODE )
128 {
129 lastTextNode = null;
130 }
131 else if ( node.getNodeType() == Node.TEXT_NODE )
132 {
133 lastTextNode = node;
134 }
135 }
136
137 if ( lastTextNode != null )
138 {
139 modules.remove( lastTextNode );
140 }
141
142 modules.addText( "\n " );
143 modules.addElement( "module" ).setText( artifactId );
144 modules.addText( "\n " );
145
146 XMLWriter xmlWriter = new XMLWriter( writer );
147 xmlWriter.write( document );
148
149 FileUtils.fileWrite( pom.getAbsolutePath(), writer.toString() );
150 }
151 }
152 finally
153 {
154 IOUtil.close( fileReader );
155 }
156 }
157
158 public void addParent( File pom, File parentPom )
159 throws IOException, XmlPullParserException
160 {
161 Model generatedModel = readPom( pom );
162 if ( null != generatedModel.getParent() )
163 {
164 getLogger().info( "Parent element not overwritten in " + pom );
165 return;
166 }
167
168 Model parentModel = readPom( parentPom );
169
170 Parent parent = new Parent();
171 parent.setGroupId( parentModel.getGroupId() );
172 if ( parent.getGroupId() == null )
173 {
174 parent.setGroupId( parentModel.getParent().getGroupId() );
175 }
176 parent.setArtifactId( parentModel.getArtifactId() );
177 parent.setVersion( parentModel.getVersion() );
178 if ( parent.getVersion() == null )
179 {
180 parent.setVersion( parentModel.getParent().getVersion() );
181 }
182 generatedModel.setParent( parent );
183
184 writePom( generatedModel, pom, pom );
185 }
186
187 public void mergePoms( File pom, File temporaryPom )
188 throws IOException, XmlPullParserException
189 {
190 Model model = readPom( pom );
191 Model generatedModel = readPom( temporaryPom );
192
193 model.getProperties().putAll( generatedModel.getProperties() );
194
195 mergeModelBase( model, generatedModel );
196 mergeModelBuild( model, generatedModel );
197 mergeProfiles( model, generatedModel );
198 mergeReportPlugins( model, generatedModel );
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261 writePom( model, pom, pom );
262 }
263
264 public Model readPom( final File pomFile )
265 throws IOException, XmlPullParserException
266 {
267 Model model;
268 Reader pomReader = null;
269 try
270 {
271 pomReader = ReaderFactory.newXmlReader( pomFile );
272
273 MavenXpp3Reader reader = new MavenXpp3Reader();
274
275 model = reader.read( pomReader );
276 }
277 finally
278 {
279 IOUtil.close( pomReader );
280 }
281 return model;
282 }
283
284
285 public Model readPom( InputStream pomStream )
286 throws IOException, XmlPullParserException
287 {
288 Reader pomReader = ReaderFactory.newXmlReader( pomStream );
289
290 MavenXpp3Reader reader = new MavenXpp3Reader();
291
292 return reader.read( pomReader );
293 }
294
295 public void writePom( final Model model, final File pomFile, final File initialPomFile )
296 throws IOException
297 {
298 InputStream inputStream = null;
299 Writer outputStreamWriter = null;
300
301 String fileEncoding =
302 StringUtils.isEmpty( model.getModelEncoding() ) ? "UTF-8" : model.getModelEncoding();
303
304 try
305 {
306 inputStream = new FileInputStream( initialPomFile );
307
308 SAXBuilder builder = new SAXBuilder();
309 org.jdom.Document doc = builder.build( inputStream );
310 inputStream.close();
311 inputStream = null;
312
313
314 MavenJDOMWriter writer = new MavenJDOMWriter();
315
316 outputStreamWriter =
317 new OutputStreamWriter( new FileOutputStream( pomFile ), fileEncoding );
318
319 Format form = Format.getRawFormat().setEncoding( fileEncoding );
320 writer.write( model, doc, outputStreamWriter, form );
321 }
322 catch ( JDOMException exc )
323 {
324 IOException ioe = new IOException( "Cannot parse the POM by JDOM while reading " + initialPomFile + ": "
325 + exc.getMessage() );
326 ioe.initCause( exc );
327 throw ioe;
328 }
329 catch ( FileNotFoundException e )
330 {
331 getLogger().debug( "Creating pom file " + pomFile );
332
333 Writer pomWriter = null;
334
335 try
336 {
337 pomWriter =
338 new OutputStreamWriter( new FileOutputStream( pomFile ), fileEncoding );
339
340 MavenXpp3Writer writer = new MavenXpp3Writer();
341 writer.write( pomWriter, model );
342 }
343 finally
344 {
345 IOUtil.close( pomWriter );
346 }
347 }
348 finally
349 {
350 IOUtil.close( inputStream );
351 IOUtil.close( outputStreamWriter );
352 }
353 }
354
355 private Map<String, Dependency> createDependencyMap( List<Dependency> dependencies )
356 {
357 Map<String, Dependency> dependencyMap = new HashMap<String, Dependency>();
358 for ( Dependency dependency : dependencies )
359 {
360 dependencyMap.put( dependency.getManagementKey(), dependency );
361 }
362
363 return dependencyMap;
364 }
365
366 private void mergeModelBuild( Model model, Model generatedModel )
367 {
368 if ( generatedModel.getBuild() != null )
369 {
370 if ( model.getBuild() == null )
371 {
372 model.setBuild( new Build() );
373 }
374
375 mergeBuildPlugins( model.getBuild(), generatedModel.getBuild() );
376 }
377 }
378
379 private void mergeProfiles( Model model, Model generatedModel )
380 {
381 @SuppressWarnings( "unchecked" )
382 List<Profile> generatedProfiles = generatedModel.getProfiles();
383 if ( generatedProfiles != null && generatedProfiles.size() > 0 )
384 {
385 @SuppressWarnings( "unchecked" )
386 List<Profile> modelProfiles = model.getProfiles();
387 Map<String, Profile> modelProfileIdMap = new HashMap<String, Profile>();
388 if ( modelProfiles == null )
389 {
390 modelProfiles = new ArrayList<Profile>();
391 model.setProfiles( modelProfiles );
392 }
393 else if ( modelProfiles.size() > 0 )
394 {
395
396 for ( Profile modelProfile : modelProfiles )
397 {
398 modelProfileIdMap.put( modelProfile.getId(), modelProfile );
399 }
400 }
401
402 for ( Profile generatedProfile : generatedProfiles )
403 {
404 String generatedProfileId = generatedProfile.getId();
405 if ( !modelProfileIdMap.containsKey( generatedProfileId ) )
406 {
407 model.addProfile( generatedProfile );
408 }
409 else
410 {
411 getLogger().warn( "Try to merge profiles with id " + generatedProfileId );
412 mergeModelBase( (Profile) modelProfileIdMap.get( generatedProfileId ), generatedProfile );
413 mergeProfileBuild( (Profile) modelProfileIdMap.get( generatedProfileId ), generatedProfile );
414 }
415 }
416 }
417 }
418
419 private void mergeProfileBuild( Profile modelProfile, Profile generatedProfile )
420 {
421 if ( generatedProfile.getBuild() != null )
422 {
423 if ( modelProfile.getBuild() == null )
424 {
425 modelProfile.setBuild( new Build() );
426 }
427 mergeBuildPlugins( modelProfile.getBuild(), generatedProfile.getBuild() );
428
429 }
430 }
431
432 private void mergeModelBase( ModelBase model, ModelBase generatedModel )
433 {
434
435
436 @SuppressWarnings( "unchecked" )
437 Map<String, Dependency> dependenciesByIds = createDependencyMap( model.getDependencies() );
438 @SuppressWarnings( "unchecked" )
439 Map<String, Dependency> generatedDependenciesByIds = createDependencyMap( generatedModel.getDependencies() );
440
441 for ( String generatedDependencyId : generatedDependenciesByIds.keySet() )
442 {
443 if ( !dependenciesByIds.containsKey( generatedDependencyId ) )
444 {
445 model.addDependency( (Dependency) generatedDependenciesByIds.get( generatedDependencyId ) );
446 }
447 else
448 {
449 getLogger().warn( "Can not override property: " + generatedDependencyId );
450 }
451
452
453 model.getProperties().putAll( generatedModel.getProperties() );
454
455
456 }
457 }
458
459 private void mergeReportPlugins( Model model, Model generatedModel )
460 {
461 if ( generatedModel.getReporting() != null )
462 {
463 if ( model.getReporting() == null )
464 {
465 model.setReporting( new Reporting() );
466 }
467
468 @SuppressWarnings( "unchecked" )
469 Map<String, ReportPlugin> reportPluginsByIds = model.getReporting().getReportPluginsAsMap();
470 @SuppressWarnings( "unchecked" )
471 Map<String, ReportPlugin> generatedReportPluginsByIds =
472 generatedModel.getReporting().getReportPluginsAsMap();
473
474 for ( String generatedReportPluginsId : generatedReportPluginsByIds.keySet() )
475 {
476 if ( !reportPluginsByIds.containsKey( generatedReportPluginsId ) )
477 {
478 model.getReporting().addPlugin( generatedReportPluginsByIds.get( generatedReportPluginsId ) );
479 }
480 else
481 {
482 getLogger().warn( "Can not override report: " + generatedReportPluginsId );
483 }
484 }
485 }
486 }
487
488 private void mergeBuildPlugins( BuildBase modelBuild, BuildBase generatedModelBuild )
489 {
490 @SuppressWarnings( "unchecked" )
491 Map<String, Plugin> pluginsByIds = modelBuild.getPluginsAsMap();
492 @SuppressWarnings( "unchecked" )
493 List<Plugin> generatedPlugins = generatedModelBuild.getPlugins();
494
495 for ( Plugin generatedPlugin : generatedPlugins )
496 {
497 String generatedPluginsId = generatedPlugin.getKey();
498
499 if ( !pluginsByIds.containsKey( generatedPluginsId ) )
500 {
501 modelBuild.addPlugin( generatedPlugin );
502 }
503 else
504 {
505 getLogger().info( "Try to merge plugin configuration of plugins with id: " + generatedPluginsId );
506 Plugin modelPlugin = (Plugin) pluginsByIds.get( generatedPluginsId );
507
508 modelPlugin.setConfiguration( Xpp3DomUtils.mergeXpp3Dom( (Xpp3Dom) generatedPlugin.getConfiguration(),
509 (Xpp3Dom) modelPlugin.getConfiguration() ) );
510 }
511 }
512 }
513 }