View Javadoc

1   package org.apache.maven.jelly.tags.maven;
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 java.util.ArrayList;
22  import java.util.Iterator;
23  import java.util.List;
24  
25  import org.apache.maven.project.Dependency;
26  import org.apache.maven.project.Project;
27  import org.apache.maven.werkz.Action;
28  import org.apache.maven.werkz.CyclicGoalChainException;
29  import org.apache.maven.werkz.Goal;
30  import org.apache.maven.werkz.NoActionDefinitionException;
31  import org.apache.maven.werkz.Session;
32  import org.apache.maven.werkz.UnattainableGoalException;
33  import org.apache.maven.werkz.WerkzProject;
34  
35  /**
36   * THIS CLASS IS NOT THREADSAFE.
37   *
38   * @author <a href="mailto:bwalding@apache.org">Ben Walding</a>
39   * @version $Id: WerkzDependencyResolver.java 517014 2007-03-11 21:15:50Z ltheussl $
40   */
41  public class WerkzDependencyResolver
42      implements DependencyResolverInterface
43  {
44      private List projects = new ArrayList();
45  
46      private final List sortedGoals = new ArrayList();
47  
48      private Goal doItAll = null;
49  
50      private WerkzProject wproject = null;
51  
52      /**
53       * @see org.apache.maven.jelly.tags.maven.DependencyResolverInterface#clear()
54       */
55      public void clear()
56      {
57          projects.clear();
58          doItAll = null;
59      }
60  
61      /**
62       * @see org.apache.maven.jelly.tags.maven.DependencyResolverInterface#setProjects(java.util.List)
63       */
64      public void setProjects( List projects )
65      {
66          this.projects = projects;
67      }
68  
69      /**
70       * Retrieves the existing goal for a project (based on Id).
71       * If no goal exists, an exception is thrown.
72       *
73       * @param project the project to retrieve a goal from
74       * @return ProjectGoal
75       */
76      protected ProjectGoal getExistingGoal( Project project )
77      {
78          ProjectGoal goal = (ProjectGoal) wproject.getGoal( project.getId() );
79  
80          if ( goal == null )
81          {
82              throw new NullPointerException( "No goal exists : " + project.getId() );
83          }
84          else
85          {
86              return goal;
87          }
88      }
89  
90      /**
91       * Retrieves the existing goal for a project (based on Id).
92       * If no goal exists, one is created for this given project.
93       *
94       * @param project
95       * @param sourceBuild
96       * @return ProjectGoal
97       */
98      protected ProjectGoal getOrCreateGoal( Project project, boolean sourceBuild )
99      {
100         ProjectGoal goal = (ProjectGoal) wproject.getGoal( project.getId() );
101         if ( goal == null )
102         {
103             goal = new ProjectGoal( project, sourceBuild );
104             goal.setAction( new ListAddAction( goal, sortedGoals ) );
105             wproject.addGoal( goal );
106         }
107         return goal;
108     }
109 
110     /**
111      * Builds the projects / dependencies into an internal acyclic directed graph
112      */
113     public void buildGraph()
114         throws CyclicGoalChainException
115     {
116         if ( doItAll != null )
117         {
118             return;
119         }
120 
121         try
122         {
123             wproject = new WerkzProject();
124 
125             doItAll = new Goal( "DO_IT_ALL" );
126             doItAll.setAction( new DummyAction() );
127 
128             //Initialise all the true goals of the system
129             Iterator iter = projects.iterator();
130             while ( iter.hasNext() )
131             {
132                 Project project = (Project) iter.next();
133                 Goal projectGoal = getOrCreateGoal( project, true );
134                 doItAll.addPrecursor( projectGoal );
135             }
136 
137             //Now add the dependencies
138             iter = projects.iterator();
139             while ( iter.hasNext() )
140             {
141                 Project project = (Project) iter.next();
142                 Goal projectGoal = getExistingGoal( project );
143 
144                 Iterator depIter = project.getDependencies().iterator();
145                 while ( depIter.hasNext() )
146                 {
147                     Dependency dep = (Dependency) depIter.next();
148                     Project depProject = new Project();
149                     depProject.setId( dep.getId() );
150 
151                     Goal depGoal = getOrCreateGoal( depProject, false );
152                     projectGoal.addPrecursor( depGoal );
153                 }
154             }
155         }
156         catch ( CyclicGoalChainException e )
157         {
158             doItAll = null;
159             wproject = new WerkzProject();
160             // We want to get the right exception
161             throw e;
162         }
163     }
164 
165     /**
166      * @see org.apache.maven.jelly.tags.maven.DependencyResolverInterface#getSortedDependencies(org.apache.maven.project.Project)
167      */
168     public List getSortedDependencies( Project project )
169         throws DependencyResolverException
170     {
171         return getSortedDependencies( project, false );
172     }
173 
174     /**
175      * Filters the given list of goals, and returns the associated projects
176      * <p/>
177      * If param:sourceBuild == true, include goal
178      * If param:sourceBuild == false, include goal if goal:sourceBuild == true
179      *
180      * @param goals
181      * @param sourceBuild
182      * @return List
183      */
184     public List getProjects( List goals, boolean sourceBuild )
185     {
186         List result = new ArrayList();
187         Iterator iter = goals.iterator();
188         while ( iter.hasNext() )
189         {
190             ProjectGoal goal = (ProjectGoal) iter.next();
191 
192             if ( ( sourceBuild ) || ( !sourceBuild && goal.getSourceBuild() ) )
193             {
194                 result.add( ( goal ).getProject() );
195             }
196 
197         }
198         return result;
199     }
200 
201     /**
202      * @see org.apache.maven.jelly.tags.maven.DependencyResolverInterface#getSortedDependencies(org.apache.maven.project.Project, boolean)
203      */
204     public List getSortedDependencies( Project project, boolean sourceBuild )
205         throws DependencyResolverException
206     {
207         try
208         {
209             buildGraph();
210             sortedGoals.clear();
211             Session session = new Session();
212             ProjectGoal g = getExistingGoal( project );
213             g.attain( session );
214         }
215         catch ( CyclicGoalChainException e )
216         {
217             throw new DependencyResolverException( "A cycle was detected", e );
218         }
219         catch ( UnattainableGoalException e )
220         {
221             throw new DependencyResolverException( "An invalid goal was called", e );
222         }
223         catch ( NoActionDefinitionException e )
224         {
225             throw new DependencyResolverException( "An invalid goal was called", e );
226         }
227 
228         return getProjects( sortedGoals, sourceBuild );
229     }
230 
231     /**
232      * @see org.apache.maven.jelly.tags.maven.DependencyResolverInterface#getSortedDependencies(boolean)
233      */
234     public List getSortedDependencies( boolean sourceBuild )
235         throws DependencyResolverException
236     {
237         try
238         {
239             buildGraph();
240             sortedGoals.clear();
241             Session session = new Session();
242             doItAll.attain( session );
243             return getProjects( sortedGoals, sourceBuild );
244         }
245         catch ( CyclicGoalChainException e )
246         {
247             throw new DependencyResolverException( "A cycle was detected", e );
248         }
249         catch ( UnattainableGoalException e )
250         {
251             throw new DependencyResolverException( "An invalid goal was called", e );
252         }
253         catch ( NoActionDefinitionException e )
254         {
255             throw new DependencyResolverException( "An invalid goal was called", e );
256         }
257     }
258 
259 }
260 
261 /**
262  * Simple action that adds the goal to a list when it is invoked
263  */
264 class ListAddAction
265     implements Action
266 {
267     private List list;
268 
269     private Goal goal;
270 
271     public ListAddAction( Goal goal, List list )
272     {
273         this.list = list;
274         this.goal = goal;
275     }
276 
277     public boolean requiresAction()
278     {
279         return true;
280     }
281 
282     public void performAction( Session session )
283         throws Exception
284     {
285         list.add( goal );
286     }
287 
288     public void performAction()
289         throws Exception
290     {
291         list.add( goal );
292     }
293 }
294 
295 /**
296  * "Do nothing" action
297  */
298 class DummyAction
299     implements Action
300 {
301     public boolean requiresAction()
302     {
303         return false;
304     }
305 
306     public void performAction( Session session )
307         throws Exception
308     {
309 
310     }
311 
312     public void performAction()
313         throws Exception
314     {
315     }
316 }
317 
318 /**
319  * Overrides Goal to add some extra project information
320  */
321 class ProjectGoal
322     extends Goal
323 {
324     private final Project project;
325 
326     private final boolean sourceBuild;
327 
328     public ProjectGoal( Project project, boolean sourceBuild )
329     {
330         super( project.getId() );
331         this.project = project;
332         this.sourceBuild = sourceBuild;
333     }
334 
335     public Project getProject()
336     {
337         return project;
338     }
339 
340     public boolean getSourceBuild()
341     {
342         return sourceBuild;
343     }
344 }