package org.apache.maven.jelly.tags.maven;
/* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.maven.project.Dependency;
import org.apache.maven.project.Project;
import org.apache.maven.werkz.Action;
import org.apache.maven.werkz.CyclicGoalChainException;
import org.apache.maven.werkz.Goal;
import org.apache.maven.werkz.NoActionDefinitionException;
import org.apache.maven.werkz.Session;
import org.apache.maven.werkz.UnattainableGoalException;
import org.apache.maven.werkz.WerkzProject;
/**
* THIS CLASS IS NOT THREADSAFE.
*
* @author <a href="mailto:bwalding@apache.org">Ben Walding</a>
* @version $Id: WerkzDependencyResolver.java 517014 2007-03-11 21:15:50Z ltheussl $
*/
public class WerkzDependencyResolver
implements DependencyResolverInterface
{
private List projects = new ArrayList();
private final List sortedGoals = new ArrayList();
private Goal doItAll = null;
private WerkzProject wproject = null;
/**
* @see org.apache.maven.jelly.tags.maven.DependencyResolverInterface#clear()
*/
public void clear()
{
projects.clear();
doItAll = null;
}
/**
* @see org.apache.maven.jelly.tags.maven.DependencyResolverInterface#setProjects(java.util.List)
*/
public void setProjects( List projects )
{
this.projects = projects;
}
/**
* Retrieves the existing goal for a project (based on Id).
* If no goal exists, an exception is thrown.
*
* @param project the project to retrieve a goal from
* @return ProjectGoal
*/
protected ProjectGoal getExistingGoal( Project project )
{
ProjectGoal goal = (ProjectGoal) wproject.getGoal( project.getId() );
if ( goal == null )
{
throw new NullPointerException( "No goal exists : " + project.getId() );
}
else
{
return goal;
}
}
/**
* Retrieves the existing goal for a project (based on Id).
* If no goal exists, one is created for this given project.
*
* @param project
* @param sourceBuild
* @return ProjectGoal
*/
protected ProjectGoal getOrCreateGoal( Project project, boolean sourceBuild )
{
ProjectGoal goal = (ProjectGoal) wproject.getGoal( project.getId() );
if ( goal == null )
{
goal = new ProjectGoal( project, sourceBuild );
goal.setAction( new ListAddAction( goal, sortedGoals ) );
wproject.addGoal( goal );
}
return goal;
}
/**
* Builds the projects / dependencies into an internal acyclic directed graph
*/
public void buildGraph()
throws CyclicGoalChainException
{
if ( doItAll != null )
{
return;
}
try
{
wproject = new WerkzProject();
doItAll = new Goal( "DO_IT_ALL" );
doItAll.setAction( new DummyAction() );
//Initialise all the true goals of the system
Iterator iter = projects.iterator();
while ( iter.hasNext() )
{
Project project = (Project) iter.next();
Goal projectGoal = getOrCreateGoal( project, true );
doItAll.addPrecursor( projectGoal );
}
//Now add the dependencies
iter = projects.iterator();
while ( iter.hasNext() )
{
Project project = (Project) iter.next();
Goal projectGoal = getExistingGoal( project );
Iterator depIter = project.getDependencies().iterator();
while ( depIter.hasNext() )
{
Dependency dep = (Dependency) depIter.next();
Project depProject = new Project();
depProject.setId( dep.getId() );
Goal depGoal = getOrCreateGoal( depProject, false );
projectGoal.addPrecursor( depGoal );
}
}
}
catch ( CyclicGoalChainException e )
{
doItAll = null;
wproject = new WerkzProject();
// We want to get the right exception
throw e;
}
}
/**
* @see org.apache.maven.jelly.tags.maven.DependencyResolverInterface#getSortedDependencies(org.apache.maven.project.Project)
*/
public List getSortedDependencies( Project project )
throws DependencyResolverException
{
return getSortedDependencies( project, false );
}
/**
* Filters the given list of goals, and returns the associated projects
* <p/>
* If param:sourceBuild == true, include goal
* If param:sourceBuild == false, include goal if goal:sourceBuild == true
*
* @param goals
* @param sourceBuild
* @return List
*/
public List getProjects( List goals, boolean sourceBuild )
{
List result = new ArrayList();
Iterator iter = goals.iterator();
while ( iter.hasNext() )
{
ProjectGoal goal = (ProjectGoal) iter.next();
if ( ( sourceBuild ) || ( !sourceBuild && goal.getSourceBuild() ) )
{
result.add( ( goal ).getProject() );
}
}
return result;
}
/**
* @see org.apache.maven.jelly.tags.maven.DependencyResolverInterface#getSortedDependencies(org.apache.maven.project.Project, boolean)
*/
public List getSortedDependencies( Project project, boolean sourceBuild )
throws DependencyResolverException
{
try
{
buildGraph();
sortedGoals.clear();
Session session = new Session();
ProjectGoal g = getExistingGoal( project );
g.attain( session );
}
catch ( CyclicGoalChainException e )
{
throw new DependencyResolverException( "A cycle was detected", e );
}
catch ( UnattainableGoalException e )
{
throw new DependencyResolverException( "An invalid goal was called", e );
}
catch ( NoActionDefinitionException e )
{
throw new DependencyResolverException( "An invalid goal was called", e );
}
return getProjects( sortedGoals, sourceBuild );
}
/**
* @see org.apache.maven.jelly.tags.maven.DependencyResolverInterface#getSortedDependencies(boolean)
*/
public List getSortedDependencies( boolean sourceBuild )
throws DependencyResolverException
{
try
{
buildGraph();
sortedGoals.clear();
Session session = new Session();
doItAll.attain( session );
return getProjects( sortedGoals, sourceBuild );
}
catch ( CyclicGoalChainException e )
{
throw new DependencyResolverException( "A cycle was detected", e );
}
catch ( UnattainableGoalException e )
{
throw new DependencyResolverException( "An invalid goal was called", e );
}
catch ( NoActionDefinitionException e )
{
throw new DependencyResolverException( "An invalid goal was called", e );
}
}
}
/**
* Simple action that adds the goal to a list when it is invoked
*/
class ListAddAction
implements Action
{
private List list;
private Goal goal;
public ListAddAction( Goal goal, List list )
{
this.list = list;
this.goal = goal;
}
public boolean requiresAction()
{
return true;
}
public void performAction( Session session )
throws Exception
{
list.add( goal );
}
public void performAction()
throws Exception
{
list.add( goal );
}
}
/**
* "Do nothing" action
*/
class DummyAction
implements Action
{
public boolean requiresAction()
{
return false;
}
public void performAction( Session session )
throws Exception
{
}
public void performAction()
throws Exception
{
}
}
/**
* Overrides Goal to add some extra project information
*/
class ProjectGoal
extends Goal
{
private final Project project;
private final boolean sourceBuild;
public ProjectGoal( Project project, boolean sourceBuild )
{
super( project.getId() );
this.project = project;
this.sourceBuild = sourceBuild;
}
public Project getProject()
{
return project;
}
public boolean getSourceBuild()
{
return sourceBuild;
}
}