View Javadoc

1   package org.apache.maven.project;
2   
3   /* ====================================================================
4    *   Licensed to the Apache Software Foundation (ASF) under one or more
5    *   contributor license agreements.  See the NOTICE file distributed with
6    *   this work for additional information regarding copyright ownership.
7    *   The ASF licenses this file to You under the Apache License, Version 2.0
8    *   (the "License"); you may not use this file except in compliance with
9    *   the License.  You may obtain a copy of the License at
10   *
11   *       http://www.apache.org/licenses/LICENSE-2.0
12   *
13   *   Unless required by applicable law or agreed to in writing, software
14   *   distributed under the License is distributed on an "AS IS" BASIS,
15   *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   *   See the License for the specific language governing permissions and
17   *   limitations under the License.
18   * ====================================================================
19   */
20  
21  import org.apache.commons.logging.Log;
22  import org.apache.commons.logging.LogFactory;
23  import org.apache.maven.ArtifactListBuilder;
24  import org.apache.maven.DependencyClasspathBuilder;
25  import org.apache.maven.MavenConstants;
26  import org.apache.maven.MavenUtils;
27  import org.apache.maven.jelly.MavenJellyContext;
28  import org.apache.maven.plugin.PluginManager;
29  import org.apache.maven.plugin.UnknownPluginException;
30  import org.apache.maven.project.io.stax.MavenStaxReader;
31  import org.apache.maven.project.io.stax.MavenStaxWriter;
32  import org.apache.maven.verifier.ChecksumVerificationException;
33  import org.apache.maven.verifier.DependencyVerifier;
34  import org.apache.maven.verifier.RepoConfigException;
35  import org.apache.maven.verifier.UnsatisfiedDependencyException;
36  
37  import java.io.ByteArrayOutputStream;
38  import java.io.File;
39  import java.io.IOException;
40  import java.io.OutputStreamWriter;
41  import java.io.Reader;
42  import java.net.URL;
43  import java.util.ArrayList;
44  import java.util.HashMap;
45  import java.util.Iterator;
46  import java.util.List;
47  import java.util.Map;
48  import java.util.Properties;
49  import java.util.Set;
50  import java.util.TreeSet;
51  
52  /**
53   * @author <a href="mailto:jason@zenplex.com">Jason van Zyl</a>
54   * @author <a href="mailto:vmassol@apache.org">Vincent Massol</a>
55   * @author <a href="mailto:glennm@apache.org">Glenn McAllister</a>
56   * @version $Id: Project.java 517014 2007-03-11 21:15:50Z ltheussl $
57   * @todo Change the file reference for the source POM to an URL.
58   */
59  public class Project
60  {
61      /**
62       * LOGGER for debug and output
63       */
64      private static final Log LOGGER = LogFactory.getLog( Project.class );
65  
66      /**
67       * Distributions map that associates the distribution ids
68       * with the distribution objects.
69       */
70      private HashMap versionMap;
71  
72      /**
73       * Parent project.
74       */
75      private Project parent;
76  
77      /**
78       * File that this POM object was derived from.
79       */
80      private File file;
81  
82      /**
83       * Map of dependency ids to their real paths in the system.
84       */
85      private Map dependencyPaths = new HashMap();
86  
87      /**
88       * Dependencies Map so that an individual dependency can
89       * be retrieved by id.
90       */
91      private Map dependencyMap = new HashMap();
92  
93      /**
94       * Artifact list.
95       */
96      private List artifactList;
97  
98      /**
99       * This project's Jelly context.
100      */
101     private MavenJellyContext context;
102 
103     /**
104      * TODO: use commons-collections.
105      */
106     private List contextStack = new ArrayList();
107 
108     /**
109      * the maven.xml file for this project
110      */
111     private File mavenXml;
112 
113     private final Model model;
114 
115     private String originalGroupId;
116 
117     /**
118      * Default constructor.
119      */
120     public Project()
121     {
122         model = new Model();
123     }
124 
125     /**
126      * Constructor with prebuilt model.
127      *
128      * @param in the input reader
129      * @throws Exception an error occured reading the file
130      * @todo should not have to throw Exception
131      */
132     public Project( Reader in )
133         throws Exception
134     {
135         MavenStaxReader reader = new MavenStaxReader();
136         model = reader.read( in );
137         resolveDependencies();
138         resolveVersions();
139     }
140 
141     /**
142      * Constructor with prebuilt model.
143      *
144      * @param url the input url
145      * @throws Exception an error occured reading the file
146      * @todo should not have to throw Exception
147      */
148     public Project( URL url )
149         throws Exception
150     {
151         MavenStaxReader reader = new MavenStaxReader();
152         model = reader.read( url.getFile() );
153         resolveDependencies();
154         resolveVersions();
155     }
156 
157     /**
158      * Constructor with prebuilt model.
159      *
160      * @param path the input path
161      * @throws Exception an error occured reading the file
162      * @todo should not have to throw Exception
163      */
164     public Project( String path )
165         throws Exception
166     {
167         MavenStaxReader reader = new MavenStaxReader();
168         model = reader.read( path );
169         resolveDependencies();
170         resolveVersions();
171     }
172 
173     /**
174      * @return the maven.xml file
175      */
176     public File getMavenXml()
177     {
178         // The getFile() is needed because interpolation calls this before the file is set
179         if ( ( mavenXml == null ) && ( getFile() != null ) )
180         {
181             mavenXml = new File( getFile().getParentFile(), MavenConstants.BUILD_FILE_NAME );
182         }
183         return mavenXml;
184     }
185 
186     /**
187      * @return true if the maven.xml file for the project exists
188      */
189     public boolean hasMavenXml()
190     {
191         File mavenXml = getMavenXml();
192         if ( mavenXml != null )
193         {
194             return mavenXml.exists();
195         }
196         else
197         {
198             return false;
199         }
200     }
201 
202     // ----------------------------------------------------------------------
203     // A C C E S S O R S
204     // ----------------------------------------------------------------------
205 
206     // trying to align dep.id with project.id
207     /**
208      * @return the id of the project
209      */
210     public String getId()
211     {
212         // The id has already been set.
213         if ( ( model.getId() != null ) && ( model.getId().indexOf( ":" ) > 0 ) )
214         {
215             return model.getId();
216         }
217         return getGroupId() + ":" + getArtifactId();
218     }
219 
220     public void setId( String id )
221     {
222         int i = id.indexOf( "+" );
223         int j = id.indexOf( ":" );
224 
225         if ( i > 0 )
226         {
227             setGroupId( id.substring( 0, i ) );
228             setArtifactId( id.replace( '+', '-' ) );
229         }
230         else if ( j > 0 )
231         {
232             setGroupId( id.substring( 0, j ) );
233             setArtifactId( id.substring( j + 1 ) );
234         }
235         else
236         {
237             setGroupId( id );
238             setArtifactId( id );
239         }
240     }
241 
242     /**
243      * Get the artifact id.
244      *
245      * @return The artifactId
246      */
247     public String getArtifactId()
248     {
249         return model.getArtifactId();
250     }
251 
252     /**
253      * Get the plugin context using the plugin name.
254      *
255      * @param pluginId Plugin name.
256      * @return The plugin context create for the named plugin when it was loaded for
257      *         this project.
258      * @throws UnknownPluginException if the plugin could not be found
259      * @todo [1.0] - when we are caching plugins, this should load on demand, also move to plugin manager
260      * @deprecated use the tag instead
261      */
262     public MavenJellyContext getPluginContext( String pluginId )
263         throws Exception
264     {
265         PluginManager pluginManager = context.getMavenSession().getPluginManager();
266         return pluginManager.getPluginContext( pluginId );
267     }
268 
269     /**
270      * Set the context attribute.
271      *
272      * @param context the context to use
273      */
274     public void setContext( MavenJellyContext context )
275     {
276         if ( contextStack.size() > 0 )
277         {
278             LOGGER.warn( "replacing a context when the stack is not empty" );
279         }
280         this.context = context;
281     }
282 
283     /**
284      * Push a new context onto the stack.
285      *
286      * @param context
287      */
288     public void pushContext( MavenJellyContext context )
289     {
290         LOGGER.debug( "pushing on " + context + " over " + this.context + " in " + getId() );
291         contextStack.add( this.context );
292         this.context = context;
293     }
294 
295     public void popContext()
296     {
297         MavenJellyContext context = (MavenJellyContext) contextStack.get( contextStack.size() - 1 );
298         contextStack.remove( contextStack.size() - 1 );
299         LOGGER.debug( "popping off " + this.context + " for " + context + " in " + getId() );
300         this.context = context;
301     }
302 
303     /**
304      * Get the context attribute.
305      *
306      * @return The
307      */
308     public MavenJellyContext getContext()
309     {
310         return context;
311     }
312 
313     /**
314      * Set the artifactList attribute.
315      *
316      * @param artifactList list of artifacts for the project
317      */
318     public void setArtifacts( List artifactList )
319     {
320         this.artifactList = artifactList;
321     }
322 
323     /**
324      * Get the atrifact attribute.
325      *
326      * @return The list of artifacts for the project
327      */
328     public List getArtifacts()
329     {
330         return artifactList;
331     }
332 
333     /**
334      * Set the file that this POM was derived from.
335      *
336      * @param file POM file
337      */
338     public void setFile( File file )
339     {
340         this.file = file;
341     }
342 
343     /**
344      * Get the file this POM was derived from
345      *
346      * @return POM file
347      */
348     public File getFile()
349     {
350         return file;
351     }
352 
353     /**
354      * @return the project that this one extends, if any
355      */
356     public Project getParent()
357     {
358         return parent;
359     }
360 
361     /**
362      * Determine whether this project has a parent.
363      *
364      * @return State of ancestry.
365      */
366     public boolean hasParent()
367     {
368         return getParent() != null;
369     }
370 
371     /**
372      * Set the project that this one extends
373      *
374      * @param parent the parent project
375      */
376     public void setParent( Project parent )
377     {
378         this.parent = parent;
379     }
380 
381     /**
382      * Get the parent's basedir.
383      *
384      * @return Parent's basedir.
385      */
386     public File parentBasedir()
387     {
388         return new File( getExtend() ).getParentFile();
389     }
390 
391     /**
392      * Get parent maven.xml file.
393      *
394      * @return Parent's maven.xml file.
395      */
396     public File parentMavenXml()
397     {
398         return new File( parentBasedir(), MavenConstants.BUILD_FILE_NAME );
399     }
400 
401     /**
402      * @return the directory name for this proejct's artifacts
403      */
404     public String getArtifactDirectory()
405     {
406         if ( getGroupId() != null )
407         {
408             return getGroupId();
409         }
410 
411         // Now we want the artifact directory to be the legacy form
412         // of the id which contains no ":" character so lets flip
413         // it back to legacy form.
414         return standardToLegacyId( getId() );
415     }
416 
417     /**
418      * Add a unique dependency for this project.
419      *
420      * @param dependency Dependency for this project.
421      */
422     public void addDependency( Dependency dependency )
423     {
424         if ( !getDependencies().contains( dependency ) )
425         {
426             model.addDependency( dependency );
427             dependencyMap.put( dependency.getKey(), dependency );
428         }
429     }
430 
431     /**
432      * @param srcList    source list to add items from
433      * @param targetList target list to add unique items to
434      * @todo eventually, just use sets instead.
435      */
436     static void mergeLists( List srcList, List targetList )
437     {
438         if ( srcList != null )
439         {
440             for ( Iterator i = srcList.iterator(); i.hasNext(); )
441             {
442                 Object o = i.next();
443                 if ( !targetList.contains( o ) )
444                 {
445                     targetList.add( o );
446                 }
447             }
448         }
449     }
450 
451     /**
452      * @param dependencies parent dependencies
453      * @todo eventually, just use the map
454      */
455     private void addParentDependencies( List dependencies )
456     {
457         for ( Iterator i = dependencies.iterator(); i.hasNext(); )
458         {
459             addDependency( (Dependency) i.next() );
460         }
461     }
462 
463     /**
464      * Get the list of dependent projects ids.
465      *
466      * @return the set of all dependencies' project ids
467      */
468     public Set getDependentProjectIds()
469     {
470         Set projectIds = new TreeSet();
471         List dependencies = getDependencies();
472         Dependency dependency;
473         for ( int i = 0; i < dependencies.size(); i++ )
474         {
475             dependency = (Dependency) dependencies.get( i );
476             projectIds.add( dependency.getId() );
477         }
478         return projectIds;
479     }
480 
481     /**
482      * Set an individual dependency's classpath entry.
483      *
484      * @param depId Dependency id.
485      * @param path  Classpath for the given dependency.
486      */
487     public void setDependencyPath( String depId, String path )
488     {
489         dependencyPaths.put( depId, path );
490     }
491 
492     /**
493      * Get an individual dependencies classpath entry.
494      *
495      * @param depId Dependency id.
496      * @return Classpath for the given dependency.
497      */
498     public String getDependencyPath( String depId )
499     {
500         return (String) dependencyPaths.get( legacyToDependencyKey( depId ) );
501     }
502 
503     /**
504      * Get an individual dependency by id.
505      *
506      * @param depId Dependency id.
507      * @return Dependency for the given id.
508      */
509     public Dependency getDependency( String depId )
510     {
511         return (Dependency) dependencyMap.get( legacyToDependencyKey( depId ) );
512     }
513 
514     /**
515      * Get flag to indicate the presence of a source repository.
516      *
517      * @return <code>true</code> if the project is part of a repository,
518      *         <code>false</code> otherwise
519      */
520     public boolean hasRepository()
521     {
522         return ( getRepository() != null );
523     }
524 
525     /**
526      * Indicate whether the POM is of the latest version.
527      *
528      * @return <code>true</code> if the pom version is the same as the
529      *         currently running version of maven specified by {@link MavenConstants},
530      *         or <code>false</code> otherwise
531      */
532     public boolean isPomCurrent()
533     {
534         return Integer.parseInt( getPomVersion() ) == MavenConstants.POM_VERSION;
535     }
536 
537     /**
538      * Return a distribution for this project.
539      *
540      * @param versionId the id of the version to return
541      * @return List of distributions.
542      */
543     public Version getVersionById( String versionId )
544     {
545         return (Version) versionMap.get( versionId );
546     }
547 
548     // ----------------------------------------------------------------------
549     //
550     // ----------------------------------------------------------------------
551 
552     /**
553      * Flag to indicate the project has been verified.
554      */
555     private boolean initialized = false;
556 
557     /**
558      * Dependency Verifier
559      */
560     private DependencyVerifier dependencyVerifier;
561 
562     /**
563      * Dependency classpath used for compilation.
564      */
565     private String dependencyClasspath;
566 
567     /**
568      * Initialize the project. This consists of the following stages.
569      * <p/>
570      * 1) Build the Ant project that can be used within plugin.jelly scripts and
571      * other Jelly scripts.
572      * <p/>
573      * 2) Build the artifact list.
574      * <p/>
575      * 3) Build the dependency classpath.
576      * <p/>
577      * 4) Create the dependency verifier.
578      * <p/>
579      * 5) Initialize the driver for this project.
580      *
581      * @throws IOException If an error occurs during project initialization.
582      */
583     public void initialize()
584         throws IOException
585     {
586         if ( initialized )
587         {
588             return;
589         }
590 
591         buildArtifactList();
592         dependencyClasspath = DependencyClasspathBuilder.build( this );
593         setDependencyVerifier( new DependencyVerifier( this ) );
594         if ( getBuild() != null )
595         {
596             resolveDirectories( getBuild(), file.getParentFile() );
597         }
598         initialized = true;
599     }
600 
601     /**
602      * Verify the dependencies for this project.
603      *
604      * @throws RepoConfigException            If an error occurs checking the local settings.
605      * @throws UnsatisfiedDependencyException If an error occurs due to missing exceptions.
606      * @throws ChecksumVerificationException  if the downloaded files fail verification
607      */
608     public void verifyDependencies()
609         throws RepoConfigException, UnsatisfiedDependencyException, ChecksumVerificationException
610     {
611         LOGGER.debug( "Verifying dependencies for " + getId() );
612 
613         // Only attempt to verify the dependencies if a project.xml file exists, and it is fully-fledged (not an uninitialized parent project).
614         if ( ( getFile() != null ) && getFile().exists() && initialized )
615         {
616             getDependencyVerifier().verify();
617         }
618     }
619 
620     /**
621      * Set the dependency verifier.
622      *
623      * @param dependencyVerifier Dependency Verifier.
624      */
625     public void setDependencyVerifier( DependencyVerifier dependencyVerifier )
626     {
627         this.dependencyVerifier = dependencyVerifier;
628     }
629 
630     /**
631      * Get the dependency verifier for this project. We can probably share a
632      * dependency verifier.
633      *
634      * @return The DependencyVerifier for this project.
635      */
636     public DependencyVerifier getDependencyVerifier()
637     {
638         return dependencyVerifier;
639     }
640 
641     /**
642      * Get the dependency classpath.
643      *
644      * @return The dependency classpath.
645      */
646     public String getDependencyClasspath()
647     {
648         return dependencyClasspath;
649     }
650 
651     /**
652      * Build the artifact list.
653      */
654     public void buildArtifactList()
655     {
656         artifactList = ArtifactListBuilder.build( this );
657     }
658 
659     // ----------------------------------------------------------------------
660     // L E G A C Y  I D  S U P P O R T
661     // ----------------------------------------------------------------------
662 
663     /**
664      * This is to support methods that are using the legacy form of
665      * the project id. Currently the id is <groupId>:<artifactId> but the
666      * following methods assume <groupId>:
667      * <p/>
668      * Project::getDependencyPath( <groupId> )
669      * Project::getDependency( <groupId> )
670      * <p/>
671      * We don't want users to have to alter any usage until we have properly
672      * deprecated the use of the <groupId> form.
673      *
674      * @param id the legacy id to convert
675      * @return the id in standard format
676      */
677     public static String legacyToStandardId( String id )
678     {
679         String newId = id;
680         if ( id.indexOf( "+" ) != -1 )
681         {
682             // legacy format is groupId "+" partial artifactId
683             // standard format is groupId ":" groupId "-" partialArtifactId
684             int plusPos = id.indexOf( "+" );
685             String groupId = id.substring( 0, plusPos );
686             String partialArtifactId = id.substring( plusPos + 1 );
687             newId = groupId + ":" + groupId + "-" + partialArtifactId;
688         }
689         else if ( id.indexOf( ":" ) == -1 )
690         {
691             // if no :, set groupId as artifactId
692             newId += ":" + id;
693         }
694         return newId;
695     }
696 
697     public String legacyToDependencyKey( String id )
698     {
699         String newId = legacyToStandardId( id );
700         int sepIndex = newId.indexOf( ':' );
701 
702         // check for type
703         sepIndex = newId.indexOf( ':', sepIndex + 1 );
704         if ( sepIndex < 0 )
705         {
706             for ( Iterator i = dependencyMap.keySet().iterator(); i.hasNext(); )
707             {
708                 String depId = (String) i.next();
709                 if ( depId.equals( newId ) )
710                 {
711                     return depId;
712                 }
713                 if ( depId.startsWith( newId + ":" ) )
714                 {
715                     return depId;
716                 }
717             }
718             newId += ":jar";
719         }
720         return newId;
721     }
722 
723     /**
724      * This method is to support methods are expecting legacy ids. The following
725      * methods expect legacy ids.
726      * <p/>
727      * MavenJellyContext::getMavenJarOverride( <groupId> )
728      * Project::getArtifactDirectory( <groupId> )
729      * <p/>
730      * We don't want users to have to alter any usage until we have properly
731      * deprecated the use of the <groupId> form.
732      *
733      * @param id the standard id to convert
734      * @return the id in legacy format
735      */
736     public static String standardToLegacyId( String id )
737     {
738         int i = id.indexOf( ":" );
739 
740         if ( i > 0 )
741         {
742             id = id.substring( i + 1 );
743         }
744 
745         return id;
746     }
747 
748     /**
749      * Setup inheritance from a parent project.
750      *
751      * @param parent the parent project
752      */
753     public void mergeParent( Project parent )
754     {
755         setParent( parent );
756 
757         if ( parent == null )
758         {
759             return;
760         }
761 
762         if ( getRepository() == null )
763         {
764             setRepository( parent.getRepository() );
765         }
766 
767         if ( getName() == null )
768         {
769             setName( parent.getName() );
770         }
771 
772         if ( getUrl() == null )
773         {
774             setUrl( parent.getUrl() );
775         }
776 
777         if ( getLogo() == null )
778         {
779             setLogo( parent.getLogo() );
780         }
781 
782         if ( getDescription() == null )
783         {
784             setDescription( parent.getDescription() );
785         }
786 
787         if ( getIssueTrackingUrl() == null )
788         {
789             setIssueTrackingUrl( parent.getIssueTrackingUrl() );
790         }
791 
792         if ( getCurrentVersion() == null )
793         {
794             setCurrentVersion( parent.getCurrentVersion() );
795         }
796 
797         if ( getOrganization() == null )
798         {
799             setOrganization( parent.getOrganization() );
800         }
801 
802         if ( getInceptionYear() == null )
803         {
804             setInceptionYear( parent.getInceptionYear() );
805         }
806 
807         if ( getPackage() == null )
808         {
809             setPackage( parent.getPackage() );
810         }
811 
812         if ( getSiteAddress() == null )
813         {
814             setSiteAddress( parent.getSiteAddress() );
815         }
816 
817         if ( getSiteDirectory() == null )
818         {
819             setSiteDirectory( parent.getSiteDirectory() );
820         }
821 
822         if ( getDistributionSite() == null )
823         {
824             setDistributionSite( parent.getDistributionSite() );
825         }
826 
827         if ( getDistributionDirectory() == null )
828         {
829             setDistributionDirectory( parent.getDistributionDirectory() );
830         }
831 
832         if ( getPomVersion() == null )
833         {
834             setPomVersion( parent.getPomVersion() );
835         }
836 
837         if ( getGumpRepositoryId() == null )
838         {
839             setGumpRepositoryId( parent.getGumpRepositoryId() );
840         }
841 
842         if ( getShortDescription() == null )
843         {
844             setShortDescription( parent.getShortDescription() );
845         }
846 
847         /*
848          if ( model.getGroupId() == null )
849          {
850          // Don't inherit if it was from an id element
851          if ( parent.originalGroupId != null || model.getId() == null )
852          {
853          // Don't inherit if only artifactId is given, see MAVEN-1704
854          if ( !( parent.originalGroupId == null && model.getId() == null ) )
855          {
856          model.setGroupId( parent.model.getGroupId() );
857          }
858          }
859          }
860          */
861 
862         // This is equivalent to the above
863         if ( model.getGroupId() == null )
864         {
865             if ( parent.originalGroupId != null )
866             {
867                 model.setGroupId( parent.model.getGroupId() );
868             }
869         }
870 
871         if ( getBuild() == null )
872         {
873             // Must copy as resolveDirs changes entries
874             setBuild( new Build() );
875             mergeParent( parent.getBuild(), getBuild() );
876         }
877         else
878         {
879             mergeParent( parent.getBuild(), getBuild() );
880         }
881 
882         // The following replaces the list merges
883         if ( ( getMailingLists() == null ) || getMailingLists().isEmpty() )
884         {
885             setMailingLists( parent.getMailingLists() );
886         }
887         if ( ( getContributors() == null ) || getContributors().isEmpty() )
888         {
889             setContributors( parent.getContributors() );
890         }
891         if ( ( getDevelopers() == null ) || getDevelopers().isEmpty() )
892         {
893             setDevelopers( parent.getDevelopers() );
894         }
895         if ( ( getVersions() == null ) || getVersions().isEmpty() )
896         {
897             model.setVersions( parent.getVersions() );
898             resolveVersions();
899         }
900         if ( ( getLicenses() == null ) || getLicenses().isEmpty() )
901         {
902             setLicenses( parent.getLicenses() );
903         }
904         if ( ( getBranches() == null ) || getBranches().isEmpty() )
905         {
906             setBranches( parent.getBranches() );
907         }
908         if ( ( getReports() == null ) || getReports().isEmpty() )
909         {
910             setReports( parent.getReports() );
911         }
912         if ( ( getPackageGroups() == null ) || getPackageGroups().isEmpty() )
913         {
914             setPackageGroups( parent.getPackageGroups() );
915         }
916 
917         //mergeLists( parent.mailingLists, mailingLists );
918         //mergeLists( parent.contributors, contributors );
919         //mergeLists( parent.developers, developers );
920         //mergeLists( parent.licenses, licenses );
921         //mergeLists( parent.branches, branches );
922         //mergeLists( parent.reports, reports );
923         //mergeLists( parent.packageGroups, packageGroups );
924 
925         // Now let's do some magic with versions and dependencies as they have maps.
926         // We take all the parent's and put them in with the child's.
927         //addParentVersions( parent.versions );
928         addParentDependencies( parent.getDependencies() );
929     }
930 
931     /**
932      * Resolve relative directories against a base directory.
933      *
934      * @param build
935      * @param basedir the base directory
936      * @throws java.io.IOException file resolution error
937      */
938     private static void resolveDirectories( Build build, File basedir )
939         throws IOException
940     {
941         for ( Iterator i = build.getResources().iterator(); i.hasNext(); )
942         {
943             Resource r = (Resource) i.next();
944             resolveDirectory( r, basedir );
945         }
946 
947         if ( build.getUnitTest() != null )
948         {
949             for ( Iterator i = build.getUnitTest().getResources().iterator(); i.hasNext(); )
950             {
951                 Resource r = (Resource) i.next();
952                 resolveDirectory( r, basedir );
953             }
954         }
955 
956         if ( ( build.getSourceDirectory() != null ) && ( build.getSourceDirectory().length() > 0 ) )
957         {
958             build.setSourceDirectory( MavenUtils.makeAbsolutePath( basedir, build.getSourceDirectory() ) );
959         }
960 
961         if ( ( build.getAspectSourceDirectory() != null ) && ( build.getAspectSourceDirectory().length() > 0 ) )
962         {
963             build.setAspectSourceDirectory( MavenUtils.makeAbsolutePath( basedir, build.getAspectSourceDirectory() ) );
964         }
965 
966         if ( ( build.getUnitTestSourceDirectory() != null ) && ( build.getUnitTestSourceDirectory().length() > 0 ) )
967         {
968             build
969                 .setUnitTestSourceDirectory( MavenUtils.makeAbsolutePath( basedir, build.getUnitTestSourceDirectory() ) );
970         }
971 
972         if ( ( build.getIntegrationUnitTestSourceDirectory() != null )
973             && ( build.getIntegrationUnitTestSourceDirectory().length() > 0 ) )
974         {
975             build.setIntegrationUnitTestSourceDirectory( MavenUtils.makeAbsolutePath( basedir, build
976                 .getIntegrationUnitTestSourceDirectory() ) );
977         }
978     }
979 
980     /**
981      * Setup inheritance from a parent project build element.
982      *
983      * @param parent the parent build element
984      * @param child
985      */
986     private static void mergeParent( Build parent, Build child )
987     {
988         if ( parent == null )
989         {
990             return;
991         }
992 
993         if ( child.getDefaultGoal() == null )
994         {
995             child.setDefaultGoal( parent.getDefaultGoal() );
996         }
997 
998         if ( child.getSourceDirectory() == null )
999         {
1000             child.setSourceDirectory( parent.getSourceDirectory() );
1001         }
1002 
1003         if ( child.getUnitTestSourceDirectory() == null )
1004         {
1005             child.setUnitTestSourceDirectory( parent.getUnitTestSourceDirectory() );
1006         }
1007 
1008         if ( child.getIntegrationUnitTestSourceDirectory() == null )
1009         {
1010             child.setIntegrationUnitTestSourceDirectory( parent.getIntegrationUnitTestSourceDirectory() );
1011         }
1012 
1013         if ( child.getAspectSourceDirectory() == null )
1014         {
1015             child.setAspectSourceDirectory( parent.getAspectSourceDirectory() );
1016         }
1017 
1018         if ( child.getNagEmailAddress() == null )
1019         {
1020             child.setNagEmailAddress( parent.getNagEmailAddress() );
1021         }
1022 
1023         if ( ( child.getResources() == null ) || child.getResources().isEmpty() )
1024         {
1025             child.setResources( parent.getResources() );
1026         }
1027         if ( ( child.getSourceModifications() == null ) || child.getSourceModifications().isEmpty() )
1028         {
1029             child.setSourceModifications( parent.getSourceModifications() );
1030         }
1031 
1032         if ( child.getUnitTest() == null )
1033         {
1034             child.setUnitTest( parent.getUnitTest() );
1035         }
1036         else
1037         {
1038             mergeUnitTestParent( parent.getUnitTest(), child.getUnitTest() );
1039         }
1040     }
1041 
1042     private static void mergeUnitTestParent( UnitTest parent, UnitTest child )
1043     {
1044         if ( parent == null )
1045         {
1046             return;
1047         }
1048 
1049         // The following replaces the list merges
1050         if ( ( child.getResources() == null ) || child.getResources().isEmpty() )
1051         {
1052             child.setResources( parent.getResources() );
1053         }
1054         if ( ( child.getIncludes() == null ) || child.getIncludes().isEmpty() )
1055         {
1056             child.setIncludes( parent.getIncludes() );
1057         }
1058         if ( ( child.getExcludes() == null ) || child.getExcludes().isEmpty() )
1059         {
1060             child.setExcludes( parent.getExcludes() );
1061         }
1062     }
1063 
1064     private static void resolveDirectory( Resource resource, File basedir )
1065         throws IOException
1066     {
1067         if ( resource.getDirectory() != null )
1068         {
1069             resource.setDirectory( MavenUtils.makeAbsolutePath( basedir, resource.getDirectory() ) );
1070         }
1071         else
1072         {
1073             resource.setDirectory( basedir.getCanonicalPath() );
1074         }
1075     }
1076 
1077     public void addBranch( Branch branch )
1078     {
1079         model.addBranch( branch );
1080     }
1081 
1082     public void addContributor( Contributor contributor )
1083     {
1084         model.addContributor( contributor );
1085     }
1086 
1087     public void addDeveloper( Developer developer )
1088     {
1089         model.addDeveloper( developer );
1090     }
1091 
1092     public void addLicense( License license )
1093     {
1094         model.addLicense( license );
1095     }
1096 
1097     public void addMailingList( MailingList mailingList )
1098     {
1099         model.addMailingList( mailingList );
1100     }
1101 
1102     public void addPackageGroup( PackageGroup packageGroup )
1103     {
1104         model.addPackageGroup( packageGroup );
1105     }
1106 
1107     public void addProperty( String s, String s1 )
1108     {
1109         model.addProperty( s, s1 );
1110     }
1111 
1112     public void addReport( String s )
1113     {
1114         model.addReport( s );
1115     }
1116 
1117     public List getBranches()
1118     {
1119         return model.getBranches();
1120     }
1121 
1122     public Build getBuild()
1123     {
1124         return model.getBuild();
1125     }
1126 
1127     public List getContributors()
1128     {
1129         return model.getContributors();
1130     }
1131 
1132     public String getCurrentVersion()
1133     {
1134         return model.getCurrentVersion();
1135     }
1136 
1137     public List getDependencies()
1138     {
1139         return model.getDependencies();
1140     }
1141 
1142     public String getDescription()
1143     {
1144         return model.getDescription();
1145     }
1146 
1147     public List getDevelopers()
1148     {
1149         return model.getDevelopers();
1150     }
1151 
1152     public String getDistributionDirectory()
1153     {
1154         return model.getDistributionDirectory();
1155     }
1156 
1157     public String getDistributionSite()
1158     {
1159         return model.getDistributionSite();
1160     }
1161 
1162     public String getExtend()
1163     {
1164         return model.getExtend();
1165     }
1166 
1167     public String getGroupId()
1168     {
1169         return model.getGroupId();
1170     }
1171 
1172     public String getGumpRepositoryId()
1173     {
1174         return model.getGumpRepositoryId();
1175     }
1176 
1177     public String getInceptionYear()
1178     {
1179         return model.getInceptionYear();
1180     }
1181 
1182     public String getIssueTrackingUrl()
1183     {
1184         return model.getIssueTrackingUrl();
1185     }
1186 
1187     public List getLicenses()
1188     {
1189         return model.getLicenses();
1190     }
1191 
1192     public String getLogo()
1193     {
1194         return model.getLogo();
1195     }
1196 
1197     public List getMailingLists()
1198     {
1199         return model.getMailingLists();
1200     }
1201 
1202     public String getName()
1203     {
1204         return model.getName();
1205     }
1206 
1207     public Organization getOrganization()
1208     {
1209         return model.getOrganization();
1210     }
1211 
1212     public String getPackage()
1213     {
1214         return model.getPackage();
1215     }
1216 
1217     public List getPackageGroups()
1218     {
1219         return model.getPackageGroups();
1220     }
1221 
1222     public String getPomVersion()
1223     {
1224         return model.getPomVersion();
1225     }
1226 
1227     public Properties getProperties()
1228     {
1229         return model.getProperties();
1230     }
1231 
1232     public List getReports()
1233     {
1234         return model.getReports();
1235     }
1236 
1237     public Repository getRepository()
1238     {
1239         return model.getRepository();
1240     }
1241 
1242     public String getShortDescription()
1243     {
1244         return model.getShortDescription();
1245     }
1246 
1247     public String getSiteAddress()
1248     {
1249         return model.getSiteAddress();
1250     }
1251 
1252     public String getSiteDirectory()
1253     {
1254         return model.getSiteDirectory();
1255     }
1256 
1257     public String getUrl()
1258     {
1259         return model.getUrl();
1260     }
1261 
1262     public List getVersions()
1263     {
1264         return model.getVersions();
1265     }
1266 
1267     public void setVersions( List list )
1268     {
1269         model.setVersions( list );
1270         resolveVersions();
1271     }
1272 
1273     public void setArtifactId( String s )
1274     {
1275         model.setArtifactId( s );
1276     }
1277 
1278     public void setBranches( List list )
1279     {
1280         model.setBranches( list );
1281     }
1282 
1283     public void setBuild( Build build )
1284     {
1285         model.setBuild( build );
1286     }
1287 
1288     public void setContributors( List list )
1289     {
1290         model.setContributors( list );
1291     }
1292 
1293     public void setCurrentVersion( String s )
1294     {
1295         model.setCurrentVersion( s );
1296     }
1297 
1298     public void setDependencies( List list )
1299     {
1300         model.setDependencies( list );
1301         dependencyMap.clear();
1302         resolveDependencies();
1303     }
1304 
1305     public void setDescription( String s )
1306     {
1307         model.setDescription( s );
1308     }
1309 
1310     public void setDevelopers( List list )
1311     {
1312         model.setDevelopers( list );
1313     }
1314 
1315     public void setDistributionDirectory( String s )
1316     {
1317         model.setDistributionDirectory( s );
1318     }
1319 
1320     public void setDistributionSite( String s )
1321     {
1322         model.setDistributionSite( s );
1323     }
1324 
1325     public void setExtend( String s )
1326     {
1327         model.setExtend( s );
1328     }
1329 
1330     public void setGroupId( String s )
1331     {
1332         model.setGroupId( s );
1333     }
1334 
1335     public void setGumpRepositoryId( String s )
1336     {
1337         model.setGumpRepositoryId( s );
1338     }
1339 
1340     public void setInceptionYear( String s )
1341     {
1342         model.setInceptionYear( s );
1343     }
1344 
1345     public void setIssueTrackingUrl( String s )
1346     {
1347         model.setIssueTrackingUrl( s );
1348     }
1349 
1350     public void setLicenses( List list )
1351     {
1352         model.setLicenses( list );
1353     }
1354 
1355     public void setLogo( String s )
1356     {
1357         model.setLogo( s );
1358     }
1359 
1360     public void setMailingLists( List list )
1361     {
1362         model.setMailingLists( list );
1363     }
1364 
1365     public void setName( String s )
1366     {
1367         model.setName( s );
1368     }
1369 
1370     public void setOrganization( Organization organization )
1371     {
1372         model.setOrganization( organization );
1373     }
1374 
1375     public void setPackage( String s )
1376     {
1377         model.setPackage( s );
1378     }
1379 
1380     public void setPackageGroups( List list )
1381     {
1382         model.setPackageGroups( list );
1383     }
1384 
1385     public void setPomVersion( String s )
1386     {
1387         model.setPomVersion( s );
1388     }
1389 
1390     public void setProperties( Properties properties )
1391     {
1392         model.setProperties( properties );
1393     }
1394 
1395     public void setReports( List list )
1396     {
1397         model.setReports( list );
1398     }
1399 
1400     public void setRepository( Repository repository )
1401     {
1402         model.setRepository( repository );
1403     }
1404 
1405     public void setShortDescription( String s )
1406     {
1407         model.setShortDescription( s );
1408     }
1409 
1410     public void setSiteAddress( String s )
1411     {
1412         model.setSiteAddress( s );
1413     }
1414 
1415     public void setSiteDirectory( String s )
1416     {
1417         model.setSiteDirectory( s );
1418     }
1419 
1420     public void setUrl( String s )
1421     {
1422         model.setUrl( s );
1423     }
1424 
1425     /**
1426      * Add a distribution to this project.
1427      *
1428      * @param version Distribution for this project.
1429      */
1430     public void addVersion( Version version )
1431     {
1432         if ( versionMap != null )
1433         {
1434             // if we've already lazy iitialised, keep it up to date
1435             versionMap.put( version.getId(), version );
1436         }
1437         model.addVersion( version );
1438     }
1439 
1440     /**
1441      * @todo hopefully can be replaced by appropraite getters in modello
1442      */
1443     public void resolveIds()
1444     {
1445         originalGroupId = model.getGroupId();
1446         if ( model.getId() != null )
1447         {
1448             if ( ( model.getGroupId() == null ) && ( model.getArtifactId() == null ) )
1449             {
1450                 setId( model.getId() );
1451             }
1452             else
1453             {
1454                 String id = model.getId();
1455                 if ( model.getGroupId() == null )
1456                 {
1457                     int j = id.indexOf( ":" );
1458                     if ( j > 0 )
1459                     {
1460                         setGroupId( id.substring( 0, j ) );
1461                     }
1462                     else
1463                     {
1464                         setGroupId( id );
1465                     }
1466                 }
1467                 if ( model.getArtifactId() == null )
1468                 {
1469                     int j = id.indexOf( ":" );
1470                     if ( j > 0 )
1471                     {
1472                         setArtifactId( id.substring( j + 1 ) );
1473                     }
1474                     else
1475                     {
1476                         setArtifactId( id );
1477                     }
1478                 }
1479             }
1480         }
1481         else if ( model.getGroupId() == null )
1482         {
1483             model.setGroupId( model.getArtifactId() );
1484             LOGGER.debug( "No groupId found, setting to: " + model.getArtifactId() );
1485         }
1486     }
1487 
1488     private void resolveVersions()
1489     {
1490         versionMap = new HashMap();
1491         for ( Iterator i = getVersions().iterator(); i.hasNext(); )
1492         {
1493             Version version = (Version) i.next();
1494             versionMap.put( version.getId(), version );
1495         }
1496     }
1497 
1498     /**
1499      * @todo hopefully can be replaced by appropraite getters in modello
1500      */
1501     private void resolveDependencies()
1502     {
1503         for ( Iterator i = getDependencies().iterator(); i.hasNext(); )
1504         {
1505             Dependency dependency = (Dependency) i.next();
1506             if ( dependency.getId() != null )
1507             {
1508                 if ( dependency.getGroupId() == null )
1509                 {
1510                     String id = dependency.getId();
1511                     int k = id.indexOf( "+" );
1512                     int j = id.indexOf( ":" );
1513 
1514                     if ( k > 0 )
1515                     {
1516                         dependency.setGroupId( id.substring( 0, k ) );
1517                         dependency.setArtifactId( id.replace( '+', '-' ) );
1518                     }
1519                     else if ( j > 0 )
1520                     {
1521                         dependency.setGroupId( id.substring( 0, j ) );
1522                         dependency.setArtifactId( id.substring( j + 1 ) );
1523                     }
1524                     else
1525                     {
1526                         dependency.setGroupId( id );
1527                     }
1528                 }
1529                 if ( dependency.getArtifactId() == null )
1530                 {
1531                     dependency.setArtifactId( dependency.getId() );
1532                 }
1533             }
1534             else if ( dependency.getGroupId() == null )
1535             {
1536                 dependency.setGroupId( dependency.getArtifactId() );
1537                 LOGGER.debug( "Dependency has no groupId, setting to: " + dependency.getArtifactId() );
1538             }
1539             dependency.setId( dependency.getGroupId() + ":" + dependency.getArtifactId() );
1540             dependencyMap.put( dependency.getKey(), dependency );
1541         }
1542     }
1543 
1544     /**
1545      * Create an XML string from the project.
1546      *
1547      * @return XML representation of the project
1548      * @throws Exception FIXME
1549      */
1550     public String getProjectAsString()
1551         throws Exception
1552     {
1553         ByteArrayOutputStream projectStream = new ByteArrayOutputStream();
1554         if ( model.getModelEncoding() == null )
1555             model.setModelEncoding( "UTF-8" );
1556         OutputStreamWriter w = new OutputStreamWriter( projectStream, model.getModelEncoding() );
1557         try
1558         {
1559             MavenStaxWriter writer = new MavenStaxWriter();
1560             writer.write( w, model );
1561         }
1562         finally
1563         {
1564             w.close();
1565         }
1566         return projectStream.toString( System.getProperty( "file.encoding" ) );
1567     }
1568 
1569     public String toString()
1570     {
1571         return getName() == null ? super.toString() : getName();
1572     }
1573 
1574     public boolean equals( Object o )
1575     {
1576         if ( o.equals( this ) )
1577         {
1578             return true;
1579         }
1580 
1581         if ( !( o instanceof Project ) )
1582         {
1583             return false;
1584         }
1585 
1586         Project project = (Project) o;
1587         return getId().equals( project.getId() );
1588     }
1589 
1590     public int hashCode()
1591     {
1592         return getId().hashCode();
1593     }
1594 }