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