1 package org.apache.maven.jelly.tags.maven;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
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
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
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 }