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