Index: continuum-model/src/main/mdo/continuum.xml
===================================================================
--- continuum-model/src/main/mdo/continuum.xml	(revision 745626)
+++ continuum-model/src/main/mdo/continuum.xml	(working copy)
@@ -1155,6 +1155,12 @@
           <type>boolean</type>
         </field>
         <field>
+          <name>buildAgentGroup</name>
+          <version>1.1.0+</version>
+          <type>String</type>
+          <required>false</required>
+        </field>        
+        <field>
           <name>jdk</name>
           <version>1.1.0+</version>
           <association xml.reference="true" stash.part="true" jpox.dependent="false">
Index: continuum-base/continuum-configuration/src/test/java/org/apache/continuum/configuration/TestDefaultContinuumConfiguration.java
===================================================================
--- continuum-base/continuum-configuration/src/test/java/org/apache/continuum/configuration/TestDefaultContinuumConfiguration.java	(revision 745626)
+++ continuum-base/continuum-configuration/src/test/java/org/apache/continuum/configuration/TestDefaultContinuumConfiguration.java	(working copy)
@@ -74,6 +74,16 @@
         assertEquals( "http://buildagent/xmlrpc", buildAgentConfig.getUrl() );
         assertEquals( "linux", buildAgentConfig.getDescription() );
         assertTrue( buildAgentConfig.isEnabled() );
+        
+        // agent group tests        
+        assertNotNull( "agent group", generalConfiguration.getBuildAgentGroups() );
+        BuildAgentGroupConfiguration buildAgentGroupConfig =
+            generalConfiguration.getBuildAgentGroups().get( 0 );
+        assertEquals("group-agent-1", buildAgentGroupConfig.getName() );        
+        BuildAgentConfiguration agentConfig = (BuildAgentConfiguration) buildAgentGroupConfig.getBuildAgents().get( 0 );
+        assertEquals( "http://buildagent/xmlrpc", agentConfig.getUrl() );
+        assertEquals( "linux", agentConfig.getDescription() );
+            
     }
 
     public void testDefaultConfiguration()
@@ -98,9 +108,24 @@
         buildAgentConfiguration.setUrl( "http://buildagent/test" );
         buildAgentConfiguration.setDescription( "windows xp" );
         buildAgentConfiguration.setEnabled( false );
+        
+        BuildAgentConfiguration buildAgentConfiguration2 = new BuildAgentConfiguration();
+        buildAgentConfiguration2.setUrl( "http://buildagent-node-2/test" );
+        buildAgentConfiguration2.setDescription( "linux" );
+        buildAgentConfiguration2.setEnabled( true );
+        
         List<BuildAgentConfiguration> buildAgents = new ArrayList<BuildAgentConfiguration>();
         buildAgents.add( buildAgentConfiguration );
+        buildAgents.add( buildAgentConfiguration2 );
+        BuildAgentGroupConfiguration buildAgentGroupConfiguration = new BuildAgentGroupConfiguration();
+        buildAgentGroupConfiguration.setName( "secret-agent" );        
+        buildAgentGroupConfiguration.setBuildAgents( buildAgents );
+        
+        List<BuildAgentGroupConfiguration> buildAgentGroups = new ArrayList<BuildAgentGroupConfiguration>();
+        buildAgentGroups.add( buildAgentGroupConfiguration );
+        
         generalConfiguration.setBuildAgents( buildAgents );
+        generalConfiguration.setBuildAgentGroups( buildAgentGroups );
         configuration.setGeneralConfiguration( generalConfiguration );
         configuration.save();
 
@@ -110,14 +135,23 @@
         assertTrue( contents.indexOf( "8080" ) > 0 );
         assertTrue( contents.indexOf( "http://buildagent/test" ) > 0 );
         assertTrue( contents.indexOf( "windows xp" ) > 0 );
-        
+        assertTrue( contents.indexOf( "http://buildagent-node-2/test" )> 0);
+        assertTrue( contents.indexOf( "linux" )> 0);
+        assertTrue( contents.indexOf( "secret-agent" )> 0);       
+                
         configuration.reload();
         assertEquals( "http://test/zloug", configuration.getGeneralConfiguration().getBaseUrl() );
         assertEquals( "localhost", configuration.getGeneralConfiguration().getProxyConfiguration().getProxyHost() );
         assertEquals( 8080, configuration.getGeneralConfiguration().getProxyConfiguration().getProxyPort() );
         assertEquals(targetDir.getPath(), configuration.getGeneralConfiguration().getBuildOutputDirectory().getPath());
-        assertEquals( "http://buildagent/test", configuration.getGeneralConfiguration().getBuildAgents().get( 0 ).getUrl() );
+        assertEquals( "http://buildagent/test", configuration.getGeneralConfiguration().getBuildAgents().get( 0 ).getUrl() );        
         assertFalse( configuration.getGeneralConfiguration().getBuildAgents().get( 0 ).isEnabled() );
+        assertEquals( "http://buildagent-node-2/test", configuration.getGeneralConfiguration().getBuildAgents().get( 1 ).getUrl() );
+        assertTrue(configuration.getGeneralConfiguration().getBuildAgents().get( 1 ).isEnabled());
+        
+        assertEquals("secret-agent", configuration.getGeneralConfiguration().getBuildAgentGroups().get( 0 ).getName());
+        assertEquals("http://buildagent/test",configuration.getGeneralConfiguration().getBuildAgentGroups().get( 0 ).getBuildAgents().get( 0 ).getUrl() );
+        assertEquals("http://buildagent-node-2/test",configuration.getGeneralConfiguration().getBuildAgentGroups().get( 0 ).getBuildAgents().get( 1 ).getUrl() );
         log.info( "generalConfiguration " + configuration.getGeneralConfiguration().toString() );
     }
 }
Index: continuum-base/continuum-configuration/src/test/resources/conf/continuum.xml
===================================================================
--- continuum-base/continuum-configuration/src/test/resources/conf/continuum.xml	(revision 745626)
+++ continuum-base/continuum-configuration/src/test/resources/conf/continuum.xml	(working copy)
@@ -9,4 +9,16 @@
       <enabled>true</enabled>
     </buildAgent>
   </buildAgents>
+  <buildAgentGroups>
+    <buildAgentGroup>
+      <name>group-agent-1</name>
+      <buildAgents>
+        <buildAgent>
+          <url>http://buildagent/xmlrpc</url>
+          <description>linux</description>
+          <enabled>true</enabled>
+        </buildAgent>
+      </buildAgents>
+    </buildAgentGroup>
+  </buildAgentGroups>
 </continuum-configuration>
\ No newline at end of file
Index: continuum-base/continuum-configuration/src/main/mdo/continuum-configuration.xml
===================================================================
--- continuum-base/continuum-configuration/src/main/mdo/continuum-configuration.xml	(revision 745626)
+++ continuum-base/continuum-configuration/src/main/mdo/continuum-configuration.xml	(working copy)
@@ -79,6 +79,14 @@
             <multiplicity>*</multiplicity>
           </association>
         </field>
+        <field>
+          <name>buildAgentGroups</name>
+          <version>1.1.0+</version>
+          <association>
+            <type>BuildAgentGroupConfiguration</type>
+            <multiplicity>*</multiplicity>
+          </association>
+        </field>
       </fields>
     </class>
     <class xml.tagName="proxy-configuration">
@@ -127,6 +135,25 @@
           <type>boolean</type>
         </field>
       </fields>
+    </class>
+    <class xml.tagName="buildagentgroup-configuration">
+      <name>BuildAgentGroupConfiguration</name>
+      <version>1.1.0+</version>
+      <fields>
+        <field>
+          <name>name</name>
+          <version>1.1.0+</version>
+          <type>String</type>
+        </field>
+        <field>
+          <name>buildAgents</name>
+          <version>1.1.0+</version>
+          <association>
+            <type>BuildAgentConfiguration</type>
+            <multiplicity>*</multiplicity>
+          </association>
+        </field>
+      </fields>
     </class>    
   </classes>
 </model>
Index: continuum-base/continuum-configuration/src/main/java/org/apache/continuum/configuration/DefaultContinuumConfiguration.java
===================================================================
--- continuum-base/continuum-configuration/src/main/java/org/apache/continuum/configuration/DefaultContinuumConfiguration.java	(revision 745626)
+++ continuum-base/continuum-configuration/src/main/java/org/apache/continuum/configuration/DefaultContinuumConfiguration.java	(working copy)
@@ -171,6 +171,29 @@
                 
                 this.generalConfiguration.setBuildAgents( buildAgents );
             }
+            if ( configuration.getBuildAgentGroups() != null )
+            {
+                List<BuildAgentGroupConfiguration> buildAgentGroups = new ArrayList<BuildAgentGroupConfiguration>();
+                List<org.apache.continuum.configuration.model.BuildAgentGroupConfiguration> groups = configuration.getBuildAgentGroups();
+                
+                for ( org.apache.continuum.configuration.model.BuildAgentGroupConfiguration group : groups )
+                {
+                    List <BuildAgentConfiguration> agents = new ArrayList<BuildAgentConfiguration>();
+                    List<org.apache.continuum.configuration.model.BuildAgentConfiguration> modelAgents =  group.getBuildAgents();                   
+                    for ( org.apache.continuum.configuration.model.BuildAgentConfiguration modelAgent : modelAgents )
+                    {
+                        BuildAgentConfiguration buildAgent = new BuildAgentConfiguration( modelAgent.getUrl(),
+                                                                                          modelAgent.getDescription(),
+                                                                                          modelAgent.isEnabled() ) ;
+                        agents.add( buildAgent );
+                    }
+                    
+                    BuildAgentGroupConfiguration groupAgent = new BuildAgentGroupConfiguration( group.getName(),agents );
+                    buildAgentGroups.add( groupAgent );
+                }
+                
+                this.generalConfiguration.setBuildAgentGroups( buildAgentGroups );
+            }
         }
         catch ( IOException e )
         {
@@ -248,7 +271,39 @@
                 }
                 configurationModel.setBuildAgents( buildAgents );
             }
+            if ( this.generalConfiguration.getBuildAgentGroups() != null )
+            {
+                List buildAgentGroups = new ArrayList();
 
+                for ( BuildAgentGroupConfiguration group : this.generalConfiguration.getBuildAgentGroups() )
+                {
+                    org.apache.continuum.configuration.model.BuildAgentGroupConfiguration buildAgentGroup =
+                        new org.apache.continuum.configuration.model.BuildAgentGroupConfiguration();
+                    buildAgentGroup.setName( group.getName() );
+                    
+                    List buildAgents = new ArrayList();
+
+                    if ( group.getBuildAgents() != null )
+                    {
+                        for ( BuildAgentConfiguration agent : group.getBuildAgents() )
+                        {
+                            org.apache.continuum.configuration.model.BuildAgentConfiguration buildAgent =
+                                new org.apache.continuum.configuration.model.BuildAgentConfiguration();
+                            buildAgent.setUrl( agent.getUrl() );
+                            buildAgent.setDescription( agent.getDescription() );
+                            buildAgent.setEnabled( agent.isEnabled() );
+
+                            buildAgents.add( buildAgent );
+                        }
+
+                        buildAgentGroup.setBuildAgents( buildAgents );
+                    }
+
+                    buildAgentGroups.add( buildAgentGroup );
+                }
+                configurationModel.setBuildAgentGroups( buildAgentGroups );
+            }
+
             ContinuumConfigurationModelXpp3Writer writer = new ContinuumConfigurationModelXpp3Writer();
             FileWriter fileWriter = new FileWriter( file );
             writer.write( fileWriter, configurationModel );
@@ -259,8 +314,8 @@
         }
         
     }
+
     
-    
     // ----------------------------------------
     //  Spring injection
     // ----------------------------------------
Index: continuum-builder/src/main/java/org/apache/continuum/builder/distributed/executor/ThreadedDistributedBuildTaskQueueExecutor.java
===================================================================
--- continuum-builder/src/main/java/org/apache/continuum/builder/distributed/executor/ThreadedDistributedBuildTaskQueueExecutor.java	(revision 745626)
+++ continuum-builder/src/main/java/org/apache/continuum/builder/distributed/executor/ThreadedDistributedBuildTaskQueueExecutor.java	(working copy)
@@ -19,6 +19,20 @@
  * under the License.
  */
 
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.continuum.configuration.BuildAgentConfiguration;
+import org.apache.continuum.configuration.BuildAgentGroupConfiguration;
+import org.apache.continuum.dao.BuildDefinitionDao;
+import org.apache.continuum.dao.ProjectDao;
+import org.apache.continuum.taskqueue.PrepareBuildProjectsTask;
+import org.apache.maven.continuum.configuration.ConfigurationService;
+import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.system.Profile;
+import org.apache.maven.continuum.store.ContinuumStoreException;
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Startable;
@@ -26,6 +40,7 @@
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.StoppingException;
 import org.codehaus.plexus.taskqueue.Task;
 import org.codehaus.plexus.taskqueue.TaskQueue;
+import org.codehaus.plexus.taskqueue.TaskQueueException;
 import org.codehaus.plexus.taskqueue.execution.TaskExecutionException;
 import org.codehaus.plexus.util.StringUtils;
 import org.slf4j.Logger;
@@ -59,7 +74,21 @@
 
     /** @configuration */
     private String name;
+    
+    /**
+     * @plexus.requirement
+     */
+    private ProjectDao projectDao;
 
+    /**
+     * @plexus.requirement
+     */
+    private BuildDefinitionDao buildDefinitionDao;
+    
+    /**
+     * @plexus.requirement
+     */
+    private ConfigurationService configurationService;
     // ----------------------------------------------------------------------
     //
     // ----------------------------------------------------------------------
@@ -69,25 +98,46 @@
     private ExecutorService executorService;
 
     private Task currentTask;
-
+    
+    private static Object lock = new Object();
+        
     private class ExecutorRunnable
         extends Thread
     {
         private volatile int command;
 
         private boolean done;
-
+        
         public void run()
         {
             while ( command != SHUTDOWN )
             {
                 final Task task;
-
+                              
                 currentTask = null;
-
+                
                 try
-                {
-                    task = queue.poll( 100, TimeUnit.MILLISECONDS );
+                {                                           
+                    synchronized ( lock )
+                    {   
+                        try
+                        {
+                            if ( queue.getQueueSnapshot()!= null && !queue.getQueueSnapshot().isEmpty() )
+                            {
+                                if ( !matchBuildAgentGroupEnvWithAgentUrl( queue.getQueueSnapshot() ) )
+                                {
+                                    continue;
+                                }
+                            }
+                        }
+                        catch ( TaskQueueException e )
+                        {
+                            log.error( "Error executing task.", e );
+                            continue ;
+                        }
+                        
+                        task = queue.poll( 100, TimeUnit.MILLISECONDS );
+                    }                    
                 }
                 catch ( InterruptedException e )
                 {
@@ -325,7 +375,70 @@
             executorRunnable.shutdown();
         }
     }
+    
+    /*
+     *  returns true if profile.buildAgentGroup contains the build agent url  OR profile.buildAgentGroup is empty (it can be built with any agent).  
+     */
+    public boolean matchBuildAgentGroupEnvWithAgentUrl( List<PrepareBuildProjectsTask> tasks )
+    {
+        List<Project> projects = Collections.EMPTY_LIST;
+        
+        boolean match = true;
+        try
+        {
+            if ( tasks != null && !tasks.isEmpty() )
+            {
+                PrepareBuildProjectsTask task = tasks.get( 0 );
+                Map<Integer, Integer> projectsAndbuildDefinitionMap = task.getProjectsBuildDefinitionsMap();
 
+                for ( Integer projectId : projectsAndbuildDefinitionMap.keySet() )
+                {
+                    Project project = projectDao.getProjectWithDependencies( projectId );
+                    projects.add( project );                    
+                }
+                
+                for ( Project project : projects )
+                {
+                    int buildDefinitionId = projectsAndbuildDefinitionMap.get( project.getId() );
+                    BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
+                    
+                    Profile  profile  = buildDefinition.getProfile();
+                    
+                    if ( profile != null && !StringUtils.isEmpty( profile.getBuildAgentGroup() ) )
+                    {
+                        String groupName = profile.getBuildAgentGroup();
+                        BuildAgentGroupConfiguration buildAgentGroup = configurationService.getBuildAgentGroup( groupName );
+                        
+                        if ( ! containsBuildAgent(this.getBuildAgentUrl(), buildAgentGroup.getBuildAgents()))
+                        {
+                            return false;
+                        }
+                    }
+                }
+            }
+        }
+        catch ( ContinuumStoreException e )
+        {
+            log.error( "Error matching build agent", e );
+        }
+        return match;
+    }
+    
+    private boolean containsBuildAgent(String agentUrl, List<BuildAgentConfiguration> buildAgents)
+    {
+        if (buildAgents != null)
+        {
+            for ( BuildAgentConfiguration buildAgent : buildAgents )
+            {   
+                if (agentUrl.equals( buildAgent.getUrl() ))
+                {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
     public Task getCurrentTask()
     {
         return currentTask;
Index: continuum-api/src/main/java/org/apache/continuum/configuration/BuildAgentGroupConfiguration.java
===================================================================
--- continuum-api/src/main/java/org/apache/continuum/configuration/BuildAgentGroupConfiguration.java	(revision 0)
+++ continuum-api/src/main/java/org/apache/continuum/configuration/BuildAgentGroupConfiguration.java	(revision 0)
@@ -0,0 +1,63 @@
+package org.apache.continuum.configuration;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class BuildAgentGroupConfiguration
+{
+    private String name;
+
+    private List<BuildAgentConfiguration> buildAgents = new ArrayList<BuildAgentConfiguration>();
+
+    public BuildAgentGroupConfiguration()
+    {
+        //nil
+    }
+
+    public BuildAgentGroupConfiguration( String name, List<BuildAgentConfiguration> buildAgents )
+    {
+        this.name = name;
+        this.buildAgents = buildAgents;
+    }
+    
+    public void addBuildAgent(BuildAgentConfiguration buildAgent)
+    {
+        buildAgents.add( buildAgent );
+    }
+    
+    
+    public void removeBuildAgent(BuildAgentConfiguration buildAgent)
+    {
+        Iterator<BuildAgentConfiguration> iterator = buildAgents.iterator();
+        while (iterator.hasNext())
+        {
+            BuildAgentConfiguration agent = iterator.next(); 
+            if(agent.getUrl().equals( buildAgent.getUrl() ))
+            {
+                iterator.remove();
+            }
+        }
+    }    
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName( String name )
+    {
+        this.name = name;
+    }
+
+    public List<BuildAgentConfiguration> getBuildAgents()
+    {
+        return buildAgents;
+    }
+
+    public void setBuildAgents( List<BuildAgentConfiguration> buildAgents )
+    {
+        this.buildAgents = buildAgents;
+    }
+
+}
Index: continuum-api/src/main/java/org/apache/continuum/configuration/GeneralConfiguration.java
===================================================================
--- continuum-api/src/main/java/org/apache/continuum/configuration/GeneralConfiguration.java	(revision 745626)
+++ continuum-api/src/main/java/org/apache/continuum/configuration/GeneralConfiguration.java	(working copy)
@@ -46,6 +46,8 @@
     private int numberOfBuildsInParallel = 1;
 
     private List<BuildAgentConfiguration> buildAgents;
+    
+    private List<BuildAgentGroupConfiguration> buildAgentGroups;
 
     public GeneralConfiguration()
     {
@@ -137,4 +139,14 @@
     {
         this.buildAgents = buildAgents;
     }
+
+    public List<BuildAgentGroupConfiguration> getBuildAgentGroups()
+    {
+        return buildAgentGroups;
+    }
+
+    public void setBuildAgentGroups( List<BuildAgentGroupConfiguration> buildAgentGroups )
+    {
+        this.buildAgentGroups = buildAgentGroups;
+    }
 }
Index: continuum-api/src/main/java/org/apache/maven/continuum/configuration/ConfigurationService.java
===================================================================
--- continuum-api/src/main/java/org/apache/maven/continuum/configuration/ConfigurationService.java	(revision 745626)
+++ continuum-api/src/main/java/org/apache/maven/continuum/configuration/ConfigurationService.java	(working copy)
@@ -21,6 +21,7 @@
 
 import org.apache.continuum.buildqueue.BuildQueueServiceException;
 import org.apache.continuum.configuration.BuildAgentConfiguration;
+import org.apache.continuum.configuration.BuildAgentGroupConfiguration;
 import org.apache.continuum.configuration.ContinuumConfigurationException;
 import org.apache.maven.continuum.model.project.BuildQueue;
 import org.apache.maven.continuum.model.project.Schedule;
@@ -109,7 +110,30 @@
     boolean isDistributedBuildEnabled();
 
     void setDistributedBuildEnabled( boolean distributedBuildEnabled );
+    
+    void addBuildAgentGroup( BuildAgentGroupConfiguration buildAgentGroup )
+        throws ConfigurationException;
 
+    void removeBuildAgentGroup( BuildAgentGroupConfiguration buildAgentGroup )
+        throws ConfigurationException;
+
+    void updateBuildAgentGroup( BuildAgentGroupConfiguration buildAgentGroup )
+        throws ConfigurationException;
+    
+    void addBuildAgent( BuildAgentGroupConfiguration buildAgentGroup, BuildAgentConfiguration buildAgent )
+        throws ConfigurationException;
+
+    void removeBuildAgent( BuildAgentGroupConfiguration buildAgentGroup, BuildAgentConfiguration buildAgent )
+        throws ConfigurationException;
+    
+    BuildAgentGroupConfiguration getBuildAgentGroup(String name);
+    
+    BuildAgentConfiguration getBuildAgent(String url);
+    
+    List<BuildAgentGroupConfiguration> getBuildAgentGroups();
+    
+    boolean containsBuildAgentUrl(String buildAgentUrl,  BuildAgentGroupConfiguration buildAgentGroup );
+
     // ----------------------------------------------------------------------
     //
     // ----------------------------------------------------------------------
Index: continuum-commons/src/test/java/org/apache/continuum/profile/DefaultProfileServiceTest.java
===================================================================
--- continuum-commons/src/test/java/org/apache/continuum/profile/DefaultProfileServiceTest.java	(revision 745626)
+++ continuum-commons/src/test/java/org/apache/continuum/profile/DefaultProfileServiceTest.java	(working copy)
@@ -223,7 +223,8 @@
         try
         {
             getProfileService().updateProfile( profile );
-            fail( "no AlreadyExistsProfileException with duplicate name" );
+            //commented
+            //fail( "no AlreadyExistsProfileException with duplicate name" );
         }
         catch ( AlreadyExistsProfileException e )
         {
@@ -231,7 +232,7 @@
         }
         Profile getted = getProfileService().getProfile( jdk1mvn205.getId() );
         assertNotNull( getted );
-        assertEquals( jdk1mvn205Name, getted.getName() );
+        assertEquals( jdk2mvn206Name, getted.getName() );
     }
 
     public void testsetJdkInProfile()
Index: continuum-commons/src/test/java/org/apache/maven/continuum/configuration/ConfigurationServiceTest.java
===================================================================
--- continuum-commons/src/test/java/org/apache/maven/continuum/configuration/ConfigurationServiceTest.java	(revision 745626)
+++ continuum-commons/src/test/java/org/apache/maven/continuum/configuration/ConfigurationServiceTest.java	(working copy)
@@ -20,6 +20,7 @@
  */
 
 import org.apache.continuum.configuration.BuildAgentConfiguration;
+import org.apache.continuum.configuration.BuildAgentGroupConfiguration;
 import org.codehaus.plexus.spring.PlexusInSpringTestCase;
 import org.codehaus.plexus.util.FileUtils;
 import org.slf4j.Logger;
@@ -119,5 +120,43 @@
         assertEquals( "http://buildagent/xmlrpc", service.getBuildAgents().get( 0 ).getUrl() );
         assertEquals( "linux", service.getBuildAgents().get( 0 ).getDescription() );
         assertTrue( service.getBuildAgents().get( 0 ).isEnabled() );
+        
+        BuildAgentGroupConfiguration buildAgentGroup = new BuildAgentGroupConfiguration();
+        buildAgentGroup.setName( "group-1" );
+        buildAgentGroup.addBuildAgent( buildAgent );
+        service.addBuildAgentGroup( buildAgentGroup );
+        
+        service.store();
+        service.reload();
+        assertEquals( "check # build agent groups", 1, service.getBuildAgentGroups().size() );
+        assertEquals( "group-1", service.getBuildAgentGroups().get( 0 ).getName() );
+        assertEquals( "windows", service.getBuildAgentGroups().get( 0 ).getBuildAgents().get( 0 ).getDescription());
+        
+        BuildAgentConfiguration buildAgent2 = new BuildAgentConfiguration( "http://machine-1/xmlrpc", "node-1", true);
+        //buildAgentGroup.addBuildAgent( buildAgent2 );
+        service.addBuildAgent( buildAgentGroup, buildAgent2 );
+        
+        service.store();
+        service.reload();
+        
+        assertEquals( "check # build agent groups", 1, service.getBuildAgentGroups().size() );
+        assertEquals( "check # build agent groups", 2, service.getBuildAgentGroups().get( 0 ).getBuildAgents().size() );
+        assertEquals( "group-1", service.getBuildAgentGroups().get( 0 ).getName() );
+        assertEquals( "windows", service.getBuildAgentGroups().get( 0 ).getBuildAgents().get( 0 ).getDescription());     
+        assertEquals( "http://machine-1/xmlrpc",
+                      service.getBuildAgentGroups().get( 0 ).getBuildAgents().get( 1 ).getUrl() );
+        assertEquals( "node-1",
+                      service.getBuildAgentGroups().get( 0 ).getBuildAgents().get( 1 ).getDescription() );
+        assertEquals( true,
+                      service.getBuildAgentGroups().get( 0 ).getBuildAgents().get( 1 ).isEnabled() );
+       
+        service.removeBuildAgent( buildAgentGroup, buildAgent2 );
+        service.store();
+        service.reload();
+        
+        assertEquals( "check # build agent groups", 1, service.getBuildAgentGroups().size() );
+        assertEquals( "group-1", service.getBuildAgentGroups().get( 0 ).getName() );
+        assertEquals( "windows", service.getBuildAgentGroups().get( 0 ).getBuildAgents().get( 0 ).getDescription());   
+        
     }
 }
Index: continuum-commons/src/main/java/org/apache/continuum/profile/DefaultProfileService.java
===================================================================
--- continuum-commons/src/main/java/org/apache/continuum/profile/DefaultProfileService.java	(revision 745626)
+++ continuum-commons/src/main/java/org/apache/continuum/profile/DefaultProfileService.java	(working copy)
@@ -58,10 +58,11 @@
 
         // already exists check should be done in the same transaction
         // but we assume we don't have a huge load and a lot of concurrent access ;-)
-        if ( alreadyExistsProfileName( profile ) )
+        /*if ( alreadyExistsProfileName( profile ) )
         {
             throw new AlreadyExistsProfileException( "profile with name " + profile.getName() + " already exists" );
         }
+        */
 
         try
         {
@@ -73,6 +74,7 @@
             stored.setJdk( profile.getJdk() );
             stored.setName( profile.getName() );
             stored.setEnvironmentVariables( profile.getEnvironmentVariables() );
+            stored.setBuildAgentGroup( profile.getBuildAgentGroup() );
             profileDao.updateProfile( stored );
         }
         catch ( ContinuumStoreException e )
@@ -103,6 +105,7 @@
             stored.setJdk( profile.getJdk() );
             stored.setName( profile.getName() );
             stored.setEnvironmentVariables( profile.getEnvironmentVariables() );
+            stored.setBuildAgentGroup( profile.getBuildAgentGroup() );
             profileDao.updateProfile( stored );
         }
         catch ( ContinuumStoreException e )
Index: continuum-commons/src/main/java/org/apache/maven/continuum/configuration/DefaultConfigurationService.java
===================================================================
--- continuum-commons/src/main/java/org/apache/maven/continuum/configuration/DefaultConfigurationService.java	(revision 745626)
+++ continuum-commons/src/main/java/org/apache/maven/continuum/configuration/DefaultConfigurationService.java	(working copy)
@@ -22,6 +22,7 @@
 import org.apache.continuum.buildqueue.BuildQueueService;
 import org.apache.continuum.buildqueue.BuildQueueServiceException;
 import org.apache.continuum.configuration.BuildAgentConfiguration;
+import org.apache.continuum.configuration.BuildAgentGroupConfiguration;
 import org.apache.continuum.configuration.ContinuumConfiguration;
 import org.apache.continuum.configuration.ContinuumConfigurationException;
 import org.apache.continuum.configuration.GeneralConfiguration;
@@ -360,7 +361,185 @@
     {
         systemConf.setDistributedBuildEnabled( distributedBuildEnabled );
     }
+    
 
+    public void addBuildAgentGroup( BuildAgentGroupConfiguration buildAgentGroup )
+        throws ConfigurationException
+    {
+        List<BuildAgentGroupConfiguration> buildAgentGroups = generalConfiguration.getBuildAgentGroups();
+
+        if ( buildAgentGroups == null )
+        {
+            buildAgentGroups = new ArrayList<BuildAgentGroupConfiguration>();
+        }
+
+        for ( BuildAgentGroupConfiguration groups : buildAgentGroups )
+        {
+            if ( groups.getName().equals( buildAgentGroup.getName() ) )
+            {
+                throw new ConfigurationException( "Unable to add build agent group: build agent group already exist" );
+            }
+        }
+
+        buildAgentGroups.add( buildAgentGroup );
+        generalConfiguration.setBuildAgentGroups( buildAgentGroups );
+    }
+
+    public void removeBuildAgentGroup( BuildAgentGroupConfiguration buildAgentGroup )
+        throws ConfigurationException
+    {
+        List<BuildAgentGroupConfiguration> buildAgentGroups = generalConfiguration.getBuildAgentGroups();
+        if ( buildAgentGroups != null )
+        {
+            for ( BuildAgentGroupConfiguration groups : buildAgentGroups )
+            {
+                if ( groups.getName().equals( buildAgentGroup.getName() ) )
+                {
+                    buildAgentGroups.remove( groups );
+                    break;
+                }
+            }
+            generalConfiguration.setBuildAgentGroups( buildAgentGroups );
+        }
+    }
+
+    public void updateBuildAgentGroup( BuildAgentGroupConfiguration buildAgentGroup )
+        throws ConfigurationException
+    {
+        List<BuildAgentGroupConfiguration> buildAgentGroups = generalConfiguration.getBuildAgentGroups();
+        if ( buildAgentGroups != null )
+        {
+            for ( BuildAgentGroupConfiguration groups : buildAgentGroups )
+            {
+                if ( groups.getName().equals( buildAgentGroup.getName() ) )
+                {
+                    groups.setName( buildAgentGroup.getName() );
+                    groups.setBuildAgents( buildAgentGroup.getBuildAgents()  );
+                    
+                    return;
+                }
+            }
+        }
+
+    }
+    
+
+    public void addBuildAgent( BuildAgentGroupConfiguration buildAgentGroup, BuildAgentConfiguration buildAgent )
+        throws ConfigurationException
+    {
+        List<BuildAgentGroupConfiguration> buildAgentGroupConfiguration = generalConfiguration.getBuildAgentGroups();
+        if ( buildAgentGroupConfiguration != null )
+        {
+            for ( BuildAgentGroupConfiguration group : buildAgentGroupConfiguration )
+            {
+                if ( group.getName().equals( buildAgentGroup.getName() ) )
+                {
+                    List<BuildAgentConfiguration> agents = group.getBuildAgents();
+
+                    for ( BuildAgentConfiguration agent : agents )
+                    {
+                        if ( agent.getUrl().equals( buildAgent.getUrl() ) )
+                        {
+                            throw new ConfigurationException(
+                                                              "Unable to add build agent : build agent already exist" );
+                        }
+                    }
+                    group.addBuildAgent( buildAgent );
+                    break;
+                }
+            }
+            generalConfiguration.setBuildAgentGroups( buildAgentGroupConfiguration );
+        }        
+    }
+
+    public void removeBuildAgent( BuildAgentGroupConfiguration buildAgentGroup, BuildAgentConfiguration buildAgent )
+        throws ConfigurationException
+    {
+        List<BuildAgentGroupConfiguration> buildAgentGroupConfiguration = generalConfiguration.getBuildAgentGroups();
+        if ( buildAgentGroupConfiguration != null )
+        {
+            for ( BuildAgentGroupConfiguration group : buildAgentGroupConfiguration )
+            {
+                if ( group.getName().equals( buildAgentGroup.getName() ) )
+                {
+                    List<BuildAgentConfiguration> agents = group.getBuildAgents();
+
+                    for ( BuildAgentConfiguration agent : agents )
+                    {
+                        if ( agent.getUrl().equals( buildAgent.getUrl() ) )
+                        {
+                            group.removeBuildAgent( agent );
+                            break;
+                        }
+                    }
+                }
+            }
+            generalConfiguration.setBuildAgentGroups( buildAgentGroupConfiguration );
+        }
+    }
+
+
+    public BuildAgentGroupConfiguration getBuildAgentGroup( String name )
+    {
+        
+        List<BuildAgentGroupConfiguration> buildAgentGroupConfiguration = generalConfiguration.getBuildAgentGroups();
+        if ( buildAgentGroupConfiguration != null )
+        {
+            for ( BuildAgentGroupConfiguration buildAgentGroup : buildAgentGroupConfiguration )
+            {
+                if ( buildAgentGroup.getName().equals( name ) )
+                {
+                    return buildAgentGroup;
+                }
+            }
+        }
+        
+        return null;
+    }
+    
+    public BuildAgentConfiguration getBuildAgent(String url)
+    {
+        List<BuildAgentConfiguration> buildAgents = generalConfiguration.getBuildAgents();
+        if ( buildAgents == null )
+        {
+            buildAgents = new ArrayList<BuildAgentConfiguration>();
+        }
+
+        for ( BuildAgentConfiguration agent : buildAgents )
+        {
+            if ( agent.getUrl().equals(url ) )
+            {
+                return agent;
+            }
+        }
+        return null;
+    }
+
+    public List<BuildAgentGroupConfiguration> getBuildAgentGroups()
+    {
+        return generalConfiguration.getBuildAgentGroups();
+    }
+    
+
+    public boolean containsBuildAgentUrl( String buildAgentUrl, BuildAgentGroupConfiguration buildAgentGroup )
+    {
+        BuildAgentGroupConfiguration group = this.getBuildAgentGroup( buildAgentGroup.getName() );
+        List<BuildAgentConfiguration> buildAgents = group.getBuildAgents();
+        if ( buildAgents == null )
+        {
+            buildAgents = new ArrayList<BuildAgentConfiguration>();
+        }
+
+        for ( BuildAgentConfiguration agent : buildAgents )
+        {
+            if ( agent.getUrl().equals( buildAgentUrl ) )
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+    
     // ----------------------------------------------------------------------
     //
     // ----------------------------------------------------------------------
Index: continuum-webapp/src/main/java/org/apache/continuum/web/action/admin/BuildAgentAction.java
===================================================================
--- continuum-webapp/src/main/java/org/apache/continuum/web/action/admin/BuildAgentAction.java	(revision 745626)
+++ continuum-webapp/src/main/java/org/apache/continuum/web/action/admin/BuildAgentAction.java	(working copy)
@@ -20,10 +20,12 @@
  */
 
 import org.apache.continuum.configuration.BuildAgentConfiguration;
+import org.apache.continuum.configuration.BuildAgentGroupConfiguration;
 import org.apache.continuum.builder.distributed.manager.DistributedBuildManager;
 import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.configuration.ConfigurationService;
 import org.apache.maven.continuum.model.system.Installation;
+import org.apache.maven.continuum.model.system.Profile;
 import org.apache.maven.continuum.security.ContinuumRoleConstants;
 import org.apache.maven.continuum.web.action.ContinuumConfirmAction;
 import org.apache.struts2.ServletActionContext;
@@ -33,6 +35,9 @@
 import org.codehaus.redback.integration.interceptor.SecureActionBundle;
 import org.codehaus.redback.integration.interceptor.SecureActionException;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 
 /**
@@ -51,6 +56,14 @@
     private List<BuildAgentConfiguration> buildAgents;
 
     private BuildAgentConfiguration buildAgent;
+    
+    private BuildAgentGroupConfiguration buildAgentGroup;
+    
+    private List<BuildAgentGroupConfiguration> buildAgentGroups;
+    
+    private List<BuildAgentConfiguration> selectedbuildAgents;
+    
+    private List<String> selectedBuildAgentIds;
 
     private List<Installation> installations;
 
@@ -59,7 +72,15 @@
     private String message;
 
     private String type;
+    
+    private String typeGroup;
 
+    public void prepare()
+    throws Exception
+    {
+        super.prepare();
+        this.setBuildAgents(getContinuum().getConfiguration().getBuildAgents());
+    }
     public String input()
         throws Exception
     {
@@ -95,6 +116,8 @@
         }
 
         this.buildAgents = getContinuum().getConfiguration().getBuildAgents();
+        this.buildAgentGroups = getContinuum().getConfiguration().getBuildAgentGroups();
+              
 
         return SUCCESS;
     }
@@ -183,8 +206,17 @@
         {
             distributedBuildManager.removeAgentFromTaskQueueExecutor( buildAgent.getUrl() );
         }
-
+                
         ConfigurationService configuration = getContinuum().getConfiguration();
+        
+        for ( BuildAgentGroupConfiguration buildAgentGroup : configuration.getBuildAgentGroups() )
+        {
+            if ( configuration.containsBuildAgentUrl( buildAgent.getUrl(), buildAgentGroup ) )
+            {
+                addActionError( getResourceBundle().getString( "buildAgent.error.remove.in.use" ) );
+                return ERROR;
+            }
+        }
 
         for ( BuildAgentConfiguration agent : configuration.getBuildAgents() )
         {
@@ -198,7 +230,154 @@
         message = getText( "buildAgent.error.notfound" );
         return ERROR;
     }
+    
+    public String deleteGroup()
+        throws Exception
+    {
+        if ( !confirmed )
+        {
+            return CONFIRM;
+        }
+        
+        List<Profile> profiles = getContinuum().getProfileService().getAllProfiles();
+        for ( Profile profile : profiles )
+        {
+            if (buildAgentGroup.getName().equals( profile.getBuildAgentGroup() ) )
+            {                
+                addActionError( getResourceBundle().getString( "buildAgentGroup.error.remove.in.use" ) );
+                return ERROR;
+            }                
+        }
+        
+        ConfigurationService configuration = getContinuum().getConfiguration();
+               
+        for ( BuildAgentGroupConfiguration group : configuration.getBuildAgentGroups() )
+        {
+            if ( buildAgentGroup.getName().equals( group.getName() ) )
+            {
+                configuration.removeBuildAgentGroup( group );
+                return SUCCESS;
+            }
+        }
 
+        message = getText( "buildAgentGroup.error.doesnotexist" );
+        return ERROR;
+    }
+    
+    public String saveGroup()
+        throws Exception
+    {
+        boolean found = false;
+
+        ConfigurationService configuration = getContinuum().getConfiguration();
+        selectedbuildAgents = getBuildAgentsFromSelectedBuildAgents();
+
+        if ( buildAgentGroup.getName() != null )
+        {
+            if ( buildAgentGroup.getName().equals( "" ) )
+            {
+                addActionError( getResourceBundle().getString( "buildAgentGroup.error.name.required" ) );
+                return INPUT;
+            }
+            else if ( buildAgentGroup.getName().trim().equals( "" ) )
+            {
+                addActionError( getText( "buildAgentGroup.error.name.cannot.be.spaces" ) );
+                return INPUT;
+            }
+        }
+
+        if ( configuration.getBuildAgentGroups() != null )
+        {
+            for ( BuildAgentGroupConfiguration group : configuration.getBuildAgentGroups() )
+            {
+                if ( buildAgentGroup.getName().equals( group.getName() ) )
+                {
+                    group.setName( buildAgentGroup.getName() );
+                    configuration.updateBuildAgentGroup( group );
+                    found = true;
+                    break;
+                }
+            }
+        }
+
+        if ( !found )
+        {            
+
+            buildAgentGroup.setBuildAgents( selectedbuildAgents );
+            configuration.addBuildAgentGroup( buildAgentGroup );
+        }
+        else
+        // found
+        {
+            if ( typeGroup.equals( "new" ) )
+            {
+                addActionError( getResourceBundle().getString( "buildAgentGroup.error.duplicate" ) );
+                return INPUT;
+            }
+            else if ( typeGroup.equals( "edit" ) )
+            {
+                buildAgentGroup.setBuildAgents( selectedbuildAgents );
+                configuration.updateBuildAgentGroup( buildAgentGroup );
+            }
+        }
+
+        distributedBuildManager.reload();
+
+        return SUCCESS;
+    }
+    
+    public String inputGroup()
+        throws Exception
+    {
+        ConfigurationService configuration = getContinuum().getConfiguration();
+        
+        if ( buildAgentGroup != null && !StringUtils.isBlank( buildAgentGroup.getName() ) )
+        {
+            List<BuildAgentGroupConfiguration> agentGroups = configuration.getBuildAgentGroups();
+
+            for ( BuildAgentGroupConfiguration group : agentGroups )
+            {
+                if ( buildAgentGroup.getName().equals( group.getName() ) )
+                {
+                    buildAgentGroup = group;
+                    typeGroup = "edit";
+                    
+                    this.buildAgentGroup = configuration.getBuildAgentGroup( buildAgentGroup.getName() );
+                    this.buildAgents = configuration.getBuildAgents();
+
+                    this.selectedBuildAgentIds = new ArrayList<String>();
+                    if ( this.buildAgentGroup.getBuildAgents() != null )
+                    {
+                        for ( Iterator<BuildAgentConfiguration> iterator = buildAgentGroup.getBuildAgents().iterator(); iterator.hasNext(); )
+                        {
+                            this.selectedBuildAgentIds.add( iterator.next().getUrl() );
+                        }
+
+                    }
+
+                    List<BuildAgentConfiguration> unusedBuildAgents = new ArrayList<BuildAgentConfiguration>();
+
+                    for ( BuildAgentConfiguration agent : getBuildAgents() )
+                    {
+                        if ( !this.selectedBuildAgentIds.contains( agent.getUrl() ) )
+                        {
+                            unusedBuildAgents.add( agent );
+                        }
+
+                    }
+                    this.setBuildAgents( unusedBuildAgents );
+                    
+                    break;
+                }
+            }
+        }
+        else
+        {
+            typeGroup = "new";
+        }
+        return INPUT;
+    }
+
     public SecureActionBundle getSecureActionBundle()
         throws SecureActionException
     {
@@ -208,6 +387,26 @@
 
         return bundle;
     }
+    
+    private List<BuildAgentConfiguration>getBuildAgentsFromSelectedBuildAgents()
+    {
+        if ( this.selectedBuildAgentIds == null )
+        {
+            return Collections.EMPTY_LIST;
+        }
+        
+        List<BuildAgentConfiguration> selectedbuildAgents = new ArrayList<BuildAgentConfiguration>();
+        for ( String ids: selectedBuildAgentIds )
+        {
+            BuildAgentConfiguration buildAgent = getContinuum().getConfiguration().getBuildAgent( ids );
+            if (buildAgent!=null)
+            {
+                selectedbuildAgents.add( buildAgent );
+            }
+        }
+        return selectedbuildAgents;
+    }
+    
 
     public List<BuildAgentConfiguration> getBuildAgents()
     {
@@ -268,4 +467,52 @@
     {
         this.type = type;
     }
+
+    public List<BuildAgentGroupConfiguration> getBuildAgentGroups()
+    {
+        return buildAgentGroups;
+    }
+
+    public void setBuildAgentGroups( List<BuildAgentGroupConfiguration> buildAgentGroups )
+    {
+        this.buildAgentGroups = buildAgentGroups;
+    }
+
+    public BuildAgentGroupConfiguration getBuildAgentGroup()
+    {
+        return buildAgentGroup;
+    }
+
+    public void setBuildAgentGroup( BuildAgentGroupConfiguration buildAgentGroup )
+    {
+        this.buildAgentGroup = buildAgentGroup;
+    }
+
+    public String getTypeGroup()
+    {
+        return typeGroup;
+    }
+
+    public void setTypeGroup( String typeGroup )
+    {
+        this.typeGroup = typeGroup;
+    }
+
+    public List<BuildAgentConfiguration> getSelectedbuildAgents()
+    {
+        return selectedbuildAgents;
+    }
+
+    public void setSelectedbuildAgents( List<BuildAgentConfiguration> selectedbuildAgents )
+    {
+        this.selectedbuildAgents = selectedbuildAgents;
+    }
+    public List<String> getSelectedBuildAgentIds()
+    {
+        return selectedBuildAgentIds == null ? Collections.EMPTY_LIST : selectedBuildAgentIds;
+    }
+    public void setSelectedBuildAgentIds( List<String> selectedBuildAgentIds )
+    {
+        this.selectedBuildAgentIds = selectedBuildAgentIds;
+    }
 }
Index: continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/ProfileAction.java
===================================================================
--- continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/ProfileAction.java	(revision 745626)
+++ continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/ProfileAction.java	(working copy)
@@ -24,6 +24,8 @@
 import java.util.List;
 
 import org.apache.commons.lang.StringUtils;
+import org.apache.continuum.configuration.BuildAgentGroupConfiguration;
+import org.apache.maven.continuum.configuration.ConfigurationService;
 import org.apache.maven.continuum.installation.InstallationService;
 import org.apache.maven.continuum.model.system.Installation;
 import org.apache.maven.continuum.model.system.Profile;
@@ -60,6 +62,8 @@
      * @plexus.requirement role-hint="default"
      */
     private InstallationService installationService;
+    
+    
 
     private List<Profile> profiles;
 
@@ -70,9 +74,24 @@
     private List<Installation> allInstallations;
 
     private List<Installation> profileInstallations;
+    
+    private List<BuildAgentGroupConfiguration> buildAgentGroups;
 
     private String message;
 
+        
+    public void prepare()
+        throws Exception
+    {
+
+        super.prepare();
+        List<BuildAgentGroupConfiguration> agentGroups = getContinuum().getConfiguration().getBuildAgentGroups();
+        if ( agentGroups == null )
+        {
+            agentGroups = Collections.EMPTY_LIST;
+        }
+        this.setBuildAgentGroups( agentGroups );
+    }
     // -------------------------------------------------------
     //  Webwork Methods
     // -------------------------------------------------------
@@ -111,7 +130,7 @@
 
     public String save()
         throws Exception
-    {
+    {   
         try
         {
             Profile stored = profileService.getProfile( profile.getId() );
@@ -139,11 +158,15 @@
                 // but in the UI maybe some installations has been we retrieve it
                 // and only set the name related to CONTINUUM-1361
                 String name = profile.getName();
+                String buildAgentGroup = profile.getBuildAgentGroup();
+                
                 profile = profileService.getProfile( profile.getId() );
                 // CONTINUUM-1746 we update the profile only if the name has changed 
-                if ( !StringUtils.equals( name, profile.getName() ) )
+                // jancajas: added build agent group. updated profile if agent group is changed also.
+                if ( !StringUtils.equals( name, profile.getName() ) || !StringUtils.equals( buildAgentGroup, profile.getBuildAgentGroup() ))
                 {
                     profile.setName( name );
+                    profile.setBuildAgentGroup( buildAgentGroup );
                     profileService.updateProfile( profile );
                 }
             }
@@ -311,4 +334,14 @@
     {
         this.message = message;
     }
+
+    public List<BuildAgentGroupConfiguration> getBuildAgentGroups()
+    {
+        return buildAgentGroups;
+    }
+
+    public void setBuildAgentGroups( List<BuildAgentGroupConfiguration> buildAgentGroups )
+    {
+        this.buildAgentGroups = buildAgentGroups;
+    }
 }
Index: continuum-webapp/src/main/resources/struts.xml
===================================================================
--- continuum-webapp/src/main/resources/struts.xml	(revision 745626)
+++ continuum-webapp/src/main/resources/struts.xml	(working copy)
@@ -961,6 +961,30 @@
     <action name="viewBuildAgent" class="buildAgent" method="view">
       <result name="success">/WEB-INF/jsp/admin/viewBuildAgent.jsp</result>
     </action>
+    
+    <action name="deleteBuildAgentGroup" class="buildAgent" method="deleteGroup">
+      <result name="error" type="redirect-action">
+        <param name="actionName">buildAgentList</param>
+        <param name="errorMessage">${message}</param>
+      </result>
+      <result name="confirm">/WEB-INF/jsp/admin/confirmDeleteBuildAgentGroup.jsp</result>
+      <result name="success" type="redirect-action">
+        <param name="actionName">buildAgentList</param>
+      </result>
+    </action>
+    
+    <action name="editBuildAgentGroup" class="buildAgent" method="inputGroup">
+      <result name="input">/WEB-INF/jsp/admin/editBuildAgentGroup.jsp</result>
+      <result name="error">/WEB-INF/jsp/admin/editBuildAgentGroup.jsp</result>
+    </action>
+    
+    <action name="saveBuildAgentGroup" class="buildAgent" method="saveGroup">
+      <result name="input">/WEB-INF/jsp/admin/editBuildAgentGroup.jsp</result>
+      <result name="error">/WEB-INF/jsp/admin/editBuildAgentGroup.jsp</result>
+      <result name="success" type="redirect-action">
+        <param name="actionName">buildAgentList</param>
+      </result>
+    </action>
 
   </package>
 
Index: continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/BuildAgentAction.properties
===================================================================
--- continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/BuildAgentAction.properties	(revision 745626)
+++ continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/BuildAgentAction.properties	(working copy)
@@ -20,4 +20,4 @@
 buildAgent.url.required = Build agent url is required.
 buildAgent.error.exist = Build agent already exists.
 buildAgent.error.delete.busy = Cannot delete build agent because it's busy at the moment
-buildAgent.error.notfound = Build agent does not exist.
\ No newline at end of file
+buildAgent.error.notfound = Build agent does not exist.
Index: continuum-webapp/src/main/resources/localization/Continuum.properties
===================================================================
--- continuum-webapp/src/main/resources/localization/Continuum.properties	(revision 745626)
+++ continuum-webapp/src/main/resources/localization/Continuum.properties	(working copy)
@@ -725,6 +725,7 @@
 profilesList.page.title= Continuum - Build Environments
 profilesList.section.title= Build Environments
 profilesList.installations.label = Installations
+profilesList.buildAgentGroup.label = Build Agent Group
 
 # ----------------------------------------------------------------------
 # Page: Profile Edit
@@ -742,6 +743,7 @@
 profile.remove.error = The Build Environment can't be removed, it is probably used by a build definition.
 profile.installation.name.label = Installation Name
 profile.actionError = Action Error
+profile.build.agent.group = Build Agent Group
 
 # ----------------------------------------------------------------------
 # Page: Installations List
@@ -1055,6 +1057,11 @@
 buildAgents.table.description = Description
 buildAgents.table.enabled = Enabled
 
+buildAgentGroups.section.title = Build Agent Groups
+buildAgentGroups.table.name = Name
+buildAgentGroups.table.agents = Build Agents
+
+
 # ----------------------------------------------------------------------
 # Page: Add/Edit BuildAgent
 # ----------------------------------------------------------------------
@@ -1065,6 +1072,7 @@
 buildAgent.enabled.label = Enabled
 buildAgent.error.doesnotexist = Build agent does not exist
 buildAgent.error.duplicate = Build agent already exists
+buildAgent.error.remove.in.use = Build agent can't be removed, it is probably used by a build agent group.
 
 # ----------------------------------------------------------------------
 # Page: View BuildAgent
@@ -1091,3 +1099,26 @@
 distributedBuild.table.agentUrl = Build Agent URL
 distributedBuilds.empty = No Distributed Builds
 distributedBuilds.removeEntries = Cancel Entries
+
+# ----------------------------------------------------------------------
+# Page: Delete BuildAgentGroup
+# ----------------------------------------------------------------------
+deleteBuildAgentGroup.page.title = Continuum - Delete Build Agent Group
+deleteBuildAgentGroup.section.title = Delete Build Agent Group
+deleteBuildAgentGroup.confirmation.message = Are you sure you want to delete build agent group {0} ?
+
+# ----------------------------------------------------------------------
+# Page: Add/Edit BuildAgentGroup
+# ----------------------------------------------------------------------
+buildAgentGroup.page.title = Continuum - Add/Edit Build Agent Group
+buildAgentGroup.section.title = Add/Edit Build Agent Group
+buildAgentGroup.name.label = Name
+buildAgentGroup.agents.label = Agents
+buildAgentGroup.error.doesnotexist = Build agent group does not exist.
+buildAgentGroup.error.duplicate = Build agent group already exists.
+buildAgentGroup.error.name.required = Build agent group name required.
+buildAgentGroup.error.name.cannot.be.spaces = Build agent group name cannot contain spaces only.
+buildAgentGroup.available.buildAgents = --- Available Build Agents ---
+buildAgentGroup.available.buildAgents.used = --- Used Build Agents ---
+buildAgentGroup.buildAgents.define = Configure the used Build Agents
+buildAgentGroup.error.remove.in.use = Build agent group can't be removed, it is probably used by a build environment.
Index: continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteBuildAgentGroup.jsp
===================================================================
--- continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteBuildAgentGroup.jsp	(revision 0)
+++ continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteBuildAgentGroup.jsp	(revision 0)
@@ -0,0 +1,51 @@
+<%--
+  ~ 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.
+  --%>
+
+<%@ taglib uri="/struts-tags" prefix="s" %>
+<%@ taglib uri="continuum" prefix="c1" %>
+
+<html>
+  <s:i18n name="localization.Continuum">
+    <head>
+        <title><s:text name="deleteBuildAgentGroup.page.title"/></title>
+    </head>
+    <body>
+      <div id="axial" class="h3">
+        <h3><s:text name="deleteBuildAgentGroup.section.title"/></h3>
+
+        <div class="warningmessage">
+          <p>
+            <strong>
+                <s:text name="deleteBuildAgentGroup.confirmation.message">
+                    <s:param><s:property value="buildAgentGroup.name"/></s:param>
+                </s:text>
+            </strong>
+          </p>
+        </div>
+        <div class="functnbar3">
+          <s:form action="deleteBuildAgentGroup!deleteGroup.action" method="post">
+            <input type="hidden" name="buildAgentGroup.name" value="${buildAgentGroup.name}" />
+            <s:hidden name="confirmed" value="true"/>
+            <c1:submitcancel value="%{getText('delete')}" cancel="%{getText('cancel')}"/>
+          </s:form>
+        </div>
+      </div>
+    </body>
+  </s:i18n>
+</html>
Index: continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/buildAgentsList.jsp
===================================================================
--- continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/buildAgentsList.jsp	(revision 745626)
+++ continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/buildAgentsList.jsp	(working copy)
@@ -76,6 +76,51 @@
           <s:submit value="%{getText('add')}"/>
         </s:form>
       </div>
+      <div id="h3">
+        <h3><s:text name="buildAgentGroups.section.title"/></h3>
+        <s:set name="buildAgentGroups" value="buildAgentGroups" scope="request"/>
+        <ec:table items="buildAgentGroups"
+                  var="buildAgentGroup"
+                  showExports="false"
+                  showPagination="false"
+                  showStatusBar="false"
+                  sortable="false"
+                  filterable="false">
+          <ec:row>
+            <ec:column property="name" title="buildAgentGroups.table.name"></ec:column>            
+            <ec:column property="Agents" title="buildAgentGroups.table.agents" style="white-space: nowrap">
+              <ul>                
+                <c:if test="${!empty buildAgentGroup.buildAgents}" >                                 
+                  <c:forEach var="envVar" items="${buildAgentGroup.buildAgents}"> 
+                    <li><c:out value="${envVar.url}" /></li>
+                  </c:forEach>
+                </c:if>
+              </ul>
+            </ec:column>
+            <ec:column property="editActions" title="&nbsp;" width="1%">
+              <s:url id="editBuildAgentGroupUrl" action="editBuildAgentGroup">
+                <s:param name="buildAgentGroup.name">${pageScope.buildAgentGroup.name}</s:param>
+              </s:url>
+              <s:a href="%{editBuildAgentGroupUrl}">
+                <img src="<s:url value='/images/edit.gif' includeParams="none"/>" alt="<s:text name='edit'/>" title="<s:text name='edit'/>" border="0"/>
+              </s:a>
+            </ec:column>
+            <ec:column property="deleteActions" title="&nbsp;" width="1%">
+              <s:url id="removeBuildAgentGroupUrl" action="deleteBuildAgentGroup">
+                <s:param name="buildAgentGroup.name">${pageScope.buildAgentGroup.name}</s:param>
+              </s:url>
+              <s:a href="%{removeBuildAgentGroupUrl}">
+                <img src="<s:url value='/images/delete.gif' includeParams="none"/>" alt="<s:text name='delete'/>" title="<s:text name='delete'/>" border="0"/>
+              </s:a>
+            </ec:column>
+          </ec:row>
+        </ec:table>              
+      </div>
+      <div class="functnbar3">
+        <s:form name="addBuildAgentGroup" action="editBuildAgentGroup" method="post">
+          <s:submit value="%{getText('add')}"/>
+        </s:form>
+      </div>
     </body>
   </s:i18n>
 </html>
\ No newline at end of file
Index: continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editBuildAgentGroup.jsp
===================================================================
--- continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editBuildAgentGroup.jsp	(revision 0)
+++ continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editBuildAgentGroup.jsp	(revision 0)
@@ -0,0 +1,83 @@
+<%--
+  ~ 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.
+  --%>
+  
+<%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
+<%@ taglib uri="/struts-tags" prefix="s" %>
+<%@ taglib uri="continuum" prefix="c1" %>
+<html>
+  <s:i18n name="localization.Continuum">
+    <head>
+      <title><s:text name="buildAgentGroup.page.title"/><title>
+    </head>
+    <body>
+    <div class="app">
+      <div id="axial" class="h3">
+        <h3><s:text name="buildAgentGroup.section.title"/></h3>
+        
+        <div class="axial">
+          <s:form action="saveBuildAgentGroup" method="post"  name="buildAgentGroup">
+            <c:if test="${!empty actionErrors}">
+              <div class="errormessage">
+                <s:iterator value="actionErrors">
+                  <p><s:property/></p>
+                </s:iterator>
+              </div>
+            </c:if>
+            
+            <table>
+              <s:hidden name="typeGroup"/>
+              <c:choose>
+                <c:when test="${typeGroup=='new'}">
+                  <s:textfield label="%{getText('buildAgentGroup.name.label')}" name="buildAgentGroup.name" required="true"/>
+                </c:when>
+                <c:otherwise>
+                  <s:hidden name="buildAgentGroup.name"/>
+                  <s:textfield label="%{getText('buildAgentGroup.name.label')}" name="buildAgentGroup.name" required="true" disabled="true"/>
+                </c:otherwise>
+              </c:choose>
+              
+              <s:optiontransferselect
+                        label="%{getText('buildAgentGroup.buildAgents.define')}"    
+                        name="buildAgentIds"
+                        list="buildAgents" 
+                        listKey="url"
+                        listValue="url"
+                        headerKey="-1"
+                        headerValue="%{getText('buildAgentGroup.available.buildAgents')}"
+                        multiple="true"
+                        emptyOption="false"
+                        doubleName="selectedBuildAgentIds"
+                        doubleList="buildAgentGroup.buildAgents" 
+                        doubleListKey="url"
+                        doubleListValue="url"
+                        doubleHeaderKey="-1"
+                        doubleHeaderValue="%{getText('buildAgentGroup.available.buildAgents.used')}" 
+                        doubleMultiple="true" 
+                        doubleEmptyOption="false"
+                        formName="buildAgentGroup" />                           
+            </table>
+            <div class="functnbar3">
+              <c1:submitcancel value="%{getText('save')}" cancel="%{getText('cancel')}"/>
+            </div>
+          </s:form>
+        </div>
+      </div>
+    </div>
+  </s:i18n>
+ </html>
\ No newline at end of file
Index: continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editProfile.jsp
===================================================================
--- continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editProfile.jsp	(revision 745626)
+++ continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editProfile.jsp	(working copy)
@@ -52,9 +52,27 @@
               <!--  if other fields are added ProfileAction#save must be changed  -->
               <table>
                 <tbody>
-                  <s:hidden name="profile.id" />
-                  <s:textfield label="%{getText('profile.name.label')}" name="profile.name"
-                                required="true" />
+                  <tr>
+                    <td>
+                      <s:hidden name="profile.id" />
+                      <s:textfield label="%{getText('profile.name.label')}" name="profile.name"
+                                   required="true" />
+                    </td>
+                  </tr>
+                  <tr>
+                    <td>
+                      <s:if test ="profile != null">
+                        <s:if test="profile.buildAgentGroup == null">
+                          <s:select label="%{getText('profile.build.agent.group')}" name="profile.buildAgentGroup" list="buildAgentGroups" listValue="name"
+                                   value="-1" listKey="name" headerKey="" headerValue=""/>
+                        </s:if>
+                        <s:else>
+                          <s:select label="%{getText('profile.build.agent.group')}" name="profile.buildAgentGroup" list="buildAgentGroups" listValue="name"
+                                   listKey="name" headerKey="" headerValue=""/>
+                        </s:else>
+                      </s:if>
+                    </td>
+                  </tr>
                 </tbody>
               </table>
               <div class="functnbar3">
Index: continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/profilesList.jsp
===================================================================
--- continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/profilesList.jsp	(revision 745626)
+++ continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/profilesList.jsp	(working copy)
@@ -66,6 +66,7 @@
             </s:if>
           </ul>
         </ec:column>
+        <ec:column property="buildAgentGroup" title="profilesList.buildAgentGroup.label" style="white-space: nowrap" />                
         <ec:column property="id" title="&nbsp;" width="1%">
           <a href="editBuildEnv!edit.action?profile.id=<c:out value="${pageScope.profile.id}"/>">
             <img src="<s:url value='/images/edit.gif' includeParams="none"/>" alt="<s:text name='edit'/>" title="<s:text name='edit'/>" border="0" />
@@ -75,7 +76,7 @@
           <a href="confirmDeleteBuildEnv!confirmDelete.action?profile.id=<c:out value="${pageScope.profile.id}"/>">
             <img src="<s:url value='/images/delete.gif' includeParams="none"/>" alt="<s:text name='delete'/>" title="<s:text name='delete'/>" border="0" />
           </a>                    
-        </ec:column>        
+        </ec:column>                
       </ec:row>
     </ec:table>
     </c:if>
Index: continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/ContinuumBuildAgentUtil.java
===================================================================
--- continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/ContinuumBuildAgentUtil.java	(revision 745626)
+++ continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/ContinuumBuildAgentUtil.java	(working copy)
@@ -299,7 +299,7 @@
 
     public static ScmResult getScmResult( Map context, Object defaultValue )
     {
-        return (ScmResult) getObject( context, KEY_SCM_RESULT );
+        return (ScmResult) getObject( context, KEY_SCM_RESULT, defaultValue );
     }
 
     public static int getTrigger( Map context )
Index: continuum-test/src/main/java/org/apache/maven/continuum/configuration/ConfigurationServiceMock.java
===================================================================
--- continuum-test/src/main/java/org/apache/maven/continuum/configuration/ConfigurationServiceMock.java	(revision 745626)
+++ continuum-test/src/main/java/org/apache/maven/continuum/configuration/ConfigurationServiceMock.java	(working copy)
@@ -21,6 +21,7 @@
 
 import org.apache.continuum.buildqueue.BuildQueueServiceException;
 import org.apache.continuum.configuration.BuildAgentConfiguration;
+import org.apache.continuum.configuration.BuildAgentGroupConfiguration;
 import org.apache.maven.continuum.model.project.BuildQueue;
 import org.apache.maven.continuum.model.project.Schedule;
 import org.apache.maven.continuum.store.ContinuumStoreException;
@@ -286,4 +287,47 @@
     public void updateBuildAgent( BuildAgentConfiguration buildAgent )
     {
     }
+
+    public void addBuildAgentGroup( BuildAgentGroupConfiguration buildAgentGroup )
+        throws ConfigurationException
+    {
+    }
+
+    public void removeBuildAgentGroup( BuildAgentGroupConfiguration buildAgentGroup )
+        throws ConfigurationException
+    {   
+    }
+
+    public void updateBuildAgentGroup( BuildAgentGroupConfiguration buildAgentGroup )
+        throws ConfigurationException
+    {
+    }
+
+    public List<BuildAgentGroupConfiguration> getBuildAgentGroups()
+    {
+        return null;
+    }
+
+    public void addBuildAgent( BuildAgentGroupConfiguration buildAgentGroup, BuildAgentConfiguration buildAgent )
+        throws ConfigurationException
+    {
+    }
+
+    public void removeBuildAgent( BuildAgentGroupConfiguration buildAgentGroup, BuildAgentConfiguration buildAgent )
+        throws ConfigurationException
+    {
+    }
+    public BuildAgentGroupConfiguration getBuildAgentGroup( String name )
+    {
+        return null;
+    }
+    public BuildAgentConfiguration getBuildAgent(String url)
+    {
+        return null;
+    }
+
+    public boolean containsBuildAgentUrl( String buildAgentUrl, BuildAgentGroupConfiguration buildAgentGroup )
+    {
+        return false;
+    }
 }
