Merged fixed release notes for 1.4.3 from trunk.

git-svn-id: https://svn.apache.org/repos/asf/continuum/branches/continuum-1.4.3-notes-fixup@1656908 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b5968d4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+target
+.settings/
+.project
+.settings
+.classpath
+continuum-webapp/src/main/webapp/template/
+*.iml
+.idea
+build/
diff --git a/Continuum.sonarj b/Continuum.sonarj
new file mode 100644
index 0000000..4987146
--- /dev/null
+++ b/Continuum.sonarj
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<context version="4.1.0.304">
+    <scope name="Continuum" type="Project">
+        <architecture>
+            <element name="Web Application" type="Layer">
+                <element name="Assignment" type="TypeFilter"/>
+                <stereotype name="Unrestricted"/>
+            </element>
+            <element name="XMLRPC" type="Layer">
+                <element name="Assignment" type="TypeFilter"/>
+                <stereotype name="Unrestricted"/>
+            </element>
+            <element name="Core API" type="Layer">
+                <element name="Assignment" type="TypeFilter"/>
+                <stereotype name="Unrestricted"/>
+            </element>
+            <element name="Core" type="Layer">
+                <element name="Assignment" type="TypeFilter"/>
+                <stereotype name="Unrestricted"/>
+            </element>
+            <element name="Notifiers" type="Layer">
+                <element name="Assignment" type="TypeFilter"/>
+                <stereotype name="Unrestricted"/>
+            </element>
+            <element name="Data Management" type="Layer">
+                <element name="Assignment" type="TypeFilter"/>
+                <stereotype name="Unrestricted"/>
+            </element>
+            <element name="Store" type="Layer">
+                <element name="Assignment" type="TypeFilter"/>
+                <stereotype name="Unrestricted"/>
+            </element>
+            <element name="Model" type="Layer">
+                <element name="Assignment" type="TypeFilter"/>
+                <stereotype name="Unrestricted"/>
+            </element>
+            <element name="Builder API" type="Layer">
+                <element name="Assignment" type="TypeFilter"/>
+                <stereotype name="Unrestricted"/>
+            </element>
+            <element name="REST" type="Layer">
+                <element name="Assignment" type="TypeFilter"/>
+                <stereotype name="Unrestricted"/>
+            </element>
+            <element name="Builder" type="Layer">
+                <element name="Assignment" type="TypeFilter"/>
+                <stereotype name="Unrestricted"/>
+            </element>
+            <element name="Configuration" type="Layer">
+                <element name="Assignment" type="TypeFilter"/>
+                <stereotype name="Unrestricted"/>
+            </element>
+            <element name="Build Queue" type="Layer">
+                <element name="Assignment" type="TypeFilter"/>
+                <stereotype name="Unrestricted"/>
+            </element>
+            <element name="Results" type="Layer">
+                <element name="Assignment" type="TypeFilter"/>
+                <stereotype name="Unrestricted"/>
+            </element>
+            <element name="Checkout" type="Layer">
+                <element name="Assignment" type="TypeFilter"/>
+                <stereotype name="Unrestricted"/>
+            </element>
+            <element name="Release" type="Layer">
+                <element name="Assignment" type="TypeFilter"/>
+                <stereotype name="Unrestricted"/>
+            </element>
+        </architecture>
+    </scope>
+    <scope name="External" type="External">
+        <element name="Filter" type="TypeFilter">
+            <element name="**" type="IncludeTypePattern"/>
+        </element>
+    </scope>
+    <scope name="Global" type="Global">
+        <element name="Configuration" type="Configuration">
+            <element name="CycleAnalysisAsymmetrical" type="ConfigurationSwitchDisabled"/>
+            <element name="CycleAnalysisDepthSourceFile" type="ConfigurationSwitchDisabled"/>
+        </element>
+        <element name="Filter" type="TypeFilter">
+            <element name="**" type="IncludeTypePattern"/>
+        </element>
+    </scope>
+</context>
diff --git a/LICENSE.txt b/LICENSE
similarity index 100%
rename from LICENSE.txt
rename to LICENSE
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..d26a672
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,8 @@
+
+Apache Continuum
+Copyright 2003-2014 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+
diff --git a/NOTICE.txt b/NOTICE.txt
deleted file mode 100644
index 3f59805..0000000
--- a/NOTICE.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-This product includes software developed by
-The Apache Software Foundation (http://www.apache.org/).
diff --git a/build.bat b/build.bat
index 591142c..a6bd656 100644
--- a/build.bat
+++ b/build.bat
@@ -1,4 +1,24 @@
 @echo off
+
+@REM #
+@REM # Licensed to the Apache Software Foundation (ASF) under one
+@REM # or more contributor license agreements.  See the NOTICE file
+@REM # distributed with this work for additional information
+@REM # regarding copyright ownership.  The ASF licenses this file
+@REM # to you under the Apache License, Version 2.0 (the
+@REM # "License"); you may not use this file except in compliance
+@REM # with the License.  You may obtain a copy of the License at
+@REM #
+@REM #   http://www.apache.org/licenses/LICENSE-2.0
+@REM #
+@REM # Unless required by applicable law or agreed to in writing,
+@REM # software distributed under the License is distributed on an
+@REM # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM # KIND, either express or implied.  See the License for the
+@REM # specific language governing permissions and limitations
+@REM # under the License.
+@REM #
+
 @REM Decide how to startup depending on the version of windows
 
 @REM -- Win98ME
diff --git a/build.sh b/build.sh
index 049df32..4ec2379 100644
--- a/build.sh
+++ b/build.sh
@@ -1,5 +1,24 @@
 #!/bin/bash
 
+#
+# 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.
+#
+
 set -e
 set -x
 
@@ -17,4 +36,4 @@
   mvn -Denv=test clean:clean install "$@"
   ret=$?; if [ $ret != 0 ]; then exit $ret; fi
 ) 2>&1 | tee result.log
-ret=$?; if [ $ret != 0 ]; then exit $ret; fi
\ No newline at end of file
+ret=$?; if [ $ret != 0 ]; then exit $ret; fi
diff --git a/continuum-api/pom.xml b/continuum-api/pom.xml
index 9cd466a..265c249 100644
--- a/continuum-api/pom.xml
+++ b/continuum-api/pom.xml
@@ -1,27 +1,28 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
+  ~ 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.
+  -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <artifactId>continuum</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>continuum-api</artifactId>
@@ -32,8 +33,8 @@
       <artifactId>continuum-model</artifactId>
     </dependency>
     <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-spring</artifactId>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-buildagent-api</artifactId>
     </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
@@ -41,29 +42,52 @@
     </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-jdo2</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-taskqueue</artifactId>
     </dependency>
     <dependency>
       <groupId>commons-lang</groupId>
       <artifactId>commons-lang</artifactId>
-    </dependency>    
+    </dependency>
     <dependency>
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-artifact</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.archiva</groupId>
-      <artifactId>archiva-common</artifactId>
-      <version>${archiva.version}</version>
+      <artifactId>archiva-model</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.archiva</groupId>
       <artifactId>archiva-repository-layer</artifactId>
-      <version>${archiva.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.release</groupId>
+      <artifactId>maven-release-manager</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-simple</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-context</artifactId>
     </dependency>
   </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <systemProperties>
+                        <sleepClasspath>${project.build.testOutputDirectory}</sleepClasspath>
+                    </systemProperties>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 </project>
diff --git a/continuum-api/src/main/java/org/apache/continuum/builder/distributed/DistributedBuildService.java b/continuum-api/src/main/java/org/apache/continuum/builder/distributed/DistributedBuildService.java
new file mode 100644
index 0000000..b64d192
--- /dev/null
+++ b/continuum-api/src/main/java/org/apache/continuum/builder/distributed/DistributedBuildService.java
@@ -0,0 +1,49 @@
+package org.apache.continuum.builder.distributed;
+
+/*
+ * 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 org.apache.maven.continuum.ContinuumException;
+
+import java.util.Map;
+
+public interface DistributedBuildService
+{
+    String ROLE = DistributedBuildService.class.getName();
+
+    void prepareBuildFinished( Map<String, Object> context )
+        throws ContinuumException;
+
+    boolean shouldBuild( Map<String, Object> context );
+
+    void startPrepareBuild( Map<String, Object> context )
+        throws ContinuumException;
+
+    void startProjectBuild( int projectId )
+        throws ContinuumException;
+
+    void updateBuildResult( Map<String, Object> context )
+        throws ContinuumException;
+
+    void updateProject( Map<String, Object> context )
+        throws ContinuumException;
+
+    Map<String, String> getEnvironments( int buildDefinitionId, String installationType )
+        throws ContinuumException;
+}
diff --git a/continuum-builder/src/main/java/org/apache/continuum/builder/distributed/executor/DistributedBuildTaskExecutor.java b/continuum-api/src/main/java/org/apache/continuum/builder/distributed/executor/DistributedBuildTaskExecutor.java
similarity index 100%
rename from continuum-builder/src/main/java/org/apache/continuum/builder/distributed/executor/DistributedBuildTaskExecutor.java
rename to continuum-api/src/main/java/org/apache/continuum/builder/distributed/executor/DistributedBuildTaskExecutor.java
diff --git a/continuum-api/src/main/java/org/apache/continuum/builder/distributed/executor/DistributedBuildTaskQueueExecutor.java b/continuum-api/src/main/java/org/apache/continuum/builder/distributed/executor/DistributedBuildTaskQueueExecutor.java
new file mode 100644
index 0000000..a7c2909
--- /dev/null
+++ b/continuum-api/src/main/java/org/apache/continuum/builder/distributed/executor/DistributedBuildTaskQueueExecutor.java
@@ -0,0 +1,65 @@
+package org.apache.continuum.builder.distributed.executor;
+
+/*
+ * 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 org.codehaus.plexus.taskqueue.Task;
+import org.codehaus.plexus.taskqueue.TaskQueue;
+
+public interface DistributedBuildTaskQueueExecutor
+{
+    String ROLE = DistributedBuildTaskQueueExecutor.class.getName();
+
+    /**
+     * Returns the build agent url of task queue executor
+     *
+     * @return the build agent url
+     */
+    String getBuildAgentUrl();
+
+    /**
+     * Sets the build agent url of this task queue executor
+     *
+     * @param buildAgentUrl
+     */
+    void setBuildAgentUrl( String buildAgentUrl );
+
+    /**
+     * Returns the currently executing task.
+     *
+     * @return the currently executing task.
+     */
+    Task getCurrentTask();
+
+    /**
+     * Cancels execution of this task, if it's currently running.
+     * Does NOT remove it from the associated queue!
+     *
+     * @param task The task to cancel
+     * @return true if the task was cancelled, false if the task was not executing.
+     */
+    boolean cancelTask( Task task );
+
+    /**
+     * Returns the task queue
+     *
+     * @return the TaskQueue of the task queue executor
+     */
+    public TaskQueue getQueue();
+}
diff --git a/continuum-api/src/main/java/org/apache/continuum/builder/distributed/manager/DistributedBuildManager.java b/continuum-api/src/main/java/org/apache/continuum/builder/distributed/manager/DistributedBuildManager.java
index ddcedf7..5bf8c87 100644
--- a/continuum-api/src/main/java/org/apache/continuum/builder/distributed/manager/DistributedBuildManager.java
+++ b/continuum-api/src/main/java/org/apache/continuum/builder/distributed/manager/DistributedBuildManager.java
@@ -19,39 +19,34 @@
  * under the License.
  */
 
-import java.util.List;
-import java.util.Map;
-
+import org.apache.continuum.buildagent.NoBuildAgentException;
+import org.apache.continuum.buildagent.NoBuildAgentInGroupException;
+import org.apache.continuum.configuration.BuildAgentConfiguration;
+import org.apache.continuum.model.project.ProjectRunSummary;
+import org.apache.continuum.model.project.ProjectScmRoot;
+import org.apache.continuum.taskqueue.BuildProjectTask;
 import org.apache.continuum.taskqueue.PrepareBuildProjectsTask;
+import org.apache.continuum.utils.build.BuildTrigger;
 import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.model.system.Installation;
 
+import java.util.List;
+import java.util.Map;
+
 public interface DistributedBuildManager
 {
     String ROLE = DistributedBuildManager.class.getName();
 
-    void cancelDistributedBuild( String buildAgentUrl, int projectGroupId, String scmRootAddress )
-        throws ContinuumException;
-
-    void updateScmResult( Map context )
-        throws ContinuumException;
-
-    void updateBuildResult( Map context )
-        throws ContinuumException;
-
-    void prepareBuildFinished( Map context )
-        throws ContinuumException;
-
-    void startProjectBuild( int projectId )
-        throws ContinuumException;
-
-    void startPrepareBuild( Map context )
+    void cancelDistributedBuild( String buildAgentUrl )
         throws ContinuumException;
 
     void reload()
         throws ContinuumException;
-    
-    void removeAgentFromTaskQueueExecutor( String buildAgentUrl )
+
+    void update( BuildAgentConfiguration buildAgent )
+        throws ContinuumException;
+
+    void removeDistributedBuildQueueOfAgent( String buildAgentUrl )
         throws ContinuumException;
 
     boolean isBuildAgentBusy( String buildAgentUrl );
@@ -59,11 +54,75 @@
     List<Installation> getAvailableInstallations( String buildAgentUrl )
         throws ContinuumException;
 
-    Map<String, PrepareBuildProjectsTask> getDistributedBuildProjects();
+    String getBuildAgentPlatform( String buildAgentUrl )
+        throws ContinuumException;
+
+    Map<String, List<PrepareBuildProjectsTask>> getProjectsInPrepareBuildQueue()
+        throws ContinuumException;
+
+    Map<String, List<BuildProjectTask>> getProjectsInBuildQueue()
+        throws ContinuumException;
 
     Map<String, Object> getBuildResult( int projectId )
         throws ContinuumException;
 
-    Map<String, String> getEnvironments( int buildDefinitionId, String installationType )
+    String generateWorkingCopyContent( int projectId, String directory, String baseUrl, String imagesBaseUrl )
+        throws ContinuumException;
+
+    Map<String, Object> getFileContent( int projectId, String directory, String filename )
+        throws ContinuumException;
+
+    void prepareBuildProjects( Map<Integer, Integer> projectsBuildDefinitionsMap, BuildTrigger buildTrigger,
+                               int projectGroupId, String projectGroupName, String scmRootAddress, int scmRootId,
+                               List<ProjectScmRoot> scmRoots )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException;
+
+    Map<String, PrepareBuildProjectsTask> getProjectsCurrentlyPreparingBuild()
+        throws ContinuumException;
+
+    Map<String, BuildProjectTask> getProjectsCurrentlyBuilding()
+        throws ContinuumException;
+
+    void removeFromPrepareBuildQueue( String buildAgnetUrl, int projectGroupId, int scmRootId )
+        throws ContinuumException;
+
+    void removeFromPrepareBuildQueue( List<String> hashCodes )
+        throws ContinuumException;
+
+    void removeFromBuildQueue( String buildAgentUrl, int projectId, int buildDefinitionId )
+        throws ContinuumException;
+
+    void removeFromBuildQueue( List<String> hashCodes )
+        throws ContinuumException;
+
+    boolean isAgentAvailable( String buildAgentUrl )
+        throws ContinuumException;
+
+    boolean pingBuildAgent( String buildAgentUrl )
+        throws ContinuumException;
+
+    boolean isProjectInAnyPrepareBuildQueue( int projectId, int buildDefinitionId )
+        throws ContinuumException;
+
+    boolean isProjectInAnyBuildQueue( int projectId, int buildDefinitionId )
+        throws ContinuumException;
+
+    boolean isProjectCurrentlyPreparingBuild( int projectId, int buildDefinitionId )
+        throws ContinuumException;
+
+    boolean isProjectCurrentlyBuilding( int projectId, int buildDefinitionId )
+        throws ContinuumException;
+
+    String getBuildAgentUrl( int projectId, int buildDefinitionId )
+        throws ContinuumException;
+
+    List<ProjectRunSummary> getCurrentRuns();
+
+    void removeCurrentRun( int projectId, int buildDefinitionId );
+
+    void cancelBuild( int projectId )
+        throws ContinuumException;
+
+    void cancelGroupBuild( int projectGroupId )
         throws ContinuumException;
 }
diff --git a/continuum-api/src/main/java/org/apache/continuum/builder/distributed/work/ContinuumWorker.java b/continuum-api/src/main/java/org/apache/continuum/builder/distributed/work/ContinuumWorker.java
new file mode 100644
index 0000000..30f55db
--- /dev/null
+++ b/continuum-api/src/main/java/org/apache/continuum/builder/distributed/work/ContinuumWorker.java
@@ -0,0 +1,25 @@
+package org.apache.continuum.builder.distributed.work;
+
+/*
+ * 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.
+ */
+
+public interface ContinuumWorker
+{
+    void work();
+}
diff --git a/continuum-api/src/main/java/org/apache/continuum/buildmanager/BuildManagerException.java b/continuum-api/src/main/java/org/apache/continuum/buildmanager/BuildManagerException.java
new file mode 100644
index 0000000..4e07c08
--- /dev/null
+++ b/continuum-api/src/main/java/org/apache/continuum/buildmanager/BuildManagerException.java
@@ -0,0 +1,42 @@
+package org.apache.continuum.buildmanager;
+
+/*
+ * 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.
+ */
+
+/**
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ */
+public class BuildManagerException
+    extends Exception
+{
+    public BuildManagerException( String message )
+    {
+        super( message );
+    }
+
+    public BuildManagerException( Throwable cause )
+    {
+        super( cause );
+    }
+
+    public BuildManagerException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}
diff --git a/continuum-api/src/main/java/org/apache/continuum/buildmanager/BuildsManager.java b/continuum-api/src/main/java/org/apache/continuum/buildmanager/BuildsManager.java
new file mode 100644
index 0000000..ebbded7
--- /dev/null
+++ b/continuum-api/src/main/java/org/apache/continuum/buildmanager/BuildsManager.java
@@ -0,0 +1,476 @@
+package org.apache.continuum.buildmanager;
+
+/*
+ * 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 org.apache.continuum.taskqueue.BuildProjectTask;
+import org.apache.continuum.taskqueue.CheckOutTask;
+import org.apache.continuum.taskqueue.PrepareBuildProjectsTask;
+import org.apache.continuum.utils.build.BuildTrigger;
+import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.BuildQueue;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.scm.ScmResult;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * BuildsManager. All builds whether forced or triggered will go through (or have to be added through) a builds manager.
+ *
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ */
+public interface BuildsManager
+{
+    /**
+     * Build projects using their corresponding build definitions. This method adds the group of projects to the
+     * build queue of the overall queue with the least amount of tasks queued.
+     *
+     * @param projects
+     * @param projectsBuildDefinitionsMap
+     * @param buildTrigger
+     * @param scmResultMap                TODO
+     * @param projectGroupId
+     * @throws BuildManagerException
+     */
+    void buildProjects( List<Project> projects, Map<Integer, BuildDefinition> projectsBuildDefinitionsMap,
+                        BuildTrigger buildTrigger, Map<Integer, ScmResult> scmResultMap, int projectGroupId )
+        throws BuildManagerException;
+
+    /**
+     * Build the project using the specified build definition. Adds the project to the build queue of the overall queue with the
+     * least among of tasks queued. The overall queue is chosen from the pool of queues attached to the schedule of the
+     * build definition.
+     *
+     * @param projectId
+     * @param buildDefinition
+     * @param projectName
+     * @param buildTrigger
+     * @param scmResult       TODO
+     * @param projectGroupId
+     * @throws BuildManagerException
+     */
+    void buildProject( int projectId, BuildDefinition buildDefinition, String projectName, BuildTrigger buildTrigger,
+                       ScmResult scmResult, int projectGroupId )
+        throws BuildManagerException;
+
+    /**
+     * Adds the projects in the prepare-build-queue.
+     *
+     * @param projectsBuildDefinitionsMap
+     * @param buildTrigger
+     * @param projectGroupId              TODO
+     * @param scmRootAddress              TODO
+     * @param scmRootId
+     * @throws BuildManagerException
+     */
+    void prepareBuildProjects( Map<Integer, Integer> projectsBuildDefinitionsMap, BuildTrigger buildTrigger,
+                               int projectGroupId, String projectGroupName, String scmRootAddress, int scmRootId )
+        throws BuildManagerException;
+
+    /**
+     * Adds the project to the checkout queue of the overall build queue with the least amount of tasks queued.
+     * The overall queue is chosen from the pool of queues attached to the schedule of the build definition.
+     *
+     * @param projectId
+     * @param projectName
+     * @param workingDirectory
+     * @param scmRootUrl             TODO
+     * @param scmUsername
+     * @param scmPassword
+     * @param defaultBuildDefinition
+     * @param subProjects            TODO
+     * @throws BuildManagerException
+     */
+    void checkoutProject( int projectId, String projectName, File workingDirectory, String scmRootUrl,
+                          String scmUsername, String scmPassword, BuildDefinition defaultBuildDefinition,
+                          List<Project> subProjects )
+        throws BuildManagerException;
+
+    /**
+     * Cancels the specified project's build.
+     *
+     * @param projectId
+     * @return
+     * @throws BuildManagerException
+     */
+    boolean cancelBuild( int projectId )
+        throws BuildManagerException;
+
+    /**
+     * Cancels all the builds in all the overall queues.
+     *
+     * @return
+     * @throws BuildManagerException
+     */
+    boolean cancelAllBuilds()
+        throws BuildManagerException;
+
+    /**
+     * Cancels the current build on the specified overall queue.
+     *
+     * @param buildQueueId
+     * @return
+     * @throws BuildManagerException
+     */
+    boolean cancelBuildInQueue( int buildQueueId )
+        throws BuildManagerException;
+
+    /**
+     * @param projectId
+     * @return
+     * @throws BuildManagerException
+     */
+    boolean cancelCheckout( int projectId )
+        throws BuildManagerException;
+
+    /**
+     * @return
+     * @throws BuildManagerException
+     */
+    boolean cancelAllCheckouts()
+        throws BuildManagerException;
+
+    // public boolean cancelPrepareBuild(int projectId) throws BuildManagerException;
+
+    /**
+     * Cancels all the prepare builds in all overall queues
+     */
+    boolean cancelAllPrepareBuilds()
+        throws BuildManagerException;
+
+    /**
+     * Cancels the specified project group prepare build
+     *
+     * @param projectGroupId
+     * @param scmRootId
+     * @return
+     * @throws BuildManagerException
+     */
+    boolean cancelPrepareBuild( int projectGroupId, int scmRootId )
+        throws BuildManagerException;
+
+    /**
+     * Cancels the specified project prepare build
+     *
+     * @param projectId
+     * @return
+     * @throws BuildManagerException
+     */
+    boolean cancelPrepareBuild( int projectId )
+        throws BuildManagerException;
+
+    /**
+     * Removes the project from the build queue.
+     *
+     * @param projectId
+     * @throws BuildManagerException
+     */
+    void removeProjectFromBuildQueue( int projectId )
+        throws BuildManagerException;
+
+    /**
+     * Removes the project built using the specified build definition from the build queue.
+     *
+     * @param projectId
+     * @param buildDefinitionId
+     * @param buildTrigger
+     * @param projectName
+     * @param projectGroupId
+     * @throws BuildManagerException
+     */
+    void removeProjectFromBuildQueue( int projectId, int buildDefinitionId, BuildTrigger buildTrigger,
+                                      String projectName, int projectGroupId )
+        throws BuildManagerException;
+
+    // TODO: should we throw an exception when one of the projects cannot be removed?
+
+    /**
+     * Removes the specified projects from their build queues.
+     *
+     * @param projectIds
+     */
+    void removeProjectsFromBuildQueue( int[] projectIds );
+
+    /**
+     * Removes a set of projects using the specified hashcodes from the build queues.
+     *
+     * @param hascodes
+     * @throws BuildManagerException
+     */
+    void removeProjectsFromBuildQueueWithHashcodes( int[] hascodes )
+        throws BuildManagerException;
+
+    /**
+     * Removes the project from the checkout queue.
+     *
+     * @param projectId
+     * @throws BuildManagerException
+     */
+    void removeProjectFromCheckoutQueue( int projectId )
+        throws BuildManagerException;
+
+    /**
+     * Removes the specified projects from their checkout queues.
+     *
+     * @param projectIds
+     */
+    void removeProjectsFromCheckoutQueue( int[] projectIds );
+
+    /**
+     * Removes a set of projects using the specified hashcodes from the checkout queues.
+     *
+     * @param hashcodes
+     * @throws BuildManagerException
+     */
+    void removeProjectsFromCheckoutQueueWithHashcodes( int[] hashcodes )
+        throws BuildManagerException;
+
+    boolean removeProjectGroupFromPrepareBuildQueue( int projectGroupId, String scmRootAddress )
+        throws BuildManagerException;
+
+    /*void removeProjectFromPrepareBuildQueue( int projectId ) throws BuildManagerException;
+
+void removeProjectsFromPrepareBuildQueue( int[] projectIds ) throws BuildManagerException;*/
+
+    /**
+     * Add an overall build queue.
+     *
+     * @param buildQueue
+     * @throws BuildManagerException TODO
+     */
+    void addOverallBuildQueue( BuildQueue buildQueue )
+        throws BuildManagerException;
+
+    /**
+     * Remove an overall build queue.
+     *
+     * @param overallBuildQueueId
+     * @throws BuildManagerException
+     */
+    void removeOverallBuildQueue( int overallBuildQueueId )
+        throws BuildManagerException;
+
+    /**
+     * Checks whether the project build is queued.
+     *
+     * @param projectId
+     * @return
+     * @throws BuildManagerException
+     */
+    boolean isInAnyBuildQueue( int projectId )
+        throws BuildManagerException;
+
+    /**
+     * Checks whether the project build using the specified build definition is queued.
+     *
+     * @param projectId
+     * @param buildDefinitionId
+     * @return
+     * @throws BuildManagerException
+     */
+    boolean isInAnyBuildQueue( int projectId, int buildDefinitionId )
+        throws BuildManagerException;
+
+    /**
+     * Checks whether the project checkout is already queued.
+     *
+     * @param projectId
+     * @return
+     * @throws BuildManagerException
+     */
+    boolean isInAnyCheckoutQueue( int projectId )
+        throws BuildManagerException;
+
+    /**
+     * Checks if at least one of the projects is currently being checked out.
+     *
+     * @param projectIds
+     * @return
+     * @throws BuildManagerException
+     */
+    boolean isAnyProjectCurrentlyBeingCheckedOut( int[] projectIds )
+        throws BuildManagerException;
+
+    /**
+     * Checks whether the project is already in the prepare-build queue.
+     *
+     * @param projectId
+     * @return
+     * @throws BuildManagerException
+     */
+    boolean isInPrepareBuildQueue( int projectId )
+        throws BuildManagerException;
+
+    /**
+     * Checks where the project group is already in the prepare-build queue
+     *
+     * @param projectGroupId
+     * @param scmRootId
+     * @return
+     * @throws BuildManagerException
+     */
+    boolean isInPrepareBuildQueue( int projectGroupId, int scmRootId )
+        throws BuildManagerException;
+
+    /**
+     * Checks whether the project is currently being built.
+     *
+     * @param projectId
+     * @return
+     * @throws BuildManagerException
+     */
+    boolean isProjectInAnyCurrentBuild( int projectId )
+        throws BuildManagerException;
+
+    /**
+     * Checks if at least one of the projects is currently preparing build
+     *
+     * @param projectIds
+     * @return
+     * @throws BuildManagerException
+     */
+    boolean isAnyProjectCurrentlyPreparingBuild( int[] projectIds )
+        throws BuildManagerException;
+
+    // needed in QueuesAction
+
+    /**
+     * Returns all the build tasks currently being executed.
+     *
+     * @return
+     * @throws BuildManagerException
+     */
+    Map<String, BuildProjectTask> getCurrentBuilds()
+        throws BuildManagerException;
+
+    /**
+     * Returns all the checkout tasks currently being executed.
+     *
+     * @return
+     * @throws BuildManagerException
+     */
+    Map<String, CheckOutTask> getCurrentCheckouts()
+        throws BuildManagerException;
+
+    /**
+     * Returns all the overall build queues together with a list of the build tasks in it's build queue.
+     *
+     * @return
+     * @throws BuildManagerException
+     */
+    Map<String, List<BuildProjectTask>> getProjectsInBuildQueues()
+        throws BuildManagerException;
+
+    /**
+     * Returns all the overall build queues together with a list of checkout tasks in it's checkout queue.
+     *
+     * @return
+     * @throws BuildManagerException
+     */
+    Map<String, List<CheckOutTask>> getProjectsInCheckoutQueues()
+        throws BuildManagerException;
+
+    /**
+     * Checks whether a build is in progress.
+     *
+     * @return
+     */
+    boolean isBuildInProgress();
+
+    /**
+     * Checks if at least one of the projects is currently building.
+     *
+     * @param projectIds
+     * @return
+     * @throws BuildManagerException
+     */
+    boolean isAnyProjectCurrentlyBuilding( int[] projectIds )
+        throws BuildManagerException;
+
+    /**
+     * Checks whether project is currently being checked out.
+     *
+     * @param projectId
+     * @return
+     * @throws BuildManagerException
+     */
+    boolean isProjectCurrentlyBeingCheckedOut( int projectId )
+        throws BuildManagerException;
+
+    /**
+     * Checks whether project is currently preparing build
+     *
+     * @param projectId
+     * @return
+     * @throws BuildManagerException
+     */
+    boolean isProjectCurrentlyPreparingBuild( int projectId )
+        throws BuildManagerException;
+
+    /**
+     * Checks whether project group is currently preparing build
+     *
+     * @param projectGroupId
+     * @param scmRootId
+     * @return
+     * @throws BuildManagerException
+     */
+    boolean isProjectGroupCurrentlyPreparingBuild( int projectGroupId, int scmRootId )
+        throws BuildManagerException;
+
+    /**
+     * Return currently preparing build project.
+     *
+     * @return
+     * @throws BuildManagerException
+     */
+    Map<String, PrepareBuildProjectsTask> getCurrentProjectInPrepareBuild()
+        throws BuildManagerException;
+
+    /**
+     * Return all projects in prepare build queue.
+     *
+     * @return
+     * @throws BuildManagerException
+     */
+    Map<String, List<PrepareBuildProjectsTask>> getProjectsInPrepareBuildQueue()
+        throws BuildManagerException;
+
+    /**
+     * Remove a project from a prepare build queue.
+     *
+     * @param projectGroupId
+     * @param scmRootId
+     * @return
+     * @throws BuildManagerException
+     */
+    boolean removeProjectFromPrepareBuildQueue( int projectGroupId, int scmRootId )
+        throws BuildManagerException;
+
+    /**
+     * Removes a set of projects using the specified hashcodes from the prepare build queues.
+     *
+     * @param hashcodes
+     * @throws BuildManagerException
+     */
+    void removeProjectsFromPrepareBuildQueueWithHashCodes( int[] hashCodes )
+        throws BuildManagerException;
+}
diff --git a/continuum-api/src/main/java/org/apache/continuum/buildqueue/BuildQueueService.java b/continuum-api/src/main/java/org/apache/continuum/buildqueue/BuildQueueService.java
new file mode 100644
index 0000000..a882c3c
--- /dev/null
+++ b/continuum-api/src/main/java/org/apache/continuum/buildqueue/BuildQueueService.java
@@ -0,0 +1,48 @@
+package org.apache.continuum.buildqueue;
+
+/*
+ * 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 org.apache.maven.continuum.model.project.BuildQueue;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ */
+public interface BuildQueueService
+{
+    BuildQueue addBuildQueue( BuildQueue buildQueue )
+        throws BuildQueueServiceException;
+
+    void removeBuildQueue( BuildQueue buildQueue )
+        throws BuildQueueServiceException;
+
+    BuildQueue getBuildQueue( int buildQueueId )
+        throws BuildQueueServiceException;
+
+    BuildQueue getBuildQueueByName( String buildQueueName )
+        throws BuildQueueServiceException;
+
+    BuildQueue updateBuildQueue( BuildQueue buildQueue )
+        throws BuildQueueServiceException;
+
+    List<BuildQueue> getAllBuildQueues()
+        throws BuildQueueServiceException;
+}
diff --git a/continuum-api/src/main/java/org/apache/continuum/buildqueue/BuildQueueServiceException.java b/continuum-api/src/main/java/org/apache/continuum/buildqueue/BuildQueueServiceException.java
new file mode 100644
index 0000000..27e2fb3
--- /dev/null
+++ b/continuum-api/src/main/java/org/apache/continuum/buildqueue/BuildQueueServiceException.java
@@ -0,0 +1,42 @@
+package org.apache.continuum.buildqueue;
+
+/*
+ * 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.
+ */
+
+/**
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ */
+public class BuildQueueServiceException
+    extends Exception
+{
+    public BuildQueueServiceException( String message )
+    {
+        super( message );
+    }
+
+    public BuildQueueServiceException( Throwable cause )
+    {
+        super( cause );
+    }
+
+    public BuildQueueServiceException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}
diff --git a/continuum-api/src/main/java/org/apache/continuum/configuration/BuildAgentConfiguration.java b/continuum-api/src/main/java/org/apache/continuum/configuration/BuildAgentConfiguration.java
index 514c308..05fe9c5 100644
--- a/continuum-api/src/main/java/org/apache/continuum/configuration/BuildAgentConfiguration.java
+++ b/continuum-api/src/main/java/org/apache/continuum/configuration/BuildAgentConfiguration.java
@@ -1,5 +1,24 @@
 package org.apache.continuum.configuration;
 
+/*
+ * 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.
+ */
+
 public class BuildAgentConfiguration
 {
     private String url;
diff --git a/continuum-api/src/main/java/org/apache/continuum/configuration/BuildAgentConfigurationException.java b/continuum-api/src/main/java/org/apache/continuum/configuration/BuildAgentConfigurationException.java
new file mode 100644
index 0000000..7c6a7a8
--- /dev/null
+++ b/continuum-api/src/main/java/org/apache/continuum/configuration/BuildAgentConfigurationException.java
@@ -0,0 +1,39 @@
+package org.apache.continuum.configuration;
+
+/*
+ * 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.
+ */
+
+public class BuildAgentConfigurationException
+    extends Exception
+{
+    public BuildAgentConfigurationException( String message )
+    {
+        super( message );
+    }
+
+    public BuildAgentConfigurationException( Throwable cause )
+    {
+        super( cause );
+    }
+
+    public BuildAgentConfigurationException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}
diff --git a/continuum-api/src/main/java/org/apache/continuum/configuration/BuildAgentGroupConfiguration.java b/continuum-api/src/main/java/org/apache/continuum/configuration/BuildAgentGroupConfiguration.java
new file mode 100644
index 0000000..7567888
--- /dev/null
+++ b/continuum-api/src/main/java/org/apache/continuum/configuration/BuildAgentGroupConfiguration.java
@@ -0,0 +1,81 @@
+package org.apache.continuum.configuration;
+
+/*
+ * 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;
+
+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;
+    }
+
+}
diff --git a/continuum-api/src/main/java/org/apache/continuum/configuration/ContinuumConfiguration.java b/continuum-api/src/main/java/org/apache/continuum/configuration/ContinuumConfiguration.java
index 8c94e0d..1120d6a 100644
--- a/continuum-api/src/main/java/org/apache/continuum/configuration/ContinuumConfiguration.java
+++ b/continuum-api/src/main/java/org/apache/continuum/configuration/ContinuumConfiguration.java
@@ -31,6 +31,7 @@
     /**
      * @return an empty or a filled on but never null !
      * @throws ContinuumConfigurationException
+     *
      */
     GeneralConfiguration getGeneralConfiguration()
         throws ContinuumConfigurationException;
@@ -44,9 +45,9 @@
     void save( File file )
         throws ContinuumConfigurationException;
 
-    void reload( )
-    throws ContinuumConfigurationException;    
-    
+    void reload()
+        throws ContinuumConfigurationException;
+
     void reload( File file )
         throws ContinuumConfigurationException;
 }
diff --git a/continuum-api/src/main/java/org/apache/continuum/configuration/GeneralConfiguration.java b/continuum-api/src/main/java/org/apache/continuum/configuration/GeneralConfiguration.java
index 6360f16..15e8f78 100644
--- a/continuum-api/src/main/java/org/apache/continuum/configuration/GeneralConfiguration.java
+++ b/continuum-api/src/main/java/org/apache/continuum/configuration/GeneralConfiguration.java
@@ -31,6 +31,8 @@
  */
 public class GeneralConfiguration
 {
+    private boolean initialized = false;
+
     private File workingDirectory;
 
     private File buildOutputDirectory;
@@ -40,11 +42,19 @@
     private String baseUrl;
 
     private ProxyConfiguration proxyConfiguration;
-    
+
     private File releaseOutputDirectory;
 
+    private int numberOfBuildsInParallel = 1;
+
     private List<BuildAgentConfiguration> buildAgents;
 
+    private List<BuildAgentGroupConfiguration> buildAgentGroups;
+
+    private boolean distributedBuildEnabled;
+
+    private String sharedSecretPassword;
+
     public GeneralConfiguration()
     {
         // nothing here
@@ -110,12 +120,22 @@
     {
         return releaseOutputDirectory;
     }
-    
+
     public void setReleaseOutputDirectory( File releaseOutputDirectory )
     {
         this.releaseOutputDirectory = releaseOutputDirectory;
     }
 
+    public int getNumberOfBuildsInParallel()
+    {
+        return numberOfBuildsInParallel;
+    }
+
+    public void setNumberOfBuildsInParallel( int numberOfBuildsInParallel )
+    {
+        this.numberOfBuildsInParallel = numberOfBuildsInParallel;
+    }
+
     public List<BuildAgentConfiguration> getBuildAgents()
     {
         return buildAgents;
@@ -125,4 +145,44 @@
     {
         this.buildAgents = buildAgents;
     }
+
+    public List<BuildAgentGroupConfiguration> getBuildAgentGroups()
+    {
+        return buildAgentGroups;
+    }
+
+    public void setBuildAgentGroups( List<BuildAgentGroupConfiguration> buildAgentGroups )
+    {
+        this.buildAgentGroups = buildAgentGroups;
+    }
+
+    public boolean isDistributedBuildEnabled()
+    {
+        return distributedBuildEnabled;
+    }
+
+    public void setDistributedBuildEnabled( boolean distributedBuildEnabled )
+    {
+        this.distributedBuildEnabled = distributedBuildEnabled;
+    }
+
+    public void setSharedSecretPassword( String sharedSecretPassword )
+    {
+        this.sharedSecretPassword = sharedSecretPassword;
+    }
+
+    public String getSharedSecretPassword()
+    {
+        return sharedSecretPassword;
+    }
+
+    public boolean isInitialized()
+    {
+        return initialized;
+    }
+
+    public void setInitialized( boolean initialized )
+    {
+        this.initialized = initialized;
+    }
 }
diff --git a/continuum-api/src/main/java/org/apache/continuum/configuration/ProxyConfiguration.java b/continuum-api/src/main/java/org/apache/continuum/configuration/ProxyConfiguration.java
index fe89fae..64ef5b5 100644
--- a/continuum-api/src/main/java/org/apache/continuum/configuration/ProxyConfiguration.java
+++ b/continuum-api/src/main/java/org/apache/continuum/configuration/ProxyConfiguration.java
@@ -20,7 +20,6 @@
  */
 
 
-
 import org.apache.commons.lang.builder.ReflectionToStringBuilder;
 
 /**
@@ -37,12 +36,12 @@
     private String proxyUser;
 
     private String proxyPassword;
-    
+
     public ProxyConfiguration()
     {
         // nothing here
     }
-    
+
     public ProxyConfiguration( String proxyHost, String proxyPassword, int proxyPort, String proxyUser )
     {
         super();
diff --git a/continuum-api/src/main/java/org/apache/continuum/dao/BuildDefinitionDao.java b/continuum-api/src/main/java/org/apache/continuum/dao/BuildDefinitionDao.java
index eac21c5..091b228 100644
--- a/continuum-api/src/main/java/org/apache/continuum/dao/BuildDefinitionDao.java
+++ b/continuum-api/src/main/java/org/apache/continuum/dao/BuildDefinitionDao.java
@@ -48,7 +48,13 @@
     List<BuildDefinition> getAllBuildDefinitions()
         throws ContinuumStoreException;
 
-    Map getDefaultBuildDefinitions();
+    /**
+     * Returns the default build definition of all projects. The key is the project id and the value is the build
+     * definition id.
+     *
+     * @return a map of all default build definitions
+     */
+    Map<Integer, Integer> getDefaultBuildDefinitions();
 
     /**
      * returns the default build definitions for the project group and there
diff --git a/continuum-api/src/main/java/org/apache/continuum/dao/BuildQueueDao.java b/continuum-api/src/main/java/org/apache/continuum/dao/BuildQueueDao.java
new file mode 100644
index 0000000..c3cc5fd
--- /dev/null
+++ b/continuum-api/src/main/java/org/apache/continuum/dao/BuildQueueDao.java
@@ -0,0 +1,49 @@
+package org.apache.continuum.dao;
+
+/*
+ * 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 org.apache.maven.continuum.model.project.BuildQueue;
+import org.apache.maven.continuum.store.ContinuumStoreException;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ */
+public interface BuildQueueDao
+{
+    BuildQueue addBuildQueue( BuildQueue buildQueue )
+        throws ContinuumStoreException;
+
+    BuildQueue getBuildQueue( int buildQueueId )
+        throws ContinuumStoreException;
+
+    BuildQueue getBuildQueueByName( String buildQueueName )
+        throws ContinuumStoreException;
+
+    void removeBuildQueue( BuildQueue buildQueue )
+        throws ContinuumStoreException;
+
+    BuildQueue storeBuildQueue( BuildQueue buildQueue )
+        throws ContinuumStoreException;
+
+    List<BuildQueue> getAllBuildQueues()
+        throws ContinuumStoreException;
+}
diff --git a/continuum-api/src/main/java/org/apache/continuum/dao/BuildResultDao.java b/continuum-api/src/main/java/org/apache/continuum/dao/BuildResultDao.java
index 50da030..66ead13 100644
--- a/continuum-api/src/main/java/org/apache/continuum/dao/BuildResultDao.java
+++ b/continuum-api/src/main/java/org/apache/continuum/dao/BuildResultDao.java
@@ -23,6 +23,7 @@
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.store.ContinuumStoreException;
 
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
 
@@ -45,30 +46,52 @@
 
     BuildResult getLatestBuildResultForProject( int projectId );
 
+    BuildResult getLatestBuildResultForProjectWithDetails( int projectId );
+
     BuildResult getLatestBuildResultForBuildDefinition( int projectId, int buildDefinitionId );
 
-    List<BuildResult> getBuildResultsInSuccessForProject( int projectId, long fromDate );
+    BuildResult getLatestBuildResultInSuccess( int projectId );
+
+    BuildResult getPreviousBuildResultInSuccess( int projectId, int buildResultId )
+        throws ContinuumStoreException;
 
     long getNbBuildResultsForProject( int projectId );
 
+    /**
+     * Returns the list of build results between the fromdate and the buildResult defined by its toBuildResultId
+     *
+     * @param projectId       The project id
+     * @param fromDate        the from date
+     * @param tobuildResultId the build result id
+     * @return the list of build results
+     */
+    List<BuildResult> getBuildResultsForProjectWithDetails( int projectId, long fromDate, int tobuildResultId );
+
+    /**
+     * Returns the number of build results in success since fromDate
+     *
+     * @param projectId The project id
+     * @param fromDate  The from date
+     * @return the number of build results
+     */
+    long getNbBuildResultsInSuccessForProject( int projectId, long fromDate );
+
     List<BuildResult> getBuildResultsForProject( int projectId );
 
     List<BuildResult> getBuildResultsForProject( int projectId, long startIndex, long endIndex );
 
     /**
-     * @since 1.2
      * @param projectId
-     * @param startIndex
+     * @param startId
      * @return the returned list will contains all BuildResult for this project after the startId
+     * @since 1.2
      */
     List<BuildResult> getBuildResultsForProjectFromId( int projectId, long startId )
-        throws ContinuumStoreException;   
-    
-    List<BuildResult> getBuildResultsForProject( int projectId, long fromDate );
+        throws ContinuumStoreException;
 
     Map<Integer, BuildResult> getLatestBuildResultsByProjectGroupId( int projectGroupId );
 
-    Map<Integer, BuildResult> getLatestBuildResults();
+    Map<Integer, BuildResult> getBuildResultsInSuccessByProjectGroupId( int projectGroupId );
 
     List<BuildResult> getBuildResultByBuildNumber( int projectId, int buildNumber );
 
@@ -77,9 +100,8 @@
     List<BuildResult> getBuildResultsByBuildDefinition( int projectId, int buildDefinitionId, long startIndex,
                                                         long endIndex );
 
-    Map<Integer, BuildResult> getBuildResultsInSuccess();
-
-    Map<Integer, BuildResult> getBuildResultsInSuccessByProjectGroupId( int projectGroupId );
-
     List<BuildResult> getAllBuildsForAProjectByDate( int projectId );
+
+    List<BuildResult> getBuildResultsInRange( Date fromDate, Date toDate, int state, String triggeredBy,
+                                              int projectGroupId );
 }
diff --git a/continuum-api/src/main/java/org/apache/continuum/dao/ContinuumReleaseResultDao.java b/continuum-api/src/main/java/org/apache/continuum/dao/ContinuumReleaseResultDao.java
index ecfeede..354c835 100644
--- a/continuum-api/src/main/java/org/apache/continuum/dao/ContinuumReleaseResultDao.java
+++ b/continuum-api/src/main/java/org/apache/continuum/dao/ContinuumReleaseResultDao.java
@@ -19,12 +19,12 @@
  * under the License.
  */
 
-import java.util.List;
-
 import org.apache.continuum.model.release.ContinuumReleaseResult;
 import org.apache.maven.continuum.store.ContinuumObjectNotFoundException;
 import org.apache.maven.continuum.store.ContinuumStoreException;
 
+import java.util.List;
+
 /**
  * @author <a href="mailto:ctan@apache.org">Maria Catherine Tan</a>
  */
@@ -37,12 +37,12 @@
         throws ContinuumStoreException;
 
     List<ContinuumReleaseResult> getContinuumReleaseResultsByProjectGroup( int projectGroupId );
-    
+
     List<ContinuumReleaseResult> getAllContinuumReleaseResults();
 
     ContinuumReleaseResult getContinuumReleaseResult( int releaseResultId )
         throws ContinuumObjectNotFoundException, ContinuumStoreException;
-    
+
     ContinuumReleaseResult getContinuumReleaseResult( int projectId, String releaseGoal, long startTime, long endTime )
         throws ContinuumStoreException;
 
diff --git a/continuum-api/src/main/java/org/apache/continuum/dao/DaoUtils.java b/continuum-api/src/main/java/org/apache/continuum/dao/DaoUtils.java
index 5aa9072..bec0bfb 100644
--- a/continuum-api/src/main/java/org/apache/continuum/dao/DaoUtils.java
+++ b/continuum-api/src/main/java/org/apache/continuum/dao/DaoUtils.java
@@ -21,7 +21,6 @@
 
 import org.apache.maven.continuum.store.ContinuumStoreException;
 
-import javax.jdo.PersistenceManagerFactory;
 import java.util.Map;
 
 /**
@@ -34,12 +33,12 @@
 
     void eraseDatabase();
 
-    Map getProjectIdsAndBuildDefinitionsIdsBySchedule( int scheduleId )
+    Map<Integer, Object> getProjectIdsAndBuildDefinitionsIdsBySchedule( int scheduleId )
         throws ContinuumStoreException;
 
-    Map getProjectGroupIdsAndBuildDefinitionsIdsBySchedule( int scheduleId )
+    Map<Integer, Object> getProjectGroupIdsAndBuildDefinitionsIdsBySchedule( int scheduleId )
         throws ContinuumStoreException;
 
-    Map getAggregatedProjectIdsAndBuildDefinitionIdsBySchedule( int scheduleId )
+    Map<Integer, Object> getAggregatedProjectIdsAndBuildDefinitionIdsBySchedule( int scheduleId )
         throws ContinuumStoreException;
 }
diff --git a/continuum-api/src/main/java/org/apache/continuum/dao/DirectoryPurgeConfigurationDao.java b/continuum-api/src/main/java/org/apache/continuum/dao/DirectoryPurgeConfigurationDao.java
index 609d1a9..20875ee 100644
--- a/continuum-api/src/main/java/org/apache/continuum/dao/DirectoryPurgeConfigurationDao.java
+++ b/continuum-api/src/main/java/org/apache/continuum/dao/DirectoryPurgeConfigurationDao.java
@@ -34,6 +34,8 @@
 
     List<DirectoryPurgeConfiguration> getDirectoryPurgeConfigurationsBySchedule( int scheduleId );
 
+    List<DirectoryPurgeConfiguration> getEnableDirectoryPurgeConfigurationsBySchedule( int scheduleId );
+
     List<DirectoryPurgeConfiguration> getDirectoryPurgeConfigurationsByLocation( String location );
 
     List<DirectoryPurgeConfiguration> getDirectoryPurgeConfigurationsByType( String type );
diff --git a/continuum-api/src/main/java/org/apache/continuum/dao/DistributedDirectoryPurgeConfigurationDao.java b/continuum-api/src/main/java/org/apache/continuum/dao/DistributedDirectoryPurgeConfigurationDao.java
new file mode 100644
index 0000000..af290a9
--- /dev/null
+++ b/continuum-api/src/main/java/org/apache/continuum/dao/DistributedDirectoryPurgeConfigurationDao.java
@@ -0,0 +1,103 @@
+package org.apache.continuum.dao;
+
+/*
+ * 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 org.apache.continuum.model.repository.DistributedDirectoryPurgeConfiguration;
+import org.apache.maven.continuum.store.ContinuumStoreException;
+
+import java.util.List;
+
+/**
+ * @author
+ * @version $Id$
+ */
+public interface DistributedDirectoryPurgeConfigurationDao
+{
+    /**
+     * Retrieve all DistributedDirectoryPurgeConfiguration instances.
+     *
+     * @return list of all DistributedDirectoryPurgeConfiguration instances
+     */
+    List<DistributedDirectoryPurgeConfiguration> getAllDistributedDirectoryPurgeConfigurations();
+
+    /**
+     * Retrieve all DistributedDirectoryPurgeConfiguration instances associated with the input scheduleId.
+     *
+     * @param scheduleId schedule id
+     * @return list of all DistributedDirectoryPurgeConfiguration instances associated with the input scheduleId
+     */
+    List<DistributedDirectoryPurgeConfiguration> getDistributedDirectoryPurgeConfigurationsBySchedule( int scheduleId );
+
+    /**
+     * Retrieve all enabled DistributedDirectoryPurgeConfiguration instances associated with the input scheduleId.
+     *
+     * @param scheduleId schedule id
+     * @return list of all enabled DistributedDirectoryPurgeConfiguration instances associated with the input scheduleId
+     */
+    List<DistributedDirectoryPurgeConfiguration> getEnableDistributedDirectoryPurgeConfigurationsBySchedule(
+        int scheduleId );
+
+    /**
+     * Retrieve all DistributedDirectoryPurgeConfiguration instances having the specified directory type.
+     *
+     * @param type directory type
+     * @return list of all DistributedDirectoryPurgeConfiguration instances having the specified directory type
+     */
+    List<DistributedDirectoryPurgeConfiguration> getDistributedDirectoryPurgeConfigurationsByType( String type );
+
+    /**
+     * Retrieve the DistributedDirectoryPurgeConfiguration instance associated with the input id.
+     *
+     * @param configurationId DistributedDirectoryPurgeConfiguration instance id
+     * @return DistributedDirectoryPurgeConfiguration instance
+     * @throws ContinuumStoreException if unable to retrieve an instance associated with the input id
+     */
+    DistributedDirectoryPurgeConfiguration getDistributedDirectoryPurgeConfiguration( int configurationId )
+        throws ContinuumStoreException;
+
+    /**
+     * Adds a new DistributedDirectoryPurgeConfiguration instance.
+     *
+     * @param purgeConfiguration DistributedDirectoryPurgeConfiguration instance to be added
+     * @return DistributedDirectoryPurgeConfiguration instance that was added
+     * @throws ContinuumStoreException if unable to add the new instance
+     */
+    DistributedDirectoryPurgeConfiguration addDistributedDirectoryPurgeConfiguration(
+        DistributedDirectoryPurgeConfiguration purgeConfiguration )
+        throws ContinuumStoreException;
+
+    /**
+     * Updates the DistributedDirectoryPurgeConfiguration instance.
+     *
+     * @param purgeConfiguration DistributedDirectoryPurgeConfiguration instance to be updated
+     * @throws ContinuumStoreException if unable to update the instance
+     */
+    void updateDistributedDirectoryPurgeConfiguration( DistributedDirectoryPurgeConfiguration purgeConfiguration )
+        throws ContinuumStoreException;
+
+    /**
+     * Removes the DistributedDirectoryPurgeConfiguration instance.
+     *
+     * @param purgeConfiguration DistributedDirectoryPurgeConfiguration instance to be removed
+     * @throws ContinuumStoreException if unable to remove the instance
+     */
+    void removeDistributedDirectoryPurgeConfiguration( DistributedDirectoryPurgeConfiguration purgeConfiguration )
+        throws ContinuumStoreException;
+}
diff --git a/continuum-api/src/main/java/org/apache/continuum/dao/InstallationDao.java b/continuum-api/src/main/java/org/apache/continuum/dao/InstallationDao.java
index 09f195d..68f0a44 100644
--- a/continuum-api/src/main/java/org/apache/continuum/dao/InstallationDao.java
+++ b/continuum-api/src/main/java/org/apache/continuum/dao/InstallationDao.java
@@ -45,4 +45,6 @@
     Installation getInstallation( int installationId )
         throws ContinuumStoreException;
 
+    Installation getInstallation( String installationName )
+        throws ContinuumStoreException;
 }
diff --git a/continuum-api/src/main/java/org/apache/continuum/dao/ProjectDao.java b/continuum-api/src/main/java/org/apache/continuum/dao/ProjectDao.java
index 3eb250a..af16504 100644
--- a/continuum-api/src/main/java/org/apache/continuum/dao/ProjectDao.java
+++ b/continuum-api/src/main/java/org/apache/continuum/dao/ProjectDao.java
@@ -19,12 +19,14 @@
  * under the License.
  */
 
+import org.apache.continuum.model.project.ProjectGroupSummary;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.project.ProjectGroup;
 import org.apache.maven.continuum.store.ContinuumObjectNotFoundException;
 import org.apache.maven.continuum.store.ContinuumStoreException;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
@@ -57,17 +59,12 @@
     Project getProjectWithCheckoutResult( int projectId )
         throws ContinuumStoreException;
 
-    Project getProjectWithScmDetails( int projectId )
-        throws ContinuumStoreException;
-
     List<Project> getProjectsInGroup( int projectGroupId )
         throws ContinuumStoreException;
 
     List<Project> getProjectsInGroupWithDependencies( int projectGroupId )
         throws ContinuumStoreException;
 
-    List<Project> getAllProjectsWithAllDetails();
-
     Project getProjectWithAllDetails( int projectId )
         throws ContinuumStoreException;
 
@@ -82,4 +79,6 @@
 
     Project getProjectWithDependencies( int projectId )
         throws ContinuumStoreException;
+
+    Map<Integer, ProjectGroupSummary> getProjectsSummary();
 }
diff --git a/continuum-api/src/main/java/org/apache/continuum/dao/ProjectGroupDao.java b/continuum-api/src/main/java/org/apache/continuum/dao/ProjectGroupDao.java
index 6a95366..6e3573c 100644
--- a/continuum-api/src/main/java/org/apache/continuum/dao/ProjectGroupDao.java
+++ b/continuum-api/src/main/java/org/apache/continuum/dao/ProjectGroupDao.java
@@ -19,10 +19,10 @@
  * under the License.
  */
 
-import org.apache.maven.continuum.model.project.ProjectGroup;
 import org.apache.maven.continuum.model.project.Project;
-import org.apache.maven.continuum.store.ContinuumStoreException;
+import org.apache.maven.continuum.model.project.ProjectGroup;
 import org.apache.maven.continuum.store.ContinuumObjectNotFoundException;
+import org.apache.maven.continuum.store.ContinuumStoreException;
 
 import java.util.Collection;
 import java.util.List;
@@ -53,7 +53,8 @@
      *
      * @param projectGroupId The project group id
      * @return The project group
-     * @throws org.apache.maven.continuum.store.ContinuumStoreException if the project group can't be obtain
+     * @throws org.apache.maven.continuum.store.ContinuumStoreException
+     *          if the project group can't be obtain
      */
     ProjectGroup getProjectGroup( int projectGroupId )
         throws ContinuumStoreException, ContinuumObjectNotFoundException;
diff --git a/continuum-api/src/main/java/org/apache/continuum/dao/ProjectScmRootDao.java b/continuum-api/src/main/java/org/apache/continuum/dao/ProjectScmRootDao.java
index 35db5f0..23afa3d 100644
--- a/continuum-api/src/main/java/org/apache/continuum/dao/ProjectScmRootDao.java
+++ b/continuum-api/src/main/java/org/apache/continuum/dao/ProjectScmRootDao.java
@@ -19,12 +19,12 @@
  * under the License.
  */
 
-import java.util.List;
-
 import org.apache.continuum.model.project.ProjectScmRoot;
 import org.apache.maven.continuum.store.ContinuumObjectNotFoundException;
 import org.apache.maven.continuum.store.ContinuumStoreException;
 
+import java.util.List;
+
 /**
  * @author <a href="mailto:ctan@apache.org">Maria Catherine Tan</a>
  */
@@ -45,7 +45,7 @@
 
     ProjectScmRoot getProjectScmRoot( int projectScmRootId )
         throws ContinuumObjectNotFoundException, ContinuumStoreException;
-    
+
     ProjectScmRoot getProjectScmRootByProjectGroupAndScmRootAddress( int projectGroupId, String scmRootAddress )
         throws ContinuumStoreException;
 }
diff --git a/continuum-api/src/main/java/org/apache/continuum/dao/RepositoryPurgeConfigurationDao.java b/continuum-api/src/main/java/org/apache/continuum/dao/RepositoryPurgeConfigurationDao.java
index dbb3c86..37421d6 100644
--- a/continuum-api/src/main/java/org/apache/continuum/dao/RepositoryPurgeConfigurationDao.java
+++ b/continuum-api/src/main/java/org/apache/continuum/dao/RepositoryPurgeConfigurationDao.java
@@ -34,6 +34,8 @@
 
     List<RepositoryPurgeConfiguration> getRepositoryPurgeConfigurationsBySchedule( int scheduleId );
 
+    List<RepositoryPurgeConfiguration> getEnableRepositoryPurgeConfigurationsBySchedule( int scheduleId );
+
     List<RepositoryPurgeConfiguration> getRepositoryPurgeConfigurationsByLocalRepository( int repositoryId );
 
     RepositoryPurgeConfiguration getRepositoryPurgeConfiguration( int configurationId )
diff --git a/continuum-api/src/main/java/org/apache/continuum/purge/ContinuumPurgeManager.java b/continuum-api/src/main/java/org/apache/continuum/purge/ContinuumPurgeManager.java
index 0158c2b..d217762 100644
--- a/continuum-api/src/main/java/org/apache/continuum/purge/ContinuumPurgeManager.java
+++ b/continuum-api/src/main/java/org/apache/continuum/purge/ContinuumPurgeManager.java
@@ -20,6 +20,7 @@
  */
 
 import org.apache.continuum.model.repository.DirectoryPurgeConfiguration;
+import org.apache.continuum.model.repository.DistributedDirectoryPurgeConfiguration;
 import org.apache.continuum.model.repository.RepositoryPurgeConfiguration;
 import org.apache.maven.continuum.model.project.Schedule;
 
@@ -29,30 +30,42 @@
  * @since 25 jul 07
  */
 public interface ContinuumPurgeManager
-{   
+{
     String ROLE = ContinuumPurgeManager.class.getName();
-    
+
     /**
-     * Purge repositories and directories 
+     * Purge repositories and directories
+     *
      * @param schedule
      * @throws ContinuumPurgeManagerException
      */
     void purge( Schedule schedule )
         throws ContinuumPurgeManagerException;
-    
+
     /**
      * Purge repository
+     *
      * @param repoPurgeConfig
      * @throws ContinuumPurgeManagerException
      */
     void purgeRepository( RepositoryPurgeConfiguration repoPurgeConfig )
         throws ContinuumPurgeManagerException;
-    
+
     /**
-     * Purge directory 
+     * Purge directory
+     *
      * @param dirPurgeConfig
      * @throws ContinuumPurgeManagerException
      */
     void purgeDirectory( DirectoryPurgeConfiguration dirPurgeConfig )
         throws ContinuumPurgeManagerException;
+
+    /**
+     * Purge directory in distributed build mode
+     *
+     * @param dirPurgeConfig distributed purge configuration
+     * @throws ContinuumPurgeManagerException
+     */
+    void purgeDistributedDirectory( DistributedDirectoryPurgeConfiguration dirPurgeConfig )
+        throws ContinuumPurgeManagerException;
 }
diff --git a/continuum-api/src/main/java/org/apache/continuum/purge/ContinuumPurgeManagerException.java b/continuum-api/src/main/java/org/apache/continuum/purge/ContinuumPurgeManagerException.java
index b39983e..ae7c6d0 100644
--- a/continuum-api/src/main/java/org/apache/continuum/purge/ContinuumPurgeManagerException.java
+++ b/continuum-api/src/main/java/org/apache/continuum/purge/ContinuumPurgeManagerException.java
@@ -31,12 +31,12 @@
     {
         super( message );
     }
-    
+
     public ContinuumPurgeManagerException( Throwable cause )
     {
         super( cause );
     }
-    
+
     public ContinuumPurgeManagerException( String message, Throwable cause )
     {
         super( message, cause );
diff --git a/continuum-api/src/main/java/org/apache/continuum/purge/PurgeConfigurationService.java b/continuum-api/src/main/java/org/apache/continuum/purge/PurgeConfigurationService.java
index 834e7d7..f85b39f 100644
--- a/continuum-api/src/main/java/org/apache/continuum/purge/PurgeConfigurationService.java
+++ b/continuum-api/src/main/java/org/apache/continuum/purge/PurgeConfigurationService.java
@@ -19,13 +19,14 @@
  * under the License.
  */
 
-import java.util.List;
-
 import org.apache.continuum.model.repository.AbstractPurgeConfiguration;
 import org.apache.continuum.model.repository.DirectoryPurgeConfiguration;
+import org.apache.continuum.model.repository.DistributedDirectoryPurgeConfiguration;
 import org.apache.continuum.model.repository.RepositoryPurgeConfiguration;
 import org.apache.continuum.purge.repository.content.RepositoryManagedContent;
 
+import java.util.List;
+
 /**
  * @author Maria Catherine Tan
  * @version $Id$
@@ -34,65 +35,88 @@
 public interface PurgeConfigurationService
 {
     String ROLE = PurgeConfigurationService.class.getName();
-    
+
     AbstractPurgeConfiguration addPurgeConfiguration( AbstractPurgeConfiguration purgeConfig )
         throws PurgeConfigurationServiceException;
-    
+
     void updatePurgeConfiguration( AbstractPurgeConfiguration purgeConfig )
         throws PurgeConfigurationServiceException;
 
     void removePurgeConfiguration( int purgeConfigId )
         throws PurgeConfigurationServiceException;
-    
+
     RepositoryPurgeConfiguration addRepositoryPurgeConfiguration( RepositoryPurgeConfiguration repoPurge )
         throws PurgeConfigurationServiceException;
-    
+
     void updateRepositoryPurgeConfiguration( RepositoryPurgeConfiguration repoPurge )
         throws PurgeConfigurationServiceException;
-    
+
     void removeRepositoryPurgeConfiguration( RepositoryPurgeConfiguration repoPurge )
         throws PurgeConfigurationServiceException;
-    
+
     RepositoryPurgeConfiguration getRepositoryPurgeConfiguration( int repoPurgeId )
         throws PurgeConfigurationServiceException;
-    
+
     RepositoryPurgeConfiguration getDefaultPurgeConfigurationForRepository( int repositoryId );
-    
+
     List<RepositoryPurgeConfiguration> getRepositoryPurgeConfigurationsBySchedule( int scheduleId );
-    
+
+    List<RepositoryPurgeConfiguration> getEnableRepositoryPurgeConfigurationsBySchedule( int scheduleId );
+
     List<RepositoryPurgeConfiguration> getRepositoryPurgeConfigurationsByRepository( int repositoryId );
-    
+
     List<RepositoryPurgeConfiguration> getAllRepositoryPurgeConfigurations();
-    
+
     DirectoryPurgeConfiguration addDirectoryPurgeConfiguration( DirectoryPurgeConfiguration dirPurge )
         throws PurgeConfigurationServiceException;
-    
+
     void updateDirectoryPurgeConfiguration( DirectoryPurgeConfiguration dirPurge )
         throws PurgeConfigurationServiceException;
-    
+
     void removeDirectoryPurgeConfiguration( DirectoryPurgeConfiguration dirPurge )
         throws PurgeConfigurationServiceException;
-    
+
     DirectoryPurgeConfiguration getDirectoryPurgeConfiguration( int dirPurgeId )
         throws PurgeConfigurationServiceException;
-    
+
     DirectoryPurgeConfiguration getDefaultPurgeConfigurationForDirectoryType( String directoryType );
-    
+
     List<DirectoryPurgeConfiguration> getDirectoryPurgeConfigurationsBySchedule( int scheduleId );
-    
+
+    List<DirectoryPurgeConfiguration> getEnableDirectoryPurgeConfigurationsBySchedule( int scheduleId );
+
     List<DirectoryPurgeConfiguration> getDirectoryPurgeConfigurationsByLocation( String location );
-    
+
     List<DirectoryPurgeConfiguration> getAllDirectoryPurgeConfigurations();
-    
+
     List<AbstractPurgeConfiguration> getAllPurgeConfigurations();
-    
+
+    List<DistributedDirectoryPurgeConfiguration> getAllDistributedDirectoryPurgeConfigurations();
+
+    DistributedDirectoryPurgeConfiguration getDistributedDirectoryPurgeConfiguration( int dirPurgeId )
+        throws PurgeConfigurationServiceException;
+
+    DistributedDirectoryPurgeConfiguration addDistributedDirectoryPurgeConfiguration(
+        DistributedDirectoryPurgeConfiguration dirPurge )
+        throws PurgeConfigurationServiceException;
+
+    void updateDistributedDirectoryPurgeConfiguration( DistributedDirectoryPurgeConfiguration dirPurge )
+        throws PurgeConfigurationServiceException;
+
+    void removeDistributedDirectoryPurgeConfiguration( DistributedDirectoryPurgeConfiguration dirPurge )
+        throws PurgeConfigurationServiceException;
+
     AbstractPurgeConfiguration getPurgeConfiguration( int purgeConfigId );
-    
+
+    List<DistributedDirectoryPurgeConfiguration> getEnableDistributedDirectoryPurgeConfigurationsBySchedule(
+        int scheduleId );
+
     /**
      * @param repositoryId
      * @return
      * @throws PurgeConfigurationServiceException
+     *
      */
-    RepositoryManagedContent getManagedRepositoryContent( int repositoryId)
+    RepositoryManagedContent getManagedRepositoryContent( int repositoryId )
         throws PurgeConfigurationServiceException;
 }
diff --git a/continuum-api/src/main/java/org/apache/continuum/purge/PurgeConfigurationServiceException.java b/continuum-api/src/main/java/org/apache/continuum/purge/PurgeConfigurationServiceException.java
index 3e18efe..bc5e4f8 100644
--- a/continuum-api/src/main/java/org/apache/continuum/purge/PurgeConfigurationServiceException.java
+++ b/continuum-api/src/main/java/org/apache/continuum/purge/PurgeConfigurationServiceException.java
@@ -31,12 +31,12 @@
     {
         super( message );
     }
-    
+
     public PurgeConfigurationServiceException( Throwable cause )
     {
         super( cause );
     }
-    
+
     public PurgeConfigurationServiceException( String message, Throwable cause )
     {
         super( message, cause );
diff --git a/continuum-api/src/main/java/org/apache/continuum/purge/controller/PurgeController.java b/continuum-api/src/main/java/org/apache/continuum/purge/controller/PurgeController.java
index b28edf7..caa291e 100644
--- a/continuum-api/src/main/java/org/apache/continuum/purge/controller/PurgeController.java
+++ b/continuum-api/src/main/java/org/apache/continuum/purge/controller/PurgeController.java
@@ -30,9 +30,11 @@
 public interface PurgeController
 {
     String ROLE = PurgeController.class.getName();
-    
+
     void initializeExecutors( AbstractPurgeConfiguration purgeConfig )
         throws ContinuumPurgeExecutorException;
-    
+
+    void doPurge( AbstractPurgeConfiguration purgeConfig );
+
     void doPurge( String path );
 }
diff --git a/continuum-api/src/main/java/org/apache/continuum/purge/executor/ContinuumPurgeExecutor.java b/continuum-api/src/main/java/org/apache/continuum/purge/executor/ContinuumPurgeExecutor.java
index 4250897..dc81f08 100644
--- a/continuum-api/src/main/java/org/apache/continuum/purge/executor/ContinuumPurgeExecutor.java
+++ b/continuum-api/src/main/java/org/apache/continuum/purge/executor/ContinuumPurgeExecutor.java
@@ -1,6 +1,5 @@
 package org.apache.continuum.purge.executor;
 
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -28,7 +27,7 @@
 public interface ContinuumPurgeExecutor
 {
     String ROLE = ContinuumPurgeExecutor.class.getName();
-    
+
     void purge( String path )
         throws ContinuumPurgeExecutorException;
 }
\ No newline at end of file
diff --git a/continuum-api/src/main/java/org/apache/continuum/purge/executor/ContinuumPurgeExecutorException.java b/continuum-api/src/main/java/org/apache/continuum/purge/executor/ContinuumPurgeExecutorException.java
index b89c83d..cfed9f5 100644
--- a/continuum-api/src/main/java/org/apache/continuum/purge/executor/ContinuumPurgeExecutorException.java
+++ b/continuum-api/src/main/java/org/apache/continuum/purge/executor/ContinuumPurgeExecutorException.java
@@ -31,12 +31,12 @@
     {
         super( message );
     }
-    
+
     public ContinuumPurgeExecutorException( Throwable cause )
     {
         super( cause );
     }
-    
+
     public ContinuumPurgeExecutorException( String message, Throwable cause )
     {
         super( message, cause );
diff --git a/continuum-api/src/main/java/org/apache/continuum/purge/repository/content/RepositoryManagedContent.java b/continuum-api/src/main/java/org/apache/continuum/purge/repository/content/RepositoryManagedContent.java
index 1c6a070..57d103d 100644
--- a/continuum-api/src/main/java/org/apache/continuum/purge/repository/content/RepositoryManagedContent.java
+++ b/continuum-api/src/main/java/org/apache/continuum/purge/repository/content/RepositoryManagedContent.java
@@ -19,9 +19,6 @@
  * under the License.
  */
 
-import java.io.File;
-import java.util.Set;
-
 import org.apache.continuum.model.repository.LocalRepository;
 import org.apache.maven.archiva.model.ArtifactReference;
 import org.apache.maven.archiva.model.ProjectReference;
@@ -29,8 +26,12 @@
 import org.apache.maven.archiva.repository.ContentNotFoundException;
 import org.apache.maven.archiva.repository.layout.LayoutException;
 
+import java.io.File;
+import java.util.Set;
+
 /**
  * Taken from Archiva's ManagedRepositoryContent interface and made some few changes.
+ *
  * @author Maria Catherine Tan
  * @version $Id$
  * @since 25 jul 07
@@ -40,41 +41,41 @@
     /**
      * Delete from the local repository all files / directories associated with the
      * provided version reference.
-     * 
+     *
      * @param reference the version reference to delete.
-     * @throws ContentNotFoundException 
+     * @throws ContentNotFoundException
      */
     public void deleteVersion( VersionedReference reference )
         throws ContentNotFoundException;
-    
+
     /**
      * <p>
      * Convenience method to get the repository id.
      * </p>
-     * 
+     *
      * <p>
      * Equivalent to calling <code>.getRepository().getId()</code>
      * </p>
-     * 
+     *
      * @return the repository id.
      */
     public int getId();
-    
+
     /**
      * <p>
      * Gather up the list of related artifacts to the ArtifactReference provided.
-     * This typically inclues the pom files, and those things with 
+     * This typically inclues the pom files, and those things with
      * classifiers (such as doc, source code, test libs, etc...)
      * </p>
-     * 
+     *
      * <p>
      * <strong>NOTE:</strong> Some layouts (such as maven 1 "legacy") are not compatible with this query.
-     * </p> 
-     * 
+     * </p>
+     *
      * @param reference the reference to work off of.
      * @return the set of ArtifactReferences for related artifacts.
      * @throws ContentNotFoundException if the initial artifact reference does not exist within the repository.
-     * @throws LayoutException 
+     * @throws LayoutException
      */
     public Set<ArtifactReference> getRelatedArtifacts( ArtifactReference reference )
         throws ContentNotFoundException, LayoutException;
@@ -83,11 +84,11 @@
      * <p>
      * Convenience method to get the repository (on disk) root directory.
      * </p>
-     * 
+     *
      * <p>
      * Equivalent to calling <code>.getLocalRepository().getDirectory()</code>
      * </p>
-     * 
+     *
      * @return the repository (on disk) root directory.
      */
     public String getRepoRoot();
@@ -95,7 +96,7 @@
     /**
      * Get the local repository associated with this
      * repository content.
-     * 
+     *
      * @return the local repository that is associated with this repository content.
      */
     public LocalRepository getRepository();
@@ -103,11 +104,11 @@
     /**
      * Given a specific {@link ProjectReference}, return the list of available versions for
      * that project reference.
-     * 
+     *
      * @param reference the project reference to work off of.
      * @return the list of versions found for that project reference.
      * @throws ContentNotFoundException if the project reference does not exist within the repository.
-     * @throws LayoutException 
+     * @throws LayoutException
      */
     public Set<String> getVersions( ProjectReference reference )
         throws ContentNotFoundException, LayoutException;
@@ -117,23 +118,23 @@
      * Given a specific {@link VersionedReference}, return the list of available versions for that
      * versioned reference.
      * </p>
-     * 
+     *
      * <p>
      * <strong>NOTE:</strong> This is really only useful when working with SNAPSHOTs.
      * </p>
-     * 
+     *
      * @param reference the versioned reference to work off of.
      * @return the set of versions found.
      * @throws ContentNotFoundException if the versioned reference does not exist within the repository.
-     * @throws LayoutException 
+     * @throws LayoutException
      */
     public Set<String> getVersions( VersionedReference reference )
         throws ContentNotFoundException, LayoutException;
-    
+
     /**
      * Set the local repository to associate with this
      * repository content.
-     * 
+     *
      * @param repo the repository to associate with this repository content.
      */
     public void setRepository( LocalRepository repo );
@@ -159,8 +160,8 @@
 
     /**
      * Given a {@link ProjectReference}, return the path to the metadata for
-     * the project. 
-     * 
+     * the project.
+     *
      * @param reference the reference to use.
      * @return the path to the metadata file, or null if no metadata is appropriate.
      */
@@ -168,8 +169,8 @@
 
     /**
      * Given a {@link VersionedReference}, return the path to the metadata for
-     * the specific version of the project. 
-     * 
+     * the specific version of the project.
+     *
      * @param reference the reference to use.
      * @return the path to the metadata file, or null if no metadata is appropriate.
      */
diff --git a/continuum-api/src/main/java/org/apache/continuum/purge/repository/scanner/RepositoryScanner.java b/continuum-api/src/main/java/org/apache/continuum/purge/repository/scanner/RepositoryScanner.java
index 9512c09..13fc385 100644
--- a/continuum-api/src/main/java/org/apache/continuum/purge/repository/scanner/RepositoryScanner.java
+++ b/continuum-api/src/main/java/org/apache/continuum/purge/repository/scanner/RepositoryScanner.java
@@ -19,14 +19,15 @@
  * under the License.
  */
 
-import java.util.List;
-
 import org.apache.continuum.model.repository.LocalRepository;
 import org.apache.continuum.purge.controller.PurgeController;
 import org.apache.continuum.purge.executor.ContinuumPurgeExecutorException;
 
+import java.util.List;
+
 /**
  * Codes were taken from Archiva and made some changes.
+ *
  * @author Maria Catherine Tan
  * @version $Id$
  * @since 25 jul 07
@@ -38,28 +39,14 @@
      * Typical Ignorable Content patterns.
      * </p>
      */
-    public static final String[] IGNORABLE_CONTENT = {
-        "bin/**",
-        "reports/**",
-        ".index",
-        ".reports/**",
-        ".maven/**",
-        "**/.svn/**",
-        "**/*snapshot-version",
-        "*/website/**",
-        "*/licences/**",
-        "**/.htaccess",
-        "**/*.html",
-        "**/*.txt",
-        "**/README*",
-        "**/CHANGELOG*",
-        "**/KEYS*" +
-        "**/*.xml*" };
-    
+    public static final String[] IGNORABLE_CONTENT =
+        {"bin/**", "reports/**", ".index", ".reports/**", ".maven/**", "**/.svn/**", "**/*snapshot-version",
+            "*/website/**", "*/licences/**", "**/.htaccess", "**/*.html", "**/*.txt", "**/README*", "**/CHANGELOG*",
+            "**/KEYS*" + "**/*.xml*"};
+
     public void scan( LocalRepository repository, PurgeController purgeController )
         throws ContinuumPurgeExecutorException;
-    
-    public void scan( LocalRepository repository, PurgeController purgeController,
-                      List<String> ignoredContentPatterns )
+
+    public void scan( LocalRepository repository, PurgeController purgeController, List<String> ignoredContentPatterns )
         throws ContinuumPurgeExecutorException;
 }
\ No newline at end of file
diff --git a/continuum-api/src/main/java/org/apache/continuum/release/distributed/manager/DistributedReleaseManager.java b/continuum-api/src/main/java/org/apache/continuum/release/distributed/manager/DistributedReleaseManager.java
new file mode 100644
index 0000000..927137c
--- /dev/null
+++ b/continuum-api/src/main/java/org/apache/continuum/release/distributed/manager/DistributedReleaseManager.java
@@ -0,0 +1,84 @@
+package org.apache.continuum.release.distributed.manager;
+
+/*
+ * 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 org.apache.continuum.configuration.BuildAgentConfigurationException;
+import org.apache.continuum.model.repository.LocalRepository;
+import org.apache.continuum.release.model.PreparedRelease;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.release.ContinuumReleaseException;
+import org.apache.maven.shared.release.ReleaseResult;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+
+public interface DistributedReleaseManager
+{
+    Map getReleasePluginParameters( int projectId, String pomFilename )
+        throws ContinuumReleaseException, BuildAgentConfigurationException;
+
+    List<Map<String, String>> processProject( int projectId, String pomFilename, boolean autoVersionSubmodules )
+        throws ContinuumReleaseException, BuildAgentConfigurationException;
+
+    String releasePrepare( Project project, Properties releaseProperties, Map<String, String> releaseVersion,
+                           Map<String, String> developmentVersion, Map<String, String> environments, String username )
+        throws ContinuumReleaseException, BuildAgentConfigurationException;
+
+    ReleaseResult getReleaseResult( String releaseId )
+        throws ContinuumReleaseException, BuildAgentConfigurationException;
+
+    Map<String, Object> getListener( String releaseId )
+        throws ContinuumReleaseException, BuildAgentConfigurationException;
+
+    void removeListener( String releaseId )
+        throws ContinuumReleaseException, BuildAgentConfigurationException;
+
+    @Deprecated
+    String getPreparedReleaseName( String releaseId )
+        throws ContinuumReleaseException;
+
+    Map<String, String> getPreparedReleases( String groupId, String artifactId )
+        throws ContinuumReleaseException;
+
+    void releasePerform( int projectId, String releaseId, String goals, String arguments, boolean useReleaseProfile,
+                         LocalRepository repository, String username )
+        throws ContinuumReleaseException, BuildAgentConfigurationException;
+
+    String releasePerformFromScm( int projectId, String goals, String arguments, boolean useReleaseProfile,
+                                  LocalRepository repository, String scmUrl, String scmUsername, String scmPassword,
+                                  String scmTag, String scmTagBase, Map environments, String username )
+        throws ContinuumReleaseException, BuildAgentConfigurationException;
+
+    void releaseRollback( String releaseId, int projectId )
+        throws ContinuumReleaseException, BuildAgentConfigurationException;
+
+    String releaseCleanup( String releaseId )
+        throws ContinuumReleaseException, BuildAgentConfigurationException;
+
+    List<Map<String, Object>> getAllReleasesInProgress()
+        throws ContinuumReleaseException, BuildAgentConfigurationException;
+
+    String getDefaultBuildagent( int projectId );
+
+    PreparedRelease getPreparedRelease( String releaseId, String releaseType )
+        throws ContinuumReleaseException;
+}
\ No newline at end of file
diff --git a/continuum-api/src/main/java/org/apache/continuum/repository/RepositoryService.java b/continuum-api/src/main/java/org/apache/continuum/repository/RepositoryService.java
index a37da20..e5fd64d 100644
--- a/continuum-api/src/main/java/org/apache/continuum/repository/RepositoryService.java
+++ b/continuum-api/src/main/java/org/apache/continuum/repository/RepositoryService.java
@@ -19,10 +19,10 @@
  * under the License.
  */
 
-import java.util.List;
-
 import org.apache.continuum.model.repository.LocalRepository;
 
+import java.util.List;
+
 /**
  * @author Maria Catherine Tan
  * @version $Id$
@@ -31,14 +31,14 @@
 public interface RepositoryService
 {
     String ROLE = RepositoryService.class.getName();
-    
+
     // ------------------------------------------------------
     //  LocalRepository
     // ------------------------------------------------------
-    
+
     /**
      * Add the local repository
-     * 
+     *
      * @param repository the local repository to add
      * @return LocalRepository the local repository
      * @throws RepositoryServiceException
@@ -48,7 +48,7 @@
 
     /**
      * Update the local repository
-     * 
+     *
      * @param repository the local repository to update
      * @throws RepositoryServiceException
      */
@@ -57,7 +57,7 @@
 
     /**
      * Remove the local repository
-     * 
+     *
      * @param repositoryId the id of the local repository to remove
      * @throws RepositoryServiceException
      */
@@ -66,36 +66,47 @@
 
     /**
      * Retrieve all local repositories
-     * 
+     *
      * @return list of all local repositories
      */
     List<LocalRepository> getAllLocalRepositories();
-    
+
     /**
      * Retrieve local repository
-     * 
+     *
      * @param location the system file path of the repository
      * @return LocalRepository the local repository
      * @throws RepositoryServiceException
      */
     LocalRepository getLocalRepositoryByLocation( String location )
         throws RepositoryServiceException;
-    
+
     /**
      * Retrieve list of local repositories with the specified layout
+     *
      * @param layout the layout of the repository. "default" or "legacy"
      * @return List of local repositories
      * @throws RepositoryServiceException
      */
     List<LocalRepository> getLocalRepositoriesByLayout( String layout );
-    
+
     /**
      * Retrieve local repository
-     * 
+     *
      * @param repositoryId the id of the local repository
      * @return LocalRepository the local repository
      * @throws RepositoryServiceException
      */
     LocalRepository getLocalRepository( int repositoryId )
         throws RepositoryServiceException;
+
+    /**
+     * Retrieve local repository
+     *
+     * @param repositoryName
+     * @return
+     * @throws RepositoryServiceException
+     */
+    LocalRepository getLocalRepositoryByName( String repositoryName )
+        throws RepositoryServiceException;
 }
\ No newline at end of file
diff --git a/continuum-api/src/main/java/org/apache/continuum/repository/RepositoryServiceException.java b/continuum-api/src/main/java/org/apache/continuum/repository/RepositoryServiceException.java
index 0dd2f33..028c34b 100644
--- a/continuum-api/src/main/java/org/apache/continuum/repository/RepositoryServiceException.java
+++ b/continuum-api/src/main/java/org/apache/continuum/repository/RepositoryServiceException.java
@@ -31,12 +31,12 @@
     {
         super( message );
     }
-    
+
     public RepositoryServiceException( Throwable cause )
     {
         super( cause );
     }
-    
+
     public RepositoryServiceException( String message, Throwable cause )
     {
         super( message, cause );
diff --git a/continuum-api/src/main/java/org/apache/continuum/taskqueue/BuildProjectTask.java b/continuum-api/src/main/java/org/apache/continuum/taskqueue/BuildProjectTask.java
index fd1b282..b8ac695 100644
--- a/continuum-api/src/main/java/org/apache/continuum/taskqueue/BuildProjectTask.java
+++ b/continuum-api/src/main/java/org/apache/continuum/taskqueue/BuildProjectTask.java
@@ -19,35 +19,41 @@
  * under the License.
  */
 
-import java.io.Serializable;
-
+import org.apache.continuum.utils.build.BuildTrigger;
+import org.apache.maven.continuum.model.scm.ScmResult;
 import org.codehaus.plexus.taskqueue.Task;
 
+import java.io.Serializable;
+
 /**
  * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
  * @version $Id$
  */
 public class BuildProjectTask
     implements Task, Serializable
-{    
-	private static final long serialVersionUID = 3647734422022017812L;
+{
+    private static final long serialVersionUID = 3647734422022017812L;
 
-	private int projectId;
+    private final int projectId;
 
-    private int buildDefinitionId;
+    private final int buildDefinitionId;
 
-    private long timestamp;
+    private final long timestamp;
 
-    private int trigger;
+    private BuildTrigger buildTrigger;
 
     private long maxExecutionTime;
-    
-    private String projectName;
-    
-    private String buildDefinitionLabel;
 
-    public BuildProjectTask( int projectId, int buildDefinitionId, int trigger, String projectName,
-                             String buildDefinitionLabel )
+    private final String projectName;
+
+    private final String buildDefinitionLabel;
+
+    private ScmResult scmResult;
+
+    int projectGroupId;
+
+    public BuildProjectTask( int projectId, int buildDefinitionId, BuildTrigger buildTrigger, String projectName,
+                             String buildDefinitionLabel, ScmResult scmResult, int projectGroupId )
     {
         this.projectId = projectId;
 
@@ -55,11 +61,15 @@
 
         this.timestamp = System.currentTimeMillis();
 
-        this.trigger = trigger;
+        this.buildTrigger = buildTrigger;
 
         this.projectName = projectName;
-        
+
         this.buildDefinitionLabel = buildDefinitionLabel;
+
+        this.scmResult = scmResult;
+
+        this.projectGroupId = projectGroupId;
     }
 
     public int getProjectId()
@@ -77,9 +87,14 @@
         return timestamp;
     }
 
-    public int getTrigger()
+    public BuildTrigger getBuildTrigger()
     {
-        return trigger;
+        return buildTrigger;
+    }
+
+    public void setBuildTrigger( BuildTrigger buildTrigger )
+    {
+        this.buildTrigger = buildTrigger;
     }
 
     public void setMaxExecutionTime( long maxExecutionTime )
@@ -95,13 +110,23 @@
     public String getProjectName()
     {
         return projectName;
-    }    
-    
+    }
+
     public String getBuildDefinitionLabel()
     {
         return buildDefinitionLabel;
-    }    
-    
+    }
+
+    public ScmResult getScmResult()
+    {
+        return scmResult;
+    }
+
+    public int getProjectGroupId()
+    {
+        return projectGroupId;
+    }
+
     public boolean equals( Object obj )
     {
         if ( obj == null )
@@ -117,18 +142,18 @@
             return false;
         }
         BuildProjectTask buildProjectTask = (BuildProjectTask) obj;
-        return buildProjectTask.getBuildDefinitionId() == this.getBuildDefinitionId()
-            && buildProjectTask.getProjectId() == this.getProjectId()
-            && buildProjectTask.getTrigger() == this.getTrigger();
+        return buildProjectTask.getBuildDefinitionId() == this.getBuildDefinitionId() &&
+            buildProjectTask.getProjectId() == this.getProjectId() &&
+            buildProjectTask.getBuildTrigger().getTrigger() == this.buildTrigger.getTrigger();
     }
 
     public int hashCode()
     {
-        return this.getBuildDefinitionId() + this.getProjectId() + this.getTrigger();
+        return this.getBuildDefinitionId() + this.getProjectId() + this.buildTrigger.getTrigger();
     }
-    
+
     public int getHashCode()
     {
         return this.hashCode();
-    }    
+    }
 }
diff --git a/continuum-api/src/main/java/org/apache/continuum/taskqueue/CheckOutTask.java b/continuum-api/src/main/java/org/apache/continuum/taskqueue/CheckOutTask.java
index bf15acf..6e68187 100644
--- a/continuum-api/src/main/java/org/apache/continuum/taskqueue/CheckOutTask.java
+++ b/continuum-api/src/main/java/org/apache/continuum/taskqueue/CheckOutTask.java
@@ -19,9 +19,11 @@
  * under the License.
  */
 
+import org.apache.maven.continuum.model.project.Project;
 import org.codehaus.plexus.taskqueue.Task;
 
 import java.io.File;
+import java.util.List;
 
 /**
  * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
@@ -30,27 +32,36 @@
 public class CheckOutTask
     implements Task
 {
-    private int projectId;
+    private final int projectId;
 
-    private File workingDirectory;
-    
-    private String projectName;
-    
-    private String scmUserName;
+    private final File workingDirectory;
 
-    private String scmPassword;
+    private final String projectName;
 
-    public CheckOutTask( int projectId, File workingDirectory, String projectName, String scmUserName, String scmPassword )
+    private final String scmUserName;
+
+    private final String scmPassword;
+
+    private final String scmRootUrl;
+
+    private final List<Project> projectsWithCommonScmRoot;
+
+    public CheckOutTask( int projectId, File workingDirectory, String projectName, String scmUserName,
+                         String scmPassword, String scmRootUrl, List<Project> projectsWithCommonScmRoot )
     {
         this.projectId = projectId;
 
         this.workingDirectory = workingDirectory;
-        
+
         this.projectName = projectName;
-        
+
         this.scmUserName = scmUserName;
-        
+
         this.scmPassword = scmPassword;
+
+        this.scmRootUrl = scmRootUrl;
+
+        this.projectsWithCommonScmRoot = projectsWithCommonScmRoot;
     }
 
     public int getProjectId()
@@ -72,8 +83,8 @@
     {
         return projectName;
     }
-    
-    
+
+
     public String getScmUserName()
     {
         return scmUserName;
@@ -83,10 +94,19 @@
     {
         return scmPassword;
     }
-    
-    
+
     public int getHashCode()
     {
         return this.hashCode();
-    }    
+    }
+
+    public String getScmRootUrl()
+    {
+        return scmRootUrl;
+    }
+
+    public List<Project> getProjectsWithCommonScmRoot()
+    {
+        return projectsWithCommonScmRoot;
+    }
 }
diff --git a/continuum-api/src/main/java/org/apache/continuum/taskqueue/OverallBuildQueue.java b/continuum-api/src/main/java/org/apache/continuum/taskqueue/OverallBuildQueue.java
new file mode 100644
index 0000000..b4f0509
--- /dev/null
+++ b/continuum-api/src/main/java/org/apache/continuum/taskqueue/OverallBuildQueue.java
@@ -0,0 +1,397 @@
+package org.apache.continuum.taskqueue;
+
+/*
+ * 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 org.apache.continuum.utils.build.BuildTrigger;
+import org.codehaus.plexus.taskqueue.TaskQueue;
+import org.codehaus.plexus.taskqueue.TaskQueueException;
+import org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ */
+public interface OverallBuildQueue
+{
+    /**
+     * Returns the id of the "overall" build queue
+     *
+     * @return
+     */
+    int getId();
+
+    void setId( int id );
+
+    /**
+     * Returns the name of the "overall" build queue
+     *
+     * @return
+     */
+    String getName();
+
+    void setName( String name );
+
+    /* Checkout Queue */
+
+    /**
+     * Returns the checkout queue.
+     *
+     * @return
+     */
+    TaskQueue getCheckoutQueue();
+
+    /**
+     * Add checkout task to checkout queue.
+     *
+     * @param checkoutTask
+     * @throws TaskQueueException TODO
+     */
+    void addToCheckoutQueue( CheckOutTask checkoutTask )
+        throws TaskQueueException;
+
+    /**
+     * Add checkout tasks to checkout queue.
+     *
+     * @param checkoutTasks
+     * @throws TaskQueueException TODO
+     */
+    void addToCheckoutQueue( List<CheckOutTask> checkoutTasks )
+        throws TaskQueueException;
+
+    /**
+     * Get all checkout tasks in checkout queue.
+     *
+     * @return
+     * @throws TaskQueueException TODO
+     */
+    List<CheckOutTask> getProjectsInCheckoutQueue()
+        throws TaskQueueException;
+
+    /**
+     * Check if the project is in the checkout queue.
+     *
+     * @param projectId
+     * @return
+     * @throws TaskQueueException TODO
+     */
+    boolean isInCheckoutQueue( int projectId )
+        throws TaskQueueException;
+
+    /**
+     * Cancel checkout of project.
+     *
+     * @param projectId
+     * @throws TaskQueueException
+     */
+    void cancelCheckoutTask( int projectId )
+        throws TaskQueueException;
+
+    /**
+     * Cancel current checkout.
+     *
+     * @return TODO
+     */
+    boolean cancelCurrentCheckout();
+
+    /**
+     * Remove project from checkout queue.
+     *
+     * @param projectId
+     * @return
+     * @throws TaskQueueException TODO
+     */
+    boolean removeProjectFromCheckoutQueue( int projectId )
+        throws TaskQueueException;
+
+    /**
+     * Remove the specified projects in the checkout queue.
+     *
+     * @param projectId
+     * @return
+     * @throws TaskQueueException TODO
+     */
+    boolean removeProjectsFromCheckoutQueue( int[] projectId )
+        throws TaskQueueException;
+
+    /**
+     * @param hashCodes
+     * @throws TaskQueueException TODO
+     */
+    void removeTasksFromCheckoutQueueWithHashCodes( int[] hashCodes )
+        throws TaskQueueException;
+
+    /* Prepare Build Queue */
+
+    /**
+     * Returns the prepare build queue.
+     *
+     * @return
+     */
+    TaskQueue getPrepareBuildQueue();
+
+    /**
+     * Add the prepare build task to the prepare build queue.
+     *
+     * @param prepareBuildTask
+     * @throws Exception
+     */
+    void addToPrepareBuildQueue( PrepareBuildProjectsTask prepareBuildTask )
+        throws TaskQueueException;
+
+    /**
+     * Add the prepare build tasks to the prepare build queue.
+     *
+     * @param prepareBuildTasks
+     * @throws TaskQueueException TODO
+     */
+    void addToPrepareBuildQueue( List<PrepareBuildProjectsTask> prepareBuildTasks )
+        throws TaskQueueException;
+
+    /**
+     * Returns the prepare build tasks in the prepare build queue.
+     *
+     * @return
+     * @throws TaskQueueException TODO
+     */
+    List<PrepareBuildProjectsTask> getProjectsInPrepareBuildQueue()
+        throws TaskQueueException;
+
+    /**
+     * Checks if the specified project is in the prepare build queue.
+     *
+     * @param projectId
+     * @return
+     * @throws TaskQueueException TODO
+     */
+    boolean isInPrepareBuildQueue( int projectId )
+        throws TaskQueueException;
+
+    /**
+     * Checks if the specified project group and scm root is in the prepare build queue.
+     *
+     * @param projectGroupId
+     * @param scmRootId
+     * @return
+     * @throws TaskQueueException
+     */
+    boolean isInPrepareBuildQueue( int projectGroupId, int scmRootId )
+        throws TaskQueueException;
+
+    /**
+     * Checks if the specified project group and scm root is in the prepare build queue.
+     *
+     * @param projectGroupId
+     * @param scmRootAddress
+     * @return
+     * @throws TaskQueueException
+     */
+    boolean isInPrepareBuildQueue( int projectGroupId, String scmRootAddress )
+        throws TaskQueueException;
+
+    /**
+     * Cancel the prepare build task of the corresponding project group and scm root.
+     *
+     * @param projectId
+     * @param scmRootId
+     */
+    void cancelPrepareBuildTask( int projectGroupId, int scmRootId );
+
+    /**
+     * Cancel the prepare build task of the corresponding project
+     *
+     * @param projectId
+     */
+    void cancelPrepareBuildTask( int projectId );
+
+    /**
+     * Cancel the current prepare build.
+     *
+     * @return
+     */
+    boolean cancelCurrentPrepareBuild();
+
+    /**
+     * Remove the project group matching the specified id, and scm root id from the prepare build queue.
+     *
+     * @param projectGroupId
+     * @param scmRootId
+     * @return
+     * @throws TaskQueueException TODO
+     */
+    boolean removeProjectFromPrepareBuildQueue( int projectGroupId, int scmRootId )
+        throws TaskQueueException;
+
+    /**
+     * Remove the project group matching the specified id and scm root address from the prepare build queue.
+     *
+     * @param projectId
+     * @param scmRootAddress
+     * @return
+     * @throws TaskQueueException TODO
+     */
+    boolean removeProjectFromPrepareBuildQueue( int projectGroupId, String scmRootAddress )
+        throws TaskQueueException;
+
+    /**
+     * Remove the projects matching the specified hashcodes from the prepare build queue.
+     *
+     * @param hashCodes
+     * @throws TaskQueueException TODO
+     */
+    void removeProjectsFromPrepareBuildQueueWithHashCodes( int[] hashCodes )
+        throws TaskQueueException;
+
+    /* Build Queue */
+
+    /**
+     * Returns the build queue.
+     *
+     * @return
+     */
+    TaskQueue getBuildQueue();
+
+    /**
+     * Add the build task to the build queue.
+     *
+     * @param buildTask
+     * @throws Exception
+     */
+    void addToBuildQueue( BuildProjectTask buildTask )
+        throws TaskQueueException;
+
+    /**
+     * Add the build tasks to the build queue.
+     *
+     * @param buildTasks
+     * @throws TaskQueueException TODO
+     */
+    void addToBuildQueue( List<BuildProjectTask> buildTasks )
+        throws TaskQueueException;
+
+    /**
+     * Returns the build tasks in the build queue.
+     *
+     * @return
+     * @throws TaskQueueException TODO
+     */
+    List<BuildProjectTask> getProjectsInBuildQueue()
+        throws TaskQueueException;
+
+    /**
+     * Checks if the specified project is in the build queue.
+     *
+     * @param projectId
+     * @return
+     * @throws TaskQueueException TODO
+     */
+    boolean isInBuildQueue( int projectId )
+        throws TaskQueueException;
+
+    /**
+     * Checks if the specified project with the specified build definition is in the build queue.
+     *
+     * @param projectId
+     * @param buildDefinitionId
+     * @return
+     * @throws TaskQueueException TODO
+     */
+    boolean isInBuildQueue( int projectId, int buildDefinitionId )
+        throws TaskQueueException;
+
+    /**
+     * Cancel the build task of the corresponding project.
+     *
+     * @param projectId
+     */
+    void cancelBuildTask( int projectId );
+
+    /**
+     * Cancel the current build.
+     *
+     * @return
+     */
+    boolean cancelCurrentBuild();
+
+    /**
+     * Remove the project matching the specified id, name, build definition and trigger from the build queue.
+     *
+     * @param projectId
+     * @param buildDefinitionId
+     * @param buildTrigger
+     * @param projectName
+     * @param projectGroupId
+     * @return
+     * @throws TaskQueueException TODO
+     */
+    boolean removeProjectFromBuildQueue( int projectId, int buildDefinitionId, BuildTrigger buildTrigger,
+                                         String projectName, int projectGroupId )
+        throws TaskQueueException;
+
+    /**
+     * Remove the specified project from the build queue.
+     *
+     * @param projectId
+     * @return
+     * @throws TaskQueueException TODO
+     */
+    boolean removeProjectFromBuildQueue( int projectId )
+        throws TaskQueueException;
+
+    /**
+     * Remove the specified projects from the build queue.
+     *
+     * @param projectIds
+     * @return
+     * @throws TaskQueueException TODO
+     */
+    boolean removeProjectsFromBuildQueue( int[] projectIds )
+        throws TaskQueueException;
+
+    /**
+     * Remove the projects matching the specified hashcodes from the build queue.
+     *
+     * @param hashCodes
+     * @throws TaskQueueException TODO
+     */
+    void removeProjectsFromBuildQueueWithHashCodes( int[] hashCodes )
+        throws TaskQueueException;
+
+    /**
+     * Returns the build task queue executor used.
+     *
+     * @return
+     */
+    TaskQueueExecutor getBuildTaskQueueExecutor();
+
+    /**
+     * Returns the checkout task queue executor used.
+     *
+     * @return
+     */
+    TaskQueueExecutor getCheckoutTaskQueueExecutor();
+
+    /**
+     * Returns the prepare build task queue executor used.
+     *
+     * @return
+     */
+    TaskQueueExecutor getPrepareBuildTaskQueueExecutor();
+}
diff --git a/continuum-api/src/main/java/org/apache/continuum/taskqueue/OverallDistributedBuildQueue.java b/continuum-api/src/main/java/org/apache/continuum/taskqueue/OverallDistributedBuildQueue.java
new file mode 100644
index 0000000..81026c2
--- /dev/null
+++ b/continuum-api/src/main/java/org/apache/continuum/taskqueue/OverallDistributedBuildQueue.java
@@ -0,0 +1,56 @@
+package org.apache.continuum.taskqueue;
+
+/*
+ * 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 org.apache.continuum.builder.distributed.executor.DistributedBuildTaskQueueExecutor;
+import org.codehaus.plexus.taskqueue.Task;
+import org.codehaus.plexus.taskqueue.TaskQueue;
+import org.codehaus.plexus.taskqueue.TaskQueueException;
+
+import java.util.List;
+
+public interface OverallDistributedBuildQueue
+{
+    String getBuildAgentUrl();
+
+    void setBuildAgentUrl( String buildAgentUrl );
+
+    TaskQueue getDistributedBuildQueue();
+
+    void addToDistributedBuildQueue( Task distributedBuildTask )
+        throws TaskQueueException;
+
+    List<PrepareBuildProjectsTask> getProjectsInQueue()
+        throws TaskQueueException;
+
+    boolean isInDistributedBuildQueue( int projectGroupId, int scmRootId )
+        throws TaskQueueException;
+
+    void removeFromDistributedBuildQueue( int projectGroupId, int scmRootId )
+        throws TaskQueueException;
+
+    void removeFromDistributedBuildQueue( int[] hashCodes )
+        throws TaskQueueException;
+
+    void removeFromDistributedBuildQueueByHashCode( int hashCode )
+        throws TaskQueueException;
+
+    DistributedBuildTaskQueueExecutor getDistributedBuildTaskQueueExecutor();
+}
diff --git a/continuum-api/src/main/java/org/apache/continuum/taskqueue/PrepareBuildProjectsTask.java b/continuum-api/src/main/java/org/apache/continuum/taskqueue/PrepareBuildProjectsTask.java
index 77ba57c..67cc172 100644
--- a/continuum-api/src/main/java/org/apache/continuum/taskqueue/PrepareBuildProjectsTask.java
+++ b/continuum-api/src/main/java/org/apache/continuum/taskqueue/PrepareBuildProjectsTask.java
@@ -1,62 +1,72 @@
 package org.apache.continuum.taskqueue;
 
-import java.util.Map;
+/*
+ * 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 org.apache.continuum.utils.build.BuildTrigger;
 import org.codehaus.plexus.taskqueue.Task;
 
+import java.util.Map;
+
 public class PrepareBuildProjectsTask
     implements Task
 {
-    private Map<Integer, Integer> projectsBuildDefinitionsMap;
+    private final Map<Integer, Integer> projectsBuildDefinitionsMap;
 
-    private int trigger;
+    private BuildTrigger buildTrigger;
 
-    private int projectGroupId;
+    private final int projectGroupId;
 
-    private String projectGroupName;
+    private final String projectGroupName;
 
-    private String scmRootAddress;
+    private final String scmRootAddress;
 
-    private int projectScmRootId;
+    private final int projectScmRootId;
 
-    public PrepareBuildProjectsTask( Map<Integer, Integer> projectsBuildDefinitionsMap, int trigger,
+    public PrepareBuildProjectsTask( Map<Integer, Integer> projectsBuildDefinitionsMap, BuildTrigger buildTrigger,
                                      int projectGroupId, String projectGroupName, String scmRootAddress,
                                      int projectScmRootId )
     {
         this.projectsBuildDefinitionsMap = projectsBuildDefinitionsMap;
-        this.trigger = trigger;
+        this.buildTrigger = buildTrigger;
         this.projectGroupId = projectGroupId;
         this.projectGroupName = projectGroupName;
         this.scmRootAddress = scmRootAddress;
         this.projectScmRootId = projectScmRootId;
     }
-    
+
     public long getMaxExecutionTime()
     {
         // TODO Auto-generated method stub
         return 0;
     }
-    
+
     public Map<Integer, Integer> getProjectsBuildDefinitionsMap()
     {
         return projectsBuildDefinitionsMap;
     }
-    
-    public void setProjectsBuildDefinitionsMap( Map<Integer, Integer> projectsBuildDefinitionsMap )
+
+    public BuildTrigger getBuildTrigger()
     {
-        this.projectsBuildDefinitionsMap = projectsBuildDefinitionsMap;
+        return buildTrigger;
     }
 
-    public int getTrigger()
-    {
-        return trigger;
-    }
-
-    public void setTrigger( int trigger )
-    {
-        this.trigger = trigger;
-    }
-    
     public int getHashCode()
     {
         return this.hashCode();
@@ -67,33 +77,23 @@
         return projectGroupId;
     }
 
-    public void setProjectGroupId( int projectGroupId )
-    {
-        this.projectGroupId = projectGroupId;
-    }
-
     public String getProjectGroupName()
     {
         return projectGroupName;
     }
 
-    public void setProjectGroupName( String projectGroupName )
-    {
-        this.projectGroupName = projectGroupName;
-    }
-
     public String getScmRootAddress()
     {
         return scmRootAddress;
     }
 
-    public void setScmRootAddress( String scmRootAddress )
+    public int getProjectScmRootId()
     {
-        this.scmRootAddress = scmRootAddress;
+        return projectScmRootId;
     }
 
     public int hashCode()
     {
-        return this.projectGroupId + this.projectScmRootId + this.trigger;
+        return this.projectGroupId + this.projectScmRootId + this.buildTrigger.getTrigger();
     }
 }
diff --git a/continuum-api/src/main/java/org/apache/continuum/taskqueue/manager/TaskQueueManager.java b/continuum-api/src/main/java/org/apache/continuum/taskqueue/manager/TaskQueueManager.java
index 92e8710..83d97ef 100644
--- a/continuum-api/src/main/java/org/apache/continuum/taskqueue/manager/TaskQueueManager.java
+++ b/continuum-api/src/main/java/org/apache/continuum/taskqueue/manager/TaskQueueManager.java
@@ -19,12 +19,7 @@
  * under the License.
  */
 
-import java.util.List;
-
-import org.apache.continuum.taskqueue.BuildProjectTask;
-import org.apache.continuum.taskqueue.PrepareBuildProjectsTask;
 import org.codehaus.plexus.taskqueue.TaskQueue;
-import org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor;
 
 /**
  * @author <a href="mailto:ctan@apache.org">Maria Catherine Tan</a>
@@ -33,70 +28,14 @@
 {
     String ROLE = TaskQueueManager.class.getName();
 
-    boolean buildInProgress()
-        throws TaskQueueManagerException;
-
-    void cancelBuildTask( int projectId )
-        throws TaskQueueManagerException;
-
-    boolean cancelCheckout( int projectId )
-        throws TaskQueueManagerException;
-
-    boolean cancelCurrentBuild()
-        throws TaskQueueManagerException;
-
-    TaskQueue getBuildQueue();
-
-    TaskQueueExecutor getBuildTaskQueueExecutor()
-        throws TaskQueueManagerException;
-
-    TaskQueue getCheckoutQueue();
-
-    List /* CheckOutTask */getCheckOutTasksInQueue()
-        throws TaskQueueManagerException;
-
-    int getCurrentProjectIdBuilding()
-        throws TaskQueueManagerException;
-
-    TaskQueue getDistributedBuildQueue();
-
-    List<PrepareBuildProjectsTask> getDistributedBuildProjectsInQueue()
-        throws TaskQueueManagerException;
-
-    TaskQueue getPrepareBuildQueue();
-
-    TaskQueueExecutor getPrepareBuildTaskQueueExecutor()
-        throws TaskQueueManagerException;
-
-    public List<BuildProjectTask> getProjectsInBuildQueue()
-        throws TaskQueueManagerException;
-
     TaskQueue getPurgeQueue();
 
-    boolean isInBuildingQueue( int projectId )
-        throws TaskQueueManagerException;
-
-    boolean isInBuildingQueue( int projectId, int buildDefinitionId )
-        throws TaskQueueManagerException;
-
-    boolean isInCheckoutQueue( int projectId )
-        throws TaskQueueManagerException;
-
-    boolean isInCurrentPrepareBuildTask( int projectId )
-        throws TaskQueueManagerException;
-
-    boolean isInDistributedBuildQueue( int projectGroupId, String scmRootAddress )
-        throws TaskQueueManagerException;
-
-    boolean isInPrepareBuildQueue( int projectId )
-        throws TaskQueueManagerException;
-
     boolean isInPurgeQueue( int purgeConfigurationId )
         throws TaskQueueManagerException;
 
     /**
      * Check if the repository is already in the purging queue
-     * 
+     *
      * @param repositoryId the id of the repository purge configuration
      * @return true if the repository is in the purging queue, otherwise false
      * @throws TaskQueueManagerException
@@ -106,7 +45,7 @@
 
     /**
      * Check if the repository is being used by a project that is currently building
-     * 
+     *
      * @param repositoryId the id of the local repository
      * @return true if the repository is in use, otherwise false
      * @throws TaskQueueManagerException
@@ -114,21 +53,22 @@
     boolean isRepositoryInUse( int repositoryId )
         throws TaskQueueManagerException;
 
+    /**
+     * Check whether a project is in the release stage based on the given releaseId.
+     *
+     * @param releaseId
+     * @return
+     * @throws TaskQueueManagerException
+     */
+    boolean isProjectInReleaseStage( String releaseId )
+        throws TaskQueueManagerException;
+
     boolean releaseInProgress()
         throws TaskQueueManagerException;
 
-    boolean removeFromBuildingQueue( int projectId, int buildDefinitionId, int trigger, String projectName )
-        throws TaskQueueManagerException;
-
-    boolean removeFromDistributedBuildQueue( int projectGroupId, String scmRootAddress )
-        throws TaskQueueManagerException;
-
-    boolean removeFromPrepareBuildQueue( int projectGroupId, String scmRootAddress )
-        throws TaskQueueManagerException;
-
     /**
      * Remove local repository from the purge queue
-     * 
+     *
      * @param purgeConfigId the id of the purge configuration
      * @return true if the purge configuration was successfully removed from the purge queue, otherwise false
      * @throws TaskQueueManagerException
@@ -138,7 +78,7 @@
 
     /**
      * Remove local repositories from the purge queue
-     * 
+     *
      * @param purgeConfigIds the ids of the purge configuration
      * @return true if the purge configurations were successfully removed from the purge queue, otherwise false
      * @throws TaskQueueManagerException
@@ -146,41 +86,12 @@
     boolean removeFromPurgeQueue( int[] purgeConfigIds )
         throws TaskQueueManagerException;
 
-    boolean removeProjectFromBuildingQueue( int projectId )
-        throws TaskQueueManagerException;
-
-    boolean removeProjectsFromBuildingQueue( int[] projectsId )
-        throws TaskQueueManagerException;
-
-    /**
-     * @param hashCodes BuildProjectTask hashCodes
-     * @throws TaskQueueManagerException
-     */
-    void removeProjectsFromBuildingQueueWithHashCodes( int[] hashCodes )
-        throws TaskQueueManagerException;
-
-    boolean removeProjectFromCheckoutQueue( int projectId )
-        throws TaskQueueManagerException;
-
-    boolean removeProjectsFromCheckoutQueue( int[] projectId )
-        throws TaskQueueManagerException;
-
     /**
      * Remove local repository from the purge queue
-     * 
+     *
      * @param repositoryId the id of the local repository
      * @throws TaskQueueManagerException
      */
     void removeRepositoryFromPurgeQueue( int repositoryId )
         throws TaskQueueManagerException;
-
-    /**
-     * @param hashCodes CheckOutTask hashCodes
-     * @throws TaskQueueManagerException
-     */
-    void removeTasksFromCheckoutQueueWithHashCodes( int[] hashCodes )
-        throws TaskQueueManagerException;
-
-    void removeTasksFromDistributedBuildQueueWithHashCodes( int[] hashCodes )
-        throws TaskQueueManagerException;
 }
diff --git a/continuum-api/src/main/java/org/apache/continuum/taskqueue/manager/TaskQueueManagerException.java b/continuum-api/src/main/java/org/apache/continuum/taskqueue/manager/TaskQueueManagerException.java
index 042ab97..35eb71d 100644
--- a/continuum-api/src/main/java/org/apache/continuum/taskqueue/manager/TaskQueueManagerException.java
+++ b/continuum-api/src/main/java/org/apache/continuum/taskqueue/manager/TaskQueueManagerException.java
@@ -1,5 +1,24 @@
 package org.apache.continuum.taskqueue.manager;
 
+/*
+ * 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.
+ */
+
 public class TaskQueueManagerException
     extends Exception
 {
diff --git a/continuum-api/src/main/java/org/apache/continuum/utils/ProjectSorter.java b/continuum-api/src/main/java/org/apache/continuum/utils/ProjectSorter.java
new file mode 100644
index 0000000..f7a295b
--- /dev/null
+++ b/continuum-api/src/main/java/org/apache/continuum/utils/ProjectSorter.java
@@ -0,0 +1,176 @@
+package org.apache.continuum.utils;
+
+/*
+ * 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 org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.project.ProjectDependency;
+import org.codehaus.plexus.util.dag.CycleDetectedException;
+import org.codehaus.plexus.util.dag.DAG;
+import org.codehaus.plexus.util.dag.TopologicalSorter;
+import org.slf4j.Logger;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Sort projects by dependencies.
+ *
+ * @author <a href="mailto:brett@apache.org">Brett Porter</a>
+ * @version $Id: ProjectSorter.java 777411 2009-05-22 07:13:37Z ctan $
+ */
+public class ProjectSorter
+{
+    private ProjectSorter()
+    {
+        // no touchy...
+    }
+
+    /**
+     * Sort a list of projects.
+     * <ul>
+     * <li>collect all the vertices for the projects that we want to build.</li>
+     * <li>iterate through the deps of each project and if that dep is within
+     * the set of projects we want to build then add an edge, otherwise throw
+     * the edge away because that dependency is not within the set of projects
+     * we are trying to build. we assume a closed set.</li>
+     * <li>do a topo sort on the graph that remains.</li>
+     * </ul>
+     */
+    public static List<Project> getSortedProjects( Collection<Project> projects, Logger logger )
+    {
+        DAG dag = new DAG();
+
+        Map<String, Project> projectMap = new HashMap<String, Project>();
+
+        for ( Project project : projects )
+        {
+            String id = getProjectId( project );
+
+            if ( dag.getVertex( id ) != null )
+            {
+                logger.warn( "Project '" + id + "' is duplicated in the reactor." );
+            }
+
+            dag.addVertex( id );
+
+            projectMap.put( id, project );
+        }
+
+        for ( Project project : projects )
+        {
+            String id = getProjectId( project );
+
+            String projectGroupId = "[" + project.getProjectGroup().getId() + "]";
+
+            // Dependencies
+            for ( Object o : project.getDependencies() )
+            {
+                ProjectDependency dependency = (ProjectDependency) o;
+
+                String dependencyId = projectGroupId + ":" + getDependencyId( dependency );
+
+                if ( dag.getVertex( dependencyId ) != null )
+                {
+                    try
+                    {
+                        dag.addEdge( id, dependencyId );
+                    }
+                    catch ( CycleDetectedException e )
+                    {
+                        logger.warn( "Ignore cycle detected in project dependencies: " + e.getMessage() );
+                    }
+                }
+            }
+
+            // Parent
+            ProjectDependency parent = project.getParent();
+
+            if ( parent != null )
+            {
+                String parentId = projectGroupId + ":" + getDependencyId( parent );
+
+                if ( dag.getVertex( parentId ) != null )
+                {
+                    // Parent is added as an edge, but must not cause a cycle - so we remove any other edges it has in conflict
+                    if ( dag.hasEdge( parentId, id ) )
+                    {
+                        dag.removeEdge( parentId, id );
+                    }
+                    try
+                    {
+                        dag.addEdge( id, parentId );
+                    }
+                    catch ( CycleDetectedException e )
+                    {
+                        logger.warn( "Ignore cycle detected in project parent: " + e.getMessage() );
+                    }
+                }
+            }
+        }
+
+        List<Project> sortedProjects = new ArrayList<Project>();
+
+        for ( Object o : TopologicalSorter.sort( dag ) )
+        {
+            String id = (String) o;
+
+            sortedProjects.add( projectMap.get( id ) );
+        }
+
+        return sortedProjects;
+    }
+
+    private static String getProjectId( Project project )
+    {
+        String groupId;
+
+        String artifactId;
+
+        if ( project.getGroupId() == null )
+        {
+            groupId = project.getName();
+        }
+        else
+        {
+            groupId = project.getGroupId();
+        }
+
+        if ( project.getArtifactId() == null )
+        {
+            artifactId = project.getName();
+        }
+        else
+        {
+            artifactId = project.getArtifactId();
+        }
+
+        String projectGroupId = "[" + project.getProjectGroup().getId() + "]";
+
+        return projectGroupId + ":" + groupId + ":" + artifactId + ":" + project.getVersion();
+    }
+
+    private static String getDependencyId( ProjectDependency project )
+    {
+        return project.getGroupId() + ":" + project.getArtifactId() + ":" + project.getVersion();
+    }
+}
diff --git a/continuum-api/src/main/java/org/apache/continuum/utils/build/BuildTrigger.java b/continuum-api/src/main/java/org/apache/continuum/utils/build/BuildTrigger.java
new file mode 100644
index 0000000..6647190
--- /dev/null
+++ b/continuum-api/src/main/java/org/apache/continuum/utils/build/BuildTrigger.java
@@ -0,0 +1,69 @@
+package org.apache.continuum.utils.build;
+
+/*
+ * 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.
+ */
+
+/**
+ * @author Jevica Arianne B. Zurbano
+ * @version $Id: BuildTrigger.java
+ * @since 19 jun 09
+ */
+public class BuildTrigger
+{
+    private int trigger;
+
+    private String triggeredBy;
+
+    public BuildTrigger( int trigger )
+    {
+        this.trigger = trigger;
+    }
+
+    public BuildTrigger( String triggeredBy )
+    {
+        this.triggeredBy = triggeredBy;
+    }
+
+    public BuildTrigger( int trigger, String triggeredBy )
+    {
+        this.trigger = trigger;
+        this.triggeredBy = triggeredBy;
+    }
+
+    public void setTrigger( int trigger )
+    {
+        this.trigger = trigger;
+    }
+
+    public int getTrigger()
+    {
+        return this.trigger;
+    }
+
+    public void setTriggeredBy( String triggeredBy )
+    {
+        this.triggeredBy = triggeredBy;
+    }
+
+    public String getTriggeredBy()
+    {
+        return this.triggeredBy;
+    }
+}
+
diff --git a/continuum-api/src/main/java/org/apache/continuum/utils/release/ReleaseUtil.java b/continuum-api/src/main/java/org/apache/continuum/utils/release/ReleaseUtil.java
new file mode 100644
index 0000000..5f4db43
--- /dev/null
+++ b/continuum-api/src/main/java/org/apache/continuum/utils/release/ReleaseUtil.java
@@ -0,0 +1,194 @@
+package org.apache.continuum.utils.release;
+
+/*
+ * 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 org.apache.maven.model.Model;
+import org.apache.maven.model.Plugin;
+import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
+import org.apache.maven.shared.release.versions.DefaultVersionInfo;
+import org.apache.maven.shared.release.versions.VersionInfo;
+import org.codehaus.plexus.util.ReaderFactory;
+import org.codehaus.plexus.util.StringUtils;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+public class ReleaseUtil
+{
+    @SuppressWarnings( "unchecked" )
+    public static Map<String, Object> getReleasePluginParameters( String workingDirectory, String pomFilename )
+        throws Exception
+    {
+        Map<String, Object> params = new HashMap<String, Object>();
+
+        // TODO: Use the model reader so we'll can get the plugin configuration from parent too
+        Model model = getMavenModel( workingDirectory, pomFilename );
+
+        if ( model.getBuild() != null && model.getBuild().getPlugins() != null )
+        {
+            for ( Plugin plugin : (List<Plugin>) model.getBuild().getPlugins() )
+            {
+                if ( plugin.getGroupId() != null && plugin.getGroupId().equals( "org.apache.maven.plugins" ) &&
+                    plugin.getArtifactId() != null && plugin.getArtifactId().equals( "maven-release-plugin" ) )
+                {
+                    Xpp3Dom dom = (Xpp3Dom) plugin.getConfiguration();
+
+                    // TODO: use constants
+                    if ( dom != null )
+                    {
+                        Xpp3Dom configuration = dom.getChild( "releaseLabel" );
+                        if ( configuration != null )
+                        {
+                            params.put( "scm-tag", configuration.getValue() );
+                        }
+
+                        configuration = dom.getChild( "tag" );
+                        if ( configuration != null )
+                        {
+                            params.put( "scm-tag", configuration.getValue() );
+                        }
+
+                        configuration = dom.getChild( "tagBase" );
+                        if ( configuration != null )
+                        {
+                            params.put( "scm-tagbase", configuration.getValue() );
+                        }
+
+                        configuration = dom.getChild( "preparationGoals" );
+                        if ( configuration != null )
+                        {
+                            params.put( "preparation-goals", configuration.getValue() );
+                        }
+
+                        configuration = dom.getChild( "arguments" );
+                        if ( configuration != null )
+                        {
+                            params.put( "arguments", configuration.getValue() );
+                        }
+
+                        configuration = dom.getChild( "scmCommentPrefix" );
+                        if ( configuration != null )
+                        {
+                            params.put( "scm-comment-prefix", configuration.getValue() );
+                        }
+
+                        configuration = dom.getChild( "autoVersionSubmodules" );
+                        if ( configuration != null )
+                        {
+                            params.put( "auto-version-submodules", Boolean.valueOf( configuration.getValue() ) );
+                        }
+
+                        configuration = dom.getChild( "addSchema" );
+                        if ( configuration != null )
+                        {
+                            params.put( "add-schema", Boolean.valueOf( configuration.getValue() ) );
+                        }
+
+                        configuration = dom.getChild( "useReleaseProfile" );
+                        if ( configuration != null )
+                        {
+                            params.put( "use-release-profile", Boolean.valueOf( configuration.getValue() ) );
+                        }
+
+                        configuration = dom.getChild( "goals" );
+                        if ( configuration != null )
+                        {
+                            String goals = configuration.getValue();
+                            if ( model.getDistributionManagement() != null &&
+                                model.getDistributionManagement().getSite() != null )
+                            {
+                                goals += " site-deploy";
+                            }
+
+                            params.put( "perform-goals", goals );
+                        }
+                    }
+                }
+            }
+        }
+        return params;
+    }
+
+    public static void processProject( String workingDirectory, String pomFilename, boolean autoVersionSubmodules,
+                                       List<Map<String, String>> projects )
+        throws Exception
+    {
+        Model model = getMavenModel( workingDirectory, pomFilename );
+
+        if ( model.getGroupId() == null )
+        {
+            model.setGroupId( model.getParent().getGroupId() );
+        }
+
+        if ( model.getVersion() == null )
+        {
+            model.setVersion( model.getParent().getVersion() );
+        }
+
+        setProperties( model, autoVersionSubmodules, projects );
+
+        for ( Iterator modules = model.getModules().iterator(); modules.hasNext(); )
+        {
+            String module = StringUtils.replace( modules.next().toString(), '\\', '/' );
+
+            processProject( workingDirectory + "/" + module, "pom.xml", autoVersionSubmodules, projects );
+        }
+    }
+
+    private static void setProperties( Model model, boolean autoVersionSubmodules, List<Map<String, String>> projects )
+        throws Exception
+    {
+        Map<String, String> params = new HashMap<String, String>();
+
+        params.put( "key", model.getGroupId() + ":" + model.getArtifactId() );
+
+        if ( model.getName() == null )
+        {
+            model.setName( model.getArtifactId() );
+        }
+        params.put( "name", model.getName() );
+
+        if ( !autoVersionSubmodules || projects.size() == 0 )
+        {
+            VersionInfo version = new DefaultVersionInfo( model.getVersion() );
+            params.put( "release", version.getReleaseVersionString() );
+            params.put( "dev", version.getNextVersion().getSnapshotVersionString() );
+        }
+        else
+        {
+            Map<String, String> rootParams = projects.get( 0 ); // get the root map
+            params.put( "release", rootParams.get( "release" ) );
+            params.put( "dev", rootParams.get( "dev" ) );
+        }
+
+        projects.add( params );
+    }
+
+    private static Model getMavenModel( String workingDirectory, String pomFilename )
+        throws Exception
+    {
+        MavenXpp3Reader pomReader = new MavenXpp3Reader();
+        return pomReader.read( ReaderFactory.newXmlReader( new File( workingDirectory, pomFilename ) ) );
+    }
+}
diff --git a/continuum-api/src/main/java/org/apache/continuum/utils/shell/DefaultShellCommandHelper.java b/continuum-api/src/main/java/org/apache/continuum/utils/shell/DefaultShellCommandHelper.java
new file mode 100644
index 0000000..419246a
--- /dev/null
+++ b/continuum-api/src/main/java/org/apache/continuum/utils/shell/DefaultShellCommandHelper.java
@@ -0,0 +1,299 @@
+package org.apache.continuum.utils.shell;
+
+/*
+ * 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 org.apache.maven.shared.release.ReleaseResult;
+import org.apache.maven.shared.release.exec.MavenExecutorException;
+import org.apache.maven.shared.release.exec.TeeConsumer;
+import org.codehaus.plexus.util.StringUtils;
+import org.codehaus.plexus.util.cli.Arg;
+import org.codehaus.plexus.util.cli.CommandLineException;
+import org.codehaus.plexus.util.cli.CommandLineUtils;
+import org.codehaus.plexus.util.cli.Commandline;
+import org.codehaus.plexus.util.cli.StreamConsumer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
+ * @version $Id$
+ */
+@Service( "shellCommandHelper" )
+public class DefaultShellCommandHelper
+    implements ShellCommandHelper
+{
+    private static final Logger log = LoggerFactory.getLogger( DefaultShellCommandHelper.class );
+
+    private Set<Long> running = Collections.synchronizedSet( new HashSet<Long>() );
+
+    // ----------------------------------------------------------------------
+    // ShellCommandHelper Implementation
+    // ----------------------------------------------------------------------
+
+    public Properties getSystemEnvVars()
+    {
+        try
+        {
+            return CommandLineUtils.getSystemEnvVars( false );
+        }
+        catch ( IOException e )
+        {
+            log.warn( "failed to get system environment", e );
+        }
+        return new Properties();
+    }
+
+    /**
+     * Make the command line
+     *
+     * @param workingDirectory
+     * @param executable
+     * @param arguments
+     * @param idCommand
+     * @param environments
+     * @return
+     * @throws Exception
+     */
+    protected Commandline createCommandline( File workingDirectory, String executable, String[] arguments,
+                                             long idCommand, Map<String, String> environments )
+        throws Exception
+    {
+        Commandline cl = new Commandline();
+
+        cl.setPid( idCommand );
+
+        cl.addEnvironment( "MAVEN_TERMINATE_CMD", "on" );
+
+        if ( environments != null && !environments.isEmpty() )
+        {
+            for ( String key : environments.keySet() )
+            {
+                String value = environments.get( key );
+                cl.addEnvironment( key, value );
+            }
+        }
+
+        cl.addSystemEnvironment();
+
+        cl.setExecutable( executable );
+
+        if ( workingDirectory != null )
+        {
+            cl.setWorkingDirectory( workingDirectory.getAbsolutePath() );
+        }
+
+        if ( arguments != null )
+        {
+            for ( String argument : arguments )
+            {
+                cl.createArg().setValue( argument );
+            }
+        }
+
+        return cl;
+    }
+
+    public ExecutionResult executeShellCommand( File workingDirectory, String executable, String arguments, File output,
+                                                long idCommand, Map<String, String> environments )
+        throws Exception
+    {
+        Commandline cl = new Commandline();
+
+        Arg argument = cl.createArg();
+
+        argument.setLine( arguments );
+
+        return executeShellCommand( workingDirectory, executable, argument.getParts(), output, idCommand,
+                                    environments );
+    }
+
+    public ExecutionResult executeShellCommand( File workingDirectory, String executable, String[] arguments,
+                                                File output, long idCommand, Map<String, String> environments )
+        throws Exception
+    {
+        FileOutputConsumer fileConsumer = new FileOutputConsumer( output );
+        try
+        {
+            return executeShellCommand( workingDirectory, executable, arguments, fileConsumer, idCommand,
+                                        environments );
+        }
+        finally
+        {
+            fileConsumer.flush();
+            fileConsumer.close();
+        }
+    }
+
+    private static class IOConsumerWrapper
+        implements StreamConsumer
+    {
+        private OutputConsumer userConsumer;
+
+        public IOConsumerWrapper( OutputConsumer userConsumer )
+        {
+            this.userConsumer = userConsumer;
+        }
+
+        public void consumeLine( String line )
+        {
+            if ( userConsumer != null )
+            {
+                userConsumer.consume( line );
+            }
+        }
+    }
+
+    public ExecutionResult executeShellCommand( File workingDirectory, String executable, String[] arguments,
+                                                OutputConsumer io, long idCommand,
+                                                Map<String, String> environments )
+        throws Exception
+    {
+        Commandline cl = createCommandline( workingDirectory, executable, arguments, idCommand, environments );
+
+        log.info( "Executing: " + cl );
+        File clWorkDir = cl.getWorkingDirectory();
+        log.info( "Working directory: " + ( clWorkDir != null ? clWorkDir.getAbsolutePath() : "default" ) );
+        log.debug( "EnvironmentVariables " + Arrays.asList( cl.getEnvironmentVariables() ) );
+
+        StreamConsumer consumer = new IOConsumerWrapper( io );
+
+        int exitCode = runCommand( cl, consumer, consumer );
+
+        return new ExecutionResult( exitCode );
+    }
+
+    public void executeGoals( File workingDirectory, String executable, String goals, boolean interactive,
+                              String arguments, ReleaseResult relResult, Map<String, String> environments )
+        throws Exception
+    {
+        Commandline cl = new Commandline();
+
+        Arg argument = cl.createArg();
+
+        argument.setLine( arguments );
+
+        executeGoals( workingDirectory, executable, goals, interactive, argument.getParts(), relResult, environments );
+    }
+
+    public void executeGoals( File workingDirectory, String executable, String goals, boolean interactive,
+                              String[] arguments, ReleaseResult relResult, Map<String, String> environments )
+        throws Exception
+    {
+        if ( executable == null )
+        {
+            executable = "mvn";
+        }
+
+        Commandline cl = createCommandline( workingDirectory, executable, arguments, -1, environments );
+
+        if ( goals != null )
+        {
+            // accept both space and comma, so the old way still work
+            String[] tokens = StringUtils.split( goals, ", " );
+
+            for ( String token : tokens )
+            {
+                cl.createArg().setValue( token );
+            }
+        }
+
+        cl.createArg().setValue( "--no-plugin-updates" );
+
+        if ( !interactive )
+        {
+            cl.createArg().setValue( "--batch-mode" );
+        }
+
+        StreamConsumer stdOut = new TeeConsumer( System.out );
+
+        StreamConsumer stdErr = new TeeConsumer( System.err );
+
+        try
+        {
+            relResult.appendInfo( "Executing: " + cl.toString() );
+            log.info( "Executing: " + cl.toString() );
+
+            int result = runCommand( cl, stdOut, stdErr );
+
+            if ( result != 0 )
+            {
+                throw new MavenExecutorException( "Maven execution failed, exit code: \'" + result + "\'", result,
+                                                  stdOut.toString(), stdErr.toString() );
+            }
+        }
+        catch ( CommandLineException e )
+        {
+            throw new MavenExecutorException( "Can't run goal " + goals, stdOut.toString(), stdErr.toString(), e );
+        }
+        finally
+        {
+            relResult.appendOutput( stdOut.toString() );
+        }
+    }
+
+    public boolean isRunning( long idCommand )
+    {
+        boolean isIdRunning = running.contains( idCommand );
+        log.debug( "process running for id {}? {}", idCommand, isIdRunning );
+        return isIdRunning;
+    }
+
+    public void killProcess( long idCommand )
+    {
+        log.warn( "unsupported attempt to kill process for id {}", idCommand );
+    }
+
+    /**
+     * Handles all command executions for the helper, allowing it to track which commands are running.
+     * The process tracking functionality done here attempts to mimick functionality lost with the move to
+     * plexus-utils 3.0.15. The utility of this method depends on two assumptions:
+     * * Command execution is synchronous (the thread is blocked while the command executes)
+     * * The scope of this object is appropriate (singleton or otherwise)
+     *
+     * @param cli       the command to run, will be tracked by abstract pid set
+     * @param systemOut the stream handler for stdout from command
+     * @param systemErr the stream handler for stderr from command
+     * @return the exit code from the process
+     */
+    private int runCommand( Commandline cli, StreamConsumer systemOut, StreamConsumer systemErr )
+        throws CommandLineException
+    {
+        Long pid = cli.getPid();
+        try
+        {
+            running.add( pid );
+            return CommandLineUtils.executeCommandLine( cli, systemOut, systemErr );
+        }
+        finally
+        {
+            running.remove( pid );
+        }
+    }
+}
diff --git a/continuum-api/src/main/java/org/apache/continuum/utils/shell/ExecutionResult.java b/continuum-api/src/main/java/org/apache/continuum/utils/shell/ExecutionResult.java
new file mode 100644
index 0000000..65d6a06
--- /dev/null
+++ b/continuum-api/src/main/java/org/apache/continuum/utils/shell/ExecutionResult.java
@@ -0,0 +1,39 @@
+package org.apache.continuum.utils.shell;
+
+/*
+ * 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.
+ */
+
+/**
+ * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
+ * @version $Id$
+ */
+public class ExecutionResult
+{
+    private final int exitCode;
+
+    public ExecutionResult( int exitCode )
+    {
+        this.exitCode = exitCode;
+    }
+
+    public int getExitCode()
+    {
+        return exitCode;
+    }
+}
diff --git a/continuum-api/src/main/java/org/apache/continuum/utils/shell/FileOutputConsumer.java b/continuum-api/src/main/java/org/apache/continuum/utils/shell/FileOutputConsumer.java
new file mode 100644
index 0000000..b688910
--- /dev/null
+++ b/continuum-api/src/main/java/org/apache/continuum/utils/shell/FileOutputConsumer.java
@@ -0,0 +1,65 @@
+package org.apache.continuum.utils.shell;
+
+/*
+ * 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.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * Collects output to a file using a buffered writer. Unlike the list-based consumer, this should be safe to use when
+ * the output size is expected to be large.
+ */
+public class FileOutputConsumer
+    implements OutputConsumer
+{
+    private PrintWriter writer;
+
+    /**
+     * Creates a output consumer for the given file.
+     *
+     * @param outputFile the file to write the results to
+     * @throws IOException if there is a problem creating a file
+     */
+    public FileOutputConsumer( File outputFile )
+        throws IOException
+    {
+        this.writer = new PrintWriter( new FileWriter( outputFile ) );
+    }
+
+    public void consume( String line )
+    {
+        if ( writer != null )
+            writer.println( line );
+    }
+
+    public void flush()
+    {
+        if ( writer != null )
+            writer.flush();
+    }
+
+    public void close()
+    {
+        if ( writer != null )
+            writer.close();
+    }
+}
\ No newline at end of file
diff --git a/continuum-api/src/main/java/org/apache/continuum/utils/shell/ListOutputConsumer.java b/continuum-api/src/main/java/org/apache/continuum/utils/shell/ListOutputConsumer.java
new file mode 100644
index 0000000..714cd3a
--- /dev/null
+++ b/continuum-api/src/main/java/org/apache/continuum/utils/shell/ListOutputConsumer.java
@@ -0,0 +1,48 @@
+package org.apache.continuum.utils.shell;
+
+/*
+ * 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.List;
+
+/**
+ * Collects output into a list. Since all output is stored in memory simultaneously, it should not be used when expected
+ * output is large.
+ */
+public class ListOutputConsumer
+    implements OutputConsumer
+{
+    List<String> list;
+
+    public ListOutputConsumer()
+    {
+        list = new ArrayList<String>();
+    }
+
+    public void consume( String line )
+    {
+        list.add( line );
+    }
+
+    public List<String> getList()
+    {
+        return list;
+    }
+}
diff --git a/continuum-api/src/main/java/org/apache/continuum/utils/shell/LogOutputConsumer.java b/continuum-api/src/main/java/org/apache/continuum/utils/shell/LogOutputConsumer.java
new file mode 100644
index 0000000..f8a7ed7
--- /dev/null
+++ b/continuum-api/src/main/java/org/apache/continuum/utils/shell/LogOutputConsumer.java
@@ -0,0 +1,43 @@
+package org.apache.continuum.utils.shell;
+
+/*
+ * 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 org.slf4j.Logger;
+
+/**
+ * Collects output to a logger. Unlike the list-based consumer, this should be safe to use when the output size is
+ * expected to be large. It logs the output at level INFO.
+ */
+public class LogOutputConsumer
+    implements OutputConsumer
+{
+    private Logger log;
+
+    public LogOutputConsumer( Logger log )
+    {
+        this.log = log;
+    }
+
+    public void consume( String line )
+    {
+        if ( log != null )
+            log.info( line );
+    }
+}
diff --git a/continuum-api/src/main/java/org/apache/continuum/utils/shell/OutputConsumer.java b/continuum-api/src/main/java/org/apache/continuum/utils/shell/OutputConsumer.java
new file mode 100644
index 0000000..f47d4df
--- /dev/null
+++ b/continuum-api/src/main/java/org/apache/continuum/utils/shell/OutputConsumer.java
@@ -0,0 +1,29 @@
+package org.apache.continuum.utils.shell;
+
+/*
+ * 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.
+ */
+
+/**
+ * Interface for handling shell output.
+ * Created to avoid dependency on plexus's CommandLineUtils.
+ */
+public interface OutputConsumer
+{
+    void consume( String line );
+}
diff --git a/continuum-api/src/main/java/org/apache/continuum/utils/shell/ShellCommandHelper.java b/continuum-api/src/main/java/org/apache/continuum/utils/shell/ShellCommandHelper.java
new file mode 100644
index 0000000..a6451ba
--- /dev/null
+++ b/continuum-api/src/main/java/org/apache/continuum/utils/shell/ShellCommandHelper.java
@@ -0,0 +1,61 @@
+package org.apache.continuum.utils.shell;
+
+/*
+ * 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 org.apache.maven.shared.release.ReleaseResult;
+
+import java.io.File;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
+ * @version $Id$
+ */
+public interface ShellCommandHelper
+{
+    String ROLE = ShellCommandHelper.class.getName();
+
+    Properties getSystemEnvVars();
+
+    ExecutionResult executeShellCommand( File workingDirectory, String executable, String arguments, File output,
+                                         long idCommand, Map<String, String> environments )
+        throws Exception;
+
+    ExecutionResult executeShellCommand( File workingDirectory, String executable, String[] arguments, OutputConsumer io,
+                                         long idCommand, Map<String, String> environments )
+        throws Exception;
+
+    ExecutionResult executeShellCommand( File workingDirectory, String executable, String[] arguments, File output,
+                                         long idCommand, Map<String, String> environments )
+        throws Exception;
+
+    boolean isRunning( long idCommand );
+
+    void killProcess( long idCommand );
+
+    void executeGoals( File workingDirectory, String executable, String goals, boolean interactive, String arguments,
+                       ReleaseResult relResult, Map<String, String> environments )
+        throws Exception;
+
+    void executeGoals( File workingDirectory, String executable, String goals, boolean interactive, String[] arguments,
+                       ReleaseResult relResult, Map<String, String> environments )
+        throws Exception;
+}
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/Continuum.java b/continuum-api/src/main/java/org/apache/maven/continuum/Continuum.java
index f72c3ce..6ded512 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/Continuum.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/Continuum.java
@@ -19,21 +19,24 @@
  * under the License.
  */
 
-import java.io.File;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.continuum.model.release.ContinuumReleaseResult;
+import org.apache.continuum.buildagent.NoBuildAgentException;
+import org.apache.continuum.buildagent.NoBuildAgentInGroupException;
+import org.apache.continuum.builder.distributed.manager.DistributedBuildManager;
+import org.apache.continuum.buildmanager.BuildsManager;
+import org.apache.continuum.model.project.ProjectGroupSummary;
 import org.apache.continuum.model.project.ProjectScmRoot;
+import org.apache.continuum.model.release.ContinuumReleaseResult;
 import org.apache.continuum.purge.ContinuumPurgeManager;
 import org.apache.continuum.purge.PurgeConfigurationService;
+import org.apache.continuum.release.distributed.manager.DistributedReleaseManager;
 import org.apache.continuum.repository.RepositoryService;
 import org.apache.continuum.taskqueue.manager.TaskQueueManager;
+import org.apache.continuum.utils.build.BuildTrigger;
 import org.apache.maven.continuum.builddefinition.BuildDefinitionService;
 import org.apache.maven.continuum.configuration.ConfigurationService;
 import org.apache.maven.continuum.installation.InstallationService;
 import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.BuildQueue;
 import org.apache.maven.continuum.model.project.BuildResult;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.project.ProjectGroup;
@@ -43,7 +46,12 @@
 import org.apache.maven.continuum.profile.ProfileService;
 import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
 import org.apache.maven.continuum.release.ContinuumReleaseManager;
-import org.codehaus.plexus.util.dag.CycleDetectedException;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
 
 /**
  * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
@@ -58,18 +66,9 @@
     // Project Groups
     // ----------------------------------------------------------------------
 
-    public static final String DEFAULT_PROJECT_GROUP_GROUP_ID = "default";
-
     public ProjectGroup getProjectGroup( int projectGroupId )
         throws ContinuumException;
 
-    /**
-     * Get all {@link ProjectGroup}s and their {@link Project}s
-     *
-     * @return {@link Collection} &lt;{@link ProjectGroup}>
-     */
-    public Collection<ProjectGroup> getAllProjectGroupsWithProjects();
-
     public List<ProjectGroup> getAllProjectGroupsWithBuildDetails();
 
     public List<ProjectGroup> getAllProjectGroups();
@@ -102,7 +101,7 @@
         throws ContinuumException;
 
     public List<ProjectGroup> getAllProjectGroupsWithRepository( int repositoryId );
-    
+
     // ----------------------------------------------------------------------
     // Project
     // ----------------------------------------------------------------------
@@ -110,12 +109,13 @@
     void removeProject( int projectId )
         throws ContinuumException;
 
-    
+
     /**
-     * @deprecated
      * @param projectId
      * @throws ContinuumException
+     * @deprecated
      */
+    @Deprecated
     void checkoutProject( int projectId )
         throws ContinuumException;
 
@@ -125,11 +125,6 @@
     Project getProjectWithBuildDetails( int projectId )
         throws ContinuumException;
 
-    List<Project> getAllProjectsWithAllDetails( int start, int end );
-
-    Collection<Project> getAllProjects( int start, int end )
-        throws ContinuumException;
-
     Collection<Project> getProjects()
         throws ContinuumException;
 
@@ -140,67 +135,55 @@
 
     Map<Integer, BuildResult> getLatestBuildResults( int projectGroupId );
 
-    Map<Integer, BuildResult> getLatestBuildResults();
-
     Map<Integer, BuildResult> getBuildResultsInSuccess( int projectGroupId );
 
-    Map<Integer, BuildResult> getBuildResultsInSuccess();
+    Map<Integer, ProjectGroupSummary> getProjectsSummaryByGroups();
 
     // ----------------------------------------------------------------------
     // Building
     // ----------------------------------------------------------------------
 
-    List<Project> getProjectsInBuildOrder()
-        throws CycleDetectedException, ContinuumException;
-
     /**
      * take a collection of projects and sort for order
      *
      * @param projects
      * @return
-     * @throws CycleDetectedException
      */
-    List<Project> getProjectsInBuildOrder( Collection<Project> projects )
-        throws CycleDetectedException;
+    List<Project> getProjectsInBuildOrder( Collection<Project> projects );
 
-    void buildProjects()
-        throws ContinuumException;
-
-    void buildProjectsWithBuildDefinition( int buildDefinitionId )
-        throws ContinuumException;
+    void buildProjects( String username )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException;
 
     void buildProjectsWithBuildDefinition( List<Project> projects, List<BuildDefinition> bds )
-        throws ContinuumException;
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException;
 
     void buildProjectsWithBuildDefinition( List<Project> projects, int buildDefinitionId )
-        throws ContinuumException;
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException;
 
-    void buildProjects( int trigger )
-        throws ContinuumException;
-
-    void buildProjects( int trigger, int buildDefinitionId )
-        throws ContinuumException;
+    void buildProjects( BuildTrigger buildTrigger )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException;
 
     void buildProjects( Schedule schedule )
         throws ContinuumException;
 
-    void buildProject( int projectId )
-        throws ContinuumException;
+    void buildProject( int projectId, String username )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException;
 
-    void buildProject( int projectId, int trigger )
-        throws ContinuumException;
+    void buildProject( int projectId, BuildTrigger buildTrigger )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException;
 
-    void buildProjectWithBuildDefinition( int projectId, int buildDefinitionId )
-        throws ContinuumException;
+    void buildProjectWithBuildDefinition( int projectId, int buildDefinitionId, BuildTrigger buildTrigger )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException;
 
-    void buildProject( int projectId, int buildDefinitionId, int trigger )
-        throws ContinuumException;
+    void buildProject( int projectId, int buildDefinitionId, BuildTrigger buildTrigger )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException;
 
-    public void buildProjectGroup( int projectGroupId )
-        throws ContinuumException;
+    public void buildProjectGroup( int projectGroupId, BuildTrigger buildTrigger )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException;
 
-    public void buildProjectGroupWithBuildDefinition( int projectGroupId, int buildDefinitionId )
-        throws ContinuumException;
+    public void buildProjectGroupWithBuildDefinition( int projectGroupId, int buildDefinitionId,
+                                                      BuildTrigger buildTrigger )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException;
 
     // ----------------------------------------------------------------------
     // Build information
@@ -226,9 +209,9 @@
     void removeBuildResult( int buildId )
         throws ContinuumException;
 
-    List<ChangeSet> getChangesSinceLastUpdate( int projectId )
-        throws ContinuumException;
-    
+    List<BuildResult> getBuildResultsInRange( int projectGroupId, Date fromDate, Date toDate, int state,
+                                              String triggeredBy );
+
     // ----------------------------------------------------------------------
     // Projects
     // ----------------------------------------------------------------------
@@ -236,17 +219,6 @@
     /**
      * Add a project to the list of building projects (ant, shell,...)
      *
-     * @param project    the project to add
-     * @param executorId the id of an {@link org.apache.maven.continuum.execution.ContinuumBuildExecutor}, eg. <code>ant</code> or <code>shell</code>
-     * @return id of the project
-     * @throws ContinuumException
-     */
-    int addProject( Project project, String executorId )
-        throws ContinuumException;
-
-    /**
-     * Add a project to the list of building projects (ant, shell,...)
-     *
      * @param project        the project to add
      * @param executorId     the id of an {@link org.apache.maven.continuum.execution.ContinuumBuildExecutor}, eg. <code>ant</code> or <code>shell</code>
      * @param projectGroupId
@@ -346,40 +318,21 @@
     /**
      * Add a Maven 2 project to the list of projects.
      *
-     * @param metadataUrl              url of the pom.xml
-     * @param projectGroupId           id of the project group to use
-     * @param checkProtocol            check if the protocol is allowed, use false if the pom is uploaded
-     * @param useCredentialsCache      whether to use cached scm account credentials or not
-     * @param loadRecursiveProjects    if multi modules project record all projects (if false only root project added)
-     * @param buildDefintionTemplateId buildDefintionTemplateId
+     * @param metadataUrl               url of the pom.xml
+     * @param projectGroupId            id of the project group to use
+     * @param checkProtocol             check if the protocol is allowed, use false if the pom is uploaded
+     * @param useCredentialsCache       whether to use cached scm account credentials or not
+     * @param loadRecursiveProjects     if multi modules project record all projects (if false only root project added)
+     * @param buildDefintionTemplateId  buildDefintionTemplateId
+     * @param checkoutInSingleDirectory TODO
      * @return a holder with the projects, project groups and errors occurred during the project adding
      * @throws ContinuumException
      */
     public ContinuumProjectBuildingResult addMavenTwoProject( String metadataUrl, int projectGroupId,
                                                               boolean checkProtocol, boolean useCredentialsCache,
                                                               boolean loadRecursiveProjects,
-                                                              int buildDefintionTemplateId )
-        throws ContinuumException;
-
-    /**
-     * Add a Maven 1 project to the list of projects.
-     *
-     * @param metadataUrl url of the project.xml
-     * @return a holder with the projects, project groups and errors occurred during the project adding
-     * @throws ContinuumException
-     */
-    ContinuumProjectBuildingResult addMavenOneProject( String metadataUrl )
-        throws ContinuumException;
-
-    /**
-     * Add a Maven 1 project to the list of projects.
-     *
-     * @param metadataUrl   url of the project.xml
-     * @param checkProtocol check if the protocol is allowed, use false if the pom is uploaded
-     * @return a holder with the projects, project groups and errors occurred during the project adding
-     * @throws ContinuumException
-     */
-    ContinuumProjectBuildingResult addMavenOneProject( String metadataUrl, boolean checkProtocol )
+                                                              int buildDefintionTemplateId,
+                                                              boolean checkoutInSingleDirectory )
         throws ContinuumException;
 
     /**
@@ -473,18 +426,21 @@
     /**
      * @deprecated
      */
+    @Deprecated
     List<BuildDefinition> getBuildDefinitions( int projectId )
         throws ContinuumException;
 
     /**
      * @deprecated
      */
+    @Deprecated
     BuildDefinition getBuildDefinition( int projectId, int buildDefinitionId )
         throws ContinuumException;
 
     /**
      * @deprecated
      */
+    @Deprecated
     void removeBuildDefinition( int projectId, int buildDefinitionId )
         throws ContinuumException;
 
@@ -516,7 +472,6 @@
     BuildDefinition addBuildDefinitionToProject( int projectId, BuildDefinition buildDefinition )
         throws ContinuumException;
 
-
     BuildDefinition addBuildDefinitionToProjectGroup( int projectGroupId, BuildDefinition buildDefinition )
         throws ContinuumException;
 
@@ -563,6 +518,10 @@
     void removeSchedule( int scheduleId )
         throws ContinuumException;
 
+    void activePurgeSchedule( Schedule schedule );
+
+    void activeBuildDefinitionSchedule( Schedule schedule );
+
     // ----------------------------------------------------------------------
     // Working copy
     // ----------------------------------------------------------------------
@@ -606,7 +565,7 @@
     ContinuumPurgeManager getPurgeManager();
 
     PurgeConfigurationService getPurgeConfigurationService();
-    
+
     // ----------------------------------------------------------------------
     // Repository Service
     // ----------------------------------------------------------------------
@@ -631,9 +590,39 @@
     // ----------------------------------------------------------------------
     TaskQueueManager getTaskQueueManager();
 
+    // ----------------------------------------------------------------------
+    // Builds Manager
+    // ----------------------------------------------------------------------
+    BuildsManager getBuildsManager();
+
+    // ----------------------------------------------------------------------
+    // Build Queue
+    // ----------------------------------------------------------------------
+
+    BuildQueue addBuildQueue( BuildQueue buildQueue )
+        throws ContinuumException;
+
+    BuildQueue getBuildQueue( int buildQueueId )
+        throws ContinuumException;
+
+    BuildQueue getBuildQueueByName( String buildQueueName )
+        throws ContinuumException;
+
+    void removeBuildQueue( BuildQueue buildQueue )
+        throws ContinuumException;
+
+    BuildQueue storeBuildQueue( BuildQueue buildQueue )
+        throws ContinuumException;
+
+    List<BuildQueue> getAllBuildQueues()
+        throws ContinuumException;
+
     public void startup()
         throws ContinuumException;
-    
+
+    ContinuumReleaseResult addContinuumReleaseResult( int projectId, String releaseId, String releaseType )
+        throws ContinuumException;
+
     ContinuumReleaseResult addContinuumReleaseResult( ContinuumReleaseResult releaseResult )
         throws ContinuumException;
 
@@ -649,7 +638,11 @@
 
     ContinuumReleaseResult getContinuumReleaseResult( int projectId, String releaseGoal, long startTime, long endTime )
         throws ContinuumException;
-    
+
     String getReleaseOutput( int releaseResultId )
         throws ContinuumException;
+
+    DistributedBuildManager getDistributedBuildManager();
+
+    DistributedReleaseManager getDistributedReleaseManager();
 }
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/ContinuumException.java b/continuum-api/src/main/java/org/apache/maven/continuum/ContinuumException.java
index c06320d..28dbdd7 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/ContinuumException.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/ContinuumException.java
@@ -26,9 +26,9 @@
 public class ContinuumException
     extends Exception
 {
-	private static final long serialVersionUID = -5566747100823603618L;
+    private static final long serialVersionUID = -5566747100823603618L;
 
-	public ContinuumException( String message )
+    public ContinuumException( String message )
     {
         super( message );
     }
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/ContinuumRuntimeException.java b/continuum-api/src/main/java/org/apache/maven/continuum/ContinuumRuntimeException.java
index 1a1f393..d81ee7f 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/ContinuumRuntimeException.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/ContinuumRuntimeException.java
@@ -21,14 +21,15 @@
 
 /**
  * Exception thrown as a result of a Continuum programming error so that the user need not deal with it.
+ *
  * @version $Id$
  */
 public class ContinuumRuntimeException
     extends RuntimeException
 {
-	private static final long serialVersionUID = 2345304356025303153L;
+    private static final long serialVersionUID = 2345304356025303153L;
 
-	public ContinuumRuntimeException( String message, Exception cause )
+    public ContinuumRuntimeException( String message, Exception cause )
     {
         super( message, cause );
     }
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/build/settings/BuildSettingsConstants.java b/continuum-api/src/main/java/org/apache/maven/continuum/build/settings/BuildSettingsConstants.java
deleted file mode 100644
index 6477a8e..0000000
--- a/continuum-api/src/main/java/org/apache/maven/continuum/build/settings/BuildSettingsConstants.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package org.apache.maven.continuum.build.settings;
-
-/*
- * 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.
- */
-
-/**
- * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
- * @version $Id$
- */
-public class BuildSettingsConstants
-{
-    // ----------------------------------------------------------------------
-    // Notification
-    // ----------------------------------------------------------------------
-
-    public static final int NOTIFICATION_STRATEGY_ALWAYS = 0;
-
-    public static final int NOTIFICATION_STRATEGY_NEVER = 1;
-
-    public static final int NOTIFICATION_STRATEGY_ON_FAILURE = 2;
-
-    // ----------------------------------------------------------------------
-    // Labelling
-    // ----------------------------------------------------------------------
-
-    public static final int LABELLING_STRATEGY_ALWAYS = 0;
-
-    public static final int LABELLING_STRATEGY_NEVER = 0;
-
-    public static final int LABELLING_STRATEGY_ON_SUCCESS = 0;
-
-    // ----------------------------------------------------------------------
-    // Scm mode
-    // ----------------------------------------------------------------------
-
-    public static final int SCM_MODE_CLEAN_CHECKOUT = 0;
-
-    public static final int SCM_MODE_UPDATE = 1;
-
-    // ----------------------------------------------------------------------
-    // Cron scheduling
-    // ----------------------------------------------------------------------
-}
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/build/settings/SchedulesActivationException.java b/continuum-api/src/main/java/org/apache/maven/continuum/build/settings/SchedulesActivationException.java
index 9e9a433..cae20e8 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/build/settings/SchedulesActivationException.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/build/settings/SchedulesActivationException.java
@@ -27,11 +27,11 @@
     extends Exception
 {
     /**
-	 * 
-	 */
-	private static final long serialVersionUID = -7901082128754563858L;
+     *
+     */
+    private static final long serialVersionUID = -7901082128754563858L;
 
-	public SchedulesActivationException( String message )
+    public SchedulesActivationException( String message )
     {
         super( message );
     }
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/build/settings/SchedulesActivator.java b/continuum-api/src/main/java/org/apache/maven/continuum/build/settings/SchedulesActivator.java
index abf14af..a937a7d 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/build/settings/SchedulesActivator.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/build/settings/SchedulesActivator.java
@@ -50,10 +50,40 @@
         throws SchedulesActivationException;
 
     /**
+     * Activate schedule only for PurgeConfiguration associated.
+     *
+     * @throws SchedulesActivationException
+     */
+    void activatePurgeSchedule( Schedule schedule, Continuum continuum )
+        throws SchedulesActivationException;
+
+    /**
+     * Activate schedule only for BuildDefinitions associated.
+     *
+     * @throws SchedulesActivationException
+     */
+    void activateBuildSchedule( Schedule schedule, Continuum continuum )
+        throws SchedulesActivationException;
+
+    /**
      * Unactivate schedule by looking at the scheduling information contained within.
      *
      * @throws SchedulesActivationException
      */
     void unactivateSchedule( Schedule schedule, Continuum continuum )
         throws SchedulesActivationException;
+
+    /**
+     * Unactivate schedule purgeConfigurations if it is not in a purgeConfiguration.
+     */
+    void unactivateOrphanPurgeSchedule( Schedule schedule )
+        throws SchedulesActivationException;
+
+    /**
+     * Unactivate schedule buildDefinitions if it is not in a buildDefinition.
+     *
+     * @throws SchedulesActivationException
+     */
+    void unactivateOrphanBuildSchedule( Schedule schedule )
+        throws SchedulesActivationException;
 }
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/builddefinition/BuildDefinitionService.java b/continuum-api/src/main/java/org/apache/maven/continuum/builddefinition/BuildDefinitionService.java
index f566dbd..b14a61f 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/builddefinition/BuildDefinitionService.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/builddefinition/BuildDefinitionService.java
@@ -1,3 +1,5 @@
+package org.apache.maven.continuum.builddefinition;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,9 +18,6 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.continuum.builddefinition;
-
-import java.util.List;
 
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.BuildDefinitionTemplate;
@@ -26,26 +25,30 @@
 import org.apache.maven.continuum.model.project.ProjectGroup;
 import org.apache.maven.continuum.store.ContinuumObjectNotFoundException;
 
+import java.util.List;
+
 /**
  * @author <a href="mailto:olamy@apache.org">olamy</a>
- * @since 15 sept. 07
  * @version $Id$
+ * @since 15 sept. 07
  */
 public interface BuildDefinitionService
 {
-    
+
     /**
      * @param buildDefinitionId
      * @return null if not in store
      * @throws BuildDefinitionServiceException
+     *
      */
     BuildDefinition getBuildDefinition( int buildDefinitionId )
         throws BuildDefinitionServiceException;
-    
-   /**
-    * @return List<BuildDefinition> all build defintions
-    * @throws BuildDefinitionServiceException
-    */
+
+    /**
+     * @return List<BuildDefinition> all build defintions
+     * @throws BuildDefinitionServiceException
+     *
+     */
     List<BuildDefinition> getAllBuildDefinitions()
         throws BuildDefinitionServiceException;
 
@@ -59,22 +62,25 @@
         throws BuildDefinitionServiceException;
 
     List<BuildDefinition> getAllTemplates()
-        throws BuildDefinitionServiceException;    
-    
+        throws BuildDefinitionServiceException;
+
     /**
      * @param buildDefinition
      * @return clone of {@link BuildDefinition} template/continuumDefault set to false
      */
     BuildDefinition cloneBuildDefinition( BuildDefinition buildDefinition );
-    
+
+    boolean isBuildDefinitionInUse( BuildDefinition buildDefinition )
+        throws BuildDefinitionServiceException;
+
     // ------------------------------------------------------
     //  BuildDefinitionTemplate
     // ------------------------------------------------------
 
     void addTemplateInProject( int buildDefinitionTemplateId, Project project )
         throws BuildDefinitionServiceException;
-    
-    
+
+
     List<BuildDefinitionTemplate> getAllBuildDefinitionTemplate()
         throws BuildDefinitionServiceException;
 
@@ -115,7 +121,7 @@
 
     public List<BuildDefinitionTemplate> getBuildDefinitionTemplatesWithType( String type )
         throws BuildDefinitionServiceException;
-    
+
     public ProjectGroup addBuildDefinitionTemplateToProjectGroup( int projectGroupId,
                                                                   BuildDefinitionTemplate buildDefinitionTemplate )
         throws BuildDefinitionServiceException, ContinuumObjectNotFoundException;
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/builddefinition/BuildDefinitionServiceException.java b/continuum-api/src/main/java/org/apache/maven/continuum/builddefinition/BuildDefinitionServiceException.java
index 47ed68f..f917a8f 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/builddefinition/BuildDefinitionServiceException.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/builddefinition/BuildDefinitionServiceException.java
@@ -1,3 +1,5 @@
+package org.apache.maven.continuum.builddefinition;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,20 +18,19 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.continuum.builddefinition;
 
 /**
  * @author <a href="mailto:olamy@apache.org">olamy</a>
- * @since 15 sept. 07
  * @version $Id$
+ * @since 15 sept. 07
  */
 public class BuildDefinitionServiceException
     extends Exception
 {
-	private static final long serialVersionUID = -399833410192238226L;
+    private static final long serialVersionUID = -399833410192238226L;
 
-	/**
-     * 
+    /**
+     *
      */
     public BuildDefinitionServiceException()
     {
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/builddefinition/BuildDefinitionUpdatePolicyConstants.java b/continuum-api/src/main/java/org/apache/maven/continuum/builddefinition/BuildDefinitionUpdatePolicyConstants.java
new file mode 100644
index 0000000..9a83d93
--- /dev/null
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/builddefinition/BuildDefinitionUpdatePolicyConstants.java
@@ -0,0 +1,34 @@
+package org.apache.maven.continuum.builddefinition;
+
+/*
+ * 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.
+ */
+
+/**
+ * @author Jose Morales Martinez
+ * @version $Id$
+ */
+public class BuildDefinitionUpdatePolicyConstants
+{
+
+    public static final int UPDATE_DESCRIPTION_ALWAYS = 0;
+
+    public static final int UPDATE_DESCRIPTION_NEVER = 1;
+
+    public static final int UPDATE_DESCRIPTION_ONLY_FOR_NEW_POM = 2;
+}
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/configuration/ConfigurationException.java b/continuum-api/src/main/java/org/apache/maven/continuum/configuration/ConfigurationException.java
index e33afea..4326007 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/configuration/ConfigurationException.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/configuration/ConfigurationException.java
@@ -26,9 +26,9 @@
 public class ConfigurationException
     extends Exception
 {
-	private static final long serialVersionUID = 5598659641431851660L;
+    private static final long serialVersionUID = 5598659641431851660L;
 
-	public ConfigurationException( String message )
+    public ConfigurationException( String message )
     {
         super( message );
     }
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/configuration/ConfigurationLoadingException.java b/continuum-api/src/main/java/org/apache/maven/continuum/configuration/ConfigurationLoadingException.java
index 546d64d..688c70f 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/configuration/ConfigurationLoadingException.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/configuration/ConfigurationLoadingException.java
@@ -26,9 +26,9 @@
 public class ConfigurationLoadingException
     extends Exception
 {
-	private static final long serialVersionUID = -8836376517389252165L;
+    private static final long serialVersionUID = -8836376517389252165L;
 
-	public ConfigurationLoadingException( String message )
+    public ConfigurationLoadingException( String message )
     {
         super( message );
     }
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/configuration/ConfigurationService.java b/continuum-api/src/main/java/org/apache/maven/continuum/configuration/ConfigurationService.java
index 2c3be48..4f203c1 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/configuration/ConfigurationService.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/configuration/ConfigurationService.java
@@ -19,8 +19,11 @@
  * under the License.
  */
 
+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;
 import org.apache.maven.continuum.store.ContinuumStoreException;
 
@@ -37,6 +40,8 @@
 
     public static final String DEFAULT_SCHEDULE_NAME = "DEFAULT_SCHEDULE";
 
+    public static final String DEFAULT_BUILD_QUEUE_NAME = "DEFAULT_BUILD_QUEUE";
+
     // ----------------------------------------------------------------------
     //
     // ----------------------------------------------------------------------
@@ -73,19 +78,26 @@
 
     File getTestReportsDirectory( int buildId, int projectId )
         throws ConfigurationException;
-    
+
     File getReleaseOutputDirectory();
-    
+
     void setReleaseOutputDirectory( File releaseOutputDirectory );
-    
+
     File getReleaseOutputDirectory( int projectGroupId );
-    
+
     File getReleaseOutputFile( int projectGroupId, String releaseName )
         throws ConfigurationException;
 
     String getReleaseOutput( int projectGroupId, String releaseName )
         throws ConfigurationException;
 
+    int getNumberOfBuildsInParallel();
+
+    void setNumberOfBuildsInParallel( int num );
+
+    BuildQueue getDefaultBuildQueue()
+        throws BuildQueueServiceException;
+
     List<BuildAgentConfiguration> getBuildAgents();
 
     void addBuildAgent( BuildAgentConfiguration buildAgent )
@@ -99,6 +111,33 @@
 
     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 );
+
+    void setSharedSecretPassword( String sharedSecretPassword );
+
+    String getSharedSecretPassword();
+
     // ----------------------------------------------------------------------
     //
     // ----------------------------------------------------------------------
@@ -118,5 +157,6 @@
         throws ConfigurationStoringException, ContinuumConfigurationException;
 
     Schedule getDefaultSchedule()
-        throws ContinuumStoreException, ConfigurationLoadingException, ContinuumConfigurationException;
+        throws ContinuumStoreException, ConfigurationLoadingException, ContinuumConfigurationException,
+        BuildQueueServiceException;
 }
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/configuration/ConfigurationStoringException.java b/continuum-api/src/main/java/org/apache/maven/continuum/configuration/ConfigurationStoringException.java
index b55f127..3a31711 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/configuration/ConfigurationStoringException.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/configuration/ConfigurationStoringException.java
@@ -26,9 +26,9 @@
 public class ConfigurationStoringException
     extends Exception
 {
-	private static final long serialVersionUID = -421385426351064628L;
+    private static final long serialVersionUID = -421385426351064628L;
 
-	public ConfigurationStoringException( String message )
+    public ConfigurationStoringException( String message )
     {
         super( message );
     }
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/execution/ContinuumBuildCancelledException.java b/continuum-api/src/main/java/org/apache/maven/continuum/execution/ContinuumBuildCancelledException.java
index 6976b52..2a47e95 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/execution/ContinuumBuildCancelledException.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/execution/ContinuumBuildCancelledException.java
@@ -26,9 +26,9 @@
 public class ContinuumBuildCancelledException
     extends ContinuumBuildExecutorException
 {
-	private static final long serialVersionUID = 6658199253278756183L;
+    private static final long serialVersionUID = 6658199253278756183L;
 
-	public ContinuumBuildCancelledException( String message )
+    public ContinuumBuildCancelledException( String message )
     {
         super( message );
     }
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/execution/ContinuumBuildExecutionResult.java b/continuum-api/src/main/java/org/apache/maven/continuum/execution/ContinuumBuildExecutionResult.java
index f4f685e..b76ccbb 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/execution/ContinuumBuildExecutionResult.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/execution/ContinuumBuildExecutionResult.java
@@ -27,9 +27,9 @@
  */
 public class ContinuumBuildExecutionResult
 {
-    private File output;
+    private final File output;
 
-    private int exitCode;
+    private final int exitCode;
 
     public ContinuumBuildExecutionResult( File output, int exitCode )
     {
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/execution/ContinuumBuildExecutor.java b/continuum-api/src/main/java/org/apache/maven/continuum/execution/ContinuumBuildExecutor.java
index 3a2e7ec..90bbd8f 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/execution/ContinuumBuildExecutor.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/execution/ContinuumBuildExecutor.java
@@ -23,6 +23,7 @@
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.scm.ChangeSet;
+import org.apache.maven.continuum.model.scm.ScmResult;
 
 import java.io.File;
 import java.util.List;
@@ -36,11 +37,13 @@
     String ROLE = ContinuumBuildExecutor.class.getName();
 
     // TODO: stream the build output
-    ContinuumBuildExecutionResult build( Project project, BuildDefinition buildDefinition, File buildOutput )
+    ContinuumBuildExecutionResult build( Project project, BuildDefinition buildDefinition, File buildOutput,
+                                         List<Project> projectsWithCommonScmRoot, String projectScmRootUrl )
         throws ContinuumBuildExecutorException;
 
     // TODO: rename to be clearer
-    void updateProjectFromCheckOut( File workingDirectory, Project project, BuildDefinition buildDefinition )
+    void updateProjectFromCheckOut( File workingDirectory, Project project, BuildDefinition buildDefinition,
+                                    ScmResult scmResult )
         throws ContinuumBuildExecutorException;
 
     boolean isBuilding( Project project );
@@ -52,7 +55,8 @@
         throws ContinuumBuildExecutorException;
 
     //TODO: Move as a plugin
-    void backupTestFiles( Project project, int buildId );
+    void backupTestFiles( Project project, int buildId, String projectScmRootUrl,
+                          List<Project> projectsWithCommonScmRoot );
 
     boolean shouldBuild( List<ChangeSet> changes, Project continuumProject, File workingDirectory,
                          BuildDefinition buildDefinition )
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/execution/ContinuumBuildExecutorConstants.java b/continuum-api/src/main/java/org/apache/maven/continuum/execution/ContinuumBuildExecutorConstants.java
index 5315877..1f9c81d 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/execution/ContinuumBuildExecutorConstants.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/execution/ContinuumBuildExecutorConstants.java
@@ -21,18 +21,29 @@
 
 /**
  * @author <a href="mailto:olamy at apache.org">olamy</a>
- * @since 11 sept. 07
  * @version $Id$
+ * @since 11 sept. 07
  */
 public class ContinuumBuildExecutorConstants
 {
-    
+
     public static final String MAVEN_TWO_BUILD_EXECUTOR = "maven2";
-    
+
     public static final String MAVEN_ONE_BUILD_EXECUTOR = "maven-1";
-    
+
     public static final String ANT_BUILD_EXECUTOR = "ant";
-    
+
     public static final String SHELL_BUILD_EXECUTOR = "shell";
+    
+    /**
+     * Determines whether the executor type is an m1 or m2 build.
+     * 
+     * @param type
+     * @return true if the excutor type will result in a maven 1 or 2+ build.
+     */
+    public static boolean isMaven( String type )
+    {
+        return MAVEN_ONE_BUILD_EXECUTOR.equals( type ) || MAVEN_TWO_BUILD_EXECUTOR.equals( type );
+    }
 
 }
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/execution/ContinuumBuildExecutorException.java b/continuum-api/src/main/java/org/apache/maven/continuum/execution/ContinuumBuildExecutorException.java
index 9a3fbdc..642010f 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/execution/ContinuumBuildExecutorException.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/execution/ContinuumBuildExecutorException.java
@@ -26,9 +26,9 @@
 public class ContinuumBuildExecutorException
     extends Exception
 {
-	private static final long serialVersionUID = 8536807061085844707L;
+    private static final long serialVersionUID = 8536807061085844707L;
 
-	public ContinuumBuildExecutorException( String message )
+    public ContinuumBuildExecutorException( String message )
     {
         super( message );
     }
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/initialization/ContinuumInitializationException.java b/continuum-api/src/main/java/org/apache/maven/continuum/initialization/ContinuumInitializationException.java
index 2b6a93e..55b8b49 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/initialization/ContinuumInitializationException.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/initialization/ContinuumInitializationException.java
@@ -26,9 +26,9 @@
 public class ContinuumInitializationException
     extends Exception
 {
-	private static final long serialVersionUID = 7629046230318917696L;
+    private static final long serialVersionUID = 7629046230318917696L;
 
-	public ContinuumInitializationException( String message )
+    public ContinuumInitializationException( String message )
     {
         super( message );
     }
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/initialization/ContinuumInitializer.java b/continuum-api/src/main/java/org/apache/maven/continuum/initialization/ContinuumInitializer.java
index 867c158..11bd49b 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/initialization/ContinuumInitializer.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/initialization/ContinuumInitializer.java
@@ -1,6 +1,5 @@
 package org.apache.maven.continuum.initialization;
 
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -26,6 +25,8 @@
  */
 public interface ContinuumInitializer
 {
+    String DEFAULT_PROJECT_GROUP_GROUP_ID = "default";
+
     String ROLE = ContinuumInitializer.class.getName();
 
     void initialize()
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/installation/AlreadyExistsInstallationException.java b/continuum-api/src/main/java/org/apache/maven/continuum/installation/AlreadyExistsInstallationException.java
index 42c31e6..03a896a 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/installation/AlreadyExistsInstallationException.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/installation/AlreadyExistsInstallationException.java
@@ -1,3 +1,5 @@
+package org.apache.maven.continuum.installation;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,22 +18,20 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.continuum.installation;
 
 import org.apache.maven.continuum.ContinuumException;
 
 /**
  * @author <a href="mailto:olamy@apache.org">olamy</a>
- * @since 9 mai 2008
  * @version $Id$
  * @since 1.2
  */
 public class AlreadyExistsInstallationException
     extends ContinuumException
 {
-	private static final long serialVersionUID = -7673670059441370868L;
+    private static final long serialVersionUID = -7673670059441370868L;
 
-	/**
+    /**
      * @param message
      */
     public AlreadyExistsInstallationException( String message )
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/installation/InstallationException.java b/continuum-api/src/main/java/org/apache/maven/continuum/installation/InstallationException.java
index f4acbf8..9f8f3cb 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/installation/InstallationException.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/installation/InstallationException.java
@@ -1,23 +1,24 @@
 package org.apache.maven.continuum.installation;
 
 /*
-* 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.
-*/
+ * 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.
+ */
+
 /**
  * @author <a href="mailto:olamy@codehaus.org">olamy</a>
  * @version $Id$
@@ -26,9 +27,9 @@
 public class InstallationException
     extends Exception
 {
-	private static final long serialVersionUID = 5055136446336281496L;
+    private static final long serialVersionUID = 5055136446336281496L;
 
-	public InstallationException( String message )
+    public InstallationException( String message )
     {
         super( message );
     }
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/installation/InstallationService.java b/continuum-api/src/main/java/org/apache/maven/continuum/installation/InstallationService.java
index 156916d..6fc6c9d 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/installation/InstallationService.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/installation/InstallationService.java
@@ -19,13 +19,13 @@
  * under the License.
  */
 
-import java.util.List;
-
 import org.apache.maven.continuum.execution.ExecutorConfigurator;
 import org.apache.maven.continuum.model.system.Installation;
 import org.apache.maven.continuum.model.system.Profile;
 import org.apache.maven.continuum.profile.AlreadyExistsProfileException;
 
+import java.util.List;
+
 /**
  * @author <a href="mailto:olamy@codehaus.org">olamy</a>
  * @version $Id$
@@ -60,6 +60,9 @@
     public Installation getInstallation( int installationId )
         throws InstallationException;
 
+    public Installation getInstallation( String installationName )
+        throws InstallationException;
+
     public List<Installation> getAllInstallations()
         throws InstallationException;
 
@@ -77,14 +80,14 @@
      * @return output of JAVA_HOME/bin/java -version (JAVA_HOME = installation.getVarValue()
      * @throws InstallationException
      */
-    public List<String> getJdkInformations( Installation installation )
+    public List<String> getJavaVersionInfo( Installation installation )
         throws InstallationException;
 
     /**
      * @return output of JAVA_HOME/bin/java -version
      * @throws InstallationException
      */
-    public List<String> getDefaultJdkInformations()
+    public List<String> getDefaultJavaVersionInfo()
         throws InstallationException;
 
     /**
@@ -93,7 +96,8 @@
      * @return the cli output of $path/ec.relativePath.ec.executable ec.versionArgument
      * @throws InstallationException
      */
-    public List<String> getExecutorConfiguratorVersion( String path, ExecutorConfigurator executorConfigurator, Profile profile )
+    public List<String> getExecutorVersionInfo( String path, ExecutorConfigurator executorConfigurator,
+                                                Profile profile )
         throws InstallationException;
 
 }
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/profile/AlreadyExistsProfileException.java b/continuum-api/src/main/java/org/apache/maven/continuum/profile/AlreadyExistsProfileException.java
index 8be1a9e..6107bbe 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/profile/AlreadyExistsProfileException.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/profile/AlreadyExistsProfileException.java
@@ -1,3 +1,5 @@
+package org.apache.maven.continuum.profile;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,22 +18,20 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.continuum.profile;
 
 import org.apache.maven.continuum.ContinuumException;
 
 /**
  * @author <a href="mailto:olamy@apache.org">olamy</a>
- * @since 9 mai 2008
  * @version $Id$
  * @since 1.2
  */
 public class AlreadyExistsProfileException
     extends ContinuumException
 {
-	private static final long serialVersionUID = -3827218055154032672L;
+    private static final long serialVersionUID = -3827218055154032672L;
 
-	/**
+    /**
      * @param message
      */
     public AlreadyExistsProfileException( String message )
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/profile/ProfileException.java b/continuum-api/src/main/java/org/apache/maven/continuum/profile/ProfileException.java
index 9432d1b..a05b841 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/profile/ProfileException.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/profile/ProfileException.java
@@ -29,9 +29,9 @@
 public class ProfileException
     extends ContinuumException
 {
-	private static final long serialVersionUID = 7775067763191224320L;
+    private static final long serialVersionUID = 7775067763191224320L;
 
-	public ProfileException( String message, Throwable throwable )
+    public ProfileException( String message, Throwable throwable )
     {
         super( message, throwable );
     }
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/profile/ProfileService.java b/continuum-api/src/main/java/org/apache/maven/continuum/profile/ProfileService.java
index 61258d3..a9aa510 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/profile/ProfileService.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/profile/ProfileService.java
@@ -69,10 +69,10 @@
 
     public void addEnvVarInProfile( Profile profile, Installation envVar )
         throws ProfileException;
-    
+
     public void addInstallationInProfile( Profile profile, Installation installation )
         throws ProfileException;
-    
+
     /**
      * @param profile
      * @param installation
@@ -81,7 +81,10 @@
      */
     public void removeInstallationFromProfile( Profile profile, Installation installation )
         throws ProfileException;
-    
+
     public Profile getProfileWithName( String profileName )
         throws ProfileException;
+
+    public boolean alreadyExistsProfileName( Profile profile )
+        throws ProfileException;
 }
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/project/builder/ContinuumProjectBuilder.java b/continuum-api/src/main/java/org/apache/maven/continuum/project/builder/ContinuumProjectBuilder.java
index 1caa092..8042c5e 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/project/builder/ContinuumProjectBuilder.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/project/builder/ContinuumProjectBuilder.java
@@ -19,10 +19,10 @@
  * under the License.
  */
 
-import java.net.URL;
-
 import org.apache.maven.continuum.model.project.BuildDefinitionTemplate;
 
+import java.net.URL;
+
 /**
  * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
  * @version $Id$
@@ -35,12 +35,21 @@
         throws ContinuumProjectBuilderException;
 
     ContinuumProjectBuildingResult buildProjectsFromMetadata( URL url, String username, String password,
-                                                              boolean recursiveProjects )
+                                                              boolean recursiveProjects,
+                                                              boolean checkoutInSingleDirectory )
         throws ContinuumProjectBuilderException;
 
     ContinuumProjectBuildingResult buildProjectsFromMetadata( URL url, String username, String password,
                                                               boolean recursiveProjects,
-                                                              BuildDefinitionTemplate buildDefinitionTemplate )
+                                                              BuildDefinitionTemplate buildDefinitionTemplate,
+                                                              boolean checkoutInSingleDirectory )
+        throws ContinuumProjectBuilderException;
+
+    ContinuumProjectBuildingResult buildProjectsFromMetadata( URL url, String username, String password,
+                                                              boolean recursiveProjects,
+                                                              BuildDefinitionTemplate buildDefinitionTemplate,
+                                                              boolean checkoutInSingleDirectory,
+                                                              int projectGroupId )
         throws ContinuumProjectBuilderException;
 
     BuildDefinitionTemplate getDefaultBuildDefinitionTemplate()
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/project/builder/ContinuumProjectBuilderException.java b/continuum-api/src/main/java/org/apache/maven/continuum/project/builder/ContinuumProjectBuilderException.java
index 462e9d0..2e1c7c6 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/project/builder/ContinuumProjectBuilderException.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/project/builder/ContinuumProjectBuilderException.java
@@ -26,9 +26,9 @@
 public class ContinuumProjectBuilderException
     extends Exception
 {
-	private static final long serialVersionUID = 2666582644236201183L;
+    private static final long serialVersionUID = 2666582644236201183L;
 
-	public ContinuumProjectBuilderException( String message )
+    public ContinuumProjectBuilderException( String message )
     {
         super( message );
     }
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/project/builder/ContinuumProjectBuildingResult.java b/continuum-api/src/main/java/org/apache/maven/continuum/project/builder/ContinuumProjectBuildingResult.java
index ee26f4b..a25ab05 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/project/builder/ContinuumProjectBuildingResult.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/project/builder/ContinuumProjectBuildingResult.java
@@ -19,15 +19,15 @@
  * under the License.
  */
 
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.project.ProjectGroup;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import org.apache.maven.continuum.model.project.Project;
-import org.apache.maven.continuum.model.project.ProjectGroup;
-
 /**
  * Holder for results of adding projects to Continuum. Contains added projects, project groups
  * and errors that happened during the add.
@@ -83,13 +83,17 @@
 
     public static final String ERROR_UNKNOWN = "add.project.unknown.error";
 
-    private List<Project> projects = new ArrayList<Project>();
+    public static final String ERROR_DUPLICATE_PROJECTS = "add.project.duplicate.error";
 
-    private List<ProjectGroup> projectGroups = new ArrayList<ProjectGroup>();
+    private final List<Project> projects = new ArrayList<Project>();
 
-    private Map<String, String> errors = new HashMap<String, String>();
-    
-    public static final String LS = System.getProperty( "line.separator" );
+    private final List<ProjectGroup> projectGroups = new ArrayList<ProjectGroup>();
+
+    private final Map<String, String> errors = new HashMap<String, String>();
+
+    private static final String LS = System.getProperty( "line.separator" );
+
+    private Project rootProject;
 
     public void addProject( Project project )
     {
@@ -184,11 +188,11 @@
     {
         return new ArrayList<String>( errors.keySet() );
     }
-    
-    public Map<String,String> getErrorsWithCause()
+
+    public Map<String, String> getErrorsWithCause()
     {
         return errors;
-    }    
+    }
 
     /**
      * Quick check to see if there are any errors.
@@ -220,4 +224,14 @@
         }
         return message.toString();
     }
+
+    public Project getRootProject()
+    {
+        return rootProject;
+    }
+
+    public void setRootProject( Project rootProject )
+    {
+        this.rootProject = rootProject;
+    }
 }
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/release/ContinuumReleaseException.java b/continuum-api/src/main/java/org/apache/maven/continuum/release/ContinuumReleaseException.java
index ec67431..8b52d60 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/release/ContinuumReleaseException.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/release/ContinuumReleaseException.java
@@ -26,9 +26,9 @@
 public class ContinuumReleaseException
     extends Exception
 {
-	private static final long serialVersionUID = 2167029372282426809L;
+    private static final long serialVersionUID = 2167029372282426809L;
 
-	public ContinuumReleaseException( String id )
+    public ContinuumReleaseException( String id )
     {
         super( id );
     }
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/release/ContinuumReleaseManager.java b/continuum-api/src/main/java/org/apache/maven/continuum/release/ContinuumReleaseManager.java
index f7f15e7..0cef3d4 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/release/ContinuumReleaseManager.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/release/ContinuumReleaseManager.java
@@ -19,9 +19,12 @@
  * under the License.
  */
 
+import org.apache.continuum.model.release.ReleaseListenerSummary;
 import org.apache.continuum.model.repository.LocalRepository;
+import org.apache.continuum.taskqueue.manager.TaskQueueManagerException;
 import org.apache.maven.continuum.model.project.Project;
-import org.apache.maven.continuum.model.system.Profile;
+import org.apache.maven.shared.release.config.ReleaseDescriptor;
+import org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor;
 
 import java.io.File;
 import java.util.Map;
@@ -46,13 +49,15 @@
      * @param releaseVersions
      * @param developmentVersions
      * @param listener
+     * @param workingDirectory
      * @return
      * @throws ContinuumReleaseException
      */
-    String prepare( Project project, Properties releaseProperties, Map releaseVersions, Map developmentVersions,
-                    ContinuumReleaseManagerListener listener )
+    String prepare( Project project, Properties releaseProperties, Map<String, String> releaseVersions,
+                    Map<String, String> developmentVersions, ContinuumReleaseManagerListener listener,
+                    String workingDirectory )
         throws ContinuumReleaseException;
-    
+
     /**
      * Prepare a project for release
      *
@@ -61,12 +66,15 @@
      * @param releaseVersions
      * @param developmentVersions
      * @param listener
-     * @param profile
+     * @param workingDirectory
+     * @param environments
+     * @param executable
      * @return
      * @throws ContinuumReleaseException
      */
-    String prepare( Project project, Properties releaseProperties, Map releaseVersions, Map developmentVersions,
-                    ContinuumReleaseManagerListener listener, Profile profile )
+    String prepare( Project project, Properties releaseProperties, Map<String, String> releaseVersions,
+                    Map<String, String> developmentVersions, ContinuumReleaseManagerListener listener,
+                    String workingDirectory, Map<String, String> environments, String executable )
         throws ContinuumReleaseException;
 
     /**
@@ -76,9 +84,11 @@
      * @param buildDirectory
      * @param goals
      * @param useReleaseProfile
+     * @param listener
      * @throws ContinuumReleaseException
+     * @deprecated to remove as not used anymore
      */
-    void perform( String releaseId, File buildDirectory, String goals, boolean useReleaseProfile,
+    void perform( String releaseId, File buildDirectory, String goals, String arguments, boolean useReleaseProfile,
                   ContinuumReleaseManagerListener listener )
         throws ContinuumReleaseException;
 
@@ -92,11 +102,29 @@
      * @param useReleaseProfile
      * @param listener
      * @throws ContinuumReleaseException
+     * @deprecated to remove as not used anymore
      */
-    void perform( String releaseId, String workingDirectory, File buildDirectory, String goals,
+    void perform( String releaseId, String workingDirectory, File buildDirectory, String goals, String arguments,
                   boolean useReleaseProfile, ContinuumReleaseManagerListener listener )
         throws ContinuumReleaseException;
 
+
+    /**
+     * FIXME use a bean to replace such very huge parameter number (ContinuumReleaseRequest)
+     *
+     * @param releaseId
+     * @param buildDirectory
+     * @param goals
+     * @param arguments
+     * @param useReleaseProfile
+     * @param listener
+     * @param repository
+     * @throws ContinuumReleaseException
+     */
+    void perform( String releaseId, File buildDirectory, String goals, String arguments, boolean useReleaseProfile,
+                  ContinuumReleaseManagerListener listener, LocalRepository repository )
+        throws ContinuumReleaseException;
+
     /**
      * Rollback changes made by a previous release.
      *
@@ -105,18 +133,67 @@
      * @param listener
      * @throws ContinuumReleaseException
      */
-    public void rollback( String releaseId, String workingDirectory, ContinuumReleaseManagerListener listener )
+    void rollback( String releaseId, String workingDirectory, ContinuumReleaseManagerListener listener )
         throws ContinuumReleaseException;
 
-    Map getPreparedReleases();
+    Map<String, ReleaseDescriptor> getPreparedReleases();
+
+    Map<String, String> getPreparedReleasesForProject( String groupId, String artifactId );
 
     Map getReleaseResults();
 
     Map getListeners();
-    
-    void perform( String releaseId, File buildDirectory, String goals, boolean useReleaseProfile,
-                  ContinuumReleaseManagerListener listener, LocalRepository repository )
-        throws ContinuumReleaseException;
 
-    Map<String, String> getEnvironments( Profile profile );
+
+    /**
+     * Clean up the tagname to respect the scm provider policy.
+     *
+     * @param scmUrl  The scm url
+     * @param tagName The tag name
+     * @return The cleaned tag name
+     */
+    String sanitizeTagName( String scmUrl, String tagName )
+        throws Exception;
+
+    /**
+     * @param releaseId
+     * @return
+     */
+    ReleaseListenerSummary getListener( String releaseId );
+
+    /**
+     * Determines if there is an ongoing release
+     *
+     * @return true if there is an ongoing release; false otherwise
+     * @throws Exception if unable to determine if release is ongoing
+     */
+    boolean isExecutingRelease()
+        throws Exception;
+
+    /**
+     * Retrieve the Release TaskQueueExecutor instance
+     *
+     * @return Release TaskQueueExecutor instance
+     * @throws TaskQueueManagerException if unable to retrieve the Release TaskQueueExecutor instance
+     */
+    TaskQueueExecutor getPerformReleaseTaskQueueExecutor()
+        throws TaskQueueManagerException;
+
+    /**
+     * Retrieve the PrepareRelease TaskQueueExecutor instance
+     *
+     * @return PrepareRelease TaskQueueExecutor instance
+     * @throws TaskQueueManagerException if unable to retrieve the PrepareRelease TaskQueueExecutor instance
+     */
+    TaskQueueExecutor getPrepareReleaseTaskQueueExecutor()
+        throws TaskQueueManagerException;
+
+    /**
+     * Retrieve the RollbackRelease TaskQueueExecutor instance
+     *
+     * @return RollbackRelease TaskQueueExecutor instance
+     * @throws TaskQueueManagerException if unable to retrieve the RollbackRelease TaskQueueExecutor instance
+     */
+    TaskQueueExecutor getRollbackReleaseTaskQueueExecutor()
+        throws TaskQueueManagerException;
 }
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/release/ContinuumReleaseManagerListener.java b/continuum-api/src/main/java/org/apache/maven/continuum/release/ContinuumReleaseManagerListener.java
index 041fab3..01e269c 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/release/ContinuumReleaseManagerListener.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/release/ContinuumReleaseManagerListener.java
@@ -29,15 +29,19 @@
 {
     int INITIALIZED = 0, LISTENING = 1, FINISHED = 3;
 
-    List getCompletedPhases();
+    List<String> getCompletedPhases();
 
     String getInProgress();
 
     String getGoalName();
 
-    List getPhases();
+    List<String> getPhases();
 
     String getError();
 
     int getState();
+
+    String getUsername();
+
+    void setUsername( String username );
 }
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/store/ContinuumObjectNotFoundException.java b/continuum-api/src/main/java/org/apache/maven/continuum/store/ContinuumObjectNotFoundException.java
index 716305f..55a5df9 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/store/ContinuumObjectNotFoundException.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/store/ContinuumObjectNotFoundException.java
@@ -26,9 +26,9 @@
 public class ContinuumObjectNotFoundException
     extends ContinuumStoreException
 {
-	private static final long serialVersionUID = 6022595625968612620L;
+    private static final long serialVersionUID = 6022595625968612620L;
 
-	public ContinuumObjectNotFoundException( String message )
+    public ContinuumObjectNotFoundException( String message )
     {
         super( message );
     }
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/store/ContinuumStoreException.java b/continuum-api/src/main/java/org/apache/maven/continuum/store/ContinuumStoreException.java
index fd5c2fd..f570aff 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/store/ContinuumStoreException.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/store/ContinuumStoreException.java
@@ -26,9 +26,9 @@
 public class ContinuumStoreException
     extends Exception
 {
-	private static final long serialVersionUID = 5183507100399672781L;
+    private static final long serialVersionUID = 5183507100399672781L;
 
-	public ContinuumStoreException( String msg )
+    public ContinuumStoreException( String msg )
     {
         super( msg );
     }
diff --git a/continuum-api/src/main/java/org/apache/maven/continuum/utils/WorkingDirectoryService.java b/continuum-api/src/main/java/org/apache/maven/continuum/utils/WorkingDirectoryService.java
index 5caa5ba..4db8749 100644
--- a/continuum-api/src/main/java/org/apache/maven/continuum/utils/WorkingDirectoryService.java
+++ b/continuum-api/src/main/java/org/apache/maven/continuum/utils/WorkingDirectoryService.java
@@ -22,6 +22,7 @@
 import org.apache.maven.continuum.model.project.Project;
 
 import java.io.File;
+import java.util.List;
 
 /**
  * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
@@ -32,4 +33,10 @@
     String ROLE = WorkingDirectoryService.class.getName();
 
     File getWorkingDirectory( Project project );
+
+    File getWorkingDirectory( Project project, boolean shouldSet );
+
+    File getWorkingDirectory( Project project, String projectScmRootUrl, List<Project> projects );
+
+    File getWorkingDirectory( Project project, String projectScmRootUrl, List<Project> projects, boolean shouldSet );
 }
diff --git a/continuum-api/src/main/resources/META-INF/spring-context.xml b/continuum-api/src/main/resources/META-INF/spring-context.xml
new file mode 100644
index 0000000..617f49e
--- /dev/null
+++ b/continuum-api/src/main/resources/META-INF/spring-context.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+
+<!--
+  ~ 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.
+  -->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+           http://www.springframework.org/schema/context 
+           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
+
+  <context:annotation-config/>
+  <context:component-scan
+      base-package="org.apache.continuum.installation,org.apache.continuum.profile,
+                  org.apache.maven.continuum.configuration,org.apache.maven.continuum.utils,
+                  org.apache.continuum.utils.shell"/>
+
+  <bean id="shellCommandHelper" class="org.apache.continuum.utils.shell.DefaultShellCommandHelper"/>
+</beans>
\ No newline at end of file
diff --git a/continuum-api/src/test/java/org/apache/continuum/utils/ProjectSorterTest.java b/continuum-api/src/test/java/org/apache/continuum/utils/ProjectSorterTest.java
new file mode 100644
index 0000000..a7202dd
--- /dev/null
+++ b/continuum-api/src/test/java/org/apache/continuum/utils/ProjectSorterTest.java
@@ -0,0 +1,226 @@
+package org.apache.continuum.utils;
+
+/*
+ * 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 junit.framework.TestCase;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.project.ProjectDependency;
+import org.apache.maven.continuum.model.project.ProjectGroup;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:jmcconnell@apache.org">Jesse McConnell</a>
+ * @version $Id:$
+ */
+public class ProjectSorterTest
+    extends TestCase
+{
+
+    /**
+     * test basic three project tree (really a line in this case)
+     */
+    public void testBasicNestedProjectStructure()
+        throws Exception
+    {
+        List<Project> list = new ArrayList<Project>();
+
+        Project top = getNewProject( "top" );
+        list.add( top );
+
+        Project c1 = getNewProject( "c1" );
+        c1.setParent( generateProjectDependency( top ) );
+        list.add( c1 );
+
+        Project c2 = getNewProject( "c2" );
+        c2.setParent( generateProjectDependency( top ) );
+        c2.setDependencies( Collections.singletonList( generateProjectDependency( c1 ) ) );
+        list.add( c2 );
+
+        List<Project> sortedList = ProjectSorter.getSortedProjects( list, null );
+
+        assertNotNull( sortedList );
+
+        Project p1 = sortedList.get( 0 );
+        assertEquals( top.getArtifactId(), p1.getArtifactId() );
+        Project p2 = sortedList.get( 1 );
+        assertEquals( c1.getArtifactId(), p2.getArtifactId() );
+        Project p3 = sortedList.get( 2 );
+        assertEquals( c2.getArtifactId(), p3.getArtifactId() );
+    }
+
+    public void testNestedProjectStructureWithoutModulesDefinedInParentPom()
+        throws Exception
+    {
+        Project top = getNewProject( "top" );
+
+        Project war1 = getNewProject( "war1" );
+        war1.setParent( generateProjectDependency( top ) );
+
+        Project war2 = getNewProject( "war2" );
+        war2.setParent( generateProjectDependency( top ) );
+
+        Project ear1 = getNewProject( "ear1" );
+        ear1.setParent( generateProjectDependency( top ) );
+        List<ProjectDependency> deps = new ArrayList<ProjectDependency>();
+        deps.add( generateProjectDependency( war1 ) );
+        deps.add( generateProjectDependency( war2 ) );
+        ear1.setDependencies( deps );
+
+        List<Project> list = new ArrayList<Project>();
+
+        // We add projects in a random order to really check the project orter
+        list.add( top );
+        list.add( ear1 );
+        list.add( war1 );
+        list.add( war2 );
+
+        List<Project> sortedList = ProjectSorter.getSortedProjects( list, null );
+
+        assertNotNull( sortedList );
+
+        Project p1 = sortedList.get( 0 ); //top project must be the first
+        assertEquals( top.getArtifactId(), p1.getArtifactId() );
+        Project p4 = sortedList.get( 3 ); //ear1 project must be the latest
+        assertEquals( ear1.getArtifactId(), p4.getArtifactId() );
+    }
+
+    /**
+     * test project build order
+     * build order: B -> A -> D -> C -> E
+     *
+     * @throws Exception
+     */
+    public void testProjectBuildOrder()
+        throws Exception
+    {
+        List<Project> list = new ArrayList<Project>();
+
+        Project projectA = getNewProject( "A" );
+        Project projectB = getNewProject( "B" );
+        Project projectC = getNewProject( "C" );
+        Project projectD = getNewProject( "D" );
+        Project projectE = getNewProject( "E" );
+
+        projectA.setParent( generateProjectDependency( projectB ) );
+        projectE.setParent( generateProjectDependency( projectB ) );
+        projectC.setParent( generateProjectDependency( projectA ) );
+        projectC.setDependencies( Collections.singletonList( generateProjectDependency( projectD ) ) );
+        projectD.setParent( generateProjectDependency( projectA ) );
+
+        list.add( projectA );
+        list.add( projectB );
+        list.add( projectC );
+        list.add( projectD );
+        list.add( projectE );
+
+        List<Project> sortedList = ProjectSorter.getSortedProjects( list, null );
+        assertNotNull( sortedList );
+
+        List<Project> expectedList = new ArrayList<Project>();
+
+        expectedList.add( projectB );
+        expectedList.add( projectA );
+        expectedList.add( projectD );
+        expectedList.add( projectC );
+        expectedList.add( projectE );
+
+        for ( int i = 0; i < sortedList.size(); i++ )
+        {
+            Project sorted = sortedList.get( i );
+            Project expected = expectedList.get( i );
+            assertEquals( sorted.getArtifactId(), expected.getArtifactId() );
+        }
+    }
+
+    /**
+     * test one of the child projects not having the artifactId or groupId empty and working off the
+     * name instead
+     */
+    public void testIncompleteNestedProjectStructure()
+        throws Exception
+    {
+        List<Project> list = new ArrayList<Project>();
+
+        Project top = getNewProject( "top" );
+        list.add( top );
+
+        Project c1 = getIncompleteProject( "c1" );
+        c1.setParent( generateProjectDependency( top ) );
+        list.add( c1 );
+
+        Project c2 = getNewProject( "c2" );
+        c2.setParent( generateProjectDependency( top ) );
+        c2.setDependencies( Collections.singletonList( generateProjectDependency( c1 ) ) );
+        list.add( c2 );
+
+        List<Project> sortedList = ProjectSorter.getSortedProjects( list, null );
+
+        assertNotNull( sortedList );
+
+        Project p1 = sortedList.get( 0 );
+        assertEquals( top.getArtifactId(), p1.getArtifactId() );
+        Project p2 = sortedList.get( 1 );
+        assertEquals( c1.getArtifactId(), p2.getArtifactId() );
+        Project p3 = sortedList.get( 2 );
+        assertEquals( c2.getArtifactId(), p3.getArtifactId() );
+    }
+
+    /**
+     * project sorter can work with name replacing the artifactid and groupId
+     *
+     * @param projectId The project id
+     * @return The generated Project
+     */
+    private Project getIncompleteProject( String projectId )
+    {
+        Project project = new Project();
+        project.setName( "foo" + projectId );
+        project.setVersion( "v" + projectId );
+        project.setProjectGroup( new ProjectGroup() );
+
+        return project;
+    }
+
+    private Project getNewProject( String projectId )
+    {
+        Project project = new Project();
+        project.setArtifactId( "a" + projectId );
+        project.setGroupId( "g" + projectId );
+        project.setVersion( "v" + projectId );
+        project.setName( "n" + projectId );
+        project.setProjectGroup( new ProjectGroup() );
+
+        return project;
+    }
+
+    private ProjectDependency generateProjectDependency( Project project )
+    {
+        ProjectDependency dep = new ProjectDependency();
+        dep.setArtifactId( project.getArtifactId() );
+        dep.setGroupId( project.getGroupId() );
+        dep.setVersion( project.getVersion() );
+
+        return dep;
+    }
+
+}
diff --git a/continuum-api/src/test/java/org/apache/continuum/utils/shell/DefaultShellCommandHelperTest.java b/continuum-api/src/test/java/org/apache/continuum/utils/shell/DefaultShellCommandHelperTest.java
new file mode 100644
index 0000000..d1571ce
--- /dev/null
+++ b/continuum-api/src/test/java/org/apache/continuum/utils/shell/DefaultShellCommandHelperTest.java
@@ -0,0 +1,119 @@
+package org.apache.continuum.utils.shell;
+
+/*
+ * 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 junit.framework.TestCase;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @see org.apache.continuum.utils.shell.DefaultShellCommandHelper
+ */
+public class DefaultShellCommandHelperTest
+    extends TestCase
+{
+    private static final Logger log = LoggerFactory.getLogger( DefaultShellCommandHelper.class );
+
+    private DefaultShellCommandHelper helper;
+
+    private String javaPath;
+
+    private String sleepClasspath;
+
+    public void setUp()
+    {
+        helper = new DefaultShellCommandHelper();
+
+        List<String> javaPathComponents =
+            Arrays.asList( new String[] { System.getProperty( "java.home" ), "bin", "java" } );
+        javaPath = StringUtils.join( javaPathComponents, File.separator );
+        sleepClasspath = System.getProperty( "sleepClasspath" );
+    }
+
+    public void tearDown()
+    {
+        helper = null;
+    }
+
+    /**
+     * To concurrently check the run status of a process.
+     */
+    private static class RunChecker
+        implements Runnable
+    {
+        ShellCommandHelper shellHelper;
+
+        long pid;
+
+        boolean wasRunning;
+
+        long sleepMillis;
+
+        public RunChecker( ShellCommandHelper shellHelper, long pid, long sleepMillis )
+        {
+            this.shellHelper = shellHelper;
+            this.pid = pid;
+            this.sleepMillis = sleepMillis;
+        }
+
+        public void run()
+        {
+            try
+            {
+                Thread.sleep( sleepMillis );
+                this.wasRunning = shellHelper.isRunning( pid );
+            }
+            catch ( InterruptedException e )
+            {
+                log.error( "run checker interrupted", e );
+            }
+        }
+    }
+
+    public void testIsRunning()
+        throws Exception
+    {
+        long virtualPid = 1, sleepMillis = 100;
+        RunChecker checker = new RunChecker( helper, virtualPid, sleepMillis );
+        String[] cmdArgs = { "-cp", sleepClasspath, Sleep.class.getCanonicalName(), "1" };
+
+        // Verify process isn't running initially
+        checker.run();
+        assertFalse( "Expected that command was not running", checker.wasRunning );
+
+        // Verify running status is true when running
+        Thread checkerThread = new Thread( checker );
+        checkerThread.start();
+
+        helper.executeShellCommand( null, javaPath, cmdArgs, new LogOutputConsumer( log ), virtualPid, null );
+        checkerThread.join();
+        assertTrue( "Expected that command was running", checker.wasRunning );
+
+        // Verify process isn't running after
+        checker.run();
+        assertFalse( "Expected that command was not running", checker.wasRunning );
+    }
+
+}
diff --git a/continuum-api/src/test/java/org/apache/continuum/utils/shell/Sleep.java b/continuum-api/src/test/java/org/apache/continuum/utils/shell/Sleep.java
new file mode 100644
index 0000000..9abbe93
--- /dev/null
+++ b/continuum-api/src/test/java/org/apache/continuum/utils/shell/Sleep.java
@@ -0,0 +1,39 @@
+package org.apache.continuum.utils.shell;
+
+/*
+ * 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.
+ */
+
+/**
+ * A portable program that sleeps. Useful for cross platform shell tests.
+ */
+public class Sleep
+{
+
+    public static void main( String[] args )
+        throws InterruptedException
+    {
+        if ( args.length != 1 )
+        {
+            System.err.printf( "usage: java %s <time-to-sleep-in-seconds>\n", Sleep.class.getName() );
+            System.exit( 1 );
+        }
+        int sleepTimeInMillis = Integer.valueOf( args[0] ) * 1000;
+        Thread.sleep( sleepTimeInMillis );
+    }
+}
diff --git a/continuum-artifact-manager/pom.xml b/continuum-artifact-manager/pom.xml
new file mode 100644
index 0000000..6fcdbd0
--- /dev/null
+++ b/continuum-artifact-manager/pom.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0"?>
+
+<!--
+  ~ 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.continuum</groupId>
+    <artifactId>continuum</artifactId>
+    <version>1.4.3</version>
+  </parent>
+  <artifactId>continuum-artifact-manager</artifactId>
+  <name>Continuum :: Replacement Artifact Manager</name>
+  <description>
+    Patched DefaultWagonManager for compatibility with plexus-spring
+  </description>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-artifact-manager</artifactId>
+      <scope>compile</scope>
+    </dependency>
+    <!-- Promoted transitive dependencies -->
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-repository-metadata</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-utils</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-artifact</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-container-default</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.wagon</groupId>
+      <artifactId>wagon-provider-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>backport-util-concurrent</groupId>
+      <artifactId>backport-util-concurrent</artifactId>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-shade-plugin</artifactId>
+        <version>2.3</version>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>shade</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <artifactSet>
+            <includes>
+              <include>org.apache.maven:maven-artifact-manager</include>
+            </includes>
+          </artifactSet>
+          <filters>
+            <filter>
+              <artifact>org.apache.maven:maven-artifact-manager</artifact>
+              <excludes>
+                <exclude>org/apache/maven/artifact/manager/DefaultWagonManager*</exclude>
+              </excludes>
+            </filter>
+          </filters>
+          <createDependencyReducedPom>false</createDependencyReducedPom>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-enforcer-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/continuum-artifact-manager/src/main/java/org/apache/maven/artifact/manager/DefaultWagonManager.java b/continuum-artifact-manager/src/main/java/org/apache/maven/artifact/manager/DefaultWagonManager.java
new file mode 100644
index 0000000..1b82503
--- /dev/null
+++ b/continuum-artifact-manager/src/main/java/org/apache/maven/artifact/manager/DefaultWagonManager.java
@@ -0,0 +1,1142 @@
+package org.apache.maven.artifact.manager;
+
+/*
+ * 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 org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.metadata.ArtifactMetadata;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
+import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
+import org.apache.maven.artifact.repository.DefaultArtifactRepository;
+import org.apache.maven.wagon.ConnectionException;
+import org.apache.maven.wagon.ResourceDoesNotExistException;
+import org.apache.maven.wagon.TransferFailedException;
+import org.apache.maven.wagon.UnsupportedProtocolException;
+import org.apache.maven.wagon.Wagon;
+import org.apache.maven.wagon.authentication.AuthenticationException;
+import org.apache.maven.wagon.authentication.AuthenticationInfo;
+import org.apache.maven.wagon.authorization.AuthorizationException;
+import org.apache.maven.wagon.events.TransferListener;
+import org.apache.maven.wagon.observers.ChecksumObserver;
+import org.apache.maven.wagon.proxy.ProxyInfo;
+import org.apache.maven.wagon.proxy.ProxyInfoProvider;
+import org.apache.maven.wagon.repository.Repository;
+import org.apache.maven.wagon.repository.RepositoryPermissions;
+import org.codehaus.plexus.PlexusConstants;
+import org.codehaus.plexus.PlexusContainer;
+import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
+import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+import org.codehaus.plexus.configuration.PlexusConfiguration;
+import org.codehaus.plexus.configuration.PlexusConfigurationException;
+import org.codehaus.plexus.context.Context;
+import org.codehaus.plexus.context.ContextException;
+import org.codehaus.plexus.logging.AbstractLogEnabled;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
+import org.codehaus.plexus.util.FileUtils;
+import org.codehaus.plexus.util.IOUtil;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.NoSuchAlgorithmException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+public class DefaultWagonManager
+    extends AbstractLogEnabled
+    implements WagonManager, Contextualizable, Initializable
+{
+    private static final String WILDCARD = "*";
+
+    private static final String EXTERNAL_WILDCARD = "external:*";
+
+    private static final String MAVEN_ARTIFACT_PROPERTIES = "META-INF/maven/org.apache.maven/maven-artifact/pom.properties";
+
+    private static final String WAGON_PROVIDER_CONFIGURATION = "wagonProvider";
+
+    private static int anonymousMirrorIdSeed = 0;
+
+    private PlexusContainer container;
+
+    // TODO: proxies, authentication and mirrors are via settings, and should come in via an alternate method - perhaps
+    // attached to ArtifactRepository before the method is called (so AR would be composed of WR, not inherit it)
+    private Map proxies = new HashMap();
+
+    private Map authenticationInfoMap = new HashMap();
+
+    private Map serverPermissionsMap = new HashMap();
+
+    //used LinkedMap to preserve the order.
+    private Map mirrors = new LinkedHashMap();
+
+    private Map<String, String> serverWagonProviderMap = new HashMap<String, String>();
+
+    private TransferListener downloadMonitor;
+
+    private boolean online = true;
+
+    private ArtifactRepositoryFactory repositoryFactory;
+
+    private boolean interactive = true;
+
+    private Map<String, PlexusContainer> availableWagons = new HashMap<String, PlexusContainer>();
+
+    private RepositoryPermissions defaultRepositoryPermissions;
+
+    private String httpUserAgent;
+
+    private WagonProviderMapping providerMapping = new DefaultWagonProviderMapping();
+
+    // TODO: this leaks the component in the public api - it is never released back to the container
+    public Wagon getWagon( Repository repository )
+        throws UnsupportedProtocolException, WagonConfigurationException
+    {
+        String protocol = repository.getProtocol();
+
+        if ( protocol == null )
+        {
+            throw new UnsupportedProtocolException( "The repository " + repository + " does not specify a protocol" );
+        }
+
+        Wagon wagon = getWagon( protocol, repository.getId() );
+
+        return wagon;
+    }
+
+    public Wagon getWagon( String protocol )
+        throws UnsupportedProtocolException
+    {
+        return getWagon( protocol, null );
+    }
+
+    private Wagon getWagon( String protocol, String repositoryId )
+        throws UnsupportedProtocolException
+    {
+        String hint = getWagonHint( protocol, repositoryId );
+        PlexusContainer container = getWagonContainer( hint );
+
+        Wagon wagon;
+        try
+        {
+            wagon = (Wagon) container.lookup( Wagon.ROLE, hint );
+        }
+        catch ( ComponentLookupException e1 )
+        {
+            throw new UnsupportedProtocolException(
+                "Cannot find wagon which supports the requested protocol: " + protocol, e1 );
+        }
+
+        wagon.setInteractive( interactive );
+
+        return wagon;
+    }
+
+    private String getWagonHint( String protocol, String repositoryId )
+    {
+        // TODO: Implement a better way to get the hint, via settings.xml or something.
+        String impl = null;
+
+        if ( repositoryId != null && serverWagonProviderMap.containsKey( repositoryId ) )
+        {
+            impl = serverWagonProviderMap.get( repositoryId );
+            getLogger().debug( "Using Wagon implementation " + impl + " from settings for server " + repositoryId );
+        }
+        else
+        {
+            impl = providerMapping.getWagonProvider( protocol );
+            if ( impl != null )
+            {
+                getLogger().debug( "Using Wagon implementation " + impl + " from default mapping for protocol " + protocol );
+            }
+        }
+
+        String hint;
+        if ( impl != null )
+        {
+            hint = protocol + "-" + impl;
+            PlexusContainer container = getWagonContainer( hint );
+            if ( container == null || !container.hasComponent( Wagon.ROLE, hint ) )
+            {
+                getLogger().debug(
+                    "Cannot find wagon for protocol-provider hint: '" + hint
+                        + "', configured for repository: '" + repositoryId + "'. Using protocol hint: '"
+                        + protocol + "' instead." );
+                hint = protocol;
+            }
+        }
+        else
+        {
+            hint = protocol;
+        }
+
+        return hint;
+    }
+
+    private PlexusContainer getWagonContainer( String hint )
+    {
+        PlexusContainer container = this.container;
+        if ( availableWagons.containsKey( hint ) )
+        {
+            container = availableWagons.get( hint );
+        }
+
+        return container;
+    }
+
+    public void putArtifact( File source,
+                             Artifact artifact,
+                             ArtifactRepository deploymentRepository )
+        throws TransferFailedException
+    {
+        putRemoteFile( deploymentRepository, source, deploymentRepository.pathOf( artifact ), downloadMonitor );
+    }
+
+    public void putArtifactMetadata( File source,
+                                     ArtifactMetadata artifactMetadata,
+                                     ArtifactRepository repository )
+        throws TransferFailedException
+    {
+        getLogger().info( "Uploading " + artifactMetadata );
+        putRemoteFile( repository, source, repository.pathOfRemoteRepositoryMetadata( artifactMetadata ), null );
+    }
+
+    private void putRemoteFile( ArtifactRepository repository,
+                                File source,
+                                String remotePath,
+                                TransferListener downloadMonitor )
+        throws TransferFailedException
+    {
+        failIfNotOnline();
+
+        String protocol = repository.getProtocol();
+
+        Wagon wagon;
+        try
+        {
+            wagon = getWagon( protocol, repository.getId() );
+        }
+        catch ( UnsupportedProtocolException e )
+        {
+            throw new TransferFailedException( "Unsupported Protocol: '" + protocol + "': " + e.getMessage(), e );
+        }
+
+        if ( downloadMonitor != null )
+        {
+            wagon.addTransferListener( downloadMonitor );
+        }
+
+        Map checksums = new HashMap( 2 );
+        Map sums = new HashMap( 2 );
+
+        // TODO: configure these on the repository
+        try
+        {
+            ChecksumObserver checksumObserver = new ChecksumObserver( "MD5" );
+            wagon.addTransferListener( checksumObserver );
+            checksums.put( "md5", checksumObserver );
+            checksumObserver = new ChecksumObserver( "SHA-1" );
+            wagon.addTransferListener( checksumObserver );
+            checksums.put( "sha1", checksumObserver );
+        }
+        catch ( NoSuchAlgorithmException e )
+        {
+            throw new TransferFailedException( "Unable to add checksum methods: " + e.getMessage(), e );
+        }
+
+        try
+        {
+            Repository artifactRepository = new Repository( repository.getId(), repository.getUrl() );
+
+            if ( serverPermissionsMap.containsKey( repository.getId() ) )
+            {
+                RepositoryPermissions perms = (RepositoryPermissions) serverPermissionsMap.get( repository.getId() );
+
+                getLogger().debug(
+                    "adding permissions to wagon connection: " + perms.getFileMode() + " " + perms.getDirectoryMode() );
+
+                artifactRepository.setPermissions( perms );
+            }
+            else
+            {
+                if ( defaultRepositoryPermissions != null )
+                {
+                    artifactRepository.setPermissions( defaultRepositoryPermissions );
+                }
+                else
+                {
+                    getLogger().debug( "not adding permissions to wagon connection" );
+                }
+            }
+
+            wagon.connect( artifactRepository, getAuthenticationInfo( repository.getId() ), new ProxyInfoProvider()
+            {
+                public ProxyInfo getProxyInfo( String protocol )
+                {
+                    return getProxy( protocol );
+                }
+            });
+
+            wagon.put( source, remotePath );
+
+            wagon.removeTransferListener( downloadMonitor );
+
+            // Pre-store the checksums as any future puts will overwrite them
+            for ( Iterator i = checksums.keySet().iterator(); i.hasNext(); )
+            {
+                String extension = (String) i.next();
+                ChecksumObserver observer = (ChecksumObserver) checksums.get( extension );
+                sums.put( extension, observer.getActualChecksum() );
+            }
+
+            // We do this in here so we can checksum the artifact metadata too, otherwise it could be metadata itself
+            for ( Iterator i = checksums.keySet().iterator(); i.hasNext(); )
+            {
+                String extension = (String) i.next();
+
+                // TODO: shouldn't need a file intermediatary - improve wagon to take a stream
+                File temp = File.createTempFile( "maven-artifact", null );
+                temp.deleteOnExit();
+                FileUtils.fileWrite( temp.getAbsolutePath(), "UTF-8", (String) sums.get( extension ) );
+
+                wagon.put( temp, remotePath + "." + extension );
+            }
+        }
+        catch ( ConnectionException e )
+        {
+            throw new TransferFailedException( "Connection failed: " + e.getMessage(), e );
+        }
+        catch ( AuthenticationException e )
+        {
+            throw new TransferFailedException( "Authentication failed: " + e.getMessage(), e );
+        }
+        catch ( AuthorizationException e )
+        {
+            throw new TransferFailedException( "Authorization failed: " + e.getMessage(), e );
+        }
+        catch ( ResourceDoesNotExistException e )
+        {
+            throw new TransferFailedException( "Resource to deploy not found: " + e.getMessage(), e );
+        }
+        catch ( IOException e )
+        {
+            throw new TransferFailedException( "Error creating temporary file for deployment: " + e.getMessage(), e );
+        }
+        finally
+        {
+            disconnectWagon( wagon );
+
+            releaseWagon( protocol, wagon, repository.getId() );
+        }
+    }
+
+    public void getArtifact( Artifact artifact,
+                             List remoteRepositories )
+        throws TransferFailedException, ResourceDoesNotExistException
+    {
+        // TODO [BP]: The exception handling here needs some work
+        boolean successful = false;
+        for ( Iterator iter = remoteRepositories.iterator(); iter.hasNext() && !successful; )
+        {
+            ArtifactRepository repository = (ArtifactRepository) iter.next();
+
+            try
+            {
+                getArtifact( artifact, repository );
+
+                successful = artifact.isResolved();
+            }
+            catch ( ResourceDoesNotExistException e )
+            {
+                // This one we will eat when looking through remote repositories
+                // because we want to cycle through them all before squawking.
+
+                getLogger().info( "Unable to find resource '" + artifact.getId() + "' in repository " +
+                                      repository.getId() + " (" + repository.getUrl() + ")" );
+            }
+            catch ( TransferFailedException e )
+            {
+                getLogger().warn( "Unable to get resource '" + artifact.getId() + "' from repository " +
+                                      repository.getId() + " (" + repository.getUrl() + "): " + e.getMessage() );
+            }
+        }
+
+        // if it already exists locally we were just trying to force it - ignore the update
+        if ( !successful && !artifact.getFile().exists() )
+        {
+            throw new ResourceDoesNotExistException( "Unable to download the artifact from any repository" );
+        }
+    }
+
+    public void getArtifact( Artifact artifact,
+                             ArtifactRepository repository )
+        throws TransferFailedException, ResourceDoesNotExistException
+    {
+        String remotePath = repository.pathOf( artifact );
+
+        ArtifactRepositoryPolicy policy = artifact.isSnapshot() ? repository.getSnapshots() : repository.getReleases();
+
+        if ( !policy.isEnabled() )
+        {
+            getLogger().debug( "Skipping disabled repository " + repository.getId() );
+        }
+        else if ( repository.isBlacklisted() )
+        {
+            getLogger().debug( "Skipping blacklisted repository " + repository.getId() );
+        }
+        else
+        {
+            getLogger().debug( "Trying repository " + repository.getId() );
+            getRemoteFile( getMirrorRepository( repository ), artifact.getFile(), remotePath, downloadMonitor,
+                           policy.getChecksumPolicy(), false );
+            getLogger().debug( "  Artifact resolved" );
+
+            artifact.setResolved( true );
+        }
+    }
+
+    public void getArtifactMetadata( ArtifactMetadata metadata,
+                                     ArtifactRepository repository,
+                                     File destination,
+                                     String checksumPolicy )
+        throws TransferFailedException, ResourceDoesNotExistException
+    {
+        String remotePath = repository.pathOfRemoteRepositoryMetadata( metadata );
+
+        getRemoteFile( getMirrorRepository( repository ), destination, remotePath, null, checksumPolicy, true );
+    }
+
+    public void getArtifactMetadataFromDeploymentRepository( ArtifactMetadata metadata, ArtifactRepository repository,
+                                                             File destination, String checksumPolicy )
+        throws TransferFailedException, ResourceDoesNotExistException
+    {
+        String remotePath = repository.pathOfRemoteRepositoryMetadata( metadata );
+
+        getRemoteFile( repository, destination, remotePath, null, checksumPolicy, true );
+    }
+
+    private void getRemoteFile( ArtifactRepository repository,
+                                File destination,
+                                String remotePath,
+                                TransferListener downloadMonitor,
+                                String checksumPolicy,
+                                boolean force )
+        throws TransferFailedException, ResourceDoesNotExistException
+    {
+        // TODO: better excetpions - transfer failed is not enough?
+
+        failIfNotOnline();
+
+        String protocol = repository.getProtocol();
+        Wagon wagon;
+        try
+        {
+            wagon = getWagon( protocol, repository.getId() );
+        }
+        catch ( UnsupportedProtocolException e )
+        {
+            throw new TransferFailedException( "Unsupported Protocol: '" + protocol + "': " + e.getMessage(), e );
+        }
+
+        if ( downloadMonitor != null )
+        {
+            wagon.addTransferListener( downloadMonitor );
+        }
+
+        File temp = new File( destination + ".tmp" );
+        temp.deleteOnExit();
+
+        boolean downloaded = false;
+
+        try
+        {
+            getLogger().debug( "Connecting to repository: \'" + repository.getId() + "\' with url: \'" + repository.getUrl() + "\'." );
+
+            wagon.connect( new Repository( repository.getId(), repository.getUrl() ),
+                           getAuthenticationInfo( repository.getId() ), new ProxyInfoProvider()
+                {
+                    public ProxyInfo getProxyInfo( String protocol )
+                    {
+                        return getProxy( protocol );
+                    }
+                });
+
+            boolean firstRun = true;
+            boolean retry = true;
+
+            // this will run at most twice. The first time, the firstRun flag is turned off, and if the retry flag
+            // is set on the first run, it will be turned off and not re-set on the second try. This is because the
+            // only way the retry flag can be set is if ( firstRun == true ).
+            while ( firstRun || retry )
+            {
+                // reset the retry flag.
+                retry = false;
+
+                // TODO: configure on repository
+                ChecksumObserver md5ChecksumObserver = null;
+                ChecksumObserver sha1ChecksumObserver = null;
+                try
+                {
+                    md5ChecksumObserver = new ChecksumObserver( "MD5" );
+                    wagon.addTransferListener( md5ChecksumObserver );
+
+                    sha1ChecksumObserver = new ChecksumObserver( "SHA-1" );
+                    wagon.addTransferListener( sha1ChecksumObserver );
+
+                    // This should take care of creating destination directory now on
+                    if ( destination.exists() && !force )
+                    {
+                        try
+                        {
+                            downloaded = wagon.getIfNewer( remotePath, temp, destination.lastModified() );
+                            if ( !downloaded )
+                            {
+                                // prevent additional checks of this artifact until it expires again
+                                destination.setLastModified( System.currentTimeMillis() );
+                            }
+                        }
+                        catch ( UnsupportedOperationException e )
+                        {
+                            // older wagons throw this. Just get() instead
+                            wagon.get( remotePath, temp );
+                            downloaded = true;
+                        }
+                    }
+                    else
+                    {
+                        wagon.get( remotePath, temp );
+                        downloaded = true;
+                    }
+                }
+                catch ( NoSuchAlgorithmException e )
+                {
+                    throw new TransferFailedException( "Unable to add checksum methods: " + e.getMessage(), e );
+                }
+                finally
+                {
+                    if ( md5ChecksumObserver != null )
+                    {
+                        wagon.removeTransferListener( md5ChecksumObserver );
+                    }
+                    if ( sha1ChecksumObserver != null )
+                    {
+                        wagon.removeTransferListener( sha1ChecksumObserver );
+                    }
+                }
+
+                if ( downloaded )
+                {
+                    // keep the checksum files from showing up on the download monitor...
+                    if ( downloadMonitor != null )
+                    {
+                        wagon.removeTransferListener( downloadMonitor );
+                    }
+
+                    // try to verify the SHA-1 checksum for this file.
+                    try
+                    {
+                        verifyChecksum( sha1ChecksumObserver, destination, temp, remotePath, ".sha1", wagon );
+                    }
+                    catch ( ChecksumFailedException e )
+                    {
+                        // if we catch a ChecksumFailedException, it means the transfer/read succeeded, but the checksum
+                        // doesn't match. This could be a problem with the server (ibiblio HTTP-200 error page), so we'll
+                        // try this up to two times. On the second try, we'll handle it as a bona-fide error, based on the
+                        // repository's checksum checking policy.
+                        if ( firstRun )
+                        {
+                            getLogger().warn( "*** CHECKSUM FAILED - " + e.getMessage() + " - RETRYING" );
+                            retry = true;
+                        }
+                        else
+                        {
+                            handleChecksumFailure( checksumPolicy, e.getMessage(), e.getCause() );
+                        }
+                    }
+                    catch ( ResourceDoesNotExistException sha1TryException )
+                    {
+                        getLogger().debug( "SHA1 not found, trying MD5", sha1TryException );
+
+                        // if this IS NOT a ChecksumFailedException, it was a problem with transfer/read of the checksum
+                        // file...we'll try again with the MD5 checksum.
+                        try
+                        {
+                            verifyChecksum( md5ChecksumObserver, destination, temp, remotePath, ".md5", wagon );
+                        }
+                        catch ( ChecksumFailedException e )
+                        {
+                            // if we also fail to verify based on the MD5 checksum, and the checksum transfer/read
+                            // succeeded, then we need to determine whether to retry or handle it as a failure.
+                            if ( firstRun )
+                            {
+                                retry = true;
+                            }
+                            else
+                            {
+                                handleChecksumFailure( checksumPolicy, e.getMessage(), e.getCause() );
+                            }
+                        }
+                        catch ( ResourceDoesNotExistException md5TryException )
+                        {
+                            // this was a failed transfer, and we don't want to retry.
+                            handleChecksumFailure( checksumPolicy, "Error retrieving checksum file for " + remotePath,
+                                                   md5TryException );
+                        }
+                    }
+
+                    // reinstate the download monitor...
+                    if ( downloadMonitor != null )
+                    {
+                        wagon.addTransferListener( downloadMonitor );
+                    }
+                }
+
+                // unset the firstRun flag, so we don't get caught in an infinite loop...
+                firstRun = false;
+            }
+        }
+        catch ( ConnectionException e )
+        {
+            throw new TransferFailedException( "Connection failed: " + e.getMessage(), e );
+        }
+        catch ( AuthenticationException e )
+        {
+            throw new TransferFailedException( "Authentication failed: " + e.getMessage(), e );
+        }
+        catch ( AuthorizationException e )
+        {
+            throw new TransferFailedException( "Authorization failed: " + e.getMessage(), e );
+        }
+        finally
+        {
+            disconnectWagon( wagon );
+
+            releaseWagon( protocol, wagon, repository.getId() );
+        }
+
+        if ( downloaded )
+        {
+            if ( !temp.exists() )
+            {
+                throw new ResourceDoesNotExistException( "Downloaded file does not exist: " + temp );
+            }
+
+            // The temporary file is named destination + ".tmp" and is done this way to ensure
+            // that the temporary file is in the same file system as the destination because the
+            // File.renameTo operation doesn't really work across file systems.
+            // So we will attempt to do a File.renameTo for efficiency and atomicity, if this fails
+            // then we will use a brute force copy and delete the temporary file.
+
+            if ( !temp.renameTo( destination ) )
+            {
+                try
+                {
+                    FileUtils.copyFile( temp, destination );
+
+                    temp.delete();
+                }
+                catch ( IOException e )
+                {
+                    throw new TransferFailedException(
+                        "Error copying temporary file to the final destination: " + e.getMessage(), e );
+                }
+            }
+        }
+    }
+
+    public ArtifactRepository getMirrorRepository( ArtifactRepository repository )
+    {
+        ArtifactRepository mirror = getMirror( repository );
+        if ( mirror != null )
+        {
+            String id = mirror.getId();
+            if ( id == null )
+            {
+                // TODO: this should be illegal in settings.xml
+                id = repository.getId();
+            }
+
+            getLogger().debug( "Using mirror: " + mirror.getUrl() + " (id: " + id + ")" );
+
+            repository = repositoryFactory.createArtifactRepository( id, mirror.getUrl(),
+                                                                     repository.getLayout(), repository.getSnapshots(),
+                                                                     repository.getReleases() );
+        }
+        return repository;
+    }
+
+    private void failIfNotOnline()
+        throws TransferFailedException
+    {
+        if ( !isOnline() )
+        {
+            throw new TransferFailedException( "System is offline." );
+        }
+    }
+
+    private void handleChecksumFailure( String checksumPolicy,
+                                        String message,
+                                        Throwable cause )
+        throws ChecksumFailedException
+    {
+        if ( ArtifactRepositoryPolicy.CHECKSUM_POLICY_FAIL.equals( checksumPolicy ) )
+        {
+            throw new ChecksumFailedException( message, cause );
+        }
+        else if ( !ArtifactRepositoryPolicy.CHECKSUM_POLICY_IGNORE.equals( checksumPolicy ) )
+        {
+            // warn if it is set to anything other than ignore
+            getLogger().warn( "*** CHECKSUM FAILED - " + message + " - IGNORING" );
+        }
+        // otherwise it is ignore
+    }
+
+    private void verifyChecksum( ChecksumObserver checksumObserver,
+                                 File destination,
+                                 File tempDestination,
+                                 String remotePath,
+                                 String checksumFileExtension,
+                                 Wagon wagon )
+        throws ResourceDoesNotExistException, TransferFailedException, AuthorizationException
+    {
+        try
+        {
+            // grab it first, because it's about to change...
+            String actualChecksum = checksumObserver.getActualChecksum();
+
+            File tempChecksumFile = new File( tempDestination + checksumFileExtension + ".tmp" );
+            tempChecksumFile.deleteOnExit();
+            wagon.get( remotePath + checksumFileExtension, tempChecksumFile );
+
+            String expectedChecksum = FileUtils.fileRead( tempChecksumFile, "UTF-8" );
+
+            // remove whitespaces at the end
+            expectedChecksum = expectedChecksum.trim();
+
+            // check for 'ALGO (name) = CHECKSUM' like used by openssl
+            if ( expectedChecksum.regionMatches( true, 0, "MD", 0, 2 )
+                || expectedChecksum.regionMatches( true, 0, "SHA", 0, 3 ) )
+            {
+                int lastSpacePos = expectedChecksum.lastIndexOf( ' ' );
+                expectedChecksum = expectedChecksum.substring( lastSpacePos + 1 );
+            }
+            else
+            {
+                // remove everything after the first space (if available)
+                int spacePos = expectedChecksum.indexOf( ' ' );
+
+                if ( spacePos != -1 )
+                {
+                    expectedChecksum = expectedChecksum.substring( 0, spacePos );
+                }
+            }
+            if ( expectedChecksum.equalsIgnoreCase( actualChecksum ) )
+            {
+                File checksumFile = new File( destination + checksumFileExtension );
+                if ( checksumFile.exists() )
+                {
+                    checksumFile.delete();
+                }
+                FileUtils.copyFile( tempChecksumFile, checksumFile );
+            }
+            else
+            {
+                throw new ChecksumFailedException( "Checksum failed on download: local = '" + actualChecksum +
+                                                       "'; remote = '" + expectedChecksum + "'" );
+            }
+        }
+        catch ( IOException e )
+        {
+            throw new ChecksumFailedException( "Invalid checksum file", e );
+        }
+    }
+
+
+    private void disconnectWagon( Wagon wagon )
+    {
+        try
+        {
+            wagon.disconnect();
+        }
+        catch ( ConnectionException e )
+        {
+            getLogger().error( "Problem disconnecting from wagon - ignoring: " + e.getMessage() );
+        }
+    }
+
+    private void releaseWagon( String protocol,
+                               Wagon wagon, String repositoryId )
+    {
+        String hint = getWagonHint( protocol, repositoryId );
+
+        PlexusContainer container = getWagonContainer( hint );
+        try
+        {
+            container.release( wagon );
+        }
+        catch ( ComponentLifecycleException e )
+        {
+            getLogger().error( "Problem releasing wagon - ignoring: " + e.getMessage() );
+        }
+    }
+
+    public ProxyInfo getProxy( String protocol )
+    {
+        ProxyInfo info = (ProxyInfo) proxies.get( protocol );
+
+        if ( info != null )
+        {
+            getLogger().debug( "Using Proxy: " + info.getHost() );
+        }
+
+        return info;
+    }
+
+    public AuthenticationInfo getAuthenticationInfo( String id )
+    {
+        return (AuthenticationInfo) authenticationInfoMap.get( id );
+    }
+
+    /**
+     * This method finds a matching mirror for the selected repository. If there is an exact match, this will be used.
+     * If there is no exact match, then the list of mirrors is examined to see if a pattern applies.
+     *
+     * @param originalRepository See if there is a mirror for this repository.
+     * @return the selected mirror or null if none are found.
+     */
+    public ArtifactRepository getMirror( ArtifactRepository originalRepository )
+    {
+        ArtifactRepository selectedMirror = (ArtifactRepository) mirrors.get( originalRepository.getId() );
+        if ( null == selectedMirror )
+        {
+            // Process the patterns in order. First one that matches wins.
+            Set keySet = mirrors.keySet();
+            if ( keySet != null )
+            {
+                Iterator iter = keySet.iterator();
+                while ( iter.hasNext() )
+                {
+                    String pattern = (String) iter.next();
+                    if ( matchPattern( originalRepository, pattern ) )
+                    {
+                        selectedMirror = (ArtifactRepository) mirrors.get( pattern );
+                        break;
+                    }
+                }
+            }
+
+        }
+        return selectedMirror;
+    }
+
+    /**
+     * This method checks if the pattern matches the originalRepository.
+     * Valid patterns:
+     * * = everything
+     * external:* = everything not on the localhost and not file based.
+     * repo,repo1 = repo or repo1
+     * *,!repo1 = everything except repo1
+     *
+     * @param originalRepository to compare for a match.
+     * @param pattern used for match. Currently only '*' is supported.
+     * @return true if the repository is a match to this pattern.
+     */
+    public boolean matchPattern( ArtifactRepository originalRepository, String pattern )
+    {
+        boolean result = false;
+        String originalId = originalRepository.getId();
+
+        // simple checks first to short circuit processing below.
+        if ( WILDCARD.equals( pattern ) || pattern.equals( originalId ) )
+        {
+            result = true;
+        }
+        else
+        {
+            // process the list
+            String[] repos = pattern.split( "," );
+            for ( int i = 0; i < repos.length; i++ )
+            {
+                String repo = repos[i];
+
+                // see if this is a negative match
+                if ( repo.length() > 1 && repo.startsWith( "!" ) )
+                {
+                    if ( originalId.equals( repo.substring( 1 ) ) )
+                    {
+                        // explicitly exclude. Set result and stop processing.
+                        result = false;
+                        break;
+                    }
+                }
+                // check for exact match
+                else if ( originalId.equals( repo ) )
+                {
+                    result = true;
+                    break;
+                }
+                // check for external:*
+                else if ( EXTERNAL_WILDCARD.equals( repo ) && isExternalRepo( originalRepository ) )
+                {
+                    result = true;
+                    // don't stop processing in case a future segment explicitly excludes this repo
+                }
+                else if ( WILDCARD.equals( repo ) )
+                {
+                    result = true;
+                    // don't stop processing in case a future segment explicitly excludes this repo
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Checks the URL to see if this repository refers to an external repository
+     *
+     * @param originalRepository
+     * @return true if external.
+     */
+    public boolean isExternalRepo( ArtifactRepository originalRepository )
+    {
+        try
+        {
+            URL url = new URL( originalRepository.getUrl() );
+            return !( url.getHost().equals( "localhost" ) || url.getHost().equals( "127.0.0.1" ) || url.getProtocol().equals(
+                "file" ) );
+        }
+        catch ( MalformedURLException e )
+        {
+            // bad url just skip it here. It should have been validated already, but the wagon lookup will deal with it
+            return false;
+        }
+    }
+
+    /**
+     * Set the proxy used for a particular protocol.
+     *
+     * @param protocol the protocol (required)
+     * @param host the proxy host name (required)
+     * @param port the proxy port (required)
+     * @param username the username for the proxy, or null if there is none
+     * @param password the password for the proxy, or null if there is none
+     * @param nonProxyHosts the set of hosts not to use the proxy for. Follows Java system property format:
+     *            <code>*.foo.com|localhost</code>.
+     * @todo [BP] would be nice to configure this via plexus in some way
+     */
+    public void addProxy( String protocol,
+                          String host,
+                          int port,
+                          String username,
+                          String password,
+                          String nonProxyHosts )
+    {
+        ProxyInfo proxyInfo = new ProxyInfo();
+        proxyInfo.setHost( host );
+        proxyInfo.setType( protocol );
+        proxyInfo.setPort( port );
+        proxyInfo.setNonProxyHosts( nonProxyHosts );
+        proxyInfo.setUserName( username );
+        proxyInfo.setPassword( password );
+
+        proxies.put( protocol, proxyInfo );
+    }
+
+    public void contextualize( Context context )
+        throws ContextException
+    {
+        container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
+    }
+
+    /** @todo I'd rather not be setting this explicitly. */
+    public void setDownloadMonitor( TransferListener downloadMonitor )
+    {
+        this.downloadMonitor = downloadMonitor;
+    }
+
+    public void addAuthenticationInfo( String repositoryId,
+                                       String username,
+                                       String password,
+                                       String privateKey,
+                                       String passphrase )
+    {
+        AuthenticationInfo authInfo = new AuthenticationInfo();
+
+        authInfo.setUserName( username );
+
+        authInfo.setPassword( password );
+
+        authInfo.setPrivateKey( privateKey );
+
+        authInfo.setPassphrase( passphrase );
+
+        authenticationInfoMap.put( repositoryId, authInfo );
+    }
+
+    public void addPermissionInfo( String repositoryId,
+                                   String filePermissions,
+                                   String directoryPermissions )
+    {
+
+        RepositoryPermissions permissions = new RepositoryPermissions();
+        boolean addPermissions = false;
+
+        if ( filePermissions != null )
+        {
+            permissions.setFileMode( filePermissions );
+            addPermissions = true;
+        }
+
+        if ( directoryPermissions != null )
+        {
+            permissions.setDirectoryMode( directoryPermissions );
+            addPermissions = true;
+        }
+
+        if ( addPermissions )
+        {
+            serverPermissionsMap.put( repositoryId, permissions );
+        }
+    }
+
+    public void addMirror( String id,
+                           String mirrorOf,
+                           String url )
+    {
+        if ( id == null )
+        {
+            id = "mirror-" + anonymousMirrorIdSeed++;
+            getLogger().warn( "You are using a mirror that doesn't declare an <id/> element. Using \'" + id + "\' instead:\nId: " + id + "\nmirrorOf: " + mirrorOf + "\nurl: " + url + "\n" );
+        }
+
+        ArtifactRepository mirror = new DefaultArtifactRepository( id, url, null );
+
+        //to preserve first wins, don't add repeated mirrors.
+        if (!mirrors.containsKey( mirrorOf ))
+        {
+            mirrors.put( mirrorOf, mirror );
+        }
+    }
+
+    public void setOnline( boolean online )
+    {
+        this.online = online;
+    }
+
+    public boolean isOnline()
+    {
+        return online;
+    }
+
+    public void setInteractive( boolean interactive )
+    {
+        this.interactive = interactive;
+    }
+
+    @SuppressWarnings( "unchecked" )
+    public void registerWagons( Collection wagons,
+                                PlexusContainer extensionContainer )
+    {
+        for ( Iterator<String> i = wagons.iterator(); i.hasNext(); )
+        {
+            availableWagons.put( i.next(), extensionContainer );
+        }
+    }
+
+    public void addConfiguration( String repositoryId,
+                                  Xpp3Dom configuration )
+    {
+        if ( repositoryId == null || configuration == null )
+        {
+            throw new IllegalArgumentException( "arguments can't be null" );
+        }
+
+        getLogger().warn( "Unsupported configuration: " + configuration + " for repository " + repositoryId );
+    }
+
+    public void setDefaultRepositoryPermissions( RepositoryPermissions defaultRepositoryPermissions )
+    {
+        this.defaultRepositoryPermissions = defaultRepositoryPermissions;
+    }
+
+    // TODO: Remove this, once the maven-shade-plugin 1.2 release is out, allowing configuration of httpHeaders in the components.xml
+    public void initialize()
+        throws InitializationException
+    {
+        if ( httpUserAgent == null )
+        {
+            InputStream resourceAsStream = null;
+            try
+            {
+                Properties properties = new Properties();
+                resourceAsStream = getClass().getClassLoader().getResourceAsStream( MAVEN_ARTIFACT_PROPERTIES );
+
+                if ( resourceAsStream != null )
+                {
+                    try
+                    {
+                        properties.load( resourceAsStream );
+
+                        httpUserAgent =
+                            "maven-artifact/" + properties.getProperty( "version" ) + " (Java "
+                                + System.getProperty( "java.version" ) + "; " + System.getProperty( "os.name" ) + " "
+                                + System.getProperty( "os.version" ) + ")";
+                    }
+                    catch ( IOException e )
+                    {
+                        getLogger().warn(
+                            "Failed to load Maven artifact properties from:\n" + MAVEN_ARTIFACT_PROPERTIES
+                                + "\n\nUser-Agent HTTP header may be incorrect for artifact resolution." );
+                    }
+                }
+            }
+            finally
+            {
+                IOUtil.close( resourceAsStream );
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setHttpUserAgent( String userAgent )
+    {
+        this.httpUserAgent = userAgent;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getHttpUserAgent()
+    {
+        return httpUserAgent;
+    }
+}
diff --git a/continuum-base/continuum-configuration/pom.xml b/continuum-base/continuum-configuration/pom.xml
index a083e7d..e3bab4a 100644
--- a/continuum-base/continuum-configuration/pom.xml
+++ b/continuum-base/continuum-configuration/pom.xml
@@ -1,27 +1,28 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
+  ~ 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.
+  -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <artifactId>continuum-base</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>continuum-configuration</artifactId>
@@ -35,7 +36,8 @@
           <models>
             <model>src/main/mdo/continuum-configuration.xml</model>
           </models>
-          <version>1.0.1</version>
+          <version>1.4.1</version>
+          <useJava5>true</useJava5>
         </configuration>
         <executions>
           <execution>
@@ -64,7 +66,43 @@
             <configuration>
               <outputDirectory>${project.build.outputDirectory}/META-INF/continuum/xsd</outputDirectory>
             </configuration>
-          </execution>                    
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>com.google.code.maven-replacer-plugin</groupId>
+        <artifactId>replacer</artifactId>
+        <executions>
+          <execution>
+            <id>replace-timestamp</id>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>replace</goal>
+            </goals>
+            <configuration>
+              <basedir>${basedir}</basedir>
+              <includes>
+                <include>target/generated-sources/**</include>
+              </includes>
+              <token>Generated by Modello.*</token>
+              <value>Generated by Modello</value>
+            </configuration>
+          </execution>
+          <execution>
+            <id>replace-site-timestamp</id>
+            <phase>pre-site</phase>
+            <goals>
+              <goal>replace</goal>
+            </goals>
+            <configuration>
+              <basedir>${basedir}</basedir>
+              <includes>
+                <include>target/generated-site/**</include>
+              </includes>
+              <token>Generated by Modello.* --&gt;</token>
+              <value>Generated by Modello --&gt;</value>
+            </configuration>
+          </execution>
         </executions>
       </plugin>
     </plugins>
@@ -77,30 +115,29 @@
     <dependency>
       <groupId>commons-lang</groupId>
       <artifactId>commons-lang</artifactId>
-    </dependency>    
+    </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
-    </dependency>      
+    </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-log4j12</artifactId>
-      <scope>test</scope>
-    </dependency>   
-    <dependency>
-      <groupId>org.springframework</groupId>
-      <artifactId>spring-core</artifactId>
-      <version>${spring.version}</version>
-    </dependency>       
-    <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-spring</artifactId>
+      <artifactId>slf4j-simple</artifactId>
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-test</artifactId>
+      <groupId>org.slf4j</groupId>
+      <artifactId>jcl-over-slf4j</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>plexus-spring</artifactId>
       <scope>test</scope>
-    </dependency>        
+    </dependency>
+    <dependency> <!-- added since depMgt doesn't override imported dependencies -->
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-utils</artifactId>
+    </dependency>
   </dependencies>
 </project>
diff --git a/continuum-base/continuum-configuration/src/main/java/org/apache/continuum/configuration/DefaultContinuumConfiguration.java b/continuum-base/continuum-configuration/src/main/java/org/apache/continuum/configuration/DefaultContinuumConfiguration.java
index ab0db60..c6f0e82 100644
--- a/continuum-base/continuum-configuration/src/main/java/org/apache/continuum/configuration/DefaultContinuumConfiguration.java
+++ b/continuum-base/continuum-configuration/src/main/java/org/apache/continuum/configuration/DefaultContinuumConfiguration.java
@@ -19,6 +19,15 @@
  * under the License.
  */
 
+import org.apache.commons.lang.StringUtils;
+import org.apache.continuum.configuration.model.ContinuumConfigurationModel;
+import org.apache.continuum.configuration.model.io.xpp3.ContinuumConfigurationModelXpp3Reader;
+import org.apache.continuum.configuration.model.io.xpp3.ContinuumConfigurationModelXpp3Writer;
+import org.codehaus.plexus.util.IOUtil;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileWriter;
@@ -27,14 +36,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.apache.commons.lang.StringUtils;
-import org.apache.continuum.configuration.model.ContinuumConfigurationModel;
-import org.apache.continuum.configuration.model.io.xpp3.ContinuumConfigurationModelXpp3Reader;
-import org.apache.continuum.configuration.model.io.xpp3.ContinuumConfigurationModelXpp3Writer;
-import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 /**
  * @author <a href="mailto:olamy@apache.org">olamy</a>
  * @version $Id$
@@ -43,12 +44,14 @@
 public class DefaultContinuumConfiguration
     implements ContinuumConfiguration
 {
-    private Logger log = LoggerFactory.getLogger( getClass() );
+    private static final Logger log = LoggerFactory.getLogger( DefaultContinuumConfiguration.class );
 
     private File configurationFile;
 
     private GeneralConfiguration generalConfiguration;
 
+    public static final String CONFIGURATION_FILE = "continuum.xml";
+
     //----------------------------------------------------
     //  Initialize method configured in the Spring xml 
     //   configuration file
@@ -89,7 +92,7 @@
     {
         if ( !configurationFile.exists() )
         {
-            configurationFile.getParentFile().mkdir();
+            configurationFile.getParentFile().mkdirs();
         }
         save( configurationFile );
     }
@@ -108,29 +111,34 @@
     {
         this.generalConfiguration = generalConfiguration;
     }
-    
+
     public void reload( File file )
         throws ContinuumConfigurationException
     {
+        FileInputStream fis = null;
         try
         {
+            fis = new FileInputStream( file );
             ContinuumConfigurationModelXpp3Reader configurationXpp3Reader = new ContinuumConfigurationModelXpp3Reader();
-            ContinuumConfigurationModel configuration = configurationXpp3Reader
-                .read( new InputStreamReader( new FileInputStream( file ) ) );
+            ContinuumConfigurationModel configuration = configurationXpp3Reader.read( new InputStreamReader( fis ) );
 
             this.generalConfiguration = new GeneralConfiguration();
+
+            this.generalConfiguration.setNumberOfBuildsInParallel( configuration.getNumberOfBuildsInParallel() );
             this.generalConfiguration.setBaseUrl( configuration.getBaseUrl() );
+            this.generalConfiguration.setSharedSecretPassword( configuration.getSharedSecretPassword() );
+
             if ( StringUtils.isNotEmpty( configuration.getBuildOutputDirectory() ) )
             {
                 // TODO take care if file exists ?
-                this.generalConfiguration.setBuildOutputDirectory( new File( configuration
-                    .getBuildOutputDirectory() ) );
+                this.generalConfiguration.setBuildOutputDirectory( new File(
+                    configuration.getBuildOutputDirectory() ) );
             }
             if ( StringUtils.isNotEmpty( configuration.getDeploymentRepositoryDirectory() ) )
             {
                 // TODO take care if file exists ?
-                this.generalConfiguration.setDeploymentRepositoryDirectory( new File( configuration
-                    .getDeploymentRepositoryDirectory() ) );
+                this.generalConfiguration.setDeploymentRepositoryDirectory( new File(
+                    configuration.getDeploymentRepositoryDirectory() ) );
             }
             if ( StringUtils.isNotEmpty( configuration.getWorkingDirectory() ) )
             {
@@ -139,23 +147,31 @@
             }
             if ( configuration.getProxyConfiguration() != null )
             {
-                ProxyConfiguration proxyConfiguration = new ProxyConfiguration( configuration
-                    .getProxyConfiguration().getProxyHost(), configuration.getProxyConfiguration()
-                    .getProxyPassword(), configuration.getProxyConfiguration().getProxyPort(), configuration
-                    .getProxyConfiguration().getProxyUser() );
+                ProxyConfiguration proxyConfiguration = new ProxyConfiguration(
+                    configuration.getProxyConfiguration().getProxyHost(),
+                    configuration.getProxyConfiguration().getProxyPassword(),
+                    configuration.getProxyConfiguration().getProxyPort(),
+                    configuration.getProxyConfiguration().getProxyUser() );
                 this.generalConfiguration.setProxyConfiguration( proxyConfiguration );
             }
             if ( StringUtils.isNotEmpty( configuration.getReleaseOutputDirectory() ) )
             {
                 // TODO take care if file exists?
-                this.generalConfiguration.setReleaseOutputDirectory( new File( configuration
-                    .getReleaseOutputDirectory() ) );
+                this.generalConfiguration.setReleaseOutputDirectory( new File(
+                    configuration.getReleaseOutputDirectory() ) );
             }
+
+            // set the configuration for diistributedBuildEnabled
+            this.generalConfiguration.setDistributedBuildEnabled( configuration.isDistributedBuildEnabled() );
+
+            this.generalConfiguration.setInitialized( configuration.isInitialized() );
+
             if ( configuration.getBuildAgents() != null )
             {
                 List<BuildAgentConfiguration> buildAgents = new ArrayList<BuildAgentConfiguration>();
 
-                List<org.apache.continuum.configuration.model.BuildAgentConfiguration> agents = configuration.getBuildAgents();
+                List<org.apache.continuum.configuration.model.BuildAgentConfiguration> agents =
+                    configuration.getBuildAgents();
                 for ( org.apache.continuum.configuration.model.BuildAgentConfiguration agent : agents )
                 {
                     BuildAgentConfiguration buildAgent = new BuildAgentConfiguration( agent.getUrl(),
@@ -163,9 +179,35 @@
                                                                                       agent.isEnabled() );
                     buildAgents.add( buildAgent );
                 }
-                
+
                 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 )
         {
@@ -177,7 +219,13 @@
             log.error( e.getMessage(), e );
             throw new RuntimeException( e.getMessage(), e );
         }
-        
+        finally
+        {
+            if ( fis != null )
+            {
+                IOUtil.close( fis );
+            }
+        }
     }
 
     public void save( File file )
@@ -187,11 +235,14 @@
         {
             ContinuumConfigurationModel configurationModel = new ContinuumConfigurationModel();
             configurationModel.setBaseUrl( this.generalConfiguration.getBaseUrl() );
+            configurationModel.setNumberOfBuildsInParallel( this.generalConfiguration.getNumberOfBuildsInParallel() );
+            configurationModel.setSharedSecretPassword( this.generalConfiguration.getSharedSecretPassword() );
+
             // normally not null but NPE free is better !
             if ( this.generalConfiguration.getBuildOutputDirectory() != null )
             {
-                configurationModel.setBuildOutputDirectory( this.generalConfiguration.getBuildOutputDirectory()
-                    .getPath() );
+                configurationModel.setBuildOutputDirectory(
+                    this.generalConfiguration.getBuildOutputDirectory().getPath() );
             }
             if ( this.generalConfiguration.getWorkingDirectory() != null )
             {
@@ -199,61 +250,98 @@
             }
             if ( this.generalConfiguration.getDeploymentRepositoryDirectory() != null )
             {
-                configurationModel.setDeploymentRepositoryDirectory( this.generalConfiguration
-                    .getDeploymentRepositoryDirectory().getPath() );
+                configurationModel.setDeploymentRepositoryDirectory(
+                    this.generalConfiguration.getDeploymentRepositoryDirectory().getPath() );
             }
             if ( this.generalConfiguration.getProxyConfiguration() != null )
             {
-                configurationModel
-                    .setProxyConfiguration( new org.apache.continuum.configuration.model.ProxyConfiguration() );
+                configurationModel.setProxyConfiguration(
+                    new org.apache.continuum.configuration.model.ProxyConfiguration() );
                 configurationModel.getProxyConfiguration().setProxyHost(
-                                                                         this.generalConfiguration
-                                                                             .getProxyConfiguration().getProxyHost() );
+                    this.generalConfiguration.getProxyConfiguration().getProxyHost() );
                 configurationModel.getProxyConfiguration().setProxyPassword(
-                                                                             this.generalConfiguration
-                                                                                 .getProxyConfiguration()
-                                                                                 .getProxyPassword() );
+                    this.generalConfiguration.getProxyConfiguration().getProxyPassword() );
                 configurationModel.getProxyConfiguration().setProxyPort(
-                                                                         this.generalConfiguration
-                                                                             .getProxyConfiguration().getProxyPort() );
+                    this.generalConfiguration.getProxyConfiguration().getProxyPort() );
                 configurationModel.getProxyConfiguration().setProxyHost(
-                                                                         this.generalConfiguration
-                                                                             .getProxyConfiguration().getProxyHost() );
+                    this.generalConfiguration.getProxyConfiguration().getProxyHost() );
             }
             if ( this.generalConfiguration.getReleaseOutputDirectory() != null )
             {
-                configurationModel.setReleaseOutputDirectory( this.generalConfiguration.getReleaseOutputDirectory()
-                    .getPath() );
+                configurationModel.setReleaseOutputDirectory(
+                    this.generalConfiguration.getReleaseOutputDirectory().getPath() );
             }
+
+            // set configuration for distributedBuildEnabled.
+            configurationModel.setDistributedBuildEnabled( this.generalConfiguration.isDistributedBuildEnabled() );
+
+            configurationModel.setInitialized( this.generalConfiguration.isInitialized() );
+
             if ( this.generalConfiguration.getBuildAgents() != null )
             {
-                List buildAgents = new ArrayList();
+                List<org.apache.continuum.configuration.model.BuildAgentConfiguration> buildAgents =
+                    new ArrayList<org.apache.continuum.configuration.model.BuildAgentConfiguration>();
 
                 for ( BuildAgentConfiguration agent : this.generalConfiguration.getBuildAgents() )
                 {
-                    org.apache.continuum.configuration.model.BuildAgentConfiguration buildAgent = 
+                    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 );
                 }
                 configurationModel.setBuildAgents( buildAgents );
             }
+            if ( this.generalConfiguration.getBuildAgentGroups() != null )
+            {
+                List<org.apache.continuum.configuration.model.BuildAgentGroupConfiguration> buildAgentGroups =
+                    new ArrayList<org.apache.continuum.configuration.model.BuildAgentGroupConfiguration>();
+
+                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<org.apache.continuum.configuration.model.BuildAgentConfiguration> buildAgents =
+                        new ArrayList<org.apache.continuum.configuration.model.BuildAgentConfiguration>();
+
+                    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 );
+            fileWriter.flush();
+            fileWriter.close();
         }
         catch ( IOException e )
         {
             throw new ContinuumConfigurationException( e.getMessage(), e );
         }
-        
+
     }
-    
-    
+
     // ----------------------------------------
     //  Spring injection
     // ----------------------------------------
@@ -268,5 +356,5 @@
     {
         this.configurationFile = configurationFile;
     }
-    
+
 }
diff --git a/continuum-base/continuum-configuration/src/main/mdo/continuum-configuration.xml b/continuum-base/continuum-configuration/src/main/mdo/continuum-configuration.xml
index fdbe4eb..d788cac 100644
--- a/continuum-base/continuum-configuration/src/main/mdo/continuum-configuration.xml
+++ b/continuum-base/continuum-configuration/src/main/mdo/continuum-configuration.xml
@@ -17,7 +17,7 @@
   ~ under the License.
   -->
 
-<model>
+<model xsd.namespace="http://modello.codehaus.org/xsd/modello-1.0.0.xsd">
   <id>continuum-configuration</id>
   <name>ContinuumConfigurationModel</name>
   <description>Continuum Configuration object model.</description>
@@ -31,44 +31,138 @@
   <classes>
     <class rootElement="true" xml.tagName="continuum-configuration">
       <name>ContinuumConfigurationModel</name>
-      <version>1.0.0+</version>
+      <version>1.1.0+</version>
       <fields>
         <field>
           <name>baseUrl</name>
-          <version>1.0.0+</version>
+          <version>1.1.0+</version>
           <type>String</type>
         </field>
         <field>
           <name>buildOutputDirectory</name>
-          <version>1.0.0+</version>
+          <version>1.1.0+</version>
           <type>String</type>
         </field>
         <field>
           <name>deploymentRepositoryDirectory</name>
-          <version>1.0.0+</version>
+          <version>1.1.0+</version>
           <type>String</type>
-        </field>   
+        </field>
         <field>
           <name>workingDirectory</name>
-          <version>1.0.0+</version>
+          <version>1.1.0+</version>
           <type>String</type>
         </field>
         <field>
           <name>proxyConfiguration</name>
-          <version>1.0.0+</version>
+          <version>1.1.0+</version>
           <association>
             <type>ProxyConfiguration</type>
             <multiplicity>1</multiplicity>
-          </association>          
-        </field>     
+          </association>
+        </field>
         <field>
           <name>releaseOutputDirectory</name>
-          <version>1.0.0+</version>
+          <version>1.1.0+</version>
+          <type>String</type>
+        </field>
+        <field>
+          <name>numberOfBuildsInParallel</name>
+          <version>1.1.0+</version>
+          <type>int</type>
+        </field>
+        <field>
+          <name>distributedBuildEnabled</name>
+          <version>1.4.1+</version>
+          <type>boolean</type>
+        </field>
+        <field>
+          <name>sharedSecretPassword</name>
+          <version>1.4.1+</version>
           <type>String</type>
         </field>
         <field>
           <name>buildAgents</name>
-          <version>1.0.1+</version>
+          <version>1.1.0+</version>
+          <association>
+            <type>BuildAgentConfiguration</type>
+            <multiplicity>*</multiplicity>
+          </association>
+        </field>
+        <field>
+          <name>buildAgentGroups</name>
+          <version>1.1.1+</version>
+          <association>
+            <type>BuildAgentGroupConfiguration</type>
+            <multiplicity>*</multiplicity>
+          </association>
+        </field>
+        <field>
+          <name>initialized</name>
+          <version>1.4.1+</version>
+          <type>boolean</type>
+        </field>
+      </fields>
+    </class>
+    <class xml.tagName="proxy-configuration">
+      <name>ProxyConfiguration</name>
+      <version>1.1.0+</version>
+      <fields>
+        <field>
+          <name>proxyHost</name>
+          <version>1.1.0+</version>
+          <type>String</type>
+        </field>
+        <field>
+          <name>proxyPort</name>
+          <version>1.1.0+</version>
+          <type>int</type>
+        </field>
+        <field>
+          <name>proxyUser</name>
+          <version>1.1.0+</version>
+          <type>String</type>
+        </field>
+        <field>
+          <name>proxyPassword</name>
+          <version>1.1.0+</version>
+          <type>String</type>
+        </field>
+      </fields>
+    </class>
+    <class xml.tagName="buildagent-configuration">
+      <name>BuildAgentConfiguration</name>
+      <version>1.1.0+</version>
+      <fields>
+        <field>
+          <name>url</name>
+          <version>1.1.0+</version>
+          <type>String</type>
+        </field>
+        <field>
+          <name>description</name>
+          <version>1.1.0+</version>
+          <type>String</type>
+        </field>
+        <field>
+          <name>enabled</name>
+          <version>1.1.0+</version>
+          <type>boolean</type>
+        </field>
+      </fields>
+    </class>
+    <class xml.tagName="buildagentgroup-configuration">
+      <name>BuildAgentGroupConfiguration</name>
+      <version>1.1.1+</version>
+      <fields>
+        <field>
+          <name>name</name>
+          <version>1.1.1+</version>
+          <type>String</type>
+        </field>
+        <field>
+          <name>buildAgents</name>
+          <version>1.1.1+</version>
           <association>
             <type>BuildAgentConfiguration</type>
             <multiplicity>*</multiplicity>
@@ -76,52 +170,5 @@
         </field>
       </fields>
     </class>
-    <class xml.tagName="proxy-configuration">
-      <name>ProxyConfiguration</name>
-      <version>1.0.0+</version>
-      <fields>
-        <field>
-          <name>proxyHost</name>
-          <version>1.0.0+</version>
-          <type>String</type>
-        </field>
-        <field>
-          <name>proxyPort</name>
-          <version>1.0.0+</version>
-          <type>int</type>
-        </field>
-        <field>
-          <name>proxyUser</name>
-          <version>1.0.0+</version>
-          <type>String</type>
-        </field>   
-        <field>
-          <name>proxyPassword</name>
-          <version>1.0.0+</version>
-          <type>String</type>
-        </field>                     
-      </fields>
-    </class>
-    <class xml.tagName="buildagent-configuration">
-      <name>BuildAgentConfiguration</name>
-      <version>1.0.1+</version>
-      <fields>
-        <field>
-          <name>url</name>
-          <version>1.0.1+</version>
-          <type>String</type>
-        </field>
-        <field>
-          <name>description</name>
-          <version>1.0.1+</version>
-          <type>String</type>
-        </field>
-        <field>
-          <name>enabled</name>
-          <version>1.0.1+</version>
-          <type>boolean</type>
-        </field>
-      </fields>
-    </class>    
   </classes>
 </model>
diff --git a/continuum-base/continuum-configuration/src/main/resources/META-INF/spring-context.xml b/continuum-base/continuum-configuration/src/main/resources/META-INF/spring-context.xml
index 57a9f41..00505b2 100644
--- a/continuum-base/continuum-configuration/src/main/resources/META-INF/spring-context.xml
+++ b/continuum-base/continuum-configuration/src/main/resources/META-INF/spring-context.xml
@@ -18,6 +18,7 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
   -->
+
 <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
diff --git a/continuum-base/continuum-configuration/src/test/java/org/apache/continuum/configuration/TestDefaultContinuumConfiguration.java b/continuum-base/continuum-configuration/src/test/java/org/apache/continuum/configuration/TestDefaultContinuumConfiguration.java
index 5ec3290..6cfa785 100644
--- a/continuum-base/continuum-configuration/src/test/java/org/apache/continuum/configuration/TestDefaultContinuumConfiguration.java
+++ b/continuum-base/continuum-configuration/src/test/java/org/apache/continuum/configuration/TestDefaultContinuumConfiguration.java
@@ -36,44 +36,54 @@
 public class TestDefaultContinuumConfiguration
     extends PlexusInSpringTestCase
 {
-    private Logger log = LoggerFactory.getLogger( getClass() );
+    private static final Logger log = LoggerFactory.getLogger( TestDefaultContinuumConfiguration.class );
 
-    private String confFile = "target/test-classes/conf/continuum.xml";
+    private static final String confFile = "target/test-classes/conf/continuum.xml";
 
     @Override
     protected void setUp()
         throws Exception
     {
         log.info( "appserver.base : " + System.getProperty( "appserver.base" ) );
-        
+
         File originalConf = new File( getBasedir(), "src/test/resources/conf/continuum.xml" );
-        
+
         File confUsed = new File( getBasedir(), confFile );
         if ( confUsed.exists() )
         {
             confUsed.delete();
         }
         FileUtils.copyFile( originalConf, confUsed );
-        
+
         super.setUp();
     }
 
     public void testLoad()
         throws Exception
     {
-        ContinuumConfiguration configuration =
-            (ContinuumConfiguration) lookup( ContinuumConfiguration.class, "default" );
+        ContinuumConfiguration configuration = (ContinuumConfiguration) lookup( ContinuumConfiguration.class,
+                                                                                "default" );
         assertNotNull( configuration );
         GeneralConfiguration generalConfiguration = configuration.getGeneralConfiguration();
         assertNotNull( generalConfiguration );
         assertNotNull( generalConfiguration.getBaseUrl() );
         assertEquals( "http://test", generalConfiguration.getBaseUrl() );
         assertEquals( new File( "myBuildOutputDir" ), generalConfiguration.getBuildOutputDirectory() );
+        assertTrue( generalConfiguration.isDistributedBuildEnabled() );
         assertNotNull( generalConfiguration.getBuildAgents() );
-        org.apache.continuum.configuration.BuildAgentConfiguration buildAgentConfig = generalConfiguration.getBuildAgents().get( 0 );
+        org.apache.continuum.configuration.BuildAgentConfiguration buildAgentConfig =
+            generalConfiguration.getBuildAgents().get( 0 );
         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 = buildAgentGroupConfig.getBuildAgents().get( 0 );
+        assertEquals( "http://buildagent/xmlrpc", agentConfig.getUrl() );
+        assertEquals( "linux", agentConfig.getDescription() );
     }
 
     public void testDefaultConfiguration()
@@ -84,23 +94,39 @@
         {
             conf.delete();
         }
-        ContinuumConfiguration configuration =
-            (ContinuumConfiguration) lookup( ContinuumConfiguration.class, "default" );
+        ContinuumConfiguration configuration = (ContinuumConfiguration) lookup( ContinuumConfiguration.class,
+                                                                                "default" );
         assertNotNull( configuration );
         GeneralConfiguration generalConfiguration = new GeneralConfiguration();
         generalConfiguration.setBaseUrl( "http://test/zloug" );
         generalConfiguration.setProxyConfiguration( new ProxyConfiguration() );
         generalConfiguration.getProxyConfiguration().setProxyHost( "localhost" );
         generalConfiguration.getProxyConfiguration().setProxyPort( 8080 );
-        File targetDir = new File(getBasedir(), "target");
+        File targetDir = new File( getBasedir(), "target" );
         generalConfiguration.setBuildOutputDirectory( targetDir );
         BuildAgentConfiguration buildAgentConfiguration = new BuildAgentConfiguration();
         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.setDistributedBuildEnabled( false );
         generalConfiguration.setBuildAgents( buildAgents );
+        generalConfiguration.setBuildAgentGroups( buildAgentGroups );
         configuration.setGeneralConfiguration( generalConfiguration );
         configuration.save();
 
@@ -110,14 +136,31 @@
         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( targetDir.getPath(),
+                      configuration.getGeneralConfiguration().getBuildOutputDirectory().getPath() );
+        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() );
+        assertFalse( configuration.getGeneralConfiguration().isDistributedBuildEnabled() );
         log.info( "generalConfiguration " + configuration.getGeneralConfiguration().toString() );
     }
 }
diff --git a/continuum-base/continuum-configuration/src/test/resources/conf/continuum.xml b/continuum-base/continuum-configuration/src/test/resources/conf/continuum.xml
index f3c61f1..4abf386 100644
--- a/continuum-base/continuum-configuration/src/test/resources/conf/continuum.xml
+++ b/continuum-base/continuum-configuration/src/test/resources/conf/continuum.xml
@@ -1,7 +1,27 @@
 <?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
 <continuum-configuration>
   <baseUrl>http://test</baseUrl>
   <buildOutputDirectory>myBuildOutputDir</buildOutputDirectory>
+  <distributedBuildEnabled>true</distributedBuildEnabled>
   <buildAgents>
     <buildAgent>
       <url>http://buildagent/xmlrpc</url>
@@ -9,4 +29,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
diff --git a/continuum-base/continuum-configuration/src/test/resources/log4j.xml b/continuum-base/continuum-configuration/src/test/resources/log4j.xml
deleted file mode 100644
index b8670cc..0000000
--- a/continuum-base/continuum-configuration/src/test/resources/log4j.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
-<!-- ===================================================================== -->
-<!-- Log4j Configuration -->
-<!-- ===================================================================== -->
-
-<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
-  debug="false">
-
-  <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
-    <param name="Target" value="System.out"/>
-    <layout class="org.apache.log4j.PatternLayout">
-      <param name="ConversionPattern" value="%d %-5p [%c{1}.%M](%L) %m%n"/>
-    </layout>
-  </appender>
-
-  <!-- quiet spring loading :-) -->
-  <category name="org.springframework">
-    <priority value="ERROR"/>
-  </category>
-  <category name="org.codehaus.plexus">
-    <priority value="ERROR"/>
-  </category>
-  <category name="org.apache.continuum.configuration">
-    <priority value="DEBUG"/>
-  </category>
-  
-  <category name="org.apache.commons.configuration">
-    <priority value="debug"/>
-  </category>    
-
-  <!-- JPOX -->
-  <category name="JPOX">
-    <priority value="WARN"/>
-  </category>
-  <category name="JPOX.RDBMS">
-    <priority value="ERROR"/>
-  </category>
-
-  <root>
-    <priority value="INFO"/>
-    <appender-ref ref="CONSOLE"/>
-  </root>
-
-</log4j:configuration>
diff --git a/continuum-base/continuum-scm/pom.xml b/continuum-base/continuum-scm/pom.xml
index 2777ee0..5708692 100644
--- a/continuum-base/continuum-scm/pom.xml
+++ b/continuum-base/continuum-scm/pom.xml
@@ -1,80 +1,86 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
+  ~ 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.
+  -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <artifactId>continuum-base</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>continuum-scm</artifactId>
   <name>Continuum :: SCM</name>
-  <!--  TODO: move versions to dependency management -->
   <dependencies>
     <dependency>
       <groupId>org.apache.maven.scm</groupId>
       <artifactId>maven-scm-api</artifactId>
-      <version>${maven-scm.version}</version>
     </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
-      <version>1.5.0</version>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-simple</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>jcl-over-slf4j</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-beans</artifactId>
     </dependency>
     <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-context</artifactId>
-      <version>${spring.version}</version>
     </dependency>
     <dependency>
-      <groupId>org.codehaus.plexus</groupId>
+      <groupId>org.codehaus.redback</groupId>
       <artifactId>plexus-spring</artifactId>
-    </dependency>   
+    </dependency>
     <dependency>
       <groupId>javax.annotation</groupId>
       <artifactId>jsr250-api</artifactId>
-    </dependency>      
+    </dependency>
     <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-simple</artifactId>
-      <version>1.5.0</version>
-      <scope>test</scope>
+      <groupId>org.apache.maven.scm</groupId>
+      <artifactId>maven-scm-provider-git-commons</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.maven.scm</groupId>
       <artifactId>maven-scm-provider-svnexe</artifactId>
-      <version>${maven-scm.version}</version>
       <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.apache.maven.scm</groupId>
       <artifactId>maven-scm-provider-cvsjava</artifactId>
-      <version>${maven-scm.version}</version>
-      <scope>test</scope>      
+      <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.apache.maven.scm</groupId>
       <artifactId>maven-scm-provider-cvsexe</artifactId>
-      <version>${maven-scm.version}</version>
-      <scope>test</scope>      
-    </dependency>    
+      <scope>test</scope>
+    </dependency>
     <dependency>
       <groupId>commons-io</groupId>
       <artifactId>commons-io</artifactId>
@@ -83,5 +89,45 @@
       <groupId>commons-lang</groupId>
       <artifactId>commons-lang</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.jmock</groupId>
+      <artifactId>jmock</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jmock</groupId>
+      <artifactId>jmock-junit3</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.hamcrest</groupId>
+      <artifactId>hamcrest-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>cglib</groupId>
+      <artifactId>cglib-nodep</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.objenesis</groupId>
+      <artifactId>objenesis</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.rat</groupId>
+          <artifactId>apache-rat-plugin</artifactId>
+          <configuration>
+            <excludes>
+              <exclude>src/test/resources/**/svnlog*.txt</exclude>
+            </excludes>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
 </project>
diff --git a/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/ContinuumScm.java b/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/ContinuumScm.java
index 9fc45b4..e1581f9 100644
--- a/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/ContinuumScm.java
+++ b/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/ContinuumScm.java
@@ -19,43 +19,56 @@
  * under the License.
  */
 
-import java.io.IOException;
-
 import org.apache.maven.scm.ScmException;
+import org.apache.maven.scm.command.changelog.ChangeLogScmResult;
 import org.apache.maven.scm.command.checkout.CheckOutScmResult;
 import org.apache.maven.scm.command.update.UpdateScmResult;
 import org.apache.maven.scm.manager.NoSuchScmProviderException;
 import org.apache.maven.scm.repository.ScmRepositoryException;
 
+import java.io.IOException;
+
 /**
  * Component that manages SCM interactions and checkouts within Continuum.
- * 
+ *
  * @version $Id$
  */
 public interface ContinuumScm
 {
     /**
      * Check out a working copy for a project.
-     * 
+     *
      * @param configuration the configuration for the working copy and SCM
      * @return the result of the check out
-     * @throws IOException if there is a problem writing to the working copy location
+     * @throws IOException                if there is a problem writing to the working copy location
      * @throws NoSuchScmProviderException if there is a problem with the configuration
-     * @throws ScmRepositoryException if there is a problem with the configuration
-     * @throws ScmException if there is a problem checking out
+     * @throws ScmRepositoryException     if there is a problem with the configuration
+     * @throws ScmException               if there is a problem checking out
      */
     CheckOutScmResult checkout( ContinuumScmConfiguration configuration )
         throws IOException, ScmRepositoryException, NoSuchScmProviderException, ScmException;
 
     /**
      * Update a working copy for a project.
-     * 
-     * @param configuration the configuration for the working copy and SCM
+     *
+     * @param config the configuration for the working copy and SCM
      * @return the result of the update
      * @throws NoSuchScmProviderException if there is a problem with the configuration
-     * @throws ScmRepositoryException if there is a problem with the configuration
-     * @throws ScmException if there is a problem updating
+     * @throws ScmRepositoryException     if there is a problem with the configuration
+     * @throws ScmException               if there is a problem updating
      */
     UpdateScmResult update( ContinuumScmConfiguration config )
         throws ScmRepositoryException, NoSuchScmProviderException, ScmException;
+
+    /**
+     * Get change log for a project
+     *
+     * @param config the configuration for the working copy and SCM
+     * @return the result of the change log
+     * @throws ScmRepositoryException     if there is a problem with the configuration
+     * @throws NoSuchScmProviderException if there is a problem with the configuration
+     * @throws ScmException               if there is a problem getting the change log
+     */
+    ChangeLogScmResult changeLog( ContinuumScmConfiguration config )
+        throws ScmRepositoryException, NoSuchScmProviderException, ScmException;
 }
diff --git a/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/ContinuumScmConfiguration.java b/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/ContinuumScmConfiguration.java
index 4f9560f..cd670b7 100644
--- a/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/ContinuumScmConfiguration.java
+++ b/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/ContinuumScmConfiguration.java
@@ -24,14 +24,15 @@
 
 /**
  * Configuration for a project's source control.
- * 
- * @todo JAXB for persistence
- * 
+ *
  * @version $Id$
+ * @todo JAXB for persistence
  */
 public class ContinuumScmConfiguration
 {
-    /** The SCM URL, in the format specified by Maven SCM. */
+    /**
+     * The SCM URL, in the format specified by Maven SCM.
+     */
     private String url;
 
     /**
@@ -41,33 +42,35 @@
 
     /**
      * The SCM password to use in connecting.
-     * 
+     *
      * @todo using some service to obtain this rather than configuring it would be preferable
      */
     private String password;
 
-    /** The tag, branch, or equivalent to check out from. */
+    /**
+     * The tag, branch, or equivalent to check out from.
+     */
     private String tag;
 
     /**
      * The location of the working directory.
-     * 
+     *
      * @todo is this a File that is absolute, or is it a relative path under the working directories? How will JAXB
-     *       manage? Don't want to store absolute path in the config unless that's what the user configured, so the base
-     *       can be relocated.
+     * manage? Don't want to store absolute path in the config unless that's what the user configured, so the base
+     * can be relocated.
      */
     private File workingDirectory;
 
     /**
      * For SCM clients that support it, use cached credentials on the system to avoid needing to pass them in.
-     * 
+     *
      * @todo using some service to obtain them rather than configuring it would be preferable
      */
     private boolean useCredentialsCache;
 
     /**
      * What was the last time this checkout was updated.
-     * 
+     *
      * @todo we need to improve on the techniques to achieve this
      */
     private Date latestUpdateDate;
@@ -136,7 +139,7 @@
     {
         return latestUpdateDate;
     }
-    
+
     public void setLatestUpdateDate( Date latestUpdateDate )
     {
         this.latestUpdateDate = latestUpdateDate;
diff --git a/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/ContinuumScmUtils.java b/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/ContinuumScmUtils.java
new file mode 100644
index 0000000..835899c
--- /dev/null
+++ b/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/ContinuumScmUtils.java
@@ -0,0 +1,84 @@
+package org.apache.continuum.scm;
+
+/*
+ * 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 org.apache.commons.lang.StringUtils;
+import org.apache.maven.scm.provider.ScmUrlUtils;
+import org.apache.maven.scm.provider.git.repository.GitScmProviderRepository;
+
+/**
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ */
+public class ContinuumScmUtils
+{
+    public static final String GIT_SCM_PROVIDERTYPE = "git";
+
+    // CONTINUUM-2628
+    public static ContinuumScmConfiguration setSCMCredentialsforSSH( ContinuumScmConfiguration config, String scmUrl,
+                                                                     String scmUsername, String scmPassword )
+    {
+        String sshScmUsername = "";
+        String sshScmPassword = "";
+        String providerType = ScmUrlUtils.getProvider( scmUrl );
+
+        String scmSpecificUrl = scmUrl.substring( providerType.length() + 5 );
+
+        if ( providerType.contains( GIT_SCM_PROVIDERTYPE ) && scmSpecificUrl.startsWith(
+            GitScmProviderRepository.PROTOCOL_SSH ) )
+        {
+            scmSpecificUrl = scmSpecificUrl.substring( GitScmProviderRepository.PROTOCOL_SSH.length() + 3 );
+
+            // extract user information
+            int indexAt = scmSpecificUrl.indexOf( "@" );
+            if ( indexAt >= 0 )
+            {
+                String userInfo = scmSpecificUrl.substring( 0, indexAt );
+                sshScmUsername = userInfo;
+                int indexPwdSep = userInfo.indexOf( ":" );
+                // password is specified in the url
+                if ( indexPwdSep < 0 )
+                {
+                    sshScmUsername = userInfo.substring( indexPwdSep + 1 );
+                }
+                else
+                {
+                    sshScmUsername = userInfo.substring( 0, indexPwdSep );
+                    sshScmPassword = userInfo.substring( indexPwdSep + 1 );
+                }
+            }
+        }
+
+        if ( StringUtils.isBlank( sshScmUsername ) )
+        {
+            config.setUsername( scmUsername );
+            config.setPassword( scmPassword );
+        }
+        else
+        {
+            config.setUsername( sshScmUsername );
+            if ( !StringUtils.isBlank( sshScmPassword ) )
+            {
+                config.setPassword( sshScmPassword );
+            }
+        }
+
+        return config;
+    }
+}
diff --git a/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/DefaultContinuumScm.java b/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/DefaultContinuumScm.java
index eba994d..ab9be67 100644
--- a/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/DefaultContinuumScm.java
+++ b/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/DefaultContinuumScm.java
@@ -19,17 +19,13 @@
  * under the License.
  */
 
-import java.io.File;
-import java.io.IOException;
-
-import javax.annotation.Resource;
-
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.maven.scm.ScmException;
 import org.apache.maven.scm.ScmFileSet;
 import org.apache.maven.scm.ScmTag;
 import org.apache.maven.scm.ScmVersion;
+import org.apache.maven.scm.command.changelog.ChangeLogScmResult;
 import org.apache.maven.scm.command.checkout.CheckOutScmResult;
 import org.apache.maven.scm.command.update.UpdateScmResult;
 import org.apache.maven.scm.manager.NoSuchScmProviderException;
@@ -38,17 +34,24 @@
 import org.apache.maven.scm.repository.ScmRepositoryException;
 import org.springframework.stereotype.Service;
 
+import java.io.File;
+import java.io.IOException;
+import java.util.Calendar;
+import java.util.Date;
+import javax.annotation.Resource;
+
 /**
  * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
- * @todo consider folding some of this into Maven SCM itself
- * 
  * @version $Id$
+ * @todo consider folding some of this into Maven SCM itself
  */
-@Service("continuumScm")
+@Service( "continuumScm" )
 public class DefaultContinuumScm
     implements ContinuumScm
 {
-    /** The Maven SCM manager to use. */
+    /**
+     * The Maven SCM manager to use.
+     */
     @Resource
     private ScmManager scmManager;
 
@@ -108,8 +111,9 @@
         if ( !workingDirectory.exists() )
         {
             // TODO: maybe we could check it out - it seems we currently rely on Continuum figuring this out
-            throw new IllegalStateException( "The working directory for the project doesn't exist " + "("
-                + workingDirectory.getAbsolutePath() + ")." );
+            throw new IllegalStateException(
+                "The working directory for the project doesn't exist " + "(" + workingDirectory.getAbsolutePath() +
+                    ")." );
         }
 
         ScmRepository repository = getScmRepository( configuration );
@@ -137,12 +141,43 @@
         return result;
     }
 
+    public ChangeLogScmResult changeLog( ContinuumScmConfiguration configuration )
+        throws ScmException
+    {
+        ScmVersion scmVersion = getScmVersion( configuration );
+        Date startDate = null;
+
+        // TODO: probably need to base this from a working directory in the main configuration
+        File workingDirectory = configuration.getWorkingDirectory();
+
+        ScmRepository repository = getScmRepository( configuration );
+
+        ChangeLogScmResult result;
+
+        ScmFileSet fileSet = new ScmFileSet( workingDirectory );
+
+        if ( scmVersion == null || StringUtils.isBlank( scmVersion.getName() ) )
+        {
+            // let's get the start date instead
+            startDate = getScmStartDate( configuration );
+
+            result = scmManager.changeLog( repository, fileSet, startDate, null, 0, null, null );
+        }
+        else
+        {
+            result = scmManager.changeLog( repository, fileSet, scmVersion, scmVersion );
+        }
+
+        return result;
+    }
+
     /**
      * Create a Maven SCM repository for obtaining the checkout from.
-     * 
-     * @param scmUrl the SCM URL to obtain the checkout from
-     * @param useCredentialsCache whether to allow the use of cached credentials for SVN
+     *
+     * @param configuration the configuration for the working copy and SCM
      * @return the repository created
+     * @throws NoSuchScmProviderException
+     * @throws ScmRepositoryException
      */
     private ScmRepository getScmRepository( ContinuumScmConfiguration configuration )
         throws ScmRepositoryException, NoSuchScmProviderException
@@ -183,6 +218,21 @@
         return repository;
     }
 
+    private Date getScmStartDate( ContinuumScmConfiguration configuration )
+    {
+        Date startDate = configuration.getLatestUpdateDate();
+
+        if ( startDate == null )
+        {
+            // start date defaults to January 1, 1970
+            Calendar cal = Calendar.getInstance();
+            cal.set( 1970, Calendar.JANUARY, 1 );
+            startDate = cal.getTime();
+        }
+
+        return startDate;
+    }
+
     public ScmManager getScmManager()
     {
         return scmManager;
diff --git a/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/manager/ScmManager.java b/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/manager/ScmManager.java
index fbbe5fb..b053994 100644
--- a/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/manager/ScmManager.java
+++ b/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/manager/ScmManager.java
@@ -19,23 +19,22 @@
  * under the License.
  */
 
-import java.util.Map;
-
 import org.apache.maven.scm.log.ScmLogger;
 import org.apache.maven.scm.manager.AbstractScmManager;
 
+import java.util.Map;
+
 /**
  * Default implementation of the SCM manager.
- * 
- * @todo move to maven-scm as the default 
- * 
+ *
  * @version $Id$
+ * @todo move to maven-scm as the default
  */
 public class ScmManager
     extends AbstractScmManager
 {
     private ScmLogger scmLogger;
-    
+
     @Override
     protected ScmLogger getScmLogger()
     {
diff --git a/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/manager/Slf4jScmLogger.java b/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/manager/Slf4jScmLogger.java
index 31074d4..759046c 100644
--- a/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/manager/Slf4jScmLogger.java
+++ b/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/manager/Slf4jScmLogger.java
@@ -26,15 +26,15 @@
 
 /**
  * SLF4J logger for Maven SCM.
- * @todo move to maven-scm? 
- * 
+ *
  * @version $Id$
+ * @todo move to maven-scm?
  */
-@Service("scmLogger")
+@Service( "scmLogger" )
 public class Slf4jScmLogger
     implements ScmLogger
 {
-    private Logger logger = LoggerFactory.getLogger( Slf4jScmLogger.class );
+    private static final Logger logger = LoggerFactory.getLogger( Slf4jScmLogger.class );
 
     public void debug( String arg0 )
     {
diff --git a/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/manager/spring/ScmProviderFactoryBean.java b/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/manager/spring/ScmProviderFactoryBean.java
index 3579348..6095816 100644
--- a/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/manager/spring/ScmProviderFactoryBean.java
+++ b/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/manager/spring/ScmProviderFactoryBean.java
@@ -19,9 +19,6 @@
  * under the License.
  */
 
-import java.util.HashMap;
-import java.util.Map;
-
 import org.apache.maven.scm.provider.ScmProvider;
 import org.codehaus.plexus.spring.PlexusToSpringUtils;
 import org.springframework.beans.BeansException;
@@ -29,15 +26,17 @@
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationContextAware;
 
+import java.util.Map;
+
 /**
  * <p>
  * Factory bean to inject all beans of type {@link ScmProvider}
  * </p>
  * <p>
  * <code>&lt;bean id="scmProviders" class="org.apache.continuum.scm.manager.spring.ScmManagerFactoryBean"/>
- </code>
+ * </code>
  * </p>
- * 
+ *
  * @author Carlos Sanchez <carlos@apache.org>
  * @version $Id$
  */
@@ -45,15 +44,16 @@
     implements FactoryBean, ApplicationContextAware
 {
     private ApplicationContext applicationContext;
-   
+
     /**
-     * FIXME : change how we find scm implementations 
+     * FIXME : change how we find scm implementations
+     *
      * @see org.springframework.beans.factory.FactoryBean#getObject()
      */
     public Object getObject()
         throws Exception
     {
-        Map<String, ScmProvider> providers = new HashMap<String, ScmProvider>();
+        Map<String, ScmProvider> providers;
         /*
          olamy : comment the pure spring use because we have a duplicate between cvs java and cvs native
           
@@ -78,7 +78,8 @@
             }
             providers.put( provider.getScmType(), provider );
         }*/
-        providers =  PlexusToSpringUtils.lookupMap(PlexusToSpringUtils.buildSpringId( ScmProvider.class ), applicationContext );
+        providers = PlexusToSpringUtils.lookupMap( PlexusToSpringUtils.buildSpringId( ScmProvider.class ),
+                                                   applicationContext );
         return providers;
     }
 
diff --git a/continuum-base/continuum-scm/src/main/resources/META-INF/spring-context.xml b/continuum-base/continuum-scm/src/main/resources/META-INF/spring-context.xml
index c936b20..3cbae7c 100644
--- a/continuum-base/continuum-scm/src/main/resources/META-INF/spring-context.xml
+++ b/continuum-base/continuum-scm/src/main/resources/META-INF/spring-context.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
+
 <!--
   ~ Licensed to the Apache Software Foundation (ASF) under one
   ~ or more contributor license agreements.  See the NOTICE file
@@ -17,6 +18,7 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
   -->
+
 <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
@@ -25,11 +27,11 @@
                 http://www.springframework.org/schema/context
                 http://www.springframework.org/schema/context/spring-context-2.5.xsd">
 
-  <context:annotation-config />
+  <context:annotation-config/>
   <context:component-scan base-package="org.apache.continuum.scm"/>
 
   <bean id="scmManager" class="org.apache.continuum.scm.manager.ScmManager">
-    <property name="scmLogger" ref="scmLogger" />
+    <property name="scmLogger" ref="scmLogger"/>
     <property name="scmProviders">
       <bean class="org.apache.continuum.scm.manager.spring.ScmProviderFactoryBean"/>
     </property>
diff --git a/continuum-base/continuum-scm/src/test/java/org/apache/continuum/scm/ContinuumScmUtilsTest.java b/continuum-base/continuum-scm/src/test/java/org/apache/continuum/scm/ContinuumScmUtilsTest.java
new file mode 100644
index 0000000..2feaf46
--- /dev/null
+++ b/continuum-base/continuum-scm/src/test/java/org/apache/continuum/scm/ContinuumScmUtilsTest.java
@@ -0,0 +1,95 @@
+package org.apache.continuum.scm;
+
+/*
+ * 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 junit.framework.TestCase;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ */
+public class ContinuumScmUtilsTest
+    extends TestCase
+{
+    public void testGitProviderWithSSHProtocolUsernameInUrl()
+        throws Exception
+    {
+        ContinuumScmConfiguration scmConfiguration = new ContinuumScmConfiguration();
+
+        scmConfiguration = ContinuumScmUtils.setSCMCredentialsforSSH( scmConfiguration,
+                                                                      "scm:git:ssh://sshUser@gitrepo.com/myproject.git",
+                                                                      "dummyuser", "dummypassword" );
+
+        assertEquals( "sshUser", scmConfiguration.getUsername() );
+        assertTrue( StringUtils.isBlank( scmConfiguration.getPassword() ) );
+    }
+
+    public void testGitProviderWithSSHProtocolUsernameAndPasswordInUrl()
+        throws Exception
+    {
+        ContinuumScmConfiguration scmConfiguration = new ContinuumScmConfiguration();
+
+        scmConfiguration = ContinuumScmUtils.setSCMCredentialsforSSH( scmConfiguration,
+                                                                      "scm:git:ssh://sshUser:sshPassword@gitrepo.com/myproject.git",
+                                                                      "dummyuser", "dummypassword" );
+
+        assertEquals( "sshUser", scmConfiguration.getUsername() );
+        assertEquals( "sshPassword", scmConfiguration.getPassword() );
+    }
+
+    public void testGitProviderWithSSHProtocolNoCredentialsInUrl()
+        throws Exception
+    {
+        ContinuumScmConfiguration scmConfiguration = new ContinuumScmConfiguration();
+
+        scmConfiguration = ContinuumScmUtils.setSCMCredentialsforSSH( scmConfiguration,
+                                                                      "scm:git:ssh://gitrepo.com/myproject.git",
+                                                                      "dummyuser", "dummypassword" );
+
+        assertEquals( "dummyuser", scmConfiguration.getUsername() );
+        assertEquals( "dummypassword", scmConfiguration.getPassword() );
+    }
+
+    public void testNotGitProvider()
+        throws Exception
+    {
+        ContinuumScmConfiguration scmConfiguration = new ContinuumScmConfiguration();
+
+        scmConfiguration = ContinuumScmUtils.setSCMCredentialsforSSH( scmConfiguration,
+                                                                      "scm:svn:ssh://svnrepo.com/repos/myproject/trunk",
+                                                                      "dummyuser", "dummypassword" );
+
+        assertEquals( "dummyuser", scmConfiguration.getUsername() );
+        assertEquals( "dummypassword", scmConfiguration.getPassword() );
+    }
+
+    public void testNotSSHProtocol()
+        throws Exception
+    {
+        ContinuumScmConfiguration scmConfiguration = new ContinuumScmConfiguration();
+
+        scmConfiguration = ContinuumScmUtils.setSCMCredentialsforSSH( scmConfiguration,
+                                                                      "scm:git:https://gitrepo.com/myproject.git",
+                                                                      "dummyuser", "dummypassword" );
+
+        assertEquals( "dummyuser", scmConfiguration.getUsername() );
+        assertEquals( "dummypassword", scmConfiguration.getPassword() );
+    }
+}
diff --git a/continuum-base/continuum-scm/src/test/java/org/apache/continuum/scm/DefaultContinuumScmTest.java b/continuum-base/continuum-scm/src/test/java/org/apache/continuum/scm/DefaultContinuumScmTest.java
new file mode 100644
index 0000000..646cde8
--- /dev/null
+++ b/continuum-base/continuum-scm/src/test/java/org/apache/continuum/scm/DefaultContinuumScmTest.java
@@ -0,0 +1,107 @@
+package org.apache.continuum.scm;
+
+/*
+ * 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 junit.framework.TestCase;
+import org.apache.continuum.scm.manager.ScmManager;
+import org.apache.maven.scm.ScmBranch;
+import org.apache.maven.scm.ScmFileSet;
+import org.apache.maven.scm.ScmVersion;
+import org.apache.maven.scm.repository.ScmRepository;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.integration.junit3.JUnit3Mockery;
+import org.jmock.lib.legacy.ClassImposteriser;
+
+import java.io.File;
+import java.util.Date;
+
+public class DefaultContinuumScmTest
+    extends TestCase
+{
+    private ScmManager scmManager;
+
+    private DefaultContinuumScm continuumScm;
+
+    private Mockery context;
+
+    private ContinuumScmConfiguration config;
+
+    @Override
+    public void setUp()
+    {
+        context = new JUnit3Mockery();
+        context.setImposteriser( ClassImposteriser.INSTANCE );
+
+        scmManager = context.mock( ScmManager.class );
+
+        continuumScm = new DefaultContinuumScm();
+        continuumScm.setScmManager( scmManager );
+
+        config = getScmConfiguration();
+    }
+
+    public void testChangeLogWithScmVersion()
+        throws Exception
+    {
+        config.setTag( "1.0-SNAPSHOT" );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( scmManager ).makeScmRepository( config.getUrl() );
+                one( scmManager ).changeLog( with( any( ScmRepository.class ) ), with( any( ScmFileSet.class ) ), with(
+                    any( ScmVersion.class ) ), with( any( ScmVersion.class ) ) );
+            }
+        } );
+
+        continuumScm.changeLog( config );
+
+        context.assertIsSatisfied();
+    }
+
+    public void testChangeLogWithNoScmVersion()
+        throws Exception
+    {
+        config.setTag( "" );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( scmManager ).makeScmRepository( config.getUrl() );
+                one( scmManager ).changeLog( with( any( ScmRepository.class ) ), with( any( ScmFileSet.class ) ), with(
+                    any( Date.class ) ), with( aNull( Date.class ) ), with( equal( 0 ) ), with( aNull(
+                    ScmBranch.class ) ), with( aNull( String.class ) ) );
+            }
+        } );
+
+        continuumScm.changeLog( config );
+        context.assertIsSatisfied();
+    }
+
+    private ContinuumScmConfiguration getScmConfiguration()
+    {
+        ContinuumScmConfiguration config = new ContinuumScmConfiguration();
+        config.setWorkingDirectory( new File( "1" ) );
+        config.setUrl( "scm:svn:http://svn.apache.org/repos/asf/maven/plugins/trunk/maven-clean-plugin" );
+
+        return config;
+    }
+}
diff --git a/continuum-base/continuum-scm/src/test/java/org/apache/continuum/scm/ScmSanityTest.java b/continuum-base/continuum-scm/src/test/java/org/apache/continuum/scm/ScmSanityTest.java
new file mode 100644
index 0000000..a2fc83c
--- /dev/null
+++ b/continuum-base/continuum-scm/src/test/java/org/apache/continuum/scm/ScmSanityTest.java
@@ -0,0 +1,69 @@
+package org.apache.continuum.scm;
+
+/*
+ * 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 junit.framework.TestCase;
+import org.apache.maven.scm.ChangeSet;
+import org.apache.maven.scm.log.DefaultLog;
+import org.apache.maven.scm.provider.svn.svnexe.command.changelog.SvnChangeLogConsumer;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.List;
+
+/**
+ * Tests to verify assumptions and avoid regressions in SCM dependencies.
+ */
+public class ScmSanityTest
+    extends TestCase
+{
+
+    private InputStream getTestInput( String path )
+    {
+        return ScmSanityTest.class.getResourceAsStream( path );
+    }
+
+    /**
+     * Tests that CONTINUUM-1640 is fixed by updated maven-scm
+     */
+    public void testSvnLogWithSpaceInAuthorWorks()
+        throws Exception
+    {
+        SvnChangeLogConsumer consumer = new SvnChangeLogConsumer( new DefaultLog(), null );
+        InputStream input = getTestInput( "svnlog-with-space-in-author.txt" );
+        BufferedReader r = new BufferedReader( new InputStreamReader( input ) );
+        String line;
+
+        while ( ( line = r.readLine() ) != null )
+        {
+            consumer.consumeLine( line );
+        }
+
+        List modifications = consumer.getModifications();
+        assertEquals( 2, modifications.size() );
+
+        ChangeSet firstEntry = (ChangeSet) modifications.get( 0 );
+        assertEquals( "Immanuel Scheerer", firstEntry.getAuthor() );
+
+        ChangeSet secondEntry = (ChangeSet) modifications.get( 1 );
+        assertEquals( "Immanuel Scheerer", secondEntry.getAuthor() );
+    }
+}
diff --git a/continuum-base/continuum-scm/src/test/java/org/apache/continuum/scm/manager/ScmManagerTest.java b/continuum-base/continuum-scm/src/test/java/org/apache/continuum/scm/manager/ScmManagerTest.java
index 8cb5f79..7032e2c 100644
--- a/continuum-base/continuum-scm/src/test/java/org/apache/continuum/scm/manager/ScmManagerTest.java
+++ b/continuum-base/continuum-scm/src/test/java/org/apache/continuum/scm/manager/ScmManagerTest.java
@@ -19,10 +19,7 @@
  * under the License.
  */
 
-import java.util.Properties;
-
 import junit.framework.TestCase;
-
 import org.apache.maven.scm.manager.NoSuchScmProviderException;
 import org.apache.maven.scm.provider.ScmProvider;
 import org.apache.maven.scm.provider.cvslib.cvsexe.CvsExeScmProvider;
@@ -32,26 +29,24 @@
 import org.slf4j.LoggerFactory;
 import org.springframework.context.ApplicationContext;
 
+import java.util.Properties;
+
 /**
- * @todo replace with a spring integration test
- * 
  * @version $Id$
+ * @todo replace with a spring integration test
  */
 public class ScmManagerTest
     extends TestCase
 {
-    private ApplicationContext context;
+    private static final Logger log = LoggerFactory.getLogger( ScmManagerTest.class );
 
     private ScmManager manager;
-    
-    private Logger log = LoggerFactory.getLogger( getClass() );
 
     public void setUp()
     {
-        context =
-            new PlexusClassPathXmlApplicationContext( new String[] { "classpath*:META-INF/spring-context.xml",
-                "classpath*:META-INF/plexus/components.xml",
-                "classpath*:" + getClass().getName().replace( '.', '/' ) + ".xml" } );
+        ApplicationContext context = new PlexusClassPathXmlApplicationContext(
+            new String[]{"classpath*:META-INF/spring-context.xml", "classpath*:META-INF/plexus/components.xml",
+                "classpath*:" + getClass().getName().replace( '.', '/' ) + ".xml"} );
         manager = (ScmManager) context.getBean( "scmManager" );
     }
 
@@ -93,6 +88,6 @@
             System.setProperties( backupSysProps );
             System.setProperty( "maven.scm.provider.cvs.implementation", "cvs" );
         }
-        
+
     }
 }
diff --git a/continuum-base/continuum-scm/src/test/resources/log4j.xml b/continuum-base/continuum-scm/src/test/resources/log4j.xml
deleted file mode 100644
index 0f10462..0000000
--- a/continuum-base/continuum-scm/src/test/resources/log4j.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
-<!-- ===================================================================== -->
-<!-- Log4j Configuration -->
-<!-- ===================================================================== -->
-
-<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
-  debug="false">
-
-    <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
-        <param name="Target" value="System.out"/>
-        <layout class="org.apache.log4j.PatternLayout">
-            <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}.%M](%L) %m%n"/>
-        </layout>
-    </appender>
-
-    <!-- quiet spring loading :-) -->
-    <category name="org.springframework.beans.factory.xml.XmlBeanDefinitionReader">
-        <priority value="ERROR"/>
-    </category>
-    <category name="org.springframework.beans.factory.support.DefaultListableBeanFactory">
-        <priority value="ERROR"/>
-    </category>
-
-    <!-- JPOX -->
-    <category name="JPOX">
-        <priority value="WARN"/>
-    </category>
-    <category name="JPOX.RDBMS">
-        <priority value="ERROR"/>
-    </category>
-
-    <root>
-        <priority value="WARN"/>
-        <appender-ref ref="CONSOLE"/>
-    </root>
-
-</log4j:configuration>
\ No newline at end of file
diff --git a/continuum-base/continuum-scm/src/test/resources/org/apache/continuum/scm/svnlog-with-space-in-author.txt b/continuum-base/continuum-scm/src/test/resources/org/apache/continuum/scm/svnlog-with-space-in-author.txt
new file mode 100644
index 0000000..1c7d33f
--- /dev/null
+++ b/continuum-base/continuum-scm/src/test/resources/org/apache/continuum/scm/svnlog-with-space-in-author.txt
@@ -0,0 +1,28 @@
+------------------------------------------------------------------------
+r15 | Immanuel Scheerer | 2002-08-26 14:33:26 -0400 (Mon, 26 Aug 2002) | 3 lines
+Changed paths:
+   M /poolserver/trunk/build.xml
+   M /poolserver/trunk/project.properties
+
+Minor formatting changes.
+
+------------------------------------------------------------------------
+r328167 | Immanuel Scheerer | 2005-10-25 00:14:48 +0200 (mar., 25 oct. 2005) | 1 line
+Changed paths:
+   M /maven/scm/trunk/maven-scm-api/pom.xml
+   M /maven/scm/trunk/maven-scm-client/pom.xml
+   M /maven/scm/trunk/maven-scm-managers/maven-scm-manager-plexus/pom.xml
+   M /maven/scm/trunk/maven-scm-managers/pom.xml
+   M /maven/scm/trunk/maven-scm-plugin/pom.xml
+   M /maven/scm/trunk/maven-scm-providers/maven-scm-provider-clearcase/pom.xml
+   M /maven/scm/trunk/maven-scm-providers/maven-scm-provider-cvs/pom.xml
+   M /maven/scm/trunk/maven-scm-providers/maven-scm-provider-local/pom.xml
+   M /maven/scm/trunk/maven-scm-providers/maven-scm-provider-perforce/pom.xml
+   M /maven/scm/trunk/maven-scm-providers/maven-scm-provider-starteam/pom.xml
+   M /maven/scm/trunk/maven-scm-providers/maven-scm-provider-svn/pom.xml
+   M /maven/scm/trunk/maven-scm-providers/pom.xml
+   M /maven/scm/trunk/maven-scm-test/pom.xml
+   M /maven/scm/trunk/pom.xml
+
+Fix new version
+------------------------------------------------------------------------
diff --git a/continuum-base/pom.xml b/continuum-base/pom.xml
index 9d4b5de..2cdb527 100644
--- a/continuum-base/pom.xml
+++ b/continuum-base/pom.xml
@@ -1,27 +1,28 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
+  ~ 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.
+  -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <artifactId>continuum</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>continuum-base</artifactId>
diff --git a/continuum-buildagent/continuum-buildagent-api/pom.xml b/continuum-buildagent/continuum-buildagent-api/pom.xml
new file mode 100644
index 0000000..5032a28
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-api/pom.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.continuum</groupId>
+    <artifactId>continuum-buildagent</artifactId>
+    <version>1.4.3</version>
+  </parent>
+
+  <artifactId>continuum-buildagent-api</artifactId>
+  <name>Continuum :: Distributed Build :: Build Agent API</name>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.codehaus.modello</groupId>
+        <artifactId>modello-maven-plugin</artifactId>
+        <configuration>
+          <models>
+            <model>src/main/mdo/continuum-buildagent.xml</model>
+          </models>
+          <useJava5>true</useJava5>
+          <version>1.4.1</version>
+        </configuration>
+        <executions>
+          <execution>
+            <id>continuum-modello</id>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>java</goal>
+              <goal>xpp3-reader</goal>
+              <goal>xpp3-writer</goal>
+            </goals>
+          </execution>
+          <execution>
+            <id>site-docs</id>
+            <phase>pre-site</phase>
+            <goals>
+              <goal>xdoc</goal>
+              <goal>xsd</goal>
+            </goals>
+          </execution>
+          <execution>
+            <id>generate-xsd</id>
+            <phase>generate-resources</phase>
+            <goals>
+              <goal>xsd</goal>
+            </goals>
+            <configuration>
+              <outputDirectory>${project.build.outputDirectory}/META-INF/continuum/xsd</outputDirectory>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>com.google.code.maven-replacer-plugin</groupId>
+        <artifactId>replacer</artifactId>
+        <executions>
+          <execution>
+            <id>replace-timestamp</id>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>replace</goal>
+            </goals>
+            <configuration>
+              <basedir>${basedir}</basedir>
+              <includes>
+                <include>target/generated-sources/**</include>
+              </includes>
+              <token>Generated by Modello.*</token>
+              <value>Generated by Modello</value>
+            </configuration>
+          </execution>
+          <execution>
+            <id>replace-site-timestamp</id>
+            <phase>pre-site</phase>
+            <goals>
+              <goal>replace</goal>
+            </goals>
+            <configuration>
+              <basedir>${basedir}</basedir>
+              <includes>
+                <include>target/generated-site/**</include>
+              </includes>
+              <token>Generated by Modello.* --&gt;</token>
+              <value>Generated by Modello --&gt;</value>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-utils</artifactId>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-api/src/main/java/org/apache/continuum/buildagent/ContinuumBuildAgentException.java b/continuum-buildagent/continuum-buildagent-api/src/main/java/org/apache/continuum/buildagent/ContinuumBuildAgentException.java
similarity index 100%
rename from continuum-distributed-build/continuum-buildagent/continuum-buildagent-api/src/main/java/org/apache/continuum/buildagent/ContinuumBuildAgentException.java
rename to continuum-buildagent/continuum-buildagent-api/src/main/java/org/apache/continuum/buildagent/ContinuumBuildAgentException.java
diff --git a/continuum-buildagent/continuum-buildagent-api/src/main/java/org/apache/continuum/buildagent/ContinuumBuildAgentService.java b/continuum-buildagent/continuum-buildagent-api/src/main/java/org/apache/continuum/buildagent/ContinuumBuildAgentService.java
new file mode 100644
index 0000000..0eef700
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-api/src/main/java/org/apache/continuum/buildagent/ContinuumBuildAgentService.java
@@ -0,0 +1,173 @@
+package org.apache.continuum.buildagent;
+
+/*
+ * 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.List;
+import java.util.Map;
+import java.util.Properties;
+
+public interface ContinuumBuildAgentService
+{
+    void buildProjects( List<Map<String, Object>> projectsBuildContext )
+        throws ContinuumBuildAgentException;
+
+    List<Map<String, String>> getAvailableInstallations()
+        throws ContinuumBuildAgentException;
+
+    Map<String, Object> getBuildResult( int projectId )
+        throws ContinuumBuildAgentException;
+
+    Map<String, Object> getProjectCurrentlyBuilding()
+        throws ContinuumBuildAgentException;
+
+    void cancelBuild()
+        throws ContinuumBuildAgentException;
+
+    String generateWorkingCopyContent( int projectId, String userDirectory, String baseUrl, String imagesBaseUrl )
+        throws ContinuumBuildAgentException;
+
+    Map<String, Object> getProjectFile( int projectId, String directory, String filename )
+        throws ContinuumBuildAgentException;
+
+    Map<String, Object> getReleasePluginParameters( int projectId, String pomFilename )
+        throws ContinuumBuildAgentException;
+
+    List<Map<String, String>> processProject( int projectId, String pomFilename, boolean autoVersionSubmodules )
+        throws ContinuumBuildAgentException;
+
+    String releasePrepare( Map project, Properties properties, Map releaseVersion, Map developmentVersion,
+                           Map<String, String> environments, String username )
+        throws ContinuumBuildAgentException;
+
+    Map<String, Object> getReleaseResult( String releaseId )
+        throws ContinuumBuildAgentException;
+
+    Map<String, Object> getListener( String releaseId )
+        throws ContinuumBuildAgentException;
+
+    void removeListener( String releaseId )
+        throws ContinuumBuildAgentException;
+
+    String getPreparedReleaseName( String releaseId )
+        throws ContinuumBuildAgentException;
+
+    void releasePerform( String releaseId, String goals, String arguments, boolean useReleaseProfile, Map repository,
+                         String username )
+        throws ContinuumBuildAgentException;
+
+    String releasePerformFromScm( String goals, String arguments, boolean useReleaseProfile, Map repository,
+                                  String scmUrl, String scmUsername, String scmPassword, String scmTag,
+                                  String scmTagBase, Map<String, String> environments, String username )
+        throws ContinuumBuildAgentException;
+
+    String releaseCleanup( String releaseId )
+        throws ContinuumBuildAgentException;
+
+    void releaseRollback( String releaseId, int projectId )
+        throws ContinuumBuildAgentException;
+
+    List<Map<String, Object>> getProjectsInPrepareBuildQueue()
+        throws ContinuumBuildAgentException;
+
+    List<Map<String, Object>> getProjectsAndBuildDefinitionsInPrepareBuildQueue()
+        throws ContinuumBuildAgentException;
+
+    List<Map<String, Object>> getProjectsInBuildQueue()
+        throws ContinuumBuildAgentException;
+
+    int getBuildSizeOfAgent()
+        throws ContinuumBuildAgentException;
+
+    Map<String, Object> getProjectCurrentlyPreparingBuild()
+        throws ContinuumBuildAgentException;
+
+    List<Map<String, Object>> getProjectsAndBuildDefinitionsCurrentlyPreparingBuild()
+        throws ContinuumBuildAgentException;
+
+    boolean isProjectGroupInQueue( int projectGroupId );
+
+    boolean isProjectScmRootInQueue( int projectScmRootId, List<Integer> projectIds );
+
+    boolean isProjectCurrentlyBuilding( int projectId, int buildDefinitionId );
+
+    boolean isProjectInBuildQueue( int projectId, int buildDefinitionId );
+
+    boolean isProjectGroupInPrepareBuildQueue( int projectGroupId );
+
+    boolean isProjectGroupCurrentlyPreparingBuild( int projectGroupId );
+
+    boolean isProjectInPrepareBuildQueue( int projectId, int buildDefinitionId );
+
+    boolean isProjectCurrentlyPreparingBuild( int projectId, int buildDefinitionId );
+
+    boolean removeFromPrepareBuildQueue( int projectGroupId, int scmRootId )
+        throws ContinuumBuildAgentException;
+
+    void removeFromPrepareBuildQueue( List<String> hashCodes )
+        throws ContinuumBuildAgentException;
+
+    boolean removeFromBuildQueue( int projectId, int builddefinitonId )
+        throws ContinuumBuildAgentException;
+
+    void removeFromBuildQueue( List<String> hashCodes )
+        throws ContinuumBuildAgentException;
+
+    boolean ping()
+        throws ContinuumBuildAgentException;
+
+    /**
+     * Get build agent's platform.
+     *
+     * @return The operating system name of the build agent
+     * @throws Exception
+     */
+    String getBuildAgentPlatform()
+        throws ContinuumBuildAgentException;
+
+    /**
+     * Determines if build agent is currently executing a build
+     *
+     * @return true if executing build; false otherwise
+     */
+    boolean isExecutingBuild();
+
+    /**
+     * Determines if build agent is currently executing a release
+     *
+     * @return true if executing release; false otherwise
+     * @throws ContinuumBuildAgentException if unable to determine if buildagent is executing a release
+     */
+    boolean isExecutingRelease()
+        throws ContinuumBuildAgentException;
+
+    /**
+     * Execute a directory purge on the build agent
+     *
+     * @param directoryType  valid types are <i>working</i> and <i>releases</i>
+     * @param daysOlder      days older
+     * @param retentionCount retention count
+     * @param deleteAll      delete all flag
+     * @return true if purge is successful; false otherwise
+     * @throws ContinuumBuildAgentException error that will occur during the purge
+     */
+    void executeDirectoryPurge( String directoryType, int daysOlder, int retentionCount, boolean deleteAll )
+        throws ContinuumBuildAgentException;
+
+}
diff --git a/continuum-buildagent/continuum-buildagent-api/src/main/java/org/apache/continuum/buildagent/NoBuildAgentException.java b/continuum-buildagent/continuum-buildagent-api/src/main/java/org/apache/continuum/buildagent/NoBuildAgentException.java
new file mode 100644
index 0000000..610dd1d
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-api/src/main/java/org/apache/continuum/buildagent/NoBuildAgentException.java
@@ -0,0 +1,39 @@
+package org.apache.continuum.buildagent;
+
+/*
+ * 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.
+ */
+
+public class NoBuildAgentException
+    extends Exception
+{
+    public NoBuildAgentException( String message )
+    {
+        super( message );
+    }
+
+    public NoBuildAgentException( Throwable cause )
+    {
+        super( cause );
+    }
+
+    public NoBuildAgentException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-api/src/main/java/org/apache/continuum/buildagent/NoBuildAgentInGroupException.java b/continuum-buildagent/continuum-buildagent-api/src/main/java/org/apache/continuum/buildagent/NoBuildAgentInGroupException.java
new file mode 100644
index 0000000..1a6a7ee
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-api/src/main/java/org/apache/continuum/buildagent/NoBuildAgentInGroupException.java
@@ -0,0 +1,39 @@
+package org.apache.continuum.buildagent;
+
+/*
+ * 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.
+ */
+
+public class NoBuildAgentInGroupException
+    extends Exception
+{
+    public NoBuildAgentInGroupException( String message )
+    {
+        super( message );
+    }
+
+    public NoBuildAgentInGroupException( Throwable cause )
+    {
+        super( cause );
+    }
+
+    public NoBuildAgentInGroupException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/BuildAgentConfigurationException.java b/continuum-buildagent/continuum-buildagent-api/src/main/java/org/apache/continuum/buildagent/configuration/BuildAgentConfigurationException.java
similarity index 100%
rename from continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/BuildAgentConfigurationException.java
rename to continuum-buildagent/continuum-buildagent-api/src/main/java/org/apache/continuum/buildagent/configuration/BuildAgentConfigurationException.java
diff --git a/continuum-buildagent/continuum-buildagent-api/src/main/java/org/apache/continuum/buildagent/configuration/BuildAgentConfigurationService.java b/continuum-buildagent/continuum-buildagent-api/src/main/java/org/apache/continuum/buildagent/configuration/BuildAgentConfigurationService.java
new file mode 100644
index 0000000..94d5871
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-api/src/main/java/org/apache/continuum/buildagent/configuration/BuildAgentConfigurationService.java
@@ -0,0 +1,56 @@
+package org.apache.continuum.buildagent.configuration;
+
+/*
+ * 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 org.apache.continuum.buildagent.model.Installation;
+import org.apache.continuum.buildagent.model.LocalRepository;
+
+import java.io.File;
+import java.util.List;
+
+public interface BuildAgentConfigurationService
+{
+    String ROLE = BuildAgentConfigurationService.class.getName();
+
+    File getBuildOutputDirectory();
+
+    File getBuildOutputDirectory( int projectId );
+
+    File getWorkingDirectory();
+
+    File getWorkingDirectory( int projectId );
+
+    String getContinuumServerUrl();
+
+    String getBuildOutput( int projectId )
+        throws BuildAgentConfigurationException;
+
+    File getBuildOutputFile( int projectId )
+        throws BuildAgentConfigurationException;
+
+    List<Installation> getAvailableInstallations();
+
+    List<LocalRepository> getLocalRepositories();
+
+    String getSharedSecretPassword();
+
+    void store()
+        throws BuildAgentConfigurationException;
+}
diff --git a/continuum-buildagent/continuum-buildagent-api/src/main/mdo/continuum-buildagent.xml b/continuum-buildagent/continuum-buildagent-api/src/main/mdo/continuum-buildagent.xml
new file mode 100644
index 0000000..a8c712a
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-api/src/main/mdo/continuum-buildagent.xml
@@ -0,0 +1,131 @@
+<!--
+  ~ 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.
+  -->
+
+<model xsd.namespace="http://modello.codehaus.org/xsd/modello-1.0.0.xsd">
+  <id>continuum-buildagent</id>
+  <name>ContinuumBuildAgentConfigurationModel</name>
+  <description>Continuum Build Agent object model.</description>
+  <defaults>
+    <default>
+      <key>package</key>
+      <value>org.apache.continuum.buildagent.model</value>
+    </default>
+  </defaults>
+
+  <classes>
+    <class rootElement="true" xml.tagName="continuum-buildagent-configuration">
+      <name>ContinuumBuildAgentConfigurationModel</name>
+      <version>1.0.0+</version>
+      <fields>
+        <field>
+          <name>buildOutputDirectory</name>
+          <version>1.0.0+</version>
+          <type>String</type>
+        </field>
+        <field>
+          <name>workingDirectory</name>
+          <version>1.0.0+</version>
+          <type>String</type>
+        </field>
+        <field>
+          <name>continuumServerUrl</name>
+          <version>1.0.0+</version>
+          <type>String</type>
+        </field>
+        <field>
+          <name>installations</name>
+          <version>1.0.0+</version>
+          <association>
+            <type>Installation</type>
+            <multiplicity>*</multiplicity>
+          </association>
+        </field>
+        <field>
+          <name>localRepositories</name>
+          <version>1.1.0+</version>
+          <association>
+            <type>LocalRepository</type>
+            <multiplicity>*</multiplicity>
+          </association>
+        </field>
+        <field>
+          <name>sharedSecretPassword</name>
+          <version>1.4.1+</version>
+          <type>String</type>
+        </field>
+      </fields>
+    </class>
+    <class xml.tagName="buildagent-installation">
+      <name>Installation</name>
+      <version>1.0.0+</version>
+      <fields>
+        <field>
+          <name>type</name>
+          <version>1.0.0+</version>
+          <type>String</type>
+        </field>
+        <field>
+          <name>varValue</name>
+          <version>1.0.0+</version>
+          <type>String</type>
+        </field>
+        <field>
+          <name>varName</name>
+          <version>1.0.0+</version>
+          <type>String</type>
+        </field>
+        <field>
+          <name>name</name>
+          <version>1.0.0+</version>
+          <type>String</type>
+        </field>
+      </fields>
+    </class>
+    <class>
+      <name>LocalRepository</name>
+      <version>1.1.0+</version>
+      <fields>
+        <field>
+          <name>name</name>
+          <version>1.1.0+</version>
+          <type>String</type>
+          <required>true</required>
+        </field>
+        <field>
+          <name>location</name>
+          <version>1.1.0+</version>
+          <type>String</type>
+          <required>true</required>
+          <description>
+            The file system location for this repository
+          </description>
+        </field>
+        <field>
+          <name>layout</name>
+          <version>1.1.0+</version>
+          <type>String</type>
+          <defaultValue>default</defaultValue>
+          <description>
+            The layout of the repository. Valid values are "default" and "legacy"
+          </description>
+        </field>
+      </fields>
+    </class>
+  </classes>
+</model>
\ No newline at end of file
diff --git a/continuum-buildagent/continuum-buildagent-core/pom.xml b/continuum-buildagent/continuum-buildagent-core/pom.xml
new file mode 100644
index 0000000..3b286fe
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/pom.xml
@@ -0,0 +1,231 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.continuum</groupId>
+    <artifactId>continuum-buildagent</artifactId>
+    <version>1.4.3</version>
+  </parent>
+
+  <artifactId>continuum-buildagent-core</artifactId>
+  <name>Continuum :: Distributed Build :: Build Agent :: Core</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-model</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-buildagent-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-scm</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.scm</groupId>
+      <artifactId>maven-scm-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-release</artifactId>
+      <exclusions>
+        <exclusion>
+          <groupId>org.apache.archiva</groupId>
+          <artifactId>archiva-common</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.apache.archiva</groupId>
+          <artifactId>archiva-repository-layer</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-distributed-master-client</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.shared</groupId>
+      <artifactId>file-management</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-component-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-utils</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-taskqueue</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-action</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-command-line</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.release</groupId>
+      <artifactId>maven-release-manager</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-model</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-artifact</artifactId>
+    </dependency>
+    <!-- start - order matters, requires maven 2.0.9+ -->
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-artifact-manager</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-artifact-manager</artifactId>
+    </dependency>
+    <!-- end - order matters, requires maven 2.0.9+ -->
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-settings</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-project</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>javax.annotation</groupId>
+      <artifactId>jsr250-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>javax.activation</groupId>
+      <artifactId>activation</artifactId>
+      <version>1.1.1</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-simple</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jmock</groupId>
+      <artifactId>jmock-junit3</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jmock</groupId>
+      <artifactId>jmock</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>jmock</groupId>
+      <artifactId>jmock</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <!-- dependency of jmock3 -->
+    <dependency>
+      <groupId>cglib</groupId>
+      <artifactId>cglib-nodep</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <!-- dependency of jmock3 -->
+    <dependency>
+      <groupId>org.objenesis</groupId>
+      <artifactId>objenesis</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.wagon</groupId>
+      <artifactId>wagon-file</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+      <version>1.9.5</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.codehaus.plexus</groupId>
+        <artifactId>plexus-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>generate</id>
+            <phase>generate-resources</phase>
+            <goals>
+              <goal>descriptor</goal>
+            </goals>
+          </execution>
+          <execution>
+            <id>merge</id>
+            <phase>process-resources</phase>
+            <goals>
+              <goal>merge-descriptors</goal>
+            </goals>
+            <configuration>
+              <descriptors>
+                <descriptor>${basedir}/src/main/resources/META-INF/plexus/components-fragment.xml</descriptor>
+                <descriptor>${project.build.outputDirectory}/META-INF/plexus/components.xml</descriptor>
+              </descriptors>
+              <output>${project.build.outputDirectory}/META-INF/plexus/components.xml</output>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.rat</groupId>
+          <artifactId>apache-rat-plugin</artifactId>
+          <configuration>
+            <excludes>
+              <exclude>src/test/test-repo/**</exclude>
+            </excludes>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+</project>
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/ContinuumBuildAgentServiceImpl.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/ContinuumBuildAgentServiceImpl.java
new file mode 100644
index 0000000..291f93f
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/ContinuumBuildAgentServiceImpl.java
@@ -0,0 +1,1283 @@
+package org.apache.continuum.buildagent;
+
+/*
+ * 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 org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.continuum.buildagent.buildcontext.BuildContext;
+import org.apache.continuum.buildagent.buildcontext.manager.BuildContextManager;
+import org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
+import org.apache.continuum.buildagent.manager.BuildAgentManager;
+import org.apache.continuum.buildagent.manager.BuildAgentPurgeManager;
+import org.apache.continuum.buildagent.manager.BuildAgentReleaseManager;
+import org.apache.continuum.buildagent.model.Installation;
+import org.apache.continuum.buildagent.taskqueue.PrepareBuildProjectsTask;
+import org.apache.continuum.buildagent.taskqueue.manager.BuildAgentTaskQueueManager;
+import org.apache.continuum.buildagent.utils.ContinuumBuildAgentUtil;
+import org.apache.continuum.buildagent.utils.WorkingCopyContentGenerator;
+import org.apache.continuum.taskqueue.BuildProjectTask;
+import org.apache.continuum.taskqueue.manager.TaskQueueManagerException;
+import org.apache.continuum.utils.build.BuildTrigger;
+import org.apache.continuum.utils.release.ReleaseUtil;
+import org.apache.maven.continuum.ContinuumException;
+import org.apache.maven.continuum.model.project.BuildResult;
+import org.apache.maven.continuum.model.scm.ChangeFile;
+import org.apache.maven.continuum.model.scm.ChangeSet;
+import org.apache.maven.continuum.model.scm.ScmResult;
+import org.apache.maven.continuum.project.ContinuumProjectState;
+import org.apache.maven.continuum.release.ContinuumReleaseException;
+import org.apache.maven.shared.release.ReleaseResult;
+import org.codehaus.plexus.taskqueue.TaskQueueException;
+import org.codehaus.plexus.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.activation.MimetypesFileTypeMap;
+
+/**
+ * @plexus.component role="org.apache.continuum.buildagent.ContinuumBuildAgentService"
+ */
+public class ContinuumBuildAgentServiceImpl
+    implements ContinuumBuildAgentService
+{
+    private static final Logger log = LoggerFactory.getLogger( ContinuumBuildAgentServiceImpl.class );
+
+    private static final String FILE_SEPARATOR = System.getProperty( "file.separator" );
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildAgentConfigurationService buildAgentConfigurationService;
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildAgentTaskQueueManager buildAgentTaskQueueManager;
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildContextManager buildContextManager;
+
+    /**
+     * @plexus.requirement
+     */
+    private WorkingCopyContentGenerator generator;
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildAgentReleaseManager buildAgentReleaseManager;
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildAgentManager buildAgentManager;
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildAgentPurgeManager purgeManager;
+
+    public void buildProjects( List<Map<String, Object>> projectsBuildContext )
+        throws ContinuumBuildAgentException
+    {
+        List<BuildContext> buildContextList = initializeBuildContext( projectsBuildContext );
+
+        PrepareBuildProjectsTask task = createPrepareBuildProjectsTask( buildContextList );
+
+        if ( task == null )
+        {
+            return;
+        }
+
+        try
+        {
+            log.info( "Adding project group {} to prepare build queue", task.getProjectGroupId() );
+            buildAgentTaskQueueManager.getPrepareBuildQueue().put( task );
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new ContinuumBuildAgentException( "Error while enqueuing projects", e );
+        }
+
+    }
+
+    public List<Map<String, String>> getAvailableInstallations()
+        throws ContinuumBuildAgentException
+    {
+        List<Map<String, String>> installationsList = new ArrayList<Map<String, String>>();
+
+        List<Installation> installations = buildAgentConfigurationService.getAvailableInstallations();
+
+        for ( Installation installation : installations )
+        {
+            Map<String, String> map = new HashMap<String, String>();
+
+            if ( StringUtils.isBlank( installation.getName() ) )
+            {
+                map.put( ContinuumBuildAgentUtil.KEY_INSTALLATION_NAME, "" );
+            }
+            else
+            {
+                map.put( ContinuumBuildAgentUtil.KEY_INSTALLATION_NAME, installation.getName() );
+            }
+
+            if ( StringUtils.isBlank( installation.getType() ) )
+            {
+                map.put( ContinuumBuildAgentUtil.KEY_INSTALLATION_TYPE, "" );
+            }
+            else
+            {
+                map.put( ContinuumBuildAgentUtil.KEY_INSTALLATION_TYPE, installation.getType() );
+            }
+
+            if ( StringUtils.isBlank( installation.getVarName() ) )
+            {
+                map.put( ContinuumBuildAgentUtil.KEY_INSTALLATION_VAR_NAME, "" );
+            }
+            else
+            {
+                map.put( ContinuumBuildAgentUtil.KEY_INSTALLATION_VAR_VALUE, installation.getVarValue() );
+            }
+
+            if ( StringUtils.isBlank( installation.getVarValue() ) )
+            {
+                map.put( ContinuumBuildAgentUtil.KEY_INSTALLATION_VAR_VALUE, "" );
+            }
+            else
+            {
+                map.put( ContinuumBuildAgentUtil.KEY_INSTALLATION_VAR_VALUE, installation.getVarValue() );
+            }
+
+            installationsList.add( map );
+        }
+
+        return installationsList;
+    }
+
+    public Map<String, Object> getBuildResult( int projectId )
+        throws ContinuumBuildAgentException
+    {
+        log.debug( "Get build result of project {}", projectId );
+
+        Map<String, Object> result = new HashMap<String, Object>();
+
+        int currentBuildId = 0;
+
+        try
+        {
+            log.debug( "Get current build project" );
+            currentBuildId = buildAgentTaskQueueManager.getIdOfProjectCurrentlyBuilding();
+        }
+        catch ( TaskQueueManagerException e )
+        {
+            throw new ContinuumBuildAgentException( e.getMessage(), e );
+        }
+
+        log.debug( "Check if project {} is the one currently building in the agent", projectId );
+        if ( projectId == currentBuildId )
+        {
+            BuildContext buildContext = buildContextManager.getBuildContext( projectId );
+
+            result.put( ContinuumBuildAgentUtil.KEY_PROJECT_ID, buildContext.getProjectId() );
+            result.put( ContinuumBuildAgentUtil.KEY_BUILD_DEFINITION_ID, buildContext.getBuildDefinitionId() );
+            result.put( ContinuumBuildAgentUtil.KEY_TRIGGER, buildContext.getTrigger() );
+            result.put( ContinuumBuildAgentUtil.KEY_USERNAME, buildContext.getUsername() );
+
+            BuildResult buildResult = buildContext.getBuildResult();
+
+            if ( buildResult != null )
+            {
+                if ( buildResult.getStartTime() <= 0 )
+                {
+                    result.put( ContinuumBuildAgentUtil.KEY_START_TIME, Long.toString(
+                        buildContext.getBuildStartTime() ) );
+                }
+                else
+                {
+                    result.put( ContinuumBuildAgentUtil.KEY_START_TIME, Long.toString( buildResult.getStartTime() ) );
+                }
+
+                if ( buildResult.getError() == null )
+                {
+                    result.put( ContinuumBuildAgentUtil.KEY_BUILD_ERROR, "" );
+                }
+                else
+                {
+                    result.put( ContinuumBuildAgentUtil.KEY_BUILD_ERROR, buildResult.getError() );
+                }
+
+                result.put( ContinuumBuildAgentUtil.KEY_BUILD_STATE, buildResult.getState() );
+                result.put( ContinuumBuildAgentUtil.KEY_END_TIME, Long.toString( buildResult.getEndTime() ) );
+                result.put( ContinuumBuildAgentUtil.KEY_BUILD_EXIT_CODE, buildResult.getExitCode() );
+            }
+            else
+            {
+                result.put( ContinuumBuildAgentUtil.KEY_START_TIME, Long.toString( buildContext.getBuildStartTime() ) );
+                result.put( ContinuumBuildAgentUtil.KEY_END_TIME, Long.toString( 0 ) );
+                result.put( ContinuumBuildAgentUtil.KEY_BUILD_STATE, ContinuumProjectState.BUILDING );
+                result.put( ContinuumBuildAgentUtil.KEY_BUILD_ERROR, "" );
+                result.put( ContinuumBuildAgentUtil.KEY_BUILD_EXIT_CODE, 0 );
+            }
+
+            String buildOutput = getBuildOutputText( projectId );
+            if ( buildOutput == null )
+            {
+                result.put( ContinuumBuildAgentUtil.KEY_BUILD_OUTPUT, "" );
+            }
+            else
+            {
+                result.put( ContinuumBuildAgentUtil.KEY_BUILD_OUTPUT, buildOutput );
+            }
+
+            result.put( ContinuumBuildAgentUtil.KEY_SCM_RESULT, ContinuumBuildAgentUtil.createScmResult(
+                buildContext ) );
+        }
+        else
+        {
+            log.debug( "Unable to get build result because project {} is not currently building in the agent",
+                       projectId );
+        }
+        return result;
+    }
+
+    public void cancelBuild()
+        throws ContinuumBuildAgentException
+    {
+        try
+        {
+            log.debug( "Cancelling current build" );
+            buildAgentTaskQueueManager.cancelBuild();
+        }
+        catch ( TaskQueueManagerException e )
+        {
+            throw new ContinuumBuildAgentException( e.getMessage(), e );
+        }
+    }
+
+    public String generateWorkingCopyContent( int projectId, String userDirectory, String baseUrl,
+                                              String imagesBaseUrl )
+        throws ContinuumBuildAgentException
+    {
+        File workingDirectory = buildAgentConfigurationService.getWorkingDirectory( projectId );
+
+        try
+        {
+            List<File> files = ContinuumBuildAgentUtil.getFiles( userDirectory, workingDirectory );
+            return generator.generate( files, baseUrl, imagesBaseUrl, workingDirectory );
+        }
+        catch ( ContinuumException e )
+        {
+            log.error( "Failed to generate working copy content", e );
+        }
+
+        return "";
+    }
+
+    public Map<String, Object> getProjectFile( int projectId, String directory, String filename )
+        throws ContinuumBuildAgentException
+    {
+        Map<String, Object> projectFile = new HashMap<String, Object>();
+
+        String relativePath = "\\.\\./"; // prevent users from using relative paths.
+        Pattern pattern = Pattern.compile( relativePath );
+        Matcher matcher = pattern.matcher( directory );
+        String filteredDirectory = matcher.replaceAll( "" );
+
+        matcher = pattern.matcher( filename );
+        String filteredFilename = matcher.replaceAll( "" );
+
+        File workingDirectory = buildAgentConfigurationService.getWorkingDirectory( projectId );
+
+        File fileDirectory = new File( workingDirectory, filteredDirectory );
+
+        File userFile = new File( fileDirectory, filteredFilename );
+        byte[] downloadFile;
+
+        try
+        {
+            downloadFile = FileUtils.readFileToByteArray( userFile );
+        }
+        catch ( IOException e )
+        {
+            throw new ContinuumBuildAgentException( "Can't read file: " + filename );
+        }
+
+        MimetypesFileTypeMap mimeTypesMap = new MimetypesFileTypeMap();
+        mimeTypesMap.addMimeTypes( "application/java-archive jar war ear" );
+        mimeTypesMap.addMimeTypes( "application/java-class class" );
+        mimeTypesMap.addMimeTypes( "image/png png" );
+
+        String mimeType = mimeTypesMap.getContentType( userFile );
+        String fileContent;
+        boolean isStream = false;
+
+        if ( ( mimeType.indexOf( "image" ) >= 0 ) || ( mimeType.indexOf( "java-archive" ) >= 0 ) ||
+            ( mimeType.indexOf( "java-class" ) >= 0 ) || ( userFile.length() > 100000 ) )
+        {
+            fileContent = "";
+            isStream = true;
+        }
+        else
+        {
+            try
+            {
+                fileContent = FileUtils.readFileToString( userFile );
+            }
+            catch ( IOException e )
+            {
+                throw new ContinuumBuildAgentException( "Can't read file " + filename, e );
+            }
+        }
+
+        projectFile.put( "downloadFileName", userFile.getName() );
+        projectFile.put( "downloadFileLength", Long.toString( userFile.length() ) );
+        projectFile.put( "downloadFile", downloadFile );
+        projectFile.put( "mimeType", mimeType );
+        projectFile.put( "fileContent", fileContent );
+        projectFile.put( "isStream", isStream );
+
+        return projectFile;
+    }
+
+    public Map<String, Object> getReleasePluginParameters( int projectId, String pomFilename )
+        throws ContinuumBuildAgentException
+    {
+        String workingDirectory = buildAgentConfigurationService.getWorkingDirectory( projectId ).getPath();
+
+        try
+        {
+            log.debug( "Getting release plugin parameters of project {}", projectId );
+            return ReleaseUtil.getReleasePluginParameters( workingDirectory, pomFilename );
+        }
+        catch ( Exception e )
+        {
+            throw new ContinuumBuildAgentException( "Error getting release plugin parameters from pom file", e );
+        }
+    }
+
+    public List<Map<String, String>> processProject( int projectId, String pomFilename, boolean autoVersionSubmodules )
+        throws ContinuumBuildAgentException
+    {
+        List<Map<String, String>> projects = new ArrayList<Map<String, String>>();
+
+        String workingDirectory = buildAgentConfigurationService.getWorkingDirectory( projectId ).getPath();
+
+        try
+        {
+            ReleaseUtil.processProject( workingDirectory, pomFilename, autoVersionSubmodules, projects );
+        }
+        catch ( Exception e )
+        {
+            throw new ContinuumBuildAgentException( "Unable to process project " + projectId, e );
+        }
+
+        return projects;
+    }
+
+    public String releasePrepare( Map project, Properties properties, Map releaseVersion, Map developmentVersion,
+                                  Map<String, String> environments, String username )
+        throws ContinuumBuildAgentException
+    {
+        try
+        {
+            log.debug( "Preparing release" );
+            return buildAgentReleaseManager.releasePrepare( project, properties, releaseVersion, developmentVersion,
+                                                            environments, username );
+        }
+        catch ( ContinuumReleaseException e )
+        {
+            throw new ContinuumBuildAgentException( "Unable to prepare release", e );
+        }
+    }
+
+    public Map<String, Object> getReleaseResult( String releaseId )
+        throws ContinuumBuildAgentException
+    {
+        log.debug( "Getting release result of release {}", releaseId );
+        ReleaseResult result = buildAgentReleaseManager.getReleaseResult( releaseId );
+
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put( ContinuumBuildAgentUtil.KEY_START_TIME, Long.toString( result.getStartTime() ) );
+        map.put( ContinuumBuildAgentUtil.KEY_END_TIME, Long.toString( result.getEndTime() ) );
+        map.put( ContinuumBuildAgentUtil.KEY_RELEASE_RESULT_CODE, result.getResultCode() );
+        map.put( ContinuumBuildAgentUtil.KEY_RELEASE_OUTPUT, result.getOutput() );
+
+        return map;
+    }
+
+    public Map<String, Object> getListener( String releaseId )
+        throws ContinuumBuildAgentException
+    {
+        return buildAgentReleaseManager.getListener( releaseId );
+    }
+
+    public void removeListener( String releaseId )
+    {
+        buildAgentReleaseManager.removeListener( releaseId );
+    }
+
+    public String getPreparedReleaseName( String releaseId )
+    {
+        return buildAgentReleaseManager.getPreparedReleaseName( releaseId );
+    }
+
+    public void releasePerform( String releaseId, String goals, String arguments, boolean useReleaseProfile,
+                                Map repository, String username )
+        throws ContinuumBuildAgentException
+    {
+        try
+        {
+            log.debug( "Performing release" );
+            buildAgentReleaseManager.releasePerform( releaseId, goals, arguments, useReleaseProfile, repository,
+                                                     username );
+        }
+        catch ( ContinuumReleaseException e )
+        {
+            throw new ContinuumBuildAgentException( "Unable to perform release " + releaseId, e );
+        }
+    }
+
+    public String releasePerformFromScm( String goals, String arguments, boolean useReleaseProfile, Map repository,
+                                         String scmUrl, String scmUsername, String scmPassword, String scmTag,
+                                         String scmTagBase, Map<String, String> environments, String username )
+        throws ContinuumBuildAgentException
+    {
+        try
+        {
+            log.debug( "Performing release from scm" );
+            return buildAgentReleaseManager.releasePerformFromScm( goals, arguments, useReleaseProfile, repository,
+                                                                   scmUrl, scmUsername, scmPassword, scmTag, scmTagBase,
+                                                                   environments, username );
+        }
+        catch ( ContinuumReleaseException e )
+        {
+            throw new ContinuumBuildAgentException( "Unable to perform release from scm", e );
+        }
+    }
+
+    public String releaseCleanup( String releaseId )
+        throws ContinuumBuildAgentException
+    {
+        log.debug( "Cleanup release {}", releaseId );
+        return buildAgentReleaseManager.releaseCleanup( releaseId );
+    }
+
+    public void releaseRollback( String releaseId, int projectId )
+        throws ContinuumBuildAgentException
+    {
+        try
+        {
+            log.debug( "Release rollback release {} with project {}", releaseId, projectId );
+            buildAgentReleaseManager.releaseRollback( releaseId, projectId );
+        }
+        catch ( ContinuumReleaseException e )
+        {
+            throw new ContinuumBuildAgentException( e );
+        }
+    }
+
+    public int getBuildSizeOfAgent()
+    {
+        int size = 0;
+
+        try
+        {
+            log.debug( "Getting number of projects in any queue" );
+
+            if ( buildAgentTaskQueueManager.getCurrentProjectInBuilding() != null )
+            {
+                size++;
+            }
+
+            PrepareBuildProjectsTask currentPrepareBuild = buildAgentTaskQueueManager.getCurrentProjectInPrepareBuild();
+
+            if ( currentPrepareBuild != null )
+            {
+                // need to get actual number of projects.
+                size = size + currentPrepareBuild.getBuildContexts().size();
+            }
+
+            size = size + buildAgentTaskQueueManager.getProjectsInBuildQueue().size();
+
+            for ( PrepareBuildProjectsTask prepareBuildTask : buildAgentTaskQueueManager.getProjectsInPrepareBuildQueue() )
+            {
+                if ( prepareBuildTask != null )
+                {
+                    size = size + prepareBuildTask.getBuildContexts().size();
+                }
+            }
+        }
+        catch ( TaskQueueManagerException e )
+        {
+            log.error( "Error occurred while getting build size of agent" );
+        }
+
+        return size;
+    }
+
+    public List<Map<String, Object>> getProjectsInPrepareBuildQueue()
+        throws ContinuumBuildAgentException
+    {
+        try
+        {
+            log.debug( "Getting projects in prepare build queue" );
+            List<Map<String, Object>> projects = new ArrayList<Map<String, Object>>();
+
+            for ( PrepareBuildProjectsTask task : buildAgentTaskQueueManager.getProjectsInPrepareBuildQueue() )
+            {
+                Map<String, Object> map = new HashMap<String, Object>();
+                map.put( ContinuumBuildAgentUtil.KEY_PROJECT_GROUP_ID, new Integer( task.getProjectGroupId() ) );
+                map.put( ContinuumBuildAgentUtil.KEY_SCM_ROOT_ID, new Integer( task.getScmRootId() ) );
+                map.put( ContinuumBuildAgentUtil.KEY_SCM_ROOT_ADDRESS, task.getScmRootAddress() );
+                map.put( ContinuumBuildAgentUtil.KEY_TRIGGER, task.getBuildTrigger().getTrigger() );
+                map.put( ContinuumBuildAgentUtil.KEY_USERNAME, task.getBuildTrigger().getTriggeredBy() );
+
+                projects.add( map );
+            }
+
+            return projects;
+        }
+        catch ( TaskQueueManagerException e )
+        {
+            log.error( "Error occurred while retrieving projects in prepare build queue", e );
+            throw new ContinuumBuildAgentException( "Error occurred while retrieving projects in prepare build queue",
+                                                    e );
+        }
+    }
+
+    public List<Map<String, Object>> getProjectsAndBuildDefinitionsInPrepareBuildQueue()
+        throws ContinuumBuildAgentException
+    {
+        try
+        {
+            log.debug( "Getting projects in prepare build queue" );
+            List<Map<String, Object>> projects = new ArrayList<Map<String, Object>>();
+
+            for ( PrepareBuildProjectsTask task : buildAgentTaskQueueManager.getProjectsInPrepareBuildQueue() )
+            {
+                for ( BuildContext context : task.getBuildContexts() )
+                {
+                    Map<String, Object> map = new HashMap<String, Object>();
+
+                    map.put( ContinuumBuildAgentUtil.KEY_PROJECT_ID, context.getProjectId() );
+                    map.put( ContinuumBuildAgentUtil.KEY_BUILD_DEFINITION_ID, context.getBuildDefinitionId() );
+
+                    projects.add( map );
+                }
+            }
+
+            return projects;
+        }
+        catch ( TaskQueueManagerException e )
+        {
+            log.error( "Error occurred while retrieving projects in prepare build queue", e );
+            throw new ContinuumBuildAgentException( "Error occurred while retrieving projects in prepare build queue",
+                                                    e );
+        }
+    }
+
+    public List<Map<String, Object>> getProjectsInBuildQueue()
+        throws ContinuumBuildAgentException
+    {
+        try
+        {
+            log.debug( "Getting projects in build queue" );
+            List<Map<String, Object>> projects = new ArrayList<Map<String, Object>>();
+
+            for ( BuildProjectTask task : buildAgentTaskQueueManager.getProjectsInBuildQueue() )
+            {
+                Map<String, Object> map = new HashMap<String, Object>();
+                map.put( ContinuumBuildAgentUtil.KEY_PROJECT_ID, new Integer( task.getProjectId() ) );
+                map.put( ContinuumBuildAgentUtil.KEY_BUILD_DEFINITION_ID, new Integer( task.getBuildDefinitionId() ) );
+                map.put( ContinuumBuildAgentUtil.KEY_TRIGGER, task.getBuildTrigger().getTrigger() );
+                map.put( ContinuumBuildAgentUtil.KEY_USERNAME, task.getBuildTrigger().getTriggeredBy() );
+                map.put( ContinuumBuildAgentUtil.KEY_PROJECT_GROUP_ID, new Integer( task.getProjectGroupId() ) );
+                map.put( ContinuumBuildAgentUtil.KEY_BUILD_DEFINITION_LABEL, task.getBuildDefinitionLabel() );
+
+                projects.add( map );
+            }
+
+            return projects;
+        }
+        catch ( TaskQueueManagerException e )
+        {
+            log.error( "Error occurred while retrieving projects in build queue", e );
+            throw new ContinuumBuildAgentException( "Error occurred while retrieving projects in build queue", e );
+        }
+    }
+
+    public Map<String, Object> getProjectCurrentlyPreparingBuild()
+        throws ContinuumBuildAgentException
+    {
+        try
+        {
+            log.debug( "Get project currently preparing build" );
+            Map<String, Object> project = new HashMap<String, Object>();
+
+            PrepareBuildProjectsTask task = buildAgentTaskQueueManager.getCurrentProjectInPrepareBuild();
+
+            if ( task != null )
+            {
+                project.put( ContinuumBuildAgentUtil.KEY_PROJECT_GROUP_ID, new Integer( task.getProjectGroupId() ) );
+                project.put( ContinuumBuildAgentUtil.KEY_SCM_ROOT_ID, new Integer( task.getScmRootId() ) );
+                project.put( ContinuumBuildAgentUtil.KEY_SCM_ROOT_ADDRESS, task.getScmRootAddress() );
+                project.put( ContinuumBuildAgentUtil.KEY_TRIGGER, task.getBuildTrigger().getTrigger() );
+                project.put( ContinuumBuildAgentUtil.KEY_USERNAME, task.getBuildTrigger().getTriggeredBy() );
+            }
+
+            return project;
+        }
+        catch ( TaskQueueManagerException e )
+        {
+            log.error( "Error occurred while retrieving current project in prepare build", e );
+            throw new ContinuumBuildAgentException( "Error occurred while retrieving current project in prepare build",
+                                                    e );
+        }
+    }
+
+    public List<Map<String, Object>> getProjectsAndBuildDefinitionsCurrentlyPreparingBuild()
+        throws ContinuumBuildAgentException
+    {
+        try
+        {
+            log.debug( "Getting projects currently preparing build" );
+            List<Map<String, Object>> projects = new ArrayList<Map<String, Object>>();
+
+            PrepareBuildProjectsTask task = buildAgentTaskQueueManager.getCurrentProjectInPrepareBuild();
+
+            if ( task != null )
+            {
+                for ( BuildContext context : task.getBuildContexts() )
+                {
+                    Map<String, Object> map = new HashMap<String, Object>();
+
+                    map.put( ContinuumBuildAgentUtil.KEY_PROJECT_ID, context.getProjectId() );
+                    map.put( ContinuumBuildAgentUtil.KEY_BUILD_DEFINITION_ID, context.getBuildDefinitionId() );
+
+                    projects.add( map );
+                }
+            }
+
+            return projects;
+        }
+        catch ( TaskQueueManagerException e )
+        {
+            log.error( "Error occurred while retrieving current projects in prepare build", e );
+            throw new ContinuumBuildAgentException( "Error occurred while retrieving current projects in prepare build",
+                                                    e );
+        }
+    }
+
+    public Map<String, Object> getProjectCurrentlyBuilding()
+        throws ContinuumBuildAgentException
+    {
+        try
+        {
+            log.debug( "Getting currently building project" );
+            Map<String, Object> project = new HashMap<String, Object>();
+
+            BuildProjectTask task = buildAgentTaskQueueManager.getCurrentProjectInBuilding();
+
+            if ( task != null )
+            {
+                project.put( ContinuumBuildAgentUtil.KEY_PROJECT_ID, new Integer( task.getProjectId() ) );
+                project.put( ContinuumBuildAgentUtil.KEY_BUILD_DEFINITION_ID, new Integer(
+                    task.getBuildDefinitionId() ) );
+                project.put( ContinuumBuildAgentUtil.KEY_TRIGGER, task.getBuildTrigger().getTrigger() );
+                project.put( ContinuumBuildAgentUtil.KEY_USERNAME, task.getBuildTrigger().getTriggeredBy() );
+                project.put( ContinuumBuildAgentUtil.KEY_PROJECT_GROUP_ID, new Integer( task.getProjectGroupId() ) );
+                project.put( ContinuumBuildAgentUtil.KEY_BUILD_DEFINITION_LABEL, task.getBuildDefinitionLabel() );
+            }
+
+            return project;
+        }
+        catch ( TaskQueueManagerException e )
+        {
+            log.error( "Error occurred while retrieving current project in building", e );
+            throw new ContinuumBuildAgentException( "Error occurred while retrieving current project in building", e );
+        }
+    }
+
+    public boolean isProjectGroupInQueue( int projectGroupId )
+    {
+        try
+        {
+            log.debug( "Checking if project group is in any queue", projectGroupId );
+            for ( PrepareBuildProjectsTask task : buildAgentTaskQueueManager.getProjectsInPrepareBuildQueue() )
+            {
+                if ( task.getProjectGroupId() == projectGroupId )
+                {
+                    log.debug( "projectGroup {} is in prepare build queue", projectGroupId );
+                    return true;
+                }
+            }
+
+            PrepareBuildProjectsTask currentPrepareBuildTask =
+                buildAgentTaskQueueManager.getCurrentProjectInPrepareBuild();
+
+            if ( currentPrepareBuildTask != null && currentPrepareBuildTask.getProjectGroupId() == projectGroupId )
+            {
+                log.debug( "projectGroup {} is currently preparing build", projectGroupId );
+                return true;
+            }
+
+            for ( BuildProjectTask task : buildAgentTaskQueueManager.getProjectsInBuildQueue() )
+            {
+                if ( task.getProjectGroupId() == projectGroupId )
+                {
+                    log.debug( "projectGroup {} is in build queue", projectGroupId );
+                    return true;
+                }
+            }
+
+            BuildProjectTask currentBuildTask = buildAgentTaskQueueManager.getCurrentProjectInBuilding();
+
+            if ( currentBuildTask != null && currentBuildTask.getProjectGroupId() == projectGroupId )
+            {
+                log.debug( "projectGroup {} is currently building", projectGroupId );
+                return true;
+            }
+        }
+        catch ( TaskQueueManagerException e )
+        {
+            log.error( "Error while checking if project group " + projectGroupId + " is queued in agent", e );
+        }
+
+        return false;
+    }
+
+    public boolean isProjectScmRootInQueue( int projectScmRootId, List<Integer> projectIds )
+    {
+        try
+        {
+            log.debug( "Checking if projects {} is in any queue", projectIds );
+            PrepareBuildProjectsTask currentPrepareBuildTask =
+                buildAgentTaskQueueManager.getCurrentProjectInPrepareBuild();
+
+            if ( currentPrepareBuildTask != null && currentPrepareBuildTask.getScmRootId() == projectScmRootId )
+            {
+                return true;
+            }
+
+            BuildProjectTask currentBuildTask = buildAgentTaskQueueManager.getCurrentProjectInBuilding();
+
+            if ( currentBuildTask != null )
+            {
+                int projectId = currentBuildTask.getProjectId();
+
+                for ( Integer pid : projectIds )
+                {
+                    if ( pid == projectId )
+                    {
+                        return true;
+                    }
+                }
+            }
+
+            for ( PrepareBuildProjectsTask task : buildAgentTaskQueueManager.getProjectsInPrepareBuildQueue() )
+            {
+                if ( task.getScmRootId() == projectScmRootId )
+                {
+                    return true;
+                }
+            }
+
+            for ( BuildProjectTask task : buildAgentTaskQueueManager.getProjectsInBuildQueue() )
+            {
+                int projectId = task.getProjectId();
+
+                for ( Integer pid : projectIds )
+                {
+                    if ( pid == projectId )
+                    {
+                        return true;
+                    }
+                }
+            }
+        }
+        catch ( TaskQueueManagerException e )
+        {
+            log.error( "Error while checking if project scm root " + projectScmRootId + " is queued in agent", e );
+        }
+
+        return false;
+    }
+
+    public boolean isProjectGroupInPrepareBuildQueue( int projectGroupId )
+    {
+        try
+        {
+            log.debug( "Checking if project group {} is in prepare build queue", projectGroupId );
+            for ( PrepareBuildProjectsTask task : buildAgentTaskQueueManager.getProjectsInPrepareBuildQueue() )
+            {
+                if ( task.getProjectGroupId() == projectGroupId )
+                {
+                    return true;
+                }
+            }
+        }
+        catch ( TaskQueueManagerException e )
+        {
+            log.error(
+                "Error while checking if project group " + projectGroupId + " is in prepare build queue in agent", e );
+        }
+
+        return false;
+    }
+
+    public boolean isProjectInPrepareBuildQueue( int projectId, int buildDefinitionId )
+    {
+        try
+        {
+            log.debug( "Checking if projectId={}, buildDefinitionId={} is in prepare build queue", projectId,
+                       buildDefinitionId );
+            for ( PrepareBuildProjectsTask task : buildAgentTaskQueueManager.getProjectsInPrepareBuildQueue() )
+            {
+                if ( task != null )
+                {
+                    for ( BuildContext context : task.getBuildContexts() )
+                    {
+                        if ( context.getProjectId() == projectId &&
+                            ( buildDefinitionId == -1 || context.getBuildDefinitionId() == buildDefinitionId ) )
+                        {
+                            log.debug( "projectId={}, buildDefinitionId={} is in prepare build queue" );
+                            return true;
+                        }
+                    }
+                }
+            }
+        }
+        catch ( TaskQueueManagerException e )
+        {
+            log.error( "Error while checking if projectId=" + projectId + ", buildDefinitionId=" + buildDefinitionId +
+                           " is in prepare build queue in agent", e );
+        }
+
+        return false;
+    }
+
+    public boolean isProjectGroupCurrentlyPreparingBuild( int projectGroupId )
+    {
+        try
+        {
+            log.debug( "Checking if project group {} currently preparing build", projectGroupId );
+            PrepareBuildProjectsTask currentPrepareBuildTask =
+                buildAgentTaskQueueManager.getCurrentProjectInPrepareBuild();
+
+            if ( currentPrepareBuildTask != null && currentPrepareBuildTask.getProjectGroupId() == projectGroupId )
+            {
+                return true;
+            }
+        }
+        catch ( TaskQueueManagerException e )
+        {
+            log.error(
+                "Error while checking if project group " + projectGroupId + " is currently preparing build in agent",
+                e );
+        }
+
+        return false;
+    }
+
+    public boolean isProjectCurrentlyPreparingBuild( int projectId, int buildDefinitionId )
+    {
+        try
+        {
+            log.debug( "Checking if projectId={}, buildDefinitionId={} currently preparing build", projectId,
+                       buildDefinitionId );
+            PrepareBuildProjectsTask currentPrepareBuildTask =
+                buildAgentTaskQueueManager.getCurrentProjectInPrepareBuild();
+
+            if ( currentPrepareBuildTask != null )
+            {
+                for ( BuildContext context : currentPrepareBuildTask.getBuildContexts() )
+                {
+                    if ( context.getProjectId() == projectId &&
+                        ( buildDefinitionId == -1 || context.getBuildDefinitionId() == buildDefinitionId ) )
+                    {
+                        log.debug( "projectId={}, buildDefinitionId={} is currently preparing build" );
+                        return true;
+                    }
+                }
+            }
+        }
+        catch ( TaskQueueManagerException e )
+        {
+            log.error( "Error while checking if projectId=" + projectId + ", buildDefinitionId=" + buildDefinitionId +
+                           " is currently preparing build in agent", e );
+        }
+
+        return false;
+    }
+
+    public boolean isProjectCurrentlyBuilding( int projectId, int buildDefinitionId )
+    {
+        try
+        {
+            log.debug( "Checking if projectId={}, buildDefinitionId={} is currently building", projectId,
+                       buildDefinitionId );
+            BuildProjectTask currentBuildTask = buildAgentTaskQueueManager.getCurrentProjectInBuilding();
+
+            if ( currentBuildTask != null && currentBuildTask.getProjectId() == projectId &&
+                ( buildDefinitionId == -1 || currentBuildTask.getBuildDefinitionId() == buildDefinitionId ) )
+            {
+                log.debug( "projectId={}, buildDefinitionId={} is currently building" );
+                return true;
+            }
+        }
+        catch ( TaskQueueManagerException e )
+        {
+            log.error(
+                "Error occurred while checking if projectId=" + projectId + ", buildDefinitionId=" + buildDefinitionId +
+                    " is currently building in agent", e );
+        }
+
+        return false;
+    }
+
+    public boolean isProjectInBuildQueue( int projectId, int buildDefinitionId )
+    {
+        try
+        {
+            log.debug( "Checking if projectId={}, buildDefinitionId={} is in build queue", projectId,
+                       buildDefinitionId );
+            List<BuildProjectTask> buildTasks = buildAgentTaskQueueManager.getProjectsInBuildQueue();
+
+            if ( buildTasks != null )
+            {
+                for ( BuildProjectTask task : buildTasks )
+                {
+                    if ( task.getProjectId() == projectId &&
+                        ( buildDefinitionId == -1 || task.getBuildDefinitionId() == buildDefinitionId ) )
+                    {
+                        log.debug( "projectId={}, buildDefinitionId={} is in build queue" );
+                        return true;
+                    }
+                }
+            }
+        }
+        catch ( TaskQueueManagerException e )
+        {
+            log.error(
+                "Error occurred while checking if projectId=" + projectId + ", buildDefinitionId=" + buildDefinitionId +
+                    " is in build queue of agent", e );
+        }
+
+        return false;
+    }
+
+    public boolean removeFromPrepareBuildQueue( int projectGroupId, int scmRootId )
+        throws ContinuumBuildAgentException
+    {
+        try
+        {
+            log.info( "Removing project group {} from prepare build queue", projectGroupId );
+            return buildAgentTaskQueueManager.removeFromPrepareBuildQueue( projectGroupId, scmRootId );
+        }
+        catch ( TaskQueueManagerException e )
+        {
+            log.error( "Error occurred while removing projects from prepare build queue", e );
+            throw new ContinuumBuildAgentException( "Error occurred while removing projects from prepare build queue",
+                                                    e );
+        }
+    }
+
+    public void removeFromPrepareBuildQueue( List<String> hashCodes )
+        throws ContinuumBuildAgentException
+    {
+        try
+        {
+            log.info( "Removing project groups {} from prepare build queue", hashCodes );
+            buildAgentTaskQueueManager.removeFromPrepareBuildQueue( listToIntArray( hashCodes ) );
+        }
+        catch ( TaskQueueManagerException e )
+        {
+            log.error( "Error occurred while removing projects from prepare build queue", e );
+            throw new ContinuumBuildAgentException( "Error occurred while removing projects from prepare build queue",
+                                                    e );
+        }
+    }
+
+    public boolean removeFromBuildQueue( int projectId, int buildDefinitionId )
+        throws ContinuumBuildAgentException
+    {
+        try
+        {
+            log.info( "Removing project {} with buildDefinition {} from build queue", projectId, buildDefinitionId );
+            return buildAgentTaskQueueManager.removeFromBuildQueue( projectId, buildDefinitionId );
+        }
+        catch ( TaskQueueManagerException e )
+        {
+            log.error( "Error occurred while removing project from build queue", e );
+            throw new ContinuumBuildAgentException( "Error occurred while removing project from build queue ", e );
+        }
+    }
+
+    public void removeFromBuildQueue( List<String> hashCodes )
+        throws ContinuumBuildAgentException
+    {
+        try
+        {
+            log.info( "Removing projects {} from build queue", hashCodes );
+            buildAgentTaskQueueManager.removeFromBuildQueue( listToIntArray( hashCodes ) );
+        }
+        catch ( TaskQueueManagerException e )
+        {
+            log.error( "Error occurred while removing projects from build queue", e );
+            throw new ContinuumBuildAgentException( "Error occurred while removing project from build queue ", e );
+        }
+    }
+
+    public boolean ping()
+        throws ContinuumBuildAgentException
+    {
+        try
+        {
+            // check first if it can ping the master
+            return buildAgentManager.pingMaster();
+        }
+        catch ( ContinuumException e )
+        {
+            throw new ContinuumBuildAgentException( e.getMessage() );
+        }
+    }
+
+    public String getBuildAgentPlatform()
+        throws ContinuumBuildAgentException
+    {
+        try
+        {
+            log.debug( "Getting build agent platform" );
+            return System.getProperty( "os.name" );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Error in when trying to get build agent's platform", e );
+            throw new ContinuumBuildAgentException( "Error in when trying to get build agent's platform", e );
+        }
+    }
+
+    public boolean isExecutingBuild()
+    {
+        return getBuildSizeOfAgent() > 0;
+    }
+
+    public boolean isExecutingRelease()
+        throws ContinuumBuildAgentException
+    {
+        try
+        {
+            return buildAgentReleaseManager.getReleaseManager().isExecutingRelease();
+        }
+        catch ( Exception e )
+        {
+            throw new ContinuumBuildAgentException( e.getMessage(), e );
+        }
+    }
+
+    public void executeDirectoryPurge( String directoryType, int daysOlder, int retentionCount, boolean deleteAll )
+        throws ContinuumBuildAgentException
+    {
+        String logMsgFormat =
+            "Directory purge [directoryType={0}, daysOlder={1}, retentionCount={2}, deleteAll={3}] not possible; {4}";
+        if ( isExecutingBuild() )
+        {
+            log.info( MessageFormat.format( logMsgFormat, directoryType, daysOlder, retentionCount, deleteAll,
+                                            "Build Agent busy" ) );
+            return;
+        }
+
+        try
+        {
+            if ( isExecutingRelease() )
+            {
+                log.info( MessageFormat.format( logMsgFormat, directoryType, daysOlder, retentionCount, deleteAll,
+                                                "Build Agent is executing a release." ) );
+                return;
+            }
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            if ( isExecutingRelease() )
+            {
+                log.info( MessageFormat.format( logMsgFormat, directoryType, daysOlder, retentionCount, deleteAll,
+                                                "Unable to determine if Build Agent is executing a release." ) );
+                return;
+            }
+        }
+
+        try
+        {
+            purgeManager.executeDirectoryPurge( directoryType, daysOlder, retentionCount, deleteAll );
+        }
+        catch ( Exception e )
+        {
+            throw new ContinuumBuildAgentException( e.getMessage(), e );
+        }
+    }
+
+    private List<BuildContext> initializeBuildContext( List<Map<String, Object>> projectsBuildContext )
+    {
+        List<BuildContext> buildContext = new ArrayList<BuildContext>();
+
+        for ( Map<String, Object> map : projectsBuildContext )
+        {
+            BuildContext context = new BuildContext();
+            context.setProjectId( ContinuumBuildAgentUtil.getProjectId( map ) );
+            context.setProjectVersion( ContinuumBuildAgentUtil.getProjectVersion( map ) );
+            context.setBuildDefinitionId( ContinuumBuildAgentUtil.getBuildDefinitionId( map ) );
+            context.setBuildFile( ContinuumBuildAgentUtil.getBuildFile( map ) );
+            context.setExecutorId( ContinuumBuildAgentUtil.getExecutorId( map ) );
+            context.setGoals( ContinuumBuildAgentUtil.getGoals( map ) );
+            context.setArguments( ContinuumBuildAgentUtil.getArguments( map ) );
+            context.setScmUrl( ContinuumBuildAgentUtil.getScmUrl( map ) );
+            context.setScmUsername( ContinuumBuildAgentUtil.getScmUsername( map ) );
+            context.setScmPassword( ContinuumBuildAgentUtil.getScmPassword( map ) );
+            context.setBuildFresh( ContinuumBuildAgentUtil.isBuildFresh( map ) );
+            context.setProjectGroupId( ContinuumBuildAgentUtil.getProjectGroupId( map ) );
+            context.setProjectGroupName( ContinuumBuildAgentUtil.getProjectGroupName( map ) );
+            context.setScmRootAddress( ContinuumBuildAgentUtil.getScmRootAddress( map ) );
+            context.setScmRootId( ContinuumBuildAgentUtil.getScmRootId( map ) );
+            context.setProjectName( ContinuumBuildAgentUtil.getProjectName( map ) );
+            context.setProjectState( ContinuumBuildAgentUtil.getProjectState( map ) );
+            context.setTrigger( ContinuumBuildAgentUtil.getTrigger( map ) );
+            context.setUsername( ContinuumBuildAgentUtil.getUsername( map ) );
+            context.setLocalRepository( ContinuumBuildAgentUtil.getLocalRepository( map ) );
+            context.setBuildNumber( ContinuumBuildAgentUtil.getBuildNumber( map ) );
+            context.setOldScmResult( getScmResult( ContinuumBuildAgentUtil.getOldScmChanges( map ) ) );
+            context.setLatestUpdateDate( ContinuumBuildAgentUtil.getLatestUpdateDate( map ) );
+            context.setBuildAgentUrl( ContinuumBuildAgentUtil.getBuildAgentUrl( map ) );
+            context.setMaxExecutionTime( ContinuumBuildAgentUtil.getMaxExecutionTime( map ) );
+            context.setBuildDefinitionLabel( ContinuumBuildAgentUtil.getBuildDefinitionLabel( map ) );
+            context.setScmTag( ContinuumBuildAgentUtil.getScmTag( map ) );
+
+            buildContext.add( context );
+        }
+
+        buildContextManager.addBuildContexts( buildContext );
+
+        return buildContext;
+    }
+
+    private String getBuildOutputText( int projectId )
+    {
+        try
+        {
+            File buildOutputFile = buildAgentConfigurationService.getBuildOutputFile( projectId );
+
+            if ( buildOutputFile.exists() )
+            {
+                return StringEscapeUtils.escapeHtml( FileUtils.readFileToString( buildOutputFile ) );
+            }
+        }
+        catch ( Exception e )
+        {
+            // do not throw exception, just log it
+            log.error( "Error retrieving build output file", e );
+        }
+
+        return null;
+    }
+
+    private ScmResult getScmResult( List<Map<String, Object>> scmChanges )
+    {
+        ScmResult scmResult = null;
+
+        if ( scmChanges != null && scmChanges.size() > 0 )
+        {
+            scmResult = new ScmResult();
+
+            for ( Map<String, Object> map : scmChanges )
+            {
+                ChangeSet changeSet = new ChangeSet();
+                changeSet.setAuthor( ContinuumBuildAgentUtil.getChangeSetAuthor( map ) );
+                changeSet.setComment( ContinuumBuildAgentUtil.getChangeSetComment( map ) );
+                changeSet.setDate( ContinuumBuildAgentUtil.getChangeSetDate( map ) );
+                setChangeFiles( changeSet, map );
+                scmResult.addChange( changeSet );
+            }
+        }
+
+        return scmResult;
+    }
+
+    private void setChangeFiles( ChangeSet changeSet, Map<String, Object> context )
+    {
+        List<Map<String, Object>> files = ContinuumBuildAgentUtil.getChangeSetFiles( context );
+
+        if ( files != null )
+        {
+            for ( Map<String, Object> map : files )
+            {
+                ChangeFile changeFile = new ChangeFile();
+                changeFile.setName( ContinuumBuildAgentUtil.getChangeFileName( map ) );
+                changeFile.setRevision( ContinuumBuildAgentUtil.getChangeFileRevision( map ) );
+                changeFile.setStatus( ContinuumBuildAgentUtil.getChangeFileStatus( map ) );
+
+                changeSet.addFile( changeFile );
+            }
+        }
+    }
+
+    private PrepareBuildProjectsTask createPrepareBuildProjectsTask( List<BuildContext> buildContexts )
+        throws ContinuumBuildAgentException
+    {
+        if ( buildContexts != null && buildContexts.size() > 0 )
+        {
+            BuildContext context = buildContexts.get( 0 );
+            return new PrepareBuildProjectsTask( buildContexts, new BuildTrigger( context.getTrigger(),
+                                                                                  context.getUsername() ),
+                                                 context.getProjectGroupId(), context.getScmRootAddress(),
+                                                 context.getScmRootId() );
+        }
+        else
+        {
+            log.info( "Nothing to build" );
+            return null;
+        }
+    }
+
+    private int[] listToIntArray( List<String> strings )
+    {
+        if ( strings == null || strings.isEmpty() )
+        {
+            return new int[0];
+        }
+        int[] array = new int[0];
+        for ( String intString : strings )
+        {
+            array = ArrayUtils.add( array, Integer.parseInt( intString ) );
+        }
+        return array;
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/ChangeLogProjectAction.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/ChangeLogProjectAction.java
new file mode 100644
index 0000000..bc9c873
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/ChangeLogProjectAction.java
@@ -0,0 +1,138 @@
+package org.apache.continuum.buildagent.action;
+
+/*
+ * 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 org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
+import org.apache.continuum.buildagent.utils.ContinuumBuildAgentUtil;
+import org.apache.continuum.scm.ContinuumScm;
+import org.apache.continuum.scm.ContinuumScmConfiguration;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.scm.ChangeSet;
+import org.apache.maven.scm.ScmException;
+import org.apache.maven.scm.command.changelog.ChangeLogScmResult;
+import org.apache.maven.scm.command.changelog.ChangeLogSet;
+import org.codehaus.plexus.action.AbstractAction;
+
+import java.io.File;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @plexus.component role="org.codehaus.plexus.action.Action" role-hint="changelog-agent-project"
+ */
+public class ChangeLogProjectAction
+    extends AbstractAction
+{
+    /**
+     * @plexus.requirement
+     */
+    private BuildAgentConfigurationService buildAgentConfigurationService;
+
+    /**
+     * @plexus.requirement
+     */
+    private ContinuumScm scm;
+
+    public void execute( Map context )
+        throws Exception
+    {
+        Project project = ContinuumBuildAgentUtil.getProject( context );
+
+        try
+        {
+            File workingDirectory = buildAgentConfigurationService.getWorkingDirectory( project.getId() );
+            ContinuumScmConfiguration config = createScmConfiguration( project, workingDirectory );
+            config.setLatestUpdateDate( ContinuumBuildAgentUtil.getLatestUpdateDate( context ) );
+            getLogger().info( "Getting changeLog of project: " + project.getName() );
+            ChangeLogScmResult changeLogResult = scm.changeLog( config );
+
+            if ( !changeLogResult.isSuccess() )
+            {
+                getLogger().warn( "Error getting change log of project " + project.getName() );
+
+                getLogger().warn( "Command Output: " + changeLogResult.getCommandOutput() );
+
+                getLogger().warn( "Provider Message: " + changeLogResult.getProviderMessage() );
+            }
+
+            context.put( ContinuumBuildAgentUtil.KEY_LATEST_UPDATE_DATE, getLatestUpdateDate( changeLogResult ) );
+        }
+        catch ( ScmException e )
+        {
+            context.put( ContinuumBuildAgentUtil.KEY_LATEST_UPDATE_DATE, null );
+
+            getLogger().error( e.getMessage(), e );
+        }
+    }
+
+    private ContinuumScmConfiguration createScmConfiguration( Project project, File workingDirectory )
+    {
+        ContinuumScmConfiguration config = new ContinuumScmConfiguration();
+        config.setUrl( project.getScmUrl() );
+        config.setUsername( project.getScmUsername() );
+        config.setPassword( project.getScmPassword() );
+        config.setUseCredentialsCache( project.isScmUseCache() );
+        config.setWorkingDirectory( workingDirectory );
+        config.setTag( project.getScmTag() );
+
+        return config;
+    }
+
+    private Date getLatestUpdateDate( ChangeLogScmResult changeLogScmResult )
+    {
+        ChangeLogSet changeLogSet = changeLogScmResult.getChangeLog();
+
+        if ( changeLogSet != null )
+        {
+            List<ChangeSet> changes = changeLogSet.getChangeSets();
+
+            if ( changes != null && !changes.isEmpty() )
+            {
+                long date = 0;
+
+                for ( ChangeSet change : changes )
+                {
+                    if ( date < change.getDate().getTime() )
+                    {
+                        date = change.getDate().getTime();
+                    }
+                }
+
+                if ( date != 0 )
+                {
+                    return new Date( date );
+                }
+            }
+        }
+
+        return null;
+    }
+
+    public void setScm( ContinuumScm scm )
+    {
+        this.scm = scm;
+    }
+
+    public void setBuildAgentConfigurationService( BuildAgentConfigurationService buildAgentConfigurationService )
+    {
+        this.buildAgentConfigurationService = buildAgentConfigurationService;
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/CheckWorkingDirectoryAction.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/CheckWorkingDirectoryAction.java
new file mode 100644
index 0000000..0f64044
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/CheckWorkingDirectoryAction.java
@@ -0,0 +1,60 @@
+package org.apache.continuum.buildagent.action;
+
+/*
+ * 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 org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
+import org.apache.continuum.buildagent.utils.ContinuumBuildAgentUtil;
+import org.apache.maven.continuum.model.project.Project;
+import org.codehaus.plexus.action.AbstractAction;
+
+import java.io.File;
+import java.util.Map;
+
+/**
+ * @plexus.component role="org.codehaus.plexus.action.Action" role-hint="check-agent-working-directory"
+ */
+public class CheckWorkingDirectoryAction
+    extends AbstractAction
+{
+    /**
+     * @plexus.requirement
+     */
+    BuildAgentConfigurationService buildAgentConfigurationService;
+
+    public void execute( Map context )
+        throws Exception
+    {
+        Project project = ContinuumBuildAgentUtil.getProject( context );
+
+        File workingDirectory = buildAgentConfigurationService.getWorkingDirectory( project.getId() );
+
+        if ( !workingDirectory.exists() )
+        {
+            context.put( ContinuumBuildAgentUtil.KEY_WORKING_DIRECTORY_EXISTS, Boolean.FALSE );
+
+            return;
+        }
+
+        File[] files = workingDirectory.listFiles();
+
+        context.put( ContinuumBuildAgentUtil.KEY_WORKING_DIRECTORY_EXISTS, files.length > 0 );
+    }
+
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/CheckoutProjectAction.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/CheckoutProjectAction.java
new file mode 100644
index 0000000..0a880e2
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/CheckoutProjectAction.java
@@ -0,0 +1,230 @@
+package org.apache.continuum.buildagent.action;
+
+/*
+ * 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 org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
+import org.apache.continuum.buildagent.utils.ContinuumBuildAgentUtil;
+import org.apache.continuum.scm.ContinuumScm;
+import org.apache.continuum.scm.ContinuumScmConfiguration;
+import org.apache.continuum.scm.ContinuumScmUtils;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.scm.ScmResult;
+import org.apache.maven.scm.ScmException;
+import org.apache.maven.scm.command.checkout.CheckOutScmResult;
+import org.apache.maven.scm.manager.NoSuchScmProviderException;
+import org.apache.maven.scm.repository.ScmRepositoryException;
+import org.codehaus.plexus.action.AbstractAction;
+
+import java.io.File;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @plexus.component role="org.codehaus.plexus.action.Action" role-hint="checkout-agent-project"
+ */
+public class CheckoutProjectAction
+    extends AbstractAction
+{
+    /**
+     * @plexus.requirement
+     */
+    private BuildAgentConfigurationService buildAgentConfigurationService;
+
+    /**
+     * @plexus.requirement
+     */
+    private ContinuumScm scm;
+
+    public void execute( Map context )
+        throws Exception
+    {
+        Project project = ContinuumBuildAgentUtil.getProject( context );
+
+        File workingDirectory = buildAgentConfigurationService.getWorkingDirectory( project.getId() );
+
+        // ----------------------------------------------------------------------
+        // Check out the project
+        // ----------------------------------------------------------------------
+
+        ScmResult result;
+
+        try
+        {
+            String scmUserName = ContinuumBuildAgentUtil.getString( context, ContinuumBuildAgentUtil.KEY_SCM_USERNAME,
+                                                                    project.getScmUsername() );
+            String scmPassword = ContinuumBuildAgentUtil.getString( context, ContinuumBuildAgentUtil.KEY_SCM_PASSWORD,
+                                                                    project.getScmPassword() );
+
+            ContinuumScmConfiguration config = createScmConfiguration( project, workingDirectory, scmUserName,
+                                                                       scmPassword );
+
+            String tag = config.getTag();
+            getLogger().info(
+                "Checking out project: '" + project.getName() + "', id: '" + project.getId() + "' " + "to '" +
+                    workingDirectory + "'" + ( tag != null ? " with branch/tag " + tag + "." : "." ) );
+
+            CheckOutScmResult checkoutResult = scm.checkout( config );
+            //if ( StringUtils.isNotEmpty( checkoutResult.getRelativePathProjectDirectory() ) )
+            //{
+            //    context.put( AbstractContinuumAction.KEY_PROJECT_RELATIVE_PATH,
+            //                 checkoutResult.getRelativePathProjectDirectory() );
+            //}
+
+            if ( !checkoutResult.isSuccess() )
+            {
+                // TODO: is it more appropriate to return this in the converted result so that it can be presented to
+                // the user?
+                String msg = "Error while checking out the code for project: '" + project.getName() + "', id: '" +
+                    project.getId() + "' to '" + workingDirectory.getAbsolutePath() + "'" +
+                    ( tag != null ? " with branch/tag " + tag + "." : "." );
+                getLogger().warn( msg );
+
+                getLogger().warn( "Command output: " + checkoutResult.getCommandOutput() );
+
+                getLogger().warn( "Provider message: " + checkoutResult.getProviderMessage() );
+            }
+            else
+            {
+                getLogger().info( "Checked out " + checkoutResult.getCheckedOutFiles().size() + " files." );
+            }
+
+            result = convertScmResult( checkoutResult );
+        }
+        catch ( ScmRepositoryException e )
+        {
+            result = new ScmResult();
+
+            result.setSuccess( false );
+
+            result.setProviderMessage( e.getMessage() + ": " + getValidationMessages( e ) );
+
+            getLogger().error( e.getMessage(), e );
+        }
+        catch ( NoSuchScmProviderException e )
+        {
+            // TODO: this is not making it back into a result of any kind - log it at least. Same is probably the case for ScmException
+            result = new ScmResult();
+
+            result.setSuccess( false );
+
+            result.setProviderMessage( e.getMessage() );
+
+            getLogger().error( e.getMessage(), e );
+        }
+        catch ( ScmException e )
+        {
+            result = new ScmResult();
+
+            result.setSuccess( false );
+
+            result.setException( ContinuumBuildAgentUtil.throwableMessagesToString( e ) );
+
+            getLogger().error( e.getMessage(), e );
+        }
+        catch ( Throwable t )
+        {
+            // TODO: do we want this here, or should it be to the logs?
+            // TODO: what throwables do we really get here that we can cope with?
+            result = new ScmResult();
+
+            result.setSuccess( false );
+
+            result.setException( ContinuumBuildAgentUtil.throwableMessagesToString( t ) );
+
+            getLogger().error( t.getMessage(), t );
+        }
+
+        context.put( ContinuumBuildAgentUtil.KEY_CHECKOUT_SCM_RESULT, result );
+    }
+
+    private ContinuumScmConfiguration createScmConfiguration( Project project, File workingDirectory,
+                                                              String scmUserName, String scmPassword )
+    {
+        ContinuumScmConfiguration config = new ContinuumScmConfiguration();
+
+        // CONTINUUM-2628
+        config = ContinuumScmUtils.setSCMCredentialsforSSH( config, project.getScmUrl(), scmUserName, scmPassword );
+
+        config.setUrl( project.getScmUrl() );
+        config.setUseCredentialsCache( project.isScmUseCache() );
+        config.setWorkingDirectory( workingDirectory );
+        config.setTag( project.getScmTag() );
+        return config;
+    }
+
+    private ScmResult convertScmResult( CheckOutScmResult scmResult )
+    {
+        ScmResult result = new ScmResult();
+
+        result.setSuccess( scmResult.isSuccess() );
+
+        result.setCommandLine( maskPassword( scmResult.getCommandLine() ) );
+
+        result.setCommandOutput( scmResult.getCommandOutput() );
+
+        result.setProviderMessage( scmResult.getProviderMessage() );
+
+        return result;
+    }
+
+    // TODO: migrate to the SvnCommandLineUtils version (preferably properly encapsulated in the provider)
+    private String maskPassword( String commandLine )
+    {
+        String cmd = commandLine;
+
+        if ( cmd != null && cmd.startsWith( "svn" ) )
+        {
+            String pwdString = "--password";
+
+            if ( cmd.indexOf( pwdString ) > 0 )
+            {
+                int index = cmd.indexOf( pwdString ) + pwdString.length() + 1;
+
+                int nextSpace = cmd.indexOf( " ", index );
+
+                cmd = cmd.substring( 0, index ) + "********" + cmd.substring( nextSpace );
+            }
+        }
+
+        return cmd;
+    }
+
+    private String getValidationMessages( ScmRepositoryException ex )
+    {
+        List<String> messages = ex.getValidationMessages();
+
+        StringBuffer message = new StringBuffer();
+
+        if ( messages != null && !messages.isEmpty() )
+        {
+            for ( Iterator<String> i = messages.iterator(); i.hasNext(); )
+            {
+                message.append( i.next() );
+
+                if ( i.hasNext() )
+                {
+                    message.append( System.getProperty( "line.separator" ) );
+                }
+            }
+        }
+        return message.toString();
+    }
+}
\ No newline at end of file
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/CleanWorkingDirectoryAction.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/CleanWorkingDirectoryAction.java
new file mode 100644
index 0000000..32dfa55
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/CleanWorkingDirectoryAction.java
@@ -0,0 +1,63 @@
+package org.apache.continuum.buildagent.action;
+
+/*
+ * 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 org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
+import org.apache.continuum.buildagent.utils.ContinuumBuildAgentUtil;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.shared.model.fileset.FileSet;
+import org.apache.maven.shared.model.fileset.util.FileSetManager;
+import org.codehaus.plexus.action.AbstractAction;
+
+import java.io.File;
+import java.util.Map;
+
+/**
+ * @plexus.component role="org.codehaus.plexus.action.Action" role-hint="clean-agent-working-directory"
+ */
+public class CleanWorkingDirectoryAction
+    extends AbstractAction
+{
+    /**
+     * @plexus.requirement
+     */
+    private BuildAgentConfigurationService buildAgentConfigurationService;
+
+    public void execute( Map context )
+        throws Exception
+    {
+        Project project = ContinuumBuildAgentUtil.getProject( context );
+
+        File workingDirectory = buildAgentConfigurationService.getWorkingDirectory( project.getId() );
+
+        if ( workingDirectory.exists() )
+        {
+            getLogger().debug( "Cleaning working directory " + workingDirectory.getAbsolutePath() );
+
+            FileSetManager fileSetManager = new FileSetManager();
+            FileSet fileSet = new FileSet();
+            fileSet.setDirectory( workingDirectory.getPath() );
+            fileSet.addInclude( "**/**" );
+            // TODO : this with a configuration option somewhere ?
+            fileSet.setFollowSymlinks( false );
+            fileSetManager.delete( fileSet );
+        }
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/CreateBuildProjectTaskAction.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/CreateBuildProjectTaskAction.java
new file mode 100644
index 0000000..ee0a724
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/CreateBuildProjectTaskAction.java
@@ -0,0 +1,90 @@
+package org.apache.continuum.buildagent.action;
+
+/*
+ * 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 org.apache.continuum.buildagent.buildcontext.BuildContext;
+import org.apache.continuum.buildagent.taskqueue.manager.BuildAgentTaskQueueManager;
+import org.apache.continuum.buildagent.utils.ContinuumBuildAgentUtil;
+import org.apache.continuum.taskqueue.BuildProjectTask;
+import org.apache.continuum.taskqueue.manager.TaskQueueManagerException;
+import org.apache.continuum.utils.build.BuildTrigger;
+import org.apache.maven.continuum.ContinuumException;
+import org.codehaus.plexus.action.AbstractAction;
+import org.codehaus.plexus.taskqueue.TaskQueueException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @plexus.component role="org.codehaus.plexus.action.Action" role-hint="create-agent-build-project-task"
+ */
+public class CreateBuildProjectTaskAction
+    extends AbstractAction
+{
+    private static final Logger log = LoggerFactory.getLogger( CreateBuildProjectTaskAction.class );
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildAgentTaskQueueManager buildAgentTaskQueueManager;
+
+    public void execute( Map context )
+        throws Exception
+    {
+        List<BuildContext> buildContexts = ContinuumBuildAgentUtil.getBuildContexts( context );
+
+        for ( BuildContext buildContext : buildContexts )
+        {
+            BuildTrigger buildTrigger = new BuildTrigger( buildContext.getTrigger(), buildContext.getUsername() );
+
+            BuildProjectTask buildProjectTask = new BuildProjectTask( buildContext.getProjectId(),
+                                                                      buildContext.getBuildDefinitionId(), buildTrigger,
+                                                                      buildContext.getProjectName(),
+                                                                      buildContext.getBuildDefinitionLabel(),
+                                                                      buildContext.getScmResult(),
+                                                                      buildContext.getProjectGroupId() );
+            buildProjectTask.setMaxExecutionTime( buildContext.getMaxExecutionTime() * 1000 );
+
+            try
+            {
+                if ( !buildAgentTaskQueueManager.isProjectInBuildQueue( buildProjectTask.getProjectId() ) )
+                {
+                    log.info( "Adding project {} to build queue", buildProjectTask.getProjectId() );
+                    buildAgentTaskQueueManager.getBuildQueue().put( buildProjectTask );
+                }
+            }
+            catch ( TaskQueueException e )
+            {
+                log.error( "Error while enqueing build task for project " + buildContext.getProjectId(), e );
+                throw new ContinuumException(
+                    "Error while enqueuing build task for project " + buildContext.getProjectId(), e );
+            }
+            catch ( TaskQueueManagerException e )
+            {
+                log.error( "Error while checking if project " + buildContext.getProjectId() + " is in build queue", e );
+                throw new ContinuumException(
+                    "Error while checking if project " + buildContext.getProjectId() + " is in build queue", e );
+            }
+        }
+    }
+
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/ExecuteBuilderAction.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/ExecuteBuilderAction.java
new file mode 100644
index 0000000..881e653
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/ExecuteBuilderAction.java
@@ -0,0 +1,137 @@
+package org.apache.continuum.buildagent.action;
+
+/*
+ * 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 org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildCancelledException;
+import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutionResult;
+import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutor;
+import org.apache.continuum.buildagent.build.execution.manager.BuildAgentBuildExecutorManager;
+import org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
+import org.apache.continuum.buildagent.utils.ContinuumBuildAgentUtil;
+import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.BuildResult;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.project.ContinuumProjectState;
+import org.codehaus.plexus.action.AbstractAction;
+
+import java.io.File;
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * @plexus.component role="org.codehaus.plexus.action.Action" role-hint="execute-agent-builder"
+ */
+public class ExecuteBuilderAction
+    extends AbstractAction
+{
+    /**
+     * @plexus.requirement
+     */
+    private BuildAgentBuildExecutorManager buildAgentBuildExecutorManager;
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildAgentConfigurationService buildAgentConfigurationService;
+
+    public void execute( Map context )
+        throws Exception
+    {
+        // ----------------------------------------------------------------------
+        // Get parameters from the context
+        // ----------------------------------------------------------------------
+
+        Project project = ContinuumBuildAgentUtil.getProject( context );
+
+        BuildDefinition buildDefinition = ContinuumBuildAgentUtil.getBuildDefinition( context );
+
+        Map<String, String> environments = ContinuumBuildAgentUtil.getEnvironments( context );
+
+        String localRepository = ContinuumBuildAgentUtil.getLocalRepository( context );
+
+        int trigger = ContinuumBuildAgentUtil.getTrigger( context );
+
+        String username = ContinuumBuildAgentUtil.getUsername( context );
+
+        ContinuumAgentBuildExecutor buildExecutor = buildAgentBuildExecutorManager.getBuildExecutor(
+            project.getExecutorId() );
+
+        // ----------------------------------------------------------------------
+        // Make the buildResult
+        // ----------------------------------------------------------------------
+
+        BuildResult buildResult = new BuildResult();
+
+        buildResult.setStartTime( new Date().getTime() );
+
+        buildResult.setState( ContinuumProjectState.BUILDING );
+
+        buildResult.setTrigger( trigger );
+
+        buildResult.setUsername( username );
+
+        buildResult.setBuildDefinition( buildDefinition );
+
+        buildResult.setScmResult( ContinuumBuildAgentUtil.getScmResult( context, null ) );
+
+        context.put( ContinuumBuildAgentUtil.KEY_BUILD_RESULT, buildResult );
+
+        try
+        {
+            File buildOutputFile = buildAgentConfigurationService.getBuildOutputFile( project.getId() );
+
+            getLogger().debug( "Start building of project " + project.getId() );
+            ContinuumAgentBuildExecutionResult result = buildExecutor.build( project, buildDefinition, buildOutputFile,
+                                                                             environments, localRepository );
+
+            buildResult.setState( result.getExitCode() == 0 ? ContinuumProjectState.OK : ContinuumProjectState.FAILED );
+
+            buildResult.setExitCode( result.getExitCode() );
+        }
+        catch ( ContinuumAgentBuildCancelledException e )
+        {
+            getLogger().info( "Cancelled build" );
+
+            buildResult.setState( ContinuumProjectState.CANCELLED );
+        }
+        catch ( Throwable e )
+        {
+            getLogger().error( "Error running buildResult", e );
+
+            buildResult.setState( ContinuumProjectState.ERROR );
+
+            buildResult.setError( ContinuumBuildAgentUtil.throwableToString( e ) );
+        }
+        finally
+        {
+            buildResult.setEndTime( new Date().getTime() );
+
+            if ( buildResult.getState() != ContinuumProjectState.OK &&
+                buildResult.getState() != ContinuumProjectState.FAILED &&
+                buildResult.getState() != ContinuumProjectState.ERROR &&
+                buildResult.getState() != ContinuumProjectState.CANCELLED )
+            {
+                buildResult.setState( ContinuumProjectState.ERROR );
+            }
+
+            context.put( ContinuumBuildAgentUtil.KEY_BUILD_RESULT, buildResult );
+        }
+    }
+}
\ No newline at end of file
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/UpdateProjectFromWorkingDirectoryAction.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/UpdateProjectFromWorkingDirectoryAction.java
new file mode 100644
index 0000000..1e309e3
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/UpdateProjectFromWorkingDirectoryAction.java
@@ -0,0 +1,71 @@
+package org.apache.continuum.buildagent.action;
+
+/*
+ * 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 org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutor;
+import org.apache.continuum.buildagent.build.execution.manager.BuildAgentBuildExecutorManager;
+import org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
+import org.apache.continuum.buildagent.utils.ContinuumBuildAgentUtil;
+import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.Project;
+import org.codehaus.plexus.action.AbstractAction;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.util.Map;
+
+/**
+ * @plexus.component role="org.codehaus.plexus.action.Action"
+ * role-hint="update-project-from-agent-working-directory"
+ */
+public class UpdateProjectFromWorkingDirectoryAction
+    extends AbstractAction
+{
+    private static final Logger logger = LoggerFactory.getLogger( UpdateProjectFromWorkingDirectoryAction.class );
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildAgentBuildExecutorManager buildAgentBuildExecutorManager;
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildAgentConfigurationService buildAgentConfigurationService;
+
+    public void execute( Map context )
+        throws Exception
+    {
+        Project project = ContinuumBuildAgentUtil.getProject( context );
+
+        logger.info( "Updating project '" + project.getName() + "' from checkout." );
+
+        BuildDefinition buildDefinition = ContinuumBuildAgentUtil.getBuildDefinition( context );
+
+        File workingDirectory = buildAgentConfigurationService.getWorkingDirectory( project.getId() );
+
+        ContinuumAgentBuildExecutor buildExecutor = buildAgentBuildExecutorManager.getBuildExecutor(
+            project.getExecutorId() );
+
+        buildExecutor.updateProjectFromWorkingDirectory( workingDirectory, project, buildDefinition );
+    }
+
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/UpdateWorkingDirectoryAction.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/UpdateWorkingDirectoryAction.java
new file mode 100644
index 0000000..fb9a269
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/UpdateWorkingDirectoryAction.java
@@ -0,0 +1,305 @@
+package org.apache.continuum.buildagent.action;
+
+/*
+ * 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 org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
+import org.apache.continuum.buildagent.utils.ContinuumBuildAgentUtil;
+import org.apache.continuum.scm.ContinuumScm;
+import org.apache.continuum.scm.ContinuumScmConfiguration;
+import org.apache.continuum.scm.ContinuumScmUtils;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.scm.ChangeFile;
+import org.apache.maven.continuum.model.scm.ChangeSet;
+import org.apache.maven.continuum.model.scm.ScmResult;
+import org.apache.maven.scm.ScmException;
+import org.apache.maven.scm.ScmFile;
+import org.apache.maven.scm.command.update.UpdateScmResult;
+import org.apache.maven.scm.manager.NoSuchScmProviderException;
+import org.apache.maven.scm.repository.ScmRepositoryException;
+import org.codehaus.plexus.action.AbstractAction;
+
+import java.io.File;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @plexus.component role="org.codehaus.plexus.action.Action" role-hint="update-agent-working-directory"
+ */
+public class UpdateWorkingDirectoryAction
+    extends AbstractAction
+{
+    /**
+     * @plexus.requirement
+     */
+    private BuildAgentConfigurationService buildAgentConfigurationService;
+
+    /**
+     * @plexus.requirement
+     */
+    private ContinuumScm scm;
+
+    public void execute( Map context )
+        throws Exception
+    {
+        Project project = ContinuumBuildAgentUtil.getProject( context );
+
+        UpdateScmResult scmResult;
+
+        ScmResult result;
+
+        try
+        {
+            File workingDirectory = buildAgentConfigurationService.getWorkingDirectory( project.getId() );
+            ContinuumScmConfiguration config = createScmConfiguration( project, workingDirectory );
+            config.setLatestUpdateDate( ContinuumBuildAgentUtil.getLatestUpdateDate( context ) );
+            String tag = config.getTag();
+            String msg = project.getName() + "', id: '" + project.getId() + "' to '" +
+                workingDirectory.getAbsolutePath() + "'" + ( tag != null ? " with branch/tag " + tag + "." : "." );
+            getLogger().info( "Updating project: " + msg );
+            scmResult = scm.update( config );
+
+            if ( !scmResult.isSuccess() )
+            {
+                getLogger().warn( "Error while updating the code for project: '" + msg );
+
+                getLogger().warn( "Command output: " + scmResult.getCommandOutput() );
+
+                getLogger().warn( "Provider message: " + scmResult.getProviderMessage() );
+            }
+
+            if ( scmResult.getUpdatedFiles() != null && scmResult.getUpdatedFiles().size() > 0 )
+            {
+                getLogger().info( "Updated " + scmResult.getUpdatedFiles().size() + " files." );
+            }
+
+            result = convertScmResult( scmResult );
+        }
+        catch ( ScmRepositoryException e )
+        {
+            result = new ScmResult();
+
+            result.setSuccess( false );
+
+            result.setProviderMessage( e.getMessage() + ": " + getValidationMessages( e ) );
+
+            getLogger().error( e.getMessage(), e );
+        }
+        catch ( NoSuchScmProviderException e )
+        {
+            // TODO: this is not making it back into a result of any kind - log it at least. Same is probably the case for ScmException
+            result = new ScmResult();
+
+            result.setSuccess( false );
+
+            result.setProviderMessage( e.getMessage() );
+
+            getLogger().error( e.getMessage(), e );
+        }
+        catch ( ScmException e )
+        {
+            result = new ScmResult();
+
+            result.setSuccess( false );
+
+            result.setException( ContinuumBuildAgentUtil.throwableMessagesToString( e ) );
+
+            getLogger().error( e.getMessage(), e );
+        }
+
+        context.put( ContinuumBuildAgentUtil.KEY_UPDATE_SCM_RESULT, result );
+
+        Date latestUpdateDate = getLatestUpdateDate( result );
+
+        if ( latestUpdateDate == null )
+        {
+            latestUpdateDate = ContinuumBuildAgentUtil.getLatestUpdateDate( context );
+        }
+
+        context.put( ContinuumBuildAgentUtil.KEY_LATEST_UPDATE_DATE, latestUpdateDate );
+    }
+
+    private ContinuumScmConfiguration createScmConfiguration( Project project, File workingDirectory )
+    {
+        ContinuumScmConfiguration config = new ContinuumScmConfiguration();
+        config.setUrl( project.getScmUrl() );
+
+        // CONTINUUM-2628
+        config = ContinuumScmUtils.setSCMCredentialsforSSH( config, project.getScmUrl(), project.getScmUsername(),
+                                                            project.getScmPassword() );
+
+        config.setUseCredentialsCache( project.isScmUseCache() );
+        config.setWorkingDirectory( workingDirectory );
+        config.setTag( project.getScmTag() );
+        return config;
+    }
+
+    private ScmResult convertScmResult( UpdateScmResult scmResult )
+    {
+        ScmResult result = new ScmResult();
+
+        result.setCommandLine( maskPassword( scmResult.getCommandLine() ) );
+
+        result.setSuccess( scmResult.isSuccess() );
+
+        result.setCommandOutput( scmResult.getCommandOutput() );
+
+        result.setProviderMessage( scmResult.getProviderMessage() );
+
+        if ( scmResult.getChanges() != null && !scmResult.getChanges().isEmpty() )
+        {
+            for ( org.apache.maven.scm.ChangeSet scmChangeSet : (List<org.apache.maven.scm.ChangeSet>) scmResult.getChanges() )
+            {
+                ChangeSet change = new ChangeSet();
+
+                change.setAuthor( scmChangeSet.getAuthor() );
+
+                change.setComment( scmChangeSet.getComment() );
+
+                if ( scmChangeSet.getDate() != null )
+                {
+                    change.setDate( scmChangeSet.getDate().getTime() );
+                }
+
+                if ( scmChangeSet.getFiles() != null )
+                {
+                    for ( org.apache.maven.scm.ChangeFile f : (List<org.apache.maven.scm.ChangeFile>) scmChangeSet.getFiles() )
+                    {
+                        ChangeFile file = new ChangeFile();
+
+                        file.setName( f.getName() );
+
+                        file.setRevision( f.getRevision() );
+
+                        change.addFile( file );
+                    }
+                }
+
+                result.addChange( change );
+            }
+        }
+        else
+        {
+            // We don't have a changes information probably because provider doesn't have a changelog command
+            // so we use the updated list that contains only the updated files list
+            ChangeSet changeSet = convertScmFileSetToChangeSet( scmResult.getUpdatedFiles() );
+
+            if ( changeSet != null )
+            {
+                result.addChange( changeSet );
+            }
+        }
+        return result;
+    }
+
+    private static ChangeSet convertScmFileSetToChangeSet( List<ScmFile> files )
+    {
+        ChangeSet changeSet = null;
+
+        if ( files != null && !files.isEmpty() )
+        {
+            changeSet = new ChangeSet();
+
+            // TODO: author, etc.
+            for ( ScmFile scmFile : files )
+            {
+                ChangeFile file = new ChangeFile();
+
+                file.setName( scmFile.getPath() );
+
+                // TODO: revision?
+
+                file.setStatus( scmFile.getStatus().toString() );
+
+                changeSet.addFile( file );
+            }
+        }
+        return changeSet;
+    }
+
+    // TODO: migrate to the SvnCommandLineUtils version (preferably properly encapsulated in the provider)
+    private String maskPassword( String commandLine )
+    {
+        String cmd = commandLine;
+
+        if ( cmd != null && cmd.startsWith( "svn" ) )
+        {
+            String pwdString = "--password";
+
+            if ( cmd.indexOf( pwdString ) > 0 )
+            {
+                int index = cmd.indexOf( pwdString ) + pwdString.length() + 1;
+
+                int nextSpace = cmd.indexOf( " ", index );
+
+                cmd = cmd.substring( 0, index ) + "********" + cmd.substring( nextSpace );
+            }
+        }
+
+        return cmd;
+    }
+
+    private String getValidationMessages( ScmRepositoryException ex )
+    {
+        List<String> messages = ex.getValidationMessages();
+
+        StringBuffer message = new StringBuffer();
+
+        if ( messages != null && !messages.isEmpty() )
+        {
+            for ( Iterator<String> i = messages.iterator(); i.hasNext(); )
+            {
+                message.append( i.next() );
+
+                if ( i.hasNext() )
+                {
+                    message.append( System.getProperty( "line.separator" ) );
+                }
+            }
+        }
+        return message.toString();
+    }
+
+    private Date getLatestUpdateDate( ScmResult result )
+    {
+        List<ChangeSet> changes = result.getChanges();
+
+        if ( changes != null && !changes.isEmpty() )
+        {
+            long date = 0;
+
+            for ( ChangeSet change : changes )
+            {
+                if ( date < change.getDate() )
+                {
+                    date = change.getDate();
+                }
+            }
+
+            if ( date != 0 )
+            {
+                return new Date( date );
+            }
+        }
+
+        return null;
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/AbstractBuildExecutor.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/AbstractBuildExecutor.java
new file mode 100644
index 0000000..df04595
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/AbstractBuildExecutor.java
@@ -0,0 +1,601 @@
+package org.apache.continuum.buildagent.build.execution;
+
+/*
+ * 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 org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
+import org.apache.continuum.buildagent.installation.BuildAgentInstallationService;
+import org.apache.continuum.buildagent.manager.BuildAgentManager;
+import org.apache.continuum.buildagent.utils.ContinuumBuildAgentUtil;
+import org.apache.continuum.utils.shell.ExecutionResult;
+import org.apache.continuum.utils.shell.ShellCommandHelper;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.project.ProjectDependency;
+import org.apache.maven.continuum.model.project.ProjectDeveloper;
+import org.apache.maven.continuum.model.project.ProjectNotifier;
+import org.apache.maven.continuum.project.ContinuumProjectState;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.commandline.ExecutableResolver;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
+import org.codehaus.plexus.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+public abstract class AbstractBuildExecutor
+    implements ContinuumAgentBuildExecutor, Initializable
+{
+    protected static final Logger log = LoggerFactory.getLogger( AbstractBuildExecutor.class );
+
+    /**
+     * @plexus.requirement
+     */
+    private ShellCommandHelper shellCommandHelper;
+
+    /**
+     * @plexus.requirement
+     */
+    private ExecutableResolver executableResolver;
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildAgentConfigurationService buildAgentConfigurationService;
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildAgentInstallationService buildAgentInstallationService;
+
+    /**
+     * @plexus.configuration
+     */
+    private String defaultExecutable;
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildAgentManager buildAgentManager;
+
+    // ----------------------------------------------------------------------
+    //
+    // ----------------------------------------------------------------------
+
+    private final String id;
+
+    private boolean resolveExecutable;
+
+    // ----------------------------------------------------------------------
+    //
+    // ----------------------------------------------------------------------
+
+    protected AbstractBuildExecutor( String id, boolean resolveExecutable )
+    {
+        this.id = id;
+
+        this.resolveExecutable = resolveExecutable;
+    }
+
+    public void setShellCommandHelper( ShellCommandHelper shellCommandHelper )
+    {
+        this.shellCommandHelper = shellCommandHelper;
+    }
+
+    public ShellCommandHelper getShellCommandHelper()
+    {
+        return shellCommandHelper;
+    }
+
+    public void setDefaultExecutable( String defaultExecutable )
+    {
+        this.defaultExecutable = defaultExecutable;
+    }
+
+    public BuildAgentConfigurationService getBuildAgentConfigurationService()
+    {
+        return buildAgentConfigurationService;
+    }
+
+    public void setBuildAgentConfigurationService( BuildAgentConfigurationService buildAgentConfigurationService )
+    {
+        this.buildAgentConfigurationService = buildAgentConfigurationService;
+    }
+
+    public BuildAgentInstallationService getBuildAgentInstallationService()
+    {
+        return buildAgentInstallationService;
+    }
+
+    public void setBuildAgentInstallationService( BuildAgentInstallationService buildAgentInstallationService )
+    {
+        this.buildAgentInstallationService = buildAgentInstallationService;
+    }
+
+    public BuildAgentManager getBuildAgentManager()
+    {
+        return buildAgentManager;
+    }
+
+    public void setBuildAgentManager( BuildAgentManager buildAgentManager )
+    {
+        this.buildAgentManager = buildAgentManager;
+    }
+
+    // ----------------------------------------------------------------------
+    // Component Lifecycle
+    // ----------------------------------------------------------------------
+
+    public String getDefaultExecutable()
+    {
+        return defaultExecutable;
+    }
+
+    public void initialize()
+        throws InitializationException
+    {
+        List path = executableResolver.getDefaultPath();
+
+        if ( resolveExecutable )
+        {
+            if ( StringUtils.isEmpty( defaultExecutable ) )
+            {
+                log.warn( "The default executable for build executor '" + id + "' is not set. " +
+                              "This will cause a problem unless the project has a executable configured." );
+            }
+            else
+            {
+                File resolvedExecutable = executableResolver.findExecutable( defaultExecutable, path );
+
+                if ( resolvedExecutable == null )
+                {
+                    log.warn(
+                        "Could not find the executable '" + defaultExecutable + "' in the " + "path '" + path + "'." );
+                }
+                else
+                {
+                    log.info( "Resolved the executable '" + defaultExecutable + "' to " + "'" +
+                                  resolvedExecutable.getAbsolutePath() + "'." );
+                }
+            }
+        }
+    }
+
+    // ----------------------------------------------------------------------
+    //
+    // ----------------------------------------------------------------------
+
+    /**
+     * Find the actual executable path to be used
+     *
+     * @param defaultExecutable
+     * @return The executable path
+     */
+    protected String findExecutable( String executable, String defaultExecutable, boolean resolveExecutable,
+                                     File workingDirectory )
+    {
+        // ----------------------------------------------------------------------
+        // If we're not searching the path for the executable, prefix the
+        // executable with the working directory to make sure the path is
+        // absolute and thus won't be tried resolved by using the PATH
+        // ----------------------------------------------------------------------
+
+        String actualExecutable;
+
+        if ( !resolveExecutable )
+        {
+            actualExecutable = new File( workingDirectory, executable ).getAbsolutePath();
+        }
+        else
+        {
+            List<String> path = executableResolver.getDefaultPath();
+
+            if ( StringUtils.isEmpty( executable ) )
+            {
+                executable = defaultExecutable;
+            }
+
+            File e = executableResolver.findExecutable( executable, path );
+
+            if ( e == null )
+            {
+                log.debug( "Could not find the executable '" + executable + "' in this path: " );
+
+                for ( String element : path )
+                {
+                    log.debug( element );
+                }
+
+                actualExecutable = defaultExecutable;
+            }
+            else
+            {
+                actualExecutable = e.getAbsolutePath();
+            }
+        }
+
+        //sometimes executable isn't found in path but it exit (CONTINUUM-365)
+        File actualExecutableFile = new File( actualExecutable );
+
+        if ( !actualExecutableFile.exists() )
+        {
+            actualExecutable = executable;
+        }
+
+        return actualExecutable;
+    }
+
+    protected ContinuumAgentBuildExecutionResult executeShellCommand( Project project, String executable,
+                                                                      String arguments, File output,
+                                                                      Map<String, String> environments )
+        throws ContinuumAgentBuildExecutorException, ContinuumAgentBuildCancelledException
+    {
+
+        File workingDirectory = getWorkingDirectory( project.getId() );
+
+        String actualExecutable = findExecutable( executable, defaultExecutable, resolveExecutable, workingDirectory );
+
+        // ----------------------------------------------------------------------
+        // Execute the build
+        // ----------------------------------------------------------------------
+
+        try
+        {
+            ExecutionResult result = getShellCommandHelper().executeShellCommand( workingDirectory, actualExecutable,
+                                                                                  arguments, output, project.getId(),
+                                                                                  environments );
+
+            log.info( "Exit code: " + result.getExitCode() );
+
+            return new ContinuumAgentBuildExecutionResult( output, result.getExitCode() );
+        }
+        catch ( Exception e )
+        {
+            if ( e.getCause() instanceof InterruptedException )
+            {
+                throw new ContinuumAgentBuildCancelledException( "The build was cancelled", e );
+            }
+            else
+            {
+                throw new ContinuumAgentBuildExecutorException(
+                    "Error while executing shell command. The most common error is that '" + executable + "' " +
+                        "is not in your path.", e );
+            }
+        }
+    }
+
+    protected Properties getContinuumSystemProperties( Project project )
+    {
+        Properties properties = new Properties();
+        properties.setProperty( "continuum.project.group.name", project.getProjectGroup().getName() );
+        properties.setProperty( "continuum.project.lastBuild.state", String.valueOf( project.getOldState() ) );
+        properties.setProperty( "continuum.project.lastBuild.number", String.valueOf( project.getBuildNumber() ) );
+        properties.setProperty( "continuum.project.nextBuild.number", String.valueOf( project.getBuildNumber() + 1 ) );
+        properties.setProperty( "continuum.project.id", String.valueOf( project.getId() ) );
+        properties.setProperty( "continuum.project.name", project.getName() );
+        properties.setProperty( "continuum.project.version", project.getVersion() );
+        return properties;
+    }
+
+    protected String getBuildFileForProject( BuildDefinition buildDefinition )
+    {
+        return StringUtils.clean( buildDefinition.getBuildFile() );
+    }
+
+    protected void updateProject( Project project )
+        throws ContinuumAgentBuildExecutorException
+    {
+        Map<String, Object> projectMap = new HashMap<String, Object>();
+
+        projectMap.put( ContinuumBuildAgentUtil.KEY_PROJECT_ID, project.getId() );
+        if ( StringUtils.isNotEmpty( project.getVersion() ) )
+        {
+            projectMap.put( ContinuumBuildAgentUtil.KEY_PROJECT_VERSION, project.getVersion() );
+        }
+        else
+        {
+            projectMap.put( ContinuumBuildAgentUtil.KEY_PROJECT_VERSION, "" );
+        }
+        if ( StringUtils.isNotEmpty( project.getArtifactId() ) )
+        {
+            projectMap.put( ContinuumBuildAgentUtil.KEY_ARTIFACT_ID, project.getArtifactId() );
+        }
+        else
+        {
+            projectMap.put( ContinuumBuildAgentUtil.KEY_ARTIFACT_ID, "" );
+        }
+        if ( StringUtils.isNotEmpty( project.getGroupId() ) )
+        {
+            projectMap.put( ContinuumBuildAgentUtil.KEY_GROUP_ID, project.getGroupId() );
+        }
+        else
+        {
+            projectMap.put( ContinuumBuildAgentUtil.KEY_GROUP_ID, "" );
+        }
+        if ( StringUtils.isNotEmpty( project.getName() ) )
+        {
+            projectMap.put( ContinuumBuildAgentUtil.KEY_PROJECT_NAME, project.getName() );
+        }
+        else
+        {
+            projectMap.put( ContinuumBuildAgentUtil.KEY_PROJECT_NAME, "" );
+        }
+        if ( StringUtils.isNotEmpty( project.getDescription() ) )
+        {
+            projectMap.put( ContinuumBuildAgentUtil.KEY_PROJECT_DESCRIPTION, project.getDescription() );
+        }
+        else
+        {
+            projectMap.put( ContinuumBuildAgentUtil.KEY_PROJECT_DESCRIPTION, "" );
+        }
+        if ( StringUtils.isNotEmpty( project.getScmUrl() ) )
+        {
+            projectMap.put( ContinuumBuildAgentUtil.KEY_SCM_URL, project.getScmUrl() );
+        }
+        else
+        {
+            projectMap.put( ContinuumBuildAgentUtil.KEY_SCM_URL, "" );
+        }
+        if ( StringUtils.isNotEmpty( project.getScmTag() ) )
+        {
+            projectMap.put( ContinuumBuildAgentUtil.KEY_SCM_TAG, project.getScmTag() );
+        }
+        else
+        {
+            projectMap.put( ContinuumBuildAgentUtil.KEY_SCM_TAG, "" );
+        }
+        if ( StringUtils.isNotEmpty( project.getUrl() ) )
+        {
+            projectMap.put( ContinuumBuildAgentUtil.KEY_PROJECT_URL, project.getUrl() );
+        }
+        else
+        {
+            projectMap.put( ContinuumBuildAgentUtil.KEY_PROJECT_URL, "" );
+        }
+        projectMap.put( ContinuumBuildAgentUtil.KEY_PROJECT_PARENT, getProjectParent( project.getParent() ) );
+        projectMap.put( ContinuumBuildAgentUtil.KEY_PROJECT_DEVELOPERS, getProjectDevelopers(
+            project.getDevelopers() ) );
+        projectMap.put( ContinuumBuildAgentUtil.KEY_PROJECT_DEPENDENCIES, getProjectDependencies(
+            project.getDependencies() ) );
+        projectMap.put( ContinuumBuildAgentUtil.KEY_PROJECT_NOTIFIERS, getProjectNotifiers( project.getNotifiers() ) );
+
+        try
+        {
+            log.debug( "Update project {}" + project.getId() );
+            buildAgentManager.updateProject( projectMap );
+        }
+        catch ( Exception e )
+        {
+            throw new ContinuumAgentBuildExecutorException( "Failed to update project", e );
+        }
+    }
+
+    protected List<Map<String, String>> getProjectDevelopers( List<ProjectDeveloper> developers )
+    {
+        List<Map<String, String>> pDevelopers = new ArrayList<Map<String, String>>();
+
+        if ( developers != null )
+        {
+            for ( ProjectDeveloper developer : developers )
+            {
+                Map<String, String> map = new HashMap<String, String>();
+                if ( StringUtils.isNotEmpty( developer.getName() ) )
+                {
+                    map.put( ContinuumBuildAgentUtil.KEY_PROJECT_DEVELOPER_NAME, developer.getName() );
+                }
+                else
+                {
+                    map.put( ContinuumBuildAgentUtil.KEY_PROJECT_DEVELOPER_NAME, "" );
+                }
+                if ( StringUtils.isNotEmpty( developer.getEmail() ) )
+                {
+                    map.put( ContinuumBuildAgentUtil.KEY_PROJECT_DEVELOPER_EMAIL, developer.getEmail() );
+                }
+                else
+                {
+                    map.put( ContinuumBuildAgentUtil.KEY_PROJECT_DEVELOPER_EMAIL, "" );
+                }
+                if ( StringUtils.isNotEmpty( developer.getScmId() ) )
+                {
+                    map.put( ContinuumBuildAgentUtil.KEY_PROJECT_DEVELOPER_SCMID, developer.getScmId() );
+                }
+                else
+                {
+                    map.put( ContinuumBuildAgentUtil.KEY_PROJECT_DEVELOPER_SCMID, "" );
+                }
+
+                pDevelopers.add( map );
+            }
+        }
+        return pDevelopers;
+    }
+
+    protected Map<String, Object> getProjectParent( ProjectDependency parent )
+    {
+        Map<String, Object> map = new HashMap<String, Object>();
+
+        if ( parent != null )
+        {
+            if ( StringUtils.isNotEmpty( parent.getGroupId() ) )
+            {
+                map.put( ContinuumBuildAgentUtil.KEY_GROUP_ID, parent.getGroupId() );
+            }
+            else
+            {
+                map.put( ContinuumBuildAgentUtil.KEY_GROUP_ID, "" );
+            }
+            if ( StringUtils.isNotEmpty( parent.getArtifactId() ) )
+            {
+                map.put( ContinuumBuildAgentUtil.KEY_ARTIFACT_ID, parent.getArtifactId() );
+            }
+            else
+            {
+                map.put( ContinuumBuildAgentUtil.KEY_ARTIFACT_ID, "" );
+            }
+            if ( StringUtils.isNotEmpty( parent.getVersion() ) )
+            {
+                map.put( ContinuumBuildAgentUtil.KEY_PROJECT_VERSION, parent.getVersion() );
+            }
+            else
+            {
+                map.put( ContinuumBuildAgentUtil.KEY_PROJECT_VERSION, "" );
+            }
+        }
+        return map;
+    }
+
+    protected List<Map<String, Object>> getProjectDependencies( List<ProjectDependency> dependencies )
+    {
+        List<Map<String, Object>> pDependencies = new ArrayList<Map<String, Object>>();
+
+        if ( dependencies != null )
+        {
+            for ( ProjectDependency dependency : dependencies )
+            {
+                Map<String, Object> map = new HashMap<String, Object>();
+                if ( StringUtils.isNotEmpty( dependency.getGroupId() ) )
+                {
+                    map.put( ContinuumBuildAgentUtil.KEY_GROUP_ID, dependency.getGroupId() );
+                }
+                else
+                {
+                    map.put( ContinuumBuildAgentUtil.KEY_GROUP_ID, "" );
+                }
+                if ( StringUtils.isNotEmpty( dependency.getArtifactId() ) )
+                {
+                    map.put( ContinuumBuildAgentUtil.KEY_ARTIFACT_ID, dependency.getArtifactId() );
+                }
+                else
+                {
+                    map.put( ContinuumBuildAgentUtil.KEY_ARTIFACT_ID, "" );
+                }
+                if ( StringUtils.isNotEmpty( dependency.getVersion() ) )
+                {
+                    map.put( ContinuumBuildAgentUtil.KEY_PROJECT_VERSION, dependency.getVersion() );
+                }
+                else
+                {
+                    map.put( ContinuumBuildAgentUtil.KEY_PROJECT_VERSION, "" );
+                }
+
+                pDependencies.add( map );
+            }
+        }
+        return pDependencies;
+    }
+
+    protected List<Map<String, Object>> getProjectNotifiers( List<ProjectNotifier> notifiers )
+    {
+        List<Map<String, Object>> pNotifiers = new ArrayList<Map<String, Object>>();
+
+        if ( notifiers != null )
+        {
+            for ( ProjectNotifier notifier : notifiers )
+            {
+                Map<String, Object> map = new HashMap<String, Object>();
+
+                if ( notifier.getConfiguration() != null )
+                {
+                    map.put( ContinuumBuildAgentUtil.KEY_NOTIFIER_CONFIGURATION, notifier.getConfiguration() );
+                }
+                else
+                {
+                    map.put( ContinuumBuildAgentUtil.KEY_NOTIFIER_CONFIGURATION, "" );
+                }
+                if ( StringUtils.isNotBlank( notifier.getType() ) )
+                {
+                    map.put( ContinuumBuildAgentUtil.KEY_NOTIFIER_TYPE, notifier.getType() );
+                }
+                else
+                {
+                    map.put( ContinuumBuildAgentUtil.KEY_NOTIFIER_TYPE, "" );
+                }
+                map.put( ContinuumBuildAgentUtil.KEY_NOTIFIER_FROM, notifier.getFrom() );
+                map.put( ContinuumBuildAgentUtil.KEY_NOTIFIER_RECIPIENT_TYPE, notifier.getRecipientType() );
+                map.put( ContinuumBuildAgentUtil.KEY_NOTIFIER_ENABLED, notifier.isEnabled() );
+                map.put( ContinuumBuildAgentUtil.KEY_NOTIFIER_SEND_ON_ERROR, notifier.isSendOnError() );
+                map.put( ContinuumBuildAgentUtil.KEY_NOTIFIER_SEND_ON_SUCCESS, notifier.isSendOnSuccess() );
+                map.put( ContinuumBuildAgentUtil.KEY_NOTIFIER_SEND_ON_FAILURE, notifier.isSendOnFailure() );
+                map.put( ContinuumBuildAgentUtil.KEY_NOTIFIER_SEND_ON_SCMFAILURE, notifier.isSendOnScmFailure() );
+                map.put( ContinuumBuildAgentUtil.KEY_NOTIFIER_SEND_ON_WARNING, notifier.isSendOnWarning() );
+                pNotifiers.add( map );
+            }
+        }
+        return pNotifiers;
+    }
+
+    public boolean isBuilding( Project project )
+    {
+        return project.getState() == ContinuumProjectState.BUILDING || getShellCommandHelper().isRunning(
+            project.getId() );
+    }
+
+    public void killProcess( Project project )
+    {
+        getShellCommandHelper().killProcess( project.getId() );
+    }
+
+    public List<Artifact> getDeployableArtifacts( Project project, File workingDirectory,
+                                                  BuildDefinition buildDefinition )
+        throws ContinuumAgentBuildExecutorException
+    {
+        // Not supported by this builder
+        return Collections.EMPTY_LIST;
+    }
+
+    public MavenProject getMavenProject( File workingDirectory, BuildDefinition buildDefinition )
+        throws ContinuumAgentBuildExecutorException
+    {
+        return null;
+    }
+
+    public File getWorkingDirectory( int projectId )
+    {
+        return getBuildAgentConfigurationService().getWorkingDirectory( projectId );
+    }
+
+    public boolean isResolveExecutable()
+    {
+        return resolveExecutable;
+    }
+
+    public void setResolveExecutable( boolean resolveExecutable )
+    {
+        this.resolveExecutable = resolveExecutable;
+    }
+
+    public void setExecutableResolver( ExecutableResolver executableResolver )
+    {
+        this.executableResolver = executableResolver;
+    }
+
+    public ExecutableResolver getExecutableResolver()
+    {
+        return executableResolver;
+    }
+}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/ContinuumAgentBuildCancelledException.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/ContinuumAgentBuildCancelledException.java
similarity index 100%
rename from continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/ContinuumAgentBuildCancelledException.java
rename to continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/ContinuumAgentBuildCancelledException.java
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/ContinuumAgentBuildExecutionResult.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/ContinuumAgentBuildExecutionResult.java
new file mode 100644
index 0000000..19549fd
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/ContinuumAgentBuildExecutionResult.java
@@ -0,0 +1,46 @@
+package org.apache.continuum.buildagent.build.execution;
+
+/*
+ * 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.io.File;
+
+public class ContinuumAgentBuildExecutionResult
+{
+    private final File output;
+
+    private final int exitCode;
+
+    public ContinuumAgentBuildExecutionResult( File output, int exitCode )
+    {
+        this.output = output;
+
+        this.exitCode = exitCode;
+    }
+
+    public File getOutput()
+    {
+        return output;
+    }
+
+    public int getExitCode()
+    {
+        return exitCode;
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/ContinuumAgentBuildExecutor.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/ContinuumAgentBuildExecutor.java
new file mode 100644
index 0000000..f1c2c21
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/ContinuumAgentBuildExecutor.java
@@ -0,0 +1,52 @@
+package org.apache.continuum.buildagent.build.execution;
+
+/*
+ * 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 org.apache.maven.artifact.Artifact;
+import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.project.MavenProject;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+
+public interface ContinuumAgentBuildExecutor
+{
+    String ROLE = ContinuumAgentBuildExecutor.class.getName();
+
+    ContinuumAgentBuildExecutionResult build( Project project, BuildDefinition buildDefinition, File buildOutput,
+                                              Map<String, String> environments, String localRepository )
+        throws ContinuumAgentBuildExecutorException, ContinuumAgentBuildCancelledException;
+
+    boolean isBuilding( Project project );
+
+    void killProcess( Project project );
+
+    // TODO: are these part of the builder interface, or a separate project/build definition interface?
+    List<Artifact> getDeployableArtifacts( Project project, File workingDirectory, BuildDefinition buildDefinition )
+        throws ContinuumAgentBuildExecutorException;
+
+    void updateProjectFromWorkingDirectory( File workingDirectory, Project project, BuildDefinition buildDefinition )
+        throws ContinuumAgentBuildExecutorException;
+
+    MavenProject getMavenProject( File workingDirectory, BuildDefinition buildDefinition )
+        throws ContinuumAgentBuildExecutorException;
+}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/ContinuumAgentBuildExecutorException.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/ContinuumAgentBuildExecutorException.java
similarity index 100%
rename from continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/ContinuumAgentBuildExecutorException.java
rename to continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/ContinuumAgentBuildExecutorException.java
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/ant/AntBuildExecutor.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/ant/AntBuildExecutor.java
new file mode 100644
index 0000000..33d908d
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/ant/AntBuildExecutor.java
@@ -0,0 +1,104 @@
+package org.apache.continuum.buildagent.build.execution.ant;
+
+/*
+ * 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 org.apache.continuum.buildagent.build.execution.AbstractBuildExecutor;
+import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildCancelledException;
+import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutionResult;
+import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutor;
+import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutorException;
+import org.apache.continuum.buildagent.installation.BuildAgentInstallationService;
+import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
+import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.Project;
+import org.codehaus.plexus.util.StringUtils;
+
+import java.io.File;
+import java.util.Enumeration;
+import java.util.Map;
+import java.util.Properties;
+
+public class AntBuildExecutor
+    extends AbstractBuildExecutor
+    implements ContinuumAgentBuildExecutor
+{
+    public static final String CONFIGURATION_EXECUTABLE = "executable";
+
+    public static final String CONFIGURATION_TARGETS = "targets";
+
+    public static final String ID = ContinuumBuildExecutorConstants.ANT_BUILD_EXECUTOR;
+
+    protected AntBuildExecutor()
+    {
+        super( ID, true );
+    }
+
+    public ContinuumAgentBuildExecutionResult build( Project project, BuildDefinition buildDefinition, File buildOutput,
+                                                     Map<String, String> environments, String localRepository )
+        throws ContinuumAgentBuildExecutorException, ContinuumAgentBuildCancelledException
+    {
+        String executable = getBuildAgentInstallationService().getExecutorConfigurator(
+            BuildAgentInstallationService.ANT_TYPE ).getExecutable();
+
+        StringBuffer arguments = new StringBuffer();
+
+        String buildFile = getBuildFileForProject( buildDefinition );
+
+        if ( !StringUtils.isEmpty( buildFile ) )
+        {
+            arguments.append( "-f " ).append( buildFile ).append( " " );
+        }
+
+        arguments.append( StringUtils.clean( buildDefinition.getArguments() ) ).append( " " );
+
+        Properties props = getContinuumSystemProperties( project );
+        for ( Enumeration itr = props.propertyNames(); itr.hasMoreElements(); )
+        {
+            String name = (String) itr.nextElement();
+            String value = props.getProperty( name );
+            arguments.append( "\"-D" ).append( name ).append( "=" ).append( value ).append( "\" " );
+        }
+
+        arguments.append( StringUtils.clean( buildDefinition.getGoals() ) );
+
+        String antHome = null;
+
+        if ( environments != null )
+        {
+            antHome = environments.get( getBuildAgentInstallationService().getEnvVar(
+                BuildAgentInstallationService.ANT_TYPE ) );
+        }
+
+        if ( StringUtils.isNotEmpty( antHome ) )
+        {
+            executable = antHome + File.separator + "bin" + File.separator + executable;
+            setResolveExecutable( false );
+        }
+
+        return executeShellCommand( project, executable, arguments.toString(), buildOutput, environments );
+    }
+
+    public void updateProjectFromWorkingDirectory( File workingDirectory, Project project,
+                                                   BuildDefinition buildDefinition )
+        throws ContinuumAgentBuildExecutorException
+    {
+        // nothing to do here
+    }
+}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/manager/BuildAgentBuildExecutorManager.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/manager/BuildAgentBuildExecutorManager.java
similarity index 100%
rename from continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/manager/BuildAgentBuildExecutorManager.java
rename to continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/manager/BuildAgentBuildExecutorManager.java
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/manager/DefaultBuildAgentBuildExecutorManager.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/manager/DefaultBuildAgentBuildExecutorManager.java
new file mode 100644
index 0000000..c78255d
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/manager/DefaultBuildAgentBuildExecutorManager.java
@@ -0,0 +1,91 @@
+package org.apache.continuum.buildagent.build.execution.manager;
+
+/*
+ * 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 org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutor;
+import org.apache.maven.continuum.ContinuumException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @plexus.component role="org.apache.continuum.buildagent.build.execution.manager.BuildAgentBuildExecutorManager"
+ * role-hint"default"
+ */
+public class DefaultBuildAgentBuildExecutorManager
+    implements BuildAgentBuildExecutorManager
+{
+    private static final Logger log = LoggerFactory.getLogger( DefaultBuildAgentBuildExecutorManager.class );
+
+    /**
+     * @plexus.requirement role="org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutor"
+     */
+    private Map<String, ContinuumAgentBuildExecutor> executors;
+
+    // ----------------------------------------------------------------------
+    // Component Lifecycle
+    // ----------------------------------------------------------------------
+
+    public void initialize()
+    {
+        if ( executors == null )
+        {
+            executors = new HashMap<String, ContinuumAgentBuildExecutor>();
+        }
+
+        if ( executors.size() == 0 )
+        {
+            log.warn( "No build executors defined." );
+        }
+        else
+        {
+            log.info( "Build executors:" );
+
+            for ( String key : executors.keySet() )
+            {
+                log.info( "  " + key );
+            }
+        }
+    }
+
+    // ----------------------------------------------------------------------
+    // BuildExecutorManager Implementation
+    // ----------------------------------------------------------------------
+
+    public ContinuumAgentBuildExecutor getBuildExecutor( String builderType )
+        throws ContinuumException
+    {
+        ContinuumAgentBuildExecutor executor = executors.get( builderType );
+
+        if ( executor == null )
+        {
+            throw new ContinuumException( "No such executor: '" + builderType + "'." );
+        }
+
+        return executor;
+    }
+
+    public boolean hasBuildExecutor( String executorId )
+    {
+        return executors.containsKey( executorId );
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m1/BuildAgentMavenOneMetadataHelper.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m1/BuildAgentMavenOneMetadataHelper.java
new file mode 100644
index 0000000..59d117c
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m1/BuildAgentMavenOneMetadataHelper.java
@@ -0,0 +1,33 @@
+package org.apache.continuum.buildagent.build.execution.maven.m1;
+
+/*
+ * 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 org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
+
+import java.io.File;
+
+public interface BuildAgentMavenOneMetadataHelper
+{
+    String ROLE = BuildAgentMavenOneMetadataHelper.class.getName();
+
+    void mapMetadata( ContinuumProjectBuildingResult result, File metadata, Project project )
+        throws BuildAgentMavenOneMetadataHelperException;
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m1/BuildAgentMavenOneMetadataHelperException.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m1/BuildAgentMavenOneMetadataHelperException.java
new file mode 100644
index 0000000..0c76691
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m1/BuildAgentMavenOneMetadataHelperException.java
@@ -0,0 +1,39 @@
+package org.apache.continuum.buildagent.build.execution.maven.m1;
+
+/*
+ * 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.
+ */
+
+public class BuildAgentMavenOneMetadataHelperException
+    extends Exception
+{
+    public BuildAgentMavenOneMetadataHelperException( String message )
+    {
+        super( message );
+    }
+
+    public BuildAgentMavenOneMetadataHelperException( Throwable cause )
+    {
+        super( cause );
+    }
+
+    public BuildAgentMavenOneMetadataHelperException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m1/DefaultBuildAgentMavenOneMetadataHelper.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m1/DefaultBuildAgentMavenOneMetadataHelper.java
new file mode 100644
index 0000000..8f404e8
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m1/DefaultBuildAgentMavenOneMetadataHelper.java
@@ -0,0 +1,369 @@
+package org.apache.continuum.buildagent.build.execution.maven.m1;
+
+/*
+ * 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 org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.project.ProjectDependency;
+import org.apache.maven.continuum.model.project.ProjectDeveloper;
+import org.apache.maven.continuum.model.project.ProjectNotifier;
+import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
+import org.codehaus.plexus.util.StringUtils;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * @plexus.component role="org.apache.continuum.buildagent.build.execution.maven.m1.BuildAgentMavenOneMetadataHelper" role-hint="default"
+ */
+public class DefaultBuildAgentMavenOneMetadataHelper
+    implements BuildAgentMavenOneMetadataHelper
+{
+    private static final Logger log = LoggerFactory.getLogger( DefaultBuildAgentMavenOneMetadataHelper.class );
+
+    public void mapMetadata( ContinuumProjectBuildingResult result, File metadata, Project project )
+        throws BuildAgentMavenOneMetadataHelperException
+    {
+        Xpp3Dom mavenProject;
+
+        try
+        {
+            mavenProject = Xpp3DomBuilder.build( new FileReader( metadata ) );
+        }
+        catch ( XmlPullParserException e )
+        {
+            result.addError( ContinuumProjectBuildingResult.ERROR_XML_PARSE );
+
+            log.info( "Error while reading maven POM (" + e.getMessage() + ").", e );
+
+            return;
+        }
+        catch ( FileNotFoundException e )
+        {
+            result.addError( ContinuumProjectBuildingResult.ERROR_POM_NOT_FOUND );
+
+            log.info( "Error while reading maven POM (" + e.getMessage() + ").", e );
+
+            return;
+        }
+        catch ( IOException e )
+        {
+            result.addError( ContinuumProjectBuildingResult.ERROR_UNKNOWN );
+
+            log.info( "Error while reading maven POM (" + e.getMessage() + ").", e );
+
+            return;
+        }
+
+        // ----------------------------------------------------------------------
+        // We cannot deal with projects that use the <extend/> element because
+        // we don't have the whole source tree and we might be missing elements
+        // that are present in the parent.
+        // ----------------------------------------------------------------------
+
+        String extend = getValue( mavenProject, "extend", null );
+
+        if ( extend != null )
+        {
+            result.addError( ContinuumProjectBuildingResult.ERROR_EXTEND );
+
+            log.info( "Cannot use a POM with an 'extend' element." );
+
+            return;
+        }
+
+        // ----------------------------------------------------------------------
+        // Artifact and group id
+        // ----------------------------------------------------------------------
+
+        String groupId;
+
+        String artifactId;
+
+        String id = getValue( mavenProject, "id", null );
+
+        if ( !StringUtils.isEmpty( id ) )
+        {
+            groupId = id;
+
+            artifactId = id;
+        }
+        else
+        {
+            groupId = getValue( mavenProject, "groupId", project.getGroupId() );
+
+            if ( StringUtils.isEmpty( groupId ) )
+            {
+                result.addError( ContinuumProjectBuildingResult.ERROR_MISSING_GROUPID );
+
+                log.info( "Missing 'groupId' element in the POM." );
+
+                // Do not throw an exception or return here, gather up as many results as possible first.
+            }
+
+            artifactId = getValue( mavenProject, "artifactId", project.getArtifactId() );
+
+            if ( StringUtils.isEmpty( artifactId ) )
+            {
+                result.addError( ContinuumProjectBuildingResult.ERROR_MISSING_ARTIFACTID );
+
+                log.info( "Missing 'artifactId' element in the POM." );
+
+                // Do not throw an exception or return here, gather up as many results as possible first.
+            }
+        }
+
+        // ----------------------------------------------------------------------
+        // version
+        // ----------------------------------------------------------------------
+
+        String version = getValue( mavenProject, "currentVersion", project.getVersion() );
+
+        if ( StringUtils.isEmpty( project.getVersion() ) && StringUtils.isEmpty( version ) )
+        {
+            result.addError( ContinuumProjectBuildingResult.ERROR_MISSING_VERSION );
+
+            // Do not throw an exception or return here, gather up as many results as possible first.
+        }
+
+        // ----------------------------------------------------------------------
+        // name
+        // ----------------------------------------------------------------------
+
+        String name = getValue( mavenProject, "name", project.getName() );
+
+        if ( StringUtils.isEmpty( project.getName() ) && StringUtils.isEmpty( name ) )
+        {
+            result.addError( ContinuumProjectBuildingResult.ERROR_MISSING_NAME );
+
+            // Do not throw an exception or return here, gather up as many results as possible first.
+        }
+
+        // ----------------------------------------------------------------------
+        // description
+        // ----------------------------------------------------------------------
+
+        String shortDescription = getValue( mavenProject, "shortDescription", project.getDescription() );
+
+        String description = getValue( mavenProject, "description", project.getDescription() );
+
+        // ----------------------------------------------------------------------
+        // scm
+        // ----------------------------------------------------------------------
+
+        Xpp3Dom repository = mavenProject.getChild( "repository" );
+
+        String scmConnection = null;
+
+        if ( repository == null )
+        {
+            if ( !StringUtils.isEmpty( project.getScmUrl() ) )
+            {
+                scmConnection = project.getScmUrl();
+            }
+            else
+            {
+                result.addError( ContinuumProjectBuildingResult.ERROR_MISSING_REPOSITORY );
+
+                // Do not throw an exception or return here, gather up as many results as possible first.
+            }
+        }
+        else
+        {
+            scmConnection = getValue( repository, "developerConnection", project.getScmUrl() );
+
+            scmConnection = getValue( repository, "connection", scmConnection );
+
+            if ( StringUtils.isEmpty( scmConnection ) )
+            {
+                result.addError( ContinuumProjectBuildingResult.ERROR_MISSING_SCM, name );
+
+                // Do not throw an exception or return here, gather up as many results as possible first.
+            }
+        }
+
+        // ----------------------------------------------------------------------
+        // Developers
+        // ----------------------------------------------------------------------
+
+        Xpp3Dom developers = mavenProject.getChild( "developers" );
+
+        if ( developers != null )
+        {
+            Xpp3Dom[] developersList = developers.getChildren();
+
+            List<ProjectDeveloper> cds = new ArrayList<ProjectDeveloper>();
+
+            for ( Xpp3Dom developer : developersList )
+            {
+                ProjectDeveloper cd = new ProjectDeveloper();
+
+                cd.setScmId( getValue( developer, "id", null ) );
+
+                cd.setName( getValue( developer, "name", null ) );
+
+                cd.setEmail( getValue( developer, "email", null ) );
+
+                cds.add( cd );
+            }
+
+            project.setDevelopers( cds );
+        }
+
+        // ----------------------------------------------------------------------
+        // Dependencies
+        // ----------------------------------------------------------------------
+
+        Xpp3Dom dependencies = mavenProject.getChild( "dependencies" );
+
+        if ( dependencies != null )
+        {
+            Xpp3Dom[] dependenciesList = dependencies.getChildren();
+
+            List<ProjectDependency> deps = new ArrayList<ProjectDependency>();
+
+            for ( Xpp3Dom dependency : dependenciesList )
+            {
+                ProjectDependency cd = new ProjectDependency();
+
+                if ( getValue( dependency, "groupId", null ) != null )
+                {
+                    cd.setGroupId( getValue( dependency, "groupId", null ) );
+
+                    cd.setArtifactId( getValue( dependency, "artifactId", null ) );
+                }
+                else
+                {
+                    cd.setGroupId( getValue( dependency, "id", null ) );
+
+                    cd.setArtifactId( getValue( dependency, "id", null ) );
+                }
+
+                cd.setVersion( getValue( dependency, "version", null ) );
+
+                deps.add( cd );
+            }
+
+            project.setDependencies( deps );
+        }
+
+        // ----------------------------------------------------------------------
+        // notifiers
+        // ----------------------------------------------------------------------
+
+        Xpp3Dom build = mavenProject.getChild( "build" );
+
+        List<ProjectNotifier> notifiers = new ArrayList<ProjectNotifier>();
+
+        // Add project Notifier
+        if ( build != null )
+        {
+            String nagEmailAddress = getValue( build, "nagEmailAddress", null );
+
+            if ( nagEmailAddress != null )
+            {
+                Properties props = new Properties();
+
+                props.put( "address", nagEmailAddress );
+
+                ProjectNotifier notifier = new ProjectNotifier();
+
+                notifier.setConfiguration( props );
+
+                notifier.setFrom( ProjectNotifier.FROM_PROJECT );
+
+                notifiers.add( notifier );
+            }
+        }
+
+        // Add all user notifiers
+        if ( project.getNotifiers() != null && !project.getNotifiers().isEmpty() )
+        {
+            for ( ProjectNotifier notif : (List<ProjectNotifier>) project.getNotifiers() )
+            {
+                if ( notif.isFromUser() )
+                {
+                    notifiers.add( notif );
+                }
+            }
+        }
+
+        // ----------------------------------------------------------------------
+        // Handle Errors / Results
+        // ----------------------------------------------------------------------
+
+        if ( result.hasErrors() )
+        {
+            // prevent project creation if there are errors.
+            return;
+        }
+
+        // ----------------------------------------------------------------------
+        // Make the project
+        // ----------------------------------------------------------------------
+
+        project.setGroupId( groupId );
+
+        project.setArtifactId( artifactId );
+
+        project.setVersion( version );
+
+        project.setName( name );
+
+        if ( StringUtils.isEmpty( shortDescription ) )
+        {
+            project.setDescription( description );
+        }
+        else
+        {
+            project.setDescription( shortDescription );
+
+        }
+
+        project.setScmUrl( scmConnection );
+
+        project.setNotifiers( notifiers );
+    }
+
+    //----------------------------------------------------------------------
+    //
+    // ----------------------------------------------------------------------
+
+    private String getValue( Xpp3Dom dom, String key, String defaultValue )
+    {
+        Xpp3Dom child = dom.getChild( key );
+
+        if ( child == null )
+        {
+            return defaultValue;
+        }
+
+        return child.getValue();
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m1/MavenOneBuildExecutor.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m1/MavenOneBuildExecutor.java
new file mode 100644
index 0000000..6442dfc
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m1/MavenOneBuildExecutor.java
@@ -0,0 +1,151 @@
+package org.apache.continuum.buildagent.build.execution.maven.m1;
+
+/*
+ * 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 org.apache.continuum.buildagent.build.execution.AbstractBuildExecutor;
+import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildCancelledException;
+import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutionResult;
+import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutor;
+import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutorException;
+import org.apache.continuum.buildagent.installation.BuildAgentInstallationService;
+import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
+import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
+import org.codehaus.plexus.util.StringUtils;
+
+import java.io.File;
+import java.util.Enumeration;
+import java.util.Map;
+import java.util.Properties;
+import javax.annotation.Resource;
+
+public class MavenOneBuildExecutor
+    extends AbstractBuildExecutor
+    implements ContinuumAgentBuildExecutor
+{
+    public final static String CONFIGURATION_GOALS = "goals";
+
+    public final static String ID = ContinuumBuildExecutorConstants.MAVEN_ONE_BUILD_EXECUTOR;
+
+    @Resource
+    private BuildAgentMavenOneMetadataHelper buildAgentMavenOneMetadataHelper;
+
+    public MavenOneBuildExecutor()
+    {
+        super( ID, true );
+    }
+
+    public ContinuumAgentBuildExecutionResult build( Project project, BuildDefinition buildDefinition, File buildOutput,
+                                                     Map<String, String> environments, String localRepository )
+        throws ContinuumAgentBuildExecutorException, ContinuumAgentBuildCancelledException
+    {
+        String executable = getBuildAgentInstallationService().getExecutorConfigurator(
+            BuildAgentInstallationService.MAVEN1_TYPE ).getExecutable();
+
+        StringBuffer arguments = new StringBuffer();
+
+        String buildFile = getBuildFileForProject( buildDefinition );
+
+        if ( !StringUtils.isEmpty( buildFile ) && !"project.xml".equals( buildFile ) )
+        {
+            arguments.append( "-p " ).append( buildFile ).append( " " );
+        }
+
+        arguments.append( StringUtils.clean( buildDefinition.getArguments() ) ).append( " " );
+
+        Properties props = getContinuumSystemProperties( project );
+        for ( Enumeration itr = props.propertyNames(); itr.hasMoreElements(); )
+        {
+            String name = (String) itr.nextElement();
+            String value = props.getProperty( name );
+            arguments.append( "\"-D" ).append( name ).append( "=" ).append( value ).append( "\" " );
+        }
+
+        if ( StringUtils.isNotEmpty( localRepository ) )
+        {
+            arguments.append( "\"-Dmaven.repo.local=" ).append( StringUtils.clean( localRepository ) ).append( "\" " );
+        }
+
+        arguments.append( StringUtils.clean( buildDefinition.getGoals() ) );
+
+        String m1Home = null;
+
+        if ( environments != null )
+        {
+            m1Home = environments.get( getBuildAgentInstallationService().getEnvVar(
+                BuildAgentInstallationService.MAVEN1_TYPE ) );
+        }
+
+        if ( StringUtils.isNotEmpty( m1Home ) )
+        {
+            executable = m1Home + File.separator + "bin" + File.separator + executable;
+            setResolveExecutable( false );
+        }
+
+        return executeShellCommand( project, executable, arguments.toString(), buildOutput, environments );
+    }
+
+    public void updateProjectFromWorkingDirectory( File workingDirectory, Project project,
+                                                   BuildDefinition buildDefinition )
+        throws ContinuumAgentBuildExecutorException
+    {
+        File projectXmlFile = null;
+
+        if ( buildDefinition != null )
+        {
+            String buildFile = StringUtils.clean( buildDefinition.getBuildFile() );
+
+            if ( !StringUtils.isEmpty( buildFile ) )
+            {
+                projectXmlFile = new File( workingDirectory, buildFile );
+            }
+        }
+
+        if ( projectXmlFile == null )
+        {
+            projectXmlFile = new File( workingDirectory, "project.xml" );
+        }
+
+        if ( !projectXmlFile.exists() )
+        {
+            throw new ContinuumAgentBuildExecutorException( "Could not find Maven project descriptor." );
+        }
+
+        try
+        {
+            ContinuumProjectBuildingResult result = new ContinuumProjectBuildingResult();
+
+            buildAgentMavenOneMetadataHelper.mapMetadata( result, projectXmlFile, project );
+
+            if ( result.hasErrors() )
+            {
+                throw new ContinuumAgentBuildExecutorException(
+                    "Error while mapping metadata:" + result.getErrorsAsString() );
+            }
+
+            updateProject( project );
+        }
+        catch ( BuildAgentMavenOneMetadataHelperException e )
+        {
+            throw new ContinuumAgentBuildExecutorException( "Error while mapping metadata.", e );
+        }
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m2/BuildAgentMavenBuilderHelper.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m2/BuildAgentMavenBuilderHelper.java
new file mode 100644
index 0000000..34a3ace
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m2/BuildAgentMavenBuilderHelper.java
@@ -0,0 +1,35 @@
+package org.apache.continuum.buildagent.build.execution.maven.m2;
+
+/*
+ * 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 org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
+import org.apache.maven.project.MavenProject;
+
+import java.io.File;
+
+public interface BuildAgentMavenBuilderHelper
+{
+    String ROLE = BuildAgentMavenBuilderHelper.class.getName();
+
+    MavenProject getMavenProject( ContinuumProjectBuildingResult result, File file );
+
+    void mapMetadataToProject( ContinuumProjectBuildingResult result, File metadata, Project project );
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m2/DefaultBuildAgentMavenBuilderHelper.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m2/DefaultBuildAgentMavenBuilderHelper.java
new file mode 100644
index 0000000..aa08fc9
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m2/DefaultBuildAgentMavenBuilderHelper.java
@@ -0,0 +1,728 @@
+package org.apache.continuum.buildagent.build.execution.maven.m2;
+
+/*
+ * 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 org.apache.maven.artifact.manager.WagonManager;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
+import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
+import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.project.ProjectDependency;
+import org.apache.maven.continuum.model.project.ProjectDeveloper;
+import org.apache.maven.continuum.model.project.ProjectNotifier;
+import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
+import org.apache.maven.model.Dependency;
+import org.apache.maven.model.Developer;
+import org.apache.maven.model.Extension;
+import org.apache.maven.model.Model;
+import org.apache.maven.model.Notifier;
+import org.apache.maven.model.Plugin;
+import org.apache.maven.model.Profile;
+import org.apache.maven.model.ReportPlugin;
+import org.apache.maven.model.Scm;
+import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
+import org.apache.maven.profiles.DefaultProfileManager;
+import org.apache.maven.profiles.ProfileManager;
+import org.apache.maven.project.InvalidProjectModelException;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.project.MavenProjectBuilder;
+import org.apache.maven.project.ProjectBuildingException;
+import org.apache.maven.project.validation.ModelValidationResult;
+import org.apache.maven.settings.MavenSettingsBuilder;
+import org.apache.maven.settings.Mirror;
+import org.apache.maven.settings.Proxy;
+import org.apache.maven.settings.Server;
+import org.apache.maven.settings.Settings;
+import org.apache.maven.settings.io.xpp3.SettingsXpp3Writer;
+import org.codehaus.plexus.PlexusConstants;
+import org.codehaus.plexus.PlexusContainer;
+import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
+import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+import org.codehaus.plexus.context.Context;
+import org.codehaus.plexus.context.ContextException;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
+import org.codehaus.plexus.util.StringUtils;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @plexus.component role="org.apache.continuum.buildagent.build.execution.maven.m2.BuildAgentMavenBuilderHelper"
+ * role-hint="default"
+ */
+public class DefaultBuildAgentMavenBuilderHelper
+    implements BuildAgentMavenBuilderHelper, Contextualizable, Initializable
+{
+    private static final Logger log = LoggerFactory.getLogger( DefaultBuildAgentMavenBuilderHelper.class );
+
+    /**
+     * @plexus.requirement
+     */
+    private MavenProjectBuilder projectBuilder;
+
+    /**
+     * @plexus.requirement
+     */
+    private MavenSettingsBuilder mavenSettingsBuilder;
+
+    /**
+     * @plexus.requirement
+     */
+    private ArtifactRepositoryFactory artifactRepositoryFactory;
+
+    /**
+     * @plexus.requirement
+     */
+    private ArtifactRepositoryLayout defaultRepositoryLayout;
+
+    private PlexusContainer container;
+
+    public MavenProject getMavenProject( ContinuumProjectBuildingResult result, File file )
+    {
+        MavenProject project;
+
+        try
+        {
+            //   TODO: This seems like code that is shared with DefaultMaven, so it should be moved to the project
+            //   builder perhaps
+
+            Settings settings = getSettings();
+
+            if ( log.isDebugEnabled() )
+            {
+                writeSettings( settings );
+            }
+
+            ProfileManager profileManager = new DefaultProfileManager( container, settings );
+
+            project = projectBuilder.build( file, getRepository( settings ), profileManager, false );
+
+            if ( log.isDebugEnabled() )
+            {
+                writePom( project );
+                writeActiveProfileStatement( project );
+            }
+
+        }
+        catch ( ProjectBuildingException e )
+        {
+            StringBuffer messages = new StringBuffer();
+
+            Throwable cause = e.getCause();
+
+            if ( cause != null )
+            {
+                while ( ( cause.getCause() != null ) && ( cause instanceof ProjectBuildingException ) )
+                {
+                    cause = cause.getCause();
+                }
+            }
+
+            if ( e instanceof InvalidProjectModelException )
+            {
+                InvalidProjectModelException ex = (InvalidProjectModelException) e;
+
+                ModelValidationResult validationResult = ex.getValidationResult();
+
+                if ( validationResult != null && validationResult.getMessageCount() > 0 )
+                {
+                    for ( String valmsg : (List<String>) validationResult.getMessages() )
+                    {
+                        result.addError( ContinuumProjectBuildingResult.ERROR_VALIDATION, valmsg );
+                        messages.append( valmsg );
+                        messages.append( "\n" );
+                    }
+                }
+            }
+
+            if ( cause instanceof ArtifactNotFoundException )
+            {
+                result.addError( ContinuumProjectBuildingResult.ERROR_ARTIFACT_NOT_FOUND, ( cause ).toString() );
+                return null;
+            }
+
+            result.addError( ContinuumProjectBuildingResult.ERROR_PROJECT_BUILDING, e.getMessage() );
+
+            String msg = "Cannot build maven project from " + file + " (" + e.getMessage() + ").\n" + messages;
+
+            log.error( msg );
+
+            return null;
+        }
+        // TODO catch all exceptions is bad
+        catch ( Exception e )
+        {
+            result.addError( ContinuumProjectBuildingResult.ERROR_PROJECT_BUILDING, e.getMessage() );
+
+            String msg = "Cannot build maven project from " + file + " (" + e.getMessage() + ").";
+
+            log.error( msg );
+
+            return null;
+        }
+
+        // ----------------------------------------------------------------------
+        // Validate the MavenProject using some Continuum rules
+        // ----------------------------------------------------------------------
+
+        // SCM connection
+        Scm scm = project.getScm();
+
+        if ( scm == null )
+        {
+            result.addError( ContinuumProjectBuildingResult.ERROR_MISSING_SCM, getProjectName( project ) );
+
+            log.error( "Missing 'scm' element in the " + getProjectName( project ) + " POM." );
+
+            return null;
+        }
+
+        String url = scm.getConnection();
+
+        if ( StringUtils.isEmpty( url ) )
+        {
+            result.addError( ContinuumProjectBuildingResult.ERROR_MISSING_SCM_CONNECTION, getProjectName( project ) );
+
+            log.error( "Missing 'connection' element in the 'scm' element in the " + getProjectName( project ) +
+                           " POM." );
+
+            return null;
+        }
+
+        return project;
+    }
+
+    public void mapMetadataToProject( ContinuumProjectBuildingResult result, File metadata, Project continuumProject )
+    {
+        MavenProject mavenProject = getMavenProject( result, metadata );
+
+        if ( mavenProject == null )
+        {
+            result.addError( ContinuumProjectBuildingResult.ERROR_UNKNOWN,
+                             "Can't load the maven project. Verify that your scm url is correct and remove/readd the project." );
+            return;
+        }
+
+        mapMavenProjectToContinuumProject( result, mavenProject, continuumProject, false );
+    }
+
+    public void mapMavenProjectToContinuumProject( ContinuumProjectBuildingResult result, MavenProject mavenProject,
+                                                   Project continuumProject, boolean groupPom )
+    {
+        if ( mavenProject == null )
+        {
+            result.addError( ContinuumProjectBuildingResult.ERROR_UNKNOWN, "The maven project is null." );
+            return;
+        }
+
+        // ----------------------------------------------------------------------
+        // Name
+        // ----------------------------------------------------------------------
+
+        continuumProject.setName( getProjectName( mavenProject ) );
+
+        // ----------------------------------------------------------------------
+        // SCM Url
+        // ----------------------------------------------------------------------
+
+        // TODO: Remove this: scm url shouldn't be null there
+        if ( StringUtils.isEmpty( continuumProject.getScmUrl() ) )
+        {
+            String scmUrl = getScmUrl( mavenProject );
+
+            continuumProject.setScmUrl( scmUrl );
+
+            if ( !"HEAD".equals( mavenProject.getScm().getTag() ) )
+            {
+                continuumProject.setScmTag( mavenProject.getScm().getTag() );
+            }
+        }
+
+        // ----------------------------------------------------------------------
+        // Version
+        // ----------------------------------------------------------------------
+
+        continuumProject.setVersion( getVersion( mavenProject ) );
+
+        // ----------------------------------------------------------------------
+        // GroupId
+        // ----------------------------------------------------------------------
+
+        if ( !StringUtils.isEmpty( mavenProject.getGroupId() ) )
+        {
+            continuumProject.setGroupId( mavenProject.getGroupId() );
+        }
+        else
+        {
+            result.addError( ContinuumProjectBuildingResult.ERROR_MISSING_GROUPID );
+            return;
+        }
+
+        // ----------------------------------------------------------------------
+        // artifactId
+        // ----------------------------------------------------------------------
+
+        if ( !StringUtils.isEmpty( mavenProject.getArtifactId() ) )
+        {
+            continuumProject.setArtifactId( mavenProject.getArtifactId() );
+        }
+        else
+        {
+            result.addError( ContinuumProjectBuildingResult.ERROR_MISSING_ARTIFACTID );
+            return;
+        }
+
+        // ----------------------------------------------------------------------
+        // Project Url
+        // ----------------------------------------------------------------------
+
+        if ( !StringUtils.isEmpty( mavenProject.getUrl() ) )
+        {
+            continuumProject.setUrl( mavenProject.getUrl() );
+        }
+
+        // ----------------------------------------------------------------------
+        // Developers
+        // ----------------------------------------------------------------------
+
+        if ( mavenProject.getDevelopers() != null )
+        {
+            List<ProjectDeveloper> developers = new ArrayList<ProjectDeveloper>();
+
+            for ( Developer d : (List<Developer>) mavenProject.getDevelopers() )
+            {
+                ProjectDeveloper cd = new ProjectDeveloper();
+
+                cd.setScmId( d.getId() );
+
+                cd.setName( d.getName() );
+
+                cd.setEmail( d.getEmail() );
+
+                developers.add( cd );
+            }
+
+            continuumProject.setDevelopers( developers );
+        }
+
+        // ----------------------------------------------------------------------
+        // Parent
+        // ----------------------------------------------------------------------
+
+        if ( mavenProject.getParent() != null )
+        {
+            MavenProject parentProject = mavenProject.getParent();
+
+            ProjectDependency parent = new ProjectDependency();
+
+            parent.setGroupId( parentProject.getGroupId() );
+
+            parent.setArtifactId( parentProject.getArtifactId() );
+
+            parent.setVersion( parentProject.getVersion() );
+
+            continuumProject.setParent( parent );
+        }
+
+        // ----------------------------------------------------------------------
+        // Dependencies
+        // ----------------------------------------------------------------------
+
+        List<ProjectDependency> dependencies = new ArrayList<ProjectDependency>();
+
+        for ( Dependency dependency : (List<Dependency>) mavenProject.getDependencies() )
+        {
+            ProjectDependency cd = new ProjectDependency();
+
+            cd.setGroupId( dependency.getGroupId() );
+
+            cd.setArtifactId( dependency.getArtifactId() );
+
+            cd.setVersion( dependency.getVersion() );
+
+            dependencies.add( cd );
+        }
+
+        for ( Plugin dependency : (List<Plugin>) mavenProject.getBuildPlugins() )
+        {
+            ProjectDependency cd = new ProjectDependency();
+
+            cd.setGroupId( dependency.getGroupId() );
+
+            cd.setArtifactId( dependency.getArtifactId() );
+
+            cd.setVersion( dependency.getVersion() );
+
+            dependencies.add( cd );
+        }
+
+        for ( ReportPlugin dependency : (List<ReportPlugin>) mavenProject.getReportPlugins() )
+        {
+            ProjectDependency cd = new ProjectDependency();
+
+            cd.setGroupId( dependency.getGroupId() );
+
+            cd.setArtifactId( dependency.getArtifactId() );
+
+            cd.setVersion( dependency.getVersion() );
+
+            dependencies.add( cd );
+        }
+
+        for ( Extension dependency : (List<Extension>) mavenProject.getBuildExtensions() )
+        {
+            ProjectDependency cd = new ProjectDependency();
+
+            cd.setGroupId( dependency.getGroupId() );
+
+            cd.setArtifactId( dependency.getArtifactId() );
+
+            cd.setVersion( dependency.getVersion() );
+
+            dependencies.add( cd );
+        }
+
+        continuumProject.setDependencies( dependencies );
+
+        // ----------------------------------------------------------------------
+        // Notifiers
+        // ----------------------------------------------------------------------
+
+        List<ProjectNotifier> userNotifiers = new ArrayList<ProjectNotifier>();
+
+        if ( continuumProject.getNotifiers() != null )
+        {
+            for ( int i = 0; i < continuumProject.getNotifiers().size(); i++ )
+            {
+                ProjectNotifier notifier = (ProjectNotifier) continuumProject.getNotifiers().get( i );
+
+                if ( notifier.isFromUser() )
+                {
+                    ProjectNotifier userNotifier = new ProjectNotifier();
+
+                    userNotifier.setType( notifier.getType() );
+
+                    userNotifier.setEnabled( notifier.isEnabled() );
+
+                    userNotifier.setConfiguration( notifier.getConfiguration() );
+
+                    userNotifier.setFrom( notifier.getFrom() );
+
+                    userNotifier.setRecipientType( notifier.getRecipientType() );
+
+                    userNotifier.setSendOnError( notifier.isSendOnError() );
+
+                    userNotifier.setSendOnFailure( notifier.isSendOnFailure() );
+
+                    userNotifier.setSendOnSuccess( notifier.isSendOnSuccess() );
+
+                    userNotifier.setSendOnWarning( notifier.isSendOnWarning() );
+
+                    userNotifier.setSendOnScmFailure( notifier.isSendOnScmFailure() );
+
+                    userNotifiers.add( userNotifier );
+                }
+            }
+        }
+
+        List<ProjectNotifier> notifiers = getNotifiers( result, mavenProject, continuumProject );
+        if ( notifiers != null )
+        {
+            continuumProject.setNotifiers( notifiers );
+        }
+
+        for ( ProjectNotifier notifier : userNotifiers )
+        {
+            continuumProject.addNotifier( notifier );
+        }
+    }
+
+    private String getScmUrl( MavenProject project )
+    {
+        return project.getScm().getConnection();
+    }
+
+    private List<ProjectNotifier> getNotifiers( ContinuumProjectBuildingResult result, MavenProject mavenProject,
+                                                Project continuumProject )
+    {
+        List<ProjectNotifier> notifiers = new ArrayList<ProjectNotifier>();
+
+        if ( mavenProject.getCiManagement() != null && mavenProject.getCiManagement().getNotifiers() != null )
+        {
+            for ( Notifier projectNotifier : (List<Notifier>) mavenProject.getCiManagement().getNotifiers() )
+            {
+                ProjectNotifier notifier = new ProjectNotifier();
+
+                if ( StringUtils.isEmpty( projectNotifier.getType() ) )
+                {
+                    result.addError( ContinuumProjectBuildingResult.ERROR_MISSING_NOTIFIER_TYPE );
+                    return null;
+                }
+
+                notifier.setType( projectNotifier.getType() );
+
+                if ( projectNotifier.getConfiguration() == null )
+                {
+                    result.addError( ContinuumProjectBuildingResult.ERROR_MISSING_NOTIFIER_CONFIGURATION );
+                    return null;
+                }
+
+                notifier.setConfiguration( projectNotifier.getConfiguration() );
+
+                notifier.setFrom( ProjectNotifier.FROM_PROJECT );
+
+                notifier.setSendOnSuccess( projectNotifier.isSendOnSuccess() );
+
+                notifier.setSendOnFailure( projectNotifier.isSendOnFailure() );
+
+                notifier.setSendOnError( projectNotifier.isSendOnError() );
+
+                notifier.setSendOnWarning( projectNotifier.isSendOnWarning() );
+
+                notifier.setSendOnScmFailure( false );
+
+                notifiers.add( notifier );
+            }
+        }
+
+        return notifiers;
+    }
+
+    private String getVersion( MavenProject project )
+    {
+        return project.getVersion();
+    }
+
+    private Settings getSettings()
+        throws SettingsConfigurationException
+    {
+        try
+        {
+            return mavenSettingsBuilder.buildSettings( false );
+        }
+        catch ( IOException e )
+        {
+            throw new SettingsConfigurationException( "Error reading settings file", e );
+        }
+        catch ( XmlPullParserException e )
+        {
+            throw new SettingsConfigurationException( e.getMessage(), e.getDetail(), e.getLineNumber(),
+                                                      e.getColumnNumber() );
+        }
+    }
+
+    private ArtifactRepository getRepository( Settings settings )
+    {
+        return artifactRepositoryFactory.createArtifactRepository( "local", "file://" + settings.getLocalRepository(),
+                                                                   defaultRepositoryLayout, null, null );
+    }
+
+    public String getProjectName( MavenProject project )
+    {
+        String name = project.getName();
+
+        if ( StringUtils.isEmpty( name ) )
+        {
+            return project.getId();
+        }
+
+        return name;
+    }
+
+    private void writeSettings( Settings settings )
+    {
+        StringWriter sWriter = new StringWriter();
+
+        SettingsXpp3Writer settingsWriter = new SettingsXpp3Writer();
+
+        try
+        {
+            settingsWriter.write( sWriter, settings );
+
+            StringBuffer message = new StringBuffer();
+
+            message.append( "\n************************************************************************************" );
+            message.append( "\nEffective Settings" );
+            message.append( "\n************************************************************************************" );
+            message.append( "\n" );
+            message.append( sWriter.toString() );
+            message.append( "\n************************************************************************************" );
+            message.append( "\n\n" );
+
+            log.debug( message.toString() );
+        }
+        catch ( IOException e )
+        {
+            log.warn( "Cannot serialize Settings to XML.", e );
+        }
+    }
+
+    private void writePom( MavenProject project )
+    {
+        StringBuffer message = new StringBuffer();
+
+        Model pom = project.getModel();
+
+        StringWriter sWriter = new StringWriter();
+
+        MavenXpp3Writer pomWriter = new MavenXpp3Writer();
+
+        try
+        {
+            pomWriter.write( sWriter, pom );
+
+            message.append( "\n************************************************************************************" );
+            message.append( "\nEffective POM for project \'" ).append( project.getId() ).append( "\'" );
+            message.append( "\n************************************************************************************" );
+            message.append( "\n" );
+            message.append( sWriter.toString() );
+            message.append( "\n************************************************************************************" );
+            message.append( "\n\n" );
+
+            log.debug( message.toString() );
+        }
+        catch ( IOException e )
+        {
+            log.warn( "Cannot serialize POM to XML.", e );
+        }
+    }
+
+    private void writeActiveProfileStatement( MavenProject project )
+    {
+        List<Profile> profiles = project.getActiveProfiles();
+
+        StringBuffer message = new StringBuffer();
+
+        message.append( "\n" );
+
+        message.append( "\n************************************************************************************" );
+        message.append( "\nActive Profiles for Project \'" ).append( project.getId() ).append( "\'" );
+        message.append( "\n************************************************************************************" );
+        message.append( "\n" );
+
+        if ( profiles == null || profiles.isEmpty() )
+        {
+            message.append( "There are no active profiles." );
+        }
+        else
+        {
+            message.append( "The following profiles are active:\n" );
+
+            for ( Profile profile : profiles )
+            {
+                message.append( "\n - " ).append( profile.getId() ).append( " (source: " ).append(
+                    profile.getSource() ).append( ")" );
+            }
+
+        }
+
+        message.append( "\n************************************************************************************" );
+        message.append( "\n\n" );
+
+        log.debug( message.toString() );
+    }
+
+    public void contextualize( Context context )
+        throws ContextException
+    {
+        container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
+    }
+
+    public void initialize()
+        throws InitializationException
+    {
+        try
+        {
+            Settings settings = getSettings();
+
+            resolveParameters( settings );
+        }
+        catch ( Exception e )
+        {
+            throw new InitializationException( "Can't initialize '" + getClass().getName() + "'", e );
+        }
+    }
+
+    /**
+     * @todo [BP] this might not be required if there is a better way to pass
+     * them in. It doesn't feel quite right.
+     * @todo [JC] we should at least provide a mapping of protocol-to-proxy for
+     * the wagons, shouldn't we?
+     */
+    private void resolveParameters( Settings settings )
+        throws ComponentLookupException, ComponentLifecycleException, SettingsConfigurationException
+    {
+        WagonManager wagonManager = (WagonManager) container.lookup( WagonManager.ROLE );
+
+        try
+        {
+            Proxy proxy = settings.getActiveProxy();
+
+            if ( proxy != null )
+            {
+                if ( proxy.getHost() == null )
+                {
+                    throw new SettingsConfigurationException( "Proxy in settings.xml has no host" );
+                }
+
+                wagonManager.addProxy( proxy.getProtocol(), proxy.getHost(), proxy.getPort(), proxy.getUsername(),
+                                       proxy.getPassword(), proxy.getNonProxyHosts() );
+            }
+
+            for ( Server server : (List<Server>) settings.getServers() )
+            {
+                wagonManager.addAuthenticationInfo( server.getId(), server.getUsername(), server.getPassword(),
+                                                    server.getPrivateKey(), server.getPassphrase() );
+
+                wagonManager.addPermissionInfo( server.getId(), server.getFilePermissions(),
+                                                server.getDirectoryPermissions() );
+
+                if ( server.getConfiguration() != null )
+                {
+                    wagonManager.addConfiguration( server.getId(), (Xpp3Dom) server.getConfiguration() );
+                }
+            }
+
+            for ( Mirror mirror : (List<Mirror>) settings.getMirrors() )
+            {
+                wagonManager.addMirror( mirror.getId(), mirror.getMirrorOf(), mirror.getUrl() );
+            }
+        }
+        finally
+        {
+            container.release( wagonManager );
+        }
+    }
+
+    void setMavenSettingsBuilder( MavenSettingsBuilder mavenSettingsBuilder )
+    {
+        this.mavenSettingsBuilder = mavenSettingsBuilder;
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m2/MavenTwoBuildExecutor.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m2/MavenTwoBuildExecutor.java
new file mode 100644
index 0000000..ea28f7d
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m2/MavenTwoBuildExecutor.java
@@ -0,0 +1,302 @@
+package org.apache.continuum.buildagent.build.execution.maven.m2;
+
+/*
+ * 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 org.apache.continuum.buildagent.build.execution.AbstractBuildExecutor;
+import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildCancelledException;
+import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutionResult;
+import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutor;
+import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutorException;
+import org.apache.continuum.buildagent.installation.BuildAgentInstallationService;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.metadata.ArtifactMetadata;
+import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
+import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.project.MavenProjectHelper;
+import org.apache.maven.project.artifact.ProjectArtifactMetadata;
+import org.codehaus.plexus.util.StringUtils;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+public class MavenTwoBuildExecutor
+    extends AbstractBuildExecutor
+    implements ContinuumAgentBuildExecutor
+{
+    public static final String CONFIGURATION_GOALS = "goals";
+
+    public static final String ID = ContinuumBuildExecutorConstants.MAVEN_TWO_BUILD_EXECUTOR;
+
+    /**
+     * @plexus.requirement
+     */
+    private MavenProjectHelper projectHelper;
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildAgentMavenBuilderHelper buildAgentMavenBuilderHelper;
+
+    public MavenTwoBuildExecutor()
+    {
+        super( ID, true );
+    }
+
+    public MavenProjectHelper getProjectHelper()
+    {
+        return projectHelper;
+    }
+
+    public void setProjectHelper( MavenProjectHelper projectHelper )
+    {
+        this.projectHelper = projectHelper;
+    }
+
+    public BuildAgentMavenBuilderHelper getBuildAgentMavenBuilderHelper()
+    {
+        return buildAgentMavenBuilderHelper;
+    }
+
+    public void setBuildAgentMavenBuilderHelper( BuildAgentMavenBuilderHelper builderHelper )
+    {
+        this.buildAgentMavenBuilderHelper = builderHelper;
+    }
+
+    public ContinuumAgentBuildExecutionResult build( Project project, BuildDefinition buildDefinition, File buildOutput,
+                                                     Map<String, String> environments, String localRepository )
+        throws ContinuumAgentBuildExecutorException, ContinuumAgentBuildCancelledException
+    {
+        String executable = getBuildAgentInstallationService().getExecutorConfigurator(
+            BuildAgentInstallationService.MAVEN2_TYPE ).getExecutable();
+
+        StringBuffer arguments = new StringBuffer();
+
+        String buildFile = getBuildFileForProject( buildDefinition );
+
+        if ( !StringUtils.isEmpty( buildFile ) && !"pom.xml".equals( buildFile ) )
+        {
+            arguments.append( "-f " ).append( buildFile ).append( " " );
+        }
+
+        arguments.append( StringUtils.clean( buildDefinition.getArguments() ) ).append( " " );
+
+        Properties props = getContinuumSystemProperties( project );
+        for ( Enumeration itr = props.propertyNames(); itr.hasMoreElements(); )
+        {
+            String name = (String) itr.nextElement();
+            String value = props.getProperty( name );
+            arguments.append( "\"-D" ).append( name ).append( "=" ).append( value ).append( "\" " );
+        }
+
+        if ( StringUtils.isNotEmpty( localRepository ) )
+        {
+            arguments.append( "\"-Dmaven.repo.local=" ).append( StringUtils.clean( localRepository ) ).append( "\" " );
+        }
+
+        arguments.append( StringUtils.clean( buildDefinition.getGoals() ) );
+
+        String m2Home = null;
+
+        if ( environments != null )
+        {
+            m2Home = environments.get( getBuildAgentInstallationService().getEnvVar(
+                BuildAgentInstallationService.MAVEN2_TYPE ) );
+        }
+
+        if ( StringUtils.isNotEmpty( m2Home ) )
+        {
+            executable = m2Home + File.separator + "bin" + File.separator + executable;
+            setResolveExecutable( false );
+        }
+
+        return executeShellCommand( project, executable, arguments.toString(), buildOutput, environments );
+    }
+
+    @Override
+    public List<Artifact> getDeployableArtifacts( Project continuumProject, File workingDirectory,
+                                                  BuildDefinition buildDefinition )
+        throws ContinuumAgentBuildExecutorException
+    {
+        MavenProject project = getMavenProject( workingDirectory, buildDefinition );
+
+        // Maven could help us out a lot more here by knowing how to get the deployment artifacts from a project.
+        // TODO: this is currently quite lame
+
+        Artifact artifact = project.getArtifact();
+
+        String projectPackaging = project.getPackaging();
+
+        boolean isPomArtifact = "pom".equals( projectPackaging );
+
+        if ( isPomArtifact )
+        {
+            artifact.setFile( project.getFile() );
+        }
+        else
+        {
+            // Attach pom
+            ArtifactMetadata metadata = new ProjectArtifactMetadata( artifact, project.getFile() );
+
+            artifact.addMetadata( metadata );
+
+            String finalName = project.getBuild().getFinalName();
+
+            String filename = finalName + "." + artifact.getArtifactHandler().getExtension();
+
+            String buildDirectory = project.getBuild().getDirectory();
+
+            File artifactFile = new File( buildDirectory, filename );
+
+            artifact.setFile( artifactFile );
+
+            // sources jar
+            File sourcesFile = new File( buildDirectory, finalName + "-sources.jar" );
+
+            if ( sourcesFile.exists() )
+            {
+                projectHelper.attachArtifact( project, "java-source", "sources", sourcesFile );
+            }
+
+            // tests sources jar
+            File testsSourcesFile = new File( buildDirectory, finalName + "-test-sources.jar" );
+
+            if ( testsSourcesFile.exists() )
+            {
+                projectHelper.attachArtifact( project, "java-source", "test-sources", testsSourcesFile );
+            }
+
+            // javadoc jar
+            File javadocFile = new File( buildDirectory, finalName + "-javadoc.jar" );
+
+            if ( javadocFile.exists() )
+            {
+                projectHelper.attachArtifact( project, "javadoc", "javadoc", javadocFile );
+            }
+
+            // client jar
+            File clientFile = new File( buildDirectory, finalName + "-client.jar" );
+
+            if ( clientFile.exists() )
+            {
+                projectHelper.attachArtifact( project, projectPackaging + "-client", "client", clientFile );
+            }
+
+            // Tests jar
+            File testsFile = new File( buildDirectory, finalName + "-tests.jar" );
+
+            if ( testsFile.exists() )
+            {
+                projectHelper.attachArtifact( project, "jar", "tests", testsFile );
+            }
+        }
+
+        List<Artifact> attachedArtifacts = project.getAttachedArtifacts();
+
+        List<Artifact> artifacts = new ArrayList<Artifact>( attachedArtifacts.size() + 1 );
+
+        if ( artifact.getFile().exists() )
+        {
+            artifacts.add( artifact );
+        }
+
+        for ( Artifact attachedArtifact : attachedArtifacts )
+        {
+            artifacts.add( attachedArtifact );
+        }
+
+        return artifacts;
+    }
+
+    public void updateProjectFromWorkingDirectory( File workingDirectory, Project project,
+                                                   BuildDefinition buildDefinition )
+        throws ContinuumAgentBuildExecutorException
+    {
+        File f = getPomFile( getBuildFileForProject( buildDefinition ), workingDirectory );
+
+        if ( !f.exists() )
+        {
+            throw new ContinuumAgentBuildExecutorException( "Could not find Maven project descriptor." );
+        }
+
+        ContinuumProjectBuildingResult result = new ContinuumProjectBuildingResult();
+
+        buildAgentMavenBuilderHelper.mapMetadataToProject( result, f, project );
+
+        if ( result.hasErrors() )
+        {
+            throw new ContinuumAgentBuildExecutorException(
+                "Error while mapping metadata:" + result.getErrorsAsString() );
+        }
+        else
+        {
+            updateProject( project );
+        }
+    }
+
+    @Override
+    public MavenProject getMavenProject( File workingDirectory, BuildDefinition buildDefinition )
+        throws ContinuumAgentBuildExecutorException
+    {
+        ContinuumProjectBuildingResult result = new ContinuumProjectBuildingResult();
+
+        File f = getPomFile( getBuildFileForProject( buildDefinition ), workingDirectory );
+
+        if ( !f.exists() )
+        {
+            throw new ContinuumAgentBuildExecutorException( "Could not find Maven project descriptor '" + f + "'." );
+        }
+
+        MavenProject project = buildAgentMavenBuilderHelper.getMavenProject( result, f );
+
+        if ( result.hasErrors() )
+        {
+            throw new ContinuumAgentBuildExecutorException(
+                "Unable to read the Maven project descriptor '" + f + "': " + result.getErrorsAsString() );
+        }
+        return project;
+    }
+
+    private static File getPomFile( String projectBuildFile, File workingDirectory )
+    {
+        File f = null;
+
+        String buildFile = StringUtils.clean( projectBuildFile );
+
+        if ( !StringUtils.isEmpty( buildFile ) )
+        {
+            f = new File( workingDirectory, buildFile );
+        }
+
+        if ( f == null )
+        {
+            f = new File( workingDirectory, "pom.xml" );
+        }
+
+        return f;
+    }
+
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m2/SettingsConfigurationException.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m2/SettingsConfigurationException.java
new file mode 100644
index 0000000..608d7c1
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m2/SettingsConfigurationException.java
@@ -0,0 +1,56 @@
+package org.apache.continuum.buildagent.build.execution.maven.m2;
+
+/*
+ * 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.
+ */
+
+public class SettingsConfigurationException
+    extends Exception
+{
+    private int lineNumber;
+
+    private int columnNumber;
+
+    public SettingsConfigurationException( String message )
+    {
+        super( message );
+    }
+
+    public SettingsConfigurationException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+
+    public SettingsConfigurationException( String message, Throwable cause, int lineNumber, int columnNumber )
+    {
+        super( message + ( lineNumber > 0 ? "\n  Line:   " + lineNumber : "" ) +
+                   ( columnNumber > 0 ? "\n  Column: " + columnNumber : "" ), cause );
+        this.lineNumber = lineNumber;
+        this.columnNumber = columnNumber;
+    }
+
+    public int getColumnNumber()
+    {
+        return columnNumber;
+    }
+
+    public int getLineNumber()
+    {
+        return lineNumber;
+    }
+}
\ No newline at end of file
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/shell/ShellBuildExecutor.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/shell/ShellBuildExecutor.java
new file mode 100644
index 0000000..7148d2a
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/shell/ShellBuildExecutor.java
@@ -0,0 +1,62 @@
+package org.apache.continuum.buildagent.build.execution.shell;
+
+/*
+ * 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 org.apache.continuum.buildagent.build.execution.AbstractBuildExecutor;
+import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildCancelledException;
+import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutionResult;
+import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutor;
+import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutorException;
+import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
+import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.Project;
+
+import java.io.File;
+import java.util.Map;
+
+public class ShellBuildExecutor
+    extends AbstractBuildExecutor
+    implements ContinuumAgentBuildExecutor
+{
+    public static final String CONFIGURATION_EXECUTABLE = "executable";
+
+    public static final String ID = ContinuumBuildExecutorConstants.SHELL_BUILD_EXECUTOR;
+
+    public ShellBuildExecutor()
+    {
+        super( ID, false );
+    }
+
+    public ContinuumAgentBuildExecutionResult build( Project project, BuildDefinition buildDefinition, File buildOutput,
+                                                     Map<String, String> environments, String localRepository )
+        throws ContinuumAgentBuildExecutorException, ContinuumAgentBuildCancelledException
+    {
+        String executable = getBuildFileForProject( buildDefinition );
+
+        return executeShellCommand( project, executable, buildDefinition.getArguments(), buildOutput, environments );
+    }
+
+    public void updateProjectFromWorkingDirectory( File workingDirectory, Project project,
+                                                   BuildDefinition buildDefinition )
+        throws ContinuumAgentBuildExecutorException
+    {
+        // nothing to do here   
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/buildcontext/BuildContext.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/buildcontext/BuildContext.java
new file mode 100644
index 0000000..1d8689d
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/buildcontext/BuildContext.java
@@ -0,0 +1,401 @@
+package org.apache.continuum.buildagent.buildcontext;
+
+/*
+ * 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 org.apache.maven.continuum.model.project.BuildResult;
+import org.apache.maven.continuum.model.scm.ScmResult;
+
+import java.util.Date;
+import java.util.Map;
+
+public class BuildContext
+{
+    private int projectId;
+
+    private String projectName;
+
+    private String projectVersion;
+
+    private int projectState;
+
+    private int buildNumber;
+
+    private int buildDefinitionId;
+
+    private String buildDefinitionLabel;
+
+    private String buildFile;
+
+    private String goals;
+
+    private String arguments;
+
+    private String executorId;
+
+    private String scmUrl;
+
+    private String scmUsername;
+
+    private String scmPassword;
+
+    private String scmTag;
+
+    private int trigger;
+
+    private String username;
+
+    private boolean buildFresh;
+
+    private int projectGroupId;
+
+    private String projectGroupName;
+
+    private String scmRootAddress;
+
+    private int scmRootId;
+
+    private Map<String, Object> actionContext;
+
+    private ScmResult scmResult;
+
+    private BuildResult buildResult;
+
+    private long buildStartTime;
+
+    private String localRepository;
+
+    private ScmResult oldScmResult;
+
+    private Date latestUpdateDate;
+
+    private String buildAgentUrl;
+
+    private int maxExecutionTime;
+
+    public int getProjectGroupId()
+    {
+        return projectGroupId;
+    }
+
+    public void setProjectGroupId( int projectGroupId )
+    {
+        this.projectGroupId = projectGroupId;
+    }
+
+    public String getScmRootAddress()
+    {
+        return scmRootAddress;
+    }
+
+    public void setScmRootAddress( String scmRootAddress )
+    {
+        this.scmRootAddress = scmRootAddress;
+    }
+
+    public int getProjectId()
+    {
+        return projectId;
+    }
+
+    public void setProjectId( int projectId )
+    {
+        this.projectId = projectId;
+    }
+
+    public String getProjectName()
+    {
+        return projectName;
+    }
+
+    public void setProjectName( String projectName )
+    {
+        this.projectName = projectName;
+    }
+
+    public int getProjectState()
+    {
+        return projectState;
+    }
+
+    public void setProjectState( int projectState )
+    {
+        this.projectState = projectState;
+    }
+
+    public int getBuildDefinitionId()
+    {
+        return buildDefinitionId;
+    }
+
+    public void setBuildDefinitionId( int buildDefinitionId )
+    {
+        this.buildDefinitionId = buildDefinitionId;
+    }
+
+    public String getBuildFile()
+    {
+        return buildFile;
+    }
+
+    public void setBuildFile( String buildFile )
+    {
+        this.buildFile = buildFile;
+    }
+
+    public String getGoals()
+    {
+        return goals;
+    }
+
+    public void setGoals( String goals )
+    {
+        this.goals = goals;
+    }
+
+    public String getArguments()
+    {
+        return arguments;
+    }
+
+    public void setArguments( String arguments )
+    {
+        this.arguments = arguments;
+    }
+
+    public String getExecutorId()
+    {
+        return executorId;
+    }
+
+    public void setExecutorId( String executorId )
+    {
+        this.executorId = executorId;
+    }
+
+    public String getScmUrl()
+    {
+        return scmUrl;
+    }
+
+    public void setScmUrl( String scmUrl )
+    {
+        this.scmUrl = scmUrl;
+    }
+
+    public String getScmUsername()
+    {
+        return scmUsername;
+    }
+
+    public void setScmUsername( String scmUsername )
+    {
+        this.scmUsername = scmUsername;
+    }
+
+    public String getScmPassword()
+    {
+        return scmPassword;
+    }
+
+    public void setScmPassword( String scmPassword )
+    {
+        this.scmPassword = scmPassword;
+    }
+
+    public String getScmTag()
+    {
+        return scmTag;
+    }
+
+    public void setScmTag( String scmTag )
+    {
+        this.scmTag = scmTag;
+    }
+
+    public int getTrigger()
+    {
+        return trigger;
+    }
+
+    public void setTrigger( int trigger )
+    {
+        this.trigger = trigger;
+    }
+
+    public boolean isBuildFresh()
+    {
+        return buildFresh;
+    }
+
+    public void setBuildFresh( boolean buildFresh )
+    {
+        this.buildFresh = buildFresh;
+    }
+
+    public Map<String, Object> getActionContext()
+    {
+        return actionContext;
+    }
+
+    public void setActionContext( Map<String, Object> actionContext )
+    {
+        this.actionContext = actionContext;
+    }
+
+    public ScmResult getScmResult()
+    {
+        return scmResult;
+    }
+
+    public void setScmResult( ScmResult scmResult )
+    {
+        this.scmResult = scmResult;
+    }
+
+    public BuildResult getBuildResult()
+    {
+        return buildResult;
+    }
+
+    public void setBuildResult( BuildResult buildResult )
+    {
+        this.buildResult = buildResult;
+    }
+
+    public long getBuildStartTime()
+    {
+        return buildStartTime;
+    }
+
+    public void setBuildStartTime( long buildStartTime )
+    {
+        this.buildStartTime = buildStartTime;
+    }
+
+    public String getLocalRepository()
+    {
+        return localRepository;
+    }
+
+    public void setLocalRepository( String localRepository )
+    {
+        this.localRepository = localRepository;
+    }
+
+    public void setProjectGroupName( String projectGroupName )
+    {
+        this.projectGroupName = projectGroupName;
+    }
+
+    public String getProjectGroupName()
+    {
+        return projectGroupName;
+    }
+
+    public void setProjectVersion( String projectVersion )
+    {
+        this.projectVersion = projectVersion;
+    }
+
+    public String getProjectVersion()
+    {
+        return projectVersion;
+    }
+
+    public void setBuildNumber( int buildNumber )
+    {
+        this.buildNumber = buildNumber;
+    }
+
+    public int getBuildNumber()
+    {
+        return buildNumber;
+    }
+
+    public void setOldScmResult( ScmResult oldScmResult )
+    {
+        this.oldScmResult = oldScmResult;
+    }
+
+    public ScmResult getOldScmResult()
+    {
+        return oldScmResult;
+    }
+
+    public void setLatestUpdateDate( Date latestUpdateDate )
+    {
+        this.latestUpdateDate = latestUpdateDate;
+    }
+
+    public Date getLatestUpdateDate()
+    {
+        return latestUpdateDate;
+    }
+
+    public void setBuildAgentUrl( String buildAgentUrl )
+    {
+        this.buildAgentUrl = buildAgentUrl;
+    }
+
+    public String getBuildAgentUrl()
+    {
+        return buildAgentUrl;
+    }
+
+    public void setMaxExecutionTime( int maxExecutionTime )
+    {
+        this.maxExecutionTime = maxExecutionTime;
+    }
+
+    public int getMaxExecutionTime()
+    {
+        return maxExecutionTime;
+    }
+
+    public void setScmRootId( int scmRootId )
+    {
+        this.scmRootId = scmRootId;
+    }
+
+    public int getScmRootId()
+    {
+        return scmRootId;
+    }
+
+    public void setBuildDefinitionLabel( String buildDefinitionLabel )
+    {
+        this.buildDefinitionLabel = buildDefinitionLabel;
+    }
+
+    public String getBuildDefinitionLabel()
+    {
+        return buildDefinitionLabel;
+    }
+
+    public void setUsername( String username )
+    {
+        this.username = username;
+    }
+
+    public String getUsername()
+    {
+        return username;
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/buildcontext/manager/BuildContextManager.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/buildcontext/manager/BuildContextManager.java
new file mode 100644
index 0000000..e7f87b4
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/buildcontext/manager/BuildContextManager.java
@@ -0,0 +1,40 @@
+package org.apache.continuum.buildagent.buildcontext.manager;
+
+/*
+ * 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 org.apache.continuum.buildagent.buildcontext.BuildContext;
+
+import java.util.List;
+
+/**
+ * @author Jan Stevens Ancajas
+ */
+public interface BuildContextManager
+{
+    String ROLE = BuildContextManager.class.getName();
+
+    public void addBuildContexts( List<BuildContext> buildContextList );
+
+    public List<BuildContext> getBuildContexts();
+
+    public BuildContext getBuildContext( int projectId );
+
+    public void removeBuildContext( int projectId );
+}
\ No newline at end of file
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/buildcontext/manager/DefaultBuildContextManager.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/buildcontext/manager/DefaultBuildContextManager.java
new file mode 100644
index 0000000..bf6012d
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/buildcontext/manager/DefaultBuildContextManager.java
@@ -0,0 +1,82 @@
+package org.apache.continuum.buildagent.buildcontext.manager;
+
+/*
+ * 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 org.apache.continuum.buildagent.buildcontext.BuildContext;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Jan Steven Ancajas
+ * @plexus.component role="org.apache.continuum.buildagent.buildcontext.manager.BuildContextManager" role-hint="default"
+ */
+public class DefaultBuildContextManager
+    implements BuildContextManager
+{
+    public Map<Integer, BuildContext> buildContexts;
+
+    public BuildContext getBuildContext( int projectId )
+    {
+        if ( buildContexts != null )
+        {
+            return buildContexts.get( projectId );
+        }
+
+        return null;
+    }
+
+    public List<BuildContext> getBuildContexts()
+    {
+        List<BuildContext> bContexts = new ArrayList<BuildContext>();
+
+        if ( buildContexts != null )
+        {
+            bContexts.addAll( buildContexts.values() );
+        }
+
+        return bContexts;
+    }
+
+    public void addBuildContexts( List<BuildContext> buildContextList )
+    {
+        if ( buildContexts == null )
+        {
+            buildContexts = new HashMap<Integer, BuildContext>();
+        }
+
+        for ( BuildContext buildContext : buildContextList )
+        {
+            buildContexts.put( buildContext.getProjectId(), buildContext );
+        }
+    }
+
+    public void removeBuildContext( int projectId )
+    {
+        BuildContext buildContext = getBuildContext( projectId );
+
+        if ( buildContext != null )
+        {
+            buildContexts.remove( buildContext );
+        }
+    }
+}
\ No newline at end of file
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/BuildAgentConfiguration.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/BuildAgentConfiguration.java
new file mode 100644
index 0000000..3448a73
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/BuildAgentConfiguration.java
@@ -0,0 +1,44 @@
+package org.apache.continuum.buildagent.configuration;
+
+/*
+ * 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.io.File;
+
+public interface BuildAgentConfiguration
+{
+    String ROLE = BuildAgentConfiguration.class.getName();
+
+    GeneralBuildAgentConfiguration getContinuumBuildAgentConfiguration()
+        throws BuildAgentConfigurationException;
+
+    void setContinuumBuildAgentConfiguration( GeneralBuildAgentConfiguration configuration );
+
+    void save()
+        throws BuildAgentConfigurationException;
+
+    void save( File file )
+        throws BuildAgentConfigurationException;
+
+    void reload()
+        throws BuildAgentConfigurationException;
+
+    void reload( File file )
+        throws BuildAgentConfigurationException;
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/DefaultBuildAgentConfiguration.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/DefaultBuildAgentConfiguration.java
new file mode 100644
index 0000000..153bc51
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/DefaultBuildAgentConfiguration.java
@@ -0,0 +1,189 @@
+package org.apache.continuum.buildagent.configuration;
+
+/*
+ * 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 org.apache.continuum.buildagent.model.ContinuumBuildAgentConfigurationModel;
+import org.apache.continuum.buildagent.model.io.xpp3.ContinuumBuildAgentConfigurationModelXpp3Reader;
+import org.apache.continuum.buildagent.model.io.xpp3.ContinuumBuildAgentConfigurationModelXpp3Writer;
+import org.codehaus.plexus.util.IOUtil;
+import org.codehaus.plexus.util.StringUtils;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+public class DefaultBuildAgentConfiguration
+    implements BuildAgentConfiguration
+{
+    private static final Logger log = LoggerFactory.getLogger( DefaultBuildAgentConfiguration.class );
+
+    private File configurationFile;
+
+    private GeneralBuildAgentConfiguration generalBuildAgentConfiguration;
+
+    protected void initialize()
+    {
+        if ( log.isDebugEnabled() )
+        {
+            log.debug( "configurationFile null " + ( configurationFile.getPath() == null ) );
+        }
+        if ( configurationFile != null && configurationFile.exists() )
+        {
+            try
+            {
+                reload( configurationFile );
+            }
+            catch ( BuildAgentConfigurationException e )
+            {
+                // skip this and only log a warn
+                log.warn( " error on loading configuration from file " + configurationFile.getPath() );
+            }
+        }
+        else
+        {
+            log.info( "build agent configuration file does not exists" );
+            this.generalBuildAgentConfiguration = new GeneralBuildAgentConfiguration();
+        }
+    }
+
+    public GeneralBuildAgentConfiguration getContinuumBuildAgentConfiguration()
+    {
+        return generalBuildAgentConfiguration;
+    }
+
+    public void reload()
+        throws BuildAgentConfigurationException
+    {
+        this.initialize();
+    }
+
+    public void reload( File file )
+        throws BuildAgentConfigurationException
+    {
+        FileInputStream fis = null;
+        try
+        {
+            fis = new FileInputStream( file );
+            ContinuumBuildAgentConfigurationModelXpp3Reader configurationXpp3Reader =
+                new ContinuumBuildAgentConfigurationModelXpp3Reader();
+            ContinuumBuildAgentConfigurationModel configuration = configurationXpp3Reader.read( new InputStreamReader(
+                fis ) );
+
+            this.generalBuildAgentConfiguration = new GeneralBuildAgentConfiguration();
+            if ( StringUtils.isNotEmpty( configuration.getBuildOutputDirectory() ) )
+            {
+                this.generalBuildAgentConfiguration.setBuildOutputDirectory( new File(
+                    configuration.getBuildOutputDirectory() ) );
+            }
+            if ( StringUtils.isNotEmpty( configuration.getWorkingDirectory() ) )
+            {
+                this.generalBuildAgentConfiguration.setWorkingDirectory( new File(
+                    configuration.getWorkingDirectory() ) );
+            }
+
+            this.generalBuildAgentConfiguration.setContinuumServerUrl( configuration.getContinuumServerUrl() );
+            this.generalBuildAgentConfiguration.setInstallations( configuration.getInstallations() );
+            this.generalBuildAgentConfiguration.setLocalRepositories( configuration.getLocalRepositories() );
+            this.generalBuildAgentConfiguration.setSharedSecretPassword( configuration.getSharedSecretPassword() );
+        }
+        catch ( IOException e )
+        {
+            log.error( e.getMessage(), e );
+            throw new BuildAgentConfigurationException( e.getMessage(), e );
+        }
+        catch ( XmlPullParserException e )
+        {
+            log.error( e.getMessage(), e );
+            throw new BuildAgentConfigurationException( e.getMessage(), e );
+        }
+        finally
+        {
+            if ( fis != null )
+            {
+                IOUtil.close( fis );
+            }
+        }
+    }
+
+    public void save()
+        throws BuildAgentConfigurationException
+    {
+        if ( !configurationFile.exists() )
+        {
+            configurationFile.getParentFile().mkdirs();
+        }
+        save( configurationFile );
+    }
+
+    public void save( File file )
+        throws BuildAgentConfigurationException
+    {
+        try
+        {
+            ContinuumBuildAgentConfigurationModel configurationModel = new ContinuumBuildAgentConfigurationModel();
+            if ( this.generalBuildAgentConfiguration.getBuildOutputDirectory() != null )
+            {
+                configurationModel.setBuildOutputDirectory(
+                    this.generalBuildAgentConfiguration.getBuildOutputDirectory().getPath() );
+            }
+            if ( this.generalBuildAgentConfiguration.getWorkingDirectory() != null )
+            {
+                configurationModel.setWorkingDirectory(
+                    this.generalBuildAgentConfiguration.getWorkingDirectory().getPath() );
+            }
+            configurationModel.setContinuumServerUrl( this.generalBuildAgentConfiguration.getContinuumServerUrl() );
+            configurationModel.setInstallations( this.generalBuildAgentConfiguration.getInstallations() );
+            configurationModel.setLocalRepositories( this.generalBuildAgentConfiguration.getLocalRepositories() );
+            configurationModel.setSharedSecretPassword( this.generalBuildAgentConfiguration.getSharedSecretPassword() );
+
+            ContinuumBuildAgentConfigurationModelXpp3Writer writer =
+                new ContinuumBuildAgentConfigurationModelXpp3Writer();
+            FileWriter fileWriter = new FileWriter( file );
+            writer.write( fileWriter, configurationModel );
+            fileWriter.flush();
+            fileWriter.close();
+        }
+        catch ( IOException e )
+        {
+            log.error( e.getMessage(), e );
+            throw new BuildAgentConfigurationException( e.getMessage(), e );
+        }
+    }
+
+    public void setContinuumBuildAgentConfiguration( GeneralBuildAgentConfiguration buildAgentConfiguration )
+    {
+        this.generalBuildAgentConfiguration = buildAgentConfiguration;
+    }
+
+    public File getConfigurationFile()
+    {
+        return configurationFile;
+    }
+
+    public void setConfigurationFile( File configurationFile )
+    {
+        this.configurationFile = configurationFile;
+    }
+}
\ No newline at end of file
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/DefaultBuildAgentConfigurationService.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/DefaultBuildAgentConfigurationService.java
new file mode 100644
index 0000000..28e551c
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/DefaultBuildAgentConfigurationService.java
@@ -0,0 +1,170 @@
+package org.apache.continuum.buildagent.configuration;
+
+/*
+ * 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 org.apache.continuum.buildagent.model.Installation;
+import org.apache.continuum.buildagent.model.LocalRepository;
+import org.codehaus.plexus.util.FileUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import javax.annotation.Resource;
+
+public class DefaultBuildAgentConfigurationService
+    implements BuildAgentConfigurationService
+{
+    private static final Logger log = LoggerFactory.getLogger( DefaultBuildAgentConfigurationService.class );
+
+    @Resource
+    private BuildAgentConfiguration buildAgentConfiguration;
+
+    private GeneralBuildAgentConfiguration generalBuildAgentConfiguration;
+
+    public void initialize()
+        throws BuildAgentConfigurationException
+    {
+        loadData();
+    }
+
+    public BuildAgentConfiguration getBuildAgentConfiguration()
+    {
+        return buildAgentConfiguration;
+    }
+
+    public void setBuildAgentConfiguration( BuildAgentConfiguration buildAgentConfiguration )
+    {
+        this.buildAgentConfiguration = buildAgentConfiguration;
+    }
+
+    public File getBuildOutputDirectory()
+    {
+        return generalBuildAgentConfiguration.getBuildOutputDirectory();
+    }
+
+    public File getBuildOutputDirectory( int projectId )
+    {
+        File dir = new File( getBuildOutputDirectory(), Integer.toString( projectId ) );
+
+        try
+        {
+            dir = dir.getCanonicalFile();
+        }
+        catch ( IOException e )
+        {
+        }
+
+        return dir;
+    }
+
+    public File getWorkingDirectory()
+    {
+        return generalBuildAgentConfiguration.getWorkingDirectory();
+    }
+
+    public File getWorkingDirectory( int projectId )
+    {
+        File dir = new File( generalBuildAgentConfiguration.getWorkingDirectory(), Integer.toString( projectId ) );
+
+        try
+        {
+            dir = dir.getCanonicalFile();
+        }
+        catch ( IOException e )
+        {
+        }
+
+        return dir;
+    }
+
+    public String getBuildOutput( int projectId )
+        throws BuildAgentConfigurationException
+    {
+        File file = getBuildOutputFile( projectId );
+
+        try
+        {
+            if ( file.exists() )
+            {
+                return FileUtils.fileRead( file.getAbsolutePath() );
+            }
+            else
+            {
+                return "There is no output for this build.";
+            }
+        }
+        catch ( IOException e )
+        {
+            log.warn( "Error reading build output for project '" + projectId + "'.", e );
+
+            return null;
+        }
+    }
+
+    public File getBuildOutputFile( int projectId )
+        throws BuildAgentConfigurationException
+    {
+        File dir = getBuildOutputDirectory( projectId );
+
+        if ( !dir.exists() && !dir.mkdirs() )
+        {
+            throw new BuildAgentConfigurationException(
+                "Could not make the build output directory: " + "'" + dir.getAbsolutePath() + "'." );
+        }
+
+        return new File( dir, "build.log.txt" );
+    }
+
+    public String getContinuumServerUrl()
+    {
+        return generalBuildAgentConfiguration.getContinuumServerUrl();
+    }
+
+    public List<Installation> getAvailableInstallations()
+    {
+        return generalBuildAgentConfiguration.getInstallations();
+    }
+
+    public List<LocalRepository> getLocalRepositories()
+    {
+        return generalBuildAgentConfiguration.getLocalRepositories();
+    }
+
+    public String getSharedSecretPassword()
+    {
+        return generalBuildAgentConfiguration.getSharedSecretPassword();
+    }
+
+    public void store()
+        throws BuildAgentConfigurationException
+    {
+        buildAgentConfiguration.setContinuumBuildAgentConfiguration( generalBuildAgentConfiguration );
+
+        buildAgentConfiguration.save();
+    }
+
+    private void loadData()
+        throws BuildAgentConfigurationException
+    {
+        generalBuildAgentConfiguration = buildAgentConfiguration.getContinuumBuildAgentConfiguration();
+    }
+}
\ No newline at end of file
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/GeneralBuildAgentConfiguration.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/GeneralBuildAgentConfiguration.java
new file mode 100644
index 0000000..2ecb962
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/GeneralBuildAgentConfiguration.java
@@ -0,0 +1,101 @@
+package org.apache.continuum.buildagent.configuration;
+
+/*
+ * 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 org.apache.continuum.buildagent.model.Installation;
+import org.apache.continuum.buildagent.model.LocalRepository;
+
+import java.io.File;
+import java.util.List;
+
+public class GeneralBuildAgentConfiguration
+{
+    private File workingDirectory;
+
+    private File buildOutputDirectory;
+
+    private String continuumServerUrl;
+
+    private List<Installation> installations;
+
+    private List<LocalRepository> localRepositories;
+
+    private String sharedSecretPassword;
+
+    public File getWorkingDirectory()
+    {
+        return workingDirectory;
+    }
+
+    public void setWorkingDirectory( File workingDirectory )
+    {
+        this.workingDirectory = workingDirectory;
+    }
+
+    public File getBuildOutputDirectory()
+    {
+        return buildOutputDirectory;
+    }
+
+    public void setBuildOutputDirectory( File buildOutputDirectory )
+    {
+        this.buildOutputDirectory = buildOutputDirectory;
+    }
+
+    public String getContinuumServerUrl()
+    {
+        return continuumServerUrl;
+    }
+
+    public void setContinuumServerUrl( String continuumServerUrl )
+    {
+        this.continuumServerUrl = continuumServerUrl;
+    }
+
+    public List<Installation> getInstallations()
+    {
+        return installations;
+    }
+
+    public void setInstallations( List<Installation> installations )
+    {
+        this.installations = installations;
+    }
+
+    public List<LocalRepository> getLocalRepositories()
+    {
+        return localRepositories;
+    }
+
+    public void setLocalRepositories( List<LocalRepository> localRepositories )
+    {
+        this.localRepositories = localRepositories;
+    }
+
+    public void setSharedSecretPassword( String sharedSecretPassword )
+    {
+        this.sharedSecretPassword = sharedSecretPassword;
+    }
+
+    public String getSharedSecretPassword()
+    {
+        return sharedSecretPassword;
+    }
+}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/installation/BuildAgentInstallationService.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/installation/BuildAgentInstallationService.java
similarity index 100%
rename from continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/installation/BuildAgentInstallationService.java
rename to continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/installation/BuildAgentInstallationService.java
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/installation/DefaultBuildAgentInstallationService.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/installation/DefaultBuildAgentInstallationService.java
new file mode 100644
index 0000000..6b3ea16
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/installation/DefaultBuildAgentInstallationService.java
@@ -0,0 +1,66 @@
+package org.apache.continuum.buildagent.installation;
+
+/*
+ * 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 org.apache.maven.continuum.execution.ExecutorConfigurator;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @plexus.component role="org.apache.continuum.buildagent.installation.BuildAgentInstallationService" role-hint="default"
+ */
+public class DefaultBuildAgentInstallationService
+    implements BuildAgentInstallationService, Initializable
+{
+    private Map<String, ExecutorConfigurator> typesValues;
+
+    public ExecutorConfigurator getExecutorConfigurator( String type )
+    {
+        return this.typesValues.get( type );
+    }
+
+    public void initialize()
+        throws InitializationException
+    {
+        this.typesValues = new HashMap<String, ExecutorConfigurator>();
+        this.typesValues.put( BuildAgentInstallationService.ANT_TYPE, new ExecutorConfigurator( "ant", "bin",
+                                                                                                "ANT_HOME",
+                                                                                                "-version" ) );
+
+        this.typesValues.put( BuildAgentInstallationService.ENVVAR_TYPE, null );
+        this.typesValues.put( BuildAgentInstallationService.JDK_TYPE, new ExecutorConfigurator( "java", "bin",
+                                                                                                "JAVA_HOME",
+                                                                                                "-version" ) );
+        this.typesValues.put( BuildAgentInstallationService.MAVEN1_TYPE, new ExecutorConfigurator( "maven", "bin",
+                                                                                                   "MAVEN_HOME",
+                                                                                                   "-v" ) );
+        this.typesValues.put( BuildAgentInstallationService.MAVEN2_TYPE, new ExecutorConfigurator( "mvn", "bin",
+                                                                                                   "M2_HOME", "-v" ) );
+    }
+
+    public String getEnvVar( String type )
+    {
+        ExecutorConfigurator executorConfigurator = this.typesValues.get( type );
+        return executorConfigurator == null ? null : executorConfigurator.getEnvVar();
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/manager/BuildAgentManager.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/manager/BuildAgentManager.java
new file mode 100644
index 0000000..6ccd538
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/manager/BuildAgentManager.java
@@ -0,0 +1,53 @@
+package org.apache.continuum.buildagent.manager;
+
+/*
+ * 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 org.apache.maven.continuum.ContinuumException;
+
+import java.util.Map;
+
+public interface BuildAgentManager
+{
+    String ROLE = BuildAgentManager.class.getName();
+
+    void returnBuildResult( Map<String, Object> result )
+        throws ContinuumException;
+
+    void startProjectBuild( int projectId )
+        throws ContinuumException;
+
+    Map<String, String> getEnvironments( int buildDefinitionId, String installationType )
+        throws ContinuumException;
+
+    void updateProject( Map<String, Object> project )
+        throws ContinuumException;
+
+    boolean shouldBuild( Map<String, Object> context )
+        throws ContinuumException;
+
+    void startPrepareBuild( Map<String, Object> context )
+        throws ContinuumException;
+
+    void endPrepareBuild( Map<String, Object> context )
+        throws ContinuumException;
+
+    boolean pingMaster()
+        throws ContinuumException;
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/manager/BuildAgentPurgeManager.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/manager/BuildAgentPurgeManager.java
new file mode 100644
index 0000000..fb942b7
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/manager/BuildAgentPurgeManager.java
@@ -0,0 +1,28 @@
+package org.apache.continuum.buildagent.manager;
+
+/*
+ * 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.
+ */
+
+public interface BuildAgentPurgeManager
+{
+    String ROLE = BuildAgentPurgeManager.class.getName();
+
+    void executeDirectoryPurge( String directoryType, int daysOlder, int retentionCount, boolean deleteAll )
+        throws Exception;
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/manager/BuildAgentReleaseManager.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/manager/BuildAgentReleaseManager.java
new file mode 100644
index 0000000..c6602e0
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/manager/BuildAgentReleaseManager.java
@@ -0,0 +1,60 @@
+package org.apache.continuum.buildagent.manager;
+
+/*
+ * 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 org.apache.maven.continuum.release.ContinuumReleaseException;
+import org.apache.maven.continuum.release.ContinuumReleaseManager;
+import org.apache.maven.shared.release.ReleaseResult;
+
+import java.util.Map;
+import java.util.Properties;
+
+public interface BuildAgentReleaseManager
+{
+    String ROLE = BuildAgentReleaseManager.class.getName();
+
+    String releasePrepare( Map<String, Object> project, Properties properties, Map<String, String> releaseVersion,
+                           Map<String, String> developmentVersion, Map<String, String> environments, String username )
+        throws ContinuumReleaseException;
+
+    ReleaseResult getReleaseResult( String releaseId );
+
+    Map<String, Object> getListener( String releaseId );
+
+    void removeListener( String releaseId );
+
+    String getPreparedReleaseName( String releaseId );
+
+    void releasePerform( String releaseId, String goals, String arguments, boolean useReleaseProfile, Map repository,
+                         String username )
+        throws ContinuumReleaseException;
+
+    String releasePerformFromScm( String goals, String arguments, boolean useReleaseProfile, Map repository,
+                                  String scmUrl, String scmUsername, String scmPassword, String scmTag,
+                                  String scmTagBase, Map<String, String> environments, String username )
+        throws ContinuumReleaseException;
+
+    String releaseCleanup( String releaseId );
+
+    void releaseRollback( String releaseId, int projectId )
+        throws ContinuumReleaseException;
+
+    ContinuumReleaseManager getReleaseManager();
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/manager/DefaultBuildAgentManager.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/manager/DefaultBuildAgentManager.java
new file mode 100644
index 0000000..a34be7c
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/manager/DefaultBuildAgentManager.java
@@ -0,0 +1,252 @@
+package org.apache.continuum.buildagent.manager;
+
+/*
+ * 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 org.apache.continuum.buildagent.buildcontext.BuildContext;
+import org.apache.continuum.buildagent.buildcontext.manager.BuildContextManager;
+import org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
+import org.apache.continuum.buildagent.utils.ContinuumBuildAgentUtil;
+import org.apache.continuum.distributed.transport.master.MasterBuildAgentTransportClient;
+import org.apache.maven.continuum.ContinuumException;
+import org.codehaus.plexus.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Map;
+
+/**
+ * @plexus.component role="org.apache.continuum.buildagent.manager.BuildAgentManager" role-hint="default"
+ */
+public class DefaultBuildAgentManager
+    implements BuildAgentManager
+{
+    private static final Logger log = LoggerFactory.getLogger( DefaultBuildAgentManager.class );
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildAgentConfigurationService buildAgentConfigurationService;
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildContextManager buildContextManager;
+
+    public void startProjectBuild( int projectId )
+        throws ContinuumException
+    {
+        try
+        {
+            MasterBuildAgentTransportClient client = new MasterBuildAgentTransportClient( new URL(
+                buildAgentConfigurationService.getContinuumServerUrl() ) );
+            client.startProjectBuild( projectId, getBuildAgentUrl( projectId ) );
+        }
+        catch ( MalformedURLException e )
+        {
+            log.error(
+                "Invalid continuum server URL '" + buildAgentConfigurationService.getContinuumServerUrl() + "'" );
+            throw new ContinuumException(
+                "Invalid continuum server URL '" + buildAgentConfigurationService.getContinuumServerUrl() + "'" );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Error starting project build", e );
+            throw new ContinuumException( "Error starting project build", e );
+        }
+    }
+
+    public void returnBuildResult( Map buildResult )
+        throws ContinuumException
+    {
+        try
+        {
+            MasterBuildAgentTransportClient client = new MasterBuildAgentTransportClient( new URL(
+                buildAgentConfigurationService.getContinuumServerUrl() ) );
+            client.returnBuildResult( buildResult, ContinuumBuildAgentUtil.getBuildAgentUrl( buildResult ) );
+        }
+        catch ( MalformedURLException e )
+        {
+            log.error(
+                "Invalid continuum server URL '" + buildAgentConfigurationService.getContinuumServerUrl() + "'" );
+            throw new ContinuumException(
+                "Invalid continuum server URL '" + buildAgentConfigurationService.getContinuumServerUrl() + "'" );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Error while returning build result to the continuum server", e );
+            throw new ContinuumException( e.getMessage(), e );
+        }
+    }
+
+    public Map<String, String> getEnvironments( int buildDefinitionId, String installationType )
+        throws ContinuumException
+    {
+        try
+        {
+            MasterBuildAgentTransportClient client = new MasterBuildAgentTransportClient( new URL(
+                buildAgentConfigurationService.getContinuumServerUrl() ) );
+            return client.getEnvironments( buildDefinitionId, installationType );
+        }
+        catch ( MalformedURLException e )
+        {
+            log.error(
+                "Invalid continuum server URL '" + buildAgentConfigurationService.getContinuumServerUrl() + "'" );
+            throw new ContinuumException(
+                "Invalid continuum server URL '" + buildAgentConfigurationService.getContinuumServerUrl() + "'" );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Error while retrieving environments for build definition " + buildDefinitionId, e );
+            throw new ContinuumException( e.getMessage(), e );
+        }
+    }
+
+    public void updateProject( Map project )
+        throws ContinuumException
+    {
+        try
+        {
+            MasterBuildAgentTransportClient client = new MasterBuildAgentTransportClient( new URL(
+                buildAgentConfigurationService.getContinuumServerUrl() ) );
+            client.updateProject( project );
+        }
+        catch ( MalformedURLException e )
+        {
+            log.error(
+                "Invalid continuum server URL '" + buildAgentConfigurationService.getContinuumServerUrl() + "'" );
+            throw new ContinuumException(
+                "Invalid continuum server URL '" + buildAgentConfigurationService.getContinuumServerUrl() + "'" );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Error while updating project", e );
+            throw new ContinuumException( e.getMessage(), e );
+        }
+    }
+
+    public boolean shouldBuild( Map<String, Object> context )
+        throws ContinuumException
+    {
+        try
+        {
+            MasterBuildAgentTransportClient client = new MasterBuildAgentTransportClient( new URL(
+                buildAgentConfigurationService.getContinuumServerUrl() ) );
+            return client.shouldBuild( context, ContinuumBuildAgentUtil.getBuildAgentUrl( context ) );
+        }
+        catch ( MalformedURLException e )
+        {
+            log.error(
+                "Invalid continuum server URL '" + buildAgentConfigurationService.getContinuumServerUrl() + "'" );
+            throw new ContinuumException(
+                "Invalid continuum server URL '" + buildAgentConfigurationService.getContinuumServerUrl() + "'" );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to determine if project should build", e );
+            throw new ContinuumException( "Failed to determine if project should build", e );
+        }
+    }
+
+    public void startPrepareBuild( Map<String, Object> context )
+        throws ContinuumException
+    {
+        try
+        {
+            MasterBuildAgentTransportClient client = new MasterBuildAgentTransportClient( new URL(
+                buildAgentConfigurationService.getContinuumServerUrl() ) );
+            client.startPrepareBuild( context, ContinuumBuildAgentUtil.getBuildAgentUrl( context ) );
+        }
+        catch ( MalformedURLException e )
+        {
+            log.error(
+                "Invalid continuum server URL '" + buildAgentConfigurationService.getContinuumServerUrl() + "'" );
+            throw new ContinuumException(
+                "Invalid continuum server URL '" + buildAgentConfigurationService.getContinuumServerUrl() + "'", e );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Error starting prepare build", e );
+            throw new ContinuumException( "Error starting prepare build", e );
+        }
+    }
+
+    public void endPrepareBuild( Map<String, Object> context )
+        throws ContinuumException
+    {
+        try
+        {
+            MasterBuildAgentTransportClient client = new MasterBuildAgentTransportClient( new URL(
+                buildAgentConfigurationService.getContinuumServerUrl() ) );
+            client.prepareBuildFinished( context, ContinuumBuildAgentUtil.getBuildAgentUrl( context ) );
+        }
+        catch ( MalformedURLException e )
+        {
+            throw new ContinuumException(
+                "Invalid Continuum Server URL '" + buildAgentConfigurationService.getContinuumServerUrl() + "'" );
+        }
+        catch ( Exception e )
+        {
+            throw new ContinuumException( "Error while finishing prepare build", e );
+        }
+    }
+
+    public boolean pingMaster()
+        throws ContinuumException
+    {
+        String continuumServerUrl = buildAgentConfigurationService.getContinuumServerUrl();
+
+        try
+        {
+            if ( StringUtils.isBlank( continuumServerUrl ) )
+            {
+                throw new ContinuumException(
+                    "Build agent is not configured properly. Missing continuumServerUrl in the configuration file" );
+            }
+
+            MasterBuildAgentTransportClient client = new MasterBuildAgentTransportClient( new URL(
+                continuumServerUrl ) );
+            return client.ping();
+        }
+        catch ( MalformedURLException e )
+        {
+            log.error( "Invalid continuum server URL '" + continuumServerUrl + "'", e );
+            throw new ContinuumException( "Invalid continuum server URL '" + continuumServerUrl + "'", e );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Unable to ping master " + continuumServerUrl, e );
+            throw new ContinuumException( "Unable to ping master " + continuumServerUrl + " from build agent", e );
+        }
+    }
+
+    private String getBuildAgentUrl( int projectId )
+    {
+        BuildContext context = buildContextManager.getBuildContext( projectId );
+
+        if ( context != null )
+        {
+            return context.getBuildAgentUrl();
+        }
+
+        return "";
+    }
+}
\ No newline at end of file
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/manager/DefaultBuildAgentPurgeManager.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/manager/DefaultBuildAgentPurgeManager.java
new file mode 100644
index 0000000..542f0b0
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/manager/DefaultBuildAgentPurgeManager.java
@@ -0,0 +1,183 @@
+package org.apache.continuum.buildagent.manager;
+
+/*
+ * 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 org.apache.commons.io.FileUtils;
+import org.apache.commons.io.comparator.LastModifiedFileComparator;
+import org.apache.commons.io.filefilter.AgeFileFilter;
+import org.apache.commons.io.filefilter.AndFileFilter;
+import org.apache.commons.io.filefilter.DirectoryFileFilter;
+import org.apache.commons.io.filefilter.IOFileFilter;
+import org.apache.commons.io.filefilter.NotFileFilter;
+import org.apache.commons.io.filefilter.WildcardFileFilter;
+import org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.util.Arrays;
+
+/**
+ * @plexus.component role="org.apache.continuum.buildagent.manager.BuildAgentPurgeManager" role-hint="default"
+ */
+public class DefaultBuildAgentPurgeManager
+    implements BuildAgentPurgeManager
+{
+    private static final Logger logger = LoggerFactory.getLogger( DefaultBuildAgentPurgeManager.class );
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildAgentConfigurationService buildAgentConfigurationService;
+
+    public void executeDirectoryPurge( String directoryType, int daysOlder, int retentionCount, boolean deleteAll )
+        throws Exception
+    {
+        StringBuilder log = new StringBuilder().append(
+            "Executing directory purge with the following settings[directoryType=" ).
+            append( directoryType ).append( ",daysOlder=" ).
+            append( daysOlder ).append( ", retentionCount=" ).
+            append( retentionCount ).append( ", deleteAll=" ).
+            append( deleteAll ).append( "]" );
+        logger.info( log.toString() );
+
+        File directory = null;
+
+        if ( "working".equals( directoryType ) || "releases".equals( directoryType ) )
+        {
+            directory = buildAgentConfigurationService.getWorkingDirectory();
+        }
+        else
+        {
+            logger.warn( "Cannot execute purge: DirectoryType: " + directoryType + " is not valid." );
+            return;
+        }
+        if ( deleteAll )
+        {
+            purgeAll( directory, directoryType );
+        }
+        else
+        {
+            purgeFiles( directory, directoryType, daysOlder, retentionCount );
+        }
+
+        logger.info( "Directory purge execution done" );
+    }
+
+    private void purgeAll( File directory, String directoryType )
+        throws Exception
+    {
+        AndFileFilter filter = new AndFileFilter();
+        filter.addFileFilter( DirectoryFileFilter.DIRECTORY );
+        filter.addFileFilter( createFileFilterForDirectoryType( directoryType ) );
+
+        File[] files = directory.listFiles( (FileFilter) filter );
+        if ( files == null )
+        {
+            return;
+        }
+        for ( File file : files )
+        {
+            try
+            {
+                FileUtils.deleteDirectory( file );
+            }
+            catch ( IOException e )
+            {
+                logger.warn( "Unable to purge " + directoryType + " directory: " + file.getName() );
+            }
+        }
+    }
+
+    private void purgeFiles( File directory, String directoryType, int daysOlder, int retentionCount )
+    {
+        AndFileFilter filter = new AndFileFilter();
+        filter.addFileFilter( DirectoryFileFilter.DIRECTORY );
+        filter.addFileFilter( createFileFilterForDirectoryType( directoryType ) );
+
+        File[] files = directory.listFiles( (FileFilter) filter );
+
+        if ( files == null )
+        {
+            return;
+        }
+
+        //calculate to include files not in the dayold category
+        int countToPurge = files.length - retentionCount;
+
+        if ( daysOlder > 0 )
+        {
+            long cutoff = System.currentTimeMillis() - ( 24 * 60 * 26 * 1000 * daysOlder );
+            filter.addFileFilter( new AgeFileFilter( cutoff ) );
+        }
+
+        files = directory.listFiles( (FileFilter) filter );
+
+        if ( files == null )
+        {
+            return;
+        }
+
+        Arrays.sort( files, LastModifiedFileComparator.LASTMODIFIED_COMPARATOR );
+
+        for ( File file : files )
+        {
+            if ( countToPurge - 1 < 0 )
+            {
+                break;
+            }
+            try
+            {
+                FileUtils.deleteDirectory( file );
+                countToPurge--;
+            }
+            catch ( IOException e )
+            {
+                logger.warn( "Unable to purge " + directoryType + " directory: " + file.getName() );
+            }
+        }
+
+    }
+
+    private IOFileFilter createFileFilterForDirectoryType( String directoryType )
+    {
+        WildcardFileFilter releasesFilter = new WildcardFileFilter( "releases-*" );
+
+        if ( "working".equals( directoryType ) )
+        {
+            return new NotFileFilter( releasesFilter );
+        }
+        else if ( "releases".equals( directoryType ) )
+        {
+            return releasesFilter;
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    public void setBuildAgentConfigurationService( BuildAgentConfigurationService buildAgentConfigurationService )
+    {
+        this.buildAgentConfigurationService = buildAgentConfigurationService;
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/manager/DefaultBuildAgentReleaseManager.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/manager/DefaultBuildAgentReleaseManager.java
new file mode 100644
index 0000000..50ceb89
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/manager/DefaultBuildAgentReleaseManager.java
@@ -0,0 +1,339 @@
+package org.apache.continuum.buildagent.manager;
+
+/*
+ * 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 org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
+import org.apache.continuum.buildagent.installation.BuildAgentInstallationService;
+import org.apache.continuum.buildagent.model.Installation;
+import org.apache.continuum.buildagent.utils.ContinuumBuildAgentUtil;
+import org.apache.continuum.model.repository.LocalRepository;
+import org.apache.continuum.release.config.ContinuumReleaseDescriptor;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.project.ProjectGroup;
+import org.apache.maven.continuum.release.ContinuumReleaseException;
+import org.apache.maven.continuum.release.ContinuumReleaseManager;
+import org.apache.maven.continuum.release.ContinuumReleaseManagerListener;
+import org.apache.maven.continuum.release.DefaultReleaseManagerListener;
+import org.apache.maven.shared.release.ReleaseResult;
+import org.apache.maven.shared.release.config.ReleaseDescriptor;
+import org.codehaus.plexus.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * @plexus.component role="org.apache.continuum.buildagent.manager.BuildAgentReleaseManager" role-hint="default"
+ */
+public class DefaultBuildAgentReleaseManager
+    implements BuildAgentReleaseManager
+{
+    private static final Logger log = LoggerFactory.getLogger( DefaultBuildAgentReleaseManager.class );
+
+    /**
+     * @plexus.requirement
+     */
+    ContinuumReleaseManager releaseManager;
+
+    /**
+     * @plexus.requirement
+     */
+    BuildAgentConfigurationService buildAgentConfigurationService;
+
+    /**
+     * @plexus.requirement
+     */
+    BuildAgentInstallationService buildAgentInstallationService;
+
+    public String releasePrepare( Map<String, Object> projectMap, Properties releaseProperties,
+                                  Map<String, String> releaseVersion, Map<String, String> developmentVersion,
+                                  Map<String, String> environments, String username )
+        throws ContinuumReleaseException
+    {
+        Project project = getProject( projectMap );
+
+        ContinuumReleaseManagerListener listener = new DefaultReleaseManagerListener();
+
+        listener.setUsername( username );
+
+        String workingDirectory = buildAgentConfigurationService.getWorkingDirectory( project.getId() ).getPath();
+
+        String executable = buildAgentInstallationService.getExecutorConfigurator(
+            BuildAgentInstallationService.MAVEN2_TYPE ).getExecutable();
+
+        if ( environments == null )
+        {
+            environments = new HashMap<String, String>();
+        }
+
+        // get environments from Slave (Build Agent)
+        List<Installation> installations = buildAgentConfigurationService.getAvailableInstallations();
+
+        if ( installations != null )
+        {
+            for ( Installation installation : installations )
+            {
+                // combine environments (Master and Slave); Slave's environments overwrite Master's environments
+                environments.put( installation.getVarName(), installation.getVarValue() );
+            }
+        }
+
+        if ( environments != null )
+        {
+            String m2Home = environments.get( buildAgentInstallationService.getEnvVar(
+                BuildAgentInstallationService.MAVEN2_TYPE ) );
+            if ( StringUtils.isNotEmpty( m2Home ) )
+            {
+                executable = m2Home + File.separator + "bin" + File.separator + executable;
+            }
+        }
+
+        try
+        {
+            return releaseManager.prepare( project, releaseProperties, releaseVersion, developmentVersion, listener,
+                                           workingDirectory, environments, executable );
+        }
+        catch ( ContinuumReleaseException e )
+        {
+            log.error( "Error while preparing release", e );
+            throw e;
+        }
+    }
+
+    public ReleaseResult getReleaseResult( String releaseId )
+    {
+        return (ReleaseResult) releaseManager.getReleaseResults().get( releaseId );
+    }
+
+    public Map<String, Object> getListener( String releaseId )
+    {
+        ContinuumReleaseManagerListener listener = (ContinuumReleaseManagerListener) releaseManager.getListeners().get(
+            releaseId );
+
+        Map<String, Object> map = new HashMap<String, Object>();
+
+        if ( listener != null )
+        {
+            map.put( ContinuumBuildAgentUtil.KEY_RELEASE_STATE, listener.getState() );
+
+            map.put( ContinuumBuildAgentUtil.KEY_USERNAME, listener.getUsername() );
+
+            if ( listener.getPhases() != null )
+            {
+                map.put( ContinuumBuildAgentUtil.KEY_RELEASE_PHASES, listener.getPhases() );
+            }
+            if ( listener.getCompletedPhases() != null )
+            {
+                map.put( ContinuumBuildAgentUtil.KEY_COMPLETED_RELEASE_PHASES, listener.getCompletedPhases() );
+            }
+            if ( listener.getInProgress() != null )
+            {
+                map.put( ContinuumBuildAgentUtil.KEY_RELEASE_IN_PROGRESS, listener.getInProgress() );
+            }
+            if ( listener.getError() != null )
+            {
+                map.put( ContinuumBuildAgentUtil.KEY_RELEASE_ERROR, listener.getError() );
+            }
+        }
+
+        return map;
+    }
+
+    public void removeListener( String releaseId )
+    {
+        releaseManager.getListeners().remove( releaseId );
+    }
+
+    public String getPreparedReleaseName( String releaseId )
+    {
+        Map preparedReleases = releaseManager.getPreparedReleases();
+
+        if ( preparedReleases.containsKey( releaseId ) )
+        {
+            ReleaseDescriptor descriptor = (ReleaseDescriptor) preparedReleases.get( releaseId );
+            return descriptor.getReleaseVersions().get( releaseId ).toString();
+        }
+
+        return "";
+    }
+
+    @SuppressWarnings( "unchecked" )
+    public void releasePerform( String releaseId, String goals, String arguments, boolean useReleaseProfile,
+                                Map repository, String username )
+        throws ContinuumReleaseException
+    {
+        ContinuumReleaseManagerListener listener = new DefaultReleaseManagerListener();
+
+        listener.setUsername( username );
+
+        LocalRepository repo = null;
+
+        if ( !repository.isEmpty() )
+        {
+            List<org.apache.continuum.buildagent.model.LocalRepository> localRepos =
+                buildAgentConfigurationService.getLocalRepositories();
+            for ( org.apache.continuum.buildagent.model.LocalRepository localRepo : localRepos )
+            {
+                if ( localRepo.getName().equalsIgnoreCase( ContinuumBuildAgentUtil.getLocalRepositoryName(
+                    repository ) ) )
+                {
+                    repo = new LocalRepository();
+                    repo.setLayout( localRepo.getLayout() );
+                    repo.setName( localRepo.getName() );
+                    repo.setLocation( localRepo.getLocation() );
+
+                    break;
+                }
+            }
+        }
+
+        File performDirectory = new File( buildAgentConfigurationService.getWorkingDirectory(),
+                                          "releases-" + System.currentTimeMillis() );
+        performDirectory.mkdirs();
+
+        releaseManager.perform( releaseId, performDirectory, goals, arguments, useReleaseProfile, listener, repo );
+    }
+
+    public String releasePerformFromScm( String goals, String arguments, boolean useReleaseProfile, Map repository,
+                                         String scmUrl, String scmUsername, String scmPassword, String scmTag,
+                                         String scmTagBase, Map<String, String> environments, String username )
+        throws ContinuumReleaseException
+    {
+        ContinuumReleaseDescriptor descriptor = new ContinuumReleaseDescriptor();
+        descriptor.setScmSourceUrl( scmUrl );
+        descriptor.setScmUsername( scmUsername );
+        descriptor.setScmPassword( scmPassword );
+        descriptor.setScmReleaseLabel( scmTag );
+        descriptor.setScmTagBase( scmTagBase );
+        descriptor.setEnvironments( environments );
+
+        String releaseId = "";
+
+        do
+        {
+            releaseId = String.valueOf( System.currentTimeMillis() );
+        }
+        while ( releaseManager.getPreparedReleases().containsKey( releaseId ) );
+
+        releaseManager.getPreparedReleases().put( releaseId, descriptor );
+
+        releasePerform( releaseId, goals, arguments, useReleaseProfile, repository, username );
+
+        return releaseId;
+    }
+
+    public String releaseCleanup( String releaseId )
+    {
+        releaseManager.getReleaseResults().remove( releaseId );
+
+        ContinuumReleaseManagerListener listener =
+            (ContinuumReleaseManagerListener) releaseManager.getListeners().remove( releaseId );
+
+        if ( listener != null )
+        {
+            return listener.getGoalName() + "Finished";
+        }
+        else
+        {
+            return "";
+        }
+    }
+
+    public void releaseRollback( String releaseId, int projectId )
+        throws ContinuumReleaseException
+    {
+        ContinuumReleaseManagerListener listener = new DefaultReleaseManagerListener();
+
+        releaseManager.rollback( releaseId, buildAgentConfigurationService.getWorkingDirectory( projectId ).getPath(),
+                                 listener );
+
+        //recurse until rollback is finished
+        while ( listener.getState() != ContinuumReleaseManagerListener.FINISHED )
+        {
+            try
+            {
+                Thread.sleep( 1000 );
+            }
+            catch ( InterruptedException e )
+            {
+                //do nothing
+            }
+        }
+
+        releaseManager.getPreparedReleases().remove( releaseId );
+
+        if ( StringUtils.isNotBlank( listener.getError() ) )
+        {
+            throw new ContinuumReleaseException( "Failed to rollback release: " + listener.getError() );
+        }
+    }
+
+    private Project getProject( Map<String, Object> context )
+    {
+        Project project = new Project();
+
+        project.setId( ContinuumBuildAgentUtil.getProjectId( context ) );
+        project.setGroupId( ContinuumBuildAgentUtil.getGroupId( context ) );
+        project.setArtifactId( ContinuumBuildAgentUtil.getArtifactId( context ) );
+        project.setScmUrl( ContinuumBuildAgentUtil.getScmUrl( context ) );
+
+        ProjectGroup group = new ProjectGroup();
+
+        String localRepo = ContinuumBuildAgentUtil.getLocalRepositoryName( context );
+
+        if ( StringUtils.isBlank( localRepo ) )
+        {
+            group.setLocalRepository( null );
+        }
+        else
+        {
+            LocalRepository localRepository = new LocalRepository();
+            List<org.apache.continuum.buildagent.model.LocalRepository> localRepos =
+                buildAgentConfigurationService.getLocalRepositories();
+            for ( org.apache.continuum.buildagent.model.LocalRepository localRepoBA : localRepos )
+            {
+                if ( localRepoBA.getName().equalsIgnoreCase( localRepo ) )
+                {
+                    localRepository.setLocation( localRepoBA.getLocation() );
+                    group.setLocalRepository( localRepository );
+                    break;
+                }
+            }
+        }
+
+        project.setProjectGroup( group );
+
+        return project;
+    }
+
+    public void setBuildAgentConfigurationService( BuildAgentConfigurationService buildAgentConfigurationService )
+    {
+        this.buildAgentConfigurationService = buildAgentConfigurationService;
+    }
+
+    public ContinuumReleaseManager getReleaseManager()
+    {
+        return releaseManager;
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/taskqueue/PrepareBuildProjectsTask.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/taskqueue/PrepareBuildProjectsTask.java
new file mode 100644
index 0000000..053e081
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/taskqueue/PrepareBuildProjectsTask.java
@@ -0,0 +1,86 @@
+package org.apache.continuum.buildagent.taskqueue;
+
+/*
+ * 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 org.apache.continuum.buildagent.buildcontext.BuildContext;
+import org.apache.continuum.utils.build.BuildTrigger;
+import org.codehaus.plexus.taskqueue.Task;
+
+import java.util.List;
+
+public class PrepareBuildProjectsTask
+    implements Task
+{
+    private final List<BuildContext> buildContexts;
+
+    private BuildTrigger buildTrigger;
+
+    private final int projectGroupId;
+
+    private final String scmRootAddress;
+
+    private final int scmRootId;
+
+    public PrepareBuildProjectsTask( List<BuildContext> buildContexts, BuildTrigger buildTrigger, int projectGroupId,
+                                     String scmRootAddress, int scmRootId )
+    {
+        this.buildContexts = buildContexts;
+        this.buildTrigger = buildTrigger;
+        this.projectGroupId = projectGroupId;
+        this.scmRootAddress = scmRootAddress;
+        this.scmRootId = scmRootId;
+    }
+
+    public long getMaxExecutionTime()
+    {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    public List<BuildContext> getBuildContexts()
+    {
+        return buildContexts;
+    }
+
+    public BuildTrigger getBuildTrigger()
+    {
+        return buildTrigger;
+    }
+
+    public int getProjectGroupId()
+    {
+        return projectGroupId;
+    }
+
+    public String getScmRootAddress()
+    {
+        return scmRootAddress;
+    }
+
+    public int getScmRootId()
+    {
+        return scmRootId;
+    }
+
+    public int getHashCode()
+    {
+        return projectGroupId + scmRootId + buildTrigger.getTrigger();
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/taskqueue/execution/BuildProjectTaskExecutor.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/taskqueue/execution/BuildProjectTaskExecutor.java
new file mode 100644
index 0000000..6731e91
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/taskqueue/execution/BuildProjectTaskExecutor.java
@@ -0,0 +1,618 @@
+package org.apache.continuum.buildagent.taskqueue.execution;
+
+/*
+ * 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 org.apache.commons.lang.StringEscapeUtils;
+import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutor;
+import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutorException;
+import org.apache.continuum.buildagent.build.execution.manager.BuildAgentBuildExecutorManager;
+import org.apache.continuum.buildagent.buildcontext.BuildContext;
+import org.apache.continuum.buildagent.buildcontext.manager.BuildContextManager;
+import org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
+import org.apache.continuum.buildagent.installation.BuildAgentInstallationService;
+import org.apache.continuum.buildagent.manager.BuildAgentManager;
+import org.apache.continuum.buildagent.model.Installation;
+import org.apache.continuum.buildagent.model.LocalRepository;
+import org.apache.continuum.buildagent.utils.BuildContextToBuildDefinition;
+import org.apache.continuum.buildagent.utils.BuildContextToProject;
+import org.apache.continuum.buildagent.utils.ContinuumBuildAgentUtil;
+import org.apache.continuum.taskqueue.BuildProjectTask;
+import org.apache.maven.continuum.ContinuumException;
+import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
+import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.BuildResult;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.project.ProjectGroup;
+import org.apache.maven.continuum.model.scm.ChangeFile;
+import org.apache.maven.continuum.model.scm.ChangeSet;
+import org.apache.maven.continuum.model.scm.ScmResult;
+import org.apache.maven.continuum.project.ContinuumProjectState;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.scm.ScmException;
+import org.apache.maven.scm.repository.ScmRepositoryException;
+import org.codehaus.plexus.action.ActionManager;
+import org.codehaus.plexus.action.ActionNotFoundException;
+import org.codehaus.plexus.taskqueue.Task;
+import org.codehaus.plexus.taskqueue.execution.TaskExecutionException;
+import org.codehaus.plexus.taskqueue.execution.TaskExecutor;
+import org.codehaus.plexus.util.FileUtils;
+import org.codehaus.plexus.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @plexus.component role="org.codehaus.plexus.taskqueue.execution.TaskExecutor"
+ * role-hint="build-agent"
+ */
+public class BuildProjectTaskExecutor
+    implements TaskExecutor
+{
+    private static final Logger log = LoggerFactory.getLogger( BuildProjectTaskExecutor.class );
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildContextManager buildContextManager;
+
+    /**
+     * @plexus.requirement
+     */
+    private ActionManager actionManager;
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildAgentConfigurationService buildAgentConfigurationService;
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildAgentManager buildAgentManager;
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildAgentBuildExecutorManager buildAgentBuildExecutorManager;
+
+    public void executeTask( Task task )
+        throws TaskExecutionException
+    {
+        BuildProjectTask buildProjectTask = (BuildProjectTask) task;
+
+        int projectId = buildProjectTask.getProjectId();
+
+        try
+        {
+            log.info( "Initializing build (projectId={})", projectId );
+            BuildContext context = buildContextManager.getBuildContext( projectId );
+            initializeBuildContext( context );
+
+            if ( !checkScmResult( context ) )
+            {
+                return;
+            }
+
+            log.info( "Checking if project '{}' should build", context.getProjectName() );
+            if ( !shouldBuild( context ) )
+            {
+                return;
+            }
+
+            log.info( "Starting build of {}", context.getProjectName() );
+            startBuild( context );
+
+            try
+            {
+                try
+                {
+                    performAction( "update-project-from-agent-working-directory", context );
+                }
+                catch ( TaskExecutionException e )
+                {
+                    updateBuildResult( context, ContinuumBuildAgentUtil.throwableToString( e ) );
+
+                    //just log the error but don't stop the build from progressing in order not to suppress any build result messages there
+                    log.error( "Error executing action update-project-from-agent-working-directory '", e );
+                }
+
+                performAction( "execute-agent-builder", context );
+
+                log.info( "Updating build result of project '{}'", context.getProjectName() );
+                updateBuildResult( context, null );
+            }
+            finally
+            {
+                log.info( "End build of project '{}'", context.getProjectName() );
+                endBuild( context );
+            }
+        }
+        catch ( TaskExecutionException e )
+        {
+            log.error( "Error while trying to build the project {}: {}", projectId, e.getMessage() );
+        }
+    }
+
+    private void initializeBuildContext( BuildContext buildContext )
+        throws TaskExecutionException
+    {
+        Map<String, Object> actionContext = new HashMap<String, Object>();
+
+        actionContext.put( ContinuumBuildAgentUtil.KEY_PROJECT_ID, buildContext.getProjectId() );
+
+        Project project = BuildContextToProject.getProject( buildContext );
+        ProjectGroup projectGroup = new ProjectGroup();
+        projectGroup.setId( buildContext.getProjectGroupId() );
+        projectGroup.setName( buildContext.getProjectGroupName() );
+        project.setProjectGroup( projectGroup );
+
+        actionContext.put( ContinuumBuildAgentUtil.KEY_PROJECT, project );
+        actionContext.put( ContinuumBuildAgentUtil.KEY_BUILD_DEFINITION,
+                           BuildContextToBuildDefinition.getBuildDefinition( buildContext ) );
+        actionContext.put( ContinuumBuildAgentUtil.KEY_BUILD_DEFINITION_ID, buildContext.getBuildDefinitionId() );
+        actionContext.put( ContinuumBuildAgentUtil.KEY_TRIGGER, buildContext.getTrigger() );
+        actionContext.put( ContinuumBuildAgentUtil.KEY_USERNAME, buildContext.getUsername() );
+        actionContext.put( ContinuumBuildAgentUtil.KEY_ENVIRONMENTS, getEnvironments(
+            buildContext.getBuildDefinitionId(), getInstallationType( buildContext ) ) );
+
+        // CONTINUUM-2391
+        if ( buildContext.getLocalRepository() != null )
+        {
+            List<LocalRepository> localRepos = buildAgentConfigurationService.getLocalRepositories();
+            for ( LocalRepository local : localRepos )
+            {
+                if ( local.getName().equalsIgnoreCase( buildContext.getLocalRepository() ) )
+                {
+                    actionContext.put( ContinuumBuildAgentUtil.KEY_LOCAL_REPOSITORY, local.getLocation() );
+                    break;
+                }
+            }
+        }
+
+        actionContext.put( ContinuumBuildAgentUtil.KEY_SCM_RESULT, buildContext.getScmResult() );
+        buildContext.setActionContext( actionContext );
+
+        buildContext.setBuildStartTime( System.currentTimeMillis() );
+    }
+
+    private boolean checkScmResult( BuildContext buildContext )
+    {
+        if ( buildContext.getScmResult() == null )
+        {
+            log.info( "Error updating from SCM, SCM result is null, not building" );
+            return false;
+        }
+        else if ( !buildContext.getScmResult().isSuccess() )
+        {
+            log.info( "Error updating from SCM, SCM result has errors, not building" );
+            return false;
+        }
+        return true;
+    }
+
+    private void startBuild( BuildContext buildContext )
+        throws TaskExecutionException
+    {
+        try
+        {
+            buildAgentManager.startProjectBuild( buildContext.getProjectId() );
+        }
+        catch ( ContinuumException e )
+        {
+            // do not throw exception, just log?
+            log.error( "Failed to start project '" + buildContext.getProjectName() + "'", e );
+            throw new TaskExecutionException( "Failed to start project '" + buildContext.getProjectName() + "'", e );
+        }
+    }
+
+    private void endBuild( BuildContext buildContext )
+        throws TaskExecutionException
+    {
+        // return build result to master
+        BuildResult buildResult = buildContext.getBuildResult();
+
+        Map<String, Object> result = new HashMap<String, Object>();
+        result.put( ContinuumBuildAgentUtil.KEY_PROJECT_ID, buildContext.getProjectId() );
+        result.put( ContinuumBuildAgentUtil.KEY_BUILD_DEFINITION_ID, buildContext.getBuildDefinitionId() );
+        result.put( ContinuumBuildAgentUtil.KEY_TRIGGER, buildContext.getTrigger() );
+        result.put( ContinuumBuildAgentUtil.KEY_USERNAME, buildContext.getUsername() );
+        result.put( ContinuumBuildAgentUtil.KEY_BUILD_STATE, buildResult.getState() );
+        result.put( ContinuumBuildAgentUtil.KEY_START_TIME, Long.toString( buildResult.getStartTime() ) );
+        result.put( ContinuumBuildAgentUtil.KEY_END_TIME, Long.toString( buildResult.getEndTime() ) );
+        result.put( ContinuumBuildAgentUtil.KEY_BUILD_EXIT_CODE, buildResult.getExitCode() );
+        if ( buildContext.getLatestUpdateDate() != null )
+        {
+            result.put( ContinuumBuildAgentUtil.KEY_LATEST_UPDATE_DATE, buildContext.getLatestUpdateDate() );
+        }
+
+        String buildOutput = getBuildOutputText( buildContext.getProjectId() );
+        if ( buildOutput == null )
+        {
+            result.put( ContinuumBuildAgentUtil.KEY_BUILD_OUTPUT, "" );
+        }
+        else
+        {
+            result.put( ContinuumBuildAgentUtil.KEY_BUILD_OUTPUT, buildOutput );
+        }
+
+        if ( buildResult.getError() != null )
+        {
+            result.put( ContinuumBuildAgentUtil.KEY_BUILD_ERROR, buildResult.getError() );
+        }
+        else
+        {
+            result.put( ContinuumBuildAgentUtil.KEY_BUILD_ERROR, "" );
+        }
+
+        result.put( ContinuumBuildAgentUtil.KEY_SCM_RESULT, ContinuumBuildAgentUtil.createScmResult( buildContext ) );
+        result.put( ContinuumBuildAgentUtil.KEY_BUILD_AGENT_URL, buildContext.getBuildAgentUrl() );
+
+        try
+        {
+            buildAgentManager.returnBuildResult( result );
+            buildContextManager.removeBuildContext( buildContext.getProjectId() );
+        }
+        catch ( ContinuumException e )
+        {
+            log.error( "Failed to return build result for project '" + buildContext.getProjectName() + "'", e );
+            throw new TaskExecutionException(
+                "Failed to return build result for project '" + buildContext.getProjectName() + "'", e );
+        }
+    }
+
+    private void performAction( String actionName, BuildContext context )
+        throws TaskExecutionException
+    {
+        String error;
+        TaskExecutionException exception;
+
+        try
+        {
+            log.info( "Performing action " + actionName );
+            actionManager.lookup( actionName ).execute( context.getActionContext() );
+            return;
+        }
+        catch ( ActionNotFoundException e )
+        {
+            error = ContinuumBuildAgentUtil.throwableToString( e );
+            exception = new TaskExecutionException( "Error looking up action '" + actionName + "'", e );
+        }
+        catch ( ScmRepositoryException e )
+        {
+            error = getValidationMessages( e ) + "\n" + ContinuumBuildAgentUtil.throwableToString( e );
+
+            exception = new TaskExecutionException( "SCM error while executing '" + actionName + "'", e );
+        }
+        catch ( ScmException e )
+        {
+            error = ContinuumBuildAgentUtil.throwableToString( e );
+
+            exception = new TaskExecutionException( "SCM error while executing '" + actionName + "'", e );
+        }
+        catch ( Exception e )
+        {
+            exception = new TaskExecutionException( "Error executing action '" + actionName + "'", e );
+            error = ContinuumBuildAgentUtil.throwableToString( exception );
+        }
+
+        updateBuildResult( context, error );
+
+        throw exception;
+    }
+
+    private void updateBuildResult( BuildContext context, String error )
+    {
+        context.setBuildResult( ContinuumBuildAgentUtil.getBuildResult( context.getActionContext(), null ) );
+
+        if ( context.getBuildResult() == null )
+        {
+            BuildResult build = new BuildResult();
+
+            build.setState( ContinuumProjectState.ERROR );
+
+            build.setTrigger( context.getTrigger() );
+
+            build.setUsername( context.getUsername() );
+
+            build.setStartTime( context.getBuildStartTime() );
+
+            build.setEndTime( System.currentTimeMillis() );
+
+            build.setBuildDefinition( BuildContextToBuildDefinition.getBuildDefinition( context ) );
+
+            build.setScmResult( context.getScmResult() );
+
+            if ( error != null )
+            {
+                build.setError( error );
+            }
+
+            context.setBuildResult( build );
+        }
+    }
+
+    private String getValidationMessages( ScmRepositoryException ex )
+    {
+        List<String> messages = ex.getValidationMessages();
+
+        StringBuffer message = new StringBuffer();
+
+        if ( messages != null && !messages.isEmpty() )
+        {
+            for ( Iterator<String> i = messages.iterator(); i.hasNext(); )
+            {
+                message.append( i.next() );
+
+                if ( i.hasNext() )
+                {
+                    message.append( System.getProperty( "line.separator" ) );
+                }
+            }
+        }
+        return message.toString();
+    }
+
+    private String getBuildOutputText( int projectId )
+    {
+        try
+        {
+            File buildOutputFile = buildAgentConfigurationService.getBuildOutputFile( projectId );
+
+            if ( buildOutputFile.exists() )
+            {
+                return StringEscapeUtils.escapeHtml( FileUtils.fileRead( buildOutputFile ) );
+            }
+        }
+        catch ( Exception e )
+        {
+            // do not throw exception, just log it
+            log.error( "Error retrieving build output file", e );
+        }
+
+        return null;
+    }
+
+    private Map<String, String> getEnvironments( int buildDefinitionId, String installationType )
+        throws TaskExecutionException
+    {
+        try
+        {
+            // get environments from Master (Continuum)
+            Map<String, String> environments = buildAgentManager.getEnvironments( buildDefinitionId, installationType );
+
+            List<Installation> installations = buildAgentConfigurationService.getAvailableInstallations();
+
+            if ( installations != null )
+            {
+                // get environments from Slave (Build Agent)
+                for ( Installation installation : installations )
+                {
+                    // combine environments (Master and Slave); Slave's environments overwrite Master's environments
+                    environments.put( installation.getVarName(), installation.getVarValue() );
+                }
+            }
+
+            return environments;
+        }
+        catch ( ContinuumException e )
+        {
+            log.error( "Error while retrieving environments of build definition: " + buildDefinitionId, e );
+            throw new TaskExecutionException(
+                "Error while retrieving environments of build definition: " + buildDefinitionId, e );
+        }
+    }
+
+    private String getInstallationType( BuildContext buildContext )
+    {
+        String executorId = buildContext.getExecutorId();
+
+        if ( ContinuumBuildExecutorConstants.MAVEN_TWO_BUILD_EXECUTOR.equals( executorId ) )
+        {
+            return BuildAgentInstallationService.MAVEN2_TYPE;
+        }
+        else if ( ContinuumBuildExecutorConstants.MAVEN_ONE_BUILD_EXECUTOR.equals( executorId ) )
+        {
+            return BuildAgentInstallationService.MAVEN1_TYPE;
+        }
+        else if ( ContinuumBuildExecutorConstants.ANT_BUILD_EXECUTOR.equals( executorId ) )
+        {
+            return BuildAgentInstallationService.ANT_TYPE;
+        }
+
+        return "";
+    }
+
+    private boolean shouldBuild( BuildContext context )
+        throws TaskExecutionException
+    {
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put( ContinuumBuildAgentUtil.KEY_PROJECT_ID, context.getProjectId() );
+        map.put( ContinuumBuildAgentUtil.KEY_BUILD_DEFINITION_ID, context.getBuildDefinitionId() );
+        map.put( ContinuumBuildAgentUtil.KEY_TRIGGER, context.getTrigger() );
+        map.put( ContinuumBuildAgentUtil.KEY_USERNAME, context.getUsername() );
+        map.put( ContinuumBuildAgentUtil.KEY_SCM_CHANGES, getScmChanges( context.getScmResult() ) );
+        map.put( ContinuumBuildAgentUtil.KEY_BUILD_AGENT_URL, context.getBuildAgentUrl() );
+
+        if ( context.getExecutorId().equals( ContinuumBuildExecutorConstants.MAVEN_TWO_BUILD_EXECUTOR ) )
+        {
+            map.put( ContinuumBuildAgentUtil.KEY_MAVEN_PROJECT, getMavenProject( context ) );
+        }
+
+        if ( context.getLatestUpdateDate() != null )
+        {
+            map.put( ContinuumBuildAgentUtil.KEY_LATEST_UPDATE_DATE, context.getLatestUpdateDate() );
+        }
+
+        try
+        {
+            return buildAgentManager.shouldBuild( map );
+        }
+        catch ( ContinuumException e )
+        {
+            log.error( "Failed to determine if project should build", e );
+            throw new TaskExecutionException( "Failed to determine if project should build", e );
+        }
+    }
+
+    private List<Map<String, Object>> getScmChanges( ScmResult scmResult )
+    {
+        List<Map<String, Object>> scmChanges = new ArrayList<Map<String, Object>>();
+
+        if ( scmResult != null && scmResult.getChanges() != null )
+        {
+            for ( Object obj : scmResult.getChanges() )
+            {
+                ChangeSet changeSet = (ChangeSet) obj;
+
+                Map<String, Object> map = new HashMap<String, Object>();
+                if ( StringUtils.isNotEmpty( changeSet.getAuthor() ) )
+                {
+                    map.put( ContinuumBuildAgentUtil.KEY_CHANGESET_AUTHOR, changeSet.getAuthor() );
+                }
+                else
+                {
+                    map.put( ContinuumBuildAgentUtil.KEY_CHANGESET_AUTHOR, "" );
+                }
+                if ( StringUtils.isNotEmpty( changeSet.getComment() ) )
+                {
+                    map.put( ContinuumBuildAgentUtil.KEY_CHANGESET_COMMENT, changeSet.getComment() );
+                }
+                else
+                {
+                    map.put( ContinuumBuildAgentUtil.KEY_CHANGESET_COMMENT, "" );
+                }
+                if ( changeSet.getDateAsDate() != null )
+                {
+                    map.put( ContinuumBuildAgentUtil.KEY_CHANGESET_DATE, changeSet.getDateAsDate() );
+                }
+                map.put( ContinuumBuildAgentUtil.KEY_CHANGESET_FILES, getScmChangeFiles( changeSet.getFiles() ) );
+                scmChanges.add( map );
+            }
+        }
+
+        return scmChanges;
+    }
+
+    private List<Map<String, String>> getScmChangeFiles( List<ChangeFile> files )
+    {
+        List<Map<String, String>> scmChangeFiles = new ArrayList<Map<String, String>>();
+
+        if ( files != null )
+        {
+            for ( ChangeFile changeFile : files )
+            {
+                Map<String, String> map = new HashMap<String, String>();
+
+                if ( StringUtils.isNotEmpty( changeFile.getName() ) )
+                {
+                    map.put( ContinuumBuildAgentUtil.KEY_CHANGEFILE_NAME, changeFile.getName() );
+                }
+                else
+                {
+                    map.put( ContinuumBuildAgentUtil.KEY_CHANGEFILE_NAME, "" );
+                }
+                if ( StringUtils.isNotEmpty( changeFile.getRevision() ) )
+                {
+                    map.put( ContinuumBuildAgentUtil.KEY_CHANGEFILE_REVISION, changeFile.getRevision() );
+                }
+                else
+                {
+                    map.put( ContinuumBuildAgentUtil.KEY_CHANGEFILE_REVISION, "" );
+                }
+                if ( StringUtils.isNotEmpty( changeFile.getStatus() ) )
+                {
+                    map.put( ContinuumBuildAgentUtil.KEY_CHANGEFILE_STATUS, changeFile.getStatus() );
+                }
+                else
+                {
+                    map.put( ContinuumBuildAgentUtil.KEY_CHANGEFILE_STATUS, "" );
+                }
+                scmChangeFiles.add( map );
+            }
+        }
+        return scmChangeFiles;
+    }
+
+    private Map getMavenProject( BuildContext context )
+        throws TaskExecutionException
+    {
+        Map<String, Object> mavenProject = new HashMap<String, Object>();
+
+        try
+        {
+            ContinuumAgentBuildExecutor buildExecutor = buildAgentBuildExecutorManager.getBuildExecutor(
+                context.getExecutorId() );
+
+            BuildDefinition buildDefinition = BuildContextToBuildDefinition.getBuildDefinition( context );
+
+            File workingDirectory = buildAgentConfigurationService.getWorkingDirectory( context.getProjectId() );
+
+            MavenProject project = buildExecutor.getMavenProject( workingDirectory, buildDefinition );
+
+            mavenProject.put( ContinuumBuildAgentUtil.KEY_PROJECT_VERSION, project.getVersion() );
+
+            if ( project.getModules() != null )
+            {
+                mavenProject.put( ContinuumBuildAgentUtil.KEY_PROJECT_MODULES, project.getModules() );
+            }
+        }
+        catch ( ContinuumAgentBuildExecutorException e )
+        {
+            log.error( "Error getting maven project", e );
+        }
+        catch ( ContinuumException e )
+        {
+            log.error( "Error getting build executor", e );
+        }
+
+        return mavenProject;
+    }
+
+    public void setBuildContextManager( BuildContextManager buildContextManager )
+    {
+        this.buildContextManager = buildContextManager;
+    }
+
+    public void setActionManager( ActionManager actionManager )
+    {
+        this.actionManager = actionManager;
+    }
+
+    public void setBuildAgentConfigurationService( BuildAgentConfigurationService buildAgentConfigurationService )
+    {
+        this.buildAgentConfigurationService = buildAgentConfigurationService;
+    }
+
+    public void setBuildAgentManager( BuildAgentManager buildAgentManager )
+    {
+        this.buildAgentManager = buildAgentManager;
+    }
+
+    public void setBuildAgentBuildExecutorManager( BuildAgentBuildExecutorManager buildAgentBuildExecutorManager )
+    {
+        this.buildAgentBuildExecutorManager = buildAgentBuildExecutorManager;
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/taskqueue/execution/PrepareBuildProjectsTaskExecutor.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/taskqueue/execution/PrepareBuildProjectsTaskExecutor.java
new file mode 100644
index 0000000..186f9c6
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/taskqueue/execution/PrepareBuildProjectsTaskExecutor.java
@@ -0,0 +1,437 @@
+package org.apache.continuum.buildagent.taskqueue.execution;
+
+/*
+ * 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 org.apache.continuum.buildagent.buildcontext.BuildContext;
+import org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
+import org.apache.continuum.buildagent.manager.BuildAgentManager;
+import org.apache.continuum.buildagent.taskqueue.PrepareBuildProjectsTask;
+import org.apache.continuum.buildagent.utils.BuildContextToBuildDefinition;
+import org.apache.continuum.buildagent.utils.BuildContextToProject;
+import org.apache.continuum.buildagent.utils.ContinuumBuildAgentUtil;
+import org.apache.maven.continuum.ContinuumException;
+import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.scm.ChangeSet;
+import org.apache.maven.continuum.model.scm.ScmResult;
+import org.apache.maven.continuum.project.ContinuumProjectState;
+import org.codehaus.plexus.action.ActionManager;
+import org.codehaus.plexus.action.ActionNotFoundException;
+import org.codehaus.plexus.taskqueue.Task;
+import org.codehaus.plexus.taskqueue.execution.TaskExecutionException;
+import org.codehaus.plexus.taskqueue.execution.TaskExecutor;
+import org.codehaus.plexus.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @plexus.component role="org.codehaus.plexus.taskqueue.execution.TaskExecutor"
+ * role-hint="prepare-build-agent"
+ */
+public class PrepareBuildProjectsTaskExecutor
+    implements TaskExecutor
+{
+    private static final Logger log = LoggerFactory.getLogger( PrepareBuildProjectsTaskExecutor.class );
+
+    /**
+     * @plexus.requirement
+     */
+    private ActionManager actionManager;
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildAgentConfigurationService buildAgentConfigurationService;
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildAgentManager buildAgentManager;
+
+    public void executeTask( Task task )
+        throws TaskExecutionException
+    {
+        List<BuildContext> buildContexts = ( (PrepareBuildProjectsTask) task ).getBuildContexts();
+
+        Map<String, Object> context = null;
+
+        try
+        {
+            if ( buildContexts != null && buildContexts.size() > 0 )
+            {
+                try
+                {
+                    for ( BuildContext buildContext : buildContexts )
+                    {
+                        BuildDefinition buildDef = BuildContextToBuildDefinition.getBuildDefinition( buildContext );
+
+                        log.debug( "Check scm root state of project group '{}'", buildContext.getProjectGroupName() );
+                        if ( !checkProjectScmRoot( context ) )
+                        {
+                            break;
+                        }
+
+                        log.info( "Starting prepare build of project group '{}'", buildContext.getProjectGroupName() );
+                        startPrepareBuild( buildContext );
+
+                        log.info( "Initializing prepare build" );
+                        initializeActionContext( buildContext );
+
+                        try
+                        {
+                            if ( buildDef.isBuildFresh() )
+                            {
+                                log.info( "Clean up working directory of project '{}'", buildContext.getProjectName() );
+                                cleanWorkingDirectory( buildContext );
+                            }
+
+                            log.info( "Updating working directory of project '{}'", buildContext.getProjectName() );
+                            updateWorkingDirectory( buildContext );
+
+                            //CONTINUUM-1393
+                            if ( !buildDef.isBuildFresh() )
+                            {
+                                log.info( "Merging SCM results of project '{}'", buildContext.getProjectName() );
+                                mergeScmResults( buildContext );
+                            }
+                        }
+                        finally
+                        {
+                            endProjectPrepareBuild( buildContext );
+                            context = buildContext.getActionContext();
+                        }
+                    }
+                }
+                finally
+                {
+                    endPrepareBuild( context );
+                }
+
+                if ( checkProjectScmRoot( context ) )
+                {
+                    log.debug( "Successful prepare build. Creating build task" );
+                    buildProjects( buildContexts );
+                }
+            }
+            else
+            {
+                throw new TaskExecutionException( "No project build context" );
+            }
+        }
+        catch ( TaskExecutionException e )
+        {
+            log.error( "Error while preparing build of project: {}", e.getMessage() );
+        }
+    }
+
+    private void startPrepareBuild( BuildContext buildContext )
+        throws TaskExecutionException
+    {
+        Map<String, Object> actionContext = buildContext.getActionContext();
+
+        if ( actionContext == null || !( ContinuumBuildAgentUtil.getScmRootState( actionContext ) ==
+            ContinuumProjectState.UPDATING ) )
+        {
+            Map<String, Object> map = new HashMap<String, Object>();
+            map.put( ContinuumBuildAgentUtil.KEY_PROJECT_GROUP_ID, buildContext.getProjectGroupId() );
+            map.put( ContinuumBuildAgentUtil.KEY_SCM_ROOT_ADDRESS, buildContext.getScmRootAddress() );
+            map.put( ContinuumBuildAgentUtil.KEY_BUILD_AGENT_URL, buildContext.getBuildAgentUrl() );
+
+            try
+            {
+                buildAgentManager.startPrepareBuild( map );
+            }
+            catch ( ContinuumException e )
+            {
+                throw new TaskExecutionException( e.getMessage(), e );
+            }
+        }
+    }
+
+    private void initializeActionContext( BuildContext buildContext )
+    {
+        Map<String, Object> actionContext = new HashMap<String, Object>();
+
+        actionContext.put( ContinuumBuildAgentUtil.KEY_PROJECT_ID, buildContext.getProjectId() );
+        actionContext.put( ContinuumBuildAgentUtil.KEY_PROJECT, BuildContextToProject.getProject( buildContext ) );
+        actionContext.put( ContinuumBuildAgentUtil.KEY_BUILD_DEFINITION,
+                           BuildContextToBuildDefinition.getBuildDefinition( buildContext ) );
+        actionContext.put( ContinuumBuildAgentUtil.KEY_SCM_ROOT_STATE, ContinuumProjectState.UPDATING );
+        actionContext.put( ContinuumBuildAgentUtil.KEY_PROJECT_GROUP_ID, buildContext.getProjectGroupId() );
+        actionContext.put( ContinuumBuildAgentUtil.KEY_SCM_ROOT_ADDRESS, buildContext.getScmRootAddress() );
+        actionContext.put( ContinuumBuildAgentUtil.KEY_OLD_SCM_RESULT, buildContext.getOldScmResult() );
+        actionContext.put( ContinuumBuildAgentUtil.KEY_LATEST_UPDATE_DATE, buildContext.getLatestUpdateDate() );
+        actionContext.put( ContinuumBuildAgentUtil.KEY_TRIGGER, buildContext.getTrigger() );
+        actionContext.put( ContinuumBuildAgentUtil.KEY_USERNAME, buildContext.getUsername() );
+        actionContext.put( ContinuumBuildAgentUtil.KEY_SCM_USERNAME, buildContext.getScmUsername() );
+        actionContext.put( ContinuumBuildAgentUtil.KEY_SCM_PASSWORD, buildContext.getScmPassword() );
+        actionContext.put( ContinuumBuildAgentUtil.KEY_BUILD_AGENT_URL, buildContext.getBuildAgentUrl() );
+
+        buildContext.setActionContext( actionContext );
+    }
+
+    private boolean checkProjectScmRoot( Map<String, Object> context )
+    {
+        return !( context != null && ContinuumBuildAgentUtil.getScmRootState( context ) ==
+            ContinuumProjectState.ERROR );
+
+    }
+
+    private void cleanWorkingDirectory( BuildContext buildContext )
+        throws TaskExecutionException
+    {
+        performAction( "clean-agent-working-directory", buildContext );
+    }
+
+    private void updateWorkingDirectory( BuildContext buildContext )
+        throws TaskExecutionException
+    {
+        Map<String, Object> actionContext = buildContext.getActionContext();
+
+        performAction( "check-agent-working-directory", buildContext );
+
+        boolean workingDirectoryExists = ContinuumBuildAgentUtil.getBoolean( actionContext,
+                                                                             ContinuumBuildAgentUtil.KEY_WORKING_DIRECTORY_EXISTS );
+
+        ScmResult scmResult;
+
+        Date date;
+
+        if ( workingDirectoryExists )
+        {
+            performAction( "update-agent-working-directory", buildContext );
+
+            scmResult = ContinuumBuildAgentUtil.getUpdateScmResult( actionContext, null );
+
+            date = ContinuumBuildAgentUtil.getLatestUpdateDate( actionContext );
+        }
+        else
+        {
+            Project project = ContinuumBuildAgentUtil.getProject( actionContext );
+
+            actionContext.put( ContinuumBuildAgentUtil.KEY_WORKING_DIRECTORY,
+                               buildAgentConfigurationService.getWorkingDirectory(
+                                   project.getId() ).getAbsolutePath() );
+
+            performAction( "checkout-agent-project", buildContext );
+
+            scmResult = ContinuumBuildAgentUtil.getCheckoutScmResult( actionContext, null );
+
+            performAction( "changelog-agent-project", buildContext );
+
+            date = ContinuumBuildAgentUtil.getLatestUpdateDate( actionContext );
+        }
+
+        buildContext.setScmResult( scmResult );
+        buildContext.setLatestUpdateDate( date );
+        actionContext.put( ContinuumBuildAgentUtil.KEY_SCM_RESULT, scmResult );
+    }
+
+    private void endProjectPrepareBuild( BuildContext buildContext )
+        throws TaskExecutionException
+    {
+        Map<String, Object> context = buildContext.getActionContext();
+
+        ScmResult scmResult = ContinuumBuildAgentUtil.getScmResult( context, null );
+
+        log.debug( "End prepare build of project '{}'", buildContext.getProjectName() );
+
+        if ( scmResult == null || !scmResult.isSuccess() )
+        {
+            context.put( ContinuumBuildAgentUtil.KEY_SCM_ROOT_STATE, ContinuumProjectState.ERROR );
+        }
+        else
+        {
+            buildContext.setScmResult( scmResult );
+        }
+    }
+
+    private void endPrepareBuild( Map<String, Object> context )
+        throws TaskExecutionException
+    {
+        if ( context != null )
+        {
+            Map<String, Object> result = new HashMap<String, Object>();
+            result.put( ContinuumBuildAgentUtil.KEY_PROJECT_GROUP_ID, ContinuumBuildAgentUtil.getProjectGroupId(
+                context ) );
+            result.put( ContinuumBuildAgentUtil.KEY_SCM_ROOT_ADDRESS, ContinuumBuildAgentUtil.getScmRootAddress(
+                context ) );
+            result.put( ContinuumBuildAgentUtil.KEY_SCM_ROOT_STATE, ContinuumBuildAgentUtil.getScmRootState(
+                context ) );
+            result.put( ContinuumBuildAgentUtil.KEY_BUILD_AGENT_URL, ContinuumBuildAgentUtil.getBuildAgentUrl(
+                context ) );
+
+            if ( ContinuumBuildAgentUtil.getScmRootState( context ) == ContinuumProjectState.ERROR )
+            {
+                String error = convertScmResultToError( ContinuumBuildAgentUtil.getScmResult( context, null ) );
+
+                if ( StringUtils.isEmpty( error ) )
+                {
+                    result.put( ContinuumBuildAgentUtil.KEY_SCM_ERROR, "" );
+                }
+                else
+                {
+                    result.put( ContinuumBuildAgentUtil.KEY_SCM_ERROR, error );
+                }
+            }
+            else
+            {
+                result.put( ContinuumBuildAgentUtil.KEY_SCM_ERROR, "" );
+            }
+
+            try
+            {
+                log.debug( "End prepare build of project group '{}'", ContinuumBuildAgentUtil.getProjectGroupId(
+                    context ) );
+                buildAgentManager.endPrepareBuild( result );
+            }
+            catch ( ContinuumException e )
+            {
+                throw new TaskExecutionException( e.getMessage(), e );
+            }
+        }
+        else
+        {
+            throw new TaskExecutionException( "No project build context" );
+        }
+    }
+
+    private String convertScmResultToError( ScmResult result )
+    {
+        String error = "";
+
+        if ( result == null )
+        {
+            error = "Scm result is null.";
+        }
+        else
+        {
+            if ( result.getCommandLine() != null )
+            {
+                error = "Command line: " + StringUtils.clean( result.getCommandLine() ) +
+                    System.getProperty( "line.separator" );
+            }
+
+            if ( result.getProviderMessage() != null )
+            {
+                error = "Provider message: " + StringUtils.clean( result.getProviderMessage() ) +
+                    System.getProperty( "line.separator" );
+            }
+
+            if ( result.getCommandOutput() != null )
+            {
+                error += "Command output: " + System.getProperty( "line.separator" );
+                error += "-------------------------------------------------------------------------------" +
+                    System.getProperty( "line.separator" );
+                error += StringUtils.clean( result.getCommandOutput() ) + System.getProperty( "line.separator" );
+                error += "-------------------------------------------------------------------------------" +
+                    System.getProperty( "line.separator" );
+            }
+
+            if ( result.getException() != null )
+            {
+                error += "Exception:" + System.getProperty( "line.separator" );
+                error += result.getException();
+            }
+        }
+
+        return error;
+    }
+
+    private void performAction( String actionName, BuildContext buildContext )
+        throws TaskExecutionException
+    {
+        TaskExecutionException exception;
+
+        try
+        {
+            log.info( "Performing action " + actionName );
+            actionManager.lookup( actionName ).execute( buildContext.getActionContext() );
+            return;
+        }
+        catch ( ActionNotFoundException e )
+        {
+            exception = new TaskExecutionException( "Error looking up action '" + actionName + "'", e );
+        }
+        catch ( Exception e )
+        {
+            exception = new TaskExecutionException( "Error executing action '" + actionName + "'", e );
+        }
+
+        ScmResult result = new ScmResult();
+
+        result.setSuccess( false );
+
+        result.setException( ContinuumBuildAgentUtil.throwableToString( exception ) );
+
+        buildContext.setScmResult( result );
+        buildContext.getActionContext().put( ContinuumBuildAgentUtil.KEY_UPDATE_SCM_RESULT, result );
+
+        throw exception;
+    }
+
+    private void mergeScmResults( BuildContext buildContext )
+    {
+        Map<String, Object> context = buildContext.getActionContext();
+        ScmResult oldScmResult = ContinuumBuildAgentUtil.getOldScmResult( context, null );
+        ScmResult newScmResult = ContinuumBuildAgentUtil.getScmResult( context, null );
+
+        if ( oldScmResult != null )
+        {
+            if ( newScmResult == null )
+            {
+                context.put( ContinuumBuildAgentUtil.KEY_SCM_RESULT, oldScmResult );
+            }
+            else
+            {
+                List<ChangeSet> oldChanges = oldScmResult.getChanges();
+
+                List<ChangeSet> newChanges = newScmResult.getChanges();
+
+                for ( ChangeSet change : newChanges )
+                {
+                    if ( !oldChanges.contains( change ) )
+                    {
+                        oldChanges.add( change );
+                    }
+                }
+
+                newScmResult.setChanges( oldChanges );
+            }
+        }
+    }
+
+    private void buildProjects( List<BuildContext> buildContexts )
+        throws TaskExecutionException
+    {
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put( ContinuumBuildAgentUtil.KEY_BUILD_CONTEXTS, buildContexts );
+
+        BuildContext context = new BuildContext();
+        context.setActionContext( map );
+
+        performAction( "create-agent-build-project-task", context );
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/taskqueue/manager/BuildAgentTaskQueueManager.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/taskqueue/manager/BuildAgentTaskQueueManager.java
new file mode 100644
index 0000000..8f401b0
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/taskqueue/manager/BuildAgentTaskQueueManager.java
@@ -0,0 +1,76 @@
+package org.apache.continuum.buildagent.taskqueue.manager;
+
+/*
+ * 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 org.apache.continuum.buildagent.taskqueue.PrepareBuildProjectsTask;
+import org.apache.continuum.taskqueue.BuildProjectTask;
+import org.apache.continuum.taskqueue.manager.TaskQueueManagerException;
+import org.apache.continuum.utils.build.BuildTrigger;
+import org.codehaus.plexus.taskqueue.TaskQueue;
+
+import java.util.List;
+
+public interface BuildAgentTaskQueueManager
+{
+    String ROLE = BuildAgentTaskQueueManager.class.getName();
+
+    TaskQueue getBuildQueue();
+
+    TaskQueue getPrepareBuildQueue();
+
+    void cancelBuild()
+        throws TaskQueueManagerException;
+
+    int getIdOfProjectCurrentlyBuilding()
+        throws TaskQueueManagerException;
+
+    BuildProjectTask getCurrentProjectInBuilding()
+        throws TaskQueueManagerException;
+
+    PrepareBuildProjectsTask getCurrentProjectInPrepareBuild()
+        throws TaskQueueManagerException;
+
+    boolean hasBuildTaskInQueue()
+        throws TaskQueueManagerException;
+
+    boolean isProjectInBuildQueue( int projectId )
+        throws TaskQueueManagerException;
+
+    boolean isInPrepareBuildQueue( int projectGroupId, BuildTrigger trigger, String scmRootAddress )
+        throws TaskQueueManagerException;
+
+    List<PrepareBuildProjectsTask> getProjectsInPrepareBuildQueue()
+        throws TaskQueueManagerException;
+
+    List<BuildProjectTask> getProjectsInBuildQueue()
+        throws TaskQueueManagerException;
+
+    boolean removeFromPrepareBuildQueue( int projectGroupId, int scmRootId )
+        throws TaskQueueManagerException;
+
+    void removeFromPrepareBuildQueue( int[] hashCodes )
+        throws TaskQueueManagerException;
+
+    boolean removeFromBuildQueue( int projectId, int buildDefinitionId )
+        throws TaskQueueManagerException;
+
+    void removeFromBuildQueue( int[] hashCodes )
+        throws TaskQueueManagerException;
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/taskqueue/manager/DefaultBuildAgentTaskQueueManager.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/taskqueue/manager/DefaultBuildAgentTaskQueueManager.java
new file mode 100644
index 0000000..9398303
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/taskqueue/manager/DefaultBuildAgentTaskQueueManager.java
@@ -0,0 +1,386 @@
+package org.apache.continuum.buildagent.taskqueue.manager;
+
+/*
+ * 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 org.apache.commons.lang.ArrayUtils;
+import org.apache.continuum.buildagent.taskqueue.PrepareBuildProjectsTask;
+import org.apache.continuum.taskqueue.BuildProjectTask;
+import org.apache.continuum.taskqueue.manager.TaskQueueManagerException;
+import org.apache.continuum.utils.build.BuildTrigger;
+import org.codehaus.plexus.PlexusConstants;
+import org.codehaus.plexus.PlexusContainer;
+import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+import org.codehaus.plexus.context.Context;
+import org.codehaus.plexus.context.ContextException;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
+import org.codehaus.plexus.taskqueue.Task;
+import org.codehaus.plexus.taskqueue.TaskQueue;
+import org.codehaus.plexus.taskqueue.TaskQueueException;
+import org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+/**
+ * @plexus.component role="org.apache.continuum.buildagent.taskqueue.manager.BuildAgentTaskQueueManager" role-hint="default"
+ */
+public class DefaultBuildAgentTaskQueueManager
+    implements BuildAgentTaskQueueManager, Contextualizable
+{
+    private static final Logger log = LoggerFactory.getLogger( DefaultBuildAgentTaskQueueManager.class );
+
+    /**
+     * @plexus.requirement role-hint="build-agent"
+     */
+    private TaskQueue buildAgentBuildQueue;
+
+    /**
+     * @plexus.requirement role-hint="prepare-build-agent"
+     */
+    private TaskQueue buildAgentPrepareBuildQueue;
+
+    private PlexusContainer container;
+
+    public void cancelBuild()
+        throws TaskQueueManagerException
+    {
+        Task task = getBuildTaskQueueExecutor().getCurrentTask();
+
+        if ( task != null )
+        {
+            if ( task instanceof BuildProjectTask )
+            {
+                log.info( "Cancelling current build task of project " + ( (BuildProjectTask) task ).getProjectId() );
+                getBuildTaskQueueExecutor().cancelTask( task );
+            }
+            else
+            {
+                log.warn( "Current task not a BuildProjectTask - not cancelling" );
+            }
+        }
+        else
+        {
+            log.warn( "No task running - not cancelling" );
+        }
+    }
+
+    public TaskQueue getBuildQueue()
+    {
+        return buildAgentBuildQueue;
+    }
+
+    public int getIdOfProjectCurrentlyBuilding()
+        throws TaskQueueManagerException
+    {
+        Task task = getBuildTaskQueueExecutor().getCurrentTask();
+        if ( task != null )
+        {
+            if ( task instanceof BuildProjectTask )
+            {
+                log.debug( "Current project building: {}", ( (BuildProjectTask) task ).getProjectName() );
+                return ( (BuildProjectTask) task ).getProjectId();
+            }
+        }
+        return -1;
+    }
+
+    public TaskQueue getPrepareBuildQueue()
+    {
+        return buildAgentPrepareBuildQueue;
+    }
+
+    private void removeProjectsFromBuildQueue()
+        throws TaskQueueManagerException
+    {
+        try
+        {
+            List<BuildProjectTask> queues = buildAgentBuildQueue.getQueueSnapshot();
+
+            if ( queues != null )
+            {
+                for ( BuildProjectTask task : queues )
+                {
+                    if ( task != null )
+                    {
+                        log.info( "remove project '{}' from build queue", task.getProjectName() );
+                        buildAgentBuildQueue.remove( task );
+                    }
+                }
+            }
+            else
+            {
+                log.info( "no build task in queue" );
+            }
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new TaskQueueManagerException( "Error while getting build tasks from queue", e );
+        }
+    }
+
+    public TaskQueueExecutor getBuildTaskQueueExecutor()
+        throws TaskQueueManagerException
+    {
+        try
+        {
+            return (TaskQueueExecutor) container.lookup( TaskQueueExecutor.class, "build-agent" );
+        }
+        catch ( ComponentLookupException e )
+        {
+            throw new TaskQueueManagerException( e.getMessage(), e );
+        }
+    }
+
+    public TaskQueueExecutor getPrepareBuildTaskQueueExecutor()
+        throws TaskQueueManagerException
+    {
+        try
+        {
+            return (TaskQueueExecutor) container.lookup( TaskQueueExecutor.class, "prepare-build-agent" );
+        }
+        catch ( ComponentLookupException e )
+        {
+            throw new TaskQueueManagerException( e.getMessage(), e );
+        }
+    }
+
+    public boolean hasBuildTaskInQueue()
+        throws TaskQueueManagerException
+    {
+        try
+        {
+            if ( getBuildQueue().getQueueSnapshot() != null && getBuildQueue().getQueueSnapshot().size() > 0 )
+            {
+                return true;
+            }
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new TaskQueueManagerException( e.getMessage(), e );
+        }
+        return false;
+    }
+
+    public boolean isProjectInBuildQueue( int projectId )
+        throws TaskQueueManagerException
+    {
+        try
+        {
+            List<BuildProjectTask> queues = buildAgentBuildQueue.getQueueSnapshot();
+
+            if ( queues != null )
+            {
+                for ( BuildProjectTask task : queues )
+                {
+                    if ( task != null && task.getProjectId() == projectId )
+                    {
+                        log.debug( "project {} is in build queue", task.getProjectName() );
+                        return true;
+                    }
+                }
+            }
+            else
+            {
+                log.info( "no build task in queue" );
+            }
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new TaskQueueManagerException( e.getMessage(), e );
+        }
+
+        return false;
+    }
+
+    public boolean isInPrepareBuildQueue( int projectGroupId, BuildTrigger buildTrigger, String scmRootAddress )
+        throws TaskQueueManagerException
+    {
+        try
+        {
+            List<PrepareBuildProjectsTask> queues = buildAgentPrepareBuildQueue.getQueueSnapshot();
+
+            if ( queues != null )
+            {
+                for ( PrepareBuildProjectsTask task : queues )
+                {
+                    if ( task != null && task.getProjectGroupId() == projectGroupId &&
+                        task.getBuildTrigger().getTrigger() == buildTrigger.getTrigger() &&
+                        task.getScmRootAddress().equals( scmRootAddress ) )
+                    {
+                        log.info( "project group {} in prepare build queue", task.getProjectGroupId() );
+                        return true;
+                    }
+                }
+            }
+            else
+            {
+                log.info( "no prepare build task in queue" );
+            }
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new TaskQueueManagerException( e.getMessage(), e );
+        }
+
+        return false;
+    }
+
+    public List<PrepareBuildProjectsTask> getProjectsInPrepareBuildQueue()
+        throws TaskQueueManagerException
+    {
+        try
+        {
+            return buildAgentPrepareBuildQueue.getQueueSnapshot();
+        }
+        catch ( TaskQueueException e )
+        {
+            log.error( "Error occurred while retrieving projects in prepare build queue", e );
+            throw new TaskQueueManagerException( "Error occurred while retrieving projects in prepare build queue", e );
+        }
+    }
+
+    public List<BuildProjectTask> getProjectsInBuildQueue()
+        throws TaskQueueManagerException
+    {
+        try
+        {
+            return buildAgentBuildQueue.getQueueSnapshot();
+        }
+        catch ( TaskQueueException e )
+        {
+            log.error( "Error occurred while retrieving projects in build queue", e );
+            throw new TaskQueueManagerException( "Error occurred while retrieving projects in build queue", e );
+        }
+    }
+
+    public PrepareBuildProjectsTask getCurrentProjectInPrepareBuild()
+        throws TaskQueueManagerException
+    {
+        Task task = getPrepareBuildTaskQueueExecutor().getCurrentTask();
+
+        if ( task != null )
+        {
+            log.debug( "Current project group preparing build: {}",
+                       ( (PrepareBuildProjectsTask) task ).getProjectGroupId() );
+            return (PrepareBuildProjectsTask) task;
+        }
+        return null;
+    }
+
+    public BuildProjectTask getCurrentProjectInBuilding()
+        throws TaskQueueManagerException
+    {
+        Task task = getBuildTaskQueueExecutor().getCurrentTask();
+
+        if ( task != null )
+        {
+            log.debug( "Current project building: {}", ( (BuildProjectTask) task ).getProjectName() );
+            return (BuildProjectTask) task;
+        }
+
+        return null;
+    }
+
+    public boolean removeFromPrepareBuildQueue( int projectGroupId, int scmRootId )
+        throws TaskQueueManagerException
+    {
+        List<PrepareBuildProjectsTask> tasks = getProjectsInPrepareBuildQueue();
+
+        if ( tasks != null )
+        {
+            for ( PrepareBuildProjectsTask task : tasks )
+            {
+                if ( task != null && task.getProjectGroupId() == projectGroupId && task.getScmRootId() == scmRootId )
+                {
+                    log.debug( "Remove project group {} from prepare build queue", projectGroupId );
+                    return getPrepareBuildQueue().remove( task );
+                }
+            }
+        }
+
+        return false;
+    }
+
+    public void removeFromPrepareBuildQueue( int[] hashCodes )
+        throws TaskQueueManagerException
+    {
+        List<PrepareBuildProjectsTask> tasks = getProjectsInPrepareBuildQueue();
+
+        if ( tasks != null )
+        {
+            for ( PrepareBuildProjectsTask task : tasks )
+            {
+                if ( task != null && ArrayUtils.contains( hashCodes, task.getHashCode() ) )
+                {
+                    log.debug( "Remove project group '{}' from prepare build queue", task.getProjectGroupId() );
+                    getPrepareBuildQueue().remove( task );
+                }
+            }
+        }
+    }
+
+    public boolean removeFromBuildQueue( int projectId, int buildDefinitionId )
+        throws TaskQueueManagerException
+    {
+        List<BuildProjectTask> tasks = getProjectsInBuildQueue();
+
+        if ( tasks != null )
+        {
+            for ( BuildProjectTask task : tasks )
+            {
+                if ( task != null && task.getProjectId() == projectId &&
+                    task.getBuildDefinitionId() == buildDefinitionId )
+                {
+                    log.debug( "Remove project {} with buildDefinition{} from build queue", task.getProjectName(),
+                               task.getBuildDefinitionId() );
+                    return getBuildQueue().remove( task );
+                }
+            }
+        }
+
+        return false;
+    }
+
+    public void removeFromBuildQueue( int[] hashCodes )
+        throws TaskQueueManagerException
+    {
+        List<BuildProjectTask> tasks = getProjectsInBuildQueue();
+
+        if ( tasks != null )
+        {
+            for ( BuildProjectTask task : tasks )
+            {
+                if ( task != null && ArrayUtils.contains( hashCodes, task.getHashCode() ) )
+                {
+                    log.debug( "Remove project '{}' from build queue", task.getProjectName() );
+                    getBuildQueue().remove( task );
+                }
+            }
+        }
+    }
+
+    public void contextualize( Context context )
+        throws ContextException
+    {
+        container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
+    }
+
+}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/BuildContextToBuildDefinition.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/BuildContextToBuildDefinition.java
similarity index 100%
rename from continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/BuildContextToBuildDefinition.java
rename to continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/BuildContextToBuildDefinition.java
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/BuildContextToProject.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/BuildContextToProject.java
new file mode 100644
index 0000000..b4a9db2
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/BuildContextToProject.java
@@ -0,0 +1,58 @@
+package org.apache.continuum.buildagent.utils;
+
+/*
+ * 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 org.apache.continuum.buildagent.buildcontext.BuildContext;
+import org.apache.maven.continuum.model.project.Project;
+
+/**
+ * @author Jan Stevens Ancajas
+ */
+public class BuildContextToProject
+{
+    public static Project getProject( BuildContext buildContext )
+    {
+        Project project = new Project();
+
+        project.setId( buildContext.getProjectId() );
+
+        project.setName( buildContext.getProjectName() );
+
+        project.setVersion( buildContext.getProjectVersion() );
+
+        project.setScmUrl( buildContext.getScmUrl() );
+
+        project.setScmUsername( buildContext.getScmUsername() );
+
+        project.setScmPassword( buildContext.getScmPassword() );
+
+        project.setScmTag( buildContext.getScmTag() );
+
+        project.setExecutorId( buildContext.getExecutorId() );
+
+        project.setState( buildContext.getProjectState() );
+
+        project.setOldState( buildContext.getProjectState() );
+
+        project.setBuildNumber( buildContext.getBuildNumber() );
+
+        return project;
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/ContinuumBuildAgentUtil.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/ContinuumBuildAgentUtil.java
new file mode 100644
index 0000000..4a845a3
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/ContinuumBuildAgentUtil.java
@@ -0,0 +1,909 @@
+package org.apache.continuum.buildagent.utils;
+
+/*
+ * 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 org.apache.continuum.buildagent.buildcontext.BuildContext;
+import org.apache.continuum.utils.build.BuildTrigger;
+import org.apache.maven.continuum.ContinuumException;
+import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.BuildResult;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.scm.ChangeFile;
+import org.apache.maven.continuum.model.scm.ChangeSet;
+import org.apache.maven.continuum.model.scm.ScmResult;
+import org.codehaus.plexus.util.StringUtils;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ContinuumBuildAgentUtil
+{
+    public static final String EOL = System.getProperty( "line.separator" );
+
+    public static final String KEY_PROJECT_ID = "project-id";
+
+    public static final String KEY_PROJECT_VERSION = "project-version";
+
+    public static final String KEY_BUILD_NUMBER = "build-number";
+
+    public static final String KEY_BUILD_DEFINITION_ID = "builddefinition-id";
+
+    public static final String KEY_BUILD_DEFINITION_LABEL = "builddefinition-label";
+
+    public static final String KEY_TRIGGER = "trigger";
+
+    public static final String KEY_USERNAME = "username";
+
+    public static final String KEY_EXECUTOR_ID = "executor-id";
+
+    public static final String KEY_SCM_URL = "scm-url";
+
+    public static final String KEY_SCM_USERNAME = "scm-username";
+
+    public static final String KEY_SCM_PASSWORD = "scm-password";
+
+    public static final String KEY_BUILD_FILE = "build-file";
+
+    public static final String KEY_GOALS = "goals";
+
+    public static final String KEY_ARGUMENTS = "arguments";
+
+    public static final String KEY_BUILD_FRESH = "build-fresh";
+
+    public static final String KEY_START_TIME = "start-time";
+
+    public static final String KEY_END_TIME = "end-time";
+
+    public static final String KEY_BUILD_ERROR = "build-error";
+
+    public static final String KEY_BUILD_EXIT_CODE = "build-exit-code";
+
+    public static final String KEY_BUILD_STATE = "build-state";
+
+    public static final String KEY_SCM_STATE = "scm-state";
+
+    public static final String KEY_SCM_COMMAND_OUTPUT = "scm-command-output";
+
+    public static final String KEY_SCM_COMMAND_LINE = "scm-command-line";
+
+    public static final String KEY_SCM_PROVIDER_MESSAGE = "scm-provider-message";
+
+    public static final String KEY_SCM_EXCEPTION = "scm-exception";
+
+    public static final String KEY_PROJECT_GROUP_ID = "project-group-id";
+
+    public static final String KEY_PROJECT_GROUP_NAME = "project-group-name";
+
+    public static final String KEY_SCM_ROOT_ADDRESS = "scm-root-address";
+
+    public static final String KEY_SCM_ROOT_ID = "scm-root-id";
+
+    public static final String KEY_SCM_ROOT_STATE = "scm-root-state";
+
+    public static final String KEY_CHECKOUT_SCM_RESULT = "checkout-scm-result";
+
+    public static final String KEY_UPDATE_SCM_RESULT = "update-scm-result";
+
+    public static final String KEY_WORKING_DIRECTORY_EXISTS = "working-directory-exists";
+
+    public static final String KEY_PROJECT = "project";
+
+    public static final String KEY_BUILD_DEFINITION = "build-definition";
+
+    public static final String KEY_SCM_RESULT = "scm-result";
+
+    public static final String KEY_WORKING_DIRECTORY = "working-directory";
+
+    public static final String KEY_SCM_SUCCESS = "scm-success";
+
+    public static final String KEY_SCM_ERROR = "scm-error";
+
+    public static final String KEY_BUILD_RESULT = "build-result";
+
+    public static final String KEY_PROJECT_NAME = "project-name";
+
+    public static final String KEY_BUILD_OUTPUT = "build-output";
+
+    public static final String KEY_PROJECT_STATE = "project-state";
+
+    public static final String KEY_INSTALLATION_NAME = "installation-name";
+
+    public static final String KEY_INSTALLATION_TYPE = "installation-type";
+
+    public static final String KEY_INSTALLATION_VAR_NAME = "installation-var-name";
+
+    public static final String KEY_INSTALLATION_VAR_VALUE = "installation-var-value";
+
+    public static final String KEY_ENVIRONMENTS = "environments";
+
+    public static final String KEY_LOCAL_REPOSITORY = "local-repository";
+
+    public static final String KEY_SCM_CHANGES = "scm-changes";
+
+    public static final String KEY_CHANGESET_AUTHOR = "changeset-author";
+
+    public static final String KEY_CHANGESET_COMMENT = "changeset-comment";
+
+    public static final String KEY_CHANGESET_DATE = "changeset-date";
+
+    public static final String KEY_CHANGESET_FILES = "changeset-files";
+
+    public static final String KEY_CHANGEFILE_NAME = "changefile-name";
+
+    public static final String KEY_CHANGEFILE_REVISION = "changefile-revision";
+
+    public static final String KEY_CHANGEFILE_STATUS = "changefile-status";
+
+    public static final String KEY_OLD_SCM_RESULT = "old-scm-result";
+
+    public static final String KEY_OLD_SCM_CHANGES = "old-scm-changes";
+
+    public static final String KEY_PROJECT_DESCRIPTION = "project-description";
+
+    public static final String KEY_GROUP_ID = "group-id";
+
+    public static final String KEY_ARTIFACT_ID = "artifact-id";
+
+    public static final String KEY_PROJECT_DEVELOPERS = "project-developers";
+
+    public static final String KEY_PROJECT_DEPENDENCIES = "project-dependencies";
+
+    public static final String KEY_PROJECT_NOTIFIERS = "project-notifiers";
+
+    public static final String KEY_PROJECT_URL = "project-url";
+
+    public static final String KEY_SCM_TAG = "scm-tag";
+
+    public static final String KEY_PROJECT_PARENT = "project-parent";
+
+    public static final String KEY_NOTIFIER_TYPE = "notifier-type";
+
+    public static final String KEY_NOTIFIER_CONFIGURATION = "notifier-configuration";
+
+    public static final String KEY_NOTIFIER_FROM = "notifier-from";
+
+    public static final String KEY_NOTIFIER_RECIPIENT_TYPE = "notifier-recipient-type";
+
+    public static final String KEY_NOTIFIER_ENABLED = "notifier-enabled";
+
+    public static final String KEY_NOTIFIER_SEND_ON_SUCCESS = "notifier-send-on-success";
+
+    public static final String KEY_NOTIFIER_SEND_ON_FAILURE = "notifier-send-on-failure";
+
+    public static final String KEY_NOTIFIER_SEND_ON_ERROR = "notifier-send-on-error";
+
+    public static final String KEY_NOTIFIER_SEND_ON_SCMFAILURE = "notifier-send-on-scmfailure";
+
+    public static final String KEY_NOTIFIER_SEND_ON_WARNING = "notifier-send-on-warning";
+
+    public static final String KEY_PROJECT_DEVELOPER_NAME = "developer-name";
+
+    public static final String KEY_PROJECT_DEVELOPER_EMAIL = "developer-email";
+
+    public static final String KEY_PROJECT_DEVELOPER_SCMID = "developer-scmid";
+
+    public static final String KEY_PROJECT_MODULES = "project-modules";
+
+    public static final String KEY_MAVEN_PROJECT = "maven-project";
+
+    public static final String KEY_LATEST_UPDATE_DATE = "latest-update-date";
+
+    public static final String KEY_BUILD_AGENT_URL = "build-agent-url";
+
+    public static final String KEY_SCM_TAGBASE = "scm-tagbase";
+
+    public static final String KEY_PREPARE_GOALS = "preparation-goals";
+
+    public static final String KEY_PERFORM_GOALS = "perform-goals";
+
+    public static final String KEY_SCM_COMMENT_PREFIX = "scm-comment-prefix";
+
+    public static final String KEY_AUTO_VERSION_SUBMODULES = "auto-version-submodules";
+
+    public static final String KEY_ADD_SCHEMA = "add-schema";
+
+    public static final String KEY_USE_RELEASE_PROFILE = "use-release-profile";
+
+    public static final String KEY_RELEASE_VERSION = "release-version";
+
+    public static final String KEY_DEVELOPMENT_VERSION = "development-version";
+
+    public static final String KEY_USE_EDIT_MODE = "use-edit-mode";
+
+    public static final String KEY_RELEASE_RESULT_CODE = "release-result-code";
+
+    public static final String KEY_RELEASE_OUTPUT = "release-output";
+
+    public static final String KEY_BUILD_CONTEXTS = "build-contexts";
+
+    public static final String KEY_MAX_JOB_EXEC_TIME = "max-job-exec-time";
+
+    public static final String KEY_RELEASE_STATE = "state";
+
+    public static final String KEY_RELEASE_PHASES = "release-phases";
+
+    public static final String KEY_RELEASE_IN_PROGRESS = "release-in-progress";
+
+    public static final String KEY_COMPLETED_RELEASE_PHASES = "completed-release-phases";
+
+    public static final String KEY_RELEASE_ERROR = "release-error";
+
+    public static final String KEY_LOCAL_REPOSITORY_NAME = "repo-name";
+
+    public static final String KEY_LOCAL_REPOSITORY_LAYOUT = "repo-layout";
+
+    public static Integer getProjectId( Map<String, Object> context )
+    {
+        return getInteger( context, KEY_PROJECT_ID );
+    }
+
+    public static String getProjectName( Map<String, Object> context )
+    {
+        return getString( context, KEY_PROJECT_NAME );
+    }
+
+    public static Integer getProjectState( Map<String, Object> context )
+    {
+        return getInteger( context, KEY_PROJECT_STATE );
+    }
+
+    public static Integer getBuildDefinitionId( Map<String, Object> context )
+    {
+        return getInteger( context, KEY_BUILD_DEFINITION_ID );
+    }
+
+    public static String getBuildFile( Map<String, Object> context )
+    {
+        return getString( context, KEY_BUILD_FILE );
+    }
+
+    public static String getExecutorId( Map<String, Object> context )
+    {
+        return getString( context, KEY_EXECUTOR_ID );
+    }
+
+    public static String getGoals( Map<String, Object> context )
+    {
+        return getString( context, KEY_GOALS );
+    }
+
+    public static String getArguments( Map<String, Object> context )
+    {
+        return getString( context, KEY_ARGUMENTS );
+    }
+
+    public static String getScmUrl( Map<String, Object> context )
+    {
+        return getString( context, KEY_SCM_URL );
+    }
+
+    public static String getScmUsername( Map<String, Object> context )
+    {
+        return getString( context, KEY_SCM_USERNAME, "" );
+    }
+
+    public static String getScmPassword( Map<String, Object> context )
+    {
+        return getString( context, KEY_SCM_PASSWORD, "" );
+    }
+
+    public static boolean isBuildFresh( Map<String, Object> context )
+    {
+        return getBoolean( context, KEY_BUILD_FRESH );
+    }
+
+    public static int getProjectGroupId( Map<String, Object> context )
+    {
+        return getInteger( context, KEY_PROJECT_GROUP_ID );
+    }
+
+    public static String getScmRootAddress( Map<String, Object> context )
+    {
+        return getString( context, KEY_SCM_ROOT_ADDRESS );
+    }
+
+    public static int getScmRootState( Map<String, Object> context )
+    {
+        return getInteger( context, KEY_SCM_ROOT_STATE );
+    }
+
+    public static Project getProject( Map<String, Object> context )
+    {
+        return (Project) getObject( context, KEY_PROJECT );
+    }
+
+    public static BuildDefinition getBuildDefinition( Map<String, Object> context )
+    {
+        return (BuildDefinition) getObject( context, KEY_BUILD_DEFINITION );
+    }
+
+    public static ScmResult getCheckoutScmResult( Map<String, Object> context, Object defaultValue )
+    {
+        return (ScmResult) getObject( context, KEY_CHECKOUT_SCM_RESULT, defaultValue );
+    }
+
+    public static ScmResult getUpdateScmResult( Map<String, Object> context, Object defaultValue )
+    {
+        return (ScmResult) getObject( context, KEY_UPDATE_SCM_RESULT, defaultValue );
+    }
+
+    public static ScmResult getScmResult( Map<String, Object> context, Object defaultValue )
+    {
+        return (ScmResult) getObject( context, KEY_SCM_RESULT, defaultValue );
+    }
+
+    public static int getTrigger( Map<String, Object> context )
+    {
+        return getInteger( context, KEY_TRIGGER );
+    }
+
+    public static String getUsername( Map<String, Object> context )
+    {
+        return getString( context, KEY_USERNAME, "scheduled" );
+    }
+
+    public static BuildTrigger getBuildTrigger( Map<String, Object> context )
+    {
+        return new BuildTrigger( getTrigger( context ), getUsername( context ) );
+    }
+
+    public static BuildResult getBuildResult( Map<String, Object> context, Object defaultValue )
+    {
+        return (BuildResult) getObject( context, KEY_BUILD_RESULT, defaultValue );
+    }
+
+    public static Map<String, String> getEnvironments( Map<String, Object> context )
+    {
+        return (Map<String, String>) getObject( context, KEY_ENVIRONMENTS );
+    }
+
+    public static String getLocalRepository( Map<String, Object> context )
+    {
+        return getString( context, KEY_LOCAL_REPOSITORY, "" );
+    }
+
+    public static String getProjectVersion( Map<String, Object> context )
+    {
+        return getString( context, KEY_PROJECT_VERSION );
+    }
+
+    public static String getProjectGroupName( Map<String, Object> context )
+    {
+        return getString( context, KEY_PROJECT_GROUP_NAME );
+    }
+
+    public static int getBuildNumber( Map<String, Object> context )
+    {
+        return getInteger( context, KEY_BUILD_NUMBER );
+    }
+
+    public static List<Map<String, Object>> getOldScmChanges( Map<String, Object> context )
+    {
+        return getList( context, KEY_OLD_SCM_CHANGES );
+    }
+
+    public static String getChangeSetAuthor( Map<String, Object> context )
+    {
+        return getString( context, KEY_CHANGESET_AUTHOR );
+    }
+
+    public static String getChangeSetComment( Map<String, Object> context )
+    {
+        return getString( context, KEY_CHANGESET_COMMENT );
+    }
+
+    public static long getChangeSetDate( Map<String, Object> context )
+    {
+        Date date = getDate( context, KEY_CHANGESET_DATE );
+
+        if ( date == null )
+        {
+            return 0;
+        }
+        else
+        {
+            return date.getTime();
+        }
+    }
+
+    public static List getChangeSetFiles( Map<String, Object> context )
+    {
+        return getList( context, KEY_CHANGESET_FILES );
+    }
+
+    public static String getChangeFileName( Map<String, Object> context )
+    {
+        return getString( context, KEY_CHANGEFILE_NAME );
+    }
+
+    public static String getChangeFileRevision( Map<String, Object> context )
+    {
+        return getString( context, KEY_CHANGEFILE_REVISION );
+    }
+
+    public static String getChangeFileStatus( Map<String, Object> context )
+    {
+        return getString( context, KEY_CHANGEFILE_STATUS );
+    }
+
+    public static ScmResult getOldScmResult( Map<String, Object> context, ScmResult defaultValue )
+    {
+        return (ScmResult) getObject( context, KEY_OLD_SCM_RESULT, defaultValue );
+    }
+
+    public static List getScmChanges( Map<String, Object> context )
+    {
+        return getList( context, KEY_SCM_CHANGES );
+    }
+
+    public static Date getLatestUpdateDate( Map<String, Object> context )
+    {
+        return getDate( context, KEY_LATEST_UPDATE_DATE );
+    }
+
+    public static String getBuildAgentUrl( Map<String, Object> context )
+    {
+        return getString( context, KEY_BUILD_AGENT_URL );
+    }
+
+    public static String getGroupId( Map<String, Object> context )
+    {
+        return getString( context, KEY_GROUP_ID );
+    }
+
+    public static String getArtifactId( Map<String, Object> context )
+    {
+        return getString( context, KEY_ARTIFACT_ID );
+    }
+
+    public static Map getReleaseVersion( Map<String, Object> context )
+    {
+        return getMap( context, KEY_RELEASE_VERSION );
+    }
+
+    public static Map getDevelopmentVersion( Map<String, Object> context )
+    {
+        return getMap( context, KEY_DEVELOPMENT_VERSION );
+    }
+
+    public static String getScmTagBase( Map<String, Object> context )
+    {
+        return getString( context, KEY_SCM_TAGBASE, "" );
+    }
+
+    public static String getScmCommentPrefix( Map<String, Object> context )
+    {
+        return getString( context, KEY_SCM_COMMENT_PREFIX, "" );
+    }
+
+    public static String getScmTag( Map<String, Object> context )
+    {
+        return getString( context, KEY_SCM_TAG, "" );
+    }
+
+    public static String getPrepareGoals( Map<String, Object> context )
+    {
+        return getString( context, KEY_PREPARE_GOALS, "" );
+    }
+
+    public static String getPerformGoals( Map<String, Object> context )
+    {
+        return getString( context, KEY_PERFORM_GOALS, "" );
+    }
+
+    public static String getUseEditMode( Map<String, Object> context )
+    {
+        return getString( context, KEY_USE_EDIT_MODE, "" );
+    }
+
+    public static String getAddSchema( Map<String, Object> context )
+    {
+        return getString( context, KEY_ADD_SCHEMA, "" );
+    }
+
+    public static String getAutoVersionSubmodules( Map<String, Object> context )
+    {
+        return getString( context, KEY_AUTO_VERSION_SUBMODULES, "" );
+    }
+
+    public static List getBuildContexts( Map<String, Object> context )
+    {
+        return getList( context, KEY_BUILD_CONTEXTS );
+    }
+
+    public static int getMaxExecutionTime( Map<String, Object> context )
+    {
+        return getInteger( context, KEY_MAX_JOB_EXEC_TIME );
+    }
+
+    public static String getLocalRepositoryName( Map<String, Object> context )
+    {
+        return getString( context, KEY_LOCAL_REPOSITORY_NAME, "" );
+    }
+
+    public static String getLocalRepositoryLayout( Map<String, Object> context )
+    {
+        return getString( context, KEY_LOCAL_REPOSITORY_LAYOUT, "" );
+    }
+
+    public static int getScmRootId( Map<String, Object> context )
+    {
+        return getInteger( context, KEY_SCM_ROOT_ID );
+    }
+
+    public static String getBuildDefinitionLabel( Map<String, Object> context )
+    {
+        return getString( context, KEY_BUILD_DEFINITION_LABEL, "" );
+    }
+
+    // ----------------------------------------------------------------------
+    //
+    // ----------------------------------------------------------------------
+
+    public static String getString( Map<String, Object> context, String key )
+    {
+        return (String) getObject( context, key );
+    }
+
+    public static String getString( Map<String, Object> context, String key, String defaultValue )
+    {
+        return (String) getObject( context, key, defaultValue );
+    }
+
+    public static boolean getBoolean( Map<String, Object> context, String key )
+    {
+        return (Boolean) getObject( context, key );
+    }
+
+    public static boolean getBoolean( Map<String, Object> context, String key, boolean defaultValue )
+    {
+        return (Boolean) getObject( context, key, defaultValue );
+    }
+
+    public static int getInteger( Map<String, Object> context, String key )
+    {
+        Object obj = getObject( context, key, null );
+
+        if ( obj == null )
+        {
+            return 0;
+        }
+        else
+        {
+            return (Integer) obj;
+        }
+    }
+
+    public static List getList( Map<String, Object> context, String key )
+    {
+        Object obj = getObject( context, key, null );
+
+        if ( obj == null )
+        {
+            return null;
+        }
+        else
+        {
+            List<Object> list = new ArrayList<Object>();
+
+            if ( obj instanceof Object[] )
+            {
+                Object[] objA = (Object[]) obj;
+
+                list.addAll( Arrays.asList( objA ) );
+            }
+            else
+            {
+                list = (List<Object>) obj;
+            }
+
+            return list;
+        }
+    }
+
+    public static Date getDate( Map<String, Object> context, String key )
+    {
+        Object obj = getObject( context, key, null );
+
+        if ( obj == null )
+        {
+            return null;
+        }
+        else
+        {
+            return (Date) obj;
+        }
+    }
+
+    protected static Map getMap( Map<String, Object> context, String key )
+    {
+        Object obj = getObject( context, key, null );
+
+        if ( obj == null )
+        {
+            return null;
+        }
+        else
+        {
+            return (Map) obj;
+        }
+    }
+
+    protected static Object getObject( Map<String, Object> context, String key )
+    {
+        if ( !context.containsKey( key ) )
+        {
+            throw new RuntimeException( "Missing key '" + key + "'." );
+        }
+
+        Object value = context.get( key );
+
+        if ( value == null )
+        {
+            throw new RuntimeException( "Missing value for key '" + key + "'." );
+        }
+
+        return value;
+    }
+
+    protected static Object getObject( Map<String, Object> context, String key, Object defaultValue )
+    {
+        Object value = context.get( key );
+
+        if ( value == null )
+        {
+            return defaultValue;
+        }
+
+        return value;
+    }
+
+    public static String throwableToString( Throwable error )
+    {
+        if ( error == null )
+        {
+            return "";
+        }
+
+        StringWriter writer = new StringWriter();
+
+        PrintWriter printer = new PrintWriter( writer );
+
+        error.printStackTrace( printer );
+
+        printer.flush();
+
+        return writer.getBuffer().toString();
+    }
+
+    public static String throwableMessagesToString( Throwable error )
+    {
+        if ( error == null )
+        {
+            return "";
+        }
+
+        StringBuffer buffer = new StringBuffer();
+
+        buffer.append( error.getMessage() );
+
+        error = error.getCause();
+
+        while ( error != null )
+        {
+            buffer.append( EOL );
+
+            buffer.append( error.getMessage() );
+
+            error = error.getCause();
+        }
+
+        return buffer.toString();
+    }
+
+    public static Map<String, Object> createScmResult( BuildContext buildContext )
+    {
+        Map<String, Object> result = new HashMap<String, Object>();
+        ScmResult scmResult = buildContext.getScmResult();
+
+        result.put( ContinuumBuildAgentUtil.KEY_PROJECT_ID, buildContext.getProjectId() );
+        if ( StringUtils.isEmpty( scmResult.getCommandLine() ) )
+        {
+            result.put( ContinuumBuildAgentUtil.KEY_SCM_COMMAND_LINE, "" );
+        }
+        else
+        {
+            result.put( ContinuumBuildAgentUtil.KEY_SCM_COMMAND_LINE, scmResult.getCommandLine() );
+        }
+        if ( StringUtils.isEmpty( scmResult.getCommandOutput() ) )
+        {
+            result.put( ContinuumBuildAgentUtil.KEY_SCM_COMMAND_OUTPUT, "" );
+        }
+        else
+        {
+            result.put( ContinuumBuildAgentUtil.KEY_SCM_COMMAND_OUTPUT, scmResult.getCommandOutput() );
+        }
+        if ( StringUtils.isEmpty( scmResult.getProviderMessage() ) )
+        {
+            result.put( ContinuumBuildAgentUtil.KEY_SCM_PROVIDER_MESSAGE, "" );
+        }
+        else
+        {
+            result.put( ContinuumBuildAgentUtil.KEY_SCM_PROVIDER_MESSAGE, scmResult.getProviderMessage() );
+        }
+        if ( StringUtils.isEmpty( scmResult.getException() ) )
+        {
+            result.put( ContinuumBuildAgentUtil.KEY_SCM_EXCEPTION, "" );
+        }
+        else
+        {
+            result.put( ContinuumBuildAgentUtil.KEY_SCM_EXCEPTION, scmResult.getException() );
+        }
+        result.put( ContinuumBuildAgentUtil.KEY_SCM_SUCCESS, scmResult.isSuccess() );
+        result.put( ContinuumBuildAgentUtil.KEY_SCM_CHANGES, getScmChanges( scmResult ) );
+
+        return result;
+    }
+
+    private static List<Map<String, Object>> getScmChanges( ScmResult scmResult )
+    {
+        List<Map<String, Object>> scmChanges = new ArrayList<Map<String, Object>>();
+
+        List<ChangeSet> changes = scmResult.getChanges();
+
+        if ( changes != null )
+        {
+            for ( ChangeSet cs : changes )
+            {
+                Map<String, Object> changeSet = new HashMap<String, Object>();
+
+                if ( StringUtils.isNotEmpty( cs.getAuthor() ) )
+                {
+                    changeSet.put( ContinuumBuildAgentUtil.KEY_CHANGESET_AUTHOR, cs.getAuthor() );
+                }
+                else
+                {
+                    changeSet.put( ContinuumBuildAgentUtil.KEY_CHANGESET_AUTHOR, "" );
+                }
+                if ( StringUtils.isNotEmpty( cs.getComment() ) )
+                {
+                    changeSet.put( ContinuumBuildAgentUtil.KEY_CHANGESET_COMMENT, cs.getComment() );
+                }
+                else
+                {
+                    changeSet.put( ContinuumBuildAgentUtil.KEY_CHANGESET_COMMENT, "" );
+                }
+                if ( cs.getDateAsDate() != null )
+                {
+                    changeSet.put( ContinuumBuildAgentUtil.KEY_CHANGESET_DATE, cs.getDateAsDate() );
+                }
+                changeSet.put( ContinuumBuildAgentUtil.KEY_CHANGESET_FILES, getChangeFiles( cs.getFiles() ) );
+
+                scmChanges.add( changeSet );
+            }
+        }
+
+        return scmChanges;
+    }
+
+    private static List<Map<String, String>> getChangeFiles( List<ChangeFile> changeFiles )
+    {
+        List<Map<String, String>> files = new ArrayList<Map<String, String>>();
+
+        if ( changeFiles != null )
+        {
+            for ( ChangeFile file : changeFiles )
+            {
+                Map<String, String> changeFile = new HashMap<String, String>();
+                if ( StringUtils.isNotEmpty( file.getName() ) )
+                {
+                    changeFile.put( ContinuumBuildAgentUtil.KEY_CHANGEFILE_NAME, file.getName() );
+                }
+                else
+                {
+                    changeFile.put( ContinuumBuildAgentUtil.KEY_CHANGEFILE_NAME, "" );
+                }
+                if ( StringUtils.isNotEmpty( file.getRevision() ) )
+                {
+                    changeFile.put( ContinuumBuildAgentUtil.KEY_CHANGEFILE_REVISION, file.getRevision() );
+                }
+                else
+                {
+                    changeFile.put( ContinuumBuildAgentUtil.KEY_CHANGEFILE_REVISION, "" );
+                }
+                if ( StringUtils.isNotEmpty( file.getStatus() ) )
+                {
+                    changeFile.put( ContinuumBuildAgentUtil.KEY_CHANGEFILE_STATUS, file.getStatus() );
+                }
+                else
+                {
+                    changeFile.put( ContinuumBuildAgentUtil.KEY_CHANGEFILE_STATUS, "" );
+                }
+
+                files.add( changeFile );
+            }
+        }
+
+        return files;
+    }
+
+    public static List<File> getFiles( String userDirectory, File workingDirectory )
+        throws ContinuumException
+    {
+        return getFiles( workingDirectory, null, userDirectory );
+    }
+
+    private static List<File> getFiles( File baseDirectory, String currentSubDirectory, String userDirectory )
+    {
+        List<File> dirs = new ArrayList<File>();
+
+        File workingDirectory;
+
+        if ( currentSubDirectory != null )
+        {
+            workingDirectory = new File( baseDirectory, currentSubDirectory );
+        }
+        else
+        {
+            workingDirectory = baseDirectory;
+        }
+
+        String[] files = workingDirectory.list();
+
+        if ( files != null )
+        {
+            for ( String file : files )
+            {
+                File current = new File( workingDirectory, file );
+
+                String currentFile;
+
+                if ( currentSubDirectory == null )
+                {
+                    currentFile = file;
+                }
+                else
+                {
+                    currentFile = currentSubDirectory + "/" + file;
+                }
+
+                if ( userDirectory != null && current.isDirectory() && userDirectory.startsWith( currentFile ) )
+                {
+                    dirs.add( current );
+
+                    dirs.addAll( getFiles( baseDirectory, currentFile, userDirectory ) );
+                }
+                else
+                {
+                    dirs.add( current );
+                }
+            }
+        }
+
+        return dirs;
+    }
+}
\ No newline at end of file
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/WorkingCopyContentGenerator.java b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/WorkingCopyContentGenerator.java
new file mode 100644
index 0000000..6a9fff6
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/WorkingCopyContentGenerator.java
@@ -0,0 +1,203 @@
+package org.apache.continuum.buildagent.utils;
+
+/*
+ * 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 org.codehaus.plexus.util.StringUtils;
+
+import java.io.File;
+import java.text.DecimalFormat;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @plexus.component role="org.apache.continuum.buildagent.utils.WorkingCopyContentGenerator"
+ */
+public class WorkingCopyContentGenerator
+{
+    private static final DecimalFormat decFormatter = new DecimalFormat( "###.##" );
+
+    private File basedir;
+
+    private String urlParamSeparator;
+
+    private static final long KILO = 1024;
+
+    private static final long MEGA = 1024 * KILO;
+
+    private static final long GIGA = 1024 * MEGA;
+
+    private boolean odd = false;
+
+    public String generate( List<File> files, String baseUrl, String imagesBaseUrl, File basedir )
+    {
+        this.basedir = basedir;
+        if ( baseUrl.indexOf( "?" ) > 0 )
+        {
+            urlParamSeparator = "&";
+        }
+        else
+        {
+            urlParamSeparator = "?";
+        }
+
+        StringBuffer buf = new StringBuffer();
+
+        buf.append( "<div class=\"eXtremeTable\" >" );
+        buf.append( "<table class=\"tableRegion\" width=\"100%\">\n" );
+
+        buf.append( "<tr class=\"odd\"><td><img src=\"" ).append( imagesBaseUrl ).append(
+            "icon_arrowfolder1_sml.gif\">&nbsp;<a href=\"" ).append( baseUrl ).append( urlParamSeparator ).append(
+            "userDirectory=/\">/</a><br /></td><td>&nbsp;</td><td>&nbsp;</td>" );
+
+        print( basedir, files, baseUrl, imagesBaseUrl, buf );
+
+        buf.append( "</table>\n" );
+        buf.append( "</div>\n" );
+
+        return buf.toString();
+    }
+
+    private void print( File basedir, List<File> files, String baseUrl, String imagesBaseUrl, StringBuffer buf )
+    {
+        for ( File f : files )
+        {
+            print( f, getIndent( basedir, f ), baseUrl, imagesBaseUrl, buf );
+        }
+    }
+
+    private void print( File f, String indent, String baseUrl, String imagesBaseUrl, StringBuffer buf )
+    {
+        String cssClass = odd ? "odd" : "even";
+
+        if ( !f.isDirectory() )
+        {
+            String fileName = f.getName();
+
+            if ( !".cvsignore".equals( fileName ) && !"vssver.scc".equals( fileName ) &&
+                !".DS_Store".equals( fileName ) && !"release.properties".equals( fileName ) )
+            {
+                String userDirectory;
+
+                if ( f.getParentFile().getAbsolutePath().equals( basedir.getAbsolutePath() ) )
+                {
+                    userDirectory = "/";
+                }
+                else
+                {
+                    userDirectory = f.getParentFile().getAbsolutePath().substring(
+                        basedir.getAbsolutePath().length() + 1 );
+                }
+
+                userDirectory = StringUtils.replace( userDirectory, "\\", "/" );
+
+                buf.append( "<tr class=\"" ).append( cssClass ).append( "\">" );
+
+                buf.append( "<td width=\"98%\">" ).append( indent ).append( "&nbsp;&nbsp;<img src=\"" ).append(
+                    imagesBaseUrl ).append( "file.gif\">&nbsp;<a href=\"" ).append( baseUrl ).append(
+                    urlParamSeparator ).append( "userDirectory=" ).append( userDirectory ).append( "&file=" ).append(
+                    fileName ).append( "\">" ).append( fileName ).append( "</a></td><td width=\"1%\">" ).append(
+                    getReadableFileSize( f.length() ) ).append( "</td><td width=\"1%\">" ).append( getFormattedDate(
+                    f.lastModified() ) ).append( "</td>\n" );
+                buf.append( "</tr>\n" );
+
+                odd = !odd;
+            }
+        }
+        else
+        {
+            String directoryName = f.getName();
+
+            if ( !"CVS".equals( directoryName ) && !".svn".equals( directoryName ) && !"SCCS".equals( directoryName ) )
+            {
+                String userDirectory = f.getAbsolutePath().substring( basedir.getAbsolutePath().length() + 1 );
+
+                userDirectory = StringUtils.replace( userDirectory, "\\", "/" );
+
+                buf.append( "<tr class=\"" ).append( cssClass ).append( "\">" );
+
+                buf.append( "<td width=\"98%\">" ).append( indent ).append( "<img src=\"" ).append(
+                    imagesBaseUrl ).append( "icon_arrowfolder1_sml.gif\">&nbsp;<a href =\"" ).append( baseUrl ).append(
+                    urlParamSeparator ).append( "userDirectory=" ).append( userDirectory ).append( "\">" ).append(
+                    directoryName ).append( "</a></td><td width=\"1%\">" + "&nbsp;" + "</td><td width=\"1%\">" ).append(
+                    getFormattedDate( f.lastModified() ) ).append( "</td>" );
+                buf.append( "</tr>\n" );
+
+                odd = !odd;
+            }
+        }
+    }
+
+    private String getFormattedDate( long timestamp )
+    {
+        Calendar cal = Calendar.getInstance();
+        cal.setTimeInMillis( timestamp );
+        Date date = cal.getTime();
+        String res = new SimpleDateFormat( "MMM dd, yyyy hh:mm:ss aaa z" ).format( date );
+        return StringUtils.replace( res, " ", "&nbsp;" );
+    }
+
+    private static String getReadableFileSize( long fileSizeInBytes )
+    {
+        if ( fileSizeInBytes >= GIGA )
+        {
+            return decFormatter.format( fileSizeInBytes / GIGA ) + "&nbsp;Gb";
+        }
+        else if ( fileSizeInBytes >= MEGA )
+        {
+            return decFormatter.format( fileSizeInBytes / MEGA ) + "&nbsp;Mb";
+        }
+        else if ( fileSizeInBytes >= KILO )
+        {
+            return decFormatter.format( fileSizeInBytes / KILO ) + "&nbsp;Kb";
+        }
+        else if ( fileSizeInBytes > 0 && fileSizeInBytes < KILO )
+        {
+            return decFormatter.format( fileSizeInBytes ) + "&nbsp;b";
+        }
+
+        return "0&nbsp;b";
+    }
+
+    private String getIndent( File basedir, File userFile )
+    {
+        String root = basedir.getAbsolutePath();
+        String userdir;
+        if ( userFile.isDirectory() )
+        {
+            userdir = userFile.getAbsolutePath();
+        }
+        else
+        {
+            userdir = userFile.getParentFile().getAbsolutePath();
+        }
+
+        userdir = userdir.substring( root.length() );
+
+        StringBuffer indent = new StringBuffer();
+        while ( userdir.indexOf( File.separator ) >= 0 )
+        {
+            indent.append( "&nbsp;&nbsp;" );
+            userdir = userdir.substring( userdir.indexOf( File.separator ) + 1 );
+        }
+        return indent.toString();
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/resources/META-INF/plexus/components-fragment.xml b/continuum-buildagent/continuum-buildagent-core/src/main/resources/META-INF/plexus/components-fragment.xml
new file mode 100644
index 0000000..a049c5f
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/resources/META-INF/plexus/components-fragment.xml
@@ -0,0 +1,76 @@
+<!--
+  ~ 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.
+  -->
+
+<component-set>
+  <components>
+    <component>
+      <role>org.codehaus.plexus.taskqueue.TaskQueue</role>
+      <role-hint>build-agent</role-hint>
+      <implementation>org.codehaus.plexus.taskqueue.DefaultTaskQueue</implementation>
+      <lifecycle-handler>plexus-configurable</lifecycle-handler>
+    </component>
+
+    <component>
+      <role>org.codehaus.plexus.taskqueue.TaskQueue</role>
+      <role-hint>prepare-build-agent</role-hint>
+      <implementation>org.codehaus.plexus.taskqueue.DefaultTaskQueue</implementation>
+      <lifecycle-handler>plexus-configurable</lifecycle-handler>
+    </component>
+
+    <component>
+      <role>org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor</role>
+      <role-hint>build-agent</role-hint>
+      <implementation>org.codehaus.plexus.taskqueue.execution.ThreadedTaskQueueExecutor</implementation>
+      <instantiation-strategy>singleton</instantiation-strategy>
+      <requirements>
+        <requirement>
+          <role>org.codehaus.plexus.taskqueue.execution.TaskExecutor</role>
+          <role-hint>build-agent</role-hint>
+        </requirement>
+        <requirement>
+          <role>org.codehaus.plexus.taskqueue.TaskQueue</role>
+          <role-hint>build-agent</role-hint>
+        </requirement>
+      </requirements>
+      <configuration>
+        <name>build-agent</name>
+      </configuration>
+    </component>
+
+    <component>
+      <role>org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor</role>
+      <role-hint>prepare-build-agent</role-hint>
+      <implementation>org.codehaus.plexus.taskqueue.execution.ThreadedTaskQueueExecutor</implementation>
+      <instantiation-strategy>singleton</instantiation-strategy>
+      <requirements>
+        <requirement>
+          <role>org.codehaus.plexus.taskqueue.execution.TaskExecutor</role>
+          <role-hint>prepare-build-agent</role-hint>
+        </requirement>
+        <requirement>
+          <role>org.codehaus.plexus.taskqueue.TaskQueue</role>
+          <role-hint>prepare-build-agent</role-hint>
+        </requirement>
+      </requirements>
+      <configuration>
+        <name>prepare-build-agent</name>
+      </configuration>
+    </component>
+  </components>
+</component-set>
\ No newline at end of file
diff --git a/continuum-buildagent/continuum-buildagent-core/src/main/resources/META-INF/spring-context.xml b/continuum-buildagent/continuum-buildagent-core/src/main/resources/META-INF/spring-context.xml
new file mode 100644
index 0000000..7ed7bf1
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/main/resources/META-INF/spring-context.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+
+
+		http://www.springframework.org/schema/context 
+        http://www.springframework.org/schema/context/spring-context-2.5.xsd">
+
+  <context:annotation-config/>
+  <context:component-scan base-package="org.apache.continuum.buildagent"/>
+
+  <bean name="continuumAgentBuildExecutor#maven2"
+        class="org.apache.continuum.buildagent.build.execution.maven.m2.MavenTwoBuildExecutor" autowire="byName">
+    <property name="defaultExecutable" value="mvn"/>
+    <property name="buildAgentMavenBuilderHelper" ref="buildAgentMavenBuilderHelper"/>
+    <property name="projectHelper" ref="mavenProjectHelper"/>
+  </bean>
+  <bean name="continuumAgentBuildExecutor#maven-1"
+        class="org.apache.continuum.buildagent.build.execution.maven.m1.MavenOneBuildExecutor" autowire="byName">
+    <property name="defaultExecutable" value="maven"/>
+  </bean>
+  <bean name="continuumAgentBuildExecutor#ant"
+        class="org.apache.continuum.buildagent.build.execution.ant.AntBuildExecutor" autowire="byName">
+    <property name="defaultExecutable" value="ant"/>
+  </bean>
+  <bean name="continuumAgentBuildExecutor#shell"
+        class="org.apache.continuum.buildagent.build.execution.shell.ShellBuildExecutor" autowire="byName">
+  </bean>
+
+  <bean id="buildAgentConfigurationService"
+        class="org.apache.continuum.buildagent.configuration.DefaultBuildAgentConfigurationService"
+        init-method="initialize"/>
+
+  <bean id="buildAgentConfiguration"
+        class="org.apache.continuum.buildagent.configuration.DefaultBuildAgentConfiguration"
+        init-method="initialize">
+    <property name="configurationFile" value="file:${appserver.base}/conf/continuum-buildagent.xml"/>
+  </bean>
+</beans>
+	
\ No newline at end of file
diff --git a/continuum-buildagent/continuum-buildagent-core/src/test/java/org/apache/continuum/buildagent/build/execution/maven/m2/DefaultBuildAgentMavenBuilderHelperTest.java b/continuum-buildagent/continuum-buildagent-core/src/test/java/org/apache/continuum/buildagent/build/execution/maven/m2/DefaultBuildAgentMavenBuilderHelperTest.java
new file mode 100644
index 0000000..7aea4c1
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/test/java/org/apache/continuum/buildagent/build/execution/maven/m2/DefaultBuildAgentMavenBuilderHelperTest.java
@@ -0,0 +1,80 @@
+package org.apache.continuum.buildagent.build.execution.maven.m2;
+
+/*
+ * 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 org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.settings.MavenSettingsBuilder;
+import org.apache.maven.settings.Profile;
+import org.apache.maven.settings.Repository;
+import org.apache.maven.settings.RepositoryPolicy;
+import org.apache.maven.settings.Settings;
+import org.codehaus.plexus.spring.PlexusInSpringTestCase;
+
+import java.io.File;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class DefaultBuildAgentMavenBuilderHelperTest
+    extends PlexusInSpringTestCase
+{
+    private DefaultBuildAgentMavenBuilderHelper helper;
+
+    @Override
+    protected void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        helper = (DefaultBuildAgentMavenBuilderHelper) lookup( BuildAgentMavenBuilderHelper.class );
+
+        MavenSettingsBuilder builder = mock(MavenSettingsBuilder.class);
+        when( builder.buildSettings( false )).thenReturn( createSettings() );
+        helper.setMavenSettingsBuilder( builder );
+    }
+
+    private static Settings createSettings()
+    {
+        Settings settings = new Settings();
+        settings.setLocalRepository( getTestFile( "target/local-repository" ).getAbsolutePath() );
+        Profile profile = new Profile();
+        profile.setId( "repo" );
+        Repository repository = new Repository();
+        repository.setId( "central" );
+        repository.setUrl( getTestFile( "src/test/test-repo" ).toURI().toString() );
+        RepositoryPolicy policy = new RepositoryPolicy();
+        policy.setEnabled( true );
+        policy.setUpdatePolicy( "always" );
+        repository.setSnapshots( policy );
+        profile.addRepository( repository );
+        settings.addProfile( profile );
+        settings.addActiveProfile( "repo" );
+        return settings;
+    }
+
+    public void testGetMavenProjectWithMaven3Metadata()
+        throws Exception
+    {
+        File pomFile = getTestFile( "src/test/test-projects/maven3-metadata/pom.xml" );
+        MavenProject project = helper.getMavenProject( new ContinuumProjectBuildingResult(), pomFile );
+        assertNotNull( project );
+    }
+}
\ No newline at end of file
diff --git a/continuum-buildagent/continuum-buildagent-core/src/test/java/org/apache/continuum/buildagent/configuration/BuildAgentConfigurationTest.java b/continuum-buildagent/continuum-buildagent-core/src/test/java/org/apache/continuum/buildagent/configuration/BuildAgentConfigurationTest.java
new file mode 100644
index 0000000..8abe505
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/test/java/org/apache/continuum/buildagent/configuration/BuildAgentConfigurationTest.java
@@ -0,0 +1,193 @@
+package org.apache.continuum.buildagent.configuration;
+
+/*
+ * 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 org.apache.continuum.buildagent.model.Installation;
+import org.apache.continuum.buildagent.model.LocalRepository;
+import org.codehaus.plexus.spring.PlexusInSpringTestCase;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+public class BuildAgentConfigurationTest
+    extends PlexusInSpringTestCase
+{
+    public void testInitialize()
+        throws Exception
+    {
+        DefaultBuildAgentConfiguration config = (DefaultBuildAgentConfiguration) lookup(
+            BuildAgentConfiguration.class );
+
+        config.setConfigurationFile( new File( getBasedir(),
+                                               "target/test-classes/buildagent-config/continuum-buildagent.xml" ) );
+
+        config.initialize();
+
+        GeneralBuildAgentConfiguration generalConfig = config.getContinuumBuildAgentConfiguration();
+        assertEquals( "http://localhost:9595/continuum/master-xmlrpc", generalConfig.getContinuumServerUrl() );
+        assertEquals( new File( "/tmp/data/build-output-directory" ), generalConfig.getBuildOutputDirectory() );
+        assertEquals( new File( "/tmp/data/working-directory" ), generalConfig.getWorkingDirectory() );
+        assertEquals( 1, generalConfig.getInstallations().size() );
+
+        Installation installation = generalConfig.getInstallations().get( 0 );
+        assertEquals( "Tool", installation.getType() );
+        assertEquals( "Maven 2.2.1 Installation", installation.getName() );
+        assertEquals( "M2_HOME", installation.getVarName() );
+        assertEquals( "/tmp/apache-maven-2.2.1", installation.getVarValue() );
+
+        LocalRepository localRepo = generalConfig.getLocalRepositories().get( 0 );
+        assertLocalRepository( getExpectedLocalRepo(), localRepo );
+    }
+
+    public void testSaveExistingConfiguration()
+        throws Exception
+    {
+        DefaultBuildAgentConfiguration config = (DefaultBuildAgentConfiguration) lookup(
+            BuildAgentConfiguration.class );
+
+        config.setConfigurationFile( new File( getBasedir(),
+                                               "target/test-classes/buildagent-config/continuum-buildagent-edit.xml" ) );
+
+        config.initialize();
+
+        String expected = "http://192.165.240.12:8080/continuum/master-xmlrpc";
+
+        GeneralBuildAgentConfiguration generalConfig = config.getContinuumBuildAgentConfiguration();
+
+        assertEquals( "http://localhost:9595/continuum/master-xmlrpc", generalConfig.getContinuumServerUrl() );
+        assertEquals( 1, generalConfig.getInstallations().size() );
+
+        generalConfig.setContinuumServerUrl( expected );
+
+        Installation expectedInstallation = getExpectedInstallation();
+        generalConfig.getInstallations().add( expectedInstallation );
+
+        LocalRepository expectedLocalRepo = getExpectedLocalRepo();
+
+        List<LocalRepository> localRepos = new ArrayList<LocalRepository>();
+        localRepos.add( expectedLocalRepo );
+
+        generalConfig.setLocalRepositories( localRepos );
+
+        config.save();
+
+        config.reload();
+
+        assertEquals( expected, config.getContinuumBuildAgentConfiguration().getContinuumServerUrl() );
+        assertEquals( 2, config.getContinuumBuildAgentConfiguration().getInstallations().size() );
+
+        Installation installation = generalConfig.getInstallations().get( 1 );
+        assertInstallation( expectedInstallation, installation );
+
+        LocalRepository localRepo = generalConfig.getLocalRepositories().get( 0 );
+        assertLocalRepository( expectedLocalRepo, localRepo );
+    }
+
+    public void testSaveNewConfiguration()
+        throws Exception
+    {
+        File configFile = new File( getBasedir(),
+                                    "target/test-classes/buildagent-config/continuum-buildagent-new.xml" );
+        DefaultBuildAgentConfiguration config = (DefaultBuildAgentConfiguration) lookup(
+            BuildAgentConfiguration.class );
+
+        config.setConfigurationFile( configFile );
+
+        config.initialize();
+
+        String expectedUrl = "http://localhost:8080/continuum/master-xmlrpc";
+        File expectedBuildOutputDir = new File( "/tmp/data/build-output-directory" );
+        File expectedWorkingDir = new File( "/tmp/data/working-directory" );
+
+        GeneralBuildAgentConfiguration generalConfig = config.getContinuumBuildAgentConfiguration();
+
+        assertNull( generalConfig.getContinuumServerUrl() );
+        assertNull( generalConfig.getBuildOutputDirectory() );
+        assertNull( generalConfig.getWorkingDirectory() );
+        assertNull( generalConfig.getInstallations() );
+
+        Installation expectedInstallation = getExpectedInstallation();
+
+        List<Installation> installations = new ArrayList<Installation>();
+        installations.add( expectedInstallation );
+
+        LocalRepository expectedLocalRepo = getExpectedLocalRepo();
+
+        List<LocalRepository> localRepos = new ArrayList<LocalRepository>();
+        localRepos.add( expectedLocalRepo );
+
+        generalConfig.setContinuumServerUrl( expectedUrl );
+        generalConfig.setBuildOutputDirectory( expectedBuildOutputDir );
+        generalConfig.setWorkingDirectory( expectedWorkingDir );
+        generalConfig.setInstallations( installations );
+        generalConfig.setLocalRepositories( localRepos );
+
+        config.save();
+
+        config.reload();
+
+        assertTrue( configFile.exists() );
+        assertEquals( expectedUrl, config.getContinuumBuildAgentConfiguration().getContinuumServerUrl() );
+        assertEquals( expectedBuildOutputDir, config.getContinuumBuildAgentConfiguration().getBuildOutputDirectory() );
+        assertEquals( expectedWorkingDir, config.getContinuumBuildAgentConfiguration().getWorkingDirectory() );
+        assertEquals( 1, config.getContinuumBuildAgentConfiguration().getInstallations().size() );
+
+        Installation installation = generalConfig.getInstallations().get( 0 );
+        assertInstallation( expectedInstallation, installation );
+
+        LocalRepository localRepo = generalConfig.getLocalRepositories().get( 0 );
+        assertLocalRepository( expectedLocalRepo, localRepo );
+    }
+
+    private Installation getExpectedInstallation()
+    {
+        Installation expectedInstallation = new Installation();
+        expectedInstallation.setName( "Maven 2.0.10 Installation" );
+        expectedInstallation.setType( "Tool" );
+        expectedInstallation.setVarName( "M2_HOME" );
+        expectedInstallation.setVarValue( "/tmp/apache-maven-2.1.10" );
+        return expectedInstallation;
+    }
+
+    private LocalRepository getExpectedLocalRepo()
+    {
+        LocalRepository expectedLocalRepo = new LocalRepository();
+        expectedLocalRepo.setName( "default" );
+        expectedLocalRepo.setLayout( "default" );
+        expectedLocalRepo.setLocation( "/tmp/.m2/repository" );
+        return expectedLocalRepo;
+    }
+
+    private void assertLocalRepository( LocalRepository expectedLocalRepo, LocalRepository localRepo )
+    {
+        assertEquals( expectedLocalRepo.getName(), localRepo.getName() );
+        assertEquals( expectedLocalRepo.getLayout(), localRepo.getLayout() );
+        assertEquals( expectedLocalRepo.getLocation(), localRepo.getLocation() );
+    }
+
+    private void assertInstallation( Installation expectedInstallation, Installation installation )
+    {
+        assertEquals( expectedInstallation.getType(), installation.getType() );
+        assertEquals( expectedInstallation.getName(), installation.getName() );
+        assertEquals( expectedInstallation.getVarName(), installation.getVarName() );
+        assertEquals( expectedInstallation.getVarValue(), installation.getVarValue() );
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/test/java/org/apache/continuum/buildagent/manager/BuildAgentPurgeManagerTest.java b/continuum-buildagent/continuum-buildagent-core/src/test/java/org/apache/continuum/buildagent/manager/BuildAgentPurgeManagerTest.java
new file mode 100644
index 0000000..a912256
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/test/java/org/apache/continuum/buildagent/manager/BuildAgentPurgeManagerTest.java
@@ -0,0 +1,307 @@
+package org.apache.continuum.buildagent.manager;
+
+/*
+ * 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 org.apache.commons.io.FileUtils;
+import org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
+import org.codehaus.plexus.spring.PlexusInSpringTestCase;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.integration.junit3.JUnit3Mockery;
+import org.jmock.lib.legacy.ClassImposteriser;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * For CONTINUUM-2658 tests, Support purging of working and release directories of build agents on a schedule
+ */
+public class BuildAgentPurgeManagerTest
+    extends PlexusInSpringTestCase
+{
+    private static final int DAYS_OLD = 2;
+
+    private static final int RELEASES_COUNT = 5;
+
+    private static final int RELEASES_DAYS_OLD_COUNT = 3;
+
+    private static final int WORKING_COUNT = 10;
+
+    private static final int WORKING_DAYS_OLD_COUNT = 9;
+
+    private static final String DIRECTORY_TYPE_RELEASES = "releases";
+
+    private static final String DIRECTORY_TYPE_WORKING = "working";
+
+    private Mockery context;
+
+    private BuildAgentConfigurationService buildAgentConfigurationService;
+
+    private DefaultBuildAgentPurgeManager purgeManager;
+
+    private File tempDir;
+
+    protected void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        context = new JUnit3Mockery();
+        context.setImposteriser( ClassImposteriser.INSTANCE );
+
+        purgeManager = (DefaultBuildAgentPurgeManager) lookup( BuildAgentPurgeManager.class );
+
+        buildAgentConfigurationService = context.mock( BuildAgentConfigurationService.class );
+
+        purgeManager.setBuildAgentConfigurationService( buildAgentConfigurationService );
+
+        createTestDirectoriesAndFiles();
+    }
+
+    protected void tearDown()
+        throws Exception
+    {
+        purgeManager = null;
+        cleanUpTestDirectoriesAndFiles();
+        super.tearDown();
+    }
+
+    // CONTINUUM-2658
+    public void testCleanAllPurge()
+        throws Exception
+    {
+        context.checking( new Expectations()
+        {
+            {
+                one( buildAgentConfigurationService ).getWorkingDirectory();
+                will( returnValue( tempDir ) );
+
+                one( buildAgentConfigurationService ).getWorkingDirectory();
+                will( returnValue( tempDir ) );
+            }
+        } );
+
+        //confirm current content of directory
+        //2 random files
+        assertEquals( RELEASES_COUNT + WORKING_COUNT + 2, tempDir.list().length );
+
+        purgeManager.executeDirectoryPurge( DIRECTORY_TYPE_WORKING, 1, 1, true );
+
+        //confirm current content of directory
+        //working directories deleted
+        assertEquals( RELEASES_COUNT + 2, tempDir.list().length );
+
+        purgeManager.executeDirectoryPurge( DIRECTORY_TYPE_RELEASES, 1, 1, true );
+
+        //confirm current content of directory
+        //releases directories deleted
+        assertEquals( 2, tempDir.list().length );
+    }
+
+    public void testRetentionOnlyPurge()
+        throws Exception
+    {
+        context.checking( new Expectations()
+        {
+            {
+                one( buildAgentConfigurationService ).getWorkingDirectory();
+                will( returnValue( tempDir ) );
+
+                one( buildAgentConfigurationService ).getWorkingDirectory();
+                will( returnValue( tempDir ) );
+            }
+        } );
+
+        //confirm current content of directory
+        //2 random files
+        assertEquals( RELEASES_COUNT + WORKING_COUNT + 2, tempDir.list().length );
+
+        purgeManager.executeDirectoryPurge( DIRECTORY_TYPE_WORKING, 0, 2, false );
+
+        List<String> fileNames = Arrays.asList( tempDir.list() );
+
+        File[] files = tempDir.listFiles();
+
+        //confirm current content of directory
+        //2 working directories left
+        assertEquals( RELEASES_COUNT + 2 + 2, fileNames.size() );
+
+        purgeManager.executeDirectoryPurge( DIRECTORY_TYPE_RELEASES, 0, 4, false );
+
+        fileNames = Arrays.asList( tempDir.list() );
+
+        //confirm current content of directory
+        //4 releases directories left
+        assertEquals( 4 + 2 + 2, fileNames.size() );
+    }
+
+    public void testDaysOldOnlyPurge()
+        throws Exception
+    {
+        context.checking( new Expectations()
+        {
+            {
+                one( buildAgentConfigurationService ).getWorkingDirectory();
+                will( returnValue( tempDir ) );
+
+                one( buildAgentConfigurationService ).getWorkingDirectory();
+                will( returnValue( tempDir ) );
+            }
+        } );
+
+        //confirm current content of directory
+        //2 random files
+        assertEquals( RELEASES_COUNT + WORKING_COUNT + 2, tempDir.list().length );
+
+        purgeManager.executeDirectoryPurge( DIRECTORY_TYPE_WORKING, 1, 0, false );
+
+        List<String> fileNames = Arrays.asList( tempDir.list() );
+
+        //confirm current content of directory
+        //days old directories are deleted
+        assertEquals( RELEASES_COUNT + ( WORKING_COUNT - WORKING_DAYS_OLD_COUNT ) + 2, fileNames.size() );
+
+        purgeManager.executeDirectoryPurge( DIRECTORY_TYPE_RELEASES, 1, 0, false );
+
+        fileNames = Arrays.asList( tempDir.list() );
+
+        //confirm current content of directory
+        //days old directories are deleted
+        assertEquals( ( RELEASES_COUNT - RELEASES_DAYS_OLD_COUNT ) + ( WORKING_COUNT - WORKING_DAYS_OLD_COUNT ) + 2,
+                      fileNames.size() );
+    }
+
+    public void testRetentionAndDaysOldOnlyPurge()
+        throws Exception
+    {
+        context.checking( new Expectations()
+        {
+            {
+                one( buildAgentConfigurationService ).getWorkingDirectory();
+                will( returnValue( tempDir ) );
+
+                one( buildAgentConfigurationService ).getWorkingDirectory();
+                will( returnValue( tempDir ) );
+            }
+        } );
+
+        //confirm current content of directory
+        //2 random files
+        assertEquals( RELEASES_COUNT + WORKING_COUNT + 2, tempDir.list().length );
+
+        purgeManager.executeDirectoryPurge( DIRECTORY_TYPE_WORKING, 1, 5, false );
+
+        List<String> fileNames = Arrays.asList( tempDir.list() );
+
+        //confirm current content of directory
+        //days old directories are deleted
+        assertEquals( RELEASES_COUNT + Math.max( 5, WORKING_COUNT - WORKING_DAYS_OLD_COUNT ) + 2, fileNames.size() );
+
+        purgeManager.executeDirectoryPurge( DIRECTORY_TYPE_RELEASES, 1, 1, false );
+
+        fileNames = Arrays.asList( tempDir.list() );
+
+        //confirm current content of directory
+        //days old directories are deleted
+        assertEquals( Math.max( 1, RELEASES_COUNT - RELEASES_DAYS_OLD_COUNT ) + Math.max( 5, WORKING_COUNT -
+            WORKING_DAYS_OLD_COUNT ) + 2, fileNames.size() );
+    }
+
+    private void createTestDirectoriesAndFiles()
+        throws Exception
+    {
+        SimpleDateFormat format = new SimpleDateFormat( "yyyyMMddHHmmss" );
+        tempDir = new File( System.getProperty( "java.io.tmpdir" ) + System.getProperty( "file.separator" ) +
+                                format.format( new Date() ) );
+        if ( !tempDir.mkdirs() )
+        {
+            throw new IOException( "Unable to create test directory: " + tempDir.getName() );
+        }
+
+        createReleasesDirectories( tempDir, RELEASES_COUNT, DAYS_OLD, RELEASES_DAYS_OLD_COUNT );
+        createWorkingDirectories( tempDir, WORKING_COUNT, DAYS_OLD, WORKING_DAYS_OLD_COUNT );
+        createRandomFile( tempDir, "random.txt" );
+        createRandomFile( tempDir, "releases-random.txt" );
+    }
+
+    private void createReleasesDirectories( File parentDir, int count, int daysOld, int daysOldCount )
+        throws Exception
+    {
+        int daysOldIndex = 0;
+        for ( int x = 1; x <= count; x++ )
+        {
+            File file = new File( tempDir.getAbsolutePath() + System.getProperty( "file.separator" ) + "releases-" +
+                                      x );
+            if ( !file.mkdirs() )
+            {
+                throw new IOException( "Unable to create test directory: " + file.getName() );
+            }
+            if ( daysOldIndex < daysOldCount )
+            {
+                long daysOldTime = System.currentTimeMillis() - 24 * 60 * 60 * 1000 * daysOld;
+                file.setLastModified( daysOldTime );
+                daysOldIndex++;
+            }
+
+        }
+    }
+
+    private void createWorkingDirectories( File parentDir, int count, int daysOld, int daysOldCount )
+        throws Exception
+    {
+        int daysOldIndex = 0;
+        for ( int x = 1; x <= count; x++ )
+        {
+            File file = new File( tempDir.getAbsolutePath() + System.getProperty( "file.separator" ) + x );
+            if ( !file.mkdirs() )
+            {
+                throw new IOException( "Unable to create test directory: " + file.getName() );
+            }
+            if ( daysOldIndex < daysOldCount )
+            {
+                long daysOldTime = System.currentTimeMillis() - 24 * 60 * 60 * 1000 * daysOld;
+                file.setLastModified( daysOldTime );
+                daysOldIndex++;
+            }
+
+        }
+    }
+
+    private File createRandomFile( File parentDir, String fileName )
+        throws IOException
+    {
+        File randomFile = new File( parentDir.getAbsolutePath() + System.getProperty( "file.separator" ) + fileName );
+        if ( !randomFile.exists() )
+        {
+            randomFile.createNewFile();
+        }
+        return randomFile;
+    }
+
+    private void cleanUpTestDirectoriesAndFiles()
+        throws IOException
+    {
+        FileUtils.deleteDirectory( tempDir );
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/test/java/org/apache/continuum/buildagent/manager/BuildAgentReleaseManagerTest.java b/continuum-buildagent/continuum-buildagent-core/src/test/java/org/apache/continuum/buildagent/manager/BuildAgentReleaseManagerTest.java
new file mode 100644
index 0000000..1e43e5a
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/test/java/org/apache/continuum/buildagent/manager/BuildAgentReleaseManagerTest.java
@@ -0,0 +1,318 @@
+package org.apache.continuum.buildagent.manager;
+
+/*
+ * 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 org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
+import org.apache.continuum.buildagent.model.LocalRepository;
+import org.apache.continuum.buildagent.utils.ContinuumBuildAgentUtil;
+import org.apache.maven.continuum.release.ContinuumReleaseException;
+import org.codehaus.plexus.spring.PlexusInSpringTestCase;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.integration.junit3.JUnit3Mockery;
+import org.jmock.lib.legacy.ClassImposteriser;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * For the CONTINUUM-2391 tests, checking of the local repository details is in ContinuumReleaseManagerStub. An
+ * exception is thrown if the set local repository in the repository map is incorrect.
+ */
+public class BuildAgentReleaseManagerTest
+    extends PlexusInSpringTestCase
+{
+    private Mockery context;
+
+    private BuildAgentConfigurationService buildAgentConfigurationService;
+
+    private DefaultBuildAgentReleaseManager releaseManager;
+
+    protected void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        context = new JUnit3Mockery();
+        context.setImposteriser( ClassImposteriser.INSTANCE );
+
+        releaseManager = (DefaultBuildAgentReleaseManager) lookup( BuildAgentReleaseManager.class );
+
+        buildAgentConfigurationService = context.mock( BuildAgentConfigurationService.class );
+
+        releaseManager.setBuildAgentConfigurationService( buildAgentConfigurationService );
+    }
+
+    protected void tearDown()
+        throws Exception
+    {
+        releaseManager = null;
+
+        super.tearDown();
+    }
+
+    // CONTINUUM-2391
+    public void testLocalRepositoryInReleasePrepare()
+        throws Exception
+    {
+        final List<LocalRepository> localRepos = createLocalRepositories();
+        final File workingDir = new File( getBasedir(), "target/test-classes/working-dir" );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( buildAgentConfigurationService ).getLocalRepositories();
+                will( returnValue( localRepos ) );
+
+                one( buildAgentConfigurationService ).getWorkingDirectory( 1 );
+                will( returnValue( workingDir ) );
+
+                one( buildAgentConfigurationService ).getAvailableInstallations();
+                will( returnValue( null ) );
+            }
+        } );
+
+        try
+        {
+            releaseManager.releasePrepare( createProjectMap(), createProperties(), createReleaseVersionMap(),
+                                           createDevVersionMap(), createEnvironmentsMap(), "user" );
+        }
+        catch ( ContinuumReleaseException e )
+        {
+            fail( "An exception should not have been thrown!" );
+        }
+    }
+
+    // CONTINUUM-2391
+    public void testLocalRepositoryNameMismatchedCaseInReleasePrepare()
+        throws Exception
+    {
+        final List<LocalRepository> localRepos = createLocalRepositories();
+        final File workingDir = new File( getBasedir(), "target/test-classes/working-dir" );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( buildAgentConfigurationService ).getLocalRepositories();
+                will( returnValue( localRepos ) );
+
+                one( buildAgentConfigurationService ).getWorkingDirectory( 1 );
+                will( returnValue( workingDir ) );
+
+                one( buildAgentConfigurationService ).getAvailableInstallations();
+                will( returnValue( null ) );
+            }
+        } );
+
+        Map<String, Object> map = createProjectMap();
+
+        try
+        {
+            releaseManager.releasePrepare( map, createProperties(), createReleaseVersionMap(), createDevVersionMap(),
+                                           createEnvironmentsMap(), "user" );
+        }
+        catch ( ContinuumReleaseException e )
+        {
+            fail( "An exception should not have been thrown!" );
+        }
+    }
+
+    // CONTINUUM-2391
+    @SuppressWarnings( "unchecked" )
+    public void testLocalRepositoryInReleasePerform()
+        throws Exception
+    {
+        final List<LocalRepository> localRepos = createLocalRepositories();
+        final File workingDir = new File( getBasedir(), "target/test-classes/working-dir" );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( buildAgentConfigurationService ).getLocalRepositories();
+                will( returnValue( localRepos ) );
+
+                one( buildAgentConfigurationService ).getWorkingDirectory();
+                will( returnValue( workingDir ) );
+            }
+        } );
+
+        Map repository = createRepositoryMap();
+        repository.put( ContinuumBuildAgentUtil.KEY_LOCAL_REPOSITORY_NAME, "DEFAULT" );
+
+        try
+        {
+            releaseManager.releasePerform( "1", "clean deploy", "", true, repository, "user" );
+        }
+        catch ( ContinuumReleaseException e )
+        {
+            fail( "An exception should not have been thrown!" );
+        }
+    }
+
+    // CONTINUUM-2391
+    public void testLocalRepositoryNameMismatchedCaseInReleasePerform()
+        throws Exception
+    {
+        final List<LocalRepository> localRepos = createLocalRepositories();
+        final File workingDir = new File( getBasedir(), "target/test-classes/working-dir" );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( buildAgentConfigurationService ).getLocalRepositories();
+                will( returnValue( localRepos ) );
+
+                one( buildAgentConfigurationService ).getWorkingDirectory();
+                will( returnValue( workingDir ) );
+            }
+        } );
+
+        try
+        {
+            releaseManager.releasePerform( "1", "clean deploy", "", true, createRepositoryMap(), "user" );
+        }
+        catch ( ContinuumReleaseException e )
+        {
+            fail( "An exception should not have been thrown!" );
+        }
+    }
+
+    // CONTINUUM-2391
+    @SuppressWarnings( "unchecked" )
+    public void testLocalRepositoryInReleasePerformFromScm()
+        throws Exception
+    {
+        final List<LocalRepository> localRepos = createLocalRepositories();
+        final File workingDir = new File( getBasedir(), "target/test-classes/working-dir" );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( buildAgentConfigurationService ).getLocalRepositories();
+                will( returnValue( localRepos ) );
+
+                one( buildAgentConfigurationService ).getWorkingDirectory();
+                will( returnValue( workingDir ) );
+            }
+        } );
+
+        Map repository = new HashMap();
+        repository.put( ContinuumBuildAgentUtil.KEY_USERNAME, "user" );
+        repository.put( ContinuumBuildAgentUtil.KEY_LOCAL_REPOSITORY_NAME, "default" );
+
+        try
+        {
+            releaseManager.releasePerformFromScm( "clean deploy", "", true, repository,
+                                                  "scm:svn:http://svn.example.com/repos/test-project", "user",
+                                                  "mypasswrd",
+                                                  "scm:svn:http://svn.example.com/repos/test-project/tags/test-project-1.0",
+                                                  "scm:svn:http://svn.example.com/repos/test-project/tags", null,
+                                                  "user" );
+        }
+        catch ( ContinuumReleaseException e )
+        {
+            fail( "An exception should not have been thrown!" );
+        }
+    }
+
+    private List<LocalRepository> createLocalRepositories()
+    {
+        List<LocalRepository> localRepos = new ArrayList<LocalRepository>();
+        LocalRepository localRepo = new LocalRepository();
+        localRepo.setName( "temp" );
+        localRepo.setLocation( "/tmp/.m2/repository" );
+        localRepo.setLayout( "default" );
+
+        localRepos.add( localRepo );
+
+        localRepo = new LocalRepository();
+        localRepo.setName( "default" );
+        localRepo.setLocation( "/home/user/.m2/repository" );
+        localRepo.setLayout( "default" );
+
+        localRepos.add( localRepo );
+
+        return localRepos;
+    }
+
+    private Map<String, String> createEnvironmentsMap()
+    {
+        Map<String, String> environments = new HashMap<String, String>();
+        environments.put( "M2_HOME", "/tmp/bin/apache-maven-2.2.1" );
+
+        return environments;
+    }
+
+    private Map<String, String> createDevVersionMap()
+    {
+        Map<String, String> devVersion = new HashMap<String, String>();
+        devVersion.put( "1.1-SNAPSHOT", "1.1-SNAPSHOT" );
+
+        return devVersion;
+    }
+
+    private Map<String, String> createReleaseVersionMap()
+    {
+        Map<String, String> releaseVersion = new HashMap<String, String>();
+        releaseVersion.put( "1.0", "1.0" );
+
+        return releaseVersion;
+    }
+
+    private Properties createProperties()
+    {
+        Properties properties = new Properties();
+        properties.put( ContinuumBuildAgentUtil.KEY_SCM_USERNAME, "scmusername" );
+        properties.put( ContinuumBuildAgentUtil.KEY_SCM_PASSWORD, "scmpassword" );
+        properties.put( ContinuumBuildAgentUtil.KEY_SCM_TAGBASE,
+                        "scm:svn:http://svn.example.com/repos/test-project/tags" );
+        properties.put( ContinuumBuildAgentUtil.KEY_PREPARE_GOALS, "clean install" );
+        properties.put( ContinuumBuildAgentUtil.KEY_ARGUMENTS, "" );
+        properties.put( ContinuumBuildAgentUtil.KEY_SCM_TAG, "test-project-1.0" );
+
+        return properties;
+    }
+
+    private Map<String, Object> createProjectMap()
+    {
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put( ContinuumBuildAgentUtil.KEY_LOCAL_REPOSITORY_NAME, "default" );
+        map.put( ContinuumBuildAgentUtil.KEY_PROJECT_ID, 1 );
+        map.put( ContinuumBuildAgentUtil.KEY_GROUP_ID, "1" );
+        map.put( ContinuumBuildAgentUtil.KEY_ARTIFACT_ID, "test-project" );
+        map.put( ContinuumBuildAgentUtil.KEY_SCM_URL, "scm:svn:http://svn.example.com/repos/test-project/trunk" );
+
+        return map;
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private Map createRepositoryMap()
+    {
+        Map repository = new HashMap();
+        repository.put( ContinuumBuildAgentUtil.KEY_USERNAME, "user" );
+        repository.put( ContinuumBuildAgentUtil.KEY_LOCAL_REPOSITORY_NAME, "default" );
+
+        return repository;
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/test/java/org/apache/continuum/buildagent/stubs/ContinuumActionStub.java b/continuum-buildagent/continuum-buildagent-core/src/test/java/org/apache/continuum/buildagent/stubs/ContinuumActionStub.java
new file mode 100644
index 0000000..81c509a
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/test/java/org/apache/continuum/buildagent/stubs/ContinuumActionStub.java
@@ -0,0 +1,42 @@
+package org.apache.continuum.buildagent.stubs;
+
+/*
+ * 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 org.apache.continuum.buildagent.utils.ContinuumBuildAgentUtil;
+import org.codehaus.plexus.action.AbstractAction;
+
+import java.util.Map;
+
+/**
+ * This is used for testing the fix for CONTINUUM-2391. See BuildPRrojectTaskExecutorTest.java and
+ * BuildProjectTaskExecutorTest.xml for details.
+ */
+public class ContinuumActionStub
+    extends AbstractAction
+{
+    public void execute( Map context )
+        throws Exception
+    {
+        if ( !ContinuumBuildAgentUtil.getLocalRepository( context ).equals( "/home/user/.m2/repository" ) )
+        {
+            throw new Exception( "Local repository set in the build context should not have been a full path!" );
+        }
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/test/java/org/apache/continuum/buildagent/stubs/ContinuumReleaseManagerStub.java b/continuum-buildagent/continuum-buildagent-core/src/test/java/org/apache/continuum/buildagent/stubs/ContinuumReleaseManagerStub.java
new file mode 100644
index 0000000..7febefc
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/test/java/org/apache/continuum/buildagent/stubs/ContinuumReleaseManagerStub.java
@@ -0,0 +1,52 @@
+package org.apache.continuum.buildagent.stubs;
+
+/*
+ * 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 org.apache.continuum.model.repository.LocalRepository;
+import org.apache.maven.continuum.release.ContinuumReleaseException;
+import org.apache.maven.continuum.release.ContinuumReleaseManagerListener;
+import org.apache.maven.continuum.release.DefaultContinuumReleaseManager;
+
+import java.io.File;
+
+public class ContinuumReleaseManagerStub
+    extends DefaultContinuumReleaseManager
+{
+    public void perform( String releaseId, File buildDirectory, String goals, String arguments,
+                         boolean useReleaseProfile, ContinuumReleaseManagerListener listener,
+                         LocalRepository repository )
+        throws ContinuumReleaseException
+    {
+        if ( !repository.getName().equalsIgnoreCase( "default" ) )
+        {
+            throw new ContinuumReleaseException( "Incorrect local repository name!" );
+        }
+
+        if ( !repository.getLocation().equals( "/home/user/.m2/repository" ) )
+        {
+            throw new ContinuumReleaseException( "Incorrect local repository location!" );
+        }
+
+        if ( !repository.getLayout().equals( "default" ) )
+        {
+            throw new ContinuumReleaseException( "Incorrect local repository layout!" );
+        }
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-core/src/test/java/org/apache/continuum/buildagent/taskqueue/execution/BuildProjectTaskExecutorTest.java b/continuum-buildagent/continuum-buildagent-core/src/test/java/org/apache/continuum/buildagent/taskqueue/execution/BuildProjectTaskExecutorTest.java
new file mode 100644
index 0000000..a0026e6
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/test/java/org/apache/continuum/buildagent/taskqueue/execution/BuildProjectTaskExecutorTest.java
@@ -0,0 +1,415 @@
+package org.apache.continuum.buildagent.taskqueue.execution;
+
+/*
+ * 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 org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutor;
+import org.apache.continuum.buildagent.build.execution.manager.BuildAgentBuildExecutorManager;
+import org.apache.continuum.buildagent.buildcontext.BuildContext;
+import org.apache.continuum.buildagent.buildcontext.manager.BuildContextManager;
+import org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
+import org.apache.continuum.buildagent.manager.BuildAgentManager;
+import org.apache.continuum.buildagent.model.Installation;
+import org.apache.continuum.buildagent.model.LocalRepository;
+import org.apache.continuum.buildagent.utils.ContinuumBuildAgentUtil;
+import org.apache.continuum.taskqueue.BuildProjectTask;
+import org.apache.continuum.utils.build.BuildTrigger;
+import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
+import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.scm.ScmResult;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.spring.PlexusInSpringTestCase;
+import org.codehaus.plexus.taskqueue.execution.TaskExecutor;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.integration.junit3.JUnit3Mockery;
+import org.jmock.lib.legacy.ClassImposteriser;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class BuildProjectTaskExecutorTest
+    extends PlexusInSpringTestCase
+{
+    private Mockery context;
+
+    private BuildContextManager buildContextManager;
+
+    private BuildAgentBuildExecutorManager buildAgentBuildExecutorManager;
+
+    private BuildAgentConfigurationService buildAgentConfigurationService;
+
+    private BuildAgentManager buildAgentManager;
+
+    protected void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        context = new JUnit3Mockery();
+        context.setImposteriser( ClassImposteriser.INSTANCE );
+
+        buildContextManager = context.mock( BuildContextManager.class );
+
+        buildAgentBuildExecutorManager = context.mock( BuildAgentBuildExecutorManager.class );
+
+        buildAgentConfigurationService = context.mock( BuildAgentConfigurationService.class );
+
+        buildAgentManager = context.mock( BuildAgentManager.class );
+    }
+
+    // CONTINUUM-2391
+    // Note: The checking of the local repo set in the context is in ContinuumActionStub. If the
+    // local repo path is incorrect, an exception will be thrown by the action stub.
+    public void testBuildProjectLocalRepository()
+        throws Exception
+    {
+        BuildProjectTaskExecutor buildProjectExecutor = (BuildProjectTaskExecutor) lookup( TaskExecutor.class,
+                                                                                           "build-agent" );
+
+        buildProjectExecutor.setBuildAgentBuildExecutorManager( buildAgentBuildExecutorManager );
+
+        buildProjectExecutor.setBuildAgentConfigurationService( buildAgentConfigurationService );
+
+        buildProjectExecutor.setBuildContextManager( buildContextManager );
+
+        buildProjectExecutor.setBuildAgentManager( buildAgentManager );
+
+        final BuildContext buildContext = createBuildContext();
+
+        final List<LocalRepository> localRepos = new ArrayList<LocalRepository>();
+
+        LocalRepository localRepo = createLocalRepository( "temp", "/tmp/.m2/repository", "default" );
+        localRepos.add( localRepo );
+
+        localRepo = createLocalRepository( "default", "/home/user/.m2/repository", "default" );
+        localRepos.add( localRepo );
+
+        final Map<String, String> masterBuildEnvironments = new HashMap<String, String>();
+        masterBuildEnvironments.put( "M2_HOME", "/tmp/apache-maven-2.2.1" );
+
+        final List<Installation> slaveBuildEnvironments = new ArrayList<Installation>();
+
+        final ContinuumAgentBuildExecutor executor = context.mock( ContinuumAgentBuildExecutor.class );
+        final File workingDir = new File( "/tmp/data/working-directory/project-test" );
+        final MavenProject project = new MavenProject();
+        final File outputFile = new File( "/tmp/data/build-output-directory/output.txt" );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( buildContextManager ).getBuildContext( 1 );
+                will( returnValue( buildContext ) );
+
+                one( buildAgentManager ).getEnvironments( 1, "maven2" );
+                will( returnValue( masterBuildEnvironments ) );
+
+                one( buildAgentConfigurationService ).getAvailableInstallations();
+                will( returnValue( slaveBuildEnvironments ) );
+
+                one( buildAgentConfigurationService ).getLocalRepositories();
+                will( returnValue( localRepos ) );
+
+                one( buildAgentManager ).shouldBuild( with( any( Map.class ) ) );
+                will( returnValue( true ) );
+
+                one( buildAgentBuildExecutorManager ).getBuildExecutor(
+                    ContinuumBuildExecutorConstants.MAVEN_TWO_BUILD_EXECUTOR );
+                will( returnValue( executor ) );
+
+                one( buildAgentConfigurationService ).getWorkingDirectory( 1 );
+                will( returnValue( workingDir ) );
+
+                one( executor ).getMavenProject( with( any( File.class ) ), with( any( BuildDefinition.class ) ) );
+                will( returnValue( project ) );
+
+                one( buildAgentManager ).startProjectBuild( 1 );
+
+                one( buildAgentConfigurationService ).getBuildOutputFile( 1 );
+                will( returnValue( outputFile ) );
+
+                one( buildAgentManager ).returnBuildResult( with( any( Map.class ) ) );
+
+                one( buildContextManager ).removeBuildContext( 1 );
+            }
+        } );
+
+        try
+        {
+            buildProjectExecutor.executeTask( createBuildProjectTask() );
+        }
+        catch ( Exception e )
+        {
+            fail( "An exception should not have been thrown!" );
+        }
+    }
+
+    public void testBuildProjectWithConfiguredInstallationsFromBuildAgent()
+        throws Exception
+    {
+        BuildProjectTaskExecutor buildProjectExecutor = (BuildProjectTaskExecutor) lookup( TaskExecutor.class,
+                                                                                           "build-agent" );
+
+        buildProjectExecutor.setBuildAgentBuildExecutorManager( buildAgentBuildExecutorManager );
+
+        buildProjectExecutor.setBuildAgentConfigurationService( buildAgentConfigurationService );
+
+        buildProjectExecutor.setBuildContextManager( buildContextManager );
+
+        buildProjectExecutor.setBuildAgentManager( buildAgentManager );
+
+        final BuildContext buildContext = createBuildContext();
+
+        final List<LocalRepository> localRepos = new ArrayList<LocalRepository>();
+
+        LocalRepository localRepo = createLocalRepository( "temp", "/tmp/.m2/repository", "default" );
+        localRepos.add( localRepo );
+
+        localRepo = createLocalRepository( "default", "/home/user/.m2/repository", "default" );
+        localRepos.add( localRepo );
+
+        final Map<String, String> masterBuildEnvironments = new HashMap<String, String>();
+        masterBuildEnvironments.put( "M2_HOME", "/tmp/apache-maven-2.2.1" );
+
+        final List<Installation> slaveBuildEnvironments = new ArrayList<Installation>();
+
+        Installation slaveBuildEnvironment = createInstallation( "M2_HOME", "/home/user/apache-maven-2.2.1" );
+        slaveBuildEnvironments.add( slaveBuildEnvironment );
+
+        slaveBuildEnvironment = createInstallation( "EXTRA_VAR", "/home/user/extra" );
+        slaveBuildEnvironments.add( slaveBuildEnvironment );
+
+        final ContinuumAgentBuildExecutor executor = context.mock( ContinuumAgentBuildExecutor.class );
+        final File workingDir = new File( "/tmp/data/working-directory/project-test" );
+        final MavenProject project = new MavenProject();
+        final File outputFile = new File( "/tmp/data/build-output-directory/output.txt" );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( buildContextManager ).getBuildContext( 1 );
+                will( returnValue( buildContext ) );
+
+                one( buildAgentManager ).getEnvironments( 1, "maven2" );
+                will( returnValue( masterBuildEnvironments ) );
+
+                one( buildAgentConfigurationService ).getAvailableInstallations();
+                will( returnValue( slaveBuildEnvironments ) );
+
+                one( buildAgentConfigurationService ).getLocalRepositories();
+                will( returnValue( localRepos ) );
+
+                one( buildAgentManager ).shouldBuild( with( any( Map.class ) ) );
+                will( returnValue( true ) );
+
+                one( buildAgentBuildExecutorManager ).getBuildExecutor(
+                    ContinuumBuildExecutorConstants.MAVEN_TWO_BUILD_EXECUTOR );
+                will( returnValue( executor ) );
+
+                one( buildAgentConfigurationService ).getWorkingDirectory( 1 );
+                will( returnValue( workingDir ) );
+
+                one( executor ).getMavenProject( with( any( File.class ) ), with( any( BuildDefinition.class ) ) );
+                will( returnValue( project ) );
+
+                one( buildAgentManager ).startProjectBuild( 1 );
+
+                one( buildAgentConfigurationService ).getBuildOutputFile( 1 );
+                will( returnValue( outputFile ) );
+
+                one( buildAgentManager ).returnBuildResult( with( any( Map.class ) ) );
+
+                one( buildContextManager ).removeBuildContext( 1 );
+            }
+        } );
+
+        try
+        {
+            buildProjectExecutor.executeTask( createBuildProjectTask() );
+
+            Map<String, String> environments = (Map<String, String>) buildContext.getActionContext().get(
+                ContinuumBuildAgentUtil.KEY_ENVIRONMENTS );
+            assertEquals( 2, environments.size() );
+            assertTrue( environments.containsKey( "M2_HOME" ) );
+            assertTrue( environments.containsKey( "EXTRA_VAR" ) );
+            // shows that build agent's environment variables overwrites Continuum Master's environment variables
+            assertEquals( "/home/user/apache-maven-2.2.1", environments.get( "M2_HOME" ) );
+            assertEquals( "/home/user/extra", environments.get( "EXTRA_VAR" ) );
+        }
+        catch ( Exception e )
+        {
+            fail( "An exception should not have been thrown!" );
+        }
+    }
+
+    public void testBuildProjectWithNoConfiguredInstallationsFromBuildAgent()
+        throws Exception
+    {
+        BuildProjectTaskExecutor buildProjectExecutor = (BuildProjectTaskExecutor) lookup( TaskExecutor.class,
+                                                                                           "build-agent" );
+
+        buildProjectExecutor.setBuildAgentBuildExecutorManager( buildAgentBuildExecutorManager );
+
+        buildProjectExecutor.setBuildAgentConfigurationService( buildAgentConfigurationService );
+
+        buildProjectExecutor.setBuildContextManager( buildContextManager );
+
+        buildProjectExecutor.setBuildAgentManager( buildAgentManager );
+
+        final BuildContext buildContext = createBuildContext();
+
+        final List<LocalRepository> localRepos = new ArrayList<LocalRepository>();
+
+        LocalRepository localRepo = createLocalRepository( "temp", "/tmp/.m2/repository", "default" );
+        localRepos.add( localRepo );
+
+        localRepo = createLocalRepository( "default", "/home/user/.m2/repository", "default" );
+        localRepos.add( localRepo );
+
+        final Map<String, String> masterBuildEnvironments = new HashMap<String, String>();
+        masterBuildEnvironments.put( "M2_HOME", "/tmp/apache-maven-2.2.1" );
+
+        final List<Installation> slaveBuildEnvironments = new ArrayList<Installation>();
+
+        final ContinuumAgentBuildExecutor executor = context.mock( ContinuumAgentBuildExecutor.class );
+        final File workingDir = new File( "/tmp/data/working-directory/project-test" );
+        final MavenProject project = new MavenProject();
+        final File outputFile = new File( "/tmp/data/build-output-directory/output.txt" );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( buildContextManager ).getBuildContext( 1 );
+                will( returnValue( buildContext ) );
+
+                one( buildAgentManager ).getEnvironments( 1, "maven2" );
+                will( returnValue( masterBuildEnvironments ) );
+
+                one( buildAgentConfigurationService ).getAvailableInstallations();
+                will( returnValue( slaveBuildEnvironments ) );
+
+                one( buildAgentConfigurationService ).getLocalRepositories();
+                will( returnValue( localRepos ) );
+
+                one( buildAgentManager ).shouldBuild( with( any( Map.class ) ) );
+                will( returnValue( true ) );
+
+                one( buildAgentBuildExecutorManager ).getBuildExecutor(
+                    ContinuumBuildExecutorConstants.MAVEN_TWO_BUILD_EXECUTOR );
+                will( returnValue( executor ) );
+
+                one( buildAgentConfigurationService ).getWorkingDirectory( 1 );
+                will( returnValue( workingDir ) );
+
+                one( executor ).getMavenProject( with( any( File.class ) ), with( any( BuildDefinition.class ) ) );
+                will( returnValue( project ) );
+
+                one( buildAgentManager ).startProjectBuild( 1 );
+
+                one( buildAgentConfigurationService ).getBuildOutputFile( 1 );
+                will( returnValue( outputFile ) );
+
+                one( buildAgentManager ).returnBuildResult( with( any( Map.class ) ) );
+
+                one( buildContextManager ).removeBuildContext( 1 );
+            }
+        } );
+
+        try
+        {
+            buildProjectExecutor.executeTask( createBuildProjectTask() );
+
+            Map<String, String> environments = (Map<String, String>) buildContext.getActionContext().get(
+                ContinuumBuildAgentUtil.KEY_ENVIRONMENTS );
+            assertEquals( 1, environments.size() );
+            assertTrue( environments.containsKey( "M2_HOME" ) );
+            assertEquals( "/tmp/apache-maven-2.2.1", environments.get( "M2_HOME" ) );
+        }
+        catch ( Exception e )
+        {
+            fail( "An exception should not have been thrown!" );
+        }
+    }
+
+    private BuildProjectTask createBuildProjectTask()
+    {
+        BuildProjectTask task = new BuildProjectTask( 1, 1, new BuildTrigger( 1 ), "Test Project",
+                                                      "Default Build Definition", new ScmResult(), 1 );
+        return task;
+    }
+
+    private BuildContext createBuildContext()
+    {
+        BuildContext context = new BuildContext();
+        context.setProjectId( 1 );
+        context.setProjectVersion( "1.0-SNAPSHOT" );
+        context.setBuildDefinitionId( 1 );
+        context.setBuildFile( "pom.xml" );
+        context.setExecutorId( ContinuumBuildExecutorConstants.MAVEN_TWO_BUILD_EXECUTOR );
+        context.setGoals( "clean intall" );
+        context.setArguments( "--batch --non-recursive" );
+        context.setScmUrl( "scm:svn:http://svn.example.com/repos/dummy/trunk" );
+        context.setScmUsername( "" );
+        context.setScmPassword( "" );
+        context.setBuildFresh( false );
+        context.setProjectGroupId( 1 );
+        context.setProjectGroupName( "Test Project Group" );
+        context.setScmRootAddress( "scm:svn:http://svn.example.com/repos/dummy" );
+        context.setScmRootId( 1 );
+        context.setProjectName( "Test Project" );
+        context.setProjectState( 1 );
+        context.setTrigger( 1 );
+        context.setUsername( "" );
+        context.setLocalRepository( "default" );
+        context.setBuildNumber( 1 );
+
+        ScmResult scmResult = new ScmResult();
+        scmResult.setSuccess( true );
+
+        context.setScmResult( scmResult );
+        context.setLatestUpdateDate( Calendar.getInstance().getTime() );
+        context.setBuildAgentUrl( "http://localhost:8181/continuum-buildagent/xmlrpc" );
+        context.setMaxExecutionTime( 7200 );
+        context.setBuildDefinitionLabel( "Default Build Definition" );
+        context.setScmTag( "scm:svn:http://svn.example.com/repos/dummy/tags" );
+
+        return context;
+    }
+
+    private LocalRepository createLocalRepository( String name, String locataion, String layout )
+    {
+        LocalRepository localRepository = new LocalRepository();
+        localRepository.setName( name );
+        localRepository.setLocation( locataion );
+        localRepository.setLayout( layout );
+        return localRepository;
+    }
+
+    private Installation createInstallation( String varName, String varValue )
+    {
+        Installation installation = new Installation();
+        installation.setVarName( varName );
+        installation.setVarValue( varValue );
+        return installation;
+    }
+}
\ No newline at end of file
diff --git a/continuum-buildagent/continuum-buildagent-core/src/test/resources/buildagent-config/continuum-buildagent-edit.xml b/continuum-buildagent/continuum-buildagent-core/src/test/resources/buildagent-config/continuum-buildagent-edit.xml
new file mode 100644
index 0000000..d2d8005
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/test/resources/buildagent-config/continuum-buildagent-edit.xml
@@ -0,0 +1,33 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+  ~ 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.
+  -->
+
+<continuum-buildagent-configuration>
+  <continuumServerUrl>http://localhost:9595/continuum/master-xmlrpc</continuumServerUrl>
+  <buildOutputDirectory>/tmp/data/build-output-directory</buildOutputDirectory>
+  <workingDirectory>/tmp/data/working-directory</workingDirectory>
+  <installations>
+    <installation>
+      <name>Maven 2.2.1 Installation</name>
+      <type>Tool</type>
+      <varName>M2_HOME</varName>
+      <varValue>/tmp/apache-maven-2.2.1</varValue>
+    </installation>
+  </installations>
+</continuum-buildagent-configuration>
\ No newline at end of file
diff --git a/continuum-buildagent/continuum-buildagent-core/src/test/resources/buildagent-config/continuum-buildagent.xml b/continuum-buildagent/continuum-buildagent-core/src/test/resources/buildagent-config/continuum-buildagent.xml
new file mode 100644
index 0000000..3028c8c
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/test/resources/buildagent-config/continuum-buildagent.xml
@@ -0,0 +1,40 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+  ~ 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.
+  -->
+
+<continuum-buildagent-configuration>
+  <continuumServerUrl>http://localhost:9595/continuum/master-xmlrpc</continuumServerUrl>
+  <buildOutputDirectory>/tmp/data/build-output-directory</buildOutputDirectory>
+  <workingDirectory>/tmp/data/working-directory</workingDirectory>
+  <installations>
+    <installation>
+      <name>Maven 2.2.1 Installation</name>
+      <type>Tool</type>
+      <varName>M2_HOME</varName>
+      <varValue>/tmp/apache-maven-2.2.1</varValue>
+    </installation>
+  </installations>
+  <localRepositories>
+    <localRepository>
+      <name>default</name>
+      <location>/tmp/.m2/repository</location>
+      <layout>default</layout>
+    </localRepository>
+  </localRepositories>
+</continuum-buildagent-configuration>
diff --git a/continuum-buildagent/continuum-buildagent-core/src/test/resources/org/apache/continuum/buildagent/manager/BuildAgentReleaseManagerTest.xml b/continuum-buildagent/continuum-buildagent-core/src/test/resources/org/apache/continuum/buildagent/manager/BuildAgentReleaseManagerTest.xml
new file mode 100644
index 0000000..0d41623
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/test/resources/org/apache/continuum/buildagent/manager/BuildAgentReleaseManagerTest.xml
@@ -0,0 +1,52 @@
+<!--
+  ~ 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.
+  -->
+
+<plexus>
+  <components>
+    <component>
+      <role>org.apache.maven.continuum.release.ContinuumReleaseManager</role>
+      <role-hint>default</role-hint>
+      <implementation>org.apache.continuum.buildagent.stubs.ContinuumReleaseManagerStub</implementation>
+      <requirements>
+        <requirement>
+          <role>org.apache.maven.shared.release.config.ReleaseDescriptorStore</role>
+          <role-hint>continuum-release-properties</role-hint>
+        </requirement>
+        <requirement>
+          <role>org.codehaus.plexus.taskqueue.TaskQueue</role>
+          <role-hint>prepare-release</role-hint>
+          <field-name>prepareReleaseQueue</field-name>
+        </requirement>
+        <requirement>
+          <role>org.codehaus.plexus.taskqueue.TaskQueue</role>
+          <role-hint>perform-release</role-hint>
+          <field-name>performReleaseQueue</field-name>
+        </requirement>
+        <requirement>
+          <role>org.codehaus.plexus.taskqueue.TaskQueue</role>
+          <role-hint>rollback-release</role-hint>
+          <field-name>rollbackReleaseQueue</field-name>
+        </requirement>
+        <requirement>
+          <role>org.apache.maven.scm.manager.ScmManager</role>
+        </requirement>
+      </requirements>
+    </component>
+  </components>
+</plexus>
\ No newline at end of file
diff --git a/continuum-buildagent/continuum-buildagent-core/src/test/resources/org/apache/continuum/buildagent/taskqueue/execution/BuildProjectTaskExecutorTest.xml b/continuum-buildagent/continuum-buildagent-core/src/test/resources/org/apache/continuum/buildagent/taskqueue/execution/BuildProjectTaskExecutorTest.xml
new file mode 100644
index 0000000..5310672
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/test/resources/org/apache/continuum/buildagent/taskqueue/execution/BuildProjectTaskExecutorTest.xml
@@ -0,0 +1,33 @@
+<!--
+  ~ 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.
+  -->
+
+<plexus>
+  <components>
+    <component>
+      <role>org.codehaus.plexus.action.Action</role>
+      <role-hint>update-project-from-agent-working-directory</role-hint>
+      <implementation>org.apache.continuum.buildagent.stubs.ContinuumActionStub</implementation>
+    </component>
+    <component>
+      <role>org.codehaus.plexus.action.Action</role>
+      <role-hint>execute-agent-builder</role-hint>
+      <implementation>org.apache.continuum.buildagent.stubs.ContinuumActionStub</implementation>
+    </component>
+  </components>
+</plexus>
\ No newline at end of file
diff --git a/continuum-buildagent/continuum-buildagent-core/src/test/test-projects/maven3-metadata/pom.xml b/continuum-buildagent/continuum-buildagent-core/src/test/test-projects/maven3-metadata/pom.xml
new file mode 100644
index 0000000..7454f92
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/test/test-projects/maven3-metadata/pom.xml
@@ -0,0 +1,31 @@
+<!--
+  ~ 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.
+  -->
+
+<project>
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>test</groupId>
+    <artifactId>test-parent</artifactId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>maven3-metadata</artifactId>
+  <scm>
+    <connection>scm:local:${basedir}/src/test/test-projects/maven3-metadata</connection>
+  </scm>
+</project>
\ No newline at end of file
diff --git a/continuum-buildagent/continuum-buildagent-core/src/test/test-repo/test/test-parent/1.0-SNAPSHOT/maven-metadata.xml b/continuum-buildagent/continuum-buildagent-core/src/test/test-repo/test/test-parent/1.0-SNAPSHOT/maven-metadata.xml
new file mode 100644
index 0000000..8790c12
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/test/test-repo/test/test-parent/1.0-SNAPSHOT/maven-metadata.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata modelVersion="1.1.0">
+  <groupId>test</groupId>
+  <artifactId>test-parent</artifactId>
+  <version>1.0-SNAPSHOT</version>
+  <versioning>
+    <snapshot>
+      <timestamp>20140514.061235</timestamp>
+      <buildNumber>2</buildNumber>
+    </snapshot>
+    <lastUpdated>20140514061235</lastUpdated>
+    <snapshotVersions>
+      <snapshotVersion>
+        <extension>pom</extension>
+        <value>1.0-20140514.061235-2</value>
+        <updated>20140514061235</updated>
+      </snapshotVersion>
+    </snapshotVersions>
+  </versioning>
+</metadata>
diff --git a/continuum-buildagent/continuum-buildagent-core/src/test/test-repo/test/test-parent/1.0-SNAPSHOT/maven-metadata.xml.sha1 b/continuum-buildagent/continuum-buildagent-core/src/test/test-repo/test/test-parent/1.0-SNAPSHOT/maven-metadata.xml.sha1
new file mode 100644
index 0000000..50379e2
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/test/test-repo/test/test-parent/1.0-SNAPSHOT/maven-metadata.xml.sha1
@@ -0,0 +1 @@
+2d919f70e0972c9f96a1a66fb5b771e560605a6c
\ No newline at end of file
diff --git a/continuum-buildagent/continuum-buildagent-core/src/test/test-repo/test/test-parent/1.0-SNAPSHOT/test-parent-1.0-20140514.061235-2.pom b/continuum-buildagent/continuum-buildagent-core/src/test/test-repo/test/test-parent/1.0-SNAPSHOT/test-parent-1.0-20140514.061235-2.pom
new file mode 100644
index 0000000..abc1eb5
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/test/test-repo/test/test-parent/1.0-SNAPSHOT/test-parent-1.0-20140514.061235-2.pom
@@ -0,0 +1,11 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>test</groupId>
+  <artifactId>test-parent</artifactId>
+  <version>1.0-SNAPSHOT</version>
+  <packaging>pom</packaging>
+
+  <name>test-parent</name>
+</project>
diff --git a/continuum-buildagent/continuum-buildagent-core/src/test/test-repo/test/test-parent/1.0-SNAPSHOT/test-parent-1.0-20140514.061235-2.pom.sha1 b/continuum-buildagent/continuum-buildagent-core/src/test/test-repo/test/test-parent/1.0-SNAPSHOT/test-parent-1.0-20140514.061235-2.pom.sha1
new file mode 100644
index 0000000..936444f
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-core/src/test/test-repo/test/test-parent/1.0-SNAPSHOT/test-parent-1.0-20140514.061235-2.pom.sha1
@@ -0,0 +1 @@
+93129798c66a60dbbb279d99bda2d53d505f5772
\ No newline at end of file
diff --git a/continuum-buildagent/continuum-buildagent-jetty/pom.xml b/continuum-buildagent/continuum-buildagent-jetty/pom.xml
new file mode 100644
index 0000000..509c0f1
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-jetty/pom.xml
@@ -0,0 +1,205 @@
+<?xml version='1.0' encoding='UTF-8'?>
+
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <artifactId>continuum-buildagent</artifactId>
+    <groupId>org.apache.continuum</groupId>
+    <version>1.4.3</version>
+  </parent>
+  <artifactId>continuum-buildagent-jetty</artifactId>
+  <packaging>pom</packaging>
+  <name>Apache Continuum Build Agent</name>
+  <dependencies>
+    <dependency>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-server</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-buildagent-webapp</artifactId>
+      <type>war</type>
+    </dependency>
+    <!-- Runtime dependencies that need to be included in the generated binaries -->
+    <dependency>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-start</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-deploy</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-jndi</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-jsp</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>appassembler-maven-plugin</artifactId>
+        <configuration>
+          <daemons>
+            <daemon>
+              <id>continuum-buildagent</id>
+              <mainClass>org.eclipse.jetty.start.Main</mainClass>
+              <commandLineArguments>
+                <commandLineArgument>conf/jetty.xml</commandLineArgument>
+                <commandLineArgument>conf/jetty-deploy.xml</commandLineArgument>
+                <commandLineArgument>conf/jetty-contexts.xml</commandLineArgument>
+                <commandLineArgument>conf/jetty-requestlog.xml</commandLineArgument>
+              </commandLineArguments>
+              <platforms>
+                <platform>jsw</platform>
+              </platforms>
+              <generatorConfigurations>
+                <generatorConfiguration>
+                  <generator>jsw</generator>
+                  <configuration>
+                    <property>
+                      <name>wrapper.console.loglevel</name>
+                      <value>INFO</value>
+                    </property>
+                    <property>
+                      <name>wrapper.java.additional.1.stripquotes</name>
+                      <value>TRUE</value>
+                    </property>
+                    <property>
+                      <name>set.default.REPO_DIR</name>
+                      <value>lib</value>
+                    </property>
+                    <property>
+                      <name>wrapper.logfile</name>
+                      <value>%CONTINUUM_BUILDAGENT_BASE%/logs/wrapper.log</value>
+                    </property>
+                    <property>
+                      <name>app.base.envvar</name>
+                      <value>CONTINUUM_BUILDAGENT_BASE</value>
+                    </property>
+                    <property>
+                      <name>wrapper.on_exit.default</name>
+                      <value>RESTART</value>
+                    </property>
+                    <property>
+                      <name>wrapper.on_exit.0</name>
+                      <value>SHUTDOWN</value>
+                    </property>
+                    <property>
+                      <name>wrapper.restart.delay</name>
+                      <value>30</value>
+                    </property>
+                  </configuration>
+                  <includes>
+                    <include>linux-x86-32</include>
+                    <include>linux-x86-64</include>
+                    <include>macosx-x86-universal-32</include>
+                    <include>solaris-x86-32</include>
+                    <include>solaris-sparc-32</include>
+                    <include>solaris-sparc-64</include>
+                    <include>windows-x86-32</include>
+                  </includes>
+                </generatorConfiguration>
+              </generatorConfigurations>
+              <jvmSettings>
+                <systemProperties>
+                  <systemProperty>appserver.home=.</systemProperty>
+                  <systemProperty>appserver.base=%CONTINUUM_BUILDAGENT_BASE%</systemProperty>
+                  <systemProperty>jetty.logs=%CONTINUUM_BUILDAGENT_BASE%/logs</systemProperty>
+                  <systemProperty>java.io.tmpdir=%CONTINUUM_BUILDAGENT_BASE%/tmp</systemProperty>
+                </systemProperties>
+              </jvmSettings>
+            </daemon>
+          </daemons>
+          <repoPath>lib</repoPath>
+          <repositoryLayout>flat</repositoryLayout>
+          <assembleDirectory>target/generated-resources/appassembler/jsw/continuum-buildagent</assembleDirectory>
+        </configuration>
+        <executions>
+          <execution>
+            <goals>
+              <goal>generate-daemons</goal>
+              <goal>create-repository</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <version>2.4</version>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>single</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <descriptor>src/main/assembly/bin.xml</descriptor>
+          <finalName>apache-continuum-buildagent-${project.version}</finalName>
+        </configuration>
+      </plugin>
+      <plugin>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>config</id>
+            <phase>process-resources</phase>
+            <configuration>
+              <tasks>
+                <copy todir="target/generated-resources/appassembler/jsw/continuum-buildagent/conf">
+                  <fileset dir="src/main/conf" />
+                </copy>
+                <mkdir dir="target/generated-resources/appassembler/jsw/continuum-buildagent/logs" />
+              </tasks>
+            </configuration>
+            <goals>
+              <goal>run</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.rat</groupId>
+          <artifactId>apache-rat-plugin</artifactId>
+          <configuration>
+            <excludes>
+              <exclude>src/main/conf/webdefault.xml</exclude>
+            </excludes>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+</project>
diff --git a/continuum-buildagent/continuum-buildagent-jetty/src/main/assembly/bin.xml b/continuum-buildagent/continuum-buildagent-jetty/src/main/assembly/bin.xml
new file mode 100644
index 0000000..e6b8231
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-jetty/src/main/assembly/bin.xml
@@ -0,0 +1,121 @@
+<!--
+  ~ 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.
+  -->
+
+<assembly>
+  <id>bin</id>
+  <formats>
+    <format>tar.gz</format>
+    <format>zip</format>
+  </formats>
+  <fileSets>
+    <fileSet>
+      <directory>target/generated-resources/appassembler/jsw/continuum-buildagent/apps</directory>
+      <outputDirectory>apps</outputDirectory>
+    </fileSet>
+    <fileSet>
+      <directory>target/generated-resources/appassembler/jsw/continuum-buildagent/conf</directory>
+      <outputDirectory>conf</outputDirectory>
+    </fileSet>
+    <fileSet>
+      <directory>target/generated-resources/appassembler/jsw/continuum-buildagent/lib</directory>
+      <outputDirectory>lib</outputDirectory>
+      <excludes>
+        <exclude>continuum-*</exclude>
+        <exclude>maven-metadata-appassembler.xml</exclude>
+      </excludes>
+      <fileMode>0755</fileMode>
+      <directoryMode>0755</directoryMode>
+    </fileSet>
+    <fileSet>
+      <directory>target/generated-resources/appassembler/jsw/continuum-buildagent/logs</directory>
+      <outputDirectory>logs</outputDirectory>
+    </fileSet>
+    <fileSet>
+      <directory>target/generated-resources/appassembler/jsw/continuum-buildagent/bin</directory>
+      <outputDirectory>bin</outputDirectory>
+      <includes>
+        <include>continuum-buildagent</include>
+      </includes>
+      <fileMode>0755</fileMode>
+      <lineEnding>unix</lineEnding>
+    </fileSet>
+    <fileSet>
+      <directory>target/generated-resources/appassembler/jsw/continuum-buildagent/bin</directory>
+      <outputDirectory>bin</outputDirectory>
+      <includes>
+        <include>wrapper-linux-x86-32</include>
+        <include>wrapper-linux-x86-64</include>
+        <include>wrapper-macosx-universal-32</include>
+        <include>wrapper-solaris-x86-32</include>
+        <include>wrapper-solaris-sparc-32</include>
+        <include>wrapper-solaris-sparc-64</include>
+      </includes>
+      <fileMode>0755</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>target/generated-resources/appassembler/jsw/continuum-buildagent/bin</directory>
+      <outputDirectory>bin</outputDirectory>
+      <includes>
+        <include>continuum-buildagent.bat</include>
+      </includes>
+      <fileMode>0755</fileMode>
+      <lineEnding>dos</lineEnding>
+    </fileSet>
+    <fileSet>
+      <directory>target/generated-resources/appassembler/jsw/continuum-buildagent/bin</directory>
+      <outputDirectory>bin</outputDirectory>
+      <includes>
+        <include>wrapper-windows-x86-32.exe</include>
+      </includes>
+      <fileMode>0755</fileMode>
+    </fileSet>
+    <fileSet>
+      <directory>target/maven-shared-archive-resources/META-INF/</directory>
+      <outputDirectory>/</outputDirectory>
+      <includes>
+        <include>NOTICE</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>src/main/resources/</directory>
+      <outputDirectory>/</outputDirectory>
+      <includes>
+        <include>LICENSE</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>src/main/tmp/</directory>
+      <outputDirectory>/tmp</outputDirectory>
+    </fileSet>
+    <fileSet>
+      <directory>src/main/contexts/</directory>
+      <outputDirectory>/contexts</outputDirectory>
+    </fileSet>
+  </fileSets>
+  <dependencySets>
+    <dependencySet>
+      <unpack>true</unpack>
+      <outputDirectory>apps/continuum-buildagent</outputDirectory>
+      <includes>
+        <include>org.apache.continuum:continuum-buildagent-webapp</include>
+      </includes>
+    </dependencySet>
+  </dependencySets>
+</assembly>
+
diff --git a/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/continuum-buildagent.xml b/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/continuum-buildagent.xml
new file mode 100644
index 0000000..b30e145
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/continuum-buildagent.xml
@@ -0,0 +1,26 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+  ~ 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.
+  -->
+
+<continuum-buildagent-configuration>
+  <continuumServerUrl>http://localhost:8080/continuum/master-xmlrpc</continuumServerUrl>
+  <buildOutputDirectory>data/build-output-directory</buildOutputDirectory>
+  <workingDirectory>data/working-directory</workingDirectory>
+  <sharedSecretPassword></sharedSecretPassword>
+</continuum-buildagent-configuration>
diff --git a/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/jetty-contexts.xml b/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/jetty-contexts.xml
new file mode 100644
index 0000000..5d6aa96
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/jetty-contexts.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<!--
+  ~ 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.
+  -->
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
+
+<!-- =============================================================== -->
+<!-- Add a ContextProvider to the deployment manager                 -->
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<!-- This scans the webapps directory for war files and directories  -->
+<!-- to deploy.                                                      -->
+<!-- This configuration must be used with jetty-deploy.xml, which    -->
+<!-- creates the deployment manager instance                         -->
+<!-- =============================================================== -->
+<Configure id="Server" class="org.eclipse.jetty.server.Server">
+        <Ref id="DeploymentManager">
+          <Call name="addAppProvider">
+            <Arg>
+              <New class="org.eclipse.jetty.deploy.providers.ContextProvider">
+                <Set name="monitoredDirName"><Property name="appserver.base" default="." />/contexts</Set>
+                <Set name="scanInterval">1</Set>
+              </New>
+            </Arg>
+          </Call>
+        </Ref>
+</Configure>
diff --git a/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/jetty-deploy.xml b/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/jetty-deploy.xml
new file mode 100644
index 0000000..80a451f
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/jetty-deploy.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0"?>
+<!--
+  ~ 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.
+  -->
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
+
+<!-- =============================================================== -->
+<!-- Create the deployment manager                                   -->
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<!-- The deplyment manager handles the lifecycle of deploying web    -->
+<!-- applications. Apps are provided by instances of the             -->
+<!-- AppProvider interface.  Typically these are provided by         -->
+<!-- one or more of:                                                 -->
+<!--   jetty-webapps.xml       - monitors webapps for wars and dirs  -->
+<!--   jetty-contexts.xml      - monitors contexts for context xml   -->
+<!--   jetty-templates.xml     - monitors contexts and templates     -->
+<!-- =============================================================== -->
+<Configure id="Server" class="org.eclipse.jetty.server.Server">
+
+    <Call name="addBean">
+      <Arg>
+        <New id="DeploymentManager" class="org.eclipse.jetty.deploy.DeploymentManager">
+          <Set name="contexts">
+            <Ref id="Contexts" />
+          </Set>
+          <Call name="setContextAttribute">
+            <Arg>org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern</Arg>
+            <Arg>.*/servlet-api-[^/]*\.jar$</Arg>
+          </Call>
+          
+          
+          <!-- Add a customize step to the deployment lifecycle -->
+          <!-- uncomment and replace DebugBinding with your extended AppLifeCycle.Binding class 
+          <Call name="insertLifeCycleNode">
+            <Arg>deployed</Arg>
+            <Arg>starting</Arg>
+            <Arg>customise</Arg>
+          </Call>
+          <Call name="addLifeCycleBinding">
+            <Arg>
+              <New class="org.eclipse.jetty.deploy.bindings.DebugBinding">
+                <Arg>customise</Arg>
+              </New>
+            </Arg>
+          </Call>
+          -->
+          
+        </New>
+      </Arg>
+    </Call>
+</Configure>
diff --git a/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/jetty-requestlog.xml b/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/jetty-requestlog.xml
new file mode 100644
index 0000000..65ec625
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/jetty-requestlog.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+<!--
+  ~ 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.
+  -->
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
+
+<!-- =============================================================== -->
+<!-- Configure the Jetty Request Log                                 -->
+<!-- =============================================================== -->
+
+<Configure id="Server" class="org.eclipse.jetty.server.Server">
+
+    <!-- =========================================================== -->
+    <!-- Configure Request Log                                       -->
+    <!-- =========================================================== -->
+    <Ref id="Handlers">
+      <Call name="addHandler">
+        <Arg>
+          <New id="RequestLog" class="org.eclipse.jetty.server.handler.RequestLogHandler">
+	    <Set name="requestLog">
+	      <New id="RequestLogImpl" class="org.eclipse.jetty.server.NCSARequestLog">
+		<Set name="filename"><Property name="jetty.logs" default="./logs"/>/yyyy_mm_dd.request.log</Set>
+		<Set name="filenameDateFormat">yyyy_MM_dd</Set>
+		<Set name="retainDays">90</Set>
+		<Set name="append">true</Set>
+		<Set name="extended">false</Set>
+		<Set name="logCookies">false</Set>
+		<Set name="LogTimeZone">GMT</Set>
+	      </New>
+	    </Set>
+	  </New>
+        </Arg>
+      </Call>
+    </Ref>
+
+</Configure>
diff --git a/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/jetty.xml b/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/jetty.xml
new file mode 100644
index 0000000..45fa019
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/jetty.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0"?>
+<!--
+  ~ 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.
+  -->
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
+
+<!-- =============================================================== -->
+<!-- Configure the Jetty Server                                      -->
+<!--                                                                 -->
+<!-- Documentation of this file format can be found at:              -->
+<!-- http://wiki.eclipse.org/Jetty/Reference/jetty.xml_syntax        -->
+<!--                                                                 -->
+<!-- Additional configuration files are available in $JETTY_HOME/etc -->
+<!-- and can be mixed in.  For example:                              -->
+<!--   java -jar start.jar etc/jetty-ssl.xml                         -->
+<!--                                                                 -->
+<!-- See start.ini file for the default configuraton files           -->
+<!-- =============================================================== -->
+
+
+<Configure id="Server" class="org.eclipse.jetty.server.Server">
+
+    <!-- =========================================================== -->
+    <!-- Server Thread Pool                                          -->
+    <!-- =========================================================== -->
+    <Set name="ThreadPool">
+      <!-- Default queued blocking threadpool -->
+      <New class="org.eclipse.jetty.util.thread.QueuedThreadPool">
+        <Set name="minThreads">10</Set>
+        <Set name="maxThreads">200</Set>
+        <Set name="detailedDump">false</Set>
+      </New>
+    </Set>
+
+    <!-- =========================================================== -->
+    <!-- Set connectors                                              -->
+    <!-- =========================================================== -->
+
+    <Call name="addConnector">
+      <Arg>
+          <New class="org.eclipse.jetty.server.nio.SelectChannelConnector">
+            <Set name="host"><Property name="jetty.host" /></Set>
+            <Set name="port"><Property name="jetty.port" default="8181"/></Set>
+            <Set name="maxIdleTime">300000</Set>
+            <Set name="Acceptors">2</Set>
+            <Set name="statsOn">false</Set>
+            <Set name="confidentialPort">8443</Set>
+	    <Set name="lowResourcesConnections">20000</Set>
+	    <Set name="lowResourcesMaxIdleTime">5000</Set>
+          </New>
+      </Arg>
+    </Call>
+
+    <!-- =========================================================== -->
+    <!-- Set handler Collection Structure                            --> 
+    <!-- =========================================================== -->
+    <Set name="handler">
+      <New id="Handlers" class="org.eclipse.jetty.server.handler.HandlerCollection">
+        <Set name="handlers">
+         <Array type="org.eclipse.jetty.server.Handler">
+           <Item>
+             <New id="Contexts" class="org.eclipse.jetty.server.handler.ContextHandlerCollection"/>
+           </Item>
+           <Item>
+             <New id="DefaultHandler" class="org.eclipse.jetty.server.handler.DefaultHandler"/>
+           </Item>
+         </Array>
+        </Set>
+      </New>
+    </Set>
+
+    <!-- =========================================================== -->
+    <!-- extra options                                               -->
+    <!-- =========================================================== -->
+    <Set name="stopAtShutdown">true</Set>
+    <Set name="sendServerVersion">true</Set>
+    <Set name="sendDateHeader">true</Set>
+    <Set name="gracefulShutdown">1000</Set>
+    <Set name="dumpAfterStart">false</Set>
+    <Set name="dumpBeforeStop">false</Set>
+
+</Configure>
diff --git a/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/shared.xml b/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/shared.xml
new file mode 100644
index 0000000..0240149
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/shared.xml
@@ -0,0 +1,21 @@
+<?xml version='1.0' encoding='UTF-8'?>
+
+<!--
+  ~ 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.
+  -->
+<configuration/>
diff --git a/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/webdefault.xml b/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/webdefault.xml
new file mode 100644
index 0000000..213138b
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/webdefault.xml
@@ -0,0 +1,527 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+  <!-- ===================================================================== -->
+  <!-- This file contains the default descriptor for web applications.       -->
+  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+  <!-- The intent of this descriptor is to include jetty specific or common  -->
+  <!-- configuration for all webapps.   If a context has a webdefault.xml    -->
+  <!-- descriptor, it is applied before the contexts own web.xml file        -->
+  <!--                                                                       -->
+  <!-- A context may be assigned a default descriptor by:                    -->
+  <!--  + Calling WebApplicationContext.setDefaultsDescriptor                -->
+  <!--  + Passed an arg to addWebApplications                                -->
+  <!--                                                                       -->
+  <!-- This file is used both as the resource within the jetty.jar (which is -->
+  <!-- used as the default if no explicit defaults descriptor is set) and it -->
+  <!-- is copied to the etc directory of the Jetty distro and explicitly     -->
+  <!-- by the jetty.xml file.                                                -->
+  <!--                                                                       -->
+  <!-- ===================================================================== -->
+<web-app
+  xmlns="http://java.sun.com/xml/ns/javaee"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+  metadata-complete="true"
+  version="2.5"
+>
+
+  <description>
+    Default web.xml file.  
+    This file is applied to a Web application before it's own WEB_INF/web.xml file
+  </description>
+
+  <!-- ==================================================================== -->
+  <!-- Removes static references to beans from javax.el.BeanELResolver to   -->
+  <!-- ensure webapp classloader can be released on undeploy                -->
+  <!-- ==================================================================== -->
+  <listener>
+   <listener-class>org.eclipse.jetty.servlet.listener.ELContextCleaner</listener-class>
+  </listener>
+  
+  <!-- ==================================================================== -->
+  <!-- Removes static cache of Methods from java.beans.Introspector to      -->
+  <!-- ensure webapp classloader can be released on undeploy                -->
+  <!-- ==================================================================== -->  
+  <listener>
+   <listener-class>org.eclipse.jetty.servlet.listener.IntrospectorCleaner</listener-class>
+  </listener>
+  
+
+  <!-- ==================================================================== -->
+  <!-- Context params to control Session Cookies                            -->
+  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
+  <!--
+    UNCOMMENT TO ACTIVATE <context-param> <param-name>org.eclipse.jetty.servlet.SessionDomain</param-name> <param-value>127.0.0.1</param-value> </context-param> <context-param>
+    <param-name>org.eclipse.jetty.servlet.SessionPath</param-name> <param-value>/</param-value> </context-param> <context-param> <param-name>org.eclipse.jetty.servlet.MaxAge</param-name>
+    <param-value>-1</param-value> </context-param>
+  -->
+
+  <!-- ==================================================================== -->
+  <!-- The default servlet.                                                 -->
+  <!-- This servlet, normally mapped to /, provides the handling for static -->
+  <!-- content, OPTIONS and TRACE methods for the context.                  -->
+  <!-- The following initParameters are supported:                          -->
+  <!--  
+ *  acceptRanges      If true, range requests and responses are
+ *                    supported
+ *
+ *  dirAllowed        If true, directory listings are returned if no
+ *                    welcome file is found. Else 403 Forbidden.
+ *
+ *  welcomeServlets   If true, attempt to dispatch to welcome files
+ *                    that are servlets, but only after no matching static
+ *                    resources could be found. If false, then a welcome
+ *                    file must exist on disk. If "exact", then exact
+ *                    servlet matches are supported without an existing file.
+ *                    Default is true.
+ *
+ *                    This must be false if you want directory listings,
+ *                    but have index.jsp in your welcome file list.
+ *
+ *  redirectWelcome   If true, welcome files are redirected rather than
+ *                    forwarded to.
+ *
+ *  gzip              If set to true, then static content will be served as
+ *                    gzip content encoded if a matching resource is
+ *                    found ending with ".gz"
+ *
+ *  resourceBase      Set to replace the context resource base
+ *
+ *  resourceCache     If set, this is a context attribute name, which the servlet 
+ *                    will use to look for a shared ResourceCache instance. 
+ *                        
+ *  relativeResourceBase
+ *                    Set with a pathname relative to the base of the
+ *                    servlet context root. Useful for only serving static content out
+ *                    of only specific subdirectories.
+ *
+ *  aliases           If True, aliases of resources are allowed (eg. symbolic
+ *                    links and caps variations). May bypass security constraints.
+ *
+ *  maxCacheSize      The maximum total size of the cache or 0 for no cache.
+ *  maxCachedFileSize The maximum size of a file to cache
+ *  maxCachedFiles    The maximum number of files to cache
+ *
+ *  useFileMappedBuffer
+ *                    If set to true, it will use mapped file buffer to serve static content
+ *                    when using NIO connector. Setting this value to false means that
+ *                    a direct buffer will be used instead of a mapped file buffer.
+ *                    By default, this is set to true.
+ *
+ *  cacheControl      If set, all static content will have this value set as the cache-control
+ *                    header.
+ -->
+ 
+ 
+  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
+  <servlet>
+    <servlet-name>default</servlet-name>
+    <servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class>
+    <init-param>
+      <param-name>aliases</param-name>
+      <param-value>false</param-value>
+    </init-param>
+    <init-param>
+      <param-name>acceptRanges</param-name>
+      <param-value>true</param-value>
+    </init-param>
+    <init-param>
+      <param-name>dirAllowed</param-name>
+      <param-value>true</param-value>
+    </init-param>
+    <init-param>
+      <param-name>welcomeServlets</param-name>
+      <param-value>false</param-value>
+    </init-param>
+    <init-param>
+      <param-name>redirectWelcome</param-name>
+      <param-value>false</param-value>
+    </init-param>
+    <init-param>
+      <param-name>maxCacheSize</param-name>
+      <param-value>256000000</param-value>
+    </init-param>
+    <init-param>
+      <param-name>maxCachedFileSize</param-name>
+      <param-value>200000000</param-value>
+    </init-param>
+    <init-param>
+      <param-name>maxCachedFiles</param-name>
+      <param-value>2048</param-value>
+    </init-param>
+    <init-param>
+      <param-name>gzip</param-name>
+      <param-value>true</param-value>
+    </init-param>
+    <init-param>
+      <param-name>useFileMappedBuffer</param-name>
+      <param-value>true</param-value>
+    </init-param>
+    <!--
+    <init-param>
+      <param-name>resourceCache</param-name>
+      <param-value>resourceCache</param-value>
+    </init-param>
+    -->
+    <!--
+    <init-param>
+      <param-name>cacheControl</param-name>
+      <param-value>max-age=3600,public</param-value>
+    </init-param>
+    -->
+    <load-on-startup>0</load-on-startup>
+  </servlet>
+
+  <servlet-mapping>
+    <servlet-name>default</servlet-name>
+    <url-pattern>/</url-pattern>
+  </servlet-mapping>
+
+
+  <!-- ==================================================================== -->
+  <!-- JSP Servlet                                                          -->
+  <!-- This is the jasper JSP servlet from the jakarta project              -->
+  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
+  <!-- The JSP page compiler and execution servlet, which is the mechanism  -->
+  <!-- used by Glassfish to support JSP pages.  Traditionally, this servlet -->
+  <!-- is mapped to URL patterh "*.jsp".  This servlet supports the         -->
+  <!-- following initialization parameters (default values are in square    -->
+  <!-- brackets):                                                           -->
+  <!--                                                                      -->
+  <!--   checkInterval       If development is false and reloading is true, -->
+  <!--                       background compiles are enabled. checkInterval -->
+  <!--                       is the time in seconds between checks to see   -->
+  <!--                       if a JSP page needs to be recompiled. [300]    -->
+  <!--                                                                      -->
+  <!--   compiler            Which compiler Ant should use to compile JSP   -->
+  <!--                       pages.  See the Ant documenation for more      -->
+  <!--                       information. [javac]                           -->
+  <!--                                                                      -->
+  <!--   classdebuginfo      Should the class file be compiled with         -->
+  <!--                       debugging information?  [true]                 -->
+  <!--                                                                      -->
+  <!--   classpath           What class path should I use while compiling   -->
+  <!--                       generated servlets?  [Created dynamically      -->
+  <!--                       based on the current web application]          -->
+  <!--                       Set to ? to make the container explicitly set  -->
+  <!--                       this parameter.                                -->
+  <!--                                                                      -->
+  <!--   development         Is Jasper used in development mode (will check -->
+  <!--                       for JSP modification on every access)?  [true] -->
+  <!--                                                                      -->
+  <!--   enablePooling       Determines whether tag handler pooling is      -->
+  <!--                       enabled  [true]                                -->
+  <!--                                                                      -->
+  <!--   fork                Tell Ant to fork compiles of JSP pages so that -->
+  <!--                       a separate JVM is used for JSP page compiles   -->
+  <!--                       from the one Tomcat is running in. [true]      -->
+  <!--                                                                      -->
+  <!--   ieClassId           The class-id value to be sent to Internet      -->
+  <!--                       Explorer when using <jsp:plugin> tags.         -->
+  <!--                       [clsid:8AD9C840-044E-11D1-B3E9-00805F499D93]   -->
+  <!--                                                                      -->
+  <!--   javaEncoding        Java file encoding to use for generating java  -->
+  <!--                       source files. [UTF-8]                          -->
+  <!--                                                                      -->
+  <!--   keepgenerated       Should we keep the generated Java source code  -->
+  <!--                       for each page instead of deleting it? [true]   -->
+  <!--                                                                      -->
+  <!--   logVerbosityLevel   The level of detailed messages to be produced  -->
+  <!--                       by this servlet.  Increasing levels cause the  -->
+  <!--                       generation of more messages.  Valid values are -->
+  <!--                       FATAL, ERROR, WARNING, INFORMATION, and DEBUG. -->
+  <!--                       [WARNING]                                      -->
+  <!--                                                                      -->
+  <!--   mappedfile          Should we generate static content with one     -->
+  <!--                       print statement per input line, to ease        -->
+  <!--                       debugging?  [false]                            -->
+  <!--                                                                      -->
+  <!--                                                                      -->
+  <!--   reloading           Should Jasper check for modified JSPs?  [true] -->
+  <!--                                                                      -->
+  <!--   suppressSmap        Should the generation of SMAP info for JSR45   -->
+  <!--                       debugging be suppressed?  [false]              -->
+  <!--                                                                      -->
+  <!--   dumpSmap            Should the SMAP info for JSR45 debugging be    -->
+  <!--                       dumped to a file? [false]                      -->
+  <!--                       False if suppressSmap is true                  -->
+  <!--                                                                      -->
+  <!--   scratchdir          What scratch directory should we use when      -->
+  <!--                       compiling JSP pages?  [default work directory  -->
+  <!--                       for the current web application]               -->
+  <!--                                                                      -->
+  <!--   tagpoolMaxSize      The maximum tag handler pool size  [5]         -->
+  <!--                                                                      -->
+  <!--   xpoweredBy          Determines whether X-Powered-By response       -->
+  <!--                       header is added by generated servlet  [false]  -->
+  <!--                                                                      -->
+  <!-- If you wish to use Jikes to compile JSP pages:                       -->
+  <!--   Set the init parameter "compiler" to "jikes".  Define              -->
+  <!--   the property "-Dbuild.compiler.emacs=true" when starting Jetty     -->
+  <!--   to cause Jikes to emit error messages in a format compatible with  -->
+  <!--   Jasper.                                                            -->
+  <!--   If you get an error reporting that jikes can't use UTF-8 encoding, -->
+  <!--   try setting the init parameter "javaEncoding" to "ISO-8859-1".     -->
+  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
+  <servlet
+    id="jsp"
+  >
+    <servlet-name>jsp</servlet-name>
+    <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
+    <init-param>
+      <param-name>logVerbosityLevel</param-name>
+      <param-value>DEBUG</param-value>
+    </init-param>
+    <init-param>
+      <param-name>fork</param-name>
+      <param-value>false</param-value>
+    </init-param>
+    <init-param>
+      <param-name>xpoweredBy</param-name>
+      <param-value>false</param-value>
+    </init-param>
+    <!--  
+    <init-param>
+        <param-name>classpath</param-name>
+        <param-value>?</param-value>
+    </init-param>
+    -->
+    <load-on-startup>0</load-on-startup>
+  </servlet>
+
+  <servlet-mapping>
+    <servlet-name>jsp</servlet-name>
+    <url-pattern>*.jsp</url-pattern>
+    <url-pattern>*.jspf</url-pattern>
+    <url-pattern>*.jspx</url-pattern>
+    <url-pattern>*.xsp</url-pattern>
+    <url-pattern>*.JSP</url-pattern>
+    <url-pattern>*.JSPF</url-pattern>
+    <url-pattern>*.JSPX</url-pattern>
+    <url-pattern>*.XSP</url-pattern>
+  </servlet-mapping>
+
+  <!-- ==================================================================== -->
+  <!-- Dynamic Servlet Invoker.                                             -->
+  <!-- This servlet invokes anonymous servlets that have not been defined   -->
+  <!-- in the web.xml or by other means. The first element of the pathInfo  -->
+  <!-- of a request passed to the envoker is treated as a servlet name for  -->
+  <!-- an existing servlet, or as a class name of a new servlet.            -->
+  <!-- This servlet is normally mapped to /servlet/*                        -->
+  <!-- This servlet support the following initParams:                       -->
+  <!--                                                                      -->
+  <!--  nonContextServlets       If false, the invoker can only load        -->
+  <!--                           servlets from the contexts classloader.    -->
+  <!--                           This is false by default and setting this  -->
+  <!--                           to true may have security implications.    -->
+  <!--                                                                      -->
+  <!--  verbose                  If true, log dynamic loads                 -->
+  <!--                                                                      -->
+  <!--  *                        All other parameters are copied to the     -->
+  <!--                           each dynamic servlet as init parameters    -->
+  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
+  <!--
+    Uncomment for dynamic invocation <servlet> <servlet-name>invoker</servlet-name> <servlet-class>org.eclipse.jetty.servlet.Invoker</servlet-class> <init-param> <param-name>verbose</param-name>
+    <param-value>false</param-value> </init-param> <init-param> <param-name>nonContextServlets</param-name> <param-value>false</param-value> </init-param> <init-param>
+    <param-name>dynamicParam</param-name> <param-value>anyValue</param-value> </init-param> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>invoker</servlet-name>
+    <url-pattern>/servlet/*</url-pattern> </servlet-mapping>
+  -->
+
+
+
+  <!-- ==================================================================== -->
+  <session-config>
+    <session-timeout>30</session-timeout>
+  </session-config>
+
+  <!-- ==================================================================== -->
+  <!-- Default MIME mappings                                                -->
+  <!-- The default MIME mappings are provided by the mime.properties        -->
+  <!-- resource in the org.eclipse.jetty.server.jar file.  Additional or modified  -->
+  <!-- mappings may be specified here                                       -->
+  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
+  <!-- UNCOMMENT TO ACTIVATE
+  <mime-mapping>
+    <extension>mysuffix</extension>
+    <mime-type>mymime/type</mime-type>
+  </mime-mapping>
+  -->
+
+  <!-- ==================================================================== -->
+  <welcome-file-list>
+    <welcome-file>index.html</welcome-file>
+    <welcome-file>index.htm</welcome-file>
+    <welcome-file>index.jsp</welcome-file>
+  </welcome-file-list>
+
+  <!-- ==================================================================== -->
+  <locale-encoding-mapping-list>
+    <locale-encoding-mapping>
+      <locale>ar</locale>
+      <encoding>ISO-8859-6</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>be</locale>
+      <encoding>ISO-8859-5</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>bg</locale>
+      <encoding>ISO-8859-5</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>ca</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>cs</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>da</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>de</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>el</locale>
+      <encoding>ISO-8859-7</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>en</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>es</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>et</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>fi</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>fr</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>hr</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>hu</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>is</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>it</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>iw</locale>
+      <encoding>ISO-8859-8</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>ja</locale>
+      <encoding>Shift_JIS</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>ko</locale>
+      <encoding>EUC-KR</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>lt</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>lv</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>mk</locale>
+      <encoding>ISO-8859-5</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>nl</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>no</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>pl</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>pt</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>ro</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>ru</locale>
+      <encoding>ISO-8859-5</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>sh</locale>
+      <encoding>ISO-8859-5</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>sk</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>sl</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>sq</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>sr</locale>
+      <encoding>ISO-8859-5</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>sv</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>tr</locale>
+      <encoding>ISO-8859-9</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>uk</locale>
+      <encoding>ISO-8859-5</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>zh</locale>
+      <encoding>GB2312</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>zh_TW</locale>
+      <encoding>Big5</encoding>
+    </locale-encoding-mapping>
+  </locale-encoding-mapping-list>
+
+  <security-constraint>
+    <web-resource-collection>
+      <web-resource-name>Disable TRACE</web-resource-name>
+      <url-pattern>/</url-pattern>
+      <http-method>TRACE</http-method>
+    </web-resource-collection>
+    <auth-constraint/>
+  </security-constraint>
+
+</web-app>
+
diff --git a/continuum-buildagent/continuum-buildagent-jetty/src/main/contexts/continuum-buildagent.xml b/continuum-buildagent/continuum-buildagent-jetty/src/main/contexts/continuum-buildagent.xml
new file mode 100644
index 0000000..7fef972
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-jetty/src/main/contexts/continuum-buildagent.xml
@@ -0,0 +1,29 @@
+<!--
+  ~ 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.
+  -->
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
+
+<Configure id='wac' class="org.eclipse.jetty.webapp.WebAppContext">
+
+  <Set name="contextPath">/continuum-buildagent</Set>
+  <Set name="war"><Property name="jetty.home" default="."/>/apps/continuum-buildagent</Set>
+
+  <Set name="extractWAR">false</Set>
+  <Set name="copyWebDir">false</Set>
+
+</Configure>
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-jetty/src/main/resources/LICENSE b/continuum-buildagent/continuum-buildagent-jetty/src/main/resources/LICENSE
similarity index 100%
rename from continuum-distributed-build/continuum-buildagent/continuum-buildagent-jetty/src/main/resources/LICENSE
rename to continuum-buildagent/continuum-buildagent-jetty/src/main/resources/LICENSE
diff --git a/continuum-webapp/src/main/resources/template/default/empty.ftl b/continuum-buildagent/continuum-buildagent-jetty/src/main/tmp/.gitignore
similarity index 100%
copy from continuum-webapp/src/main/resources/template/default/empty.ftl
copy to continuum-buildagent/continuum-buildagent-jetty/src/main/tmp/.gitignore
diff --git a/continuum-buildagent/continuum-buildagent-webapp/pom.xml b/continuum-buildagent/continuum-buildagent-webapp/pom.xml
new file mode 100644
index 0000000..9b67f38
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webapp/pom.xml
@@ -0,0 +1,190 @@
+<?xml version="1.0"?>
+
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <artifactId>continuum-buildagent</artifactId>
+    <groupId>org.apache.continuum</groupId>
+    <version>1.4.3</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>continuum-buildagent-webapp</artifactId>
+  <packaging>war</packaging>
+  <name>Continuum :: Distributed Build :: Build Agent :: Webapp</name>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-buildagent-core</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-distributed-slave-server</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-distributed-master-client</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-buildagent-webdav</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-taskqueue</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>plexus-spring</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-web</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-slf4j-logging</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.atlassian.xmlrpc</groupId>
+      <artifactId>atlassian-xmlrpc-binder-server-spring</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.wagon</groupId>
+      <artifactId>wagon-file</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.wagon</groupId>
+      <artifactId>wagon-http-lightweight</artifactId>
+      <scope>runtime</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>xml-apis</groupId>
+          <artifactId>xml-apis</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.wagon</groupId>
+      <artifactId>wagon-ssh</artifactId>
+      <scope>runtime</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>org.codehaus.plexus</groupId>
+          <artifactId>plexus-container-default</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>classworlds</groupId>
+          <artifactId>classworlds</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>plexus</groupId>
+          <artifactId>plexus-utils</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.wagon</groupId>
+      <artifactId>wagon-ssh-external</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.wagon</groupId>
+      <artifactId>wagon-webdav-jackrabbit</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.mortbay.jetty</groupId>
+        <artifactId>jetty-maven-plugin</artifactId>
+        <configuration>
+          <scanIntervalSeconds>10</scanIntervalSeconds>
+          <stopKey>stopkey</stopKey>
+          <stopPort>9292</stopPort>
+          <connectors>
+            <connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
+              <port>9191</port>
+              <maxIdleTime>60000</maxIdleTime>
+            </connector>
+          </connectors>
+          <systemProperties>
+            <systemProperty>
+              <name>appserver.base</name>
+              <value>${project.build.directory}/appserver-base</value>
+            </systemProperty>
+          </systemProperties>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>tomcat-maven-plugin</artifactId>
+        <configuration>
+          <path>/continuum-buildagent</path>
+          <port>9191</port>
+          <contextFile>${basedir}/src/test/tomcat/tomcat-context-continuum.xml</contextFile>
+          <systemProperties>
+            <appserver.base>${project.build.directory}/appserver-base</appserver.base>
+          </systemProperties>
+        </configuration>
+      </plugin>
+      <plugin>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <executions>
+          <execution>
+            <phase>generate-resources</phase>
+            <goals>
+              <goal>run</goal>
+            </goals>
+            <configuration>
+              <tasks>
+                <copy todir="${project.build.directory}/appserver-base">
+                  <fileset dir="src/appserver-base" />
+                </copy>
+              </tasks>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/continuum-buildagent/continuum-buildagent-webapp/src/appserver-base/conf/continuum-buildagent.xml b/continuum-buildagent/continuum-buildagent-webapp/src/appserver-base/conf/continuum-buildagent.xml
new file mode 100644
index 0000000..c728bf5
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webapp/src/appserver-base/conf/continuum-buildagent.xml
@@ -0,0 +1,26 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+  ~ 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.
+  -->
+
+<continuum-buildagent-configuration>
+  <continuumServerUrl>http://localhost:9090/master-xmlrpc</continuumServerUrl>
+  <buildOutputDirectory>target/data/build-agent/build-output-directory</buildOutputDirectory>
+  <workingDirectory>target/data/build-agent/working-directory</workingDirectory>
+  <sharedSecretPassword>continuum1234</sharedSecretPassword>
+</continuum-buildagent-configuration>
diff --git a/continuum-buildagent/continuum-buildagent-webapp/src/main/java/org/apache/continuum/web/startup/BuildAgentStartup.java b/continuum-buildagent/continuum-buildagent-webapp/src/main/java/org/apache/continuum/web/startup/BuildAgentStartup.java
new file mode 100644
index 0000000..b3afad6
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webapp/src/main/java/org/apache/continuum/web/startup/BuildAgentStartup.java
@@ -0,0 +1,70 @@
+package org.apache.continuum.web.startup;
+
+/*
+ * 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 org.codehaus.plexus.spring.PlexusToSpringUtils;
+import org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+public class BuildAgentStartup
+    implements ServletContextListener
+{
+    private static final Logger log = LoggerFactory.getLogger( BuildAgentStartup.class );
+
+    /**
+     * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent)
+     */
+    public void contextDestroyed( ServletContextEvent sce )
+    {
+        // nothing to do here
+    }
+
+    /**
+     * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent)
+     */
+    public void contextInitialized( ServletContextEvent sce )
+    {
+        log.info( "Initializing Build Agent Task Queue Executor" );
+
+        WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(
+            sce.getServletContext() );
+
+        TaskQueueExecutor buildAgent = (TaskQueueExecutor) wac.getBean( PlexusToSpringUtils.buildSpringId(
+            TaskQueueExecutor.class, "build-agent" ) );
+
+        TaskQueueExecutor prepareBuildAgent = (TaskQueueExecutor) wac.getBean( PlexusToSpringUtils.buildSpringId(
+            TaskQueueExecutor.class, "prepare-build-agent" ) );
+
+        TaskQueueExecutor prepareRelease = (TaskQueueExecutor) wac.getBean( PlexusToSpringUtils.buildSpringId(
+            TaskQueueExecutor.class, "prepare-release" ) );
+
+        TaskQueueExecutor performRelease = (TaskQueueExecutor) wac.getBean( PlexusToSpringUtils.buildSpringId(
+            TaskQueueExecutor.class, "perform-release" ) );
+
+        TaskQueueExecutor rollbackRelease = (TaskQueueExecutor) wac.getBean( PlexusToSpringUtils.buildSpringId(
+            TaskQueueExecutor.class, "rollback-release" ) );
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-webapp/src/main/resources/META-INF/continuum/continuum-configuration.xml b/continuum-buildagent/continuum-buildagent-webapp/src/main/resources/META-INF/continuum/continuum-configuration.xml
new file mode 100644
index 0000000..ce34638
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webapp/src/main/resources/META-INF/continuum/continuum-configuration.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+
+<!--
+  ~ 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.
+  -->
+
+<configuration>
+  <system/>
+  <jndi prefix="java:comp/env" config-optional="true"/>
+  <xml fileName="${appserver.base}/conf/continuum-buildagent.xml" config-optional="true"
+       config-forceCreate="true" config-name="org.apache.continuum"/>
+  <xml fileName="${user.home}/.m2/continuum-buildagent.xml" config-optional="true"
+       config-forceCreate="true" config-name="org.apache.continuum.user"/>
+</configuration>
diff --git a/continuum-buildagent/continuum-buildagent-webapp/src/main/resources/META-INF/plexus/application.xml b/continuum-buildagent/continuum-buildagent-webapp/src/main/resources/META-INF/plexus/application.xml
new file mode 100644
index 0000000..a7ac617
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webapp/src/main/resources/META-INF/plexus/application.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!--
+  ~ 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.
+  -->
+
+<plexus>
+  <components>
+
+    <!--
+    | Logger manager
+    -->
+    <component>
+      <role>org.codehaus.plexus.logging.LoggerManager</role>
+      <implementation>org.codehaus.plexus.logging.slf4j.Slf4jLoggerManager</implementation>
+      <lifecycle-handler>basic</lifecycle-handler>
+    </component>
+
+  </components>
+
+  <lifecycle-handler-manager implementation="org.codehaus.plexus.lifecycle.DefaultLifecycleHandlerManager">
+    <default-lifecycle-handler-id>plexus</default-lifecycle-handler-id>
+    <lifecycle-handlers>
+      <lifecycle-handler implementation="org.codehaus.plexus.personality.plexus.PlexusLifecycleHandler">
+        <id>plexus</id>
+        <name>Plexus Lifecycle Handler</name>
+        <begin-segment>
+          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.LogEnablePhase"/>
+          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.CompositionPhase"/>
+          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.ContextualizePhase"/>
+          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.AutoConfigurePhase"/>
+          <phase implementation="org.codehaus.plexus.registry.RegistryConfigurePhase"/>
+          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.ServiceablePhase"/>
+          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializePhase"/>
+          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.StartPhase"/>
+        </begin-segment>
+        <suspend-segment>
+          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.SuspendPhase"/>
+        </suspend-segment>
+        <resume-segment>
+          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.ResumePhase"/>
+        </resume-segment>
+        <end-segment>
+          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.StopPhase"/>
+          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.DisposePhase"/>
+          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.LogDisablePhase"/>
+        </end-segment>
+      </lifecycle-handler>
+    </lifecycle-handlers>
+  </lifecycle-handler-manager>
+</plexus>
diff --git a/continuum-buildagent/continuum-buildagent-webapp/src/main/resources/applicationContext.xml b/continuum-buildagent/continuum-buildagent-webapp/src/main/resources/applicationContext.xml
new file mode 100644
index 0000000..2c7705b
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webapp/src/main/resources/applicationContext.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+  <bean id="slaveBuildAgentTransportServer" lazy-init="true" scope="singleton"
+        class="org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportServer">
+    <constructor-arg ref="continuumBuildAgentService"/>
+  </bean>
+
+  <bean name="xmlrpcServicesList" lazy-init="true" scope="singleton" class="java.util.ArrayList">
+    <constructor-arg>
+      <list>
+        <ref bean="slaveBuildAgentTransportServer"/>
+      </list>
+    </constructor-arg>
+  </bean>
+
+  <bean name="xmlRpcAuthenticator"
+        class="org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportAuthenticator">
+    <constructor-arg ref="buildAgentConfigurationService"/>
+  </bean>
+</beans>
diff --git a/continuum-buildagent/continuum-buildagent-webapp/src/main/resources/log4j.xml b/continuum-buildagent/continuum-buildagent-webapp/src/main/resources/log4j.xml
new file mode 100644
index 0000000..af54273
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webapp/src/main/resources/log4j.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+  ~ 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.
+  -->
+
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+  <appender name="rolling" class="org.apache.log4j.DailyRollingFileAppender">
+    <param name="file" value="${appserver.base}/logs/continuum-buildagent.log"/>
+    <param name="append" value="true"/>
+    <param name="datePattern" value="'.'yyyy-MM-dd"/>
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="%d [%t] %-5p %c %x - %m%n"/>
+    </layout>
+  </appender>
+
+  <!--
+    <logger name="org.apache.continuum.buildagent">
+      <level value="info"/>
+    </logger>
+
+    <logger name="org.apache.continuum.web">
+      <level value="info"/>
+    </logger>
+
+    <logger name="org.apache.continuum.distributed">
+      <level value="info"/>
+    </logger>
+  -->
+
+  <logger name="org.springframework">
+    <level value="error"/>
+  </logger>
+
+  <root>
+    <priority value="info"/>
+    <appender-ref ref="rolling"/>
+  </root>
+</log4j:configuration>
diff --git a/continuum-buildagent/continuum-buildagent-webapp/src/main/webapp/WEB-INF/jboss-web.xml b/continuum-buildagent/continuum-buildagent-webapp/src/main/webapp/WEB-INF/jboss-web.xml
new file mode 100644
index 0000000..a8dfff2
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webapp/src/main/webapp/WEB-INF/jboss-web.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<!DOCTYPE jboss-web PUBLIC
+    "-//JBoss//DTD Web Application 5.0//EN"
+    "http://www.jboss.org/j2ee/dtd/jboss-web_5_0.dtd">
+<jboss-web>
+
+  <class-loading java2ClassLoadingCompliance='false'>
+    <loader-repository>
+      org.apache.continuum:loader=continuum-buildagent
+      <loader-repository-config>java2ParentDelegation=false</loader-repository-config>
+    </loader-repository>
+
+  </class-loading>
+
+  <context-root>continuum-buildagent</context-root>
+
+
+</jboss-web>
+
diff --git a/continuum-buildagent/continuum-buildagent-webapp/src/main/webapp/WEB-INF/web.xml b/continuum-buildagent/continuum-buildagent-webapp/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..af5ca0e
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webapp/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0"?>
+
+<!--
+  ~ 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.
+  -->
+
+<web-app xmlns="http://java.sun.com/xml/ns/j2ee" version="2.4"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+  <display-name>Continuum Distributed Build Transport Tests</display-name>
+
+  <context-param>
+    <param-name>contextClass</param-name>
+    <param-value>org.codehaus.plexus.spring.PlexusWebApplicationContext</param-value>
+  </context-param>
+
+  <context-param>
+    <param-name>contextConfigLocation</param-name>
+    <param-value>
+      classpath*:/META-INF/spring-context.xml
+      classpath*:/applicationContext.xml
+      classpath*:/META-INF/plexus/components.xml
+      classpath*:/META-INF/plexus/application.xml
+    </param-value>
+  </context-param>
+
+  <listener>
+    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
+  </listener>
+
+  <listener>
+    <!-- TODO: some Spring technique for this? -->
+    <listener-class>org.apache.continuum.web.startup.BuildAgentStartup</listener-class>
+  </listener>
+
+  <servlet>
+    <servlet-name>SlaveXmlRpcServlet</servlet-name>
+    <servlet-class>
+      com.atlassian.xmlrpc.spring.BinderSpringXmlRpcServlet
+    </servlet-class>
+    <init-param>
+      <param-name>serviceListBeanName</param-name>
+      <param-value>xmlrpcServicesList</param-value>
+    </init-param>
+    <init-param>
+      <param-name>authHandlerBeanName</param-name>
+      <param-value>xmlRpcAuthenticator</param-value>
+    </init-param>
+    <init-param>
+      <param-name>enabledForExtensions</param-name>
+      <param-value>true</param-value>
+    </init-param>
+    <load-on-startup>1</load-on-startup>
+  </servlet>
+
+  <servlet>
+    <servlet-name>WorkingCopyServlet</servlet-name>
+    <servlet-class>
+      org.apache.continuum.webdav.WorkingCopyServlet
+    </servlet-class>
+    <!-- Loading this on startup so as to take advantage of configuration listeners -->
+    <load-on-startup>1</load-on-startup>
+  </servlet>
+
+  <servlet-mapping>
+    <servlet-name>SlaveXmlRpcServlet</servlet-name>
+    <url-pattern>/xmlrpc</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>WorkingCopyServlet</servlet-name>
+    <url-pattern>/workingcopy/*</url-pattern>
+  </servlet-mapping>
+</web-app>
diff --git a/continuum-buildagent/continuum-buildagent-webapp/src/main/webapp/index.jsp b/continuum-buildagent/continuum-buildagent-webapp/src/main/webapp/index.jsp
new file mode 100644
index 0000000..6db69ff
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webapp/src/main/webapp/index.jsp
@@ -0,0 +1,20 @@
+<%--
+  ~ 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.
+  --%>
+
+<% response.sendRedirect(  request.getContextPath() + "/xmlrpc" ); %>
diff --git a/continuum-buildagent/continuum-buildagent-webapp/src/test/tomcat/tomcat-context-continuum-buildagent.xml b/continuum-buildagent/continuum-buildagent-webapp/src/test/tomcat/tomcat-context-continuum-buildagent.xml
new file mode 100644
index 0000000..0545e51
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webapp/src/test/tomcat/tomcat-context-continuum-buildagent.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ 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.
+  -->
+
+<Context path="/continuum"/>
+  
\ No newline at end of file
diff --git a/continuum-buildagent/continuum-buildagent-webdav-client/pom.xml b/continuum-buildagent/continuum-buildagent-webdav-client/pom.xml
new file mode 100644
index 0000000..b89bd79
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webdav-client/pom.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0"?>
+<!--
+  ~ 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.continuum</groupId>
+    <artifactId>continuum-buildagent</artifactId>
+    <version>1.4.3</version>
+  </parent>
+  <artifactId>continuum-buildagent-webdav-client</artifactId>
+  <version>1.4.3</version>
+  <name>Continuum :: Distributed Build :: Build Agent :: Webdav Client</name>
+  <dependencies>
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.httpcomponents</groupId>
+      <artifactId>httpclient</artifactId>
+      <version>4.1.1</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.httpcomponents</groupId>
+      <artifactId>httpcore</artifactId>
+      <version>4.1.1</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jackrabbit</groupId>
+      <artifactId>jackrabbit-webdav</artifactId>
+      <version>2.2.7</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-logging</groupId>
+      <artifactId>commons-logging</artifactId>
+      <version>1.1.1</version>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-jdk14</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+  </dependencies>
+  <build>
+    <!--
+    To execute the sample working copy webdav client, just execute "mvn exec:java".
+
+    By default, the sample webdav client gets the POM file of the Continuum project with id "1"
+    from the working copy directory. Change the values of the continuumProjectId and pomFile
+    properties depending on the contents of the continuum-buildagent's working directory you
+    are running this against.
+    -->
+    <plugins>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>exec-maven-plugin</artifactId>
+        <configuration>
+          <executable>java</executable>
+          <mainClass>org.apache.continuum.buildagent.webdav.client.WorkingCopyWebdavClient</mainClass>
+          <arguments>
+            <argument>${url}/workingcopy/${continuumProjectId}/${pomFile}</argument>
+            <argument>${sharedSecretPassword}</argument>
+          </arguments>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-enforcer-plugin</artifactId>
+        <executions>
+          <execution>
+            <goals>
+              <goal>enforce</goal>
+            </goals>
+            <configuration>
+              <rules>
+                <bannedDependencies>
+                  <includes>
+                    <!--
+                     Needed during runtime by httpclient. This module isn't included in webapp so it
+                     should be alright to include commons-logging
+                     -->
+                    <include>commons-logging:commons-logging:1.1.1:jar:runtime</include>
+                  </includes>
+                </bannedDependencies>
+              </rules>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  <properties>
+    <url>http://localhost:${port}/continuum-buildagent</url>
+    <port>8181</port>
+    <sharedSecretPassword>secret</sharedSecretPassword>
+    <continuumProjectId>1</continuumProjectId>
+    <pomFile>pom.xml</pomFile>
+  </properties>
+</project>
diff --git a/continuum-buildagent/continuum-buildagent-webdav-client/src/main/java/org/apache/continuum/buildagent/webdav/client/WorkingCopyWebdavClient.java b/continuum-buildagent/continuum-buildagent-webdav-client/src/main/java/org/apache/continuum/buildagent/webdav/client/WorkingCopyWebdavClient.java
new file mode 100644
index 0000000..061b7ed
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webdav-client/src/main/java/org/apache/continuum/buildagent/webdav/client/WorkingCopyWebdavClient.java
@@ -0,0 +1,225 @@
+package org.apache.continuum.buildagent.webdav.client;
+
+/*
+ * 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 org.apache.commons.httpclient.Credentials;
+import org.apache.commons.httpclient.HostConfiguration;
+import org.apache.commons.httpclient.HttpConnectionManager;
+import org.apache.commons.httpclient.HttpMethod;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpVersion;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.AuthCache;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.protocol.ClientContext;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.params.ConnManagerPNames;
+import org.apache.http.conn.params.ConnPerRouteBean;
+import org.apache.http.conn.scheme.PlainSocketFactory;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.scheme.SchemeRegistry;
+import org.apache.http.impl.auth.BasicScheme;
+import org.apache.http.impl.client.BasicAuthCache;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
+import org.apache.http.params.BasicHttpParams;
+import org.apache.http.params.HttpParams;
+import org.apache.http.params.HttpProtocolParams;
+import org.apache.http.protocol.BasicHttpContext;
+import org.apache.http.util.EntityUtils;
+import org.apache.jackrabbit.webdav.DavConstants;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.MultiStatus;
+import org.apache.jackrabbit.webdav.MultiStatusResponse;
+import org.apache.jackrabbit.webdav.client.methods.DavMethod;
+import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
+import org.apache.jackrabbit.webdav.property.DavProperty;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+public class WorkingCopyWebdavClient
+{
+    public static void main( String[] args )
+        throws Exception
+    {
+        System.out.println( "Running webdav client.." );
+
+        // get resource
+        getResourceUsingHttpclient( args[0], "", args[1] );
+
+        // list resources
+        getResourcesUsingJackrabbit( args[0], "", args[1] );
+    }
+
+    private static void getResourceUsingHttpclient( String resourceUrl, String username, String password )
+        throws URISyntaxException, IOException
+    {
+        SchemeRegistry schemeRegistry = new SchemeRegistry();
+        schemeRegistry.register( new Scheme( "http", PlainSocketFactory.getSocketFactory(), 80 ) );
+
+        HttpParams params = new BasicHttpParams();
+        params.setParameter( ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 30 );
+        params.setParameter( ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, new ConnPerRouteBean( 30 ) );
+
+        HttpProtocolParams.setVersion( params, HttpVersion.HTTP_1_1 );
+
+        ClientConnectionManager cm = new ThreadSafeClientConnManager( params, schemeRegistry );
+
+        DefaultHttpClient httpClient = new DefaultHttpClient( cm, params );
+
+        URL url = new URL( resourceUrl );
+        URI uri = url.toURI();
+        HttpGet httpGet = new HttpGet( uri );
+
+        httpClient.getCredentialsProvider().setCredentials( new AuthScope( uri.getHost(), uri.getPort() ),
+                                                            new UsernamePasswordCredentials( username, password ) );
+
+        HttpHost targetHost = new HttpHost( url.getHost(), url.getPort(), url.getProtocol() );
+
+        AuthCache authCache = new BasicAuthCache();
+        BasicScheme basicAuth = new BasicScheme();
+        authCache.put( targetHost, basicAuth );
+
+        BasicHttpContext localcontext = new BasicHttpContext();
+        localcontext.setAttribute( ClientContext.AUTH_CACHE, authCache );
+
+        System.out.println( "Retrieving resource '" + url.toString() + "' using HttpClient's get method.." );
+
+        HttpResponse httpResponse = httpClient.execute( targetHost, httpGet, localcontext );
+
+        System.out.println( "Response status code :: " + httpResponse.getStatusLine().getStatusCode() );
+
+        InputStream is = IOUtils.toInputStream( EntityUtils.toString( httpResponse.getEntity(),
+                                                                      EntityUtils.getContentCharSet(
+                                                                          httpResponse.getEntity() ) ) );
+        String content = IOUtils.toString( is );
+
+        System.out.println( "Content :: " + content );
+    }
+
+    private static void getResourcesUsingJackrabbit( String filePath, String username, String password )
+        throws IOException, URISyntaxException, DavException
+    {
+        int idx = filePath.lastIndexOf( "/" );
+        if ( idx != -1 )
+        {
+            filePath = StringUtils.substring( filePath, 0, idx + 1 );
+        }
+
+        System.out.println( "\nRetrieve resources from '" + filePath + "' using Jackrabbit's webdav client.." );
+
+        URL url = new URL( filePath );
+        URI uri = url.toURI();
+
+        DavMethod pFind = new PropFindMethod( uri.toString(), DavConstants.PROPFIND_ALL_PROP, DavConstants.DEPTH_1 );
+
+        executeMethod( username, password, uri, pFind );
+
+        MultiStatus multiStatus = pFind.getResponseBodyAsMultiStatus();
+        MultiStatusResponse[] responses = multiStatus.getResponses();
+        MultiStatusResponse currResponse;
+        System.out.println( "Folders and files in " + filePath + ":" );
+
+        for ( int i = 0; i < responses.length; i++ )
+        {
+            currResponse = responses[i];
+            if ( !( currResponse.getHref().equals( uri.toString() ) || currResponse.getHref().equals(
+                uri.toString() + "/" ) ) )
+            {
+                String currResponseHref = StringUtils.trim( currResponse.getHref() );
+
+                System.out.println( "\nResource url :: " + currResponseHref );
+
+                DavProperty displayNameDavProperty = currResponse.getProperties( HttpStatus.SC_OK ).get(
+                    "displayname" );
+                String displayName;
+                if ( displayNameDavProperty != null )
+                {
+                    displayName = (String) displayNameDavProperty.getValue();
+                }
+                else
+                {
+                    displayName = StringUtils.substring( currResponseHref, currResponseHref.lastIndexOf( "/" ) );
+                }
+
+                HttpMethod httpGet = new GetMethod( currResponseHref );
+
+                URL resourceUrl = new URL( currResponseHref );
+
+                executeMethod( username, password, resourceUrl.toURI(), httpGet );
+
+                System.out.println( "Returned status code :: " + httpGet.getStatusCode() );
+
+                if ( httpGet.getStatusCode() == HttpStatus.SC_OK )
+                {
+                    InputStream is = httpGet.getResponseBodyAsStream();
+
+                    try
+                    {
+                        System.out.println( "Contents of file '" + displayName + "' :: " + IOUtils.toString( is ) );
+                    }
+                    finally
+                    {
+                        IOUtils.closeQuietly( is );
+                    }
+                }
+            }
+        }
+    }
+
+    private static void executeMethod( String username, String password, URI uri, HttpMethod pFind )
+        throws IOException
+    {
+        HostConfiguration hostConfig = new HostConfiguration();
+        hostConfig.setHost( uri.getHost() );
+
+        int maxHostConnections = 20;
+
+        HttpConnectionManagerParams params = new HttpConnectionManagerParams();
+        params.setMaxConnectionsPerHost( hostConfig, maxHostConnections );
+
+        HttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
+        connectionManager.setParams( params );
+
+        org.apache.commons.httpclient.HttpClient client = new org.apache.commons.httpclient.HttpClient(
+            connectionManager );
+
+        Credentials creds = new org.apache.commons.httpclient.UsernamePasswordCredentials( username, password );
+
+        client.getState().setCredentials( org.apache.commons.httpclient.auth.AuthScope.ANY, creds );
+        client.setHostConfiguration( hostConfig );
+        client.getParams().setAuthenticationPreemptive( true );
+
+        client.executeMethod( hostConfig, pFind );
+    }
+
+}
diff --git a/continuum-buildagent/continuum-buildagent-webdav/pom.xml b/continuum-buildagent/continuum-buildagent-webdav/pom.xml
new file mode 100644
index 0000000..6e08649
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webdav/pom.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0"?>
+<!--
+  ~ 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.continuum</groupId>
+    <artifactId>continuum-buildagent</artifactId>
+    <version>1.4.3</version>
+  </parent>
+  <artifactId>continuum-buildagent-webdav</artifactId>
+  <name>Continuum :: Distributed Build :: Build Agent :: Webdav</name>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-buildagent-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>plexus-spring</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jackrabbit</groupId>
+      <artifactId>jackrabbit-webdav</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>joda-time</groupId>
+      <artifactId>joda-time</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-web</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>javax.activation</groupId>
+      <artifactId>activation</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>httpunit</groupId>
+      <artifactId>httpunit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>nekohtml</groupId>
+      <artifactId>nekohtml</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-simple</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>easymock</groupId>
+      <artifactId>easymock</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.codehaus.plexus</groupId>
+        <artifactId>plexus-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>generate</id>
+            <phase>generate-resources</phase>
+            <goals>
+              <goal>descriptor</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
\ No newline at end of file
diff --git a/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/ContinuumBuildAgentDavLocatorFactory.java b/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/ContinuumBuildAgentDavLocatorFactory.java
new file mode 100644
index 0000000..0a8aef2
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/ContinuumBuildAgentDavLocatorFactory.java
@@ -0,0 +1,69 @@
+package org.apache.continuum.webdav;
+
+/*
+ * 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 org.apache.continuum.webdav.util.WorkingCopyPathUtil;
+import org.apache.jackrabbit.util.Text;
+import org.apache.jackrabbit.webdav.DavLocatorFactory;
+import org.apache.jackrabbit.webdav.DavResourceLocator;
+
+public class ContinuumBuildAgentDavLocatorFactory
+    implements DavLocatorFactory
+{
+    public DavResourceLocator createResourceLocator( String prefix, String href )
+    {
+        // build prefix string and remove all prefixes from the given href.
+        StringBuilder b = new StringBuilder();
+        if ( prefix != null && prefix.length() > 0 )
+        {
+            b.append( prefix );
+            if ( !prefix.endsWith( "/" ) )
+            {
+                b.append( '/' );
+            }
+            if ( href.startsWith( prefix ) )
+            {
+                href = href.substring( prefix.length() );
+            }
+        }
+
+        // special treatment for root item, that has no name but '/' path.
+        if ( href == null || "".equals( href ) )
+        {
+            href = "/";
+        }
+
+        final int projectId = WorkingCopyPathUtil.getProjectId( href );
+        return new ContinuumBuildAgentDavResourceLocator( b.toString(), Text.unescape( href ), this, projectId );
+    }
+
+    public DavResourceLocator createResourceLocator( String prefix, String workspacePath, String resourcePath )
+    {
+        return createResourceLocator( prefix, workspacePath, resourcePath, true );
+    }
+
+    public DavResourceLocator createResourceLocator( String prefix, String workspacePath, String path,
+                                                     boolean isResourcePath )
+    {
+        final int projectId = WorkingCopyPathUtil.getProjectId( path );
+        return new ContinuumBuildAgentDavResourceLocator( prefix, path, this, projectId );
+    }
+
+}
diff --git a/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/ContinuumBuildAgentDavResource.java b/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/ContinuumBuildAgentDavResource.java
new file mode 100644
index 0000000..968dca8
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/ContinuumBuildAgentDavResource.java
@@ -0,0 +1,405 @@
+package org.apache.continuum.webdav;
+
+/*
+ * 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 org.apache.commons.io.IOUtils;
+import org.apache.jackrabbit.util.Text;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavResource;
+import org.apache.jackrabbit.webdav.DavResourceFactory;
+import org.apache.jackrabbit.webdav.DavResourceIterator;
+import org.apache.jackrabbit.webdav.DavResourceIteratorImpl;
+import org.apache.jackrabbit.webdav.DavResourceLocator;
+import org.apache.jackrabbit.webdav.DavSession;
+import org.apache.jackrabbit.webdav.MultiStatusResponse;
+import org.apache.jackrabbit.webdav.io.InputContext;
+import org.apache.jackrabbit.webdav.io.OutputContext;
+import org.apache.jackrabbit.webdav.lock.ActiveLock;
+import org.apache.jackrabbit.webdav.lock.LockInfo;
+import org.apache.jackrabbit.webdav.lock.LockManager;
+import org.apache.jackrabbit.webdav.lock.Scope;
+import org.apache.jackrabbit.webdav.lock.Type;
+import org.apache.jackrabbit.webdav.property.DavProperty;
+import org.apache.jackrabbit.webdav.property.DavPropertyName;
+import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
+import org.apache.jackrabbit.webdav.property.DavPropertySet;
+import org.apache.jackrabbit.webdav.property.DefaultDavProperty;
+import org.apache.jackrabbit.webdav.property.ResourceType;
+import org.joda.time.DateTime;
+import org.joda.time.format.DateTimeFormatter;
+import org.joda.time.format.ISODateTimeFormat;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import javax.activation.MimetypesFileTypeMap;
+
+public class ContinuumBuildAgentDavResource
+    implements DavResource
+{
+    private static final Logger log = LoggerFactory.getLogger( ContinuumBuildAgentDavResource.class );
+
+    private final ContinuumBuildAgentDavResourceLocator locator;
+
+    private final DavResourceFactory factory;
+
+    private final File localResource;
+
+    private final String logicalResource;
+
+    private final DavSession session;
+
+    private final MimetypesFileTypeMap mimeTypes;
+
+    private DavPropertySet properties = null;
+
+    public static final String COMPLIANCE_CLASS = "1, 2";
+
+    public static final String HIDDEN_PATH_PREFIX = ".";
+
+    public static final String SUPPORTED_METHODS = "OPTIONS, GET, HEAD, TRACE, PROPFIND";
+
+    public ContinuumBuildAgentDavResource( String localResource, String logicalResource, DavSession session,
+                                           ContinuumBuildAgentDavResourceLocator locator, DavResourceFactory factory,
+                                           MimetypesFileTypeMap mimeTypes )
+    {
+        this.localResource = new File( localResource );
+        this.logicalResource = logicalResource;
+        this.locator = locator;
+        this.factory = factory;
+        this.session = session;
+        this.mimeTypes = mimeTypes;
+    }
+
+    public void addLockManager( LockManager lockManager )
+    {
+    }
+
+    public void addMember( DavResource davResource, InputContext inputContext )
+        throws DavException
+    {
+        throw new UnsupportedOperationException( "Not supported" );
+    }
+
+    public MultiStatusResponse alterProperties( List changeList )
+        throws DavException
+    {
+        return null;
+    }
+
+    public MultiStatusResponse alterProperties( DavPropertySet setProperties, DavPropertyNameSet removePropertyNames )
+        throws DavException
+    {
+        return null;
+    }
+
+    public void copy( DavResource destination, boolean shallow )
+        throws DavException
+    {
+        throw new UnsupportedOperationException( "Not supported" );
+    }
+
+    public boolean exists()
+    {
+        return localResource.exists();
+    }
+
+    public DavResource getCollection()
+    {
+        DavResource parent = null;
+        if ( getResourcePath() != null && !"/".equals( getResourcePath() ) )
+        {
+            String parentPath = Text.getRelativeParent( getResourcePath(), 1 );
+            if ( "".equals( parentPath ) )
+            {
+                parentPath = "/";
+            }
+
+            DavResourceLocator parentloc = locator.getFactory().createResourceLocator( locator.getPrefix(),
+                                                                                       parentPath );
+
+            try
+            {
+                parent = factory.createResource( parentloc, session );
+            }
+            catch ( DavException e )
+            {
+                // should not occur
+            }
+        }
+        return parent;
+    }
+
+    public String getComplianceClass()
+    {
+        return COMPLIANCE_CLASS;
+    }
+
+    public String getDisplayName()
+    {
+        String resPath = getResourcePath();
+        return ( resPath != null ) ? Text.getName( resPath ) : resPath;
+    }
+
+    public DavResourceFactory getFactory()
+    {
+        return factory;
+    }
+
+    public String getHref()
+    {
+        return locator.getHref( isCollection() );
+    }
+
+    public File getLocalResource()
+    {
+        return localResource;
+    }
+
+    public DavResourceLocator getLocator()
+    {
+        return locator;
+    }
+
+    public ActiveLock getLock( Type type, Scope scope )
+    {
+        return null;
+    }
+
+    public ActiveLock[] getLocks()
+    {
+        return null;
+    }
+
+    public String getLogicalResource()
+    {
+        return logicalResource;
+    }
+
+    public DavResourceIterator getMembers()
+    {
+        List<DavResource> list = new ArrayList<DavResource>();
+        if ( exists() && isCollection() )
+        {
+            for ( String item : localResource.list() )
+            {
+                try
+                {
+                    if ( !item.startsWith( HIDDEN_PATH_PREFIX ) )
+                    {
+                        String path = locator.getResourcePath() + '/' + item;
+                        DavResourceLocator resourceLocator = locator.getFactory().createResourceLocator(
+                            locator.getPrefix(), path );
+                        DavResource resource = factory.createResource( resourceLocator, session );
+
+                        if ( resource != null )
+                        {
+                            log.debug( "Retrieved resource: " + resource.getResourcePath() );
+                            list.add( resource );
+                        }
+                    }
+                }
+                catch ( DavException e )
+                {
+                    // should not occur
+                }
+            }
+        }
+
+        return new DavResourceIteratorImpl( list );
+    }
+
+    public MimetypesFileTypeMap getMimeTypes()
+    {
+        return mimeTypes;
+    }
+
+    public long getModificationTime()
+    {
+        return localResource.lastModified();
+    }
+
+    public DavPropertySet getProperties()
+    {
+        return initProperties();
+    }
+
+    public DavProperty getProperty( DavPropertyName propertyName )
+    {
+        return getProperties().get( propertyName );
+    }
+
+    public DavPropertyName[] getPropertyNames()
+    {
+        return getProperties().getPropertyNames();
+    }
+
+    public String getResourcePath()
+    {
+        return locator.getResourcePath();
+    }
+
+    public DavSession getSession()
+    {
+        return session;
+    }
+
+    public String getSupportedMethods()
+    {
+        return SUPPORTED_METHODS;
+    }
+
+    public boolean hasLock( Type type, Scope scope )
+    {
+        return false;
+    }
+
+    public boolean isCollection()
+    {
+        return localResource.isDirectory();
+    }
+
+    public boolean isLockable( Type type, Scope scope )
+    {
+        return false;
+    }
+
+    public ActiveLock lock( LockInfo lockInfo )
+        throws DavException
+    {
+        return null;
+    }
+
+    public void move( DavResource destination )
+        throws DavException
+    {
+        throw new UnsupportedOperationException( "Not supported" );
+    }
+
+    public ActiveLock refreshLock( LockInfo lockInfo, String lockTocken )
+        throws DavException
+    {
+        return null;
+    }
+
+    public void removeMember( DavResource member )
+        throws DavException
+    {
+        throw new UnsupportedOperationException( "Not supported" );
+    }
+
+    public void removeProperty( DavPropertyName propertyName )
+        throws DavException
+    {
+        throw new UnsupportedOperationException( "Not supported" );
+    }
+
+    public void setProperty( DavProperty property )
+        throws DavException
+    {
+        throw new UnsupportedOperationException( "Not supported" );
+    }
+
+    public void spool( OutputContext outputContext )
+        throws IOException
+    {
+        if ( !isCollection() )
+        {
+            outputContext.setContentLength( localResource.length() );
+            outputContext.setContentType( mimeTypes.getContentType( localResource ) );
+        }
+
+        if ( !isCollection() && outputContext.hasStream() )
+        {
+            FileInputStream is = null;
+            try
+            {
+                // Write content to stream
+                is = new FileInputStream( localResource );
+                IOUtils.copy( is, outputContext.getOutputStream() );
+            }
+            finally
+            {
+                IOUtils.closeQuietly( is );
+            }
+        }
+    }
+
+    public void unlock( String lockTocken )
+        throws DavException
+    {
+    }
+
+    /**
+     * Fill the set of properties
+     */
+    protected DavPropertySet initProperties()
+    {
+        if ( !exists() )
+        {
+            properties = new DavPropertySet();
+        }
+
+        if ( properties != null )
+        {
+            return properties;
+        }
+
+        DavPropertySet properties = new DavPropertySet();
+
+        // set (or reset) fundamental properties
+        if ( getDisplayName() != null )
+        {
+            properties.add( new DefaultDavProperty( DavPropertyName.DISPLAYNAME, getDisplayName() ) );
+        }
+        if ( isCollection() )
+        {
+            properties.add( new ResourceType( ResourceType.COLLECTION ) );
+            // Windows XP support
+            properties.add( new DefaultDavProperty( DavPropertyName.ISCOLLECTION, "1" ) );
+        }
+        else
+        {
+            properties.add( new ResourceType( ResourceType.DEFAULT_RESOURCE ) );
+
+            // Windows XP support
+            properties.add( new DefaultDavProperty( DavPropertyName.ISCOLLECTION, "0" ) );
+        }
+
+        // Need to get the ISO8601 date for properties
+        DateTime dt = new DateTime( localResource.lastModified() );
+        DateTimeFormatter fmt = ISODateTimeFormat.dateTime();
+        String modifiedDate = fmt.print( dt );
+
+        properties.add( new DefaultDavProperty( DavPropertyName.GETLASTMODIFIED, modifiedDate ) );
+
+        properties.add( new DefaultDavProperty( DavPropertyName.CREATIONDATE, modifiedDate ) );
+
+        properties.add( new DefaultDavProperty( DavPropertyName.GETCONTENTLENGTH, localResource.length() ) );
+
+        this.properties = properties;
+
+        return properties;
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/ContinuumBuildAgentDavResourceFactory.java b/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/ContinuumBuildAgentDavResourceFactory.java
new file mode 100644
index 0000000..15291e3
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/ContinuumBuildAgentDavResourceFactory.java
@@ -0,0 +1,177 @@
+package org.apache.continuum.webdav;
+
+/*
+ * 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 org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
+import org.apache.continuum.webdav.util.WebdavMethodUtil;
+import org.apache.continuum.webdav.util.WorkingCopyPathUtil;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavResource;
+import org.apache.jackrabbit.webdav.DavResourceFactory;
+import org.apache.jackrabbit.webdav.DavResourceLocator;
+import org.apache.jackrabbit.webdav.DavServletRequest;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.DavSession;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import javax.activation.MimetypesFileTypeMap;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * @plexus.component role="org.apache.continuum.webdav.ContinuumBuildAgentDavResourceFactory"
+ */
+public class ContinuumBuildAgentDavResourceFactory
+    implements DavResourceFactory
+{
+    private static final Logger log = LoggerFactory.getLogger( ContinuumBuildAgentDavResourceFactory.class );
+
+    private static final MimetypesFileTypeMap mimeTypes;
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildAgentConfigurationService buildAgentConfigurationService;
+
+    static
+    {
+        mimeTypes = new MimetypesFileTypeMap();
+        mimeTypes.addMimeTypes( "application/java-archive jar war ear" );
+        mimeTypes.addMimeTypes( "application/java-class class" );
+        mimeTypes.addMimeTypes( "image/png png" );
+    }
+
+    public DavResource createResource( final DavResourceLocator locator, final DavSession davSession )
+        throws DavException
+    {
+        ContinuumBuildAgentDavResourceLocator continuumLocator = checkLocatorIsInstanceOfContinuumBuildAgentLocator(
+            locator );
+
+        String logicalResource = WorkingCopyPathUtil.getLogicalResource( locator.getResourcePath() );
+        if ( logicalResource.startsWith( "/" ) )
+        {
+            logicalResource = logicalResource.substring( 1 );
+        }
+
+        File resourceFile = getResourceFile( continuumLocator.getProjectId(), logicalResource );
+
+        if ( !resourceFile.exists() || ( continuumLocator.getHref( false ).endsWith( "/" ) &&
+            !resourceFile.isDirectory() ) )
+        {
+            // force a resource not found
+            log.error( "Resource file '" + resourceFile.getAbsolutePath() + "' does not exist" );
+            throw new DavException( HttpServletResponse.SC_NOT_FOUND, "Resource does not exist" );
+        }
+        else
+        {
+            return createResource( resourceFile, logicalResource, davSession, continuumLocator );
+        }
+    }
+
+    public DavResource createResource( DavResourceLocator locator, DavServletRequest request,
+                                       DavServletResponse response )
+        throws DavException
+    {
+        ContinuumBuildAgentDavResourceLocator continuumLocator = checkLocatorIsInstanceOfContinuumBuildAgentLocator(
+            locator );
+
+        if ( !WebdavMethodUtil.isReadMethod( request.getMethod() ) )
+        {
+            throw new DavException( HttpServletResponse.SC_METHOD_NOT_ALLOWED,
+                                    "Write method not allowed in working copy" );
+        }
+
+        String logicalResource = WorkingCopyPathUtil.getLogicalResource( continuumLocator.getResourcePath() );
+        if ( logicalResource.startsWith( "/" ) )
+        {
+            logicalResource = logicalResource.substring( 1 );
+        }
+
+        File resourceFile = getResourceFile( continuumLocator.getProjectId(), logicalResource );
+
+        if ( !resourceFile.exists() || ( continuumLocator.getHref( false ).endsWith( "/" ) &&
+            !resourceFile.isDirectory() ) )
+        {
+            // force a resource not found
+            log.error( "Resource file '" + resourceFile.getAbsolutePath() + "' does not exist" );
+            throw new DavException( HttpServletResponse.SC_NOT_FOUND, "Resource does not exist" );
+        }
+        else
+        {
+            return createResource( resourceFile, logicalResource, request.getDavSession(), continuumLocator );
+        }
+    }
+
+    public BuildAgentConfigurationService getBuildAgentConfigurationService()
+    {
+        return buildAgentConfigurationService;
+    }
+
+    public MimetypesFileTypeMap getMimeTypes()
+    {
+        return mimeTypes;
+    }
+
+    public void setBuildAgentConfigurationService( BuildAgentConfigurationService buildAgentConfigurationService )
+    {
+        this.buildAgentConfigurationService = buildAgentConfigurationService;
+    }
+
+    private ContinuumBuildAgentDavResourceLocator checkLocatorIsInstanceOfContinuumBuildAgentLocator(
+        DavResourceLocator locator )
+        throws DavException
+    {
+        if ( !( locator instanceof ContinuumBuildAgentDavResourceLocator ) )
+        {
+            throw new DavException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+                                    "Locator does not implement ContinuumBuildAgentLocator" );
+        }
+
+        // Hidden paths
+        if ( locator.getResourcePath().startsWith( ContinuumBuildAgentDavResource.HIDDEN_PATH_PREFIX ) )
+        {
+            throw new DavException( HttpServletResponse.SC_NOT_FOUND );
+        }
+
+        ContinuumBuildAgentDavResourceLocator continuumLocator = (ContinuumBuildAgentDavResourceLocator) locator;
+        if ( continuumLocator.getProjectId() <= 0 )
+        {
+            log.error( "Invalid project id: " + continuumLocator.getProjectId() );
+            throw new DavException( HttpServletResponse.SC_NO_CONTENT );
+        }
+
+        return continuumLocator;
+    }
+
+    protected File getResourceFile( int projectId, String logicalResource )
+    {
+        File workingDir = buildAgentConfigurationService.getWorkingDirectory( projectId );
+
+        return new File( workingDir, logicalResource );
+    }
+
+    protected DavResource createResource( File resourceFile, String logicalResource, DavSession session,
+                                          ContinuumBuildAgentDavResourceLocator locator )
+    {
+        return new ContinuumBuildAgentDavResource( resourceFile.getAbsolutePath(), logicalResource, session, locator,
+                                                   this, mimeTypes );
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/ContinuumBuildAgentDavResourceLocator.java b/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/ContinuumBuildAgentDavResourceLocator.java
new file mode 100644
index 0000000..d4e49db
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/ContinuumBuildAgentDavResourceLocator.java
@@ -0,0 +1,156 @@
+package org.apache.continuum.webdav;
+
+/*
+ * 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 org.apache.jackrabbit.util.Text;
+import org.apache.jackrabbit.webdav.DavLocatorFactory;
+import org.apache.jackrabbit.webdav.DavResourceLocator;
+
+public class ContinuumBuildAgentDavResourceLocator
+    implements DavResourceLocator
+{
+    private final String prefix;
+
+    private final String resourcePath;
+
+    private final String href;
+
+    private final DavLocatorFactory davLocatorFactory;
+
+    private final int projectId;
+
+    public ContinuumBuildAgentDavResourceLocator( String prefix, String resourcePath,
+                                                  DavLocatorFactory davLocatorFactory, int projectId )
+    {
+        this.prefix = prefix;
+        this.davLocatorFactory = davLocatorFactory;
+        this.projectId = projectId;
+
+        String escapedPath = Text.escapePath( resourcePath );
+        String hrefPrefix = prefix;
+
+        // Ensure no extra slashes when href is joined
+        if ( hrefPrefix.endsWith( "/" ) && escapedPath.startsWith( "/" ) )
+        {
+            hrefPrefix = hrefPrefix.substring( 0, hrefPrefix.length() - 1 );
+        }
+
+        href = hrefPrefix + escapedPath;
+
+        String path = resourcePath;
+
+        if ( !resourcePath.startsWith( "/" ) )
+        {
+            path = "/" + resourcePath;
+        }
+
+        //Remove trailing slashes otherwise Text.getRelativeParent fails
+        if ( resourcePath.endsWith( "/" ) && resourcePath.length() > 1 )
+        {
+            path = resourcePath.substring( 0, resourcePath.length() - 1 );
+        }
+
+        this.resourcePath = path;
+    }
+
+    public DavLocatorFactory getFactory()
+    {
+        return davLocatorFactory;
+    }
+
+    public String getHref( boolean isCollection )
+    {
+        // avoid doubled trailing '/' for the root item
+        String suffix = ( isCollection && !isRootLocation() && !href.endsWith( "/" ) ) ? "/" : "";
+        return href + suffix;
+    }
+
+    public String getPrefix()
+    {
+        return prefix;
+    }
+
+    public int getProjectId()
+    {
+        return projectId;
+    }
+
+    public String getRepositoryPath()
+    {
+        return getResourcePath();
+    }
+
+    public String getResourcePath()
+    {
+        return resourcePath;
+    }
+
+    public String getWorkspaceName()
+    {
+        return "";
+    }
+
+    public String getWorkspacePath()
+    {
+        return "";
+    }
+
+    /**
+     * Computes the hash code from the href, which is built using the final fields prefix and resourcePath.
+     *
+     * @return the hash code
+     */
+    public int hashCode()
+    {
+        return href.hashCode();
+    }
+
+    public boolean isRootLocation()
+    {
+        return "/".equals( resourcePath );
+    }
+
+    public boolean isSameWorkspace( DavResourceLocator locator )
+    {
+        return isSameWorkspace( locator.getWorkspaceName() );
+    }
+
+    public boolean isSameWorkspace( String workspaceName )
+    {
+        return getWorkspaceName().equals( workspaceName );
+    }
+
+    /**
+     * Equality of path is achieved if the specified object is a <code>DavResourceLocator</code> object with the same
+     * hash code.
+     *
+     * @param obj the object to compare to
+     * @return <code>true</code> if the 2 objects are equal; <code>false</code> otherwise
+     */
+    public boolean equals( Object obj )
+    {
+        if ( obj instanceof DavResourceLocator )
+        {
+            DavResourceLocator other = (DavResourceLocator) obj;
+            return hashCode() == other.hashCode();
+        }
+        return false;
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/ContinuumBuildAgentDavSession.java b/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/ContinuumBuildAgentDavSession.java
new file mode 100644
index 0000000..f463261
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/ContinuumBuildAgentDavSession.java
@@ -0,0 +1,56 @@
+package org.apache.continuum.webdav;
+
+/*
+ * 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 org.apache.jackrabbit.webdav.DavSession;
+
+import java.util.HashSet;
+
+public class ContinuumBuildAgentDavSession
+    implements DavSession
+{
+    private final HashSet<String> lockTokens = new HashSet<String>();
+
+    public void addLockToken( String token )
+    {
+        lockTokens.add( token );
+    }
+
+    public void addReference( Object reference )
+    {
+        throw new UnsupportedOperationException( "Not supported yet" );
+    }
+
+    public String[] getLockTokens()
+    {
+        return (String[]) lockTokens.toArray( new String[lockTokens.size()] );
+    }
+
+    public void removeLockToken( String token )
+    {
+        lockTokens.remove( token );
+    }
+
+    public void removeReference( Object reference )
+    {
+        throw new UnsupportedOperationException( "Not supported yet" );
+    }
+
+}
diff --git a/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/ContinuumBuildAgentDavSessionProvider.java b/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/ContinuumBuildAgentDavSessionProvider.java
new file mode 100644
index 0000000..14352ae
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/ContinuumBuildAgentDavSessionProvider.java
@@ -0,0 +1,97 @@
+package org.apache.continuum.webdav;
+
+/*
+ * 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 org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavSessionProvider;
+import org.apache.jackrabbit.webdav.WebdavRequest;
+import org.codehaus.plexus.util.Base64;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.http.HttpServletResponse;
+
+public class ContinuumBuildAgentDavSessionProvider
+    implements DavSessionProvider
+{
+    private Logger log = LoggerFactory.getLogger( this.getClass() );
+
+    private BuildAgentConfigurationService buildAgentConfigurationService;
+
+    public ContinuumBuildAgentDavSessionProvider( BuildAgentConfigurationService buildAgentConfigurationService )
+    {
+        this.buildAgentConfigurationService = buildAgentConfigurationService;
+    }
+
+    public boolean attachSession( WebdavRequest request )
+        throws DavException
+    {
+        if ( !isAuthorized( request ) )
+        {
+            throw new DavException( HttpServletResponse.SC_UNAUTHORIZED );
+        }
+
+        request.setDavSession( new ContinuumBuildAgentDavSession() );
+
+        return true;
+    }
+
+    public void releaseSession( WebdavRequest request )
+    {
+        request.setDavSession( null );
+    }
+
+    private boolean isAuthorized( WebdavRequest request )
+    {
+        String header = request.getHeader( "Authorization" );
+
+        // in tomcat this is : authorization=Basic YWRtaW46TWFuYWdlMDc=
+        if ( header == null )
+        {
+            header = request.getHeader( "authorization" );
+        }
+
+        if ( ( header != null ) && header.startsWith( "Basic " ) )
+        {
+            String base64Token = header.substring( 6 );
+            String token = new String( Base64.decodeBase64( base64Token.getBytes() ) );
+
+            String password = "";
+            int delim = token.indexOf( ':' );
+
+            if ( delim != ( -1 ) )
+            {
+                password = token.substring( delim + 1 );
+            }
+
+            if ( buildAgentConfigurationService.getSharedSecretPassword() != null &&
+                buildAgentConfigurationService.getSharedSecretPassword().equals( password ) )
+            {
+                log.debug( "Password matches configured shared key in continuum build agent." );
+                return true;
+            }
+        }
+
+        log.warn( "Not authorized to access the working copy." );
+
+        return false;
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/WorkingCopyServlet.java b/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/WorkingCopyServlet.java
new file mode 100644
index 0000000..20cce30
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/WorkingCopyServlet.java
@@ -0,0 +1,213 @@
+package org.apache.continuum.webdav;
+
+/*
+ * 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 org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavLocatorFactory;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.DavResource;
+import org.apache.jackrabbit.webdav.DavResourceFactory;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.DavSessionProvider;
+import org.apache.jackrabbit.webdav.WebdavRequest;
+import org.apache.jackrabbit.webdav.WebdavRequestImpl;
+import org.apache.jackrabbit.webdav.WebdavResponse;
+import org.apache.jackrabbit.webdav.WebdavResponseImpl;
+import org.apache.jackrabbit.webdav.server.AbstractWebdavServlet;
+import org.codehaus.plexus.spring.PlexusToSpringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+
+import java.io.IOException;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class WorkingCopyServlet
+    extends AbstractWebdavServlet
+{
+    private Logger log = LoggerFactory.getLogger( this.getClass() );
+
+    private DavLocatorFactory locatorFactory;
+
+    private DavResourceFactory resourceFactory;
+
+    protected DavSessionProvider sessionProvider;
+
+    @Override
+    public void init( ServletConfig servletConfig )
+        throws ServletException
+    {
+        super.init( servletConfig );
+        initServers( servletConfig );
+    }
+
+    /**
+     * Service the given request. This method has been overridden and copy/pasted to allow better exception handling and
+     * to support different realms
+     *
+     * @param request
+     * @param response
+     * @throws ServletException
+     * @throws java.io.IOException
+     */
+    @Override
+    protected void service( HttpServletRequest request, HttpServletResponse response )
+        throws ServletException, IOException
+    {
+        WebdavRequest webdavRequest = new WebdavRequestImpl( request, getLocatorFactory() );
+
+        // DeltaV requires 'Cache-Control' header for all methods except 'VERSION-CONTROL' and 'REPORT'.
+        int methodCode = DavMethods.getMethodCode( request.getMethod() );
+        boolean noCache = DavMethods.isDeltaVMethod( webdavRequest ) &&
+            !( DavMethods.DAV_VERSION_CONTROL == methodCode || DavMethods.DAV_REPORT == methodCode );
+        WebdavResponse webdavResponse = new WebdavResponseImpl( response, noCache );
+        DavResource resource = null;
+
+        try
+        {
+            // make sure there is a authenticated user
+            if ( !( getDavSessionProvider() ).attachSession( webdavRequest ) )
+            {
+                return;
+            }
+
+            // check matching if=header for lock-token relevant operations
+            resource = getResourceFactory().createResource( webdavRequest.getRequestLocator(), webdavRequest,
+                                                            webdavResponse );
+
+            if ( !isPreconditionValid( webdavRequest, resource ) )
+            {
+                webdavResponse.sendError( DavServletResponse.SC_PRECONDITION_FAILED );
+                return;
+            }
+            if ( !execute( webdavRequest, webdavResponse, methodCode, resource ) )
+            {
+                super.service( request, response );
+            }
+        }
+        catch ( DavException e )
+        {
+            if ( e.getErrorCode() == HttpServletResponse.SC_UNAUTHORIZED )
+            {
+                final String msg = "Unauthorized error";
+                log.error( msg );
+                webdavResponse.sendError( e.getErrorCode(), msg );
+            }
+            else if ( e.getCause() != null )
+            {
+                webdavResponse.sendError( e.getErrorCode(), e.getCause().getMessage() );
+            }
+            else
+            {
+                webdavResponse.sendError( e.getErrorCode(), e.getMessage() );
+            }
+        }
+        finally
+        {
+            getDavSessionProvider().releaseSession( webdavRequest );
+        }
+    }
+
+    public synchronized void initServers( ServletConfig servletConfig )
+    {
+        WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(
+            servletConfig.getServletContext() );
+
+        resourceFactory = (DavResourceFactory) wac.getBean( PlexusToSpringUtils.
+            buildSpringId( ContinuumBuildAgentDavResourceFactory.class ) );
+
+        BuildAgentConfigurationService buildAgentConfigurationService = (BuildAgentConfigurationService) wac.getBean(
+            PlexusToSpringUtils.buildSpringId( BuildAgentConfigurationService.class ) );
+
+        locatorFactory = new ContinuumBuildAgentDavLocatorFactory();
+        sessionProvider = new ContinuumBuildAgentDavSessionProvider( buildAgentConfigurationService );
+    }
+
+    @Override
+    public String getAuthenticateHeaderValue()
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public DavSessionProvider getDavSessionProvider()
+    {
+        return sessionProvider;
+    }
+
+    @Override
+    public DavLocatorFactory getLocatorFactory()
+    {
+        return locatorFactory;
+    }
+
+    @Override
+    public DavResourceFactory getResourceFactory()
+    {
+        return resourceFactory;
+    }
+
+    @Override
+    protected boolean isPreconditionValid( WebdavRequest request, DavResource resource )
+    {
+        // TODO Auto-generated method stub
+        return true;
+    }
+
+    @Override
+    public void setDavSessionProvider( final DavSessionProvider sessionProvider )
+    {
+        this.sessionProvider = sessionProvider;
+    }
+
+    @Override
+    public void setLocatorFactory( final DavLocatorFactory locatorFactory )
+    {
+        this.locatorFactory = locatorFactory;
+    }
+
+    @Override
+    public void setResourceFactory( DavResourceFactory resourceFactory )
+    {
+        this.resourceFactory = resourceFactory;
+    }
+
+    @Override
+    public void destroy()
+    {
+        resourceFactory = null;
+        locatorFactory = null;
+        sessionProvider = null;
+
+        WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext( getServletContext() );
+
+        if ( wac instanceof ConfigurableApplicationContext )
+        {
+            ( (ConfigurableApplicationContext) wac ).close();
+        }
+        super.destroy();
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/util/IndexWriter.java b/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/util/IndexWriter.java
new file mode 100644
index 0000000..009de71
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/util/IndexWriter.java
@@ -0,0 +1,129 @@
+package org.apache.continuum.webdav.util;
+
+/*
+ * 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 org.apache.commons.lang.StringUtils;
+import org.apache.jackrabbit.webdav.DavResource;
+import org.apache.jackrabbit.webdav.io.OutputContext;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+public class IndexWriter
+{
+    private final String logicalResource;
+
+    private final List<File> localResources;
+
+    public IndexWriter( DavResource resource, File localResource, String logicalResource )
+    {
+        this.localResources = new ArrayList<File>();
+        this.localResources.add( localResource );
+        this.logicalResource = logicalResource;
+    }
+
+    public IndexWriter( DavResource resource, List<File> localResources, String logicalResource )
+    {
+        this.localResources = localResources;
+        this.logicalResource = logicalResource;
+    }
+
+    public void write( OutputContext outputContext )
+    {
+        outputContext.setModificationTime( new Date().getTime() );
+        outputContext.setContentType( "text/html" );
+        outputContext.setETag( "" );
+        if ( outputContext.hasStream() )
+        {
+            PrintWriter writer = new PrintWriter( outputContext.getOutputStream() );
+            writeDocumentStart( writer );
+            writeHyperlinks( writer );
+            writeDocumentEnd( writer );
+            writer.flush();
+            writer.close();
+        }
+    }
+
+    private void writeDocumentStart( PrintWriter writer )
+    {
+        writer.println( "<html>" );
+        writer.println( "<head>" );
+        writer.println( "<title>Working Copy: /" + logicalResource + "</title>" );
+        writer.println( "</head>" );
+        writer.println( "<body>" );
+        writer.println( "<h3>Working Copy: /" + logicalResource + "</h3>" );
+
+        // Check if not root
+        if ( logicalResource.length() > 0 )
+        {
+            File file = new File( logicalResource );
+            String parentName = file.getParent() == null ? "/" : file.getParent();
+
+            //convert to unix path in case archiva is hosted on windows
+            parentName = StringUtils.replace( parentName, "\\", "/" );
+
+            writer.println( "<ul>" );
+            writer.println( "<li><a href=\"../\">" + parentName + "</a> <i><small>(Parent)</small></i></li>" );
+            writer.println( "</ul>" );
+        }
+
+        writer.println( "</ul>" );
+    }
+
+    private void writeDocumentEnd( PrintWriter writer )
+    {
+        writer.println( "</ul>" );
+        writer.println( "</body>" );
+        writer.println( "</html>" );
+    }
+
+    private void writeHyperlinks( PrintWriter writer )
+    {
+        for ( File localResource : localResources )
+        {
+            List<File> files = new ArrayList<File>( Arrays.asList( localResource.listFiles() ) );
+            Collections.sort( files );
+
+            for ( File file : files )
+            {
+                writeHyperlink( writer, file.getName(), file.isDirectory() );
+            }
+        }
+    }
+
+    private void writeHyperlink( PrintWriter writer, String resourceName, boolean directory )
+    {
+        if ( directory && !"CVS".equals( resourceName ) && !".svn".equals( resourceName ) && !"SCCS".equals(
+            resourceName ) )
+        {
+            writer.println( "<li><a href=\"" + resourceName + "/\">" + resourceName + "</a></li>" );
+        }
+        else if ( !directory && !".cvsignore".equals( resourceName ) && !"vssver.scc".equals( resourceName ) &&
+            !".DS_Store".equals( resourceName ) && !"release.properties".equals( resourceName ) )
+        {
+            writer.println( "<li><a href=\"" + resourceName + "\">" + resourceName + "</a></li>" );
+        }
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/util/WebdavMethodUtil.java b/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/util/WebdavMethodUtil.java
new file mode 100644
index 0000000..8bbe1fd
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/util/WebdavMethodUtil.java
@@ -0,0 +1,50 @@
+package org.apache.continuum.webdav.util;
+
+/*
+ * 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 org.apache.commons.lang.StringUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+public class WebdavMethodUtil
+{
+    private static final List<String> READ_METHODS;
+
+    static
+    {
+        READ_METHODS = new ArrayList<String>();
+        READ_METHODS.add( "HEAD" );
+        READ_METHODS.add( "GET" );
+        READ_METHODS.add( "PROPFIND" );
+        READ_METHODS.add( "OPTIONS" );
+        READ_METHODS.add( "REPORT" );
+    }
+
+    public static boolean isReadMethod( String method )
+    {
+        if ( StringUtils.isBlank( method ) )
+        {
+            throw new IllegalArgumentException( "WebDAV method is empty" );
+        }
+        return READ_METHODS.contains( method.toUpperCase( Locale.US ) );
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/util/WorkingCopyPathUtil.java b/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/util/WorkingCopyPathUtil.java
new file mode 100644
index 0000000..351b087
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webdav/src/main/java/org/apache/continuum/webdav/util/WorkingCopyPathUtil.java
@@ -0,0 +1,121 @@
+package org.apache.continuum.webdav.util;
+
+/*
+ * 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 org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.StringUtils;
+
+public class WorkingCopyPathUtil
+{
+    public static String getLogicalResource( final String href )
+    {
+        String logicalResource = null;
+        String requestPathInfo = StringUtils.defaultString( href );
+
+        //remove prefix ie /workingcopy/blah becomes /blah
+        requestPathInfo = removePrefix( requestPathInfo );
+
+        // Remove prefixing slash as the project id doesn't contain it;
+        if ( requestPathInfo.startsWith( "/" ) )
+        {
+            requestPathInfo = requestPathInfo.substring( 1 );
+        }
+
+        int slash = requestPathInfo.indexOf( '/' );
+        if ( slash > 0 )
+        {
+            logicalResource = requestPathInfo.substring( slash );
+
+            if ( logicalResource.endsWith( "/.." ) )
+            {
+                logicalResource += "/";
+            }
+
+            if ( logicalResource != null && logicalResource.startsWith( "//" ) )
+            {
+                logicalResource = logicalResource.substring( 1 );
+            }
+
+            if ( logicalResource == null )
+            {
+                logicalResource = "/";
+            }
+        }
+        else
+        {
+            logicalResource = "/";
+        }
+        return logicalResource;
+    }
+
+    public static int getProjectId( final String href )
+    {
+        String requestPathInfo = StringUtils.defaultString( href );
+
+        // Remove prefix ie /workingcopy/blah becomes /blah
+        requestPathInfo = removePrefix( requestPathInfo );
+
+        // Remove prefixing slash as the project id doesn't contain it;
+        if ( requestPathInfo.startsWith( "/" ) )
+        {
+            requestPathInfo = requestPathInfo.substring( 1 );
+        }
+
+        int projectId = 0;
+
+        try
+        {
+            // Find first element, if slash exists.
+            int slash = requestPathInfo.indexOf( '/' );
+            if ( slash > 0 )
+            {
+                // Filtered: "1/src/main/java/" -> "1"
+                projectId = Integer.parseInt( requestPathInfo.substring( 0, slash ) );
+            }
+            else
+            {
+                projectId = Integer.parseInt( requestPathInfo );
+            }
+        }
+        catch ( NumberFormatException e )
+        {
+        }
+
+        return projectId;
+    }
+
+    private static String removePrefix( final String href )
+    {
+        String[] parts = StringUtils.split( href, '/' );
+        parts = (String[]) ArrayUtils.subarray( parts, 1, parts.length );
+        if ( parts == null || parts.length == 0 )
+        {
+            return "/";
+        }
+
+        String joinedString = StringUtils.join( parts, '/' );
+        if ( href.endsWith( "/" ) )
+        {
+            joinedString = joinedString + "/";
+        }
+
+        return joinedString;
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/ContinuumBuildAgentDavResourceFactoryTest.java b/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/ContinuumBuildAgentDavResourceFactoryTest.java
new file mode 100644
index 0000000..e15565f
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/ContinuumBuildAgentDavResourceFactoryTest.java
@@ -0,0 +1,157 @@
+package org.apache.continuum.webdav;
+
+/*
+ * 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 org.apache.commons.io.FileUtils;
+import org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavResourceLocator;
+import org.apache.jackrabbit.webdav.DavServletRequest;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.codehaus.plexus.spring.PlexusInSpringTestCase;
+import org.easymock.MockControl;
+
+import java.io.File;
+
+public class ContinuumBuildAgentDavResourceFactoryTest
+    extends PlexusInSpringTestCase
+{
+    private MockControl requestControl;
+
+    private DavServletRequest request;
+
+    private MockControl responseControl;
+
+    private DavServletResponse response;
+
+    private MockControl buildAgentConfigurationServiceControl;
+
+    private BuildAgentConfigurationService buildAgentConfigurationService;
+
+    private ContinuumBuildAgentDavResourceFactory resourceFactory;
+
+    private File workingDirectory;
+
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        requestControl = MockControl.createControl( DavServletRequest.class );
+        request = (DavServletRequest) requestControl.getMock();
+
+        responseControl = MockControl.createControl( DavServletResponse.class );
+        response = (DavServletResponse) responseControl.getMock();
+        responseControl.setDefaultMatcher( MockControl.ALWAYS_MATCHER );
+
+        buildAgentConfigurationServiceControl = MockControl.
+            createControl( BuildAgentConfigurationService.class );
+        buildAgentConfigurationService =
+            (BuildAgentConfigurationService) buildAgentConfigurationServiceControl.getMock();
+
+        resourceFactory = new ContinuumBuildAgentDavResourceFactory();
+        resourceFactory.setBuildAgentConfigurationService( buildAgentConfigurationService );
+
+        String appserverBase = getTestFile( "target/appserver-base" ).getAbsolutePath();
+        System.setProperty( "appserver.base", appserverBase );
+
+        workingDirectory = new File( appserverBase, "data/working-directory" );
+
+        new File( workingDirectory, "1/target" ).mkdirs();
+        new File( workingDirectory, "1/target/continuum-artifact-1.0.jar" ).createNewFile();
+    }
+
+    @Override
+    public void tearDown()
+        throws Exception
+    {
+        if ( workingDirectory.exists() )
+        {
+            FileUtils.deleteDirectory( workingDirectory );
+        }
+
+        super.tearDown();
+    }
+
+    public void testRequestArtifact()
+        throws Exception
+    {
+        DavResourceLocator locator = new ContinuumBuildAgentDavResourceLocator( "http://myhost/",
+                                                                                "/workingcopy/1/target/continuum-artifact-1.0.jar",
+                                                                                new ContinuumBuildAgentDavLocatorFactory(),
+                                                                                1 );
+
+        try
+        {
+            requestControl.expectAndReturn( request.getMethod(), "GET" );
+            buildAgentConfigurationServiceControl.
+                expectAndReturn( buildAgentConfigurationService.getWorkingDirectory( 1 ), getWorkingDirectory( 1 ) );
+            requestControl.expectAndReturn( request.getDavSession(), new ContinuumBuildAgentDavSession() );
+
+            requestControl.replay();
+            buildAgentConfigurationServiceControl.replay();
+
+            resourceFactory.createResource( locator, request, response );
+
+            requestControl.verify();
+            buildAgentConfigurationServiceControl.verify();
+        }
+        catch ( DavException e )
+        {
+            fail( "A DavException should not have been thrown!" );
+        }
+    }
+
+    public void testRequestArtifactDoesNotExist()
+        throws Exception
+    {
+        DavResourceLocator locator = new ContinuumBuildAgentDavResourceLocator( "http://myhost/",
+                                                                                "/workingcopy/1/pom.xml",
+                                                                                new ContinuumBuildAgentDavLocatorFactory(),
+                                                                                1 );
+
+        try
+        {
+            requestControl.expectAndReturn( request.getMethod(), "GET", 1 );
+            buildAgentConfigurationServiceControl.
+                expectAndReturn( buildAgentConfigurationService.getWorkingDirectory( 1 ), getWorkingDirectory( 1 ) );
+
+            requestControl.replay();
+            buildAgentConfigurationServiceControl.replay();
+
+            resourceFactory.createResource( locator, request, response );
+
+            requestControl.verify();
+            buildAgentConfigurationServiceControl.verify();
+
+            fail( "A DavException with 404 error code should have been thrown." );
+        }
+        catch ( DavException e )
+        {
+            assertEquals( 404, e.getErrorCode() );
+        }
+    }
+
+    private File getWorkingDirectory( int projectId )
+    {
+        return new File( workingDirectory, String.valueOf( projectId ) );
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/ContinuumBuildAgentDavResourceLocatorTest.java b/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/ContinuumBuildAgentDavResourceLocatorTest.java
new file mode 100644
index 0000000..7fb2d00
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/ContinuumBuildAgentDavResourceLocatorTest.java
@@ -0,0 +1,111 @@
+package org.apache.continuum.webdav;
+
+/*
+ * 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 junit.framework.TestCase;
+
+public class ContinuumBuildAgentDavResourceLocatorTest
+    extends TestCase
+{
+    private ContinuumBuildAgentDavLocatorFactory factory;
+
+    private ContinuumBuildAgentDavResourceLocator locator;
+
+    @Override
+    protected void setUp()
+        throws Exception
+    {
+        super.setUp();
+        factory = new ContinuumBuildAgentDavLocatorFactory();
+    }
+
+    public void testAvoidDoubleSlashInHref()
+        throws Exception
+    {
+        String prefix = "http://myhost/";
+        String href = "/workingcopy/1/";
+        locator = getLocator( prefix, href );
+
+        assertEquals( 1, locator.getProjectId() );
+        assertEquals( "", locator.getWorkspaceName() );
+        assertEquals( "", locator.getWorkspacePath() );
+        assertEquals( "http://myhost/", locator.getPrefix() );
+        assertEquals( "http://myhost/workingcopy/1/", locator.getHref( false ) );
+        assertEquals( "http://myhost/workingcopy/1/", locator.getHref( true ) );
+        assertEquals( "/workingcopy/1", locator.getResourcePath() );
+        assertEquals( "/workingcopy/1", locator.getRepositoryPath() );
+    }
+
+    public void testLocatorWithPrefixHref()
+        throws Exception
+    {
+        String prefix = "http://myhost/";
+        String href = "/workingcopy/1";
+        locator = getLocator( prefix, href );
+
+        assertEquals( 1, locator.getProjectId() );
+        assertEquals( "", locator.getWorkspaceName() );
+        assertEquals( "", locator.getWorkspacePath() );
+        assertEquals( "http://myhost/", locator.getPrefix() );
+        assertEquals( "http://myhost/workingcopy/1", locator.getHref( false ) );
+        assertEquals( "http://myhost/workingcopy/1/", locator.getHref( true ) );
+        assertEquals( "/workingcopy/1", locator.getResourcePath() );
+        assertEquals( "/workingcopy/1", locator.getRepositoryPath() );
+    }
+
+    public void testLocatorWithHrefThatContainsPrefix()
+        throws Exception
+    {
+        String prefix = "http://myhost/";
+        String href = "http://myhost/workingcopy/1";
+        locator = getLocator( prefix, href );
+
+        assertEquals( 1, locator.getProjectId() );
+        assertEquals( "", locator.getWorkspaceName() );
+        assertEquals( "", locator.getWorkspacePath() );
+        assertEquals( "http://myhost/", locator.getPrefix() );
+        assertEquals( "http://myhost/workingcopy/1", locator.getHref( false ) );
+        assertEquals( "http://myhost/workingcopy/1/", locator.getHref( true ) );
+        assertEquals( "/workingcopy/1", locator.getResourcePath() );
+        assertEquals( "/workingcopy/1", locator.getRepositoryPath() );
+    }
+
+    public void testLocatorWithRootHref()
+        throws Exception
+    {
+        String prefix = "http://myhost/";
+        String href = "/";
+        locator = getLocator( prefix, href );
+
+        assertEquals( 0, locator.getProjectId() );
+        assertEquals( "", locator.getWorkspaceName() );
+        assertEquals( "", locator.getWorkspacePath() );
+        assertEquals( "http://myhost/", locator.getPrefix() );
+        assertEquals( "http://myhost/", locator.getHref( false ) );
+        assertEquals( "http://myhost/", locator.getHref( true ) );
+        assertEquals( "/", locator.getResourcePath() );
+        assertEquals( "/", locator.getRepositoryPath() );
+    }
+
+    private ContinuumBuildAgentDavResourceLocator getLocator( String prefix, String href )
+    {
+        return (ContinuumBuildAgentDavResourceLocator) factory.createResourceLocator( prefix, href );
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/ContinuumBuildAgentDavResourceTest.java b/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/ContinuumBuildAgentDavResourceTest.java
new file mode 100644
index 0000000..f425c9c
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/ContinuumBuildAgentDavResourceTest.java
@@ -0,0 +1,165 @@
+package org.apache.continuum.webdav;
+
+/*
+ * 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 org.apache.commons.io.FileUtils;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavResource;
+import org.apache.jackrabbit.webdav.DavResourceFactory;
+import org.apache.jackrabbit.webdav.DavResourceLocator;
+import org.apache.jackrabbit.webdav.DavServletRequest;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.DavSession;
+import org.codehaus.plexus.spring.PlexusInSpringTestCase;
+
+import java.io.File;
+import javax.activation.MimetypesFileTypeMap;
+
+public class ContinuumBuildAgentDavResourceTest
+    extends PlexusInSpringTestCase
+{
+    private DavSession session;
+
+    private DavResourceFactory resourceFactory;
+
+    private ContinuumBuildAgentDavResourceLocator resourceLocator;
+
+    private DavResource resource;
+
+    private MimetypesFileTypeMap mimeTypes;
+
+    private File baseDir;
+
+    private File resourceFile;
+
+    private final String RESOURCE_FILE = "resource.jar";
+
+    @Override
+    protected void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        session = new ContinuumBuildAgentDavSession();
+
+        mimeTypes = new MimetypesFileTypeMap();
+        mimeTypes.addMimeTypes( "application/java-archive jar war ear" );
+        mimeTypes.addMimeTypes( "application/java-class class" );
+        mimeTypes.addMimeTypes( "image/png png" );
+
+        baseDir = getTestFile( "target/DavResourceTest" );
+        baseDir.mkdirs();
+        resourceFile = new File( baseDir, RESOURCE_FILE );
+        resourceFile.createNewFile();
+
+        resourceFactory = new RootContextDavResourceFactory();
+        resourceLocator = (ContinuumBuildAgentDavResourceLocator) new ContinuumBuildAgentDavLocatorFactory().
+            createResourceLocator( "/", RESOURCE_FILE );
+        resource = getDavResource( resourceLocator.getHref( false ), resourceFile );
+    }
+
+    @Override
+    protected void tearDown()
+        throws Exception
+    {
+        if ( baseDir.exists() )
+        {
+            FileUtils.deleteDirectory( baseDir );
+        }
+
+        super.tearDown();
+    }
+
+    public void testAddResource()
+        throws Exception
+    {
+        File newResource = new File( baseDir, "newResource.jar" );
+        assertFalse( newResource.exists() );
+        try
+        {
+            resource.getCollection().addMember( resource, null );
+            fail( "Should have thrown an UnsupportedOperationException" );
+        }
+        catch ( UnsupportedOperationException e )
+        {
+            assertFalse( newResource.exists() );
+        }
+    }
+
+    public void testDeleteCollection()
+        throws Exception
+    {
+        File dir = new File( baseDir, "testdir" );
+        try
+        {
+            assertTrue( dir.mkdir() );
+            DavResource directoryResource = getDavResource( "/testdir", dir );
+            directoryResource.getCollection().removeMember( directoryResource );
+            fail( "Should have thrown an UnsupportedOperationException" );
+        }
+        catch ( UnsupportedOperationException e )
+        {
+            assertTrue( dir.exists() );
+        }
+        finally
+        {
+            FileUtils.deleteDirectory( dir );
+        }
+    }
+
+    public void testDeleteResource()
+        throws Exception
+    {
+        assertTrue( resourceFile.exists() );
+        try
+        {
+            resource.getCollection().removeMember( resource );
+            fail( "Should have thrown an UnsupportedOperationException" );
+        }
+        catch ( UnsupportedOperationException e )
+        {
+            assertTrue( resourceFile.exists() );
+        }
+    }
+
+    private DavResource getDavResource( String logicalPath, File file )
+    {
+        return new ContinuumBuildAgentDavResource( file.getAbsolutePath(), logicalPath, session, resourceLocator,
+                                                   resourceFactory, mimeTypes );
+    }
+
+    private class RootContextDavResourceFactory
+        implements DavResourceFactory
+    {
+        public DavResource createResource( DavResourceLocator locator, DavServletRequest request,
+                                           DavServletResponse response )
+            throws DavException
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public DavResource createResource( DavResourceLocator locator, DavSession session )
+            throws DavException
+        {
+            return new ContinuumBuildAgentDavResource( baseDir.getAbsolutePath(), "/", session, resourceLocator,
+                                                       resourceFactory, mimeTypes );
+        }
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/ContinuumBuildAgentDavSessionProviderTest.java b/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/ContinuumBuildAgentDavSessionProviderTest.java
new file mode 100644
index 0000000..8295c72
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/ContinuumBuildAgentDavSessionProviderTest.java
@@ -0,0 +1,403 @@
+package org.apache.continuum.webdav;
+
+/*
+ * 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 junit.framework.TestCase;
+import org.apache.commons.io.IOUtils;
+import org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
+import org.apache.jackrabbit.webdav.DavSessionProvider;
+import org.apache.jackrabbit.webdav.WebdavRequest;
+import org.apache.jackrabbit.webdav.WebdavRequestImpl;
+import org.codehaus.plexus.util.Base64;
+import org.easymock.MockControl;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.Principal;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Map;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+public class ContinuumBuildAgentDavSessionProviderTest
+    extends TestCase
+{
+    private DavSessionProvider sessionProvider;
+
+    private WebdavRequest request;
+
+    private MockControl buildAgentConfigurationServiceControl;
+
+    private BuildAgentConfigurationService buildAgentConfigurationService;
+
+    @Override
+    protected void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        buildAgentConfigurationServiceControl = MockControl.
+            createControl( BuildAgentConfigurationService.class );
+        buildAgentConfigurationService =
+            (BuildAgentConfigurationService) buildAgentConfigurationServiceControl.getMock();
+
+        sessionProvider = new ContinuumBuildAgentDavSessionProvider( buildAgentConfigurationService );
+        request = new WebdavRequestImpl( new HttpServletRequestMock(), null );
+
+        buildAgentConfigurationServiceControl.expectAndReturn( buildAgentConfigurationService.getSharedSecretPassword(),
+                                                               "secret", 2 );
+
+        buildAgentConfigurationServiceControl.replay();
+
+    }
+
+    public void testAttachSession()
+        throws Exception
+    {
+        assertNull( request.getDavSession() );
+
+        sessionProvider.attachSession( request );
+
+        buildAgentConfigurationServiceControl.verify();
+
+        assertNotNull( request.getDavSession() );
+    }
+
+    public void testReleaseSession()
+        throws Exception
+    {
+        assertNull( request.getDavSession() );
+
+        sessionProvider.attachSession( request );
+
+        buildAgentConfigurationServiceControl.verify();
+
+        assertNotNull( request.getDavSession() );
+
+        sessionProvider.releaseSession( request );
+        assertNull( request.getDavSession() );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private class HttpServletRequestMock
+        implements HttpServletRequest
+    {
+        public Object getAttribute( String arg0 )
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public Enumeration getAttributeNames()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public String getCharacterEncoding()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public int getContentLength()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public String getContentType()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public ServletInputStream getInputStream()
+            throws IOException
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public String getLocalAddr()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public String getLocalName()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public int getLocalPort()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public Locale getLocale()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public Enumeration getLocales()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public String getParameter( String arg0 )
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public Map getParameterMap()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public Enumeration getParameterNames()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public String[] getParameterValues( String arg0 )
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public String getProtocol()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public BufferedReader getReader()
+            throws IOException
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public String getRealPath( String arg0 )
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public String getRemoteAddr()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public String getRemoteHost()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public int getRemotePort()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public RequestDispatcher getRequestDispatcher( String arg0 )
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public String getScheme()
+        {
+            return "";
+        }
+
+        public String getServerName()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public int getServerPort()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public boolean isSecure()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public void removeAttribute( String arg0 )
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public void setAttribute( String arg0, Object arg1 )
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public void setCharacterEncoding( String arg0 )
+            throws UnsupportedEncodingException
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+
+        public String getAuthType()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public String getContextPath()
+        {
+            return "/";
+        }
+
+        public Cookie[] getCookies()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public long getDateHeader( String arg0 )
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public String getHeader( String arg0 )
+        {
+            if ( arg0 != null && arg0.equalsIgnoreCase( "authorization" ) )
+            {
+                return getAuthorizationHeader();
+            }
+
+            return "";
+        }
+
+        public Enumeration getHeaderNames()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public Enumeration getHeaders( String arg0 )
+        {
+            Hashtable<String, String> hashTable = new Hashtable<String, String>();
+            hashTable.put( "Authorization", getAuthorizationHeader() );
+
+            return hashTable.elements();
+        }
+
+        public int getIntHeader( String arg0 )
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public String getMethod()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public String getPathInfo()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public String getPathTranslated()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public String getQueryString()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public String getRemoteUser()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public String getRequestURI()
+        {
+            return "/";
+        }
+
+        public StringBuffer getRequestURL()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public String getRequestedSessionId()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public String getServletPath()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public HttpSession getSession( boolean arg0 )
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public HttpSession getSession()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public Principal getUserPrincipal()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public boolean isRequestedSessionIdFromCookie()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public boolean isRequestedSessionIdFromURL()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public boolean isRequestedSessionIdFromUrl()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public boolean isRequestedSessionIdValid()
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        public boolean isUserInRole( String arg0 )
+        {
+            throw new UnsupportedOperationException( "Not supported yet." );
+        }
+
+        private String getAuthorizationHeader()
+        {
+            try
+            {
+                String encodedPassword = IOUtils.toString( Base64.encodeBase64( ":secret".getBytes() ) );
+                return "Basic " + encodedPassword;
+            }
+            catch ( IOException e )
+            {
+                return "";
+            }
+        }
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/ContinuumBuildAgentDavSessionTest.java b/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/ContinuumBuildAgentDavSessionTest.java
new file mode 100644
index 0000000..06e8527
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/ContinuumBuildAgentDavSessionTest.java
@@ -0,0 +1,67 @@
+package org.apache.continuum.webdav;
+
+/*
+ * 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 junit.framework.TestCase;
+
+public class ContinuumBuildAgentDavSessionTest
+    extends TestCase
+{
+    public void testTokens()
+    {
+        ContinuumBuildAgentDavSession session = new ContinuumBuildAgentDavSession();
+        final String myToken = "thisisadavtoken";
+
+        session.addLockToken( myToken );
+        assertEquals( 1, session.getLockTokens().length );
+        assertEquals( myToken, session.getLockTokens()[0] );
+
+        session.removeLockToken( myToken );
+        assertEquals( 0, session.getLockTokens().length );
+    }
+
+    public void testAddReferencesThrowsUnsupportedOperationException()
+    {
+        ContinuumBuildAgentDavSession session = new ContinuumBuildAgentDavSession();
+        try
+        {
+            session.addReference( new Object() );
+            fail( "Did not throw UnsupportedOperationException" );
+        }
+        catch ( UnsupportedOperationException e )
+        {
+            assertTrue( true );
+        }
+    }
+
+    public void testRemoveReferencesThrowsUnsupportedOperationException()
+    {
+        ContinuumBuildAgentDavSession session = new ContinuumBuildAgentDavSession();
+        try
+        {
+            session.removeReference( new Object() );
+            fail( "Did not throw UnsupportedOperationException" );
+        }
+        catch ( UnsupportedOperationException e )
+        {
+            assertTrue( true );
+        }
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/MockContinuumBuildAgentDavResource.java b/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/MockContinuumBuildAgentDavResource.java
new file mode 100644
index 0000000..33b8b3d
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/MockContinuumBuildAgentDavResource.java
@@ -0,0 +1,72 @@
+package org.apache.continuum.webdav;
+
+/*
+ * 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 org.apache.commons.io.IOUtils;
+import org.apache.continuum.webdav.util.IndexWriter;
+import org.apache.jackrabbit.webdav.DavResourceFactory;
+import org.apache.jackrabbit.webdav.DavSession;
+import org.apache.jackrabbit.webdav.io.OutputContext;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import javax.activation.MimetypesFileTypeMap;
+
+public class MockContinuumBuildAgentDavResource
+    extends ContinuumBuildAgentDavResource
+{
+    public MockContinuumBuildAgentDavResource( String localResource, String logicalResource, DavSession session,
+                                               ContinuumBuildAgentDavResourceLocator locator,
+                                               DavResourceFactory factory, MimetypesFileTypeMap mimeTypes )
+    {
+        super( localResource, logicalResource, session, locator, factory, mimeTypes );
+    }
+
+    @Override
+    public void spool( OutputContext outputContext )
+        throws IOException
+    {
+        if ( !isCollection() )
+        {
+            outputContext.setContentLength( getLocalResource().length() );
+            outputContext.setContentType( getMimeTypes().getContentType( getLocalResource() ) );
+        }
+
+        if ( !isCollection() && outputContext.hasStream() )
+        {
+            FileInputStream is = null;
+            try
+            {
+                // Write content to stream
+                is = new FileInputStream( getLocalResource() );
+                IOUtils.copy( is, outputContext.getOutputStream() );
+            }
+            finally
+            {
+                IOUtils.closeQuietly( is );
+            }
+        }
+        else if ( outputContext.hasStream() )
+        {
+            IndexWriter writer = new IndexWriter( this, getLocalResource(), getLogicalResource() );
+            writer.write( outputContext );
+        }
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/MockContinuumBuildAgentDavResourceFactory.java b/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/MockContinuumBuildAgentDavResourceFactory.java
new file mode 100644
index 0000000..edf13c9
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/MockContinuumBuildAgentDavResourceFactory.java
@@ -0,0 +1,66 @@
+package org.apache.continuum.webdav;
+
+/*
+ * 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 org.apache.jackrabbit.webdav.DavResource;
+import org.apache.jackrabbit.webdav.DavSession;
+
+import java.io.File;
+import java.io.IOException;
+
+public class MockContinuumBuildAgentDavResourceFactory
+    extends ContinuumBuildAgentDavResourceFactory
+{
+    @Override
+    protected File getResourceFile( int projectId, String logicalResource )
+    {
+        return new File( getWorkingDirectory( projectId ), logicalResource );
+    }
+
+    @Override
+    protected DavResource createResource( File resourceFile, String logicalResource, DavSession session,
+                                          ContinuumBuildAgentDavResourceLocator locator )
+    {
+        return new MockContinuumBuildAgentDavResource( resourceFile.getAbsolutePath(), logicalResource, session,
+                                                       locator, this, getMimeTypes() );
+    }
+
+    private File getWorkingDirectory( int projectId )
+    {
+        String basedir = System.getProperty( "basedir" );
+
+        if ( basedir == null )
+        {
+            basedir = new File( "" ).getAbsolutePath();
+        }
+
+        File dir = new File( basedir, "target/appserver-base/data/working-directory/" + projectId );
+
+        try
+        {
+            dir = dir.getCanonicalFile();
+        }
+        catch ( IOException e )
+        {
+        }
+
+        return dir;
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/MockWorkingCopyServlet.java b/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/MockWorkingCopyServlet.java
new file mode 100644
index 0000000..e80b6e3
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/MockWorkingCopyServlet.java
@@ -0,0 +1,45 @@
+package org.apache.continuum.webdav;
+
+/*
+ * 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 org.apache.continuum.buildagent.configuration.DefaultBuildAgentConfigurationService;
+
+import javax.servlet.ServletConfig;
+
+public class MockWorkingCopyServlet
+    extends WorkingCopyServlet
+{
+    @Override
+    public synchronized void initServers( ServletConfig servletConfig )
+    {
+        super.initServers( servletConfig );
+        sessionProvider = new ContinuumBuildAgentDavSessionProvider( new BuildAgentConfigurationServiceMock() );
+    }
+
+    public class BuildAgentConfigurationServiceMock
+        extends DefaultBuildAgentConfigurationService
+    {
+        @Override
+        public String getSharedSecretPassword()
+        {
+            return "secret";
+        }
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/WorkingCopyServletTest.java b/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/WorkingCopyServletTest.java
new file mode 100644
index 0000000..187a266
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/WorkingCopyServletTest.java
@@ -0,0 +1,201 @@
+package org.apache.continuum.webdav;
+
+/*
+ * 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 com.meterware.httpunit.GetMethodWebRequest;
+import com.meterware.httpunit.HttpUnitOptions;
+import com.meterware.httpunit.WebLink;
+import com.meterware.httpunit.WebRequest;
+import com.meterware.httpunit.WebResponse;
+import com.meterware.servletunit.ServletRunner;
+import com.meterware.servletunit.ServletUnitClient;
+import net.sf.ehcache.CacheManager;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.codehaus.plexus.spring.PlexusInSpringTestCase;
+import org.codehaus.plexus.util.Base64;
+
+import java.io.File;
+import java.io.IOException;
+import javax.servlet.http.HttpServletResponse;
+
+public class WorkingCopyServletTest
+    extends PlexusInSpringTestCase
+{
+    private static final String REQUEST_PATH = "http://machine.com/workingcopy/1/";
+
+    private WebRequest request;
+
+    private WebResponse response;
+
+    private ServletRunner sr;
+
+    private ServletUnitClient sc;
+
+    private File workingDirectory;
+
+    @Override
+    protected void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        String appserverBase = getTestFile( "target/appserver-base" ).getAbsolutePath();
+        System.setProperty( "appserver.base", appserverBase );
+
+        workingDirectory = new File( appserverBase, "data/working-directory" );
+
+        CacheManager.getInstance().removeCache( "url-failures-cache" );
+
+        HttpUnitOptions.setExceptionsThrownOnErrorStatus( false );
+
+        sr = new ServletRunner( getTestFile( "src/test/resources/WEB-INF/web.xml" ) );
+        sr.registerServlet( "/workingcopy/*", MockWorkingCopyServlet.class.getName() );
+        sc = sr.newClient();
+
+        new File( workingDirectory, "1/src/main/java/org/apache/continuum" ).mkdirs();
+        new File( workingDirectory, "1/src/main/java/org/apache/continuum/App.java" ).createNewFile();
+        new File( workingDirectory, "1/src/test" ).mkdirs();
+        new File( workingDirectory, "1/pom.xml" ).createNewFile();
+        new File( workingDirectory, "1/target" ).mkdir();
+        new File( workingDirectory, "1/target/continuum-artifact-1.0.jar" ).createNewFile();
+    }
+
+    @Override
+    protected void tearDown()
+        throws Exception
+    {
+        if ( sc != null )
+        {
+            sc.clearContents();
+        }
+
+        if ( sr != null )
+        {
+            sr.shutDown();
+        }
+
+        if ( workingDirectory.exists() )
+        {
+            FileUtils.deleteDirectory( workingDirectory );
+        }
+
+        super.tearDown();
+    }
+
+    public void testGetWorkingCopy()
+        throws Exception
+    {
+        MockWorkingCopyServlet servlet = (MockWorkingCopyServlet) sc.newInvocation( REQUEST_PATH ).getServlet();
+        assertNotNull( servlet );
+    }
+
+    public void testBrowse()
+        throws Exception
+    {
+        request = new GetMethodWebRequest( REQUEST_PATH );
+        request.setHeaderField( "Authorization", getAuthorizationHeader() );
+
+        response = sc.getResponse( request );
+        assertEquals( "Response", HttpServletResponse.SC_OK, response.getResponseCode() );
+
+        String expectedLinks[] = new String[]{"pom.xml", "src/", "target/"};
+        assertLinks( expectedLinks, response.getLinks() );
+    }
+
+    public void testBrowseSubDirectory()
+        throws Exception
+    {
+        request = new GetMethodWebRequest( REQUEST_PATH + "src/" );
+        request.setHeaderField( "Authorization", getAuthorizationHeader() );
+
+        response = sc.getResponse( request );
+        assertEquals( "Response", HttpServletResponse.SC_OK, response.getResponseCode() );
+
+        String expectedLinks[] = new String[]{"../", "main/", "test/"};
+        assertLinks( expectedLinks, response.getLinks() );
+    }
+
+    public void testGetFile()
+        throws Exception
+    {
+        request = new GetMethodWebRequest( REQUEST_PATH + "src/main/java/org/apache/continuum" );
+        request.setHeaderField( "Authorization", getAuthorizationHeader() );
+        response = sc.getResponse( request );
+        assertEquals( "Response", HttpServletResponse.SC_OK, response.getResponseCode() );
+
+        request = new GetMethodWebRequest( REQUEST_PATH + "src/main/java/org/apache/continuum/" );
+        request.setHeaderField( "Authorization", getAuthorizationHeader() );
+        response = sc.getResponse( request );
+        assertEquals( "Response", HttpServletResponse.SC_OK, response.getResponseCode() );
+
+        request = new GetMethodWebRequest( REQUEST_PATH + "src/main/java/org/apache/continuum/App.java" );
+        request.setHeaderField( "Authorization", getAuthorizationHeader() );
+        response = sc.getResponse( request );
+        assertEquals( "Response", HttpServletResponse.SC_OK, response.getResponseCode() );
+
+        request = new GetMethodWebRequest( REQUEST_PATH + "src/main/java/org/apache/continuum/App.java/" );
+        request.setHeaderField( "Authorization", getAuthorizationHeader() );
+        response = sc.getResponse( request );
+        assertEquals( "Response", HttpServletResponse.SC_NOT_FOUND, response.getResponseCode() );
+
+        request = new GetMethodWebRequest( REQUEST_PATH + "pom.xml" );
+        request.setHeaderField( "Authorization", getAuthorizationHeader() );
+        response = sc.getResponse( request );
+        assertEquals( "Response", HttpServletResponse.SC_OK, response.getResponseCode() );
+
+        request = new GetMethodWebRequest( REQUEST_PATH + "pom.xml/" );
+        request.setHeaderField( "Authorization", getAuthorizationHeader() );
+        response = sc.getResponse( request );
+        assertEquals( "Response", HttpServletResponse.SC_NOT_FOUND, response.getResponseCode() );
+
+        request = new GetMethodWebRequest( REQUEST_PATH + "target/continuum-artifact-1.0.jar" );
+        request.setHeaderField( "Authorization", getAuthorizationHeader() );
+        response = sc.getResponse( request );
+        assertEquals( "Response", HttpServletResponse.SC_OK, response.getResponseCode() );
+
+        request = new GetMethodWebRequest( REQUEST_PATH + "target/continuum-artifact-1.0.jar/" );
+        request.setHeaderField( "Authorization", getAuthorizationHeader() );
+        response = sc.getResponse( request );
+        assertEquals( "Response", HttpServletResponse.SC_NOT_FOUND, response.getResponseCode() );
+    }
+
+    private void assertLinks( String expectedLinks[], WebLink actualLinks[] )
+    {
+        assertEquals( "Links.length", expectedLinks.length, actualLinks.length );
+        for ( int i = 0; i < actualLinks.length; i++ )
+        {
+            assertEquals( "Link[" + i + "]", expectedLinks[i], actualLinks[i].getURLString() );
+        }
+    }
+
+    private String getAuthorizationHeader()
+    {
+        try
+        {
+            String encodedPassword = IOUtils.toString( Base64.encodeBase64( ":secret".getBytes() ) );
+            return "Basic " + encodedPassword;
+        }
+        catch ( IOException e )
+        {
+            return "";
+        }
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/util/WorkingCopyPathUtilTest.java b/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/util/WorkingCopyPathUtilTest.java
new file mode 100644
index 0000000..f712d21
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webdav/src/test/java/org/apache/continuum/webdav/util/WorkingCopyPathUtilTest.java
@@ -0,0 +1,52 @@
+package org.apache.continuum.webdav.util;
+
+/*
+ * 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 junit.framework.TestCase;
+
+public class WorkingCopyPathUtilTest
+    extends TestCase
+{
+    public void testGetProjectId()
+    {
+        String href = "/path/1/src/main/java";
+        assertEquals( 1, WorkingCopyPathUtil.getProjectId( href ) );
+
+        href = "path/2/src/test";
+        assertEquals( 2, WorkingCopyPathUtil.getProjectId( href ) );
+    }
+
+    public void testGetLogicalPath()
+    {
+        String href = "/workingcopy/1/src/main/java/org/apache/maven/someartifact.jar";
+        assertEquals( "/src/main/java/org/apache/maven/someartifact.jar", WorkingCopyPathUtil.getLogicalResource(
+            href ) );
+
+        href = "workingcopy/1/src/main/java/org/apache/maven/someartifact.jar";
+        assertEquals( "/src/main/java/org/apache/maven/someartifact.jar", WorkingCopyPathUtil.getLogicalResource(
+            href ) );
+
+        href = "workingcopy/1/src/main/java/";
+        assertEquals( "/src/main/java/", WorkingCopyPathUtil.getLogicalResource( href ) );
+
+        href = "workingcopy";
+        assertEquals( "/", WorkingCopyPathUtil.getLogicalResource( href ) );
+    }
+}
diff --git a/continuum-buildagent/continuum-buildagent-webdav/src/test/resources/WEB-INF/web.xml b/continuum-buildagent/continuum-buildagent-webdav/src/test/resources/WEB-INF/web.xml
new file mode 100644
index 0000000..d43b147
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webdav/src/test/resources/WEB-INF/web.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+  ~ 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.
+  -->
+
+<web-app xmlns="http://java.sun.com/xml/ns/j2ee" version="2.4"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+
+  <display-name>Apache Continuum Build Agent</display-name>
+
+  <listener>
+    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
+  </listener>
+
+  <context-param>
+    <param-name>contextClass</param-name>
+    <param-value>org.codehaus.plexus.spring.PlexusWebApplicationContext</param-value>
+  </context-param>
+
+  <context-param>
+    <param-name>contextConfigLocation</param-name>
+    <param-value>
+      classpath*:/META-INF/plexus/components.xml
+      classpath*:/META-INF/spring-context.xml
+      target/test-classes/org/apache/continuum/webdav/WorkingCopyServletTest.xml
+    </param-value>
+  </context-param>
+
+</web-app>
\ No newline at end of file
diff --git a/continuum-buildagent/continuum-buildagent-webdav/src/test/resources/org/apache/continuum/webdav/WorkingCopyServletTest.xml b/continuum-buildagent/continuum-buildagent-webdav/src/test/resources/org/apache/continuum/webdav/WorkingCopyServletTest.xml
new file mode 100644
index 0000000..8ec9a5a
--- /dev/null
+++ b/continuum-buildagent/continuum-buildagent-webdav/src/test/resources/org/apache/continuum/webdav/WorkingCopyServletTest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+  ~ 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.
+  -->
+
+<plexus>
+  <components>
+    <component>
+      <role>org.apache.continuum.webdav.ContinuumBuildAgentDavResourceFactory</role>
+      <implementation>org.apache.continuum.webdav.MockContinuumBuildAgentDavResourceFactory</implementation>
+    </component>
+  </components>
+</plexus>
\ No newline at end of file
diff --git a/continuum-buildagent/pom.xml b/continuum-buildagent/pom.xml
new file mode 100644
index 0000000..c7f38e2
--- /dev/null
+++ b/continuum-buildagent/pom.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.continuum</groupId>
+    <artifactId>continuum</artifactId>
+    <version>1.4.3</version>
+  </parent>
+
+  <artifactId>continuum-buildagent</artifactId>
+  <packaging>pom</packaging>
+  <name>Continuum :: Distributed Build :: Build Agent</name>
+
+  <modules>
+    <module>continuum-buildagent-api</module>
+    <module>continuum-buildagent-core</module>
+    <module>continuum-buildagent-webdav</module>
+    <module>continuum-buildagent-webapp</module>
+    <module>continuum-buildagent-jetty</module>
+    <module>continuum-buildagent-webdav-client</module>
+  </modules>
+</project>
diff --git a/continuum-builder/pom.xml b/continuum-builder/pom.xml
index 23ca871..72ab7e9 100644
--- a/continuum-builder/pom.xml
+++ b/continuum-builder/pom.xml
@@ -1,34 +1,32 @@
 <?xml version='1.0' encoding='UTF-8'?>
 <!--
-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.
--->
+  ~ 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.
+  -->
 
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
     <artifactId>continuum</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <artifactId>continuum-builder</artifactId>
   <name>Continuum :: Builder</name>
-  <version>1.3.1-SNAPSHOT</version>
-  <url>http://maven.apache.org</url>
   <dependencies>
     <dependency>
       <groupId>org.apache.continuum</groupId>
@@ -46,30 +44,39 @@
     </dependency>
     <dependency>
       <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-model</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
       <artifactId>continuum-commons</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-store</artifactId>
+      <artifactId>continuum-distributed-slave-client</artifactId>
     </dependency>
     <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-distributed-build-transport-slave-client</artifactId>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-component-api</artifactId>
     </dependency>
     <dependency>
-      <groupId>hsqldb</groupId>
-      <artifactId>hsqldb</artifactId>
-      <scope>test</scope>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-utils</artifactId>
     </dependency>
     <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-test</artifactId>
-      <scope>test</scope>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-taskqueue</artifactId>
     </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-log4j12</artifactId>
-      <scope>test</scope>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>backport-util-concurrent</groupId>
+      <artifactId>backport-util-concurrent</artifactId>
     </dependency>
   </dependencies>
 </project>
diff --git a/continuum-builder/src/main/java/org/apache/continuum/builder/distributed/executor/DistributedBuildProjectTaskExecutor.java b/continuum-builder/src/main/java/org/apache/continuum/builder/distributed/executor/DistributedBuildProjectTaskExecutor.java
index 0df6e9e..7938b92 100644
--- a/continuum-builder/src/main/java/org/apache/continuum/builder/distributed/executor/DistributedBuildProjectTaskExecutor.java
+++ b/continuum-builder/src/main/java/org/apache/continuum/builder/distributed/executor/DistributedBuildProjectTaskExecutor.java
@@ -19,13 +19,6 @@
  * under the License.
  */
 
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 import org.apache.continuum.builder.utils.ContinuumBuildConstant;
 import org.apache.continuum.dao.BuildDefinitionDao;
 import org.apache.continuum.dao.BuildResultDao;
@@ -37,22 +30,35 @@
 import org.apache.continuum.taskqueue.PrepareBuildProjectsTask;
 import org.apache.continuum.utils.ContinuumUtils;
 import org.apache.continuum.utils.ProjectSorter;
+import org.apache.continuum.utils.build.BuildTrigger;
 import org.apache.maven.continuum.ContinuumException;
+import org.apache.maven.continuum.configuration.ConfigurationService;
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.BuildResult;
 import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.scm.ChangeFile;
+import org.apache.maven.continuum.model.scm.ChangeSet;
+import org.apache.maven.continuum.model.scm.ScmResult;
 import org.apache.maven.continuum.project.ContinuumProjectState;
 import org.apache.maven.continuum.store.ContinuumStoreException;
 import org.codehaus.plexus.taskqueue.Task;
 import org.codehaus.plexus.taskqueue.execution.TaskExecutionException;
-import org.codehaus.plexus.util.dag.CycleDetectedException;
+import org.codehaus.plexus.util.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 public class DistributedBuildProjectTaskExecutor
     implements DistributedBuildTaskExecutor
 {
-    private Logger log = LoggerFactory.getLogger( this.getClass() );
+    private static final Logger log = LoggerFactory.getLogger( DistributedBuildProjectTaskExecutor.class );
 
     private String buildAgentUrl;
 
@@ -80,6 +86,11 @@
      */
     private BuildResultDao buildResultDao;
 
+    /**
+     * @plexus.requirement
+     */
+    private ConfigurationService configurationService;
+
     public void setBuildAgentUrl( String buildAgentUrl )
     {
         this.buildAgentUrl = buildAgentUrl;
@@ -97,16 +108,16 @@
 
         try
         {
-            SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
+            SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ), "",
+                                                                                        configurationService.getSharedSecretPassword() );
 
-            log.info( "initializing buildContext" );
-            List buildContext = initializeBuildContext( prepareBuildTask.getProjectsBuildDefinitionsMap(), 
-                                                        prepareBuildTask.getTrigger(), 
-                                                        prepareBuildTask.getScmRootAddress() );
+            log.info( "initializing buildContext for projectGroupId=" + prepareBuildTask.getProjectGroupId() );
+            List<Map<String, Object>> buildContext = initializeBuildContext(
+                prepareBuildTask.getProjectsBuildDefinitionsMap(), prepareBuildTask.getBuildTrigger(),
+                prepareBuildTask.getScmRootAddress(), prepareBuildTask.getProjectScmRootId() );
 
             startTime = System.currentTimeMillis();
             client.buildProjects( buildContext );
-
             endTime = System.currentTimeMillis();
         }
         catch ( MalformedURLException e )
@@ -122,52 +133,57 @@
         }
     }
 
-    private List initializeBuildContext( Map<Integer, Integer> projectsAndBuildDefinitions, 
-                                         int trigger, String scmRootAddress )
+    private List<Map<String, Object>> initializeBuildContext( Map<Integer, Integer> projectsAndBuildDefinitions,
+                                                              BuildTrigger buildTrigger, String scmRootAddress,
+                                                              int scmRootId )
         throws ContinuumException
     {
-        List buildContext = new ArrayList();
-        List<Project> projects = new ArrayList<Project>();
+        List<Map<String, Object>> buildContext = new ArrayList<Map<String, Object>>();
 
         try
         {
-            for ( Integer projectId : projectsAndBuildDefinitions.keySet() )
-            {
-                Project project = projectDao.getProjectWithDependencies( projectId );
-                projects.add( project );
-            }
+            ProjectScmRoot scmRoot = projectScmRootDao.getProjectScmRoot( scmRootId );
 
-            try
-            {
-                projects = ProjectSorter.getSortedProjects( projects, null );
-            }
-            catch ( CycleDetectedException e )
-            {
-                log.info( "Cycle Detected" );
-            }
+            List<Project> projects = projectDao.getProjectsWithDependenciesByGroupId(
+                scmRoot.getProjectGroup().getId() );
+            List<Project> sortedProjects = ProjectSorter.getSortedProjects( projects, null );
 
-            for ( Project project : projects )
-            {                
+            for ( Project project : sortedProjects )
+            {
+                if ( !projectsAndBuildDefinitions.containsKey( project.getId() ) )
+                {
+                    continue;
+                }
+
                 int buildDefinitionId = projectsAndBuildDefinitions.get( project.getId() );
                 BuildDefinition buildDef = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
-                BuildResult oldBuildResult =
-                    buildResultDao.getLatestBuildResultForBuildDefinition( project.getId(), buildDefinitionId );
+                BuildResult buildResult = buildResultDao.getLatestBuildResultForProject( project.getId() );
 
-                Map context = new HashMap();
-                
-                context.put( ContinuumBuildConstant.KEY_PROJECT_GROUP_ID, new Integer( project.getProjectGroup().getId() ) );
+                Map<String, Object> context = new HashMap<String, Object>();
+
+                context.put( ContinuumBuildConstant.KEY_PROJECT_GROUP_ID, project.getProjectGroup().getId() );
+                context.put( ContinuumBuildConstant.KEY_PROJECT_GROUP_NAME, project.getProjectGroup().getName() );
+                context.put( ContinuumBuildConstant.KEY_SCM_ROOT_ID, scmRootId );
                 context.put( ContinuumBuildConstant.KEY_SCM_ROOT_ADDRESS, scmRootAddress );
-                context.put( ContinuumBuildConstant.KEY_PROJECT_ID, new Integer( project.getId() ) );
+                context.put( ContinuumBuildConstant.KEY_PROJECT_ID, project.getId() );
                 context.put( ContinuumBuildConstant.KEY_PROJECT_NAME, project.getName() );
+                context.put( ContinuumBuildConstant.KEY_PROJECT_VERSION, project.getVersion() );
                 context.put( ContinuumBuildConstant.KEY_EXECUTOR_ID, project.getExecutorId() );
+                context.put( ContinuumBuildConstant.KEY_PROJECT_BUILD_NUMBER, project.getBuildNumber() );
                 context.put( ContinuumBuildConstant.KEY_SCM_URL, project.getScmUrl() );
-                context.put( ContinuumBuildConstant.KEY_PROJECT_STATE, new Integer( project.getState() ) );
+                context.put( ContinuumBuildConstant.KEY_PROJECT_STATE, project.getState() );
+                if ( buildResult != null )
+                {
+                    context.put( ContinuumBuildConstant.KEY_LATEST_UPDATE_DATE, new Date(
+                        buildResult.getLastChangedDate() ) );
+                }
 
                 LocalRepository localRepo = project.getProjectGroup().getLocalRepository();
 
                 if ( localRepo != null )
                 {
-                    context.put( ContinuumBuildConstant.KEY_LOCAL_REPOSITORY, localRepo.getLocation() );
+                    // CONTINUUM-2391
+                    context.put( ContinuumBuildConstant.KEY_LOCAL_REPOSITORY, localRepo.getName() );
                 }
                 else
                 {
@@ -192,9 +208,33 @@
                     context.put( ContinuumBuildConstant.KEY_SCM_PASSWORD, project.getScmPassword() );
                 }
 
-                context.put( ContinuumBuildConstant.KEY_BUILD_DEFINITION_ID, new Integer( buildDefinitionId ) );
+                if ( project.getScmTag() != null )
+                {
+                    context.put( ContinuumBuildConstant.KEY_SCM_TAG, project.getScmTag() );
+                }
+                else
+                {
+                    context.put( ContinuumBuildConstant.KEY_SCM_TAG, "" );
+                }
+
+                context.put( ContinuumBuildConstant.KEY_BUILD_DEFINITION_ID, buildDefinitionId );
+                String buildDefinitionLabel = buildDef.getDescription();
+                if ( StringUtils.isEmpty( buildDefinitionLabel ) )
+                {
+                    buildDefinitionLabel = buildDef.getGoals();
+                }
+                context.put( ContinuumBuildConstant.KEY_BUILD_DEFINITION_LABEL, buildDefinitionLabel );
+
                 context.put( ContinuumBuildConstant.KEY_BUILD_FILE, buildDef.getBuildFile() );
-                context.put( ContinuumBuildConstant.KEY_GOALS, buildDef.getGoals() );
+
+                if ( buildDef.getGoals() == null )
+                {
+                    context.put( ContinuumBuildConstant.KEY_GOALS, "" );
+                }
+                else
+                {
+                    context.put( ContinuumBuildConstant.KEY_GOALS, buildDef.getGoals() );
+                }
 
                 if ( buildDef.getArguments() == null )
                 {
@@ -204,8 +244,31 @@
                 {
                     context.put( ContinuumBuildConstant.KEY_ARGUMENTS, buildDef.getArguments() );
                 }
-                context.put( ContinuumBuildConstant.KEY_TRIGGER, new Integer( trigger ) );
-                context.put( ContinuumBuildConstant.KEY_BUILD_FRESH, new Boolean( buildDef.isBuildFresh() ) );
+                context.put( ContinuumBuildConstant.KEY_TRIGGER, buildTrigger.getTrigger() );
+
+                if ( buildTrigger.getTrigger() == ContinuumProjectState.TRIGGER_FORCED )
+                {
+                    if ( buildTrigger.getTriggeredBy() == null )
+                    {
+                        context.put( ContinuumBuildConstant.KEY_USERNAME, "" );
+                    }
+                    else
+                    {
+                        context.put( ContinuumBuildConstant.KEY_USERNAME, buildTrigger.getTriggeredBy() );
+                    }
+                }
+                else
+                {
+                    context.put( ContinuumBuildConstant.KEY_USERNAME, buildDef.getSchedule().getName() );
+                }
+
+                context.put( ContinuumBuildConstant.KEY_BUILD_FRESH, buildDef.isBuildFresh() );
+                context.put( ContinuumBuildConstant.KEY_ALWAYS_BUILD, buildDef.isAlwaysBuild() );
+                context.put( ContinuumBuildConstant.KEY_OLD_SCM_CHANGES, getOldScmChanges( project.getId(),
+                                                                                           buildDefinitionId ) );
+                context.put( ContinuumBuildConstant.KEY_BUILD_AGENT_URL, buildAgentUrl );
+                context.put( ContinuumBuildConstant.KEY_MAX_JOB_EXEC_TIME,
+                             buildDef.getSchedule().getMaxJobExecutionTime() );
 
                 buildContext.add( context );
             }
@@ -223,7 +286,8 @@
     {
         try
         {
-            ProjectScmRoot scmRoot = projectScmRootDao.getProjectScmRootByProjectGroupAndScmRootAddress( task.getProjectGroupId(), task.getScmRootAddress() );
+            ProjectScmRoot scmRoot = projectScmRootDao.getProjectScmRootByProjectGroupAndScmRootAddress(
+                task.getProjectGroupId(), task.getScmRootAddress() );
 
             if ( scmRoot.getState() == ContinuumProjectState.UPDATING )
             {
@@ -240,15 +304,17 @@
                     Project project = projectDao.getProject( projectId );
                     BuildDefinition buildDef = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
                     BuildResult latestBuildResult = buildResultDao.
-                                                        getLatestBuildResultForBuildDefinition( projectId, buildDefinitionId );
-                    if ( latestBuildResult == null || ( latestBuildResult.getStartTime() >= startTime && latestBuildResult.getEndTime() > 0 && 
-                           latestBuildResult.getEndTime() < endTime ) || latestBuildResult.getStartTime() < startTime )
+                        getLatestBuildResultForBuildDefinition( projectId, buildDefinitionId );
+                    if ( latestBuildResult == null ||
+                        ( latestBuildResult.getStartTime() >= startTime && latestBuildResult.getEndTime() > 0 &&
+                            latestBuildResult.getEndTime() < endTime ) || latestBuildResult.getStartTime() < startTime )
                     {
                         BuildResult buildResult = new BuildResult();
                         buildResult.setBuildDefinition( buildDef );
                         buildResult.setError( error );
                         buildResult.setState( ContinuumProjectState.ERROR );
-                        buildResult.setTrigger( task.getTrigger() );
+                        buildResult.setTrigger( task.getBuildTrigger().getTrigger() );
+                        buildResult.setUsername( task.getBuildTrigger().getTriggeredBy() );
                         buildResult.setStartTime( startTime );
                         buildResult.setEndTime( endTime );
 
@@ -263,4 +329,140 @@
             throw new TaskExecutionException( "Error while creating result", e );
         }
     }
+
+    private List<Map<String, Object>> getOldScmChanges( int projectId, int buildDefinitionId )
+        throws ContinuumStoreException
+    {
+        List<Map<String, Object>> scmChanges = new ArrayList<Map<String, Object>>();
+
+        BuildResult oldBuildResult = buildResultDao.getLatestBuildResultForBuildDefinition( projectId,
+                                                                                            buildDefinitionId );
+
+        if ( oldBuildResult != null )
+        {
+            ScmResult scmResult = getOldScmResults( projectId, oldBuildResult.getBuildNumber(),
+                                                    oldBuildResult.getEndTime() );
+
+            scmChanges = getScmChanges( scmResult );
+        }
+
+        return scmChanges;
+    }
+
+    private List<Map<String, Object>> getScmChanges( ScmResult scmResult )
+    {
+        List<Map<String, Object>> scmChanges = new ArrayList<Map<String, Object>>();
+
+        if ( scmResult != null && scmResult.getChanges() != null )
+        {
+            for ( Object obj : scmResult.getChanges() )
+            {
+                ChangeSet changeSet = (ChangeSet) obj;
+
+                Map<String, Object> map = new HashMap<String, Object>();
+                if ( StringUtils.isNotEmpty( changeSet.getAuthor() ) )
+                {
+                    map.put( ContinuumBuildConstant.KEY_CHANGESET_AUTHOR, changeSet.getAuthor() );
+                }
+                else
+                {
+                    map.put( ContinuumBuildConstant.KEY_CHANGESET_AUTHOR, "" );
+                }
+                if ( StringUtils.isNotEmpty( changeSet.getComment() ) )
+                {
+                    map.put( ContinuumBuildConstant.KEY_CHANGESET_COMMENT, changeSet.getComment() );
+                }
+                else
+                {
+                    map.put( ContinuumBuildConstant.KEY_CHANGESET_COMMENT, "" );
+                }
+                if ( changeSet.getDateAsDate() != null )
+                {
+                    map.put( ContinuumBuildConstant.KEY_CHANGESET_DATE, changeSet.getDateAsDate() );
+                }
+                map.put( ContinuumBuildConstant.KEY_CHANGESET_FILES, getScmChangeFiles( changeSet.getFiles() ) );
+                scmChanges.add( map );
+            }
+        }
+
+        return scmChanges;
+    }
+
+    private List<Map<String, String>> getScmChangeFiles( List<ChangeFile> files )
+    {
+        List<Map<String, String>> scmChangeFiles = new ArrayList<Map<String, String>>();
+
+        if ( files != null )
+        {
+            for ( ChangeFile changeFile : files )
+            {
+                Map<String, String> map = new HashMap<String, String>();
+
+                if ( StringUtils.isNotEmpty( changeFile.getName() ) )
+                {
+                    map.put( ContinuumBuildConstant.KEY_CHANGEFILE_NAME, changeFile.getName() );
+                }
+                else
+                {
+                    map.put( ContinuumBuildConstant.KEY_CHANGEFILE_NAME, "" );
+                }
+                if ( StringUtils.isNotEmpty( changeFile.getRevision() ) )
+                {
+                    map.put( ContinuumBuildConstant.KEY_CHANGEFILE_REVISION, changeFile.getRevision() );
+                }
+                else
+                {
+                    map.put( ContinuumBuildConstant.KEY_CHANGEFILE_REVISION, "" );
+                }
+                if ( StringUtils.isNotEmpty( changeFile.getStatus() ) )
+                {
+                    map.put( ContinuumBuildConstant.KEY_CHANGEFILE_STATUS, changeFile.getStatus() );
+                }
+                else
+                {
+                    map.put( ContinuumBuildConstant.KEY_CHANGEFILE_STATUS, "" );
+                }
+                scmChangeFiles.add( map );
+            }
+        }
+        return scmChangeFiles;
+    }
+
+    private ScmResult getOldScmResults( int projectId, long startId, long fromDate )
+        throws ContinuumStoreException
+    {
+        List<BuildResult> results = buildResultDao.getBuildResultsForProjectFromId( projectId, startId );
+
+        ScmResult res = new ScmResult();
+
+        if ( results != null && results.size() > 0 )
+        {
+            for ( BuildResult result : results )
+            {
+                ScmResult scmResult = result.getScmResult();
+
+                if ( scmResult != null )
+                {
+                    List<ChangeSet> changes = scmResult.getChanges();
+
+                    if ( changes != null )
+                    {
+                        for ( ChangeSet changeSet : changes )
+                        {
+                            if ( changeSet.getDate() < fromDate )
+                            {
+                                continue;
+                            }
+                            if ( !res.getChanges().contains( changeSet ) )
+                            {
+                                res.addChange( changeSet );
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return res;
+    }
 }
diff --git a/continuum-builder/src/main/java/org/apache/continuum/builder/distributed/executor/DistributedBuildTaskQueueExecutor.java b/continuum-builder/src/main/java/org/apache/continuum/builder/distributed/executor/DistributedBuildTaskQueueExecutor.java
deleted file mode 100644
index f9327c5..0000000
--- a/continuum-builder/src/main/java/org/apache/continuum/builder/distributed/executor/DistributedBuildTaskQueueExecutor.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package org.apache.continuum.builder.distributed.executor;
-
-/*
- * 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 org.codehaus.plexus.taskqueue.Task;
-
-public interface DistributedBuildTaskQueueExecutor
-{
-    String ROLE = DistributedBuildTaskQueueExecutor.class.getName();
-
-    /**
-     * Returns the build agent url of task queue executor
-     * 
-     * @return the build agent url
-     */
-    String getBuildAgentUrl();
-
-    /**
-     * Sets the build agent url of this task queue executor
-     * 
-     * @param buildAgentUrl
-     */
-    void setBuildAgentUrl( String buildAgentUrl );
-
-    /**
-     * Returns the currently executing task.
-     *
-     * @return the currently executing task.
-     */
-    Task getCurrentTask();
-
-    /**
-     * Cancels execution of this task, if it's currently running.
-     * Does NOT remove it from the associated queue!
-     *
-     * @param task The task to cancel
-     * @return true if the task was cancelled, false if the task was not executing.
-     */
-    boolean cancelTask( Task task );
-}
diff --git a/continuum-builder/src/main/java/org/apache/continuum/builder/distributed/executor/ThreadedDistributedBuildTaskQueueExecutor.java b/continuum-builder/src/main/java/org/apache/continuum/builder/distributed/executor/ThreadedDistributedBuildTaskQueueExecutor.java
index fb384bc..8b23fdf 100644
--- a/continuum-builder/src/main/java/org/apache/continuum/builder/distributed/executor/ThreadedDistributedBuildTaskQueueExecutor.java
+++ b/continuum-builder/src/main/java/org/apache/continuum/builder/distributed/executor/ThreadedDistributedBuildTaskQueueExecutor.java
@@ -19,6 +19,13 @@
  * under the License.
  */
 
+import edu.emory.mathcs.backport.java.util.concurrent.CancellationException;
+import edu.emory.mathcs.backport.java.util.concurrent.ExecutionException;
+import edu.emory.mathcs.backport.java.util.concurrent.ExecutorService;
+import edu.emory.mathcs.backport.java.util.concurrent.Executors;
+import edu.emory.mathcs.backport.java.util.concurrent.Future;
+import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
+import edu.emory.mathcs.backport.java.util.concurrent.TimeoutException;
 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;
@@ -31,14 +38,6 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import edu.emory.mathcs.backport.java.util.concurrent.CancellationException;
-import edu.emory.mathcs.backport.java.util.concurrent.ExecutionException;
-import edu.emory.mathcs.backport.java.util.concurrent.ExecutorService;
-import edu.emory.mathcs.backport.java.util.concurrent.Executors;
-import edu.emory.mathcs.backport.java.util.concurrent.Future;
-import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
-import edu.emory.mathcs.backport.java.util.concurrent.TimeoutException;
-
 /**
  * Codes were taken from Plexus' ThreadedTaskQueueExecutor
  */
@@ -49,15 +48,21 @@
 
     private static final int CANCEL_TASK = 2;
 
-    private Logger log = LoggerFactory.getLogger( this.getClass() );
+    private static final Logger log = LoggerFactory.getLogger( ThreadedDistributedBuildTaskQueueExecutor.class );
 
-    /** @requirement */
+    /**
+     * @requirement
+     */
     private TaskQueue queue;
 
-    /** @requirement */
+    /**
+     * @requirement
+     */
     private DistributedBuildTaskExecutor executor;
 
-    /** @configuration */
+    /**
+     * @configuration
+     */
     private String name;
 
     // ----------------------------------------------------------------------
@@ -91,8 +96,9 @@
                 }
                 catch ( InterruptedException e )
                 {
-                    log.info( "Executor thread interrupted, command: "
-                        + ( command == SHUTDOWN ? "Shutdown" : command == CANCEL_TASK ? "Cancel task" : "Unknown" ) );
+                    log.info( "Executor thread interrupted, command: " + ( command == SHUTDOWN
+                        ? "Shutdown"
+                        : command == CANCEL_TASK ? "Cancel task" : "Unknown" ) );
                     continue;
                 }
 
@@ -212,8 +218,9 @@
                 }
                 else
                 {
-                    log.warn( "Task not cancelled (Flags: done: " + future.isDone() + " cancelled: "
-                        + future.isCancelled() + ")" );
+                    log.warn(
+                        "Task not cancelled (Flags: done: " + future.isDone() + " cancelled: " + future.isCancelled() +
+                            ")" );
                 }
             }
             else
@@ -345,4 +352,9 @@
     {
         return executor.getBuildAgentUrl();
     }
+
+    public TaskQueue getQueue()
+    {
+        return queue;
+    }
 }
diff --git a/continuum-builder/src/main/java/org/apache/continuum/builder/distributed/taskqueue/DefaultOverallDistributedBuildQueue.java b/continuum-builder/src/main/java/org/apache/continuum/builder/distributed/taskqueue/DefaultOverallDistributedBuildQueue.java
new file mode 100644
index 0000000..a5795a2
--- /dev/null
+++ b/continuum-builder/src/main/java/org/apache/continuum/builder/distributed/taskqueue/DefaultOverallDistributedBuildQueue.java
@@ -0,0 +1,157 @@
+package org.apache.continuum.builder.distributed.taskqueue;
+
+/*
+ * 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 org.apache.commons.lang.ArrayUtils;
+import org.apache.continuum.builder.distributed.executor.DistributedBuildTaskQueueExecutor;
+import org.apache.continuum.builder.distributed.executor.ThreadedDistributedBuildTaskQueueExecutor;
+import org.apache.continuum.taskqueue.OverallDistributedBuildQueue;
+import org.apache.continuum.taskqueue.PrepareBuildProjectsTask;
+import org.codehaus.plexus.taskqueue.Task;
+import org.codehaus.plexus.taskqueue.TaskQueue;
+import org.codehaus.plexus.taskqueue.TaskQueueException;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class DefaultOverallDistributedBuildQueue
+    implements OverallDistributedBuildQueue
+{
+    private String buildAgentUrl;
+
+    private DistributedBuildTaskQueueExecutor distributedBuildTaskQueueExecutor;
+
+    public void addToDistributedBuildQueue( Task distributedBuildTask )
+        throws TaskQueueException
+    {
+        getDistributedBuildQueue().put( distributedBuildTask );
+    }
+
+    public String getBuildAgentUrl()
+    {
+        return buildAgentUrl;
+    }
+
+    public TaskQueue getDistributedBuildQueue()
+    {
+        return ( (ThreadedDistributedBuildTaskQueueExecutor) distributedBuildTaskQueueExecutor ).getQueue();
+    }
+
+    public DistributedBuildTaskQueueExecutor getDistributedBuildTaskQueueExecutor()
+    {
+        return distributedBuildTaskQueueExecutor;
+    }
+
+    public List<PrepareBuildProjectsTask> getProjectsInQueue()
+        throws TaskQueueException
+    {
+        return getDistributedBuildQueue().getQueueSnapshot();
+    }
+
+    public boolean isInDistributedBuildQueue( int projectGroupId, int scmRootId )
+        throws TaskQueueException
+    {
+        List<PrepareBuildProjectsTask> tasks = getProjectsInQueue();
+
+        for ( PrepareBuildProjectsTask task : tasks )
+        {
+            if ( task != null )
+            {
+                if ( task.getProjectGroupId() == projectGroupId && task.getProjectScmRootId() == scmRootId )
+                {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    public void removeFromDistributedBuildQueue( int projectGroupId, int scmRootId )
+        throws TaskQueueException
+    {
+        List<PrepareBuildProjectsTask> tasks = getProjectsInQueue();
+
+        for ( PrepareBuildProjectsTask task : tasks )
+        {
+            if ( task != null )
+            {
+                if ( task.getProjectGroupId() == projectGroupId && task.getProjectScmRootId() == scmRootId )
+                {
+                    getDistributedBuildQueue().remove( task );
+                    return;
+                }
+            }
+        }
+    }
+
+    public void removeFromDistributedBuildQueue( int[] hashCodes )
+        throws TaskQueueException
+    {
+        List<PrepareBuildProjectsTask> tasks = getProjectsInQueue();
+
+        List<PrepareBuildProjectsTask> tasksToRemove = new ArrayList<PrepareBuildProjectsTask>();
+
+        for ( PrepareBuildProjectsTask task : tasks )
+        {
+            if ( task != null )
+            {
+                if ( ArrayUtils.contains( hashCodes, task.getHashCode() ) )
+                {
+                    tasksToRemove.add( task );
+                }
+            }
+        }
+
+        if ( !tasksToRemove.isEmpty() )
+        {
+            getDistributedBuildQueue().removeAll( tasksToRemove );
+        }
+    }
+
+    public void removeFromDistributedBuildQueueByHashCode( int hashCode )
+        throws TaskQueueException
+    {
+        List<PrepareBuildProjectsTask> tasks = getProjectsInQueue();
+
+        for ( PrepareBuildProjectsTask task : tasks )
+        {
+            if ( task != null )
+            {
+                if ( task.getHashCode() == hashCode )
+                {
+                    getDistributedBuildQueue().remove( task );
+                    return;
+                }
+            }
+        }
+    }
+
+    public void setBuildAgentUrl( String buildAgentUrl )
+    {
+        this.buildAgentUrl = buildAgentUrl;
+    }
+
+    public void setDistributedBuildTaskQueueExecutor(
+        DistributedBuildTaskQueueExecutor distributedBuildTaskQueueExecutor )
+    {
+        this.distributedBuildTaskQueueExecutor = distributedBuildTaskQueueExecutor;
+    }
+}
diff --git a/continuum-builder/src/main/java/org/apache/continuum/builder/utils/ContinuumBuildConstant.java b/continuum-builder/src/main/java/org/apache/continuum/builder/utils/ContinuumBuildConstant.java
index 74ed55c..bf9e369 100644
--- a/continuum-builder/src/main/java/org/apache/continuum/builder/utils/ContinuumBuildConstant.java
+++ b/continuum-builder/src/main/java/org/apache/continuum/builder/utils/ContinuumBuildConstant.java
@@ -19,18 +19,33 @@
  * under the License.
  */
 
-import java.util.Map;
-
+import org.apache.continuum.utils.build.BuildTrigger;
 import org.apache.maven.continuum.model.project.BuildResult;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
 public class ContinuumBuildConstant
 {
     public static final String KEY_PROJECT_ID = "project-id";
 
+    public static final String KEY_PROJECT_VERSION = "project-version";
+
+    public static final String KEY_PROJECT_BUILD_NUMBER = "build-number";
+
     public static final String KEY_BUILD_DEFINITION_ID = "builddefinition-id";
 
+    public static final String KEY_BUILD_DEFINITION_LABEL = "builddefinition-label";
+
     public static final String KEY_TRIGGER = "trigger";
 
+    public static final String KEY_USERNAME = "username";
+
+    public static final String KEY_BUILD_TRIGGER = "buildTrigger";
+
     public static final String KEY_EXECUTOR_ID = "executor-id";
 
     public static final String KEY_SCM_URL = "scm-url";
@@ -47,9 +62,11 @@
 
     public static final String KEY_BUILD_FRESH = "build-fresh";
 
-    public static final String KEY_BUILD_START = "build-start";
+    public static final String KEY_ALWAYS_BUILD = "always-build";
 
-    public static final String KEY_BUILD_END = "build-end";
+    public static final String KEY_START_TIME = "start-time";
+
+    public static final String KEY_END_TIME = "end-time";
 
     public static final String KEY_BUILD_ERROR = "build-error";
 
@@ -69,8 +86,12 @@
 
     public static final String KEY_PROJECT_GROUP_ID = "project-group-id";
 
+    public static final String KEY_PROJECT_GROUP_NAME = "project-group-name";
+
     public static final String KEY_SCM_ROOT_ADDRESS = "scm-root-address";
 
+    public static final String KEY_SCM_ROOT_ID = "scm-root-id";
+
     public static final String KEY_SCM_ERROR = "scm-error";
 
     public static final String KEY_PROJECT_NAME = "project-name";
@@ -91,121 +112,418 @@
 
     public static final String KEY_LOCAL_REPOSITORY = "local-repository";
 
-    public static int getProjectId( Map context )
+    public static final String KEY_SCM_CHANGES = "scm-changes";
+
+    public static final String KEY_CHANGESET_ID = "changeset-id";
+
+    public static final String KEY_CHANGESET_AUTHOR = "changeset-author";
+
+    public static final String KEY_CHANGESET_COMMENT = "changeset-comment";
+
+    public static final String KEY_CHANGESET_DATE = "changeset-date";
+
+    public static final String KEY_CHANGESET_FILES = "changeset-files";
+
+    public static final String KEY_CHANGEFILE_NAME = "changefile-name";
+
+    public static final String KEY_CHANGEFILE_REVISION = "changefile-revision";
+
+    public static final String KEY_CHANGEFILE_STATUS = "changefile-status";
+
+    public static final String KEY_OLD_SCM_CHANGES = "old-scm-changes";
+
+    public static final String KEY_PROJECT_DESCRIPTION = "project-description";
+
+    public static final String KEY_GROUP_ID = "group-id";
+
+    public static final String KEY_ARTIFACT_ID = "artifact-id";
+
+    public static final String KEY_PROJECT_DEVELOPERS = "project-developers";
+
+    public static final String KEY_PROJECT_DEPENDENCIES = "project-dependencies";
+
+    public static final String KEY_PROJECT_NOTIFIERS = "project-notifiers";
+
+    public static final String KEY_PROJECT_URL = "project-url";
+
+    public static final String KEY_SCM_TAG = "scm-tag";
+
+    public static final String KEY_SCM_RESULT = "scm-result";
+
+    public static final String KEY_PROJECT_PARENT = "project-parent";
+
+    public static final String KEY_NOTIFIER_TYPE = "notifier-type";
+
+    public static final String KEY_NOTIFIER_CONFIGURATION = "notifier-configuration";
+
+    public static final String KEY_NOTIFIER_FROM = "notifier-from";
+
+    public static final String KEY_NOTIFIER_RECIPIENT_TYPE = "notifier-recipient-type";
+
+    public static final String KEY_NOTIFIER_ENABLED = "notifier-enabled";
+
+    public static final String KEY_NOTIFIER_SEND_ON_SUCCESS = "notifier-send-on-success";
+
+    public static final String KEY_NOTIFIER_SEND_ON_FAILURE = "notifier-send-on-failure";
+
+    public static final String KEY_NOTIFIER_SEND_ON_ERROR = "notifier-send-on-error";
+
+    public static final String KEY_NOTIFIER_SEND_ON_SCMFAILURE = "notifier-send-on-scmfailure";
+
+    public static final String KEY_NOTIFIER_SEND_ON_WARNING = "notifier-send-on-warning";
+
+    public static final String KEY_PROJECT_DEVELOPER_NAME = "developer-name";
+
+    public static final String KEY_PROJECT_DEVELOPER_EMAIL = "developer-email";
+
+    public static final String KEY_PROJECT_DEVELOPER_SCMID = "developer-scmid";
+
+    public static final String KEY_MAVEN_PROJECT = "maven-project";
+
+    public static final String KEY_PROJECT_MODULES = "project-modules";
+
+    public static final String KEY_LATEST_UPDATE_DATE = "latest-update-date";
+
+    public static final String KEY_BUILD_AGENT_URL = "build-agent-url";
+
+    public static final String KEY_MAX_JOB_EXEC_TIME = "max-job-exec-time";
+
+    public static int getProjectId( Map<String, Object> context )
     {
         return getInteger( context, KEY_PROJECT_ID );
     }
 
-    public static int getBuildDefinitionId( Map context )
+    public static int getBuildDefinitionId( Map<String, Object> context )
     {
         return getInteger( context, KEY_BUILD_DEFINITION_ID );
     }
 
-    public static String getBuildError( Map context )
+    public static String getBuildError( Map<String, Object> context )
     {
         return getString( context, KEY_BUILD_ERROR );
     }
 
-    public static int getTrigger( Map context )
+    public static int getTrigger( Map<String, Object> context )
     {
         return getInteger( context, KEY_TRIGGER );
     }
 
-    public static long getBuildStart( Map context )
+    public static String getUsername( Map<String, Object> context )
     {
-        return new Long( getString( context, KEY_BUILD_START ) );
+        return getString( context, KEY_USERNAME, "" );
     }
 
-    public static long getBuildEnd( Map context )
+    public static BuildTrigger getBuildTrigger( Map<String, Object> context )
     {
-        return new Long( getString( context, KEY_BUILD_END ) );
+        BuildTrigger defaultValue = new BuildTrigger( 0, "" );
+        return (BuildTrigger) getObject( context, KEY_BUILD_TRIGGER, defaultValue );
     }
 
-    public static int getBuildExitCode( Map context )
+    public static long getStartTime( Map<String, Object> context )
+    {
+        return new Long( getString( context, KEY_START_TIME ) );
+    }
+
+    public static long getEndTime( Map<String, Object> context )
+    {
+        return new Long( getString( context, KEY_END_TIME ) );
+    }
+
+    public static int getBuildExitCode( Map<String, Object> context )
     {
         return getInteger( context, KEY_BUILD_EXIT_CODE );
     }
 
-    public static int getBuildState( Map context )
+    public static int getBuildState( Map<String, Object> context )
     {
         return getInteger( context, KEY_BUILD_STATE );
     }
 
-    public static String getScmCommandLine( Map context )
+    public static String getScmCommandLine( Map<String, Object> context )
     {
         return getString( context, KEY_SCM_COMMAND_LINE );
     }
 
-    public static String getScmCommandOutput( Map context )
+    public static String getScmCommandOutput( Map<String, Object> context )
     {
         return getString( context, KEY_SCM_COMMAND_OUTPUT );
     }
 
-    public static String getScmException( Map context )
+    public static String getScmException( Map<String, Object> context )
     {
         return getString( context, KEY_SCM_EXCEPTION );
     }
 
-    public static String getScmProviderMessage( Map context )
+    public static String getScmProviderMessage( Map<String, Object> context )
     {
         return getString( context, KEY_SCM_PROVIDER_MESSAGE );
     }
 
-    public static boolean isScmSuccess( Map context )
+    public static boolean isScmSuccess( Map<String, Object> context )
     {
         return getBoolean( context, KEY_SCM_SUCCESS );
     }
 
-    public static int getProjectGroupId( Map context )
+    public static int getProjectGroupId( Map<String, Object> context )
     {
         return getInteger( context, KEY_PROJECT_GROUP_ID );
     }
 
-    public static String getScmRootAddress( Map context )
+    public static String getScmRootAddress( Map<String, Object> context )
     {
         return getString( context, KEY_SCM_ROOT_ADDRESS );
     }
 
-    public static String getScmError( Map context )
+    public static String getScmError( Map<String, Object> context )
     {
         return getString( context, KEY_SCM_ERROR );
     }
 
-    public static String getBuildOutput( Map context )
+    public static String getBuildOutput( Map<String, Object> context )
     {
         return getString( context, KEY_BUILD_OUTPUT );
     }
 
-    public static BuildResult getBuildResult( Map context, Object defaultValue )
+    public static BuildResult getBuildResult( Map<String, Object> context, Object defaultValue )
     {
         return (BuildResult) getObject( context, KEY_BUILD_RESULT, defaultValue );
     }
 
-    public static String getInstallationName( Map context )
+    public static String getInstallationName( Map<String, Object> context )
     {
         return getString( context, KEY_INSTALLATION_NAME );
     }
 
-    public static String getInstallationType( Map context )
+    public static String getInstallationType( Map<String, Object> context )
     {
         return getString( context, KEY_INSTALLATION_TYPE );
     }
 
-    public static String getInstallationVarValue( Map context )
+    public static String getInstallationVarValue( Map<String, Object> context )
     {
         return getString( context, KEY_INSTALLATION_VAR_VALUE );
     }
 
-    public static String getInstallationVarName( Map context )
+    public static String getInstallationVarName( Map<String, Object> context )
     {
         return getString( context, KEY_INSTALLATION_VAR_NAME );
     }
 
+    public static List<Map<String, Object>> getScmChanges( Map<String, Object> context )
+    {
+        return getList( context, KEY_SCM_CHANGES );
+    }
+
+    public static String getChangeSetAuthor( Map<String, Object> context )
+    {
+        return getString( context, KEY_CHANGESET_AUTHOR );
+    }
+
+    public static String getChangeSetComment( Map<String, Object> context )
+    {
+        return getString( context, KEY_CHANGESET_COMMENT );
+    }
+
+    public static long getChangeSetDate( Map<String, Object> context )
+    {
+        Date date = getDate( context, KEY_CHANGESET_DATE );
+
+        if ( date == null )
+        {
+            return 0;
+        }
+        else
+        {
+            return date.getTime();
+        }
+    }
+
+    public static List<Map<String, Object>> getChangeSetFiles( Map<String, Object> context )
+    {
+        return getList( context, KEY_CHANGESET_FILES );
+    }
+
+    public static String getChangeFileName( Map<String, Object> context )
+    {
+        return getString( context, KEY_CHANGEFILE_NAME );
+    }
+
+    public static String getChangeFileRevision( Map<String, Object> context )
+    {
+        return getString( context, KEY_CHANGEFILE_REVISION );
+    }
+
+    public static String getChangeFileStatus( Map<String, Object> context )
+    {
+        return getString( context, KEY_CHANGEFILE_STATUS );
+    }
+
+    public static String getGroupId( Map<String, Object> context )
+    {
+        return getString( context, KEY_GROUP_ID );
+    }
+
+    public static String getArtifactId( Map<String, Object> context )
+    {
+        return getString( context, KEY_ARTIFACT_ID );
+    }
+
+    public static String getVersion( Map<String, Object> context )
+    {
+        return getString( context, KEY_PROJECT_VERSION );
+
+    }
+
+    public static String getProjectName( Map<String, Object> context )
+    {
+        return getString( context, KEY_PROJECT_NAME );
+    }
+
+    public static String getProjectDescription( Map<String, Object> context )
+    {
+        return getString( context, KEY_PROJECT_DESCRIPTION );
+    }
+
+    public static String getProjectUrl( Map<String, Object> context )
+    {
+        return getString( context, KEY_PROJECT_URL );
+    }
+
+    public static String getScmUrl( Map<String, Object> context )
+    {
+        return getString( context, KEY_SCM_URL );
+    }
+
+    public static String getScmTag( Map<String, Object> context )
+    {
+        return getString( context, KEY_SCM_TAG );
+    }
+
+    public static Map<String, Object> getProjectParent( Map<String, Object> context )
+    {
+        return getMap( context, KEY_PROJECT_PARENT );
+    }
+
+    public static List<Map<String, Object>> getProjectDevelopers( Map<String, Object> context )
+    {
+        return getList( context, KEY_PROJECT_DEVELOPERS );
+    }
+
+    public static String getDeveloperName( Map<String, Object> context )
+    {
+        return getString( context, KEY_PROJECT_DEVELOPER_NAME );
+    }
+
+    public static String getDeveloperEmail( Map<String, Object> context )
+    {
+        return getString( context, KEY_PROJECT_DEVELOPER_EMAIL );
+    }
+
+    public static String getDeveloperScmId( Map<String, Object> context )
+    {
+        return getString( context, KEY_PROJECT_DEVELOPER_SCMID );
+    }
+
+    public static List<Map<String, Object>> getProjectDependencies( Map<String, Object> context )
+    {
+        return getList( context, KEY_PROJECT_DEPENDENCIES );
+    }
+
+    public static List<Map<String, Object>> getProjectNotifiers( Map<String, Object> context )
+    {
+        return getList( context, KEY_PROJECT_NOTIFIERS );
+    }
+
+    public static Map getNotifierConfiguration( Map<String, Object> context )
+    {
+        return getMap( context, KEY_NOTIFIER_CONFIGURATION );
+    }
+
+    public static int getNotifierFrom( Map<String, Object> context )
+    {
+        return getInteger( context, KEY_NOTIFIER_FROM );
+    }
+
+    public static int getNotifierRecipientType( Map<String, Object> context )
+    {
+        return getInteger( context, KEY_NOTIFIER_RECIPIENT_TYPE );
+    }
+
+    public static String getNotifierType( Map<String, Object> context )
+    {
+        return getString( context, KEY_NOTIFIER_TYPE );
+    }
+
+    public static boolean isNotifierEnabled( Map<String, Object> context )
+    {
+        return getBoolean( context, KEY_NOTIFIER_ENABLED );
+    }
+
+    public static boolean isNotifierSendOnError( Map<String, Object> context )
+    {
+        return getBoolean( context, KEY_NOTIFIER_SEND_ON_ERROR );
+    }
+
+    public static boolean isNotifierSendOnFailure( Map<String, Object> context )
+    {
+        return getBoolean( context, KEY_NOTIFIER_SEND_ON_FAILURE );
+    }
+
+    public static boolean isNotifierSendOnScmFailure( Map<String, Object> context )
+    {
+        return getBoolean( context, KEY_NOTIFIER_SEND_ON_SCMFAILURE );
+    }
+
+    public static boolean isNotifierSendOnSuccess( Map<String, Object> context )
+    {
+        return getBoolean( context, KEY_NOTIFIER_SEND_ON_SUCCESS );
+    }
+
+    public static boolean isNotifierSendOnWarning( Map<String, Object> context )
+    {
+        return getBoolean( context, KEY_NOTIFIER_SEND_ON_WARNING );
+    }
+
+    public static Map<String, Object> getScmResult( Map<String, Object> context )
+    {
+        return getMap( context, KEY_SCM_RESULT );
+    }
+
+    public static Map<String, Object> getMavenProject( Map<String, Object> context )
+    {
+        return getMap( context, KEY_MAVEN_PROJECT );
+    }
+
+    public static List<String> getProjectModules( Map<String, Object> context )
+    {
+        return getList( context, KEY_PROJECT_MODULES );
+    }
+
+    public static Date getLatestUpdateDate( Map<String, Object> context )
+    {
+        return getDate( context, KEY_LATEST_UPDATE_DATE );
+    }
+
+    public static String getBuildAgentUrl( Map<String, Object> context )
+    {
+        return getString( context, KEY_BUILD_AGENT_URL );
+    }
+
+    public static int getScmRootId( Map<String, Object> context )
+    {
+        return getInteger( context, KEY_SCM_ROOT_ID );
+    }
+
+    public static String getBuildDefinitionLabel( Map<String, Object> context )
+    {
+        return getString( context, KEY_BUILD_DEFINITION_LABEL, "" );
+    }
+
     // ----------------------------------------------------------------------
     //
     // ----------------------------------------------------------------------
 
-    protected static String getString( Map context, String key )
+    protected static String getString( Map<String, Object> context, String key )
     {
         Object obj = getObject( context, key, null );
 
@@ -219,59 +537,85 @@
         }
     }
 
-    protected static String getString( Map context, String key, String defaultValue )
+    protected static String getString( Map<String, Object> context, String key, String defaultValue )
     {
         return (String) getObject( context, key, defaultValue );
     }
 
-    protected static boolean getBoolean( Map context, String key )
+    protected static boolean getBoolean( Map<String, Object> context, String key )
     {
         Object obj = getObject( context, key, null );
-        
-        if ( obj == null )
-        {
-            return false;
-        }
-        else
-        {
-            return ( (Boolean) obj ).booleanValue();
-        }
-    }
-    
-    protected static boolean getBoolean( Map context, String key, boolean defaultValue )
-    {
-        return ( (Boolean) getObject( context, key, Boolean.valueOf( defaultValue ) ) ).booleanValue();
-    }    
 
-    protected static int getInteger( Map context, String key )
+        return obj != null && (Boolean) obj;
+    }
+
+    protected static boolean getBoolean( Map<String, Object> context, String key, boolean defaultValue )
+    {
+        return (Boolean) getObject( context, key, defaultValue );
+    }
+
+    protected static int getInteger( Map<String, Object> context, String key )
     {
         Object obj = getObject( context, key, null );
-        
+
         if ( obj == null )
         {
             return 0;
         }
         else
         {
-            return ( (Integer) obj ).intValue();
+            return (Integer) obj;
         }
     }
 
-    protected static long getLong( Map context, String key )
+    protected static Date getDate( Map<String, Object> context, String key )
     {
         Object obj = getObject( context, key, null );
-        
+
         if ( obj == null )
         {
-            return 0;
+            return null;
         }
         else
         {
-            return ( (Long) obj ).longValue();
+            return (Date) obj;
         }
     }
 
-    protected static Object getObject( Map context, String key )
+    protected static List getList( Map<String, Object> context, String key )
+    {
+        Object obj = getObject( context, key, null );
+
+        if ( obj == null )
+        {
+            return null;
+        }
+        else
+        {
+            List<Object> list = new ArrayList<Object>();
+            Object[] objA = (Object[]) obj;
+
+            list.addAll( Arrays.asList( objA ) );
+
+            return list;
+        }
+    }
+
+    protected static Map getMap( Map<String, Object> context, String key )
+    {
+        Object obj = getObject( context, key, null );
+
+        if ( obj == null )
+        {
+            return null;
+        }
+        else
+        {
+            return (Map) obj;
+        }
+    }
+
+    protected static Object getObject( Map<String, Object> context, String key )
     {
         if ( !context.containsKey( key ) )
         {
@@ -288,7 +632,7 @@
         return value;
     }
 
-    protected static Object getObject( Map context, String key, Object defaultValue )
+    protected static Object getObject( Map<String, Object> context, String key, Object defaultValue )
     {
         Object value = context.get( key );
 
diff --git a/continuum-builder/src/main/resources/META-INF/plexus/components.xml b/continuum-builder/src/main/resources/META-INF/plexus/components.xml
index 98bfe38..fa40ef4 100644
--- a/continuum-builder/src/main/resources/META-INF/plexus/components.xml
+++ b/continuum-builder/src/main/resources/META-INF/plexus/components.xml
@@ -19,7 +19,7 @@
 
 <component-set>
   <components>
-  
+
     <!--
      |
      | Distributed Build Task Queue
@@ -31,12 +31,14 @@
       <role-hint>distributed-build-project</role-hint>
       <implementation>org.codehaus.plexus.taskqueue.DefaultTaskQueue</implementation>
       <lifecycle-handler>plexus-configurable</lifecycle-handler>
+      <instantiation-strategy>per-lookup</instantiation-strategy>
     </component>
 
     <component>
       <role>org.apache.continuum.builder.distributed.executor.DistributedBuildTaskExecutor</role>
       <role-hint>distributed-build-project</role-hint>
-      <implementation>org.apache.continuum.builder.distributed.executor.DistributedBuildProjectTaskExecutor</implementation>
+      <implementation>org.apache.continuum.builder.distributed.executor.DistributedBuildProjectTaskExecutor
+      </implementation>
       <instantiation-strategy>per-lookup</instantiation-strategy>
       <requirements>
         <requirement>
@@ -51,15 +53,19 @@
         <requirement>
           <role>org.apache.continuum.dao.BuildDefinitionDao</role>
         </requirement>
+        <requirement>
+          <role>org.apache.maven.continuum.configuration.ConfigurationService</role>
+        </requirement>
       </requirements>
     </component>
 
     <component>
       <role>org.apache.continuum.builder.distributed.executor.DistributedBuildTaskQueueExecutor</role>
       <role-hint>distributed-build-project</role-hint>
-      <implementation>org.apache.continuum.builder.distributed.executor.ThreadedDistributedBuildTaskQueueExecutor</implementation>
+      <implementation>org.apache.continuum.builder.distributed.executor.ThreadedDistributedBuildTaskQueueExecutor
+      </implementation>
       <instantiation-strategy>per-lookup</instantiation-strategy>
-	  <requirements>
+      <requirements>
         <requirement>
           <role>org.codehaus.plexus.taskqueue.TaskQueue</role>
           <role-hint>distributed-build-project</role-hint>
diff --git a/continuum-builder/src/main/resources/META-INF/spring-context.xml b/continuum-builder/src/main/resources/META-INF/spring-context.xml
new file mode 100644
index 0000000..485dd9a
--- /dev/null
+++ b/continuum-builder/src/main/resources/META-INF/spring-context.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+  <bean name="overallDistributedBuildQueue"
+        class="org.apache.continuum.builder.distributed.taskqueue.DefaultOverallDistributedBuildQueue" scope="prototype"
+        autowire="byName">
+    <property name="distributedBuildTaskQueueExecutor"
+              ref="distributedBuildTaskQueueExecutor#distributed-build-project"/>
+  </bean>
+</beans>
\ No newline at end of file
diff --git a/continuum-builder/src/test/resources/log4j.xml b/continuum-builder/src/test/resources/log4j.xml
deleted file mode 100644
index 75a95bd..0000000
--- a/continuum-builder/src/test/resources/log4j.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
-<!-- ===================================================================== -->
-<!-- Log4j Configuration -->
-<!-- ===================================================================== -->
-
-<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
-  debug="false">
-
-  <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
-    <param name="Target" value="System.out"/>
-    <layout class="org.apache.log4j.PatternLayout">
-      <param name="ConversionPattern" value="%d %-5p [%c{1}.%M](%L) %m%n"/>
-    </layout>
-  </appender>
-
-  <!-- quiet spring loading :-) -->
-  <category name="org.springframework">
-    <priority value="ERROR"/>
-  </category>
-  <category name="org.codehaus.plexus">
-    <priority value="ERROR"/>
-  </category>
-  <category name="org.apache.continuum.builder">
-    <priority value="DEBUG"/>
-  </category>
-
-  <category name="org.apache.commons.builder">
-    <priority value="ERROR"/>
-  </category>
-
-  <!-- JPOX -->
-  <category name="JPOX">
-    <priority value="WARN"/>
-  </category>
-  <category name="JPOX.RDBMS">
-    <priority value="ERROR"/>
-  </category>
-
-  <root>
-    <priority value="INFO"/>
-    <appender-ref ref="CONSOLE"/>
-  </root>
-
-</log4j:configuration>
diff --git a/continuum-commons/pom.xml b/continuum-commons/pom.xml
index 8887895..c3effc5 100644
--- a/continuum-commons/pom.xml
+++ b/continuum-commons/pom.xml
@@ -1,28 +1,29 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
+  ~ 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.
+  -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
     <artifactId>continuum</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <artifactId>continuum-commons</artifactId>
   <name>Continuum :: Commons</name>
@@ -33,34 +34,90 @@
     </dependency>
     <dependency>
       <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-store</artifactId>
+      <artifactId>continuum-model</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.springframework</groupId>
-      <artifactId>spring-context-support</artifactId>
-    </dependency>      
-    <dependency>
-      <groupId>javax.annotation</groupId>
-      <artifactId>jsr250-api</artifactId>
-    </dependency>    
+    <!-- required because Sprint pre-instantiates them, and we have no stubs -->
     <dependency>
       <groupId>org.apache.continuum</groupId>
       <artifactId>continuum-configuration</artifactId>
+      <scope>runtime</scope>
     </dependency>
+    <!-- required because Sprint pre-instantiates them, and we have no stubs -->
     <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-spring</artifactId>
-    </dependency>    
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-store</artifactId>
+      <scope>runtime</scope>
+    </dependency>
     <dependency>
       <groupId>org.apache.maven.release</groupId>
       <artifactId>maven-release-manager</artifactId>
-      <version>1.0-alpha-3</version>
-      <exclusions>
-        <exclusion>
-          <groupId>org.codehaus.plexus</groupId>
-          <artifactId>plexus-container-default</artifactId>
-        </exclusion>
-      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>javax.annotation</groupId>
+      <artifactId>jsr250-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-context</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>jcl-over-slf4j</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jmock</groupId>
+      <artifactId>jmock-junit3</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <!-- dependency of jmock3 -->
+    <dependency>
+      <groupId>cglib</groupId>
+      <artifactId>cglib-nodep</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <!-- dependency of jmock3 -->
+    <dependency>
+      <groupId>org.objenesis</groupId>
+      <artifactId>objenesis</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jmock</groupId>
+      <artifactId>jmock</artifactId>
+      <version>2.4.0</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>jmock</groupId>
+      <artifactId>jmock</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-simple</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-component-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-utils</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>plexus-spring</artifactId>
+      <scope>test</scope>
     </dependency>
     <!-- === Testing Dependencies === -->
     <dependency>
@@ -73,10 +130,5 @@
       <artifactId>continuum-test</artifactId>
       <scope>test</scope>
     </dependency>
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-log4j12</artifactId>
-      <scope>test</scope>
-    </dependency>      
   </dependencies>
 </project>
diff --git a/continuum-commons/src/main/java/org/apache/continuum/buildqueue/DefaultBuildQueueService.java b/continuum-commons/src/main/java/org/apache/continuum/buildqueue/DefaultBuildQueueService.java
new file mode 100644
index 0000000..e352f83
--- /dev/null
+++ b/continuum-commons/src/main/java/org/apache/continuum/buildqueue/DefaultBuildQueueService.java
@@ -0,0 +1,157 @@
+package org.apache.continuum.buildqueue;
+
+/*
+ * 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 org.apache.continuum.dao.BuildQueueDao;
+import org.apache.continuum.dao.ScheduleDao;
+import org.apache.maven.continuum.model.project.BuildQueue;
+import org.apache.maven.continuum.model.project.Schedule;
+import org.apache.maven.continuum.store.ContinuumStoreException;
+
+import java.util.List;
+import javax.annotation.Resource;
+
+/**
+ * DefaultBuildQueueService
+ *
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ */
+public class DefaultBuildQueueService
+    implements BuildQueueService
+{
+    @Resource
+    private BuildQueueDao buildQueueDao;
+
+    @Resource
+    private ScheduleDao scheduleDao;
+
+    public BuildQueue addBuildQueue( BuildQueue buildQueue )
+        throws BuildQueueServiceException
+    {
+        try
+        {
+            return buildQueueDao.addBuildQueue( buildQueue );
+        }
+        catch ( ContinuumStoreException e )
+        {
+            throw new BuildQueueServiceException( e );
+        }
+    }
+
+    public List<BuildQueue> getAllBuildQueues()
+        throws BuildQueueServiceException
+    {
+        try
+        {
+            return buildQueueDao.getAllBuildQueues();
+        }
+        catch ( ContinuumStoreException e )
+        {
+            throw new BuildQueueServiceException( e );
+        }
+    }
+
+    public BuildQueue getBuildQueue( int buildQueueId )
+        throws BuildQueueServiceException
+    {
+        try
+        {
+            return buildQueueDao.getBuildQueue( buildQueueId );
+        }
+        catch ( ContinuumStoreException e )
+        {
+            throw new BuildQueueServiceException( e );
+        }
+    }
+
+    public BuildQueue getBuildQueueByName( String buildQueueName )
+        throws BuildQueueServiceException
+    {
+        try
+        {
+            return buildQueueDao.getBuildQueueByName( buildQueueName );
+        }
+        catch ( ContinuumStoreException e )
+        {
+            throw new BuildQueueServiceException( e );
+        }
+    }
+
+    public void removeBuildQueue( BuildQueue buildQueue )
+        throws BuildQueueServiceException
+    {
+        try
+        {
+            // detach from schedule(s) first
+            List<Schedule> schedules = scheduleDao.getAllSchedulesByName();
+            for ( Schedule schedule : schedules )
+            {
+                List<BuildQueue> buildQueues = schedule.getBuildQueues();
+                if ( buildQueues.contains( buildQueue ) )
+                {
+                    buildQueues.remove( buildQueue );
+                }
+                schedule.setBuildQueues( buildQueues );
+
+                scheduleDao.updateSchedule( schedule );
+            }
+
+            buildQueueDao.removeBuildQueue( buildQueue );
+        }
+        catch ( ContinuumStoreException e )
+        {
+            throw new BuildQueueServiceException( e );
+        }
+    }
+
+    public BuildQueue updateBuildQueue( BuildQueue buildQueue )
+        throws BuildQueueServiceException
+    {
+        try
+        {
+            return buildQueueDao.storeBuildQueue( buildQueue );
+        }
+        catch ( ContinuumStoreException e )
+        {
+            throw new BuildQueueServiceException( e );
+        }
+    }
+
+    public BuildQueueDao getBuildQueueDao()
+    {
+        return buildQueueDao;
+    }
+
+    public void setBuildQueueDao( BuildQueueDao buildQueueDao )
+    {
+        this.buildQueueDao = buildQueueDao;
+    }
+
+    public ScheduleDao getScheduleDao()
+    {
+        return scheduleDao;
+    }
+
+    public void setScheduleDao( ScheduleDao scheduleDao )
+    {
+        this.scheduleDao = scheduleDao;
+    }
+
+}
diff --git a/continuum-commons/src/main/java/org/apache/continuum/installation/DefaultInstallationService.java b/continuum-commons/src/main/java/org/apache/continuum/installation/DefaultInstallationService.java
index 96caa9f..215918e 100644
--- a/continuum-commons/src/main/java/org/apache/continuum/installation/DefaultInstallationService.java
+++ b/continuum-commons/src/main/java/org/apache/continuum/installation/DefaultInstallationService.java
@@ -19,19 +19,11 @@
  * under the License.
  */
 
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
-import javax.annotation.Resource;
-
 import org.apache.continuum.dao.InstallationDao;
+import org.apache.continuum.utils.shell.ExecutionResult;
+import org.apache.continuum.utils.shell.ListOutputConsumer;
+import org.apache.continuum.utils.shell.OutputConsumer;
+import org.apache.continuum.utils.shell.ShellCommandHelper;
 import org.apache.maven.continuum.execution.ExecutorConfigurator;
 import org.apache.maven.continuum.installation.AlreadyExistsInstallationException;
 import org.apache.maven.continuum.installation.InstallationException;
@@ -45,26 +37,30 @@
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
 import org.codehaus.plexus.util.StringUtils;
-import org.codehaus.plexus.util.cli.CommandLineException;
-import org.codehaus.plexus.util.cli.CommandLineUtils;
-import org.codehaus.plexus.util.cli.Commandline;
-import org.codehaus.plexus.util.cli.StreamConsumer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import javax.annotation.Resource;
+
 /**
  * @author <a href="mailto:olamy@codehaus.org">olamy</a>
  * @version $Id$
- * TODO use some cache mechanism to prevent always reading from store ?
+ *          TODO use some cache mechanism to prevent always reading from store ?
  * @since 13 juin 07
- * 
  */
-@Service("installationService")
+@Service( "installationService" )
 public class DefaultInstallationService
     implements InstallationService, Initializable
 {
-    private Logger log = LoggerFactory.getLogger( DefaultInstallationService.class );
+    private static final Logger log = LoggerFactory.getLogger( DefaultInstallationService.class );
 
     @Resource
     private InstallationDao installationDao;
@@ -72,6 +68,9 @@
     @Resource
     private ProfileService profileService;
 
+    @Resource
+    private ShellCommandHelper shellCommandHelper;
+
     private Map<String, ExecutorConfigurator> typesValues;
 
     // ---------------------------------------------
@@ -82,16 +81,16 @@
         throws InitializationException
     {
         this.typesValues = new HashMap<String, ExecutorConfigurator>();
-        this.typesValues.put( InstallationService.ANT_TYPE,
-                              new ExecutorConfigurator( "ant", "bin", "ANT_HOME", "-version" ) );
+        this.typesValues.put( InstallationService.ANT_TYPE, new ExecutorConfigurator( "ant", "bin", "ANT_HOME",
+                                                                                      "-version" ) );
 
         this.typesValues.put( InstallationService.ENVVAR_TYPE, null );
-        this.typesValues.put( InstallationService.JDK_TYPE,
-                              new ExecutorConfigurator( "java", "bin", "JAVA_HOME", "-version" ) );
-        this.typesValues.put( InstallationService.MAVEN1_TYPE,
-                              new ExecutorConfigurator( "maven", "bin", "MAVEN_HOME", "-v" ) );
-        this.typesValues
-            .put( InstallationService.MAVEN2_TYPE, new ExecutorConfigurator( "mvn", "bin", "M2_HOME", "-v" ) );
+        this.typesValues.put( InstallationService.JDK_TYPE, new ExecutorConfigurator( "java", "bin", "JAVA_HOME",
+                                                                                      "-version" ) );
+        this.typesValues.put( InstallationService.MAVEN1_TYPE, new ExecutorConfigurator( "maven", "bin", "MAVEN_HOME",
+                                                                                         "-v" ) );
+        this.typesValues.put( InstallationService.MAVEN2_TYPE, new ExecutorConfigurator( "mvn", "bin", "M2_HOME",
+                                                                                         "-v" ) );
     }
 
     /**
@@ -120,7 +119,7 @@
                 "Installation with name " + installation.getName() + " already exists" );
         }
         // TODO must be done in the same transaction
-        Installation storedOne = null;
+        Installation storedOne;
         try
         {
             String envVarName = this.getEnvVar( installation.getType() );
@@ -172,13 +171,13 @@
     /**
      * @see org.apache.maven.continuum.installation.InstallationService#getAllInstallations()
      */
-    @SuppressWarnings("unchecked")
+    @SuppressWarnings( "unchecked" )
     public List<Installation> getAllInstallations()
         throws InstallationException
     {
         try
         {
-            List installations = installationDao.getAllInstallations();
+            List<Installation> installations = installationDao.getAllInstallations();
             return installations == null ? Collections.EMPTY_LIST : installations;
         }
         catch ( ContinuumStoreException e )
@@ -204,10 +203,26 @@
     }
 
     /**
+     * @see org.apache.maven.continuum.installation.InstallationService#getInstallation(String)
+     */
+    public Installation getInstallation( String installationName )
+        throws InstallationException
+    {
+        try
+        {
+            return installationDao.getInstallation( installationName );
+        }
+        catch ( ContinuumStoreException e )
+        {
+            throw new InstallationException( e.getMessage(), e );
+        }
+    }
+
+    /**
      * @see org.apache.maven.continuum.installation.InstallationService#update(org.apache.maven.continuum.model.system.Installation)
      */
     public void update( Installation installation )
-        throws InstallationException
+        throws InstallationException, AlreadyExistsInstallationException
     {
         try
         {
@@ -218,6 +233,11 @@
             }
 
             stored.setName( installation.getName() );
+            if ( alreadyExistInstallationName( installation ) )
+            {
+                throw new AlreadyExistsInstallationException(
+                    "Installation with name " + installation.getName() + " already exists" );
+            }
             stored.setType( installation.getType() );
             String envVarName = this.getEnvVar( installation.getType() );
             // override with the defined var name for defined types
@@ -261,96 +281,78 @@
     // -------------------------------------------------------------
 
     /**
-     * TODO replace with calling getExecutorConfiguratorVersion
+     * TODO replace with calling getExecutorVersionInfo
      *
-     * @see org.apache.maven.continuum.installation.InstallationService#getDefaultJdkInformations()
+     * @see org.apache.maven.continuum.installation.InstallationService#getDefaultJavaVersionInfo()
      */
-    public List<String> getDefaultJdkInformations()
+    public List<String> getDefaultJavaVersionInfo()
         throws InstallationException
     {
         try
         {
-            Properties systemEnvVars = CommandLineUtils.getSystemEnvVars( false );
-
+            Properties systemEnvVars = shellCommandHelper.getSystemEnvVars();
             String javaHome = (String) systemEnvVars.get( "JAVA_HOME" );
-            // olamy : JAVA_HOME can not exists with a mac user
+            // olamy : JAVA_HOME may not exist for mac users
             if ( StringUtils.isEmpty( javaHome ) )
             {
-                return getJavaHomeInformations( System.getProperty( "java.home" ) );
+                return getJavaVersionInfo( System.getProperty( "java.home" ) );
             }
-            return getJavaHomeInformations( javaHome );
+            return getJavaVersionInfo( javaHome );
 
         }
-        catch ( IOException e )
-        {
-            throw new InstallationException( e.getMessage(), e );
-        }
-        catch ( CommandLineException e )
+        catch ( Exception e )
         {
             throw new InstallationException( e.getMessage(), e );
         }
     }
 
     /**
-     * TODO replace with calling getExecutorConfiguratorVersion
+     * TODO replace with calling getExecutorVersionInfo
      *
-     * @see org.apache.maven.continuum.installation.InstallationService#getJdkInformations(org.apache.maven.continuum.model.system.Installation)
+     * @see org.apache.maven.continuum.installation.InstallationService#getJavaVersionInfo(org.apache.maven.continuum.model.system.Installation)
      */
-    public List<String> getJdkInformations( Installation installation )
+    public List<String> getJavaVersionInfo( Installation installation )
         throws InstallationException
     {
         if ( installation == null )
         {
-            return getDefaultJdkInformations();
+            return getDefaultJavaVersionInfo();
         }
         if ( StringUtils.isEmpty( installation.getVarValue() ) )
         {
-            return getDefaultJdkInformations();
+            return getDefaultJavaVersionInfo();
         }
         try
         {
-            return getJavaHomeInformations( installation.getVarValue() );
+            return getJavaVersionInfo( installation.getVarValue() );
         }
-        catch ( CommandLineException e )
+        catch ( Exception e )
         {
             throw new InstallationException( e.getMessage(), e );
         }
     }
 
     /**
-     * @param javaHome
+     * @param homePath
      * @return
-     * @throws CommandLineException
+     * @throws Exception
      */
-    private List<String> getJavaHomeInformations( String javaHome )
-        throws CommandLineException
+    private List<String> getJavaVersionInfo( String homePath )
+        throws Exception
     {
-        Commandline commandline = new Commandline();
 
-        String executable = javaHome + File.separator + "bin" + File.separator + "java";
-
-        commandline.setExecutable( executable );
-        commandline.addArguments( new String[]{"-version"} );
-        final List<String> cliOutput = new ArrayList<String>();
-        //TODO ShellCommandHelper ?
-        int result = CommandLineUtils.executeCommandLine( commandline, new StreamConsumer()
+        String executable = homePath + File.separator + "bin" + File.separator + "java";
+        ListOutputConsumer outputConsumer = new ListOutputConsumer();
+        ExecutionResult result = shellCommandHelper.executeShellCommand( null, executable, new String[] { "-version" },
+                                                                         outputConsumer, -1, null );
+        int exitCode = result.getExitCode();
+        if ( exitCode != 0 )
         {
-            public void consumeLine( String line )
-            {
-                cliOutput.add( line );
-            }
-        }, new StreamConsumer()
-        {
-            public void consumeLine( String line )
-            {
-                cliOutput.add( line );
-            }
-        } );
-        if ( result != 0 )
-        {
-            throw new CommandLineException( "cli to get JAVA_HOME informations return code " + result );
+            throw new Exception(
+                String.format( "failed to get java version information, %s returned exit code %s", executable,
+                               exitCode ) );
         }
-        return cliOutput;
+        return outputConsumer.getList();
     }
 
     private Map<String, String> getEnvVars( Profile profile )
@@ -379,72 +381,53 @@
     }
 
     /**
-     * @see org.apache.maven.continuum.installation.InstallationService#getExecutorConfiguratorVersion(java.lang.String,org.apache.maven.continuum.execution.ExecutorConfigurator,Profile)
+     * @see org.apache.maven.continuum.installation.InstallationService#getExecutorVersionInfo(java.lang.String, org.apache.maven.continuum.execution.ExecutorConfigurator, Profile)
      */
-    @SuppressWarnings("unchecked")
-    public List<String> getExecutorConfiguratorVersion( String path, ExecutorConfigurator executorConfigurator,
-                                                        Profile profile )
+    public List<String> getExecutorVersionInfo( String path, ExecutorConfigurator executorConfigurator,
+                                                Profile profile )
         throws InstallationException
     {
+        if ( executorConfigurator == null || executorConfigurator.getExecutable() == null )
+        {
+            return Collections.EMPTY_LIST;
+        }
 
-        if ( executorConfigurator == null )
-        {
-            return Collections.EMPTY_LIST;
-        }
-        if ( executorConfigurator.getExecutable() == null )
-        {
-            return Collections.EMPTY_LIST;
-        }
         StringBuilder executable = new StringBuilder();
+
+        Map<String, String> env = new HashMap<String, String>();
+
+        if ( StringUtils.isNotEmpty( path ) )
+        {
+            executable.append( path ).append( File.separator );
+            executable.append( executorConfigurator.getRelativePath() ).append( File.separator );
+            env.put( executorConfigurator.getEnvVar(), path );
+        }
+        executable = executable.append( executorConfigurator.getExecutable() );
+
+        env.putAll( getEnvVars( profile ) );
+
+        ListOutputConsumer outputConsumer = new ListOutputConsumer();
+        ExecutionResult result;
         try
         {
-            Commandline commandline = new Commandline();
-            if ( StringUtils.isNotEmpty( path ) )
-            {
-                executable.append( path ).append( File.separator );
-                executable.append( executorConfigurator.getRelativePath() + File.separator );
-                commandline.addEnvironment( executorConfigurator.getEnvVar(), path );
-            }
-            //Installations are env var they must be add if exists
-            Map<String, String> environments = getEnvVars( profile );
-            // no null check we use a private method just here
-            for ( Iterator<String> iterator = environments.keySet().iterator(); iterator.hasNext(); )
-            {
-                String key = iterator.next();
-                String value = environments.get( key );
-                commandline.addEnvironment( key, value );
-            }
-
-            executable = executable.append( executorConfigurator.getExecutable() );
-            commandline.setExecutable( executable.toString() );
-            commandline.addArguments( new String[]{executorConfigurator.getVersionArgument()} );
-            final List<String> cliOutput = new ArrayList<String>();
-            //TODO ShellCommandHelper ?
-            int result = CommandLineUtils.executeCommandLine( commandline, new StreamConsumer()
-            {
-                public void consumeLine( String line )
-                {
-                    cliOutput.add( line );
-                }
-            }, new StreamConsumer()
-            {
-                public void consumeLine( String line )
-                {
-                    cliOutput.add( line );
-                }
-            } );
-            if ( result != 0 )
-            {
-                throw new InstallationException( "cli to get " + executable + " version return code " + result );
-            }
-            return cliOutput;
+            result = shellCommandHelper.executeShellCommand( null, executable.toString(),
+                                                             new String[] { executorConfigurator.getVersionArgument() },
+                                                             outputConsumer, -1, null );
         }
-        catch ( CommandLineException e )
+        catch ( Exception e )
         {
-            log.error(
-                "fail to execute " + executable + " with arg " + executorConfigurator.getVersionArgument() );
+            log.error( "failed to get executor version info", e );
             throw new InstallationException( e.getMessage(), e );
         }
+        int exitCode = result.getExitCode();
+        if ( exitCode != 0 )
+        {
+
+            throw new InstallationException(
+                String.format( "failed to get executor version info, %s returned exit code %s", executable,
+                               exitCode ) );
+        }
+        return outputConsumer.getList();
     }
 
     private boolean alreadyExistInstallationName( Installation installation )
@@ -453,7 +436,9 @@
         List<Installation> all = getAllInstallations();
         for ( Installation install : all )
         {
-            if ( org.apache.commons.lang.StringUtils.equals( installation.getName(), install.getName() ) )
+            if ( org.apache.commons.lang.StringUtils.equals( installation.getName(), install.getName() ) &&
+                ( installation.getInstallationId() == 0 ||
+                    installation.getInstallationId() != install.getInstallationId() ) )
             {
                 return true;
             }
diff --git a/continuum-commons/src/main/java/org/apache/continuum/profile/DefaultProfileService.java b/continuum-commons/src/main/java/org/apache/continuum/profile/DefaultProfileService.java
index a625de1..8b5f138 100644
--- a/continuum-commons/src/main/java/org/apache/continuum/profile/DefaultProfileService.java
+++ b/continuum-commons/src/main/java/org/apache/continuum/profile/DefaultProfileService.java
@@ -19,11 +19,6 @@
  * under the License.
  */
 
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.annotation.Resource;
-
 import org.apache.commons.lang.StringUtils;
 import org.apache.continuum.dao.ProfileDao;
 import org.apache.maven.continuum.installation.InstallationService;
@@ -36,13 +31,17 @@
 import org.apache.maven.continuum.store.ContinuumStoreException;
 import org.springframework.stereotype.Service;
 
+import java.util.ArrayList;
+import java.util.List;
+import javax.annotation.Resource;
+
 /**
  * @author <a href="mailto:olamy@codehaus.org">olamy</a>
  * @version $Id$
- * TODO use some cache mechanism to prevent always reading from store ?
+ *          TODO use some cache mechanism to prevent always reading from store ?
  * @since 15 juin 07
  */
-@Service("profileService")
+@Service( "profileService" )
 public class DefaultProfileService
     implements ProfileService
 {
@@ -55,7 +54,6 @@
     public void updateProfile( Profile profile )
         throws ProfileException, AlreadyExistsProfileException
     {
-
         // 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 ) )
@@ -73,6 +71,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 +102,7 @@
             stored.setJdk( profile.getJdk() );
             stored.setName( profile.getName() );
             stored.setEnvironmentVariables( profile.getEnvironmentVariables() );
+            stored.setBuildAgentGroup( profile.getBuildAgentGroup() );
             profileDao.updateProfile( stored );
         }
         catch ( ContinuumStoreException e )
@@ -176,7 +176,7 @@
     }
 
     /**
-     * @see org.apache.maven.continuum.profile.ProfileService#setBuilderInProfile(org.apache.maven.continuum.model.system.Profile,org.apache.maven.continuum.model.system.Installation)
+     * @see org.apache.maven.continuum.profile.ProfileService#setBuilderInProfile(org.apache.maven.continuum.model.system.Profile, org.apache.maven.continuum.model.system.Installation)
      */
     public void setBuilderInProfile( Profile profile, Installation builder )
         throws ProfileException
@@ -194,7 +194,7 @@
     }
 
     /**
-     * @see org.apache.maven.continuum.profile.ProfileService#setJdkInProfile(org.apache.maven.continuum.model.system.Profile,org.apache.maven.continuum.model.system.Installation)
+     * @see org.apache.maven.continuum.profile.ProfileService#setJdkInProfile(org.apache.maven.continuum.model.system.Profile, org.apache.maven.continuum.model.system.Installation)
      */
     public void setJdkInProfile( Profile profile, Installation jdk )
         throws ProfileException
@@ -212,7 +212,7 @@
     }
 
     /**
-     * @see org.apache.maven.continuum.profile.ProfileService#addEnvVarInProfile(org.apache.maven.continuum.model.system.Profile,org.apache.maven.continuum.model.system.Installation)
+     * @see org.apache.maven.continuum.profile.ProfileService#addEnvVarInProfile(org.apache.maven.continuum.model.system.Profile, org.apache.maven.continuum.model.system.Installation)
      */
     public void addEnvVarInProfile( Profile profile, Installation envVar )
         throws ProfileException
@@ -308,10 +308,11 @@
      * @return true if profile with same name (<b>case sensitive</b>) exists
      * @throws ProfileException
      */
-    private boolean alreadyExistsProfileName( Profile profile )
+    public boolean alreadyExistsProfileName( Profile profile )
         throws ProfileException
     {
-        return getProfileWithName( profile.getName() ) != null;
+        Profile storedProfile = getProfileWithName( profile.getName() );
+        return ( storedProfile != null && storedProfile.getId() != profile.getId() );
     }
 
 }
diff --git a/continuum-commons/src/main/java/org/apache/continuum/utils/ProjectSorter.java b/continuum-commons/src/main/java/org/apache/continuum/utils/ProjectSorter.java
deleted file mode 100644
index 6cd1d02..0000000
--- a/continuum-commons/src/main/java/org/apache/continuum/utils/ProjectSorter.java
+++ /dev/null
@@ -1,159 +0,0 @@
-package org.apache.continuum.utils;
-
-/*
- * 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 org.apache.maven.continuum.model.project.Project;
-import org.apache.maven.continuum.model.project.ProjectDependency;
-import org.codehaus.plexus.util.dag.CycleDetectedException;
-import org.codehaus.plexus.util.dag.DAG;
-import org.codehaus.plexus.util.dag.TopologicalSorter;
-import org.slf4j.Logger;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Sort projects by dependencies.
- *
- * @author <a href="mailto:brett@apache.org">Brett Porter</a>
- * @version $Id$
- */
-public class ProjectSorter
-{
-    private ProjectSorter()
-    {
-        // no touchy...
-    }
-
-    /**
-     * Sort a list of projects.
-     * <ul>
-     * <li>collect all the vertices for the projects that we want to build.</li>
-     * <li>iterate through the deps of each project and if that dep is within
-     * the set of projects we want to build then add an edge, otherwise throw
-     * the edge away because that dependency is not within the set of projects
-     * we are trying to build. we assume a closed set.</li>
-     * <li>do a topo sort on the graph that remains.</li>
-     * </ul>
-     */
-    public static List<Project> getSortedProjects( Collection<Project> projects, Logger logger )
-        throws CycleDetectedException
-    {
-        DAG dag = new DAG();
-
-        Map<String, Project> projectMap = new HashMap<String, Project>();
-
-        for ( Project project : projects )
-        {
-            String id = getProjectId( project );
-
-            if ( dag.getVertex( id ) != null )
-            {
-                logger.warn( "Project '" + id + "' is duplicated in the reactor" );
-            }
-
-            dag.addVertex( id );
-
-            projectMap.put( id, project );
-        }
-
-        for ( Project project : projects )
-        {
-            String id = getProjectId( project );
-
-            // Dependencies
-            for ( Object o : project.getDependencies() )
-            {
-                ProjectDependency dependency = (ProjectDependency) o;
-
-                String dependencyId = getDependencyId( dependency );
-
-                if ( dag.getVertex( dependencyId ) != null )
-                {
-                    dag.addEdge( id, dependencyId );
-                }
-            }
-
-            // Parent
-            ProjectDependency parent = project.getParent();
-
-            if ( parent != null )
-            {
-                String parentId = getDependencyId( parent );
-
-                if ( dag.getVertex( parentId ) != null )
-                {
-                    // Parent is added as an edge, but must not cause a cycle - so we remove any other edges it has in conflict
-                    if ( dag.hasEdge( parentId, id ) )
-                    {
-                        dag.removeEdge( parentId, id );
-                    }
-                    dag.addEdge( id, parentId );
-                }
-            }
-        }
-
-        List<Project> sortedProjects = new ArrayList<Project>();
-
-        for ( Object o : TopologicalSorter.sort( dag ) )
-        {
-            String id = (String) o;
-
-            sortedProjects.add( projectMap.get( id ) );
-        }
-
-        return sortedProjects;
-    }
-
-    private static String getProjectId( Project project )
-    {
-        String groupId;
-
-        String artifactId;
-
-        if ( project.getGroupId() == null )
-        {
-            groupId = project.getName();
-        }
-        else
-        {
-            groupId = project.getGroupId();
-        }
-
-        if ( project.getArtifactId() == null )
-        {
-            artifactId = project.getName();
-        }
-        else
-        {
-            artifactId = project.getArtifactId();
-        }
-
-        return groupId + ":" + artifactId + ":" + project.getVersion();
-    }
-
-    private static String getDependencyId( ProjectDependency project )
-    {
-        return project.getGroupId() + ":" + project.getArtifactId() + ":" + project.getVersion();
-    }
-}
diff --git a/continuum-commons/src/main/java/org/apache/continuum/utils/shell/DefaultShellCommandHelper.java b/continuum-commons/src/main/java/org/apache/continuum/utils/shell/DefaultShellCommandHelper.java
deleted file mode 100644
index 89e150f..0000000
--- a/continuum-commons/src/main/java/org/apache/continuum/utils/shell/DefaultShellCommandHelper.java
+++ /dev/null
@@ -1,227 +0,0 @@
-package org.apache.continuum.utils.shell;
-
-/*
- * 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.io.File;
-import java.io.FileWriter;
-import java.io.Writer;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.Map;
-
-import org.apache.maven.shared.release.ReleaseResult;
-import org.apache.maven.shared.release.exec.MavenExecutorException;
-import org.apache.maven.shared.release.exec.TeeConsumer;
-import org.codehaus.plexus.util.StringUtils;
-import org.codehaus.plexus.util.cli.CommandLineException;
-import org.codehaus.plexus.util.cli.CommandLineUtils;
-import org.codehaus.plexus.util.cli.Commandline;
-import org.codehaus.plexus.util.cli.StreamConsumer;
-import org.codehaus.plexus.util.cli.WriterStreamConsumer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Service;
-
-/**
- * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
- * @version $Id$
- */
-@Service("shellCommandHelper")
-public class DefaultShellCommandHelper
-    implements ShellCommandHelper
-{
-    private Logger log = LoggerFactory.getLogger( DefaultShellCommandHelper.class );
-
-    // ----------------------------------------------------------------------
-    // ShellCommandHelper Implementation
-    // ----------------------------------------------------------------------
-
-    public ExecutionResult executeShellCommand( File workingDirectory, String executable, String arguments, File output,
-                                                long idCommand, Map<String, String> environments )
-        throws Exception
-    {
-        Commandline cl = new Commandline();
-
-        Commandline.Argument argument = cl.createArgument();
-
-        argument.setLine( arguments );
-
-        return executeShellCommand( workingDirectory, executable, argument.getParts(), output, idCommand,
-                                    environments );
-    }
-
-    /**
-     * Make the command line
-     * 
-     * @param workingDirectory
-     * @param executable
-     * @param arguments
-     * @param idCommand
-     * @param environments
-     * @return
-     * @throws Exception
-     */
-    protected Commandline createCommandline( File workingDirectory, String executable, String[] arguments,
-                                             long idCommand, Map<String, String> environments )
-        throws Exception
-    {
-        Commandline cl = new Commandline();
-
-        cl.setPid( idCommand );
-
-        cl.addEnvironment( "MAVEN_TERMINATE_CMD", "on" );
-
-        if ( environments != null && !environments.isEmpty() )
-        {
-            for ( Iterator<String> iterator = environments.keySet().iterator(); iterator.hasNext(); )
-            {
-                String key = iterator.next();
-                String value = environments.get( key );
-                cl.addEnvironment( key, value );
-            }
-        }
-
-        cl.addSystemEnvironment();
-
-        cl.setExecutable( executable );
-
-        cl.setWorkingDirectory( workingDirectory.getAbsolutePath() );
-
-        if ( arguments != null )
-        {
-            for ( int i = 0; i < arguments.length; i++ )
-            {
-                String argument = arguments[i];
-
-                cl.createArgument().setValue( argument );
-            }
-        }
-
-        return cl;
-    }
-
-    public ExecutionResult executeShellCommand( File workingDirectory, String executable, String[] arguments,
-                                                File output, long idCommand, Map<String, String> environments )
-        throws Exception
-    {
-
-        Commandline cl = createCommandline( workingDirectory, executable, arguments, idCommand, environments );
-
-        log.info( "Executing: " + cl );
-        log.info( "Working directory: " + cl.getWorkingDirectory().getAbsolutePath() );
-        log.debug( "EnvironmentVariables " + Arrays.asList( cl.getEnvironmentVariables() ) );
-
-        // ----------------------------------------------------------------------
-        //
-        // ----------------------------------------------------------------------
-
-        //CommandLineUtils.StringStreamConsumer consumer = new CommandLineUtils.StringStreamConsumer();
-
-        Writer writer = new FileWriter( output );
-
-        StreamConsumer consumer = new WriterStreamConsumer( writer );
-
-        int exitCode = CommandLineUtils.executeCommandLine( cl, consumer, consumer );
-
-        writer.flush();
-
-        writer.close();
-
-        // ----------------------------------------------------------------------
-        //
-        // ----------------------------------------------------------------------
-
-        return new ExecutionResult( exitCode );
-    }
-
-    public boolean isRunning( long idCommand )
-    {
-        return CommandLineUtils.isAlive( idCommand );
-    }
-
-    public void killProcess( long idCommand )
-    {
-        CommandLineUtils.killProcess( idCommand );
-    }
-
-    public void executeGoals( File workingDirectory, String goals, boolean interactive, String arguments,
-                              ReleaseResult relResult, Map<String, String> environments )
-        throws Exception
-    {
-        Commandline cl = new Commandline();
-
-        Commandline.Argument argument = cl.createArgument();
-
-        argument.setLine( arguments );
-
-        executeGoals( workingDirectory, goals, interactive, argument.getParts(), relResult, environments );
-    }
-
-    public void executeGoals( File workingDirectory, String goals, boolean interactive, String[] arguments,
-                              ReleaseResult relResult, Map<String, String> environments )
-        throws Exception
-    {
-        Commandline cl = createCommandline( workingDirectory, "mvn", arguments, -1, environments );
-
-        if ( goals != null )
-        {
-            // accept both space and comma, so the old way still work
-            String[] tokens = StringUtils.split( goals, ", " );
-
-            for ( int i = 0; i < tokens.length; ++i )
-    		{
-                cl.createArgument().setValue( tokens[i] );
-    		}
-        }
-
-        cl.createArgument().setValue( "--no-plugin-updates" );
-
-        if ( !interactive )
-        {
-            cl.createArgument().setValue( "--batch-mode" );
-        }
-
-        StreamConsumer stdOut = new TeeConsumer( System.out );
-
-        StreamConsumer stdErr = new TeeConsumer( System.err );
-
-        try
-        {
-    		relResult.appendInfo( "Executing: " + cl.toString() );
-    		log.info( "Executing: " + cl.toString() );
-
-    		int result = CommandLineUtils.executeCommandLine( cl, stdOut, stdErr );
-
-    		if ( result != 0 )
-    		{
-    		    throw new MavenExecutorException( "Maven execution failed, exit code: \'" + result + "\'", result,
-    		                                      stdOut.toString(), stdErr.toString() );
-    		}
-        }
-        catch ( CommandLineException e )
-        {
-            throw new MavenExecutorException( "Can't run goal " + goals, stdOut.toString(), stdErr.toString(), e );
-        }
-        finally
-        {
-            relResult.appendOutput( stdOut.toString() );
-        }
-    }
-}
diff --git a/continuum-commons/src/main/java/org/apache/continuum/utils/shell/ExecutionResult.java b/continuum-commons/src/main/java/org/apache/continuum/utils/shell/ExecutionResult.java
deleted file mode 100644
index 72c99cd..0000000
--- a/continuum-commons/src/main/java/org/apache/continuum/utils/shell/ExecutionResult.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.apache.continuum.utils.shell;
-
-/*
- * 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.
- */
-
-/**
- * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
- * @version $Id$
- */
-public class ExecutionResult
-{
-    private int exitCode;
-
-    public ExecutionResult( int exitCode )
-    {
-        this.exitCode = exitCode;
-    }
-
-    public int getExitCode()
-    {
-        return exitCode;
-    }
-}
diff --git a/continuum-commons/src/main/java/org/apache/continuum/utils/shell/ShellCommandHelper.java b/continuum-commons/src/main/java/org/apache/continuum/utils/shell/ShellCommandHelper.java
deleted file mode 100644
index fcdbd88..0000000
--- a/continuum-commons/src/main/java/org/apache/continuum/utils/shell/ShellCommandHelper.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package org.apache.continuum.utils.shell;
-
-/*
- * 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.io.File;
-import java.util.Map;
-
-import org.apache.continuum.utils.shell.ExecutionResult;
-import org.apache.maven.shared.release.ReleaseResult;
-
-/**
- * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
- * @version $Id$
- */
-public interface ShellCommandHelper
-{
-    String ROLE = ShellCommandHelper.class.getName();
-
-    ExecutionResult executeShellCommand( File workingDirectory, String executable, String arguments, File output,
-                                         long idCommand, Map<String, String> environments )
-        throws Exception;
-
-    ExecutionResult executeShellCommand( File workingDirectory, String executable, String[] arguments, File output,
-                                         long idCommand, Map<String, String> environments )
-        throws Exception;
-
-    boolean isRunning( long idCommand );
-
-    void killProcess( long idCommand );
-
-    void executeGoals( File workingDirectory, String goals, boolean interactive, String arguments,
-                       ReleaseResult relResult, Map<String, String> environments )
-        throws Exception;
-
-    void executeGoals( File workingDirectory, String goals, boolean interactive, String[] arguments,
-                       ReleaseResult relResult, Map<String, String> environments )
-        throws Exception;
-}
diff --git a/continuum-commons/src/main/java/org/apache/maven/continuum/configuration/DefaultConfigurationService.java b/continuum-commons/src/main/java/org/apache/maven/continuum/configuration/DefaultConfigurationService.java
index 802c6d1..ed0b67d 100644
--- a/continuum-commons/src/main/java/org/apache/maven/continuum/configuration/DefaultConfigurationService.java
+++ b/continuum-commons/src/main/java/org/apache/maven/continuum/configuration/DefaultConfigurationService.java
@@ -19,12 +19,16 @@
  * under the License.
  */
 
+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;
 import org.apache.continuum.dao.ScheduleDao;
 import org.apache.continuum.dao.SystemConfigurationDao;
+import org.apache.maven.continuum.model.project.BuildQueue;
 import org.apache.maven.continuum.model.project.Schedule;
 import org.apache.maven.continuum.model.system.SystemConfiguration;
 import org.apache.maven.continuum.store.ContinuumStoreException;
@@ -37,7 +41,6 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
-
 import javax.annotation.Resource;
 
 /**
@@ -47,9 +50,9 @@
 public class DefaultConfigurationService
     implements ConfigurationService
 {
-    private Logger log = LoggerFactory.getLogger( this.getClass() );
+    private static final Logger log = LoggerFactory.getLogger( DefaultConfigurationService.class );
 
-    // when adding requirement the template in application.xml must be updated CONTINUUM-1207
+    // when adding a requirement, the template in spring-context.xml must be updated CONTINUUM-1207
 
     /**
      * @plexus.configuration default-value="${plexus.home}"
@@ -63,6 +66,9 @@
     private SystemConfigurationDao systemConfigurationDao;
 
     @Resource
+    private BuildQueueService buildQueueService;
+
+    @Resource
     private ContinuumConfiguration configuration;
 
     private GeneralConfiguration generalConfiguration;
@@ -95,6 +101,16 @@
         this.scheduleDao = scheduleDao;
     }
 
+    public BuildQueueService getBuildQueueService()
+    {
+        return buildQueueService;
+    }
+
+    public void setBuildQueueService( BuildQueueService buildQueueService )
+    {
+        this.buildQueueService = buildQueueService;
+    }
+
     public SystemConfigurationDao getSystemConfigurationDao()
     {
         return systemConfigurationDao;
@@ -127,12 +143,12 @@
 
     public void setInitialized( boolean initialized )
     {
-        systemConf.setInitialized( initialized );
+        generalConfiguration.setInitialized( initialized );
     }
 
     public boolean isInitialized()
     {
-        return systemConf.isInitialized();
+        return systemConf.isInitialized() || generalConfiguration.isInitialized();
     }
 
     public String getUrl()
@@ -151,7 +167,7 @@
         generalConfiguration.setBaseUrl( url );
     }
 
-    /** 
+    /**
      * @see org.apache.maven.continuum.configuration.ConfigurationService#getBuildOutputDirectory()
      */
     public File getBuildOutputDirectory()
@@ -232,7 +248,7 @@
             }
             else
             {
-                return "There are no output for this build.";
+                return "There is no output for this build.";
             }
         }
         catch ( IOException e )
@@ -282,6 +298,9 @@
     public void addBuildAgent( BuildAgentConfiguration buildAgent )
         throws ConfigurationException
     {
+        // trim trailing space
+        buildAgent.setUrl( buildAgent.getUrl().trim() );
+
         List<BuildAgentConfiguration> buildAgents = generalConfiguration.getBuildAgents();
         if ( buildAgents == null )
         {
@@ -290,7 +309,7 @@
 
         for ( BuildAgentConfiguration agent : buildAgents )
         {
-            if ( agent.getUrl().equals( buildAgent.getUrl() ) )
+            if ( agent.getUrl().trim().equals( buildAgent.getUrl() ) )
             {
                 throw new ConfigurationException( "Unable to add build agent: build agent already exist" );
             }
@@ -319,16 +338,20 @@
 
     public void updateBuildAgent( BuildAgentConfiguration buildAgent )
     {
+        // trim trailing space
+        buildAgent.setUrl( buildAgent.getUrl().trim() );
+
         List<BuildAgentConfiguration> buildAgents = getBuildAgents();
         if ( buildAgents != null )
         {
             for ( BuildAgentConfiguration agent : buildAgents )
             {
-                if ( agent.getUrl().equals( buildAgent.getUrl() ) )
+                if ( agent.getUrl().trim().equals( buildAgent.getUrl() ) )
                 {
                     agent.setDescription( buildAgent.getDescription() );
                     agent.setEnabled( buildAgent.isEnabled() );
-                    
+                    agent.setUrl( buildAgent.getUrl() );
+
                     return;
                 }
             }
@@ -337,12 +360,184 @@
 
     public boolean isDistributedBuildEnabled()
     {
-        return systemConf.isDistributedBuildEnabled();
+        return generalConfiguration.isDistributedBuildEnabled();
     }
 
     public void setDistributedBuildEnabled( boolean distributedBuildEnabled )
     {
-        systemConf.setDistributedBuildEnabled( distributedBuildEnabled );
+        generalConfiguration.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;
     }
 
     // ----------------------------------------------------------------------
@@ -395,9 +590,9 @@
         {
             return null;
         }
-        
+
         File dir = new File( getReleaseOutputDirectory(), Integer.toString( projectGroupId ) );
-        
+
         try
         {
             dir = dir.getCanonicalFile();
@@ -405,7 +600,7 @@
         catch ( IOException e )
         {
         }
-        
+
         return dir;
     }
 
@@ -418,7 +613,7 @@
         {
             return null;
         }
-        
+
         if ( !dir.exists() && !dir.mkdirs() )
         {
             throw new ConfigurationException(
@@ -441,7 +636,7 @@
             }
             else
             {
-                return "There are no output for this release.";
+                return "There is no output for this release.";
             }
         }
         catch ( IOException e )
@@ -451,6 +646,26 @@
         }
     }
 
+    public int getNumberOfBuildsInParallel()
+    {
+        return generalConfiguration.getNumberOfBuildsInParallel();
+    }
+
+    public void setNumberOfBuildsInParallel( int num )
+    {
+        generalConfiguration.setNumberOfBuildsInParallel( num );
+    }
+
+    public String getSharedSecretPassword()
+    {
+        return generalConfiguration.getSharedSecretPassword();
+    }
+
+    public void setSharedSecretPassword( String sharedSecretPassword )
+    {
+        generalConfiguration.setSharedSecretPassword( sharedSecretPassword );
+    }
+
     // ----------------------------------------------------------------------
     //
     // ----------------------------------------------------------------------
@@ -464,7 +679,7 @@
 
         File f = null;
 
-        if ( filename != null && filename.length() != 0 )
+        if ( filename.length() != 0 )
         {
             f = new File( filename );
 
@@ -476,7 +691,11 @@
 
         try
         {
-            return f.getCanonicalFile();
+            if ( f != null )
+            {
+                return f.getCanonicalFile();
+            }
+            return null;
         }
         catch ( IOException e )
         {
@@ -506,7 +725,6 @@
             if ( systemConf == null )
             {
                 systemConf = new SystemConfiguration();
-
                 systemConf = getSystemConfigurationDao().addSystemConfiguration( systemConf );
             }
 
@@ -529,19 +747,13 @@
         throws ConfigurationStoringException, ContinuumConfigurationException
     {
         configuration.setGeneralConfiguration( generalConfiguration );
+
         configuration.save();
-        try
-        {
-            getSystemConfigurationDao().updateSystemConfiguration( systemConf );
-        }
-        catch ( ContinuumStoreException e )
-        {
-            throw new ConfigurationStoringException( "Error writting configuration to database.", e );
-        }
     }
 
     public Schedule getDefaultSchedule()
-        throws ContinuumStoreException, ConfigurationLoadingException, ContinuumConfigurationException
+        throws ContinuumStoreException, ConfigurationLoadingException, ContinuumConfigurationException,
+        BuildQueueServiceException
     {
         // Schedule
         Schedule defaultSchedule = scheduleDao.getScheduleByName( DEFAULT_SCHEDULE_NAME );
@@ -556,12 +768,28 @@
         return defaultSchedule;
     }
 
+    public BuildQueue getDefaultBuildQueue()
+        throws BuildQueueServiceException
+    {
+        BuildQueue defaultBuildQueue = buildQueueService.getBuildQueueByName( DEFAULT_BUILD_QUEUE_NAME );
+
+        if ( defaultBuildQueue == null )
+        {
+            defaultBuildQueue = createDefaultBuildQueue();
+
+            defaultBuildQueue = buildQueueService.addBuildQueue( defaultBuildQueue );
+        }
+
+        return defaultBuildQueue;
+    }
+
     // ----------------------------------------------------------------------
     //
     // ----------------------------------------------------------------------
 
     private Schedule createDefaultSchedule()
-        throws ConfigurationLoadingException, ContinuumConfigurationException
+        throws ConfigurationLoadingException, ContinuumConfigurationException, ContinuumStoreException,
+        BuildQueueServiceException
     {
 
         log.info( "create Default Schedule" );
@@ -582,7 +810,21 @@
 
         schedule.setActive( true );
 
+        BuildQueue buildQueue = getDefaultBuildQueue();
+
+        schedule.addBuildQueue( buildQueue );
+
         return schedule;
     }
 
+    private BuildQueue createDefaultBuildQueue()
+    {
+        log.info( "create Default Build Queue" );
+
+        BuildQueue buildQueue = new BuildQueue();
+
+        buildQueue.setName( DEFAULT_BUILD_QUEUE_NAME );
+
+        return buildQueue;
+    }
 }
diff --git a/continuum-commons/src/main/java/org/apache/maven/continuum/utils/ChrootJailWorkingDirectoryService.java b/continuum-commons/src/main/java/org/apache/maven/continuum/utils/ChrootJailWorkingDirectoryService.java
index 07c44b5..5a6f7f2 100644
--- a/continuum-commons/src/main/java/org/apache/maven/continuum/utils/ChrootJailWorkingDirectoryService.java
+++ b/continuum-commons/src/main/java/org/apache/maven/continuum/utils/ChrootJailWorkingDirectoryService.java
@@ -19,19 +19,20 @@
  * under the License.
  */
 
-import java.io.File;
-import javax.annotation.Resource;
-
 import org.apache.maven.continuum.configuration.ConfigurationService;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.project.ProjectGroup;
 import org.springframework.stereotype.Service;
 
+import java.io.File;
+import java.util.List;
+import javax.annotation.Resource;
+
 /**
  * @author <a href="mailto:carlos@apache.org">Carlos Sanchez</a>
  * @version $Id$
  */
-@Service("workingDirectoryService#chrootJail")
+@Service( "workingDirectoryService#chrootJail" )
 public class ChrootJailWorkingDirectoryService
     implements WorkingDirectoryService
 {
@@ -65,10 +66,25 @@
 
     public File getWorkingDirectory( Project project )
     {
+        return getWorkingDirectory( project, true );
+    }
+
+    public File getWorkingDirectory( Project project, boolean shouldSet )
+    {
         ProjectGroup projectGroup = project.getProjectGroup();
 
         File f = new File( getChrootJailDirectory(), projectGroup.getGroupId() );
         f = new File( f, getConfigurationService().getWorkingDirectory().getPath() );
         return new File( f, Integer.toString( project.getId() ) );
     }
+
+    public File getWorkingDirectory( Project project, String projectScmRoot, List<Project> projects )
+    {
+        return getWorkingDirectory( project, true );
+    }
+
+    public File getWorkingDirectory( Project project, String projectScmRoot, List<Project> projects, boolean shouldSet )
+    {
+        return getWorkingDirectory( project, shouldSet );
+    }
 }
diff --git a/continuum-commons/src/main/java/org/apache/maven/continuum/utils/ContinuumUrlValidator.java b/continuum-commons/src/main/java/org/apache/maven/continuum/utils/ContinuumUrlValidator.java
index 1530b4c..b9b7c9d 100644
--- a/continuum-commons/src/main/java/org/apache/maven/continuum/utils/ContinuumUrlValidator.java
+++ b/continuum-commons/src/main/java/org/apache/maven/continuum/utils/ContinuumUrlValidator.java
@@ -19,26 +19,26 @@
  * under the License.
  */
 
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-
 import org.apache.commons.lang.StringUtils;
 import org.codehaus.plexus.configuration.PlexusConfiguration;
 import org.codehaus.plexus.configuration.PlexusConfigurationException;
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Configurable;
 import org.springframework.stereotype.Service;
 
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
 /**
  * @author <a href="mailto:olamy@apache.org">olamy</a>
- * @since 27 mars 2008
  * @version $Id$
  * @plexus.component role="org.apache.maven.continuum.utils.ContinuumUrlValidator"
- *   role-hint="continuumUrl"
+ * role-hint="continuumUrl"
+ * @since 27 mars 2008
  */
-@Service("continuumUrlValidator#continuumUrl")
+@Service( "continuumUrlValidator#continuumUrl" )
 public class ContinuumUrlValidator
     implements Configurable
 {
@@ -50,7 +50,7 @@
     /**
      * If no schemes are provided, default to this set.
      */
-    protected String[] defaultSchemes = { "http", "https", "ftp" };
+    protected String[] defaultSchemes = {"http", "https", "ftp"};
 
     /**
      * Create a UrlValidator with default properties.
@@ -62,10 +62,11 @@
 
     /**
      * Behavior of validation is modified by passing in several strings options:
+     *
      * @param schemes Pass in one or more url schemes to consider valid, passing in
-     *        a null will default to "http,https,ftp" being valid.
-     *        If a non-null schemes is specified then all valid schemes must
-     *        be specified.
+     *                a null will default to "http,https,ftp" being valid.
+     *                If a non-null schemes is specified then all valid schemes must
+     *                be specified.
      */
     public ContinuumUrlValidator( String[] schemes )
     {
@@ -81,7 +82,7 @@
      * <p>Checks if a field has a valid url address.</p>
      *
      * @param value The value validation is being performed on.  A <code>null</code>
-     * value is considered invalid.
+     *              value is considered invalid.
      * @return true if the url is valid.
      */
     public boolean validate( String value )
@@ -93,7 +94,7 @@
      * <p>Checks if a field has a valid url address.</p>
      *
      * @param value The value validation is being performed on.  A <code>null</code>
-     * value is considered valid.
+     *              value is considered valid.
      * @return true if the url is valid.
      */
     public boolean isValid( String value )
diff --git a/continuum-commons/src/main/java/org/apache/maven/continuum/utils/DefaultWorkingDirectoryService.java b/continuum-commons/src/main/java/org/apache/maven/continuum/utils/DefaultWorkingDirectoryService.java
index 3952b8a..83aaa3b 100644
--- a/continuum-commons/src/main/java/org/apache/maven/continuum/utils/DefaultWorkingDirectoryService.java
+++ b/continuum-commons/src/main/java/org/apache/maven/continuum/utils/DefaultWorkingDirectoryService.java
@@ -21,17 +21,18 @@
 
 import org.apache.maven.continuum.configuration.ConfigurationService;
 import org.apache.maven.continuum.model.project.Project;
+import org.codehaus.plexus.util.StringUtils;
 import org.springframework.stereotype.Service;
 
 import java.io.File;
-
+import java.util.List;
 import javax.annotation.Resource;
 
 /**
  * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
  * @version $Id$
  */
-@Service("workingDirectoryService")
+@Service( "workingDirectoryService" )
 public class DefaultWorkingDirectoryService
     implements WorkingDirectoryService
 {
@@ -54,19 +55,92 @@
 
     public File getWorkingDirectory( Project project )
     {
+        return getWorkingDirectory( project, null, null );
+    }
+
+    public File getWorkingDirectory( Project project, boolean shouldSet )
+    {
+        return getWorkingDirectory( project, null, null, shouldSet );
+    }
+
+    /**
+     * @param project
+     * @param projectScmRoot
+     * @param projects       projects under the same projectScmRoot
+     * @return
+     */
+    public File getWorkingDirectory( Project project, String projectScmRoot, List<Project> projects )
+    {
+        return getWorkingDirectory( project, projectScmRoot, projects, true );
+    }
+
+    /**
+     * @param project
+     * @param projectScmRoot
+     * @param projects       projects under the same projectScmRoot
+     * @param shouldSet
+     * @return
+     */
+    public File getWorkingDirectory( Project project, String projectScmRoot, List<Project> projects, boolean shouldSet )
+    {
 //        TODO: Enable, this is what we really want
 //        ContinuumProjectGroup projectGroup = project.getProjectGroup();
 //
 //        return new File( projectGroup.getWorkingDirectory(),
 //                         project.getPath() );
 
-        if ( project.getWorkingDirectory() == null )
+        String workingDirectory = project.getWorkingDirectory();
+
+        if ( project.getWorkingDirectory() == null || "".equals( project.getWorkingDirectory() ) )
         {
-            project.setWorkingDirectory( Integer.toString( project.getId() ) );
+            if ( project.isCheckedOutInSingleDirectory() && projectScmRoot != null && !"".equals( projectScmRoot ) )
+            {
+                Project rootProject = project;
+                if ( projects != null )
+                {
+                    // the root project should have the lowest id since it's always added first                    
+                    for ( Project projectUnderScmRoot : projects )
+                    {
+                        if ( projectUnderScmRoot.getId() < rootProject.getId() )
+                        {
+                            rootProject = projectUnderScmRoot;
+                        }
+                    }
+                }
+
+                // determine the path
+                String projectScmUrl = project.getScmUrl();
+                int indexDiff = StringUtils.differenceAt( projectScmUrl, projectScmRoot );
+
+                String pathToProject = "";
+                if ( indexDiff != -1 )
+                {
+                    pathToProject = projectScmUrl.substring( indexDiff );
+                }
+
+                if ( pathToProject.startsWith( "\\" ) || pathToProject.startsWith( "/" ) )
+                {
+                    workingDirectory = Integer.toString( rootProject.getId() ) + pathToProject;
+                }
+                else
+                {
+                    workingDirectory = Integer.toString( rootProject.getId() ) + File.separatorChar + pathToProject;
+                }
+            }
+            else
+            {
+                workingDirectory = Integer.toString( project.getId() );
+            }
+        }
+
+        if ( shouldSet )
+        {
+            project.setWorkingDirectory( workingDirectory );
         }
 
         File workDir;
-        File projectWorkingDirectory = new File( project.getWorkingDirectory() );
+        File projectWorkingDirectory = new File( workingDirectory );
+
         if ( projectWorkingDirectory.isAbsolute() )
         {
             // clean the project working directory path if it's a subdirectory of the global working directory
@@ -79,15 +153,22 @@
                 {
                     pwd = pwd.substring( 1 );
                 }
-                project.setWorkingDirectory( pwd );
+
+                if ( shouldSet )
+                {
+                    project.setWorkingDirectory( pwd );
+                }
             }
 
             workDir = projectWorkingDirectory;
         }
         else
         {
-            workDir = new File( getConfigurationService().getWorkingDirectory(), project.getWorkingDirectory() );
+            File baseWorkingDir = getConfigurationService().getWorkingDirectory();
+
+            workDir = new File( baseWorkingDir, workingDirectory );
         }
+
         return workDir;
     }
 }
diff --git a/continuum-commons/src/main/java/org/apache/maven/continuum/utils/URLUserInfo.java b/continuum-commons/src/main/java/org/apache/maven/continuum/utils/URLUserInfo.java
index b65bb43..2161329 100644
--- a/continuum-commons/src/main/java/org/apache/maven/continuum/utils/URLUserInfo.java
+++ b/continuum-commons/src/main/java/org/apache/maven/continuum/utils/URLUserInfo.java
@@ -28,11 +28,11 @@
 {
 
     private String username;
-    
+
     private String password;
-    
+
     /**
-     * 
+     *
      */
     public URLUserInfo()
     {
diff --git a/continuum-commons/src/main/resources/META-INF/spring-context.xml b/continuum-commons/src/main/resources/META-INF/spring-context.xml
index 464986b..720b5db 100644
--- a/continuum-commons/src/main/resources/META-INF/spring-context.xml
+++ b/continuum-commons/src/main/resources/META-INF/spring-context.xml
@@ -18,6 +18,7 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
   -->
+
 <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
@@ -26,15 +27,14 @@
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-2.5.xsd">
 
-  <context:annotation-config />
-  <context:component-scan 
-    base-package="org.apache.continuum.installation,org.apache.continuum.profile,
-                  org.apache.maven.continuum.configuration,org.apache.maven.continuum.utils,
-                  org.apache.continuum.utils,org.apache.continuum.utils.shell"/>
+  <context:annotation-config/>
+  <context:component-scan
+      base-package="org.apache.continuum.installation,org.apache.continuum.profile,
+                  org.apache.maven.continuum.configuration,org.apache.maven.continuum.utils"/>
 
   <bean id="configurationService" class="org.apache.maven.continuum.configuration.DefaultConfigurationService"
         init-method="initialize">
     <property name="applicationHome" value="data"/>
-  </bean> 
-  <bean id="shellCommandHelper" class="org.apache.continuum.utils.shell.DefaultShellCommandHelper"/>  
+  </bean>
+  <bean id="buildQueueService" class="org.apache.continuum.buildqueue.DefaultBuildQueueService"/>
 </beans>
\ No newline at end of file
diff --git a/continuum-commons/src/test/java/org/apache/continuum/installation/DefaultInstallationServiceTest.java b/continuum-commons/src/test/java/org/apache/continuum/installation/DefaultInstallationServiceTest.java
index f9c66c0..9c48d31 100644
--- a/continuum-commons/src/test/java/org/apache/continuum/installation/DefaultInstallationServiceTest.java
+++ b/continuum-commons/src/test/java/org/apache/continuum/installation/DefaultInstallationServiceTest.java
@@ -39,34 +39,14 @@
 public class DefaultInstallationServiceTest
     extends AbstractContinuumTest
 {
-    private static final String DEFAULT_INSTALLATION_NAME = "defaultInstallation";
-
     private static final String NEW_INSTALLATION_NAME = "newInstallation";
 
-    //public Installation defaultInstallation;
-
     protected void setUp()
         throws Exception
     {
         super.setUp();
         DaoUtils daoUtils = (DaoUtils) lookup( DaoUtils.class.getName() );
         daoUtils.eraseDatabase();
-        /*if ( getInstallationService().getAllInstallations().isEmpty() )
-        {
-            defaultInstallation = createDefault();
-            ContinuumStore store = getStore();
-            defaultInstallation = store.addInstallation( defaultInstallation );
-        }*/
-    }
-
-    private Installation createDefaultInstallation()
-    {
-        Installation installation = new Installation();
-        installation.setType( "description" );
-        installation.setName( DEFAULT_INSTALLATION_NAME );
-        installation.setVarName( "varName" );
-        installation.setVarValue( "varValue" );
-        return installation;
     }
 
     private InstallationService getInstallationService()
@@ -82,7 +62,7 @@
     {
 
         Installation installation = new Installation();
-        installation.setType( InstallationService.JDK_TYPE );
+        installation.setType( type );
         installation.setName( name );
         installation.setVarName( varName );
         installation.setVarValue( varValue );
@@ -98,6 +78,7 @@
         assertEquals( getInstallationService().getEnvVar( InstallationService.JDK_TYPE ), getted.getVarName() );
         assertEquals( "bar", getted.getVarValue() );
         assertEquals( 1, getInstallationService().getAllInstallations().size() );
+        assertNotNull( getInstallationService().getInstallation( NEW_INSTALLATION_NAME ) );
     }
 
     public void testAddDuplicateInstallation()
@@ -110,7 +91,7 @@
         assertEquals( "bar", getted.getVarValue() );
         try
         {
-            added = this.addInstallation( NEW_INSTALLATION_NAME, null, "bar", InstallationService.JDK_TYPE );
+            this.addInstallation( NEW_INSTALLATION_NAME, null, "bar", InstallationService.JDK_TYPE );
             fail( "not in AlreadyExistsInstallationException" );
         }
         catch ( AlreadyExistsInstallationException e )
@@ -151,15 +132,15 @@
         assertEquals( "updatedbar", getted.getVarValue() );
     }
 
-    public void testgetDefaultJdkInformations()
+    public void testGetDefaultJavaVersionInfo()
         throws Exception
     {
         InstallationService installationService = (InstallationService) lookup( InstallationService.ROLE, "default" );
-        List<String> infos = installationService.getDefaultJdkInformations();
+        List<String> infos = installationService.getDefaultJavaVersionInfo();
         assertNotNull( infos );
     }
 
-    public void testgetJdkInformations()
+    public void testGetJavaVersionInfo()
         throws Exception
     {
         InstallationService installationService = (InstallationService) lookup( InstallationService.ROLE, "default" );
@@ -173,11 +154,11 @@
         installation.setType( InstallationService.JDK_TYPE );
         installation.setVarValue( javaHome );
 
-        List<String> infos = installationService.getJdkInformations( installation );
+        List<String> infos = installationService.getJavaVersionInfo( installation );
         assertNotNull( infos );
     }
 
-    public void testgetJdkInformationsWithCommonMethod()
+    public void testGetJavaVersionInfoWithCommonMethod()
         throws Exception
     {
         InstallationService installationService = (InstallationService) lookup( InstallationService.ROLE, "default" );
@@ -187,19 +168,21 @@
         {
             javaHome = System.getProperty( "java.home" );
         }
-        List<String> infos = installationService.getExecutorConfiguratorVersion( javaHome, java, null );
+        List<String> infos = installationService.getExecutorVersionInfo( javaHome, java, null );
         System.out.println( infos );
         assertNotNull( infos );
     }
 
+/* CONTINUUM-2559 - test may fail even in a valid environment
     public void testgetMvnVersionWithCommonMethod()
         throws Exception
     {
         InstallationService installationService = (InstallationService) lookup( InstallationService.ROLE, "default" );
         ExecutorConfigurator java = installationService.getExecutorConfigurator( InstallationService.MAVEN2_TYPE );
-        List<String> infos = installationService.getExecutorConfiguratorVersion( null, java, null );
+        List<String> infos = installationService.getExecutorVersionInfo( null, java, null );
         assertNotNull( infos );
     }
+*/
 
     public void testAddInstallationAutomaticProfile()
         throws Exception
@@ -210,11 +193,11 @@
         installation.setName( "automaticJdk" );
         installation.setVarName( "automaticvarName" );
         installation.setVarValue( "automaticvarValue" );
-        installation = getInstallationService().add( installation, true );
+        getInstallationService().add( installation, true );
         ProfileService profileService = (ProfileService) lookup( ProfileService.ROLE, "default" );
         List<Profile> profiles = profileService.getAllProfiles();
         assertEquals( 1, profiles.size() );
-        Profile profile = (Profile) profiles.get( 0 );
+        Profile profile = profiles.get( 0 );
         assertEquals( "automaticJdk", profile.getName() );
         Installation jdk = profile.getJdk();
         assertNotNull( jdk );
diff --git a/continuum-commons/src/test/java/org/apache/continuum/profile/DefaultProfileServiceTest.java b/continuum-commons/src/test/java/org/apache/continuum/profile/DefaultProfileServiceTest.java
index e3540a6..d50cc17 100644
--- a/continuum-commons/src/test/java/org/apache/continuum/profile/DefaultProfileServiceTest.java
+++ b/continuum-commons/src/test/java/org/apache/continuum/profile/DefaultProfileServiceTest.java
@@ -40,35 +40,35 @@
 
     Installation jdk1;
 
-    String jdk1Name = "jdk1";
+    private static final String jdk1Name = "jdk1";
 
-    Installation jdk2;
+    private Installation jdk2;
 
-    String jdk2Name = "jdk2";
+    private static final String jdk2Name = "jdk2";
 
     Installation mvn205;
 
-    String mvn205Name = "mvn 2.0.5";
+    private static final String mvn205Name = "mvn 2.0.5";
 
     Installation mvn206;
 
-    String mvn206Name = "mvn 2.0.6";
+    private static final String mvn206Name = "mvn 2.0.6";
 
     Profile jdk1mvn205;
 
-    String jdk1mvn205Name = "jdk1 mvn 2.0.5";
+    private static final String jdk1mvn205Name = "jdk1 mvn 2.0.5";
 
     Profile jdk2mvn206;
 
-    String jdk2mvn206Name = "jdk2 mvn 2.0.6";
+    private static final String jdk2mvn206Name = "jdk2 mvn 2.0.6";
 
     Installation mvnOpts1;
 
-    String mvnOpts1Name = "mvnOpts1";
+    private static final String mvnOpts1Name = "mvnOpts1";
 
     Installation mvnOpts2;
 
-    String mvnOpts2Name = "mvnOpts2";
+    private static final String mvnOpts2Name = "mvnOpts2";
 
     protected void setUp()
         throws Exception
@@ -168,7 +168,7 @@
         defaultProfile.setName( name );
         try
         {
-            getted = getProfileService().addProfile( defaultProfile );
+            getProfileService().addProfile( defaultProfile );
             fail( "no AlreadyExistsProfileException with an already exist name " );
         }
         catch ( AlreadyExistsProfileException e )
@@ -216,20 +216,22 @@
     public void testupdateProfileDuplicateName()
         throws Exception
     {
-        Profile profile = getProfileService().getProfile( jdk1mvn205.getId() );
+        int profileId = jdk1mvn205.getId();
+        Profile profile = getProfileService().getProfile( profileId );
         assertEquals( jdk1mvn205Name, profile.getName() );
         profile.setName( jdk2mvn206Name );
 
         try
         {
             getProfileService().updateProfile( profile );
+
             fail( "no AlreadyExistsProfileException with duplicate name" );
         }
         catch ( AlreadyExistsProfileException e )
         {
             // we must be here
         }
-        Profile getted = getProfileService().getProfile( jdk1mvn205.getId() );
+        Profile getted = getProfileService().getProfile( profileId );
         assertNotNull( getted );
         assertEquals( jdk1mvn205Name, getted.getName() );
     }
@@ -273,7 +275,7 @@
         Profile profile = getProfileService().getProfile( jdk1mvn205.getId() );
         getProfileService().setJdkInProfile( profile, jdk2 );
 
-        profile = getProfileService().getProfile( jdk1mvn205.getId() );
+        getProfileService().getProfile( jdk1mvn205.getId() );
         InstallationService installationService = (InstallationService) lookup( InstallationService.ROLE, "default" );
         installationService.delete( jdk2 );
     }
diff --git a/continuum-commons/src/test/java/org/apache/continuum/utils/ContinuumUtilsTest.java b/continuum-commons/src/test/java/org/apache/continuum/utils/ContinuumUtilsTest.java
index ae1b0ed..a1c0c82 100644
--- a/continuum-commons/src/test/java/org/apache/continuum/utils/ContinuumUtilsTest.java
+++ b/continuum-commons/src/test/java/org/apache/continuum/utils/ContinuumUtilsTest.java
@@ -19,8 +19,6 @@
  * under the License.
  */
 
-import org.apache.continuum.utils.ContinuumUtils;
-
 import junit.framework.TestCase;
 
 /**
diff --git a/continuum-commons/src/test/java/org/apache/continuum/utils/ProjectSorterTest.java b/continuum-commons/src/test/java/org/apache/continuum/utils/ProjectSorterTest.java
deleted file mode 100644
index 6785a75..0000000
--- a/continuum-commons/src/test/java/org/apache/continuum/utils/ProjectSorterTest.java
+++ /dev/null
@@ -1,144 +0,0 @@
-package org.apache.continuum.utils;
-
-/*
- * 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 junit.framework.TestCase;
-import org.apache.maven.continuum.model.project.Project;
-import org.apache.maven.continuum.model.project.ProjectDependency;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * @author <a href="mailto:jmcconnell@apache.org">Jesse McConnell</a>
- * @version $Id:$
- */
-public class ProjectSorterTest
-    extends TestCase
-{
-
-    /**
-     * test basic three project tree (really a line in this case)
-     *
-     * @throws Exception
-     */
-    public void testBasicNestedProjectStructure()
-        throws Exception
-    {
-        List<Project> list = new ArrayList<Project>();
-
-        Project top = getNewProject( "top" );
-        list.add( top );
-
-        Project c1 = getNewProject( "c1" );
-        c1.setParent( generateProjectDependency( top ) );
-        list.add( c1 );
-
-        Project c2 = getNewProject( "c2" );
-        c2.setParent( generateProjectDependency( top ) );
-        c2.setDependencies( Collections.singletonList( generateProjectDependency( c1 ) ) );
-        list.add( c2 );
-
-        List<Project> sortedList = ProjectSorter.getSortedProjects( list, null );
-
-        assertNotNull( sortedList );
-
-        Project p1 = (Project) sortedList.get( 0 );
-        assertEquals( top.getArtifactId(), p1.getArtifactId() );
-        Project p2 = (Project) sortedList.get( 1 );
-        assertEquals( c1.getArtifactId(), p2.getArtifactId() );
-        Project p3 = (Project) sortedList.get( 2 );
-        assertEquals( c2.getArtifactId(), p3.getArtifactId() );
-    }
-
-    /**
-     * test one of the child projects not having the artifactId or groupId empty and working off the
-     * name instead
-     *
-     * @throws Exception
-     */
-    public void testIncompleteNestedProjectStructure()
-        throws Exception
-    {
-        List<Project> list = new ArrayList<Project>();
-
-        Project top = getNewProject( "top" );
-        list.add( top );
-
-        Project c1 = getIncompleteProject( "c1" );
-        c1.setParent( generateProjectDependency( top ) );
-        list.add( c1 );
-
-        Project c2 = getNewProject( "c2" );
-        c2.setParent( generateProjectDependency( top ) );
-        c2.setDependencies( Collections.singletonList( generateProjectDependency( c1 ) ) );
-        list.add( c2 );
-
-        List<Project> sortedList = ProjectSorter.getSortedProjects( list, null );
-
-        assertNotNull( sortedList );
-
-        Project p1 = (Project) sortedList.get( 0 );
-        assertEquals( top.getArtifactId(), p1.getArtifactId() );
-        Project p2 = (Project) sortedList.get( 1 );
-        assertEquals( c1.getArtifactId(), p2.getArtifactId() );
-        Project p3 = (Project) sortedList.get( 2 );
-        assertEquals( c2.getArtifactId(), p3.getArtifactId() );
-
-    }
-
-    /**
-     * project sorter can work with name replacing the artifactid and groupId
-     *
-     * @param projectId
-     * @return
-     */
-    private Project getIncompleteProject( String projectId )
-    {
-        Project project = new Project();
-        project.setName( "foo" + projectId );
-        project.setVersion( "v" + projectId );
-
-        return project;
-    }
-
-    private Project getNewProject( String projectId )
-    {
-        Project project = new Project();
-        project.setArtifactId( "a" + projectId );
-        project.setGroupId( "g" + projectId );
-        project.setVersion( "v" + projectId );
-        project.setName( "n" + projectId );
-
-        return project;
-    }
-
-    private ProjectDependency generateProjectDependency( Project project )
-    {
-        ProjectDependency dep = new ProjectDependency();
-        dep.setArtifactId( project.getArtifactId() );
-        dep.setGroupId( project.getGroupId() );
-        dep.setVersion( project.getVersion() );
-
-        return dep;
-    }
-
-}
\ No newline at end of file
diff --git a/continuum-commons/src/test/java/org/apache/maven/continuum/configuration/ConfigurationServiceTest.java b/continuum-commons/src/test/java/org/apache/maven/continuum/configuration/ConfigurationServiceTest.java
index 3fc72a5..98c28da 100644
--- a/continuum-commons/src/test/java/org/apache/maven/continuum/configuration/ConfigurationServiceTest.java
+++ b/continuum-commons/src/test/java/org/apache/maven/continuum/configuration/ConfigurationServiceTest.java
@@ -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;
@@ -34,9 +35,9 @@
 public class ConfigurationServiceTest
     extends PlexusInSpringTestCase
 {
-    private Logger log = LoggerFactory.getLogger( getClass() );
+    private static final Logger log = LoggerFactory.getLogger( ConfigurationServiceTest.class );
 
-    private String confFile = "target/test-classes/conf/continuum.xml";
+    private static final String confFile = "target/test-classes/conf/continuum.xml";
 
     @Override
     protected void setUp()
@@ -64,8 +65,8 @@
         log.info( "myBuildOutputDir " + new File( getBasedir(), "target/myBuildOutputDir" ).getAbsolutePath() );
 
         log.info( "getBuildOutputDirectory " + service.getBuildOutputDirectory().getAbsolutePath() );
-        assertEquals( new File( getBasedir(), "target/myBuildOutputDir" ).getAbsolutePath(), service
-            .getBuildOutputDirectory().getAbsolutePath() );
+        assertEquals( new File( getBasedir(), "target/myBuildOutputDir" ).getAbsolutePath(),
+                      service.getBuildOutputDirectory().getAbsolutePath() );
     }
 
     public void testConfigurationService()
@@ -90,7 +91,7 @@
 //        assertEquals( "working-directory", service.getWorkingDirectory().getName() );
 
         assertEquals( "check # build agents", 1, service.getBuildAgents().size() );
-        
+
         service.setUrl( "http://test/zloug" );
         service.setBuildOutputDirectory( new File( "testBuildOutputDir" ) );
 
@@ -105,7 +106,7 @@
         service.reload();
 
         assertEquals( "http://test/zloug", service.getUrl() );
-        assertEquals( "check # build agents", 2, service.getBuildAgents().size() );        
+        assertEquals( "check # build agents", 2, service.getBuildAgents().size() );
         assertEquals( "http://test/xmlrpc", service.getBuildAgents().get( 1 ).getUrl() );
         assertEquals( "windows", service.getBuildAgents().get( 1 ).getDescription() );
         assertFalse( service.getBuildAgents().get( 1 ).isEnabled() );
@@ -119,5 +120,78 @@
         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() );
+        assertNull( service.getSharedSecretPassword() );
+
+        service.setSharedSecretPassword( "password" );
+        service.store();
+        service.reload();
+
+        assertEquals( "password", service.getSharedSecretPassword() );
+    }
+
+    public void testAddDuplicateBuildAgentUrl()
+        throws Exception
+    {
+        ConfigurationService service = (ConfigurationService) lookup( "configurationService" );
+
+        assertNotNull( service );
+
+        BuildAgentConfiguration buildAgent = new BuildAgentConfiguration( "http://agent1/xmlrpc ", "windows", false );
+        service.addBuildAgent( buildAgent );
+        service.store();
+        service.reload();
+
+        assertEquals( "check # build agents", 2, service.getBuildAgents().size() );
+        assertNotNull( service.getBuildAgent( "http://agent1/xmlrpc" ) );
+
+        BuildAgentConfiguration buildAgent2 = new BuildAgentConfiguration( "http://agent1/xmlrpc", "windows", false );
+
+        try
+        {
+            service.addBuildAgent( buildAgent2 );
+            fail( "Should have thrown an exception because of duplicate agent url" );
+        }
+        catch ( ConfigurationException e )
+        {
+            assertEquals( "Unable to add build agent: build agent already exist", e.getMessage() );
+        }
+
+        service.removeBuildAgent( buildAgent );
+        service.store();
     }
 }
diff --git a/continuum-commons/src/test/java/org/apache/maven/continuum/utils/ContinuumUrlValidatorTest.java b/continuum-commons/src/test/java/org/apache/maven/continuum/utils/ContinuumUrlValidatorTest.java
index 2e638f3..ec3cf44 100644
--- a/continuum-commons/src/test/java/org/apache/maven/continuum/utils/ContinuumUrlValidatorTest.java
+++ b/continuum-commons/src/test/java/org/apache/maven/continuum/utils/ContinuumUrlValidatorTest.java
@@ -1,9 +1,9 @@
 package org.apache.maven.continuum.utils;
 
-import java.io.File;
-
 import org.codehaus.plexus.spring.PlexusInSpringTestCase;
 
+import java.io.File;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -30,7 +30,7 @@
 public class ContinuumUrlValidatorTest
     extends PlexusInSpringTestCase
 {
-    
+
     protected ContinuumUrlValidator getContinuumUrlValidator()
         throws Exception
     {
@@ -41,7 +41,7 @@
         throws Exception
     {
         return (ContinuumUrlValidator) lookup( ContinuumUrlValidator.class, roleHint );
-    }    
+    }
 
     public void testSuccessHttp()
         throws Exception
@@ -58,15 +58,15 @@
     public void testSuccessHttpWithAuth()
         throws Exception
     {
-        assertTrue( getContinuumUrlValidator()
-            .validate( "https://username:password@svn.apache.org/repos/asf/continuum/trunk/pom.xml" ) );
+        assertTrue( getContinuumUrlValidator().validate(
+            "https://username:password@svn.apache.org/repos/asf/continuum/trunk/pom.xml" ) );
     }
 
     public void testFailureHttpWithAuth()
         throws Exception
     {
-        assertTrue( getContinuumUrlValidator()
-            .validate( "http://username:passwordsvn.apache.org/repos/asf/continuum/trunk/pom.xml" ) );
+        assertTrue( getContinuumUrlValidator().validate(
+            "http://username:passwordsvn.apache.org/repos/asf/continuum/trunk/pom.xml" ) );
     }
 
     public void testFailureHttpWithFile()
@@ -84,91 +84,88 @@
     public void testSuccessHttpsWithAuth()
         throws Exception
     {
-        assertTrue( getContinuumUrlValidator()
-            .validate( "https://username:password@svn.apache.org/repos/asf/continuum/trunk/pom.xml" ) );
+        assertTrue( getContinuumUrlValidator().validate(
+            "https://username:password@svn.apache.org/repos/asf/continuum/trunk/pom.xml" ) );
     }
 
     public void testSuccessHttpviewvc()
         throws Exception
     {
-        assertTrue( getContinuumUrlValidator()
-            .validate( "http://svn.apache.org/viewvc/continuum/trunk/pom.xml?revision=681492&content-type=text%2Fplain" ) );
+        assertTrue( getContinuumUrlValidator().validate(
+            "http://svn.apache.org/viewvc/continuum/trunk/pom.xml?revision=681492&content-type=text%2Fplain" ) );
     }
 
     public void testSuccessHttpviewvcWithAuth()
         throws Exception
     {
-        assertTrue( getContinuumUrlValidator()
-            .validate(
-                       "http://username:password@svn.apache.org/viewvc/continuum/trunk/pom.xml?revision=681492&content-type=text%2Fplain" ) );
+        assertTrue( getContinuumUrlValidator().validate(
+            "http://username:password@svn.apache.org/viewvc/continuum/trunk/pom.xml?revision=681492&content-type=text%2Fplain" ) );
     }
 
     public void testSuccessHttpsviewvc()
         throws Exception
     {
-        assertTrue( getContinuumUrlValidator()
-            .validate(
-                       "https://svn.apache.org/viewvc/continuum/trunk/pom.xml?revision=681492&content-type=text%2Fplain" ) );
+        assertTrue( getContinuumUrlValidator().validate(
+            "https://svn.apache.org/viewvc/continuum/trunk/pom.xml?revision=681492&content-type=text%2Fplain" ) );
     }
 
     public void testSuccessHttpsviewvcWithAuth()
         throws Exception
     {
-        assertTrue( getContinuumUrlValidator()
-            .validate(
-                       "https://username:password@svn.apache.org/viewvc/continuum/trunk/pom.xml?revision=681492&content-type=text%2Fplain" ) );
+        assertTrue( getContinuumUrlValidator().validate(
+            "https://username:password@svn.apache.org/viewvc/continuum/trunk/pom.xml?revision=681492&content-type=text%2Fplain" ) );
     }
 
     public void testSuccessHttpfisheye()
         throws Exception
     {
-        assertTrue( getContinuumUrlValidator()
-            .validate( "http://fisheye6.atlassian.com/browse/~raw,r=680040/continuum/trunk/pom.xml" ) );
+        assertTrue( getContinuumUrlValidator().validate(
+            "http://fisheye6.atlassian.com/browse/~raw,r=680040/continuum/trunk/pom.xml" ) );
     }
 
     public void testSuccessHttpsfisheye()
         throws Exception
     {
-        assertTrue( getContinuumUrlValidator()
-            .validate( "https://fisheye6.atlassian.com/browse/~raw,r=680040/continuum/trunk/pom.xml" ) );
+        assertTrue( getContinuumUrlValidator().validate(
+            "https://fisheye6.atlassian.com/browse/~raw,r=680040/continuum/trunk/pom.xml" ) );
     }
 
     public void testValidateFile()
         throws Exception
     {
-        File rootPom = getTestFile( "src/test/resources/log4j.xml" );
+        File rootPom = getTestFile( "src/test/resources/META-INF/continuum/continuum-configuration.xml" );
         assertTrue( rootPom.exists() );
         assertTrue( getContinuumUrlValidator().validate( rootPom.toURL().toExternalForm() ) );
     }
-   
-    
+
+
     public void testExtractUserNamePwd()
         throws Exception
     {
         ContinuumUrlValidator continuumUrlValidator = new ContinuumUrlValidator();
-        URLUserInfo usrInfo = continuumUrlValidator
-            .extractURLUserInfo( "https://username:password@svn.apache.org/repos/asf/continuum/trunk/pom.xml" );
+        URLUserInfo usrInfo = continuumUrlValidator.extractURLUserInfo(
+            "https://username:password@svn.apache.org/repos/asf/continuum/trunk/pom.xml" );
         assertEquals( "username", usrInfo.getUsername() );
         assertEquals( "password", usrInfo.getPassword() );
     }
-    
+
     public void testExtractUserNameEmptyPwd()
         throws Exception
     {
         ContinuumUrlValidator continuumUrlValidator = new ContinuumUrlValidator();
-        URLUserInfo usrInfo = continuumUrlValidator
-            .extractURLUserInfo( "https://username@svn.apache.org/repos/asf/continuum/trunk/pom.xml" );
+        URLUserInfo usrInfo = continuumUrlValidator.extractURLUserInfo(
+            "https://username@svn.apache.org/repos/asf/continuum/trunk/pom.xml" );
         assertEquals( "username", usrInfo.getUsername() );
         assertNull( usrInfo.getPassword() );
     }
-    
+
     public void testExtractEmptyUserNameEmptyPwd()
         throws Exception
     {
         ContinuumUrlValidator continuumUrlValidator = new ContinuumUrlValidator();
-        URLUserInfo usrInfo = continuumUrlValidator
-            .extractURLUserInfo( "https://svn.apache.org/repos/asf/continuum/trunk/pom.xml" );
+        URLUserInfo usrInfo = continuumUrlValidator.extractURLUserInfo(
+            "https://svn.apache.org/repos/asf/continuum/trunk/pom.xml" );
         assertNull( usrInfo.getUsername() );
         assertNull( usrInfo.getPassword() );
-    }     
+    }
 }
diff --git a/continuum-commons/src/test/java/org/apache/maven/continuum/utils/DefaultWorkingDirectoryServiceTest.java b/continuum-commons/src/test/java/org/apache/maven/continuum/utils/DefaultWorkingDirectoryServiceTest.java
new file mode 100644
index 0000000..a08653f
--- /dev/null
+++ b/continuum-commons/src/test/java/org/apache/maven/continuum/utils/DefaultWorkingDirectoryServiceTest.java
@@ -0,0 +1,177 @@
+package org.apache.maven.continuum.utils;
+
+/*
+ * 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 org.apache.maven.continuum.configuration.ConfigurationService;
+import org.apache.maven.continuum.model.project.Project;
+import org.codehaus.plexus.spring.PlexusInSpringTestCase;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.integration.junit3.JUnit3Mockery;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ */
+public class DefaultWorkingDirectoryServiceTest
+    extends PlexusInSpringTestCase
+{
+    private DefaultWorkingDirectoryService workingDirectoryService;
+
+    private Mockery context;
+
+    private ConfigurationService configurationService;
+
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        context = new JUnit3Mockery();
+
+        configurationService = context.mock( ConfigurationService.class );
+
+        workingDirectoryService = (DefaultWorkingDirectoryService) lookup( WorkingDirectoryService.class );
+
+        workingDirectoryService.setConfigurationService( configurationService );
+    }
+
+    private Project createProject( int id, String groupId, String artifactId, String version, String scmUrl,
+                                   boolean checkedOutInSingleDirectory )
+    {
+        Project project = new Project();
+        project.setId( id );
+        project.setGroupId( groupId );
+        project.setArtifactId( artifactId );
+        project.setVersion( version );
+        project.setScmUrl( scmUrl );
+        project.setCheckedOutInSingleDirectory( checkedOutInSingleDirectory );
+
+        return project;
+    }
+
+    public void testGetWorkingDirectoryOfSingleCheckoutFlatMultiModules()
+        throws Exception
+    {
+        List<Project> projects = new ArrayList<Project>();
+
+        Project project = createProject( 7, "org.apache.continuum", "module-a", "1.0-SNAPSHOT",
+                                         "scm:local:src/test-projects:flat-multi-module/module-a", true );
+
+        projects.add( project );
+
+        projects.add( createProject( 8, "org.apache.continuum", "module-b", "1.0-SNAPSHOT",
+                                     "scm:local:src/test-projects:flat-multi-module/module-b", true ) );
+
+        projects.add( createProject( 6, "org.apache.continuum", "parent-project", "1.0-SNAPSHOT",
+                                     "scm:local:src/test-projects:flat-multi-module/parent-project", true ) );
+
+        final File baseWorkingDirectory = new File( getBasedir(), "target" + File.separatorChar + "working-directory" );
+
+        context.checking( new Expectations()
+        {
+            {
+                exactly( 2 ).of( configurationService ).getWorkingDirectory();
+                will( returnValue( baseWorkingDirectory ) );
+            }
+        } );
+
+        File projectWorkingDirectory = workingDirectoryService.getWorkingDirectory( project,
+                                                                                    "scm:local:src/test-projects:flat-multi-module",
+                                                                                    projects );
+
+        assertEquals( "Incorrect working directory for flat multi-module project", baseWorkingDirectory +
+            File.separator + "6" + File.separator + "module-a", projectWorkingDirectory.getPath() );
+
+        // test if separator is appended at the end of the scm root url
+        projectWorkingDirectory = workingDirectoryService.getWorkingDirectory( project,
+                                                                               "scm:local:src/test-projects:flat-multi-module/",
+                                                                               projects );
+
+        assertEquals( "Incorrect working directory for flat multi-module project", baseWorkingDirectory +
+            File.separator + "6" + File.separator + "module-a", projectWorkingDirectory.getPath() );
+    }
+
+    public void testGetWorkingDirectoryOfSingleCheckoutRegularMultiModules()
+        throws Exception
+    {
+        List<Project> projects = new ArrayList<Project>();
+
+        Project project = createProject( 10, "org.apache.continuum", "module-a", "1.0-SNAPSHOT",
+                                         "scm:local:src/test-projects:regular-multi-module/module-a", true );
+
+        projects.add( project );
+
+        projects.add( createProject( 11, "org.apache.continuum", "module-b", "1.0-SNAPSHOT",
+                                     "scm:local:src/test-projects:regular-multi-module/module-b", true ) );
+
+        projects.add( createProject( 9, "org.apache.continuum", "parent-project", "1.0-SNAPSHOT",
+                                     "scm:local:src/test-projects:regular-multi-module/", true ) );
+
+        final File baseWorkingDirectory = new File( getBasedir(), "target" + File.separator + "working-directory" );
+
+        context.checking( new Expectations()
+        {
+            {
+                exactly( 2 ).of( configurationService ).getWorkingDirectory();
+                will( returnValue( baseWorkingDirectory ) );
+            }
+        } );
+
+        File projectWorkingDirectory = workingDirectoryService.getWorkingDirectory( project,
+                                                                                    "scm:local:src/test-projects:regular-multi-module",
+                                                                                    projects );
+
+        assertEquals( "Incorrect working directory for regular multi-module project",
+                      baseWorkingDirectory + File.separator +
+                          "9" + File.separator + "module-a", projectWorkingDirectory.getPath() );
+
+        // test if separator is appended at the end of the scm root url
+        projectWorkingDirectory = workingDirectoryService.getWorkingDirectory( project,
+                                                                               "scm:local:src/test-projects:regular-multi-module/",
+                                                                               projects );
+
+        assertEquals( "Incorrect working directory for regular multi-module project",
+                      baseWorkingDirectory + File.separator +
+                          "9" + File.separator + "module-a", projectWorkingDirectory.getPath() );
+
+        // test generated path of parent project
+        project = createProject( 9, "org.apache.continuum", "parent-project", "1.0-SNAPSHOT",
+                                 "scm:local:src/test-projects:regular-multi-module", true );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( configurationService ).getWorkingDirectory();
+                will( returnValue( baseWorkingDirectory ) );
+            }
+        } );
+
+        projectWorkingDirectory = workingDirectoryService.getWorkingDirectory( project,
+                                                                               "scm:local:src/test-projects:regular-multi-module",
+                                                                               projects );
+
+        assertEquals( "Incorrect working directory for regular multi-module project", baseWorkingDirectory +
+            File.separator + "9", projectWorkingDirectory.getPath() );
+    }
+}
\ No newline at end of file
diff --git a/continuum-commons/src/test/resources/META-INF/continuum/continuum-configuration.xml b/continuum-commons/src/test/resources/META-INF/continuum/continuum-configuration.xml
index d273425..7168804 100644
--- a/continuum-commons/src/test/resources/META-INF/continuum/continuum-configuration.xml
+++ b/continuum-commons/src/test/resources/META-INF/continuum/continuum-configuration.xml
@@ -21,9 +21,9 @@
 
 <configuration>
   <system/>
-  <jndi prefix="java:comp/env" config-optional="true"/>  
+  <jndi prefix="java:comp/env" config-optional="true"/>
   <xml fileName="${appserver.base}/conf/continuum.xml" config-optional="true"
        config-forceCreate="true" config-name="org.apache.continuum"/>
   <xml fileName="${user.home}/.m2/continuum.xml" config-optional="true"
-       config-forceCreate="true" config-name="org.apache.continuum.user"/>  
+       config-forceCreate="true" config-name="org.apache.continuum.user"/>
 </configuration>
diff --git a/continuum-commons/src/test/resources/conf/continuum.xml b/continuum-commons/src/test/resources/conf/continuum.xml
index 6012086..699a1d9 100644
--- a/continuum-commons/src/test/resources/conf/continuum.xml
+++ b/continuum-commons/src/test/resources/conf/continuum.xml
@@ -1,4 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
 <continuum-configuration>
   <baseUrl>http://test</baseUrl>
   <buildOutputDirectory>target/myBuildOutputDir</buildOutputDirectory>
@@ -9,5 +28,4 @@
       <enabled>true</enabled>
     </buildAgent>
   </buildAgents>
-  <distributedBuildEnabled>true</distributedBuildEnabled>
 </continuum-configuration>
\ No newline at end of file
diff --git a/continuum-commons/src/test/resources/log4j.xml b/continuum-commons/src/test/resources/log4j.xml
deleted file mode 100644
index 8dc69e9..0000000
--- a/continuum-commons/src/test/resources/log4j.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
-<!-- ===================================================================== -->
-<!-- Log4j Configuration -->
-<!-- ===================================================================== -->
-
-<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
-  debug="false">
-
-  <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
-    <param name="Target" value="System.out"/>
-    <layout class="org.apache.log4j.PatternLayout">
-      <param name="ConversionPattern" value="%d %-5p [%c{1}.%M](%L) %m%n"/>
-    </layout>
-  </appender>
-
-  <!-- quiet spring loading :-) -->
-  <category name="org.springframework">
-    <priority value="ERROR"/>
-  </category>
-  <category name="org.codehaus.plexus">
-    <priority value="ERROR"/>
-  </category>
-  <category name="org.apache.continuum.configuration">
-    <priority value="DEBUG"/>
-  </category>
-
-  <category name="org.apache.commons.configuration">
-    <priority value="ERROR"/>
-  </category>
-
-  <!-- JPOX -->
-  <category name="JPOX">
-    <priority value="WARN"/>
-  </category>
-  <category name="JPOX.RDBMS">
-    <priority value="ERROR"/>
-  </category>
-
-  <root>
-    <priority value="INFO"/>
-    <appender-ref ref="CONSOLE"/>
-  </root>
-
-</log4j:configuration>
diff --git a/continuum-commons/src/test/resources/org/apache/maven/continuum/configuration/ConfigurationServiceTest.xml b/continuum-commons/src/test/resources/org/apache/maven/continuum/configuration/ConfigurationServiceTest.xml
deleted file mode 100644
index 935aa70..0000000
--- a/continuum-commons/src/test/resources/org/apache/maven/continuum/configuration/ConfigurationServiceTest.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<plexus/>
\ No newline at end of file
diff --git a/continuum-commons/src/test/resources/org/apache/maven/continuum/utils/ContinuumUrlValidatorTest.xml b/continuum-commons/src/test/resources/org/apache/maven/continuum/utils/ContinuumUrlValidatorTest.xml
index 0ec53aa..51c99ca 100644
--- a/continuum-commons/src/test/resources/org/apache/maven/continuum/utils/ContinuumUrlValidatorTest.xml
+++ b/continuum-commons/src/test/resources/org/apache/maven/continuum/utils/ContinuumUrlValidatorTest.xml
@@ -43,7 +43,7 @@
         </allowedSchemes>
       </configuration>
     </component>
-    
-    
+
+
   </components>
 </plexus>
diff --git a/continuum-core/design.apt b/continuum-core/design.apt
index 8424789..804e76d 100644
--- a/continuum-core/design.apt
+++ b/continuum-core/design.apt
@@ -1,6 +1,23 @@
 Sequences
 ---------
 
+~~ 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.
+
 -------------------------------------------------------------
 Adding project
 -------------------------------------------------------------
@@ -33,4 +50,4 @@
 
 build contains a result, but there would be many results ...
 
-Build <>---- BuildResult
\ No newline at end of file
+Build <>---- BuildResult
diff --git a/continuum-core/pom.xml b/continuum-core/pom.xml
index 1e6b226..cceb46e 100644
--- a/continuum-core/pom.xml
+++ b/continuum-core/pom.xml
@@ -1,33 +1,43 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
+  ~ 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.
+  -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <parent>  
+  <parent>
     <artifactId>continuum</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>continuum-core</artifactId>
   <name>Continuum :: Core</name>
   <dependencies>
     <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-simple</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-quartz</artifactId>
     </dependency>
@@ -46,7 +56,7 @@
     <dependency>
       <groupId>org.apache.continuum</groupId>
       <artifactId>continuum-reports</artifactId>
-    </dependency>    
+    </dependency>
     <dependency>
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-model</artifactId>
@@ -54,7 +64,7 @@
     <dependency>
       <groupId>org.apache.maven.shared</groupId>
       <artifactId>file-management</artifactId>
-    </dependency>    
+    </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-velocity</artifactId>
@@ -70,56 +80,44 @@
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-command-line</artifactId>
-      <version>1.0-alpha-2</version>
-      <exclusions>
-        <exclusion>
-          <groupId>org.codehaus.plexus</groupId>
-          <artifactId>plexus-container-default</artifactId>
-        </exclusion>
-      </exclusions>
     </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-component-api</artifactId>
-    </dependency>    
+    </dependency>
     <dependency>
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-artifact</artifactId>
     </dependency>
+    <!-- start - order matters, requires maven 2.0.9+ -->
     <dependency>
-      <groupId>org.apache.maven.wagon</groupId>
-      <artifactId>wagon-provider-api</artifactId>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-artifact-manager</artifactId>
     </dependency>
     <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-artifact-manager</artifactId>
+    </dependency>
+    <!-- end - order matters -->
+    <dependency>
       <groupId>org.apache.maven.scm</groupId>
       <artifactId>maven-scm-api</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.maven</groupId>
-      <artifactId>maven-project</artifactId> 
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven</groupId>
-      <artifactId>maven-core</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-jdo2</artifactId>
+      <artifactId>maven-project</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.httpcomponents</groupId>
       <artifactId>httpclient</artifactId>
-    </dependency>    
+    </dependency>
+    <dependency>
+      <groupId>org.apache.httpcomponents</groupId>
+      <artifactId>httpcore</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-action</artifactId>
-      <version>1.0-alpha-6</version>
-      <exclusions>
-        <exclusion>
-          <groupId>org.codehaus.plexus</groupId>
-          <artifactId>plexus-container-default</artifactId>
-        </exclusion>
-      </exclusions>
     </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
@@ -130,8 +128,28 @@
       <artifactId>jpox</artifactId>
     </dependency>
     <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>backport-util-concurrent</groupId>
+      <artifactId>backport-util-concurrent</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>quartz</groupId>
+      <artifactId>quartz</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>javax.annotation</groupId>
+      <artifactId>jsr250-api</artifactId>
+    </dependency>
+    <dependency>
       <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-store</artifactId>
+      <artifactId>continuum-model</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.continuum</groupId>
@@ -139,10 +157,6 @@
     </dependency>
     <dependency>
       <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-security</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
       <artifactId>continuum-scm</artifactId>
     </dependency>
     <dependency>
@@ -154,31 +168,62 @@
       <artifactId>continuum-purge</artifactId>
     </dependency>
     <dependency>
-      <groupId>org.apache.archiva</groupId>
-      <artifactId>archiva-common</artifactId>
-      <version>${archiva.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.archiva</groupId>
-      <artifactId>archiva-repository-layer</artifactId>
-      <version>${archiva.version}</version>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-context-support</artifactId>
     </dependency>
     <dependency>
       <groupId>org.springframework</groupId>
-      <artifactId>spring-context-support</artifactId>
-    </dependency>    
+      <artifactId>spring-context</artifactId>
+    </dependency>
     <dependency>
-      <groupId>javax.mail</groupId>
-      <artifactId>mail</artifactId>
-      <version>1.4</version>
-      <scope>provided</scope>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-beans</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.continuum</groupId>
       <artifactId>continuum-builder</artifactId>
-    </dependency>    
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-distributed-slave-client</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>velocity</groupId>
+      <artifactId>velocity</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.release</groupId>
+      <artifactId>maven-release-manager</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>javax.mail</groupId>
+      <artifactId>mail</artifactId>
+    </dependency>
+    <!-- contains redback-core.xml that is needed to instantiate some test classes -->
+    <dependency>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>redback-struts2-integration</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <!-- contains redback.xml that is needed to pass some test classes -->
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-security</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <!-- A test that goes way too deep into the stack requires this -->
+    <dependency>
+      <groupId>org.apache.maven.wagon</groupId>
+      <artifactId>wagon-http-lightweight</artifactId>
+      <scope>test</scope>
+    </dependency>
     <!-- === Testing Dependencies === -->
     <dependency>
+      <groupId>org.hamcrest</groupId>
+      <artifactId>hamcrest-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
       <groupId>hsqldb</groupId>
       <artifactId>hsqldb</artifactId>
       <scope>test</scope>
@@ -189,15 +234,6 @@
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-security</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-configuration</artifactId>
-    </dependency>
-    <dependency>
       <groupId>org.apache.maven.scm</groupId>
       <artifactId>maven-scm-provider-local</artifactId>
       <scope>test</scope>
@@ -208,45 +244,35 @@
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>xml-apis</groupId>
-      <artifactId>xml-apis</artifactId>
-      <version>1.0.b2</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>xerces</groupId>
-      <artifactId>xercesImpl</artifactId>
-      <version>2.6.2</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.codehaus.redback</groupId>
-      <artifactId>redback-struts2-integration</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
       <groupId>org.codehaus.redback</groupId>
       <artifactId>redback-rbac-memory</artifactId>
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-slf4j-logging</artifactId>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>plexus-spring</artifactId>
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-spring</artifactId>
+      <groupId>org.jmock</groupId>
+      <artifactId>jmock-junit3</artifactId>
       <scope>test</scope>
-    </dependency>  
+    </dependency>
+    <!-- dependency of jmock3 -->
     <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-log4j12</artifactId>
+      <groupId>cglib</groupId>
+      <artifactId>cglib-nodep</artifactId>
       <scope>test</scope>
-    </dependency>  
+    </dependency>
+    <!-- dependency of jmock3 -->
     <dependency>
-      <groupId>commons-collections</groupId>
-      <artifactId>commons-collections</artifactId>
+      <groupId>org.objenesis</groupId>
+      <artifactId>objenesis</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jmock</groupId>
+      <artifactId>jmock</artifactId>
       <scope>test</scope>
     </dependency>
     <dependency>
@@ -255,8 +281,9 @@
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>org.jmock</groupId>
-      <artifactId>jmock-junit3</artifactId>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-server</artifactId>
+      <version>${jetty.version}</version>
       <scope>test</scope>
     </dependency>
   </dependencies>
@@ -268,20 +295,21 @@
         <executions>
           <execution>
             <id>generate</id>
+            <phase>generate-resources</phase>
             <goals>
               <goal>descriptor</goal>
             </goals>
           </execution>
           <execution>
             <id>merge</id>
-            <!--
+            <phase>process-resources</phase>
             <configuration>
               <descriptors>
-                <descriptor>${basedir}/src/main/resources/META-INF/plexus/components.xml</descriptor>
-                <descriptor>${project.build.directory}/generated-resources/plexus/META-INF/plexus/components.xml</descriptor>
+                <descriptor>${basedir}/src/main/resources/META-INF/plexus/components-fragment.xml</descriptor>
+                <descriptor>${project.build.outputDirectory}/META-INF/plexus/components.xml</descriptor>
               </descriptors>
+              <output>${project.build.outputDirectory}/META-INF/plexus/components.xml</output>
             </configuration>
-            -->
             <goals>
               <goal>merge-descriptors</goal>
             </goals>
@@ -291,28 +319,65 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-surefire-plugin</artifactId>
-        <configuration>
-          <excludes>
-            <!-- this test only test cancelling Taskqueue implementation from plexus-task -->
-            <exclude>**/BuildProjectTaskExecutorTest.*</exclude>
-          </excludes>
-        </configuration>        
+        <executions>
+          <execution>
+            <id>default-test</id>
+            <configuration>
+              <excludes>
+                <!-- this test only test cancelling Taskqueue implementation from plexus-task -->
+                <exclude>**/BuildProjectTaskExecutorTest.*</exclude>
+                <!-- CONTINUUM-2559 -->
+                <exclude>**/MailContinuumNotifierTest.*</exclude>
+                <!-- Requires low memory for meaningful result -->
+                <exclude>**/CleanWorkingDirectoryActionTest.*</exclude>
+              </excludes>
+            </configuration>
+          </execution>
+        </executions>
       </plugin>
     </plugins>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.rat</groupId>
+          <artifactId>apache-rat-plugin</artifactId>
+          <configuration>
+            <excludes combine.children="append">
+              <exclude>src/test-projects/**</exclude>
+            </excludes>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
   </build>
   <profiles>
     <profile>
-      <id>it</id>
+      <id>lowmem-test</id>
+      <activation>
+        <os>
+          <family>unix</family>
+        </os>
+      </activation>
       <build>
         <plugins>
-          <plugin>
-            <groupId>org.apache.maven.plugins</groupId>
-            <artifactId>maven-surefire-plugin</artifactId>
-            <configuration>
-              <argLine>-Xmx512m</argLine>
-              <childDelegation>true</childDelegation>
-            </configuration>
-          </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>lowmem-test</id>
+                        <goals>
+                            <goal>test</goal>
+                        </goals>
+                        <configuration>
+                            <argLine>-Xmx2m -Xms2m</argLine>
+                            <includes>
+                                <include>**/CleanWorkingDirectoryActionTest.*</include>
+                            </includes>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
         </plugins>
       </build>
     </profile>
diff --git a/continuum-core/src/main/java/org/apache/continuum/builder/distributed/DefaultDistributedBuildService.java b/continuum-core/src/main/java/org/apache/continuum/builder/distributed/DefaultDistributedBuildService.java
new file mode 100644
index 0000000..b2024d4
--- /dev/null
+++ b/continuum-core/src/main/java/org/apache/continuum/builder/distributed/DefaultDistributedBuildService.java
@@ -0,0 +1,800 @@
+package org.apache.continuum.builder.distributed;
+
+/*
+ * 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 org.apache.continuum.builder.distributed.manager.DistributedBuildManager;
+import org.apache.continuum.builder.distributed.util.DistributedBuildUtil;
+import org.apache.continuum.builder.utils.ContinuumBuildConstant;
+import org.apache.continuum.dao.BuildDefinitionDao;
+import org.apache.continuum.dao.BuildResultDao;
+import org.apache.continuum.dao.ProjectDao;
+import org.apache.continuum.dao.ProjectScmRootDao;
+import org.apache.continuum.model.project.ProjectScmRoot;
+import org.apache.maven.continuum.ContinuumException;
+import org.apache.maven.continuum.configuration.ConfigurationException;
+import org.apache.maven.continuum.configuration.ConfigurationService;
+import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
+import org.apache.maven.continuum.installation.InstallationService;
+import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.BuildResult;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.project.ProjectDependency;
+import org.apache.maven.continuum.model.project.ProjectDeveloper;
+import org.apache.maven.continuum.model.project.ProjectNotifier;
+import org.apache.maven.continuum.model.scm.ChangeFile;
+import org.apache.maven.continuum.model.scm.ChangeSet;
+import org.apache.maven.continuum.model.system.Installation;
+import org.apache.maven.continuum.model.system.Profile;
+import org.apache.maven.continuum.notification.ContinuumNotificationDispatcher;
+import org.apache.maven.continuum.project.ContinuumProjectState;
+import org.apache.maven.continuum.store.ContinuumStoreException;
+import org.codehaus.plexus.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @plexus.component role="org.apache.continuum.builder.distributed.DistributedBuildService"
+ */
+public class DefaultDistributedBuildService
+    implements DistributedBuildService
+{
+    private static final Logger log = LoggerFactory.getLogger( DefaultDistributedBuildService.class );
+
+    /**
+     * @plexus.requirement
+     */
+    private ProjectDao projectDao;
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildDefinitionDao buildDefinitionDao;
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildResultDao buildResultDao;
+
+    /**
+     * @plexus.requirement
+     */
+    private ProjectScmRootDao projectScmRootDao;
+
+    /**
+     * @plexus.requirement
+     */
+    private ConfigurationService configurationService;
+
+    /**
+     * @plexus.requirement
+     */
+    private InstallationService installationService;
+
+    /**
+     * @plexus.requirement
+     */
+    private ContinuumNotificationDispatcher notifierDispatcher;
+
+    /**
+     * @plexus.requirement
+     */
+    private DistributedBuildUtil distributedBuildUtil;
+
+    /**
+     * @plexus.requirement
+     */
+    private DistributedBuildManager distributedBuildManager;
+
+    public void updateBuildResult( Map<String, Object> context )
+        throws ContinuumException
+    {
+        try
+        {
+            int projectId = ContinuumBuildConstant.getProjectId( context );
+            int buildDefinitionId = ContinuumBuildConstant.getBuildDefinitionId( context );
+
+            log.info( "update build result of project '" + projectId + "'" );
+
+            Project project = projectDao.getProjectWithAllDetails( projectId );
+            BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
+
+            BuildResult oldBuildResult = buildResultDao.getLatestBuildResultForBuildDefinition( projectId,
+                                                                                                buildDefinitionId );
+
+            int buildNumber;
+
+            if ( ContinuumBuildConstant.getBuildState( context ) == ContinuumProjectState.OK )
+            {
+                buildNumber = project.getBuildNumber() + 1;
+            }
+            else
+            {
+                buildNumber = project.getBuildNumber();
+            }
+
+            // ----------------------------------------------------------------------
+            // Make the buildResult
+            // ----------------------------------------------------------------------
+
+            BuildResult buildResult = distributedBuildUtil.convertMapToBuildResult( context );
+
+            if ( buildResult.getState() != ContinuumProjectState.CANCELLED )
+            {
+                buildResult.setBuildDefinition( buildDefinition );
+                buildResult.setBuildNumber( buildNumber );
+                buildResult.setModifiedDependencies( distributedBuildUtil.getModifiedDependencies( oldBuildResult,
+                                                                                                   context ) );
+                buildResult.setScmResult( distributedBuildUtil.getScmResult( context ) );
+
+                Date date = ContinuumBuildConstant.getLatestUpdateDate( context );
+                if ( date != null )
+                {
+                    buildResult.setLastChangedDate( date.getTime() );
+                }
+                else if ( oldBuildResult != null )
+                {
+                    buildResult.setLastChangedDate( oldBuildResult.getLastChangedDate() );
+                }
+
+                buildResultDao.addBuildResult( project, buildResult );
+
+                buildResult = buildResultDao.getBuildResult( buildResult.getId() );
+
+                project.setOldState( project.getState() );
+                project.setState( ContinuumBuildConstant.getBuildState( context ) );
+                project.setBuildNumber( buildNumber );
+                project.setLatestBuildId( buildResult.getId() );
+            }
+            else
+            {
+                project.setState( project.getOldState() );
+                project.setOldState( 0 );
+            }
+
+            projectDao.updateProject( project );
+
+            File buildOutputFile = configurationService.getBuildOutputFile( buildResult.getId(), project.getId() );
+
+            FileWriter fstream = new FileWriter( buildOutputFile );
+            BufferedWriter out = new BufferedWriter( fstream );
+            out.write( ContinuumBuildConstant.getBuildOutput( context ) == null
+                           ? ""
+                           : ContinuumBuildConstant.getBuildOutput( context ) );
+            out.close();
+
+            if ( buildResult.getState() != ContinuumProjectState.CANCELLED )
+            {
+                notifierDispatcher.buildComplete( project, buildDefinition, buildResult );
+            }
+
+            distributedBuildManager.removeCurrentRun( projectId, buildDefinitionId );
+        }
+        catch ( ContinuumStoreException e )
+        {
+            throw new ContinuumException( "Error while updating build result for project", e );
+        }
+        catch ( ConfigurationException e )
+        {
+            throw new ContinuumException( "Error retrieving build output file", e );
+        }
+        catch ( IOException e )
+        {
+            throw new ContinuumException( "Error while writing build output to file", e );
+        }
+    }
+
+    public void prepareBuildFinished( Map<String, Object> context )
+        throws ContinuumException
+    {
+        int projectGroupId = ContinuumBuildConstant.getProjectGroupId( context );
+        String scmRootAddress = ContinuumBuildConstant.getScmRootAddress( context );
+
+        try
+        {
+            ProjectScmRoot scmRoot = projectScmRootDao.getProjectScmRootByProjectGroupAndScmRootAddress( projectGroupId,
+                                                                                                         scmRootAddress );
+
+            String error = ContinuumBuildConstant.getScmError( context );
+
+            if ( StringUtils.isEmpty( error ) )
+            {
+                scmRoot.setState( ContinuumProjectState.UPDATED );
+            }
+            else
+            {
+                scmRoot.setState( ContinuumProjectState.ERROR );
+                scmRoot.setError( error );
+            }
+
+            projectScmRootDao.updateProjectScmRoot( scmRoot );
+
+            notifierDispatcher.prepareBuildComplete( scmRoot );
+        }
+        catch ( ContinuumStoreException e )
+        {
+            throw new ContinuumException( "Error while updating project scm root '" + scmRootAddress + "'", e );
+        }
+    }
+
+    public void startProjectBuild( int projectId )
+        throws ContinuumException
+    {
+        try
+        {
+            Project project = projectDao.getProject( projectId );
+            project.setOldState( project.getState() );
+            project.setState( ContinuumProjectState.BUILDING );
+            projectDao.updateProject( project );
+        }
+        catch ( ContinuumStoreException e )
+        {
+            log.error( "Error while updating project's state (projectId=" + projectId + ")", e );
+            throw new ContinuumException( "Error while updating project's state (projectId=" + projectId + ")", e );
+        }
+    }
+
+    public void startPrepareBuild( Map<String, Object> context )
+        throws ContinuumException
+    {
+        int projectGroupId = ContinuumBuildConstant.getProjectGroupId( context );
+
+        try
+        {
+            String scmRootAddress = ContinuumBuildConstant.getScmRootAddress( context );
+
+            ProjectScmRoot scmRoot = projectScmRootDao.getProjectScmRootByProjectGroupAndScmRootAddress( projectGroupId,
+                                                                                                         scmRootAddress );
+            scmRoot.setOldState( scmRoot.getState() );
+            scmRoot.setState( ContinuumProjectState.UPDATING );
+            projectScmRootDao.updateProjectScmRoot( scmRoot );
+        }
+        catch ( ContinuumStoreException e )
+        {
+            log.error( "Error while updating project group'" + projectGroupId + "' scm root's state", e );
+            throw new ContinuumException( "Error while updating project group'" + projectGroupId + "' scm root's state",
+                                          e );
+        }
+    }
+
+    public Map<String, String> getEnvironments( int buildDefinitionId, String installationType )
+        throws ContinuumException
+    {
+        BuildDefinition buildDefinition;
+
+        try
+        {
+            buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
+        }
+        catch ( ContinuumStoreException e )
+        {
+            throw new ContinuumException( "Failed to retrieve build definition: " + buildDefinitionId, e );
+        }
+
+        Profile profile = buildDefinition.getProfile();
+        if ( profile == null )
+        {
+            return Collections.EMPTY_MAP;
+        }
+        Map<String, String> envVars = new HashMap<String, String>();
+        String javaHome = getJavaHomeValue( buildDefinition );
+        if ( !StringUtils.isEmpty( javaHome ) )
+        {
+            envVars.put( installationService.getEnvVar( InstallationService.JDK_TYPE ), javaHome );
+        }
+        Installation builder = profile.getBuilder();
+        if ( builder != null )
+        {
+            envVars.put( installationService.getEnvVar( installationType ), builder.getVarValue() );
+        }
+        envVars.putAll( getEnvironmentVariables( buildDefinition ) );
+        return envVars;
+    }
+
+    public void updateProject( Map<String, Object> context )
+        throws ContinuumException
+    {
+        try
+        {
+            Project project = projectDao.getProjectWithAllDetails( ContinuumBuildConstant.getProjectId( context ) );
+
+            if ( StringUtils.isNotBlank( ContinuumBuildConstant.getGroupId( context ) ) )
+            {
+                project.setGroupId( ContinuumBuildConstant.getGroupId( context ) );
+            }
+            if ( StringUtils.isNotBlank( ContinuumBuildConstant.getArtifactId( context ) ) )
+            {
+                project.setArtifactId( ContinuumBuildConstant.getArtifactId( context ) );
+            }
+            if ( StringUtils.isNotBlank( ContinuumBuildConstant.getVersion( context ) ) )
+            {
+                project.setVersion( ContinuumBuildConstant.getVersion( context ) );
+            }
+            if ( StringUtils.isNotBlank( ContinuumBuildConstant.getProjectName( context ) ) )
+            {
+                project.setName( ContinuumBuildConstant.getProjectName( context ) );
+            }
+            if ( StringUtils.isNotBlank( ContinuumBuildConstant.getProjectDescription( context ) ) )
+            {
+                project.setDescription( ContinuumBuildConstant.getProjectDescription( context ) );
+            }
+            if ( StringUtils.isNotBlank( ContinuumBuildConstant.getProjectUrl( context ) ) )
+            {
+                project.setUrl( ContinuumBuildConstant.getProjectUrl( context ) );
+            }
+            if ( StringUtils.isNotBlank( ContinuumBuildConstant.getScmUrl( context ) ) )
+            {
+                project.setScmUrl( ContinuumBuildConstant.getScmUrl( context ) );
+            }
+            if ( StringUtils.isNotBlank( ContinuumBuildConstant.getScmTag( context ) ) )
+            {
+                project.setScmTag( ContinuumBuildConstant.getScmTag( context ) );
+            }
+            project.setParent( getProjectParent( context ) );
+            project.setDependencies( getProjectDependencies( context ) );
+            project.setDevelopers( getProjectDevelopers( context ) );
+
+            List<ProjectNotifier> userNotifiers = new ArrayList<ProjectNotifier>();
+
+            if ( project.getNotifiers() != null )
+            {
+                for ( ProjectNotifier notifier : project.getNotifiers() )
+                {
+                    if ( notifier.isFromUser() )
+                    {
+                        ProjectNotifier userNotifier = new ProjectNotifier();
+
+                        userNotifier.setType( notifier.getType() );
+
+                        userNotifier.setEnabled( notifier.isEnabled() );
+
+                        userNotifier.setConfiguration( notifier.getConfiguration() );
+
+                        userNotifier.setFrom( notifier.getFrom() );
+
+                        userNotifier.setRecipientType( notifier.getRecipientType() );
+
+                        userNotifier.setSendOnError( notifier.isSendOnError() );
+
+                        userNotifier.setSendOnFailure( notifier.isSendOnFailure() );
+
+                        userNotifier.setSendOnSuccess( notifier.isSendOnSuccess() );
+
+                        userNotifier.setSendOnWarning( notifier.isSendOnWarning() );
+
+                        userNotifier.setSendOnScmFailure( notifier.isSendOnScmFailure() );
+
+                        userNotifiers.add( userNotifier );
+                    }
+                }
+            }
+
+            project.setNotifiers( getProjectNotifiers( context ) );
+
+            for ( ProjectNotifier userNotifier : userNotifiers )
+            {
+                project.addNotifier( userNotifier );
+            }
+
+            projectDao.updateProject( project );
+        }
+        catch ( ContinuumStoreException e )
+        {
+            throw new ContinuumException( "Unable to update project '" + ContinuumBuildConstant.getProjectId(
+                context ) +
+                                              "' from working copy", e );
+        }
+    }
+
+    public boolean shouldBuild( Map<String, Object> context )
+    {
+        int projectId = ContinuumBuildConstant.getProjectId( context );
+
+        try
+        {
+            int buildDefinitionId = ContinuumBuildConstant.getBuildDefinitionId( context );
+
+            int trigger = ContinuumBuildConstant.getTrigger( context );
+
+            Project project = projectDao.getProjectWithAllDetails( projectId );
+
+            BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
+
+            BuildResult oldBuildResult = buildResultDao.getLatestBuildResultForBuildDefinition( projectId,
+                                                                                                buildDefinitionId );
+
+            List<ProjectDependency> modifiedDependencies = distributedBuildUtil.getModifiedDependencies( oldBuildResult,
+                                                                                                         context );
+
+            List<ChangeSet> changes = distributedBuildUtil.getScmChanges( context );
+
+            if ( buildDefinition.isAlwaysBuild() )
+            {
+                log.info( "AlwaysBuild configured, building (projectId=" + projectId + ")" );
+                return true;
+            }
+            if ( oldBuildResult == null )
+            {
+                log.info(
+                    "The project '" + projectId + "' was never built with the current build definition, building" );
+                return true;
+            }
+
+            //CONTINUUM-1428
+            if ( project.getOldState() == ContinuumProjectState.ERROR ||
+                oldBuildResult.getState() == ContinuumProjectState.ERROR )
+            {
+                log.info( "Latest state was 'ERROR', building (projectId=" + projectId + ")" );
+                return true;
+            }
+
+            if ( trigger == ContinuumProjectState.TRIGGER_FORCED )
+            {
+                log.info( "The project '" + projectId + "' build is forced, building" );
+                return true;
+            }
+
+            Date date = ContinuumBuildConstant.getLatestUpdateDate( context );
+            if ( date != null && oldBuildResult.getLastChangedDate() >= date.getTime() )
+            {
+                log.info( "No changes found, not building (projectId=" + projectId + ")" );
+                return false;
+            }
+            else if ( date != null && changes.isEmpty() )
+            {
+                // fresh checkout from build agent that's why changes is empty
+                log.info( "Changes found in the current project, building (projectId=" + projectId + ")" );
+                return true;
+            }
+
+            boolean shouldBuild = false;
+
+            boolean allChangesUnknown = true;
+
+            if ( project.getOldState() != ContinuumProjectState.NEW &&
+                project.getOldState() != ContinuumProjectState.CHECKEDOUT &&
+                project.getState() != ContinuumProjectState.NEW &&
+                project.getState() != ContinuumProjectState.CHECKEDOUT )
+            {
+                // Check SCM changes
+                allChangesUnknown = checkAllChangesUnknown( changes );
+
+                if ( allChangesUnknown )
+                {
+                    if ( !changes.isEmpty() )
+                    {
+                        log.info( "The project '" + projectId +
+                                      "' was not built because all changes are unknown (maybe local modifications or ignored files not defined in your SCM tool." );
+                    }
+                    else
+                    {
+                        log.info( "The project '" + projectId +
+                                      "' was not built because no changes were detected in sources since the last build." );
+                    }
+                }
+
+                // Check dependencies changes
+                if ( modifiedDependencies != null && !modifiedDependencies.isEmpty() )
+                {
+                    log.info( "Found dependencies changes, building (projectId=" + projectId + ")" );
+                    shouldBuild = true;
+                }
+            }
+
+            // Check changes
+            if ( !shouldBuild && ( ( !allChangesUnknown && !changes.isEmpty() ) || project.getExecutorId().equals(
+                ContinuumBuildExecutorConstants.MAVEN_TWO_BUILD_EXECUTOR ) ) )
+            {
+                shouldBuild = shouldBuild( changes, buildDefinition, project, getMavenProjectVersion( context ),
+                                           getMavenProjectModules( context ) );
+            }
+
+            if ( shouldBuild )
+            {
+                log.info( "Changes found in the current project, building (projectId=" + projectId + ")" );
+            }
+            else
+            {
+                log.info( "No changes in the current project, not building (projectId=" + projectId + ")" );
+            }
+
+            return shouldBuild;
+        }
+        catch ( ContinuumStoreException e )
+        {
+            log.error( "Failed to determine if project '" + projectId + "' should build", e );
+        }
+        catch ( ContinuumException e )
+        {
+            log.error( "Failed to determine if project '" + projectId + "' should build", e );
+        }
+
+        return false;
+    }
+
+    private boolean shouldBuild( List<ChangeSet> changes, BuildDefinition buildDefinition, Project project,
+                                 String mavenProjectVersion, List<String> mavenProjectModules )
+    {
+        //Check if it's a recursive build
+        boolean isRecursive = false;
+        if ( StringUtils.isNotEmpty( buildDefinition.getArguments() ) )
+        {
+            isRecursive = buildDefinition.getArguments().indexOf( "-N" ) < 0 && buildDefinition.getArguments().indexOf(
+                "--non-recursive" ) < 0;
+        }
+
+        if ( isRecursive && changes != null && !changes.isEmpty() )
+        {
+            if ( log.isInfoEnabled() )
+            {
+                log.info( "recursive build and changes found --> building (projectId=" + project.getId() + ")" );
+            }
+            return true;
+        }
+
+        if ( !project.getVersion().equals( mavenProjectVersion ) )
+        {
+            log.info( "Found changes in project's version ( maybe project '" + project.getId() +
+                          "' was recently released ), building" );
+            return true;
+        }
+
+        if ( changes == null || changes.isEmpty() )
+        {
+            if ( log.isInfoEnabled() )
+            {
+                log.info( "Found no changes, not building (projectId=" + project.getId() + ")" );
+            }
+            return false;
+        }
+
+        //check if changes are only in sub-modules or not
+        List<ChangeFile> files = new ArrayList<ChangeFile>();
+        for ( ChangeSet changeSet : changes )
+        {
+            files.addAll( changeSet.getFiles() );
+        }
+
+        int i = 0;
+        while ( i <= files.size() - 1 )
+        {
+            ChangeFile file = files.get( i );
+            if ( log.isDebugEnabled() )
+            {
+                log.debug( "changeFile.name " + file.getName() );
+                log.debug( "check in modules " + mavenProjectModules );
+            }
+            boolean found = false;
+            if ( mavenProjectModules != null )
+            {
+                for ( String module : mavenProjectModules )
+                {
+                    if ( file.getName().indexOf( module ) >= 0 )
+                    {
+                        if ( log.isDebugEnabled() )
+                        {
+                            log.debug( "changeFile.name " + file.getName() + " removed because in a module" );
+                        }
+                        files.remove( file );
+                        found = true;
+                        break;
+                    }
+                    if ( log.isDebugEnabled() )
+                    {
+                        log.debug( "not removing file " + file.getName() + " not in module " + module );
+                    }
+                }
+            }
+            if ( !found )
+            {
+                i++;
+            }
+        }
+
+        boolean shouldBuild = !files.isEmpty();
+
+        if ( !shouldBuild )
+        {
+            log.info( "Changes are only in sub-modules (projectId=" + project.getId() + ")." );
+        }
+
+        if ( log.isDebugEnabled() )
+        {
+            log.debug( "shoulbuild = " + shouldBuild );
+        }
+
+        return shouldBuild;
+    }
+
+    private boolean checkAllChangesUnknown( List<ChangeSet> changes )
+    {
+        for ( ChangeSet changeSet : changes )
+        {
+            List<ChangeFile> changeFiles = changeSet.getFiles();
+
+            for ( ChangeFile changeFile : changeFiles )
+            {
+                if ( !"unknown".equalsIgnoreCase( changeFile.getStatus() ) )
+                {
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+
+
+    private String getJavaHomeValue( BuildDefinition buildDefinition )
+    {
+        Profile profile = buildDefinition.getProfile();
+        if ( profile == null )
+        {
+            return null;
+        }
+        Installation jdk = profile.getJdk();
+        if ( jdk == null )
+        {
+            return null;
+        }
+        return jdk.getVarValue();
+    }
+
+    private Map<String, String> getEnvironmentVariables( BuildDefinition buildDefinition )
+    {
+        Profile profile = buildDefinition.getProfile();
+        Map<String, String> envVars = new HashMap<String, String>();
+        if ( profile == null )
+        {
+            return envVars;
+        }
+        List<Installation> environmentVariables = profile.getEnvironmentVariables();
+        if ( environmentVariables.isEmpty() )
+        {
+            return envVars;
+        }
+        for ( Installation installation : environmentVariables )
+        {
+            envVars.put( installation.getVarName(), installation.getVarValue() );
+        }
+        return envVars;
+    }
+
+    private ProjectDependency getProjectParent( Map<String, Object> context )
+    {
+        Map<String, Object> map = ContinuumBuildConstant.getProjectParent( context );
+
+        if ( map != null && map.size() > 0 )
+        {
+            ProjectDependency parent = new ProjectDependency();
+            parent.setGroupId( ContinuumBuildConstant.getGroupId( map ) );
+            parent.setArtifactId( ContinuumBuildConstant.getArtifactId( map ) );
+            parent.setVersion( ContinuumBuildConstant.getVersion( map ) );
+
+            return parent;
+        }
+
+        return null;
+    }
+
+    private List<ProjectDependency> getProjectDependencies( Map<String, Object> context )
+    {
+        List<ProjectDependency> projectDependencies = new ArrayList<ProjectDependency>();
+
+        List<Map<String, Object>> dependencies = ContinuumBuildConstant.getProjectDependencies( context );
+
+        if ( dependencies != null )
+        {
+            for ( Map<String, Object> map : dependencies )
+            {
+                ProjectDependency dependency = new ProjectDependency();
+                dependency.setGroupId( ContinuumBuildConstant.getGroupId( map ) );
+                dependency.setArtifactId( ContinuumBuildConstant.getArtifactId( map ) );
+                dependency.setVersion( ContinuumBuildConstant.getVersion( map ) );
+
+                projectDependencies.add( dependency );
+            }
+        }
+        return projectDependencies;
+    }
+
+    private List<ProjectDeveloper> getProjectDevelopers( Map<String, Object> context )
+    {
+        List<ProjectDeveloper> projectDevelopers = new ArrayList<ProjectDeveloper>();
+
+        List<Map<String, Object>> developers = ContinuumBuildConstant.getProjectDevelopers( context );
+
+        if ( developers != null )
+        {
+            for ( Map<String, Object> map : developers )
+            {
+                ProjectDeveloper developer = new ProjectDeveloper();
+                developer.setName( ContinuumBuildConstant.getDeveloperName( map ) );
+                developer.setEmail( ContinuumBuildConstant.getDeveloperEmail( map ) );
+                developer.setScmId( ContinuumBuildConstant.getDeveloperScmId( map ) );
+
+                projectDevelopers.add( developer );
+            }
+        }
+        return projectDevelopers;
+    }
+
+    private List<ProjectNotifier> getProjectNotifiers( Map<String, Object> context )
+    {
+        List<ProjectNotifier> projectNotifiers = new ArrayList<ProjectNotifier>();
+
+        List<Map<String, Object>> notifiers = ContinuumBuildConstant.getProjectNotifiers( context );
+
+        if ( notifiers != null )
+        {
+            for ( Map<String, Object> map : notifiers )
+            {
+                ProjectNotifier notifier = new ProjectNotifier();
+                notifier.setConfiguration( ContinuumBuildConstant.getNotifierConfiguration( map ) );
+                notifier.setEnabled( ContinuumBuildConstant.isNotifierEnabled( map ) );
+                notifier.setFrom( ContinuumBuildConstant.getNotifierFrom( map ) );
+                notifier.setRecipientType( ContinuumBuildConstant.getNotifierRecipientType( map ) );
+                notifier.setSendOnError( ContinuumBuildConstant.isNotifierSendOnError( map ) );
+                notifier.setSendOnFailure( ContinuumBuildConstant.isNotifierSendOnFailure( map ) );
+                notifier.setSendOnScmFailure( ContinuumBuildConstant.isNotifierSendOnScmFailure( map ) );
+                notifier.setSendOnSuccess( ContinuumBuildConstant.isNotifierSendOnSuccess( map ) );
+                notifier.setSendOnWarning( ContinuumBuildConstant.isNotifierSendOnWarning( map ) );
+                notifier.setType( ContinuumBuildConstant.getNotifierType( map ) );
+
+                projectNotifiers.add( notifier );
+            }
+        }
+        return projectNotifiers;
+    }
+
+    private String getMavenProjectVersion( Map<String, Object> context )
+    {
+        Map<String, Object> map = ContinuumBuildConstant.getMavenProject( context );
+
+        if ( !map.isEmpty() )
+        {
+            return ContinuumBuildConstant.getVersion( map );
+        }
+
+        return null;
+    }
+
+    private List<String> getMavenProjectModules( Map<String, Object> context )
+    {
+        Map<String, Object> map = ContinuumBuildConstant.getMavenProject( context );
+
+        if ( !map.isEmpty() )
+        {
+            return ContinuumBuildConstant.getProjectModules( map );
+        }
+
+        return null;
+    }
+}
diff --git a/continuum-core/src/main/java/org/apache/continuum/builder/distributed/manager/DefaultDistributedBuildManager.java b/continuum-core/src/main/java/org/apache/continuum/builder/distributed/manager/DefaultDistributedBuildManager.java
index 4a41af0..39c97cf 100644
--- a/continuum-core/src/main/java/org/apache/continuum/builder/distributed/manager/DefaultDistributedBuildManager.java
+++ b/continuum-core/src/main/java/org/apache/continuum/builder/distributed/manager/DefaultDistributedBuildManager.java
@@ -19,45 +19,36 @@
  * under the License.
  */
 
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.continuum.builder.distributed.executor.DistributedBuildTaskQueueExecutor;
+import org.apache.continuum.buildagent.NoBuildAgentException;
+import org.apache.continuum.buildagent.NoBuildAgentInGroupException;
 import org.apache.continuum.builder.distributed.executor.ThreadedDistributedBuildTaskQueueExecutor;
+import org.apache.continuum.builder.distributed.util.DistributedBuildUtil;
 import org.apache.continuum.builder.utils.ContinuumBuildConstant;
 import org.apache.continuum.configuration.BuildAgentConfiguration;
+import org.apache.continuum.configuration.BuildAgentGroupConfiguration;
 import org.apache.continuum.dao.BuildDefinitionDao;
 import org.apache.continuum.dao.BuildResultDao;
 import org.apache.continuum.dao.ProjectDao;
 import org.apache.continuum.dao.ProjectScmRootDao;
 import org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportClient;
+import org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportService;
+import org.apache.continuum.model.project.ProjectRunSummary;
 import org.apache.continuum.model.project.ProjectScmRoot;
+import org.apache.continuum.taskqueue.BuildProjectTask;
+import org.apache.continuum.taskqueue.OverallDistributedBuildQueue;
 import org.apache.continuum.taskqueue.PrepareBuildProjectsTask;
 import org.apache.continuum.utils.ContinuumUtils;
+import org.apache.continuum.utils.ProjectSorter;
+import org.apache.continuum.utils.build.BuildTrigger;
 import org.apache.maven.continuum.ContinuumException;
-import org.apache.maven.continuum.configuration.ConfigurationException;
 import org.apache.maven.continuum.configuration.ConfigurationService;
-import org.apache.maven.continuum.installation.InstallationService;
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.BuildResult;
 import org.apache.maven.continuum.model.project.Project;
-import org.apache.maven.continuum.model.project.ProjectDependency;
-import org.apache.maven.continuum.model.scm.ScmResult;
 import org.apache.maven.continuum.model.system.Installation;
 import org.apache.maven.continuum.model.system.Profile;
-import org.apache.maven.continuum.notification.ContinuumNotificationDispatcher;
 import org.apache.maven.continuum.project.ContinuumProjectState;
 import org.apache.maven.continuum.store.ContinuumStoreException;
-
 import org.codehaus.plexus.PlexusConstants;
 import org.codehaus.plexus.PlexusContainer;
 import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
@@ -68,10 +59,21 @@
 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.StoppingException;
+import org.codehaus.plexus.taskqueue.Task;
+import org.codehaus.plexus.taskqueue.TaskQueueException;
 import org.codehaus.plexus.util.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 /**
  * @author Maria Catherine Tan
  * @plexus.component role="org.apache.continuum.builder.distributed.manager.DistributedBuildManager"
@@ -79,7 +81,12 @@
 public class DefaultDistributedBuildManager
     implements DistributedBuildManager, Contextualizable, Initializable
 {
-    private Logger log = LoggerFactory.getLogger( this.getClass() );
+    private static final Logger log = LoggerFactory.getLogger( DefaultDistributedBuildManager.class );
+
+    private Map<String, OverallDistributedBuildQueue> overallDistributedBuildQueues = Collections.synchronizedMap(
+        new HashMap<String, OverallDistributedBuildQueue>() );
+
+    private List<ProjectRunSummary> currentRuns = Collections.synchronizedList( new ArrayList<ProjectRunSummary>() );
 
     /**
      * @plexus.requirement
@@ -89,11 +96,6 @@
     /**
      * @plexus.requirement
      */
-    private InstallationService installationService;
-
-    /**
-     * @plexus.requirement
-     */
     private ProjectDao projectDao;
 
     /**
@@ -104,22 +106,20 @@
     /**
      * @plexus.requirement
      */
-    private ProjectScmRootDao projectScmRootDao;
-
-    /**
-     * @plexus.requirement
-     */
     private BuildResultDao buildResultDao;
 
     /**
      * @plexus.requirement
      */
-    private ContinuumNotificationDispatcher notifierDispatcher;
+    private ProjectScmRootDao projectScmRootDao;
+
+    /**
+     * @plexus.requirement
+     */
+    private DistributedBuildUtil distributedBuildUtil;
 
     private PlexusContainer container;
 
-    private Map<String, ThreadedDistributedBuildTaskQueueExecutor> taskQueueExecutors;
-
     // --------------------------------
     //  Plexus Lifecycle
     // --------------------------------
@@ -132,43 +132,52 @@
     public void initialize()
         throws InitializationException
     {
-        taskQueueExecutors = new HashMap<String, ThreadedDistributedBuildTaskQueueExecutor>();
-
         List<BuildAgentConfiguration> agents = configurationService.getBuildAgents();
 
         if ( agents != null )
         {
-            for ( BuildAgentConfiguration agent : agents )
+            synchronized ( overallDistributedBuildQueues )
             {
-                if ( agent.isEnabled() )
+                for ( BuildAgentConfiguration agent : agents )
                 {
-                    try
+                    if ( agent.isEnabled() )
                     {
-                        SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( agent.getUrl() ) );
-                        
-                        if ( client.ping() )
+                        try
                         {
-                            log.info( "agent is enabled, add TaskQueueExecutor for build agent '" + agent.getUrl() + "'" );
-                            addTaskQueueExecutor( agent.getUrl() );
+                            SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                                agent.getUrl() );
+
+                            if ( client.ping() )
+                            {
+                                log.debug( "agent is enabled, create distributed build queue for build agent '{}'",
+                                           agent.getUrl() );
+                                createDistributedBuildQueueForAgent( agent.getUrl() );
+                            }
+                            else
+                            {
+                                log.debug( "unable to ping build agent '{}'", agent.getUrl() );
+                            }
                         }
-                        else
+                        catch ( MalformedURLException e )
                         {
-                            log.info( "unable to ping build agent '" + agent.getUrl() + "'" );
+                            // do not throw exception, just log it
+                            log.error( "Invalid build agent URL {}, not creating distributed build queue",
+                                       agent.getUrl() );
+                        }
+                        catch ( ContinuumException e )
+                        {
+                            throw new InitializationException( "Error while initializing distributed build queues", e );
+                        }
+                        catch ( Exception e )
+                        {
+                            agent.setEnabled( false );
+                            log.debug( "unable to ping build agent '{}' : {}", agent.getUrl(),
+                                       ContinuumUtils.throwableToString( e ) );
                         }
                     }
-                    catch ( MalformedURLException e )
+                    else
                     {
-                        // do not throw exception, just log it
-                        log.info( "Invalid build agent URL " + agent.getUrl() + ", not creating task queue executor" );
-                    }
-                    catch ( ContinuumException e )
-                    {
-                        throw new InitializationException( "Error while initializing distributed build task queue executors", e );
-                    }
-                    catch ( Exception e )
-                    {
-                        agent.setEnabled( false );
-                        log.info( "unable to ping build agent '" + agent.getUrl() + "': " + ContinuumUtils.throwableToString( e ) );
+                        log.debug( "agent {} is disabled, not creating distributed build queue", agent.getUrl() );
                     }
                 }
             }
@@ -179,442 +188,722 @@
         throws ContinuumException
     {
         List<BuildAgentConfiguration> agents = configurationService.getBuildAgents();
-        
-        for ( BuildAgentConfiguration agent : agents )
-        {
-            if ( agent.isEnabled() && !taskQueueExecutors.containsKey( agent.getUrl() ) )
-            {
-                try
-                {
-                    SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( agent.getUrl() ) );
-                    
-                    if ( client.ping() )
-                    {
-                        log.info( "agent is enabled, add TaskQueueExecutor for build agent '" + agent.getUrl() + "'" );
-                        addTaskQueueExecutor( agent.getUrl() );
-                    }
-                    else
-                    {
-                        log.info( "unable to ping build agent '" + agent.getUrl() + "'" );
-                    }
-                }
-                catch ( MalformedURLException e )
-                {
-                    // do not throw exception, just log it
-                    log.info( "Invalid build agent URL " + agent.getUrl() + ", not creating task queue executor" );
-                }
-                catch ( Exception e )
-                {
-                    agent.setEnabled( false );
-                    log.info( "unable to ping build agent '" + agent.getUrl() + "': " + ContinuumUtils.throwableToString( e ) );
-                }
-            }
-            else if ( !agent.isEnabled() && taskQueueExecutors.containsKey( agent.getUrl() ) )
-            {
-                log.info( "agent is disabled, remove TaskQueueExecutor for build agent '" + agent.getUrl() + "'" );
-                removeAgentFromTaskQueueExecutor( agent.getUrl() );
-            }
-        }
-    }
 
-    public void removeAgentFromTaskQueueExecutor( String buildAgentUrl)
-        throws ContinuumException
-    {
-        log.info( "remove TaskQueueExecutor for build agent '" + buildAgentUrl + "'" );
-        ThreadedDistributedBuildTaskQueueExecutor executor = taskQueueExecutors.get( buildAgentUrl );
-
-        if ( executor == null )
+        if ( agents == null )
         {
             return;
         }
 
-        try
+        synchronized ( overallDistributedBuildQueues )
         {
-            executor.stop();
-            container.release( executor );
-        }
-        catch ( StoppingException e )
-        {
-            throw new ContinuumException( "Error while stopping task queue executor", e );
-        }
-        catch ( ComponentLifecycleException e )
-        {
-            throw new ContinuumException( "Error while releasing task queue executor from container", e );
-        }
-
-        taskQueueExecutors.remove( buildAgentUrl );
-    }
-
-    public boolean isBuildAgentBusy( String buildAgentUrl )
-    {
-        ThreadedDistributedBuildTaskQueueExecutor executor = taskQueueExecutors.get( buildAgentUrl );
-        
-        if ( executor != null && executor.getCurrentTask() != null )
-        {
-            log.info( "build agent '" + buildAgentUrl + "' is busy" );
-            return true;
-        }
-
-        log.info( "build agent '" + buildAgentUrl + "' is not busy" );
-        return false;
-    }
-
-    private void addTaskQueueExecutor( String url )
-        throws ContinuumException
-    {
-        try
-        {            
-            ThreadedDistributedBuildTaskQueueExecutor taskQueueExecutor = (ThreadedDistributedBuildTaskQueueExecutor) container.
-                                                                          lookup( DistributedBuildTaskQueueExecutor.class, "distributed-build-project" );
-            taskQueueExecutor.setBuildAgentUrl( url );
-            taskQueueExecutors.put( url, taskQueueExecutor );
-        }
-        catch ( ComponentLookupException e )
-        {
-            throw new ContinuumException( "Unable to lookup TaskQueueExecutor for distributed-build-project", e );
-        }
-    }
-
-    public void cancelDistributedBuild( String buildAgentUrl, int projectGroupId, String scmRootAddress )
-        throws ContinuumException
-    {
-        ThreadedDistributedBuildTaskQueueExecutor taskQueueExecutor = taskQueueExecutors.get( buildAgentUrl );
-
-        if ( taskQueueExecutor != null )
-        {
-            if ( taskQueueExecutor.getCurrentTask() != null )
+            for ( BuildAgentConfiguration agent : agents )
             {
-                if ( taskQueueExecutor.getCurrentTask() instanceof PrepareBuildProjectsTask )
+                if ( agent.isEnabled() && !overallDistributedBuildQueues.containsKey( agent.getUrl() ) )
                 {
-                    PrepareBuildProjectsTask currentTask = (PrepareBuildProjectsTask) taskQueueExecutor.getCurrentTask();
-                    
-                    if ( currentTask.getProjectGroupId() == projectGroupId && 
-                         currentTask.getScmRootAddress().equals( scmRootAddress ) )
-                    {
-                        log.info( "cancelling task for project group " + projectGroupId + 
-                                  " with scm root address " + scmRootAddress );
-                        taskQueueExecutor.cancelTask( currentTask );
+                    SlaveBuildAgentTransportService client = null;
 
+                    try
+                    {
+                        client = createSlaveBuildAgentTransportClientConnection( agent.getUrl() );
+                    }
+                    catch ( MalformedURLException e )
+                    {
+                        log.error( "Invalid build agent URL {}, not creating distributed build queue", agent.getUrl() );
+                        throw new ContinuumException( "Malformed build agent url " + agent.getUrl() );
+                    }
+                    catch ( Exception e )
+                    {
+                        agent.setEnabled( false );
+                        configurationService.updateBuildAgent( agent );
+
+                        log.error( "Error binding build agent {} service : {} ", agent.getUrl(),
+                                   ContinuumUtils.throwableToString( e ) );
+                        throw new ContinuumException( e.getMessage() );
+                    }
+
+                    boolean ping = false;
+
+                    try
+                    {
+                        ping = client.ping();
+                    }
+                    catch ( Exception e )
+                    {
+                        agent.setEnabled( false );
+                        log.error( "Unable to ping build agent '{}': {}", agent.getUrl(),
+                                   ContinuumUtils.throwableToString( e ) );
+                    }
+
+                    if ( ping )
+                    {
                         try
                         {
-                            SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
-                            client.cancelBuild();
+                            createDistributedBuildQueueForAgent( agent.getUrl() );
+                            log.debug( "Agent is enabled, create distributed build queue for build agent '{}'",
+                                       agent.getUrl() );
                         }
                         catch ( Exception e )
                         {
-                            log.error( "Error while cancelling build in build agent '" + buildAgentUrl + "'" );
-                            throw new ContinuumException( "Error while cancelling build in build agent '" + buildAgentUrl + "'", e );
+                            agent.setEnabled( false );
+                            log.error( "Unable to create distributed queue for build agent {} : {}", agent.getUrl(),
+                                       ContinuumUtils.throwableToString( e ) );
                         }
                     }
                     else
                     {
-                        log.info( "current task not for project group " + projectGroupId + 
-                                  " with scm root address " + scmRootAddress );
+                        agent.setEnabled( false );
+                        log.error( "Unable to ping build agent '{}'", agent.getUrl() );
+                    }
+
+                    configurationService.updateBuildAgent( agent );
+                }
+                else if ( !agent.isEnabled() && overallDistributedBuildQueues.containsKey( agent.getUrl() ) )
+                {
+                    log.debug( "agent is disabled, remove distributed build queue for build agent '{}'",
+                               agent.getUrl() );
+                    removeDistributedBuildQueueOfAgent( agent.getUrl() );
+                }
+            }
+        }
+    }
+
+    public void update( BuildAgentConfiguration agent )
+        throws ContinuumException
+    {
+        synchronized ( overallDistributedBuildQueues )
+        {
+            if ( agent.isEnabled() && !overallDistributedBuildQueues.containsKey( agent.getUrl() ) )
+            {
+                SlaveBuildAgentTransportService client;
+
+                try
+                {
+                    client = createSlaveBuildAgentTransportClientConnection( agent.getUrl() );
+                }
+                catch ( MalformedURLException e )
+                {
+                    log.error( "Invalid build agent URL {}, not creating distributed build queue", agent.getUrl() );
+                    throw new ContinuumException( "Malformed build agent url " + agent.getUrl() );
+                }
+                catch ( Exception e )
+                {
+                    log.error( "Error binding build agent {} service : {} ", agent.getUrl(),
+                               ContinuumUtils.throwableToString( e ) );
+                    throw new ContinuumException( e.getMessage() );
+                }
+
+                boolean ping;
+
+                try
+                {
+                    ping = client.ping();
+                }
+                catch ( Exception e )
+                {
+                    log.error( "Unable to ping build agent '{}': {}", agent.getUrl(), ContinuumUtils.throwableToString(
+                        e ) );
+                    throw new ContinuumException( "Unable to ping build agent " + agent.getUrl() );
+                }
+
+                if ( ping )
+                {
+                    try
+                    {
+                        createDistributedBuildQueueForAgent( agent.getUrl() );
+                        log.debug( "Agent is enabled, create distributed build queue for build agent '{}'",
+                                   agent.getUrl() );
+                    }
+                    catch ( Exception e )
+                    {
+                        log.error( "Unable to create distributed queue for build agent {} : {}", agent.getUrl(),
+                                   ContinuumUtils.throwableToString( e ) );
                     }
                 }
                 else
                 {
-                    log.info( "current task not a prepare build projects task, not cancelling" );
+                    log.error( "Unable to ping build agent '{}'", agent.getUrl() );
+                    throw new ContinuumException( "Unable to ping build agent " + agent.getUrl() );
+                }
+            }
+            else if ( !agent.isEnabled() && overallDistributedBuildQueues.containsKey( agent.getUrl() ) )
+            {
+                log.debug( "agent is disabled, remove distributed build queue for build agent '{}'", agent.getUrl() );
+                removeDistributedBuildQueueOfAgent( agent.getUrl() );
+            }
+        }
+    }
+
+    @SuppressWarnings( "unused" )
+    public void prepareBuildProjects( Map<Integer, Integer> projectsBuildDefinitionsMap, BuildTrigger buildTrigger,
+                                      int projectGroupId, String projectGroupName, String scmRootAddress, int scmRootId,
+                                      List<ProjectScmRoot> scmRoots )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException
+    {
+        PrepareBuildProjectsTask task = new PrepareBuildProjectsTask( projectsBuildDefinitionsMap, buildTrigger,
+                                                                      projectGroupId, projectGroupName, scmRootAddress,
+                                                                      scmRootId );
+
+        if ( buildTrigger.getTrigger() == ContinuumProjectState.TRIGGER_FORCED )
+        {
+            log.debug( "Build project (projectGroupId={}) triggered manually by {}", projectGroupId,
+                       buildTrigger.getTriggeredBy() );
+        }
+        else
+        {
+            log.debug( "Build project (projectGroupId={}) triggered by schedule {}", projectGroupId,
+                       buildTrigger.getTriggeredBy() );
+        }
+
+        if ( log.isDebugEnabled() )
+        {
+            Map<String, BuildProjectTask> buildTasks = getProjectsCurrentlyBuilding();
+
+            for ( String key : buildTasks.keySet() )
+            {
+                log.debug( "Current build of agent {} :: Project {}", key, buildTasks.get( key ).getProjectName() );
+            }
+
+            Map<String, List<BuildProjectTask>> buildQueues = getProjectsInBuildQueue();
+
+            for ( String key : buildQueues.keySet() )
+            {
+                for ( BuildProjectTask buildTask : buildQueues.get( key ) )
+                {
+                    log.debug( "Build Queue of agent {} :: Project {}", key, buildTask.getProjectName() );
+                }
+            }
+
+            Map<String, PrepareBuildProjectsTask> prepareBuildTasks = getProjectsCurrentlyPreparingBuild();
+
+            for ( String key : prepareBuildTasks.keySet() )
+            {
+                PrepareBuildProjectsTask prepareBuildTask = prepareBuildTasks.get( key );
+                log.debug( "Current prepare build of agent {} :: Project Group {} - Scm Root {}",
+                           new Object[]{key, prepareBuildTask.getProjectGroupName(),
+                               prepareBuildTask.getProjectScmRootId()} );
+            }
+
+            Map<String, List<PrepareBuildProjectsTask>> prepareBuildQueues = getProjectsInPrepareBuildQueue();
+
+            for ( String key : prepareBuildQueues.keySet() )
+            {
+                for ( PrepareBuildProjectsTask prepareBuildTask : prepareBuildQueues.get( key ) )
+                {
+                    log.debug( "Prepare Build Queue of agent {} : Project Group {} - Scm Root {}",
+                               new Object[]{key, prepareBuildTask.getProjectGroupName(),
+                                   prepareBuildTask.getProjectScmRootId()} );
+                }
+            }
+        }
+
+        log.debug( "Determining which build agent should build the project..." );
+
+        OverallDistributedBuildQueue overallDistributedBuildQueue = getOverallDistributedBuildQueueByGroup(
+            projectGroupId, scmRoots, scmRootId );
+
+        if ( overallDistributedBuildQueue == null )
+        {
+            log.debug(
+                "No projects with the same continuum group is currently building, checking if build definition has an attached build agent group" );
+
+            if ( hasBuildagentGroup( projectsBuildDefinitionsMap ) )
+            {
+                log.debug(
+                    "Build definition used has an attached build agent group, checking if there are configured build agents in the group" );
+
+                if ( !hasBuildagentInGroup( projectsBuildDefinitionsMap ) )
+                {
+                    log.warn( "No build agent configured in build agent group. Not building projects." );
+
+                    throw new NoBuildAgentInGroupException( "No build agent configured in build agent group" );
+                }
+                else
+                {
+                    // get overall distributed build queue from build agent group
+                    log.info( "Getting the least busy build agent within the build agent group" );
+                    overallDistributedBuildQueue = getOverallDistributedBuildQueueByAgentGroup(
+                        projectsBuildDefinitionsMap );
                 }
             }
             else
             {
-                log.info( "no current task in build agent '" + buildAgentUrl + "'" );
+                // project does not have build agent group
+                log.info( "Project does not have a build agent group, getting the least busy of all build agents" );
+                overallDistributedBuildQueue = getOverallDistributedBuildQueue();
+            }
+        }
+
+        if ( overallDistributedBuildQueue != null )
+        {
+            try
+            {
+                String agentUrl = overallDistributedBuildQueue.getBuildAgentUrl();
+                log.info( "Building project in the least busy agent {}", agentUrl );
+                overallDistributedBuildQueue.addToDistributedBuildQueue( task );
+                createProjectRunSummaries( task, agentUrl );
+            }
+            catch ( TaskQueueException e )
+            {
+                log.error( "Error while enqueuing prepare build task", e );
+                throw new ContinuumException( "Error occurred while enqueuing prepare build task", e );
             }
         }
         else
         {
-            log.info( "no task queue executor defined for build agent '" + buildAgentUrl + "'" );
+            log.warn(
+                "Unable to determine which build agent should build the project. No build agent configured. Not building projects." );
+
+            throw new NoBuildAgentException( "No build agent configured" );
         }
+
+        // call in case we disabled a build agent
+        reload();
     }
 
-    public void updateScmResult( Map context )
+    public void removeDistributedBuildQueueOfAgent( String buildAgentUrl )
         throws ContinuumException
     {
-        try
+        if ( overallDistributedBuildQueues.containsKey( buildAgentUrl ) )
         {
-            int projectId = ContinuumBuildConstant.getProjectId( context );
+            List<PrepareBuildProjectsTask> tasks = null;
 
-            log.info( "update scm result of project" + projectId );
-            Project project = projectDao.getProjectWithScmDetails( projectId );
-            
-            ScmResult scmResult = new ScmResult();
-            scmResult.setCommandLine( ContinuumBuildConstant.getScmCommandLine( context ) );
-            scmResult.setCommandOutput( ContinuumBuildConstant.getScmCommandOutput( context ) );
-            scmResult.setException( ContinuumBuildConstant.getScmException( context ) );
-            scmResult.setProviderMessage( ContinuumBuildConstant.getScmProviderMessage( context ) );
-            scmResult.setSuccess( ContinuumBuildConstant.isScmSuccess( context ) );
+            synchronized ( overallDistributedBuildQueues )
+            {
+                OverallDistributedBuildQueue overallDistributedBuildQueue = overallDistributedBuildQueues.get(
+                    buildAgentUrl );
 
-            project.setScmResult( scmResult );
-            projectDao.updateProject( project );
-        }
-        catch ( ContinuumStoreException e )
-        {
-            throw new ContinuumException( "Error updating project's scm result", e );
+                try
+                {
+                    if ( overallDistributedBuildQueue.getDistributedBuildTaskQueueExecutor().getCurrentTask() != null )
+                    {
+                        log.error( "Unable to remove build agent because it is currently being used" );
+                        throw new ContinuumException(
+                            "Unable to remove build agent because it is currently being used" );
+                    }
+
+                    tasks = overallDistributedBuildQueue.getProjectsInQueue();
+
+                    overallDistributedBuildQueue.getDistributedBuildQueue().removeAll( tasks );
+
+                    ( (ThreadedDistributedBuildTaskQueueExecutor) overallDistributedBuildQueue.getDistributedBuildTaskQueueExecutor() ).stop();
+
+                    container.release( overallDistributedBuildQueue );
+
+                    overallDistributedBuildQueues.remove( buildAgentUrl );
+
+                    log.debug( "remove distributed build queue for build agent '{}'", buildAgentUrl );
+                }
+                catch ( TaskQueueException e )
+                {
+                    log.error( "Error occurred while removing build agent {}", buildAgentUrl, e );
+                    throw new ContinuumException( "Error occurred while removing build agent " + buildAgentUrl, e );
+                }
+                catch ( ComponentLifecycleException e )
+                {
+                    log.error( "Error occurred while removing build agent {}", buildAgentUrl, e );
+                    throw new ContinuumException( "Error occurred while removing build agent " + buildAgentUrl, e );
+                }
+                catch ( StoppingException e )
+                {
+                    log.error( "Error occurred while removing build agent {}", buildAgentUrl, e );
+                    throw new ContinuumException( "Error occurred while removing build agent " + buildAgentUrl, e );
+                }
+            }
         }
     }
 
-    public void updateBuildResult( Map context )
+    public Map<String, List<PrepareBuildProjectsTask>> getProjectsInPrepareBuildQueue()
         throws ContinuumException
     {
-        try
+        Map<String, List<PrepareBuildProjectsTask>> map = new HashMap<String, List<PrepareBuildProjectsTask>>();
+
+        synchronized ( overallDistributedBuildQueues )
         {
-            int projectId = ContinuumBuildConstant.getProjectId( context );
-            int buildDefinitionId = ContinuumBuildConstant.getBuildDefinitionId( context );
-
-            log.info( "update build result of project '" + projectId + "'" );
-
-            Project project = projectDao.getProjectWithAllDetails( projectId );
-            BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
-
-            BuildResult oldBuildResult =
-                buildResultDao.getLatestBuildResultForBuildDefinition( projectId, buildDefinitionId );
-
-            int buildNumber;
-
-            if ( ContinuumBuildConstant.getBuildState( context ) == ContinuumProjectState.OK )
+            for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
             {
-                buildNumber = project.getBuildNumber() + 1;
-            }
-            else
-            {
-                buildNumber = project.getBuildNumber();
-            }
+                List<PrepareBuildProjectsTask> tasks = new ArrayList<PrepareBuildProjectsTask>();
 
-            // ----------------------------------------------------------------------
-            // Make the buildResult
-            // ----------------------------------------------------------------------
+                try
+                {
+                    if ( isAgentAvailable( buildAgentUrl ) )
+                    {
+                        log.debug( "Getting projects in prepare build queue of build agent {}", buildAgentUrl );
 
-            BuildResult buildResult = convertMapToBuildResult( context );
-            
-            if ( buildResult.getState() != ContinuumProjectState.CANCELLED )
-            {
-                buildResult.setBuildDefinition( buildDefinition );
-                buildResult.setBuildNumber( buildNumber );
-                buildResult.setModifiedDependencies( getModifiedDependencies( oldBuildResult, context ) );
-                
-                buildResultDao.addBuildResult( project, buildResult );
-            
-                project.setOldState( project.getState() );
-                project.setState( ContinuumBuildConstant.getBuildState( context ) );
-                project.setBuildNumber( buildNumber );
-                project.setLatestBuildId( buildResult.getId() );
-            }
-            else
-            {
-                project.setState( project.getOldState() );
-                project.setOldState( 0 );
-            }
+                        SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                            buildAgentUrl );
 
-            projectDao.updateProject( project );
+                        List<Map<String, Object>> projects = client.getProjectsInPrepareBuildQueue();
 
-            File buildOutputFile = configurationService.getBuildOutputFile( buildResult.getId(), project.getId() );
-            
-            FileWriter fstream = new FileWriter( buildOutputFile );
-            BufferedWriter out = new BufferedWriter(fstream);
-            out.write( ContinuumBuildConstant.getBuildOutput( context ) == null ? "" : ContinuumBuildConstant.getBuildOutput( context ) );
-            out.close();
+                        for ( Map<String, Object> context : projects )
+                        {
+                            tasks.add( getPrepareBuildProjectsTask( context ) );
+                        }
 
-            if ( buildResult.getState() != ContinuumProjectState.CANCELLED )
-            {
-                notifierDispatcher.buildComplete( project, buildDefinition, buildResult );
+                        map.put( buildAgentUrl, tasks );
+                    }
+                    else
+                    {
+                        log.debug( "Unable to get projects in prepare build queue. Build agent {} not available",
+                                   buildAgentUrl );
+                    }
+                }
+                catch ( MalformedURLException e )
+                {
+                    throw new ContinuumException( "Invalid build agent url: " + buildAgentUrl );
+                }
+                catch ( Exception e )
+                {
+                    throw new ContinuumException( "Error while retrieving projects in prepare build queue", e );
+                }
             }
         }
-        catch ( ContinuumStoreException e )
-        {
-            throw new ContinuumException( "Error while updating build result for project", e );
-        }
-        catch ( ConfigurationException e )
-        {
-            throw new ContinuumException( "Error retrieving build output file", e );
-        }
-        catch ( IOException e )
-        {
-            throw new ContinuumException( "Error while writing build output to file", e );
-        }
-    }
 
-    public void prepareBuildFinished( Map context )
-        throws ContinuumException
-    {
-        int projectGroupId = ContinuumBuildConstant.getProjectGroupId( context );
-        String scmRootAddress = ContinuumBuildConstant.getScmRootAddress( context );
-
-        try
-        {
-            ProjectScmRoot scmRoot = projectScmRootDao.getProjectScmRootByProjectGroupAndScmRootAddress( projectGroupId, scmRootAddress );
-            
-            String error = ContinuumBuildConstant.getScmError( context );
-            
-            if ( StringUtils.isEmpty( error ) )
-            {
-                scmRoot.setState( ContinuumProjectState.UPDATED );
-            }
-            else
-            {
-                scmRoot.setState( ContinuumProjectState.ERROR );
-                scmRoot.setError( error );
-            }
-
-            projectScmRootDao.updateProjectScmRoot( scmRoot );
-
-            notifierDispatcher.prepareBuildComplete( scmRoot );
-        }
-        catch ( ContinuumStoreException e )
-        {
-            throw new ContinuumException( "Error while updating project scm root '" + scmRootAddress + "'", e );
-        }
-    }
-
-    public Map<String, PrepareBuildProjectsTask> getDistributedBuildProjects()
-    {
-        Map<String, PrepareBuildProjectsTask> map = new HashMap<String, PrepareBuildProjectsTask>();
-
-        for ( String url : taskQueueExecutors.keySet() )
-        {
-            ThreadedDistributedBuildTaskQueueExecutor taskQueueExecutor = taskQueueExecutors.get( url );
-
-            if ( taskQueueExecutor.getCurrentTask() != null )
-            {
-                PrepareBuildProjectsTask task = (PrepareBuildProjectsTask) taskQueueExecutor.getCurrentTask();
-                
-                map.put( url, task );
-            }
-        }
+        // call reload in case we disable a build agent
+        reload();
 
         return map;
     }
 
-    public List<Installation> getAvailableInstallations( String buildAgentUrl )
+    public Map<String, PrepareBuildProjectsTask> getProjectsCurrentlyPreparingBuild()
         throws ContinuumException
     {
-        List<Installation> installations = new ArrayList<Installation>();
+        Map<String, PrepareBuildProjectsTask> map = new HashMap<String, PrepareBuildProjectsTask>();
 
-        try
+        synchronized ( overallDistributedBuildQueues )
         {
-            SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
-            
-            List<Map> installationsList = client.getAvailableInstallations();
-
-            for ( Map context : installationsList )
+            for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
             {
-                Installation installation = new Installation();
-                installation.setName( ContinuumBuildConstant.getInstallationName( context ) );
-                installation.setType( ContinuumBuildConstant.getInstallationType( context ) );
-                installation.setVarName( ContinuumBuildConstant.getInstallationVarName( context ) );
-                installation.setVarValue( ContinuumBuildConstant.getInstallationVarValue( context ) );
-                installations.add( installation );
-            }
-            
-            return installations;
-        }
-        catch ( Exception e )
-        {
-            throw new ContinuumException( "Unable to get available installations of build agent", e );
-        }
-    }
-
-    private List<ProjectDependency> getModifiedDependencies( BuildResult oldBuildResult, Map context )
-        throws ContinuumException
-    {
-        if ( oldBuildResult == null )
-        {
-            return null;
-        }
-
-        try
-        {
-            Project project = projectDao.getProjectWithAllDetails( ContinuumBuildConstant.getProjectId( context ) );
-            List<ProjectDependency> dependencies = project.getDependencies();
-
-            if ( dependencies == null )
-            {
-                dependencies = new ArrayList<ProjectDependency>();
-            }
-
-            if ( project.getParent() != null )
-            {
-                dependencies.add( project.getParent() );
-            }
-
-            if ( dependencies.isEmpty() )
-            {
-                return null;
-            }
-
-            List<ProjectDependency> modifiedDependencies = new ArrayList<ProjectDependency>();
-
-            for ( ProjectDependency dep : dependencies )
-            {
-                Project dependencyProject =
-                    projectDao.getProject( dep.getGroupId(), dep.getArtifactId(), dep.getVersion() );
-
-                if ( dependencyProject != null )
+                try
                 {
-                    List buildResults = buildResultDao.getBuildResultsInSuccessForProject( dependencyProject.getId(),
-                                                                                           oldBuildResult.getEndTime() );
-                    if ( buildResults != null && !buildResults.isEmpty() )
+                    if ( isAgentAvailable( buildAgentUrl ) )
                     {
-                        log.debug( "Dependency changed: " + dep.getGroupId() + ":" + dep.getArtifactId() + ":" +
-                            dep.getVersion() );
-                        modifiedDependencies.add( dep );
+                        log.debug( "Getting project currently preparing build in build agent {}", buildAgentUrl );
+
+                        SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                            buildAgentUrl );
+                        Map<String, Object> project = client.getProjectCurrentlyPreparingBuild();
+
+                        if ( !project.isEmpty() )
+                        {
+                            map.put( buildAgentUrl, getPrepareBuildProjectsTask( project ) );
+                        }
                     }
                     else
                     {
-                        log.debug( "Dependency not changed: " + dep.getGroupId() + ":" + dep.getArtifactId() +
-                            ":" + dep.getVersion() );
+                        log.debug( "Unable to get projects currently preparing build. Build agent {} is not available",
+                                   buildAgentUrl );
                     }
                 }
-                else
+                catch ( MalformedURLException e )
                 {
-                    log.debug( "Skip non Continuum project: " + dep.getGroupId() + ":" + dep.getArtifactId() +
-                        ":" + dep.getVersion() );
+                    throw new ContinuumException( "Invalid build agent url: " + buildAgentUrl );
+                }
+                catch ( Exception e )
+                {
+                    throw new ContinuumException(
+                        "Error retrieving projects currently preparing build in " + buildAgentUrl, e );
+                }
+            }
+        }
+
+        // call reload in case we disable a build agent
+        reload();
+
+        return map;
+    }
+
+    public Map<String, BuildProjectTask> getProjectsCurrentlyBuilding()
+        throws ContinuumException
+    {
+        Map<String, BuildProjectTask> map = new HashMap<String, BuildProjectTask>();
+
+        synchronized ( overallDistributedBuildQueues )
+        {
+            for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
+            {
+                try
+                {
+                    if ( isAgentAvailable( buildAgentUrl ) )
+                    {
+                        log.debug( "Getting projects currently building in build agent {}", buildAgentUrl );
+
+                        SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                            buildAgentUrl );
+                        Map<String, Object> project = client.getProjectCurrentlyBuilding();
+
+                        if ( !project.isEmpty() )
+                        {
+                            map.put( buildAgentUrl, getBuildProjectTask( project ) );
+                        }
+                    }
+                    else
+                    {
+                        log.debug( "Unable to get projects currently building. Build agent {} is not available",
+                                   buildAgentUrl );
+                    }
+                }
+                catch ( MalformedURLException e )
+                {
+                    throw new ContinuumException( "Invalid build agent url: " + buildAgentUrl );
+                }
+                catch ( Exception e )
+                {
+                    throw new ContinuumException( "Error retrieving projects currently building in " + buildAgentUrl,
+                                                  e );
+                }
+            }
+        }
+
+        // call reload in case we disable a build agent
+        reload();
+
+        return map;
+    }
+
+    public Map<String, List<BuildProjectTask>> getProjectsInBuildQueue()
+        throws ContinuumException
+    {
+        Map<String, List<BuildProjectTask>> map = new HashMap<String, List<BuildProjectTask>>();
+
+        synchronized ( overallDistributedBuildQueues )
+        {
+            for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
+            {
+                List<BuildProjectTask> tasks = new ArrayList<BuildProjectTask>();
+
+                try
+                {
+                    if ( isAgentAvailable( buildAgentUrl ) )
+                    {
+                        log.debug( "Getting projects in build queue in build agent {}", buildAgentUrl );
+
+                        SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                            buildAgentUrl );
+                        List<Map<String, Object>> projects = client.getProjectsInBuildQueue();
+
+                        for ( Map<String, Object> context : projects )
+                        {
+                            tasks.add( getBuildProjectTask( context ) );
+                        }
+
+                        map.put( buildAgentUrl, tasks );
+                    }
+                    else
+                    {
+                        log.debug( "Unable to get projects in build queue. Build agent {} is not available",
+                                   buildAgentUrl );
+                    }
+                }
+                catch ( MalformedURLException e )
+                {
+                    throw new ContinuumException( "Invalid build agent url: " + buildAgentUrl );
+                }
+                catch ( Exception e )
+                {
+                    throw new ContinuumException( "Error while retrieving projects in build queue", e );
+                }
+            }
+        }
+
+        // call reload in case we disable a build agent
+        reload();
+
+        return map;
+    }
+
+    public boolean isBuildAgentBusy( String buildAgentUrl )
+    {
+        synchronized ( overallDistributedBuildQueues )
+        {
+            OverallDistributedBuildQueue overallDistributedBuildQueue = overallDistributedBuildQueues.get(
+                buildAgentUrl );
+
+            if ( overallDistributedBuildQueue != null &&
+                overallDistributedBuildQueue.getDistributedBuildTaskQueueExecutor().getCurrentTask() != null )
+            {
+                log.debug( "build agent '" + buildAgentUrl + "' is busy" );
+                return true;
+            }
+
+            log.debug( "build agent '" + buildAgentUrl + "' is not busy" );
+            return false;
+        }
+    }
+
+    public void cancelDistributedBuild( String buildAgentUrl )
+        throws ContinuumException
+    {
+        try
+        {
+            if ( isAgentAvailable( buildAgentUrl ) )
+            {
+                log.debug( "Cancelling build in build agent {}", buildAgentUrl );
+
+                SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                    buildAgentUrl );
+
+                client.cancelBuild();
+            }
+            else
+            {
+                log.debug( "Unable to cancel build, build agent {} is not available", buildAgentUrl );
+            }
+
+            // call reload in case we disable the build agent
+            reload();
+        }
+        catch ( MalformedURLException e )
+        {
+            log.error( "Error cancelling build in build agent: Invalid build agent url " + buildAgentUrl );
+            throw new ContinuumException(
+                "Error cancelling build in build agent: Invalid build agent url " + buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Error occurred while cancelling build in build agent " + buildAgentUrl, e );
+            throw new ContinuumException( "Error occurred while cancelling build in build agent " + buildAgentUrl, e );
+        }
+    }
+
+    public void cancelGroupBuild( int projectGroupId )
+        throws ContinuumException
+    {
+        log.debug( "Cancelling all builds of project group {}", projectGroupId );
+
+        List<ProjectRunSummary> runsToDelete = new ArrayList<ProjectRunSummary>();
+
+        synchronized ( currentRuns )
+        {
+            for ( ProjectRunSummary run : currentRuns )
+            {
+                if ( run.getProjectGroupId() == projectGroupId )
+                {
+                    cancelCurrentRun( run, runsToDelete );
                 }
             }
 
-            return modifiedDependencies;
-        }
-        catch ( ContinuumStoreException e )
-        {
-            log.warn( "Can't get the project dependencies", e );
-        }
-
-        return null;
-    }
-
-    public void startProjectBuild( int projectId )
-        throws ContinuumException
-    {
-        try
-        {
-            Project project = projectDao.getProject( projectId );
-            project.setState( ContinuumProjectState.BUILDING );
-            projectDao.updateProject( project );
-        }
-        catch ( ContinuumStoreException e )
-        {
-            log.error( "Error while updating project's state", e );
-            throw new ContinuumException( "Error while updating project's state", e );
+            if ( runsToDelete.size() > 0 )
+            {
+                currentRuns.removeAll( runsToDelete );
+            }
         }
     }
 
-    public void startPrepareBuild( Map context )
+    public void cancelBuild( int projectId )
         throws ContinuumException
     {
-        try
+        log.debug( "Cancelling all builds of project {}", projectId );
+
+        List<ProjectRunSummary> runsToDelete = new ArrayList<ProjectRunSummary>();
+
+        synchronized ( currentRuns )
         {
-            int projectGroupId = ContinuumBuildConstant.getProjectGroupId( context );
-            String scmRootAddress = ContinuumBuildConstant.getScmRootAddress( context );
-            
-            ProjectScmRoot scmRoot = projectScmRootDao.getProjectScmRootByProjectGroupAndScmRootAddress( projectGroupId, scmRootAddress );
-            scmRoot.setOldState( scmRoot.getState() );
-            scmRoot.setState( ContinuumProjectState.UPDATING );
-            projectScmRootDao.updateProjectScmRoot( scmRoot );
+            for ( ProjectRunSummary run : currentRuns )
+            {
+                if ( run.getProjectId() == projectId )
+                {
+                    cancelCurrentRun( run, runsToDelete );
+                }
+            }
+
+            if ( runsToDelete.size() > 0 )
+            {
+                currentRuns.removeAll( runsToDelete );
+            }
         }
-        catch ( ContinuumStoreException e )
+    }
+
+    private void cancelCurrentRun( ProjectRunSummary run, List<ProjectRunSummary> runsToDelete )
+        throws ContinuumException
+    {
+        int projectId = run.getProjectId();
+        int buildDefinitionId = run.getBuildDefinitionId();
+        String buildAgentUrl = run.getBuildAgentUrl();
+
+        // try to remove from any queue first
+        removeFromPrepareBuildQueue( buildAgentUrl, run.getProjectGroupId(), run.getProjectScmRootId() );
+        removeFromBuildQueue( buildAgentUrl, projectId, buildDefinitionId );
+
+        if ( isProjectCurrentlyPreparingBuild( projectId, buildDefinitionId ) )
         {
-            log.error( "Error while updating project scm root's state", e );
-            throw new ContinuumException( "Error while updating project scm root's state", e );
+            log.debug(
+                "Unable to cancel build of projectId={}, buildDefinitionId={} in build agent{}. Project is currently doing scm update." );
+            return;
+        }
+        else if ( isProjectCurrentlyBuilding( projectId, buildDefinitionId ) )
+        {
+            log.debug( "Cancel build of projectId={}, buildDefinitionId={} in build agent {}",
+                       new Object[]{projectId, buildDefinitionId, buildAgentUrl} );
+            cancelDistributedBuild( buildAgentUrl );
+            runsToDelete.add( run );
+        }
+        else
+        {
+            try
+            {
+                ProjectScmRoot scmRoot = projectScmRootDao.getProjectScmRoot( run.getProjectScmRootId() );
+
+                if ( scmRoot != null && scmRoot.getState() == ContinuumProjectState.UPDATING )
+                {
+                    // no longer updating, but state was not updated.
+                    scmRoot.setState( ContinuumProjectState.ERROR );
+                    scmRoot.setError(
+                        "Problem encountered while returning scm update result to master by build agent '" +
+                            buildAgentUrl + "'. \n" +
+                            "Make sure build agent is configured properly. Check the logs for more information." );
+                    projectScmRootDao.updateProjectScmRoot( scmRoot );
+
+                    log.debug(
+                        "projectId={}, buildDefinitionId={} is not updating anymore. Problem encountered while return scm update result by build agent {}. Stopping the build.",
+                        new Object[]{projectId, buildDefinitionId, buildAgentUrl} );
+                    runsToDelete.add( run );
+                }
+                else if ( scmRoot != null && scmRoot.getState() == ContinuumProjectState.ERROR )
+                {
+                    log.debug(
+                        "projectId={}, buildDefinitionId={} is not updating anymore. Problem encountered while return scm update result by build agent {}. Stopping the build.",
+                        new Object[]{projectId, buildDefinitionId, buildAgentUrl} );
+                    runsToDelete.add( run );
+                }
+                else
+                {
+                    Project project = projectDao.getProject( projectId );
+                    BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
+
+                    // no longer building, but state was not updated
+                    BuildResult buildResult = new BuildResult();
+                    buildResult.setBuildDefinition( buildDefinition );
+                    buildResult.setBuildUrl( run.getBuildAgentUrl() );
+                    buildResult.setTrigger( run.getTrigger() );
+                    buildResult.setUsername( run.getTriggeredBy() );
+                    buildResult.setState( ContinuumProjectState.ERROR );
+                    buildResult.setSuccess( false );
+                    buildResult.setStartTime( new Date().getTime() );
+                    buildResult.setEndTime( new Date().getTime() );
+                    buildResult.setExitCode( 1 );
+                    buildResult.setError(
+                        "Problem encountered while returning build result to master by build agent '" + buildAgentUrl +
+                            "'. \n" +
+                            "Make sure build agent is configured properly. Check the logs for more information." );
+                    buildResultDao.addBuildResult( project, buildResult );
+
+                    project.setState( ContinuumProjectState.ERROR );
+                    project.setLatestBuildId( buildResult.getId() );
+                    projectDao.updateProject( project );
+
+                    log.debug(
+                        "projectId={}, buildDefinitionId={} is not building anymore. Problem encountered while return build result by build agent {}. Stopping the build.",
+                        new Object[]{projectId, buildDefinitionId, buildAgentUrl} );
+
+                    // create a build result
+                    runsToDelete.add( run );
+                }
+            }
+            catch ( Exception e )
+            {
+                log.error( "Unable to end build for projectId={}, buildDefinitionId={} : {}",
+                           new Object[]{projectId, buildDefinitionId, e.getMessage()} );
+            }
         }
     }
 
@@ -622,39 +911,55 @@
         throws ContinuumException
     {
         Map<String, Object> map = new HashMap<String, Object>();
-        
+
         String buildAgentUrl = getBuildAgent( projectId );
-        
+
         if ( buildAgentUrl == null )
         {
+            log.debug( "Unable to determine the build agent where project is building" );
             return null;
         }
 
         try
         {
-            SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
-
-            Map result = client.getBuildResult( projectId );
-            
-            if ( result != null )
+            if ( isAgentAvailable( buildAgentUrl ) )
             {
-                int buildDefinitionId = ContinuumBuildConstant.getBuildDefinitionId( result );
+                log.debug( "Getting build result of project in build agent {}", buildAgentUrl );
+                SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                    buildAgentUrl );
 
-                Project project = projectDao.getProjectWithAllDetails( projectId );
-                BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
+                Map<String, Object> result = client.getBuildResult( projectId );
 
-                BuildResult oldBuildResult =
-                    buildResultDao.getLatestBuildResultForBuildDefinition( projectId, buildDefinitionId );
+                if ( result != null )
+                {
+                    int buildDefinitionId = ContinuumBuildConstant.getBuildDefinitionId( result );
 
-                BuildResult buildResult = convertMapToBuildResult( result );
-                buildResult.setBuildDefinition( buildDefinition );
-                buildResult.setBuildNumber( project.getBuildNumber() + 1 );
-                buildResult.setModifiedDependencies( getModifiedDependencies( oldBuildResult, result ) );
+                    Project project = projectDao.getProjectWithAllDetails( projectId );
+                    BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
 
-                String buildOutput = ContinuumBuildConstant.getBuildOutput( result );
-                
-                map.put( ContinuumBuildConstant.KEY_BUILD_RESULT, buildResult );
-                map.put( ContinuumBuildConstant.KEY_BUILD_OUTPUT, buildOutput );
+                    BuildResult oldBuildResult = buildResultDao.getLatestBuildResultForBuildDefinition( projectId,
+                                                                                                        buildDefinitionId );
+
+                    BuildResult buildResult = distributedBuildUtil.convertMapToBuildResult( result );
+                    buildResult.setBuildDefinition( buildDefinition );
+                    buildResult.setBuildNumber( project.getBuildNumber() + 1 );
+                    buildResult.setModifiedDependencies( distributedBuildUtil.getModifiedDependencies( oldBuildResult,
+                                                                                                       result ) );
+                    buildResult.setScmResult( distributedBuildUtil.getScmResult( result ) );
+
+                    String buildOutput = ContinuumBuildConstant.getBuildOutput( result );
+
+                    map.put( ContinuumBuildConstant.KEY_BUILD_RESULT, buildResult );
+                    map.put( ContinuumBuildConstant.KEY_BUILD_OUTPUT, buildOutput );
+                }
+                else
+                {
+                    log.debug( "No build result returned by build agent {}", buildAgentUrl );
+                }
+            }
+            else
+            {
+                log.debug( "Unable to get build result of project. Build agent {} is not available", buildAgentUrl );
             }
         }
         catch ( MalformedURLException e )
@@ -666,111 +971,1201 @@
             throw new ContinuumException( "Error while retrieving build result for project" + projectId, e );
         }
 
+        // call reload in case we disable the build agent
+        reload();
+
         return map;
     }
 
-    public Map<String, String> getEnvironments( int buildDefinitionId, String installationType )
+    public String getBuildAgentPlatform( String buildAgentUrl )
         throws ContinuumException
     {
-        BuildDefinition buildDefinition;
+        try
+        {
+            String platform = "";
+            if ( isAgentAvailable( buildAgentUrl ) )
+            {
+                log.debug( "Getting build agent {} platform", buildAgentUrl );
+
+                SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                    buildAgentUrl );
+                platform = client.getBuildAgentPlatform();
+            }
+            else
+            {
+                log.debug( "Unable to get build agent platform. Build agent {} is not available", buildAgentUrl );
+            }
+            // call reload in case we disable the build agent
+            reload();
+            return platform;
+        }
+        catch ( Exception e )
+        {
+            throw new ContinuumException( "Unable to get platform of build agent", e );
+        }
+    }
+
+
+    public List<Installation> getAvailableInstallations( String buildAgentUrl )
+        throws ContinuumException
+    {
+        List<Installation> installations = new ArrayList<Installation>();
 
         try
         {
-            buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
+            if ( isAgentAvailable( buildAgentUrl ) )
+            {
+                log.debug( "Getting available installations in build agent {}", buildAgentUrl );
+
+                SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                    buildAgentUrl );
+
+                List<Map<String, String>> installationsList = client.getAvailableInstallations();
+
+                for ( Map context : installationsList )
+                {
+                    Installation installation = new Installation();
+                    installation.setName( ContinuumBuildConstant.getInstallationName( context ) );
+                    installation.setType( ContinuumBuildConstant.getInstallationType( context ) );
+                    installation.setVarName( ContinuumBuildConstant.getInstallationVarName( context ) );
+                    installation.setVarValue( ContinuumBuildConstant.getInstallationVarValue( context ) );
+                    installations.add( installation );
+                }
+            }
+            else
+            {
+                log.debug( "Unable to get available installations. Build agent {} is not available", buildAgentUrl );
+            }
+
+            // call reload in case we disable the build agent
+            reload();
+
+            return installations;
         }
-        catch ( ContinuumStoreException e )
+        catch ( Exception e )
         {
-            throw new ContinuumException( "Failed to retrieve build definition: " + buildDefinitionId, e );
+            throw new ContinuumException( "Unable to get available installations of build agent", e );
+        }
+    }
+
+    public String generateWorkingCopyContent( int projectId, String directory, String baseUrl, String imageBaseUrl )
+        throws ContinuumException
+    {
+        BuildResult buildResult = buildResultDao.getLatestBuildResultForProject( projectId );
+
+        if ( buildResult != null )
+        {
+            String buildAgentUrl = buildResult.getBuildUrl();
+
+            if ( buildAgentUrl == null )
+            {
+                log.debug( "Unable to determine the build agent where project last built" );
+
+                return "";
+            }
+
+            try
+            {
+                if ( directory == null )
+                {
+                    directory = "";
+                }
+
+                if ( isAgentAvailable( buildAgentUrl ) )
+                {
+                    log.debug( "Generating working copy content of project in build agent {}", buildAgentUrl );
+
+                    SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                        buildAgentUrl );
+                    return client.generateWorkingCopyContent( projectId, directory, baseUrl, imageBaseUrl );
+                }
+                else
+                {
+                    log.debug( "Unable to generate working copy content of project. Build agent {} is not available",
+                               buildAgentUrl );
+                }
+            }
+            catch ( MalformedURLException e )
+            {
+                log.error( "Invalid build agent url " + buildAgentUrl );
+            }
+            catch ( Exception e )
+            {
+                log.error( "Error while generating working copy content from build agent " + buildAgentUrl, e );
+            }
+        }
+        else
+        {
+            log.debug( "Unable to generate working copy content. Project hasn't been built yet." );
         }
 
-        Profile profile = buildDefinition.getProfile();
-        if ( profile == null )
+        // call reload in case we disable the build agent
+        reload();
+
+        return "";
+    }
+
+    public Map<String, Object> getFileContent( int projectId, String directory, String filename )
+        throws ContinuumException
+    {
+        BuildResult buildResult = buildResultDao.getLatestBuildResultForProject( projectId );
+
+        if ( buildResult != null )
         {
-            return Collections.EMPTY_MAP;
+            String buildAgentUrl = buildResult.getBuildUrl();
+
+            if ( buildAgentUrl == null )
+            {
+                log.debug( "Unable to determine build agent where project last built" );
+                return null;
+            }
+
+            try
+            {
+                if ( isAgentAvailable( buildAgentUrl ) )
+                {
+                    SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                        buildAgentUrl );
+                    return client.getProjectFile( projectId, directory, filename );
+                }
+            }
+            catch ( MalformedURLException e )
+            {
+                log.error( "Invalid build agent url " + buildAgentUrl );
+            }
+            catch ( Exception e )
+            {
+                log.error( "Error while retrieving content of " + filename, e );
+            }
         }
-        Map<String, String> envVars = new HashMap<String, String>();
-        String javaHome = getJavaHomeValue( buildDefinition );
-        if ( !StringUtils.isEmpty( javaHome ) )
+        else
         {
-            envVars.put( installationService.getEnvVar( InstallationService.JDK_TYPE ), javaHome );
+            log.debug( "Unable to get file content because project hasn't been built yet" );
         }
-        Installation builder = profile.getBuilder();
-        if ( builder != null )
+
+        // call reload in case we disable the build agent
+        reload();
+
+        return null;
+    }
+
+    public void removeFromPrepareBuildQueue( String buildAgentUrl, int projectGroupId, int scmRootId )
+        throws ContinuumException
+    {
+        try
         {
-            envVars.put( installationService.getEnvVar( installationType ), builder.getVarValue() );
+            if ( isAgentAvailable( buildAgentUrl ) )
+            {
+                log.info( "Removing projectGroupId {} from prepare build queue of build agent {}", projectGroupId,
+                          buildAgentUrl );
+
+                SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                    buildAgentUrl );
+                client.removeFromPrepareBuildQueue( projectGroupId, scmRootId );
+            }
+            else
+            {
+                log.debug(
+                    "Unable to remove projectGroupId {} from prepare build queue. Build agent {} is not available",
+                    projectGroupId, buildAgentUrl );
+            }
         }
-        envVars.putAll( getEnvironmentVariables( buildDefinition ) );
-        return envVars;
+        catch ( MalformedURLException e )
+        {
+            log.error( "Unable to remove projectGroupId=" + projectGroupId + " scmRootId=" + scmRootId +
+                           " from prepare build queue: Invalid build agent url " + buildAgentUrl );
+            throw new ContinuumException(
+                "Unable to remove projectGroupId=" + projectGroupId + " scmRootId=" + scmRootId +
+                    " from prepare build queue: Invalid build agent url " + buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Error occurred while removing projectGroupId=" + projectGroupId + " scmRootId=" + scmRootId +
+                           " from prepare build queue of agent " + buildAgentUrl, e );
+            throw new ContinuumException(
+                "Error occurred while removing projectGroupId=" + projectGroupId + " scmRootId=" +
+                    scmRootId + " from prepare build queue of agent " + buildAgentUrl, e );
+        }
+
+        // call reload in case we disable the build agent
+        reload();
+    }
+
+    public void removeFromBuildQueue( String buildAgentUrl, int projectId, int buildDefinitionId )
+        throws ContinuumException
+    {
+        try
+        {
+            if ( isAgentAvailable( buildAgentUrl ) )
+            {
+                log.info( "Removing projectId {} from build queue of build agent {}", projectId, buildAgentUrl );
+                SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                    buildAgentUrl );
+                client.removeFromBuildQueue( projectId, buildDefinitionId );
+            }
+            else
+            {
+                log.debug( "Unable to remove projectId {} from build queue. Build agent {} is not available", projectId,
+                           buildAgentUrl );
+            }
+        }
+        catch ( MalformedURLException e )
+        {
+            log.error( "Unable to remove project " + projectId +
+                           " from build queue: Invalid build agent url " + buildAgentUrl );
+            throw new ContinuumException( "Unable to remove project " + projectId +
+                                              " from build queue: Invalid build agent url " + buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Error occurred while removing project " + projectId +
+                           " from build queue of agent " + buildAgentUrl, e );
+            throw new ContinuumException( "Error occurred while removing project " + projectId +
+                                              " from build queue of agent " + buildAgentUrl, e );
+        }
+
+        // call reload in case we disable the build agent
+        reload();
+    }
+
+    public void removeFromPrepareBuildQueue( List<String> hashCodes )
+        throws ContinuumException
+    {
+        synchronized ( overallDistributedBuildQueues )
+        {
+            for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
+            {
+                try
+                {
+                    if ( isAgentAvailable( buildAgentUrl ) )
+                    {
+                        log.info( "Removing project groups from prepare build queue of build agent {}", buildAgentUrl );
+
+                        SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                            buildAgentUrl );
+                        client.removeFromPrepareBuildQueue( hashCodes );
+                    }
+                    else
+                    {
+                        log.debug(
+                            "Unable to remove project groups from prepare build queue. Build agent {} is not available",
+                            buildAgentUrl );
+                    }
+                }
+                catch ( MalformedURLException e )
+                {
+                    log.error( "Error trying to remove projects from prepare build queue. Invalid build agent url: " +
+                                   buildAgentUrl );
+                }
+                catch ( Exception e )
+                {
+                    log.error( "Error trying to remove projects from prepare build queue of agent " + buildAgentUrl,
+                               e );
+                }
+            }
+        }
+
+        // call reload in case we disable a build agent
+        reload();
+    }
+
+    public void removeFromBuildQueue( List<String> hashCodes )
+        throws ContinuumException
+    {
+        synchronized ( overallDistributedBuildQueues )
+        {
+            for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
+            {
+                try
+                {
+                    if ( isAgentAvailable( buildAgentUrl ) )
+                    {
+                        log.info( "Removing projects from build queue of build agent {}", buildAgentUrl );
+
+                        SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                            buildAgentUrl );
+                        client.removeFromBuildQueue( hashCodes );
+                    }
+                    else
+                    {
+                        log.debug( "Unable to remove projects from build queue. Build agent {} is not available",
+                                   buildAgentUrl );
+                    }
+                }
+                catch ( MalformedURLException e )
+                {
+                    log.error(
+                        "Error trying to remove projects from build queue. Invalid build agent url: " + buildAgentUrl );
+                }
+                catch ( Exception e )
+                {
+                    log.error( "Error trying to remove projects from build queue of agent " + buildAgentUrl, e );
+                }
+            }
+        }
+
+        // call reload in case we disable a build agent
+        reload();
+    }
+
+    public boolean isProjectInAnyPrepareBuildQueue( int projectId, int buildDefinitionId )
+        throws ContinuumException
+    {
+        boolean found = false;
+
+        synchronized ( overallDistributedBuildQueues )
+        {
+            for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
+            {
+                try
+                {
+                    if ( isAgentAvailable( buildAgentUrl ) )
+                    {
+                        log.debug( "Checking if project {} is in prepare build queue of build agent {}", projectId,
+                                   buildAgentUrl );
+
+                        SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                            buildAgentUrl );
+
+                        List<Map<String, Object>> projects = client.getProjectsAndBuildDefinitionsInPrepareBuildQueue();
+
+                        for ( Map<String, Object> context : projects )
+                        {
+                            int pid = ContinuumBuildConstant.getProjectId( context );
+                            int buildId = ContinuumBuildConstant.getBuildDefinitionId( context );
+
+                            if ( pid == projectId && ( buildId == buildDefinitionId || buildDefinitionId == -1 ) )
+                            {
+                                found = true;
+                                break;
+                            }
+
+                        }
+                    }
+                    else
+                    {
+                        log.debug(
+                            "Unable to check if project {} is in prepare build queue. Build agent {} is not available",
+                            projectId, buildAgentUrl );
+                    }
+
+                    if ( found )
+                    {
+                        break;
+                    }
+                }
+                catch ( MalformedURLException e )
+                {
+                    throw new ContinuumException( "Invalid build agent url: " + buildAgentUrl );
+                }
+                catch ( Exception e )
+                {
+                    throw new ContinuumException( "Error while retrieving projects in prepare build queue", e );
+                }
+            }
+        }
+
+        // call reload in case we disable a build agent
+        reload();
+
+        if ( found )
+        {
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    public boolean isProjectInAnyBuildQueue( int projectId, int buildDefinitionId )
+        throws ContinuumException
+    {
+        Map<String, List<BuildProjectTask>> map = getProjectsInBuildQueue();
+
+        for ( String url : map.keySet() )
+        {
+            for ( BuildProjectTask task : map.get( url ) )
+            {
+                if ( task.getProjectId() == projectId &&
+                    ( buildDefinitionId == -1 || task.getBuildDefinitionId() == buildDefinitionId ) )
+                {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    public boolean isProjectCurrentlyPreparingBuild( int projectId, int buildDefinitionId )
+        throws ContinuumException
+    {
+        boolean found = false;
+
+        synchronized ( overallDistributedBuildQueues )
+        {
+            for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
+            {
+                try
+                {
+                    if ( isAgentAvailable( buildAgentUrl ) )
+                    {
+                        log.debug( "Checking if project {} is currently preparing build in build agent {}", projectId,
+                                   buildAgentUrl );
+
+                        SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                            buildAgentUrl );
+                        List<Map<String, Object>> projects =
+                            client.getProjectsAndBuildDefinitionsCurrentlyPreparingBuild();
+
+                        for ( Map<String, Object> context : projects )
+                        {
+                            int pid = ContinuumBuildConstant.getProjectId( context );
+                            int buildId = ContinuumBuildConstant.getBuildDefinitionId( context );
+
+                            if ( pid == projectId && ( buildDefinitionId == -1 || buildId == buildDefinitionId ) )
+                            {
+                                found = true;
+                                break;
+                            }
+                        }
+                    }
+                    else
+                    {
+                        log.debug(
+                            "Unable to check if project {} is currently preparing build. Build agent {} is not available",
+                            projectId, buildAgentUrl );
+                    }
+
+                    if ( found )
+                    {
+                        break;
+                    }
+                }
+                catch ( MalformedURLException e )
+                {
+                    throw new ContinuumException( "Invalid build agent url: " + buildAgentUrl );
+                }
+                catch ( Exception e )
+                {
+                    throw new ContinuumException(
+                        "Error retrieving projects currently preparing build in " + buildAgentUrl, e );
+                }
+            }
+        }
+
+        // call reload in case we disable a build agent
+        reload();
+
+        if ( found )
+        {
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    public boolean isProjectCurrentlyBuilding( int projectId, int buildDefinitionId )
+        throws ContinuumException
+    {
+        Map<String, BuildProjectTask> map = getProjectsCurrentlyBuilding();
+
+        for ( String url : map.keySet() )
+        {
+            BuildProjectTask task = map.get( url );
+
+            if ( task.getProjectId() == projectId &&
+                ( buildDefinitionId == -1 || task.getBuildDefinitionId() == buildDefinitionId ) )
+            {
+                return true;
+            }
+        }
+
+        return false;
     }
 
     private String getBuildAgent( int projectId )
         throws ContinuumException
     {
-        Map<String, PrepareBuildProjectsTask> map = getDistributedBuildProjects();
-        
-        for ( String url : map.keySet() )
+        String agentUrl = null;
+
+        synchronized ( overallDistributedBuildQueues )
         {
-            PrepareBuildProjectsTask task = map.get( url );
-            
-            for ( Integer id : task.getProjectsBuildDefinitionsMap().keySet() )
+            for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
             {
-                if ( projectId == id )
+                OverallDistributedBuildQueue overallDistributedBuildQueue = overallDistributedBuildQueues.get(
+                    buildAgentUrl );
+
+                if ( overallDistributedBuildQueue != null )
                 {
-                    return url;
+                    try
+                    {
+                        if ( isAgentAvailable( buildAgentUrl ) )
+                        {
+                            SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                                buildAgentUrl );
+
+                            // TODO: should check for specific build definition and handle that in UI;
+                            // project with different build definitions can build at the same time in different agents and
+                            // currently, we can't handle that in the ui.
+                            if ( client.isProjectCurrentlyBuilding( projectId, -1 ) )
+                            {
+                                agentUrl = buildAgentUrl;
+                                break;
+                            }
+                        }
+                        else
+                        {
+                            log.debug(
+                                "Unable to check if project {} is currently building. Build agent {} is not available",
+                                projectId, buildAgentUrl );
+                        }
+                    }
+                    catch ( MalformedURLException e )
+                    {
+                        log.warn(
+                            "Unable to check if project {} is currently building in agent: Invalid build agent url {}",
+                            projectId, buildAgentUrl );
+                    }
+                    catch ( Exception e )
+                    {
+                        log.warn( "Unable to check if project {} is currently building in agent", projectId, e );
+                    }
                 }
             }
         }
-        
+
+        // call reload in case we disable a build agent
+        reload();
+
+        return agentUrl;
+    }
+
+    public String getBuildAgentUrl( int projectId, int buildDefinitionId )
+        throws ContinuumException
+    {
+        String agentUrl = null;
+
+        synchronized ( overallDistributedBuildQueues )
+        {
+            for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
+            {
+                OverallDistributedBuildQueue overallDistributedBuildQueue = overallDistributedBuildQueues.get(
+                    buildAgentUrl );
+
+                if ( overallDistributedBuildQueue != null )
+                {
+                    try
+                    {
+                        if ( isAgentAvailable( buildAgentUrl ) )
+                        {
+                            log.debug(
+                                "Checking if project {} with build definition {} is currently queued or processed in agent {}",
+                                new Object[]{projectId, buildDefinitionId, buildAgentUrl} );
+
+                            SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                                buildAgentUrl );
+
+                            if ( client.isProjectInPrepareBuildQueue( projectId, buildDefinitionId ) ||
+                                client.isProjectCurrentlyPreparingBuild( projectId, buildDefinitionId ) ||
+                                client.isProjectInBuildQueue( projectId, buildDefinitionId ) ||
+                                client.isProjectCurrentlyBuilding( projectId, buildDefinitionId ) )
+                            {
+                                log.debug(
+                                    "Project {} with build definition {} is currently queued or processed in agent {}",
+                                    new Object[]{projectId, buildDefinitionId, buildAgentUrl} );
+                                agentUrl = buildAgentUrl;
+                                break;
+                            }
+                        }
+                        else
+                        {
+                            log.debug(
+                                "Unable to check if project {} is currently queued or processed in agent. Build agent {} is not available",
+                                projectId, buildAgentUrl );
+                        }
+                    }
+                    catch ( MalformedURLException e )
+                    {
+                        log.warn(
+                            "Unable to check if project {} is currently queued or processed in agent: Invalid build agent url {}",
+                            projectId, buildAgentUrl );
+                    }
+                    catch ( Exception e )
+                    {
+                        log.warn( "Unable to check if project {} is currently queued or processed in agent", projectId,
+                                  e );
+                    }
+                }
+            }
+        }
+
+        // call reload in case we disable a build agent
+        reload();
+
+        return agentUrl;
+    }
+
+    private void createDistributedBuildQueueForAgent( String buildAgentUrl )
+        throws ComponentLookupException
+    {
+        if ( !overallDistributedBuildQueues.containsKey( buildAgentUrl ) )
+        {
+            OverallDistributedBuildQueue overallDistributedBuildQueue = (OverallDistributedBuildQueue) container.lookup(
+                OverallDistributedBuildQueue.class );
+            overallDistributedBuildQueue.setBuildAgentUrl( buildAgentUrl );
+            overallDistributedBuildQueue.getDistributedBuildTaskQueueExecutor().setBuildAgentUrl( buildAgentUrl );
+
+            overallDistributedBuildQueues.put( buildAgentUrl, overallDistributedBuildQueue );
+        }
+    }
+
+    private OverallDistributedBuildQueue getOverallDistributedBuildQueueByScmRoot( ProjectScmRoot scmRoot,
+                                                                                   int projectGroupId )
+        throws ContinuumException
+    {
+        int scmRootId = scmRoot.getId();
+
+        synchronized ( overallDistributedBuildQueues )
+        {
+            for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
+            {
+                OverallDistributedBuildQueue distributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl );
+
+                try
+                {
+                    for ( PrepareBuildProjectsTask task : distributedBuildQueue.getProjectsInQueue() )
+                    {
+                        if ( task.getProjectScmRootId() == scmRootId )
+                        {
+                            log.debug(
+                                "Projects in the same continuum group are building in build agent: {}. Also building project in the same agent.",
+                                buildAgentUrl );
+                            return distributedBuildQueue;
+                        }
+                    }
+
+                    Task task = distributedBuildQueue.getDistributedBuildTaskQueueExecutor().getCurrentTask();
+                    if ( task != null && ( (PrepareBuildProjectsTask) task ).getProjectScmRootId() == scmRootId )
+                    {
+                        log.debug(
+                            "Projects in the same continuum group are building in build agent: {}. Also building project in the same agent.",
+                            buildAgentUrl );
+                        return distributedBuildQueue;
+                    }
+
+                    if ( isAgentAvailable( buildAgentUrl ) )
+                    {
+                        List<Project> projects = projectDao.getProjectsInGroup( projectGroupId );
+                        List<Integer> pIds = new ArrayList<Integer>();
+
+                        for ( Project project : projects )
+                        {
+                            if ( project.getScmUrl().startsWith( scmRoot.getScmRootAddress() ) )
+                            {
+                                pIds.add( project.getId() );
+                            }
+                        }
+
+                        SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                            buildAgentUrl );
+
+                        if ( client.isProjectScmRootInQueue( scmRootId, pIds ) )
+                        {
+                            log.debug(
+                                "Projects in the same continuum group are building in build agent: {}. Also building project in the same agent.",
+                                buildAgentUrl );
+                            return distributedBuildQueue;
+                        }
+                    }
+                    else
+                    {
+                        log.debug( "Build agent {} is not available. Skipping...", buildAgentUrl );
+                    }
+                }
+                catch ( TaskQueueException e )
+                {
+                    log.error( "Error occurred while retrieving distributed build queue of scmRootId=" + scmRootId, e );
+                    throw new ContinuumException( "Error occurred while retrieving distributed build queue of scmRoot",
+                                                  e );
+                }
+                catch ( MalformedURLException e )
+                {
+                    log.error( "Error occurred while retrieving distributed build queue of scmRootId=" + scmRootId +
+                                   ": Invalid build agent url " + buildAgentUrl );
+                    throw new ContinuumException(
+                        "Error occurred while retrieving distributed build queue of scmRootId=" + scmRootId +
+                            ": Invalid build agent url " + buildAgentUrl );
+                }
+                catch ( Exception e )
+                {
+                    log.error( "Error occurred while retrieving distributed build queue of scmRootId=" + scmRootId, e );
+                    throw new ContinuumException( "Error occurred while retrieving distributed build queue of scmRoot",
+                                                  e );
+                }
+            }
+        }
+
         return null;
     }
 
-    private BuildResult convertMapToBuildResult( Map context )
+    private OverallDistributedBuildQueue getOverallDistributedBuildQueueByGroup( int projectGroupId,
+                                                                                 List<ProjectScmRoot> scmRoots,
+                                                                                 int scmRootId )
+        throws ContinuumException
     {
-        BuildResult buildResult = new BuildResult();
+        if ( scmRoots != null )
+        {
+            log.debug( "Checking if the project group is already building in one of the build agents" );
 
-        buildResult.setStartTime( ContinuumBuildConstant.getBuildStart( context ) );
-        buildResult.setEndTime( ContinuumBuildConstant.getBuildEnd( context ) );
-        buildResult.setError( ContinuumBuildConstant.getBuildError( context ) );
-        buildResult.setExitCode( ContinuumBuildConstant.getBuildExitCode( context ) );
-        buildResult.setState( ContinuumBuildConstant.getBuildState( context ) );
-        buildResult.setTrigger( ContinuumBuildConstant.getTrigger( context ) );
-
-        return buildResult;
+            for ( ProjectScmRoot scmRoot : scmRoots )
+            {
+                if ( scmRoot.getId() == scmRootId )
+                {
+                    break;
+                }
+                else if ( scmRoot.getProjectGroup().getId() == projectGroupId )
+                {
+                    return getOverallDistributedBuildQueueByScmRoot( scmRoot, projectGroupId );
+                }
+            }
+        }
+        return null;
     }
 
-    private String getJavaHomeValue( BuildDefinition buildDefinition )
+    private OverallDistributedBuildQueue getOverallDistributedBuildQueueByAgentGroup(
+        Map<Integer, Integer> projectsAndBuildDefinitionsMap )
+        throws ContinuumException
     {
-        Profile profile = buildDefinition.getProfile();
-        if ( profile == null )
+        OverallDistributedBuildQueue whereToBeQueued = null;
+
+        BuildAgentGroupConfiguration buildAgentGroup = getBuildAgentGroup( projectsAndBuildDefinitionsMap );
+
+        if ( buildAgentGroup != null )
+        {
+            List<BuildAgentConfiguration> buildAgents = buildAgentGroup.getBuildAgents();
+
+            if ( buildAgents != null && buildAgents.size() > 0 )
+            {
+                List<String> buildAgentUrls = new ArrayList<String>();
+
+                for ( BuildAgentConfiguration buildAgent : buildAgents )
+                {
+                    buildAgentUrls.add( buildAgent.getUrl() );
+                }
+
+                synchronized ( overallDistributedBuildQueues )
+                {
+                    int idx = 0;
+                    int size = 0;
+
+                    for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
+                    {
+                        if ( !buildAgentUrls.isEmpty() && buildAgentUrls.contains( buildAgentUrl ) )
+                        {
+                            OverallDistributedBuildQueue distributedBuildQueue = overallDistributedBuildQueues.get(
+                                buildAgentUrl );
+
+                            if ( distributedBuildQueue != null )
+                            {
+                                try
+                                {
+                                    if ( isAgentAvailable( buildAgentUrl ) )
+                                    {
+                                        log.debug( "Build agent {} is available", buildAgentUrl );
+
+                                        SlaveBuildAgentTransportService client =
+                                            createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+                                        int agentBuildSize = client.getBuildSizeOfAgent();
+
+                                        log.debug( "Number of projects currently building in agent: {}",
+                                                   agentBuildSize );
+                                        if ( idx == 0 )
+                                        {
+                                            log.debug( "Current least busy agent: {}", buildAgentUrl );
+                                            whereToBeQueued = distributedBuildQueue;
+                                            size = agentBuildSize;
+                                            idx++;
+                                        }
+
+                                        if ( agentBuildSize < size )
+                                        {
+                                            log.debug( "Current least busy agent: {}", buildAgentUrl );
+                                            whereToBeQueued = distributedBuildQueue;
+                                            size = agentBuildSize;
+                                        }
+                                    }
+                                    else
+                                    {
+                                        log.debug( "Build agent {} is not available. Skipping...", buildAgentUrl );
+                                    }
+                                }
+                                catch ( MalformedURLException e )
+                                {
+                                    log.error(
+                                        "Error occurred while retrieving distributed build queue: Invalid build agent url " +
+                                            buildAgentUrl );
+                                }
+                                catch ( Exception e )
+                                {
+                                    log.error( "Error occurred while retrieving distributed build queue ", e );
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return whereToBeQueued;
+    }
+
+    private OverallDistributedBuildQueue getOverallDistributedBuildQueue()
+        throws ContinuumException
+    {
+        OverallDistributedBuildQueue whereToBeQueued = null;
+
+        synchronized ( overallDistributedBuildQueues )
+        {
+            if ( overallDistributedBuildQueues.isEmpty() )
+            {
+                log.info( "No distributed build queues are configured for build agents" );
+                return null;
+            }
+
+            int idx = 0;
+            int size = 0;
+
+            for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
+            {
+                OverallDistributedBuildQueue distributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl );
+
+                if ( distributedBuildQueue != null )
+                {
+                    try
+                    {
+                        if ( isAgentAvailable( buildAgentUrl ) )
+                        {
+                            log.debug( "Build agent {} is available", buildAgentUrl );
+
+                            SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                                buildAgentUrl );
+                            int agentBuildSize = client.getBuildSizeOfAgent();
+
+                            log.debug( "Number of projects currently building in agent: {}", agentBuildSize );
+                            if ( idx == 0 )
+                            {
+                                log.debug( "Current least busy agent: {}", buildAgentUrl );
+                                whereToBeQueued = distributedBuildQueue;
+                                size = agentBuildSize;
+                                idx++;
+                            }
+
+                            if ( agentBuildSize < size )
+                            {
+                                log.debug( "Current least busy agent: {}", buildAgentUrl );
+                                whereToBeQueued = distributedBuildQueue;
+                                size = agentBuildSize;
+                            }
+                        }
+                        else
+                        {
+                            log.debug( "Build agent {} is not available. Skipping...", buildAgentUrl );
+                        }
+                    }
+                    catch ( MalformedURLException e )
+                    {
+                        log.error( "Error occurred while retrieving distributed build queue: invalid build agent url " +
+                                       buildAgentUrl );
+                    }
+                    catch ( Exception e )
+                    {
+                        log.error( "Error occurred while retrieving distributed build queue", e );
+                        throw new ContinuumException( "Error occurred while retrieving distributed build queue", e );
+                    }
+                }
+            }
+        }
+
+        return whereToBeQueued;
+    }
+
+    private BuildAgentGroupConfiguration getBuildAgentGroup( Map<Integer, Integer> projectsAndBuildDefinitions )
+        throws ContinuumException
+    {
+        if ( projectsAndBuildDefinitions == null )
         {
             return null;
         }
-        Installation jdk = profile.getJdk();
-        if ( jdk == null )
+
+        try
         {
-            return null;
+            List<Project> projects = new ArrayList<Project>();
+
+            for ( Integer projectId : projectsAndBuildDefinitions.keySet() )
+            {
+                projects.add( projectDao.getProjectWithDependencies( projectId ) );
+            }
+
+            projects = ProjectSorter.getSortedProjects( projects, log );
+
+            int buildDefinitionId = projectsAndBuildDefinitions.get( projects.get( 0 ).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 );
+
+                return buildAgentGroup;
+            }
         }
-        return jdk.getVarValue();
+        catch ( ContinuumStoreException e )
+        {
+            log.error( "Error while getting build agent group", e );
+            throw new ContinuumException( "Error while getting build agent group", e );
+        }
+
+        log.info( "profile build agent group is null" );
+
+        return null;
     }
 
-    private Map<String, String> getEnvironmentVariables( BuildDefinition buildDefinition )
+    private PrepareBuildProjectsTask getPrepareBuildProjectsTask( Map context )
     {
-        Profile profile = buildDefinition.getProfile();
-        Map<String, String> envVars = new HashMap<String, String>();
-        if ( profile == null )
-        {
-            return envVars;
-        }
-        List<Installation> environmentVariables = profile.getEnvironmentVariables();
-        if ( environmentVariables.isEmpty() )
-        {
-            return envVars;
-        }
-        for ( Installation installation : environmentVariables )
-        {
-            envVars.put( installation.getVarName(), installation.getVarValue() );
-        }
-        return envVars;
+        int projectGroupId = ContinuumBuildConstant.getProjectGroupId( context );
+        int scmRootId = ContinuumBuildConstant.getScmRootId( context );
+        String scmRootAddress = ContinuumBuildConstant.getScmRootAddress( context );
+        BuildTrigger buildTrigger = new BuildTrigger( ContinuumBuildConstant.getTrigger( context ),
+                                                      ContinuumBuildConstant.getUsername( context ) );
+
+        return new PrepareBuildProjectsTask( null, buildTrigger, projectGroupId, null, scmRootAddress, scmRootId );
     }
 
+    private BuildProjectTask getBuildProjectTask( Map context )
+    {
+        int projectId = ContinuumBuildConstant.getProjectId( context );
+        int buildDefinitionId = ContinuumBuildConstant.getBuildDefinitionId( context );
+        BuildTrigger buildTrigger = new BuildTrigger( ContinuumBuildConstant.getTrigger( context ),
+                                                      ContinuumBuildConstant.getUsername( context ) );
+        int projectGroupId = ContinuumBuildConstant.getProjectGroupId( context );
+        String buildDefinitionLabel = ContinuumBuildConstant.getBuildDefinitionLabel( context );
+
+        return new BuildProjectTask( projectId, buildDefinitionId, buildTrigger, null, buildDefinitionLabel, null,
+                                     projectGroupId );
+    }
+
+    public boolean isAgentAvailable( String buildAgentUrl )
+        throws ContinuumException
+    {
+        try
+        {
+            if ( pingBuildAgent( buildAgentUrl ) )
+            {
+                return true;
+            }
+        }
+        catch ( Exception e )
+        {
+            log.warn( "Disable build agent: {}; Unable to ping due to {}", buildAgentUrl, e );
+        }
+
+        // disable it
+        disableBuildAgent( buildAgentUrl );
+
+        return false;
+    }
+
+    public boolean pingBuildAgent( String buildAgentUrl )
+        throws ContinuumException
+    {
+        try
+        {
+            SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+
+            return client.ping();
+        }
+        catch ( MalformedURLException e )
+        {
+            log.warn( "Invalid build agent url {}", buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            throw new ContinuumException( "Unable to ping build agent " + buildAgentUrl + " : " + e.getMessage() );
+        }
+
+        return false;
+    }
+
+    public List<ProjectRunSummary> getCurrentRuns()
+    {
+        return currentRuns;
+    }
+
+    public void removeCurrentRun( int projectId, int buildDefinitionId )
+    {
+        synchronized ( currentRuns )
+        {
+            boolean found = false;
+            ProjectRunSummary runToDelete = null;
+
+            for ( ProjectRunSummary currentRun : currentRuns )
+            {
+                if ( currentRun.getProjectId() == projectId && currentRun.getBuildDefinitionId() == buildDefinitionId )
+                {
+                    found = true;
+                    runToDelete = currentRun;
+                    break;
+                }
+            }
+
+            if ( found )
+            {
+                currentRuns.remove( runToDelete );
+            }
+        }
+    }
+
+    private void createProjectRunSummaries( PrepareBuildProjectsTask task, String buildAgentUrl )
+    {
+        synchronized ( currentRuns )
+        {
+            int projectGroupId = task.getProjectGroupId();
+            int projectScmRootId = task.getProjectScmRootId();
+            Map<Integer, Integer> map = task.getProjectsBuildDefinitionsMap();
+
+            for ( int projectId : map.keySet() )
+            {
+                int buildDefinitionId = map.get( projectId );
+
+                ProjectRunSummary runToDelete = null;
+
+                // check if there is an existing current run with that project id and build definition id
+                for ( ProjectRunSummary currentRun : currentRuns )
+                {
+                    if ( currentRun.getProjectId() == projectId &&
+                        currentRun.getBuildDefinitionId() == buildDefinitionId )
+                    {
+                        runToDelete = currentRun;
+                        break;
+                    }
+                }
+
+                if ( runToDelete != null )
+                {
+                    // previous run already finished, but was not removed from the list
+                    // removed it
+                    currentRuns.remove( runToDelete );
+                }
+
+                ProjectRunSummary run = new ProjectRunSummary();
+                run.setProjectGroupId( projectGroupId );
+                run.setProjectScmRootId( projectScmRootId );
+                run.setProjectId( projectId );
+                run.setBuildDefinitionId( buildDefinitionId );
+                run.setTriggeredBy( task.getBuildTrigger().getTriggeredBy() );
+                run.setTrigger( task.getBuildTrigger().getTrigger() );
+                run.setBuildAgentUrl( buildAgentUrl );
+                currentRuns.add( run );
+            }
+        }
+    }
+
+    private void disableBuildAgent( String buildAgentUrl )
+        throws ContinuumException
+    {
+        List<BuildAgentConfiguration> agents = configurationService.getBuildAgents();
+
+        for ( BuildAgentConfiguration agent : agents )
+        {
+            if ( agent.getUrl().equals( buildAgentUrl ) )
+            {
+                agent.setEnabled( false );
+                configurationService.updateBuildAgent( agent );
+
+                try
+                {
+                    configurationService.store();
+
+                    log.debug( "Disabled build agent {}", buildAgentUrl );
+                }
+                catch ( Exception e )
+                {
+                    throw new ContinuumException( "Unable to disable build agent: " + buildAgentUrl, e );
+                }
+            }
+        }
+    }
+
+    private boolean hasBuildagentGroup( Map<Integer, Integer> projectsAndBuildDefinitionsMap )
+        throws ContinuumException
+    {
+        BuildAgentGroupConfiguration buildAgentGroup = getBuildAgentGroup( projectsAndBuildDefinitionsMap );
+
+        return buildAgentGroup != null && buildAgentGroup.getName().length() > 0 ? true : false;
+    }
+
+    private boolean hasBuildagentInGroup( Map<Integer, Integer> projectsAndBuildDefinitionsMap )
+        throws ContinuumException
+    {
+        BuildAgentGroupConfiguration buildAgentGroup = getBuildAgentGroup( projectsAndBuildDefinitionsMap );
+
+        return buildAgentGroup != null && buildAgentGroup.getBuildAgents().size() > 0 ? true : false;
+    }
+
+    public SlaveBuildAgentTransportService createSlaveBuildAgentTransportClientConnection( String buildAgentUrl )
+        throws MalformedURLException, Exception
+    {
+        return new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ), "",
+                                                   configurationService.getSharedSecretPassword() );
+    }
+
+    // for unit testing
+
+    public void setOverallDistributedBuildQueues(
+        Map<String, OverallDistributedBuildQueue> overallDistributedBuildQueues )
+    {
+        this.overallDistributedBuildQueues = overallDistributedBuildQueues;
+    }
+
+    public void setConfigurationService( ConfigurationService configurationService )
+    {
+        this.configurationService = configurationService;
+    }
+
+    public void setProjectDao( ProjectDao projectDao )
+    {
+        this.projectDao = projectDao;
+    }
+
+    public void setBuildDefinitionDao( BuildDefinitionDao buildDefinitionDao )
+    {
+        this.buildDefinitionDao = buildDefinitionDao;
+    }
+
+    public void setBuildResultDao( BuildResultDao buildResultDao )
+    {
+        this.buildResultDao = buildResultDao;
+    }
+
+    public void setContainer( PlexusContainer container )
+    {
+        this.container = container;
+    }
+
+    public void setCurrentRuns( List<ProjectRunSummary> currentRuns )
+    {
+        this.currentRuns = currentRuns;
+    }
+
+    public void setProjectScmRootDao( ProjectScmRootDao projectScmRootDao )
+    {
+        this.projectScmRootDao = projectScmRootDao;
+    }
 }
diff --git a/continuum-core/src/main/java/org/apache/continuum/builder/distributed/util/DistributedBuildUtil.java b/continuum-core/src/main/java/org/apache/continuum/builder/distributed/util/DistributedBuildUtil.java
new file mode 100644
index 0000000..3aa426b
--- /dev/null
+++ b/continuum-core/src/main/java/org/apache/continuum/builder/distributed/util/DistributedBuildUtil.java
@@ -0,0 +1,199 @@
+package org.apache.continuum.builder.distributed.util;
+
+/*
+ * 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 org.apache.continuum.builder.utils.ContinuumBuildConstant;
+import org.apache.continuum.dao.BuildResultDao;
+import org.apache.continuum.dao.ProjectDao;
+import org.apache.maven.continuum.ContinuumException;
+import org.apache.maven.continuum.model.project.BuildResult;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.project.ProjectDependency;
+import org.apache.maven.continuum.model.scm.ChangeFile;
+import org.apache.maven.continuum.model.scm.ChangeSet;
+import org.apache.maven.continuum.model.scm.ScmResult;
+import org.apache.maven.continuum.store.ContinuumStoreException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @plexus.component role="org.apache.continuum.builder.distributed.util.DistributedBuildUtil"
+ */
+public class DistributedBuildUtil
+{
+    private Logger log = LoggerFactory.getLogger( DistributedBuildUtil.class );
+
+    /**
+     * @plexus.requirement
+     */
+    private ProjectDao projectDao;
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildResultDao buildResultDao;
+
+    public BuildResult convertMapToBuildResult( Map<String, Object> context )
+    {
+        BuildResult buildResult = new BuildResult();
+
+        buildResult.setStartTime( ContinuumBuildConstant.getStartTime( context ) );
+        buildResult.setEndTime( ContinuumBuildConstant.getEndTime( context ) );
+        buildResult.setError( ContinuumBuildConstant.getBuildError( context ) );
+        buildResult.setExitCode( ContinuumBuildConstant.getBuildExitCode( context ) );
+        buildResult.setState( ContinuumBuildConstant.getBuildState( context ) );
+        buildResult.setTrigger( ContinuumBuildConstant.getTrigger( context ) );
+        buildResult.setUsername( ContinuumBuildConstant.getUsername( context ) );
+        buildResult.setBuildUrl( ContinuumBuildConstant.getBuildAgentUrl( context ) );
+
+        return buildResult;
+    }
+
+    public List<ProjectDependency> getModifiedDependencies( BuildResult oldBuildResult, Map<String, Object> context )
+        throws ContinuumException
+    {
+        if ( oldBuildResult == null )
+        {
+            return null;
+        }
+
+        try
+        {
+            Project project = projectDao.getProjectWithAllDetails( ContinuumBuildConstant.getProjectId( context ) );
+            List<ProjectDependency> dependencies = project.getDependencies();
+
+            if ( dependencies == null )
+            {
+                dependencies = new ArrayList<ProjectDependency>();
+            }
+
+            if ( project.getParent() != null )
+            {
+                dependencies.add( project.getParent() );
+            }
+
+            if ( dependencies.isEmpty() )
+            {
+                return null;
+            }
+
+            List<ProjectDependency> modifiedDependencies = new ArrayList<ProjectDependency>();
+
+            for ( ProjectDependency dep : dependencies )
+            {
+                Project dependencyProject = projectDao.getProject( dep.getGroupId(), dep.getArtifactId(),
+                                                                   dep.getVersion() );
+
+                if ( dependencyProject != null )
+                {
+                    long nbBuild = buildResultDao.getNbBuildResultsInSuccessForProject( dependencyProject.getId(),
+                                                                                        oldBuildResult.getEndTime() );
+                    if ( nbBuild > 0 )
+                    {
+                        log.debug( "Dependency changed: " + dep.getGroupId() + ":" + dep.getArtifactId() + ":" +
+                                       dep.getVersion() );
+                        modifiedDependencies.add( dep );
+                    }
+                    else
+                    {
+                        log.debug( "Dependency not changed: " + dep.getGroupId() + ":" + dep.getArtifactId() + ":" +
+                                       dep.getVersion() );
+                    }
+                }
+                else
+                {
+                    log.debug( "Skip non Continuum project: " + dep.getGroupId() + ":" + dep.getArtifactId() + ":" +
+                                   dep.getVersion() );
+                }
+            }
+
+            return modifiedDependencies;
+        }
+        catch ( ContinuumStoreException e )
+        {
+            log.warn( "Can't get the project dependencies", e );
+        }
+
+        return null;
+    }
+
+    public ScmResult getScmResult( Map<String, Object> context )
+    {
+        Map<String, Object> map = ContinuumBuildConstant.getScmResult( context );
+
+        if ( !map.isEmpty() )
+        {
+            ScmResult scmResult = new ScmResult();
+            scmResult.setCommandLine( ContinuumBuildConstant.getScmCommandLine( map ) );
+            scmResult.setCommandOutput( ContinuumBuildConstant.getScmCommandOutput( map ) );
+            scmResult.setException( ContinuumBuildConstant.getScmException( map ) );
+            scmResult.setProviderMessage( ContinuumBuildConstant.getScmProviderMessage( map ) );
+            scmResult.setSuccess( ContinuumBuildConstant.isScmSuccess( map ) );
+            scmResult.setChanges( getScmChanges( map ) );
+
+            return scmResult;
+        }
+
+        return null;
+    }
+
+    public List<ChangeSet> getScmChanges( Map<String, Object> context )
+    {
+        List<ChangeSet> changes = new ArrayList<ChangeSet>();
+        List<Map<String, Object>> scmChanges = ContinuumBuildConstant.getScmChanges( context );
+
+        if ( scmChanges != null )
+        {
+            for ( Map<String, Object> map : scmChanges )
+            {
+                ChangeSet changeSet = new ChangeSet();
+                changeSet.setAuthor( ContinuumBuildConstant.getChangeSetAuthor( map ) );
+                changeSet.setComment( ContinuumBuildConstant.getChangeSetComment( map ) );
+                changeSet.setDate( ContinuumBuildConstant.getChangeSetDate( map ) );
+                setChangeFiles( changeSet, map );
+                changes.add( changeSet );
+            }
+        }
+
+        return changes;
+    }
+
+    private void setChangeFiles( ChangeSet changeSet, Map<String, Object> context )
+    {
+        List<Map<String, Object>> changeFiles = ContinuumBuildConstant.getChangeSetFiles( context );
+
+        if ( changeFiles != null )
+        {
+            for ( Map<String, Object> map : changeFiles )
+            {
+                ChangeFile changeFile = new ChangeFile();
+                changeFile.setName( ContinuumBuildConstant.getChangeFileName( map ) );
+                changeFile.setRevision( ContinuumBuildConstant.getChangeFileRevision( map ) );
+                changeFile.setStatus( ContinuumBuildConstant.getChangeFileStatus( map ) );
+
+                changeSet.addFile( changeFile );
+            }
+        }
+    }
+}
diff --git a/continuum-core/src/main/java/org/apache/continuum/builder/distributed/work/DefaultContinuumWorker.java b/continuum-core/src/main/java/org/apache/continuum/builder/distributed/work/DefaultContinuumWorker.java
new file mode 100644
index 0000000..c92341b
--- /dev/null
+++ b/continuum-core/src/main/java/org/apache/continuum/builder/distributed/work/DefaultContinuumWorker.java
@@ -0,0 +1,222 @@
+package org.apache.continuum.builder.distributed.work;
+
+/*
+ * 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 org.apache.continuum.builder.distributed.manager.DistributedBuildManager;
+import org.apache.continuum.dao.BuildDefinitionDao;
+import org.apache.continuum.dao.BuildResultDao;
+import org.apache.continuum.dao.ProjectDao;
+import org.apache.continuum.dao.ProjectScmRootDao;
+import org.apache.continuum.model.project.ProjectRunSummary;
+import org.apache.continuum.model.project.ProjectScmRoot;
+import org.apache.maven.continuum.configuration.ConfigurationService;
+import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.BuildResult;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.project.ContinuumProjectState;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @plexus.component role="org.apache.continuum.builder.distributed.work.ContinuumWorker"
+ */
+public class DefaultContinuumWorker
+    implements ContinuumWorker
+{
+    private static final Logger log = LoggerFactory.getLogger( DefaultContinuumWorker.class );
+
+    /**
+     * @plexus.requirement
+     */
+    private ProjectDao projectDao;
+
+    /**
+     * @plexus.requirement
+     */
+    private ProjectScmRootDao projectScmRootDao;
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildDefinitionDao buildDefinitionDao;
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildResultDao buildResultDao;
+
+    /**
+     * @plexus.requirement
+     */
+    private DistributedBuildManager distributedBuildManager;
+
+    /**
+     * @plexus.requirement
+     */
+    private ConfigurationService configurationService;
+
+    public synchronized void work()
+    {
+        if ( !configurationService.isDistributedBuildEnabled() )
+        {
+            return;
+        }
+
+        log.debug( "Start continuum worker..." );
+
+        List<ProjectRunSummary> currentRuns = new ArrayList<ProjectRunSummary>(
+            distributedBuildManager.getCurrentRuns() );
+        List<ProjectRunSummary> runsToDelete = new ArrayList<ProjectRunSummary>();
+
+        synchronized ( currentRuns )
+        {
+            for ( ProjectRunSummary currentRun : currentRuns )
+            {
+                try
+                {
+                    // check for scm update
+                    ProjectScmRoot scmRoot = projectScmRootDao.getProjectScmRoot( currentRun.getProjectScmRootId() );
+
+                    if ( scmRoot != null && scmRoot.getState() == ContinuumProjectState.UPDATING )
+                    {
+                        // check if it's still updating
+                        if ( !distributedBuildManager.isProjectCurrentlyPreparingBuild( currentRun.getProjectId(),
+                                                                                        currentRun.getBuildDefinitionId() ) )
+                        {
+                            // no longer updating, but state was not updated.
+                            scmRoot.setState( ContinuumProjectState.ERROR );
+                            scmRoot.setError(
+                                "Problem encountered while returning scm update result to master by build agent '" +
+                                    currentRun.getBuildAgentUrl() + "'. \n" +
+                                    "Make sure build agent is configured properly. Check the logs for more information." );
+                            projectScmRootDao.updateProjectScmRoot( scmRoot );
+
+                            log.debug(
+                                "projectId={}, buildDefinitionId={} is not updating anymore. Problem encountered while return scm update result by build agent {}. Stopping the build.",
+                                new Object[]{currentRun.getProjectId(), currentRun.getBuildDefinitionId(),
+                                    currentRun.getBuildAgentUrl()} );
+                            runsToDelete.add( currentRun );
+                        }
+                    }
+                    else if ( scmRoot != null && scmRoot.getState() == ContinuumProjectState.ERROR )
+                    {
+                        log.debug(
+                            "projectId={}, buildDefinitionId={} is not updating anymore. Problem encountered while return scm update result by build agent {}. Stopping the build.",
+                            new Object[]{currentRun.getProjectId(), currentRun.getBuildDefinitionId(),
+                                currentRun.getBuildAgentUrl()} );
+                        runsToDelete.add( currentRun );
+                    }
+                    else
+                    {
+                        Project project = projectDao.getProject( currentRun.getProjectId() );
+
+                        if ( project != null && project.getState() == ContinuumProjectState.BUILDING )
+                        {
+                            // check if it's still building
+                            if ( !distributedBuildManager.isProjectCurrentlyBuilding( currentRun.getProjectId(),
+                                                                                      currentRun.getBuildDefinitionId() ) )
+                            {
+                                BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition(
+                                    currentRun.getBuildDefinitionId() );
+
+                                // no longer building, but state was not updated
+                                BuildResult buildResult = new BuildResult();
+                                buildResult.setBuildDefinition( buildDefinition );
+                                buildResult.setBuildUrl( currentRun.getBuildAgentUrl() );
+                                buildResult.setTrigger( currentRun.getTrigger() );
+                                buildResult.setUsername( currentRun.getTriggeredBy() );
+                                buildResult.setState( ContinuumProjectState.ERROR );
+                                buildResult.setSuccess( false );
+                                buildResult.setStartTime( new Date().getTime() );
+                                buildResult.setEndTime( new Date().getTime() );
+                                buildResult.setExitCode( 1 );
+                                buildResult.setError(
+                                    "Problem encountered while returning build result to master by build agent '" +
+                                        currentRun.getBuildAgentUrl() + "'. \n" +
+                                        "Make sure build agent is configured properly. Check the logs for more information." );
+                                buildResultDao.addBuildResult( project, buildResult );
+
+                                project.setState( ContinuumProjectState.ERROR );
+                                project.setLatestBuildId( buildResult.getId() );
+                                projectDao.updateProject( project );
+
+                                log.debug(
+                                    "projectId={}, buildDefinitionId={} is not building anymore. Problem encountered while return build result by build agent {}. Stopping the build.",
+                                    new Object[]{currentRun.getProjectId(), currentRun.getBuildDefinitionId(),
+                                        currentRun.getBuildAgentUrl()} );
+
+                                // create a build result
+                                runsToDelete.add( currentRun );
+                            }
+                        }
+                    }
+                }
+                catch ( Exception e )
+                {
+                    log.error(
+                        "Unable to check if projectId={}, buildDefinitionId={} is still updating or building: {}",
+                        new Object[]{currentRun.getProjectId(), currentRun.getBuildDefinitionId(), e.getMessage()} );
+                }
+            }
+
+            if ( runsToDelete.size() > 0 )
+            {
+                distributedBuildManager.getCurrentRuns().removeAll( runsToDelete );
+            }
+        }
+
+        log.debug( "End continuum worker..." );
+    }
+
+    // for testing
+    public void setProjectDao( ProjectDao projectDao )
+    {
+        this.projectDao = projectDao;
+    }
+
+    public void setProjectScmRootDao( ProjectScmRootDao projectScmRootDao )
+    {
+        this.projectScmRootDao = projectScmRootDao;
+    }
+
+    public void setBuildDefinitionDao( BuildDefinitionDao buildDefinitionDao )
+    {
+        this.buildDefinitionDao = buildDefinitionDao;
+    }
+
+    public void setBuildResultDao( BuildResultDao buildResultDao )
+    {
+        this.buildResultDao = buildResultDao;
+    }
+
+    public void setConfigurationService( ConfigurationService configurationService )
+    {
+        this.configurationService = configurationService;
+    }
+
+    public void setDistributedBuildManager( DistributedBuildManager distributedBuildManager )
+    {
+        this.distributedBuildManager = distributedBuildManager;
+    }
+}
diff --git a/continuum-core/src/main/java/org/apache/continuum/buildmanager/ParallelBuildsManager.java b/continuum-core/src/main/java/org/apache/continuum/buildmanager/ParallelBuildsManager.java
new file mode 100644
index 0000000..3d43531
--- /dev/null
+++ b/continuum-core/src/main/java/org/apache/continuum/buildmanager/ParallelBuildsManager.java
@@ -0,0 +1,1819 @@
+package org.apache.continuum.buildmanager;
+
+/*
+ * 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.io.File;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Resource;
+
+import org.apache.continuum.buildqueue.BuildQueueService;
+import org.apache.continuum.buildqueue.BuildQueueServiceException;
+import org.apache.continuum.dao.BuildDefinitionDao;
+import org.apache.continuum.dao.ProjectDao;
+import org.apache.continuum.taskqueue.BuildProjectTask;
+import org.apache.continuum.taskqueue.CheckOutTask;
+import org.apache.continuum.taskqueue.OverallBuildQueue;
+import org.apache.continuum.taskqueue.PrepareBuildProjectsTask;
+import org.apache.continuum.taskqueueexecutor.ParallelBuildsThreadedTaskQueueExecutor;
+import org.apache.continuum.utils.build.BuildTrigger;
+import org.apache.maven.continuum.configuration.ConfigurationService;
+import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.BuildQueue;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.scm.ScmResult;
+import org.apache.maven.continuum.store.ContinuumStoreException;
+import org.codehaus.plexus.PlexusConstants;
+import org.codehaus.plexus.PlexusContainer;
+import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
+import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+import org.codehaus.plexus.context.Context;
+import org.codehaus.plexus.context.ContextException;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.StoppingException;
+import org.codehaus.plexus.taskqueue.TaskQueue;
+import org.codehaus.plexus.taskqueue.TaskQueueException;
+import org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor;
+import org.codehaus.plexus.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Parallel builds manager.
+ *
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ * @version $Id$
+ */
+public class ParallelBuildsManager
+    implements BuildsManager, Contextualizable
+{
+    private static final Logger log = LoggerFactory.getLogger( ParallelBuildsManager.class );
+
+    // map must be synchronized!
+    private Map<Integer, OverallBuildQueue> overallBuildQueues = Collections.synchronizedMap(
+        new HashMap<Integer, OverallBuildQueue>() );
+
+    private static final int BUILD_QUEUE = 1;
+
+    private static final int CHECKOUT_QUEUE = 2;
+
+    private static final int PREPARE_BUILD_QUEUE = 3;
+
+    @Resource
+    private BuildDefinitionDao buildDefinitionDao;
+
+    @Resource
+    private ProjectDao projectDao;
+
+    @Resource
+    private ConfigurationService configurationService;
+
+    @Resource
+    private BuildQueueService buildQueueService;
+
+    private PlexusContainer container;
+
+    /**
+     * @see BuildsManager#buildProject(int, BuildDefinition, String, BuildTrigger, ScmResult, int)
+     */
+    public void buildProject( int projectId, BuildDefinition buildDefinition, String projectName,
+                              BuildTrigger buildTrigger, ScmResult scmResult, int projectGroupId )
+        throws BuildManagerException
+    {
+        try
+        {
+            if ( isInQueue( projectId, BUILD_QUEUE, -1 ) )
+            {
+                log.warn( "Project already queued." );
+                return;
+            }
+            else if ( isProjectInAnyCurrentBuild( projectId ) )
+            {
+                log.warn( "Project is already building." );
+                return;
+            }
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException(
+                "Error occurred while checking if the project is already in queue: " + e.getMessage() );
+        }
+
+        OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectsInGroupAreQueued( projectGroupId );
+
+        if ( overallBuildQueue == null )
+        {
+            overallBuildQueue = getOverallBuildQueue( BUILD_QUEUE, buildDefinition.getSchedule().getBuildQueues() );
+        }
+
+        if ( overallBuildQueue != null )
+        {
+            String buildDefinitionLabel = buildDefinition.getDescription();
+
+            if ( StringUtils.isEmpty( buildDefinitionLabel ) )
+            {
+                buildDefinitionLabel = buildDefinition.getGoals();
+            }
+
+            BuildProjectTask buildTask = new BuildProjectTask( projectId, buildDefinition.getId(), buildTrigger,
+                                                               projectName, buildDefinitionLabel, scmResult,
+                                                               projectGroupId );
+            try
+            {
+                log.info( "Project '" + projectName + "' added to overall build queue '" + overallBuildQueue.getName() +
+                              "'." );
+                overallBuildQueue.addToBuildQueue( buildTask );
+            }
+            catch ( TaskQueueException e )
+            {
+                throw new BuildManagerException(
+                    "Error occurred while adding project to build queue: " + e.getMessage() );
+            }
+        }
+        else
+        {
+            log.warn( "No build queue configured. Not building." );
+        }
+    }
+
+    /**
+     * @see BuildsManager#buildProjects(List, Map, BuildTrigger, Map, int)
+     */
+    public void buildProjects( List<Project> projects, Map<Integer, BuildDefinition> projectsBuildDefinitionsMap,
+                               BuildTrigger buildTrigger, Map<Integer, ScmResult> scmResultMap, int projectGroupId )
+        throws BuildManagerException
+    {
+        Project firstBuildableProject = null;
+        // get id of the first project in the list that is not yet in the build queue
+        for ( Project project : projects )
+        {
+            try
+            {
+                if ( !isInQueue( project.getId(), BUILD_QUEUE, -1 ) && !isProjectInAnyCurrentBuild( project.getId() ) )
+                {
+                    firstBuildableProject = project;
+                    break;
+                }
+            }
+            catch ( TaskQueueException e )
+            {
+                log.warn( "Error occurred while verifying if project is already queued." );
+            }
+        }
+
+        boolean projectsToBuild = firstBuildableProject != null;
+
+        if ( projectsToBuild )
+        {
+            BuildDefinition buildDef = projectsBuildDefinitionsMap.get( firstBuildableProject.getId() );
+
+            if ( buildDef.getSchedule() == null )
+            {
+                String msg = String.format( "Invalid data, null schedule for builddef id=%s/project id=%s",
+                                            buildDef.getId(), firstBuildableProject.getId() );
+                log.error( msg );
+                throw new BuildManagerException( msg + ", please notify your system adminitrator" );
+            }
+            OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectsInGroupAreQueued( projectGroupId );
+
+            if ( overallBuildQueue == null )
+            {
+                overallBuildQueue = getOverallBuildQueue( BUILD_QUEUE, buildDef.getSchedule().getBuildQueues() );
+            }
+
+            if ( overallBuildQueue != null )
+            {
+                for ( Project project : projects )
+                {
+                    try
+                    {
+                        if ( isInQueue( project.getId(), BUILD_QUEUE, projectsBuildDefinitionsMap.get(
+                            project.getId() ).getId() ) )
+                        {
+                            log.warn( "Project '" + project.getId() + "' - '" + project.getName() +
+                                          "' is already in build queue." );
+                            continue;
+                        }
+                        else if ( isProjectInAnyCurrentBuild( project.getId() ) )
+                        {
+                            log.warn( "Project '" + project.getId() + "' - '" + project.getName() +
+                                          "' is already building." );
+                            continue;
+                        }
+                    }
+                    catch ( TaskQueueException e )
+                    {
+                        log.warn( "Error occurred while verifying if project is already queued." );
+                        continue;
+                    }
+
+                    BuildDefinition buildDefinition = projectsBuildDefinitionsMap.get( project.getId() );
+                    String buildDefinitionLabel = buildDefinition.getDescription();
+                    if ( StringUtils.isEmpty( buildDefinitionLabel ) )
+                    {
+                        buildDefinitionLabel = buildDefinition.getGoals();
+                    }
+
+                    ScmResult scmResult = scmResultMap.get( project.getId() );
+                    BuildProjectTask buildTask = new BuildProjectTask( project.getId(), buildDefinition.getId(),
+                                                                       buildTrigger, project.getName(),
+                                                                       buildDefinitionLabel, scmResult,
+                                                                       projectGroupId );
+
+                    if ( buildDefinition.getSchedule() == null )
+                    {
+                        log.warn( String.format( "Invalid data, null schedule for builddef id=%s/project id=%s",
+                                                 buildDef.getId(), project.getId() ) );
+                    }
+                    else
+                    {
+                        buildTask.setMaxExecutionTime( buildDefinition.getSchedule().getMaxJobExecutionTime() * 1000 );
+                    }
+
+                    try
+                    {
+                        log.info( "Project '" + project.getId() + "' - '" + project.getName() +
+                                      "' added to overall build queue '" + overallBuildQueue.getName() + "'." );
+
+                        overallBuildQueue.addToBuildQueue( buildTask );
+                    }
+                    catch ( TaskQueueException e )
+                    {
+                        throw new BuildManagerException(
+                            "Error occurred while adding project to build queue: " + e.getMessage() );
+                    }
+                }
+            }
+            else
+            {
+                log.warn( "No build queue configured. Not building" );
+            }
+        }
+        else
+        {
+            log.error( "Projects are already in build queue." );
+        }
+    }
+
+    /**
+     * @see BuildsManager#cancelBuildInQueue(int)
+     */
+    public boolean cancelBuildInQueue( int buildQueueId )
+        throws BuildManagerException
+    {
+        synchronized ( overallBuildQueues )
+        {
+            OverallBuildQueue overallBuildQueue;
+            overallBuildQueue = overallBuildQueues.get( buildQueueId );
+            if ( overallBuildQueue != null )
+            {
+                overallBuildQueue.cancelCurrentBuild();
+            }
+            else
+            {
+                log.warn( "Project not found in any of the build queues." );
+            }
+
+            return true;
+        }
+    }
+
+    /**
+     * @see BuildsManager#cancelAllBuilds()
+     */
+    public boolean cancelAllBuilds()
+        throws BuildManagerException
+    {
+        synchronized ( overallBuildQueues )
+        {
+            Set<Integer> keySet = overallBuildQueues.keySet();
+            OverallBuildQueue overallBuildQueue = null;
+            for ( Integer key : keySet )
+            {
+                overallBuildQueue = overallBuildQueues.get( key );
+                overallBuildQueue.cancelCurrentBuild();
+            }
+
+            return true;
+        }
+    }
+
+    /**
+     * @see BuildsManager#cancelAllCheckouts()
+     */
+    public boolean cancelAllCheckouts()
+        throws BuildManagerException
+    {
+        synchronized ( overallBuildQueues )
+        {
+            Set<Integer> keySet = overallBuildQueues.keySet();
+            OverallBuildQueue overallBuildQueue;
+            for ( Integer key : keySet )
+            {
+                overallBuildQueue = overallBuildQueues.get( key );
+                overallBuildQueue.cancelCurrentCheckout();
+            }
+
+            return true;
+        }
+    }
+
+    /**
+     * @see BuildsManager#cancelBuild(int)
+     */
+    public boolean cancelBuild( int projectId )
+        throws BuildManagerException
+    {
+        try
+        {
+            OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId, BUILD_QUEUE );
+            if ( overallBuildQueue != null )
+            {
+                overallBuildQueue.cancelBuildTask( projectId );
+            }
+            else
+            {
+                synchronized ( overallBuildQueues )
+                {
+                    Set<Integer> keySet = overallBuildQueues.keySet();
+                    for ( Integer key : keySet )
+                    {
+                        overallBuildQueue = overallBuildQueues.get( key );
+                        BuildProjectTask buildTask =
+                            (BuildProjectTask) overallBuildQueue.getBuildTaskQueueExecutor().getCurrentTask();
+                        if ( buildTask != null && buildTask.getProjectId() == projectId )
+                        {
+                            overallBuildQueue.cancelBuildTask( projectId );
+                            return true;
+                        }
+                    }
+                    log.error( "Project '" + projectId + "' not found in any of the builds queues." );
+                }
+            }
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException( "Error occurred while cancelling build: " + e.getMessage() );
+        }
+
+        return true;
+    }
+
+    /**
+     * @see BuildsManager#cancelCheckout(int)
+     */
+    public boolean cancelCheckout( int projectId )
+        throws BuildManagerException
+    {
+        try
+        {
+            OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId, CHECKOUT_QUEUE );
+            if ( overallBuildQueue != null )
+            {
+                overallBuildQueue.cancelCheckoutTask( projectId );
+            }
+            else
+            {
+                synchronized ( overallBuildQueues )
+                {
+                    Set<Integer> keySet = overallBuildQueues.keySet();
+                    for ( Integer key : keySet )
+                    {
+                        overallBuildQueue = overallBuildQueues.get( key );
+                        CheckOutTask checkoutTask =
+                            (CheckOutTask) overallBuildQueue.getCheckoutTaskQueueExecutor().getCurrentTask();
+                        if ( checkoutTask != null && checkoutTask.getProjectId() == projectId )
+                        {
+                            overallBuildQueue.cancelCheckoutTask( projectId );
+                            return true;
+                        }
+                    }
+                    log.info( "Project '" + projectId + "' not found in any of the checkout queues." );
+                }
+            }
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException( "Error occurred while cancelling build: " + e.getMessage() );
+        }
+
+        return true;
+    }
+
+    public boolean cancelPrepareBuild( int projectGroupId, int scmRootId )
+        throws BuildManagerException
+    {
+        try
+        {
+            OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectGroupIsQueued( projectGroupId,
+                                                                                                 scmRootId );
+
+            if ( overallBuildQueue != null )
+            {
+                overallBuildQueue.cancelPrepareBuildTask( projectGroupId, scmRootId );
+            }
+            else
+            {
+                synchronized ( overallBuildQueues )
+                {
+                    Set<Integer> keySet = overallBuildQueues.keySet();
+                    for ( Integer key : keySet )
+                    {
+                        overallBuildQueue = overallBuildQueues.get( key );
+                        PrepareBuildProjectsTask task =
+                            (PrepareBuildProjectsTask) overallBuildQueue.getPrepareBuildTaskQueueExecutor().getCurrentTask();
+                        if ( task != null && task.getProjectGroupId() == projectGroupId &&
+                            task.getProjectScmRootId() == scmRootId )
+                        {
+                            overallBuildQueue.cancelPrepareBuildTask( projectGroupId, scmRootId );
+                            return true;
+                        }
+                    }
+                    log.error( "Project group '{}' with scm root '{}' not found in any of the builds queues.",
+                               projectGroupId, scmRootId );
+                }
+            }
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException( "Error occurred while cancelling build: " + e.getMessage() );
+        }
+
+        return true;
+    }
+
+    public boolean cancelPrepareBuild( int projectId )
+        throws BuildManagerException
+    {
+        try
+        {
+            OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId,
+                                                                                            PREPARE_BUILD_QUEUE );
+
+            if ( overallBuildQueue != null )
+            {
+                overallBuildQueue.cancelPrepareBuildTask( projectId );
+            }
+            else
+            {
+                synchronized ( overallBuildQueues )
+                {
+                    Set<Integer> keySet = overallBuildQueues.keySet();
+                    for ( Integer key : keySet )
+                    {
+                        overallBuildQueue = overallBuildQueues.get( key );
+                        PrepareBuildProjectsTask task =
+                            (PrepareBuildProjectsTask) overallBuildQueue.getPrepareBuildTaskQueueExecutor().getCurrentTask();
+                        if ( task != null )
+                        {
+                            Map<Integer, Integer> map = task.getProjectsBuildDefinitionsMap();
+
+                            if ( map.size() > 0 )
+                            {
+                                Set<Integer> projectIds = map.keySet();
+
+                                if ( projectIds.contains( new Integer( projectId ) ) )
+                                {
+                                    overallBuildQueue.cancelPrepareBuildTask( projectId );
+                                    return true;
+                                }
+                            }
+                        }
+                    }
+                    log.error( "Project '{}' not found in any of the builds queues.", projectId );
+                }
+            }
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException( "Error occurred while cancelling build: " + e.getMessage() );
+        }
+
+        return true;
+    }
+
+    /**
+     * @see BuildsManager#checkoutProject(int, String, File, String, String, String, BuildDefinition, List)
+     */
+    public void checkoutProject( int projectId, String projectName, File workingDirectory, String scmRootUrl,
+                                 String scmUsername, String scmPassword, BuildDefinition defaultBuildDefinition,
+                                 List<Project> subProjects )
+        throws BuildManagerException
+    {
+        try
+        {
+            if ( isInQueue( projectId, CHECKOUT_QUEUE, -1 ) )
+            {
+                log.warn( "Project already in checkout queue." );
+                return;
+            }
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException(
+                "Error occurred while checking if the project is already in queue: " + e.getMessage() );
+        }
+
+        OverallBuildQueue overallBuildQueue = getOverallBuildQueue( CHECKOUT_QUEUE,
+                                                                    defaultBuildDefinition.getSchedule().getBuildQueues() );
+        CheckOutTask checkoutTask = new CheckOutTask( projectId, workingDirectory, projectName, scmUsername,
+                                                      scmPassword, scmRootUrl, subProjects );
+        try
+        {
+            if ( overallBuildQueue != null )
+            {
+                log.info( "Project '" + projectName + "' added to overall build queue '" + overallBuildQueue.getName() +
+                              "'." );
+                overallBuildQueue.addToCheckoutQueue( checkoutTask );
+            }
+            else
+            {
+                throw new BuildManagerException(
+                    "Unable to add project to checkout queue. No overall build queue configured." );
+            }
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException(
+                "Error occurred while adding project to checkout queue: " + e.getMessage() );
+        }
+    }
+
+    /**
+     * @see BuildsManager#isInAnyBuildQueue(int)
+     */
+    public boolean isInAnyBuildQueue( int projectId )
+        throws BuildManagerException
+    {
+        try
+        {
+            return isInQueue( projectId, BUILD_QUEUE, -1 );
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException( e.getMessage() );
+        }
+    }
+
+    /**
+     * @see BuildsManager#isInAnyBuildQueue(int, int)
+     */
+    public boolean isInAnyBuildQueue( int projectId, int buildDefinitionId )
+        throws BuildManagerException
+    {
+        try
+        {
+            return isInQueue( projectId, BUILD_QUEUE, buildDefinitionId );
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException( e.getMessage() );
+        }
+    }
+
+    /**
+     * @see BuildsManager#isInAnyCheckoutQueue(int)
+     */
+    public boolean isInAnyCheckoutQueue( int projectId )
+        throws BuildManagerException
+    {
+        try
+        {
+            return isInQueue( projectId, CHECKOUT_QUEUE, -1 );
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException( e.getMessage() );
+        }
+    }
+
+    /**
+     * @see BuildsManager#isAnyProjectCurrentlyBeingCheckedOut(int[])
+     */
+    public boolean isAnyProjectCurrentlyBeingCheckedOut( int[] projectIds )
+        throws BuildManagerException
+    {
+        for ( int projectId : projectIds )
+        {
+            Map<String, CheckOutTask> checkouts = getCurrentCheckouts();
+            Set<String> keySet = checkouts.keySet();
+            for ( String key : keySet )
+            {
+                CheckOutTask task = checkouts.get( key );
+                if ( task.getProjectId() == projectId )
+                {
+                    log.info( "Project " + projectId + " is currently being checked out" );
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * @see BuildsManager#isInPrepareBuildQueue(int)
+     */
+    public boolean isInPrepareBuildQueue( int projectId )
+        throws BuildManagerException
+    {
+        try
+        {
+            synchronized ( overallBuildQueues )
+            {
+                Set<Integer> keySet = overallBuildQueues.keySet();
+                for ( Integer key : keySet )
+                {
+                    OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
+
+                    if ( overallBuildQueue.isInPrepareBuildQueue( projectId ) )
+                    {
+                        return true;
+                    }
+                }
+
+                return false;
+            }
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException( "Unable to check if projectId " + projectId + " is in prepare build queue",
+                                             e );
+        }
+    }
+
+    /**
+     * @param projectGroupId
+     * @param scmRootId
+     * @return
+     * @see BuildsManager#isInPrepareBuildQueue(int, int)
+     */
+    public boolean isInPrepareBuildQueue( int projectGroupId, int scmRootId )
+        throws BuildManagerException
+    {
+        try
+        {
+            synchronized ( overallBuildQueues )
+            {
+                Set<Integer> keySet = overallBuildQueues.keySet();
+                for ( Integer key : keySet )
+                {
+                    OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
+
+                    if ( overallBuildQueue.isInPrepareBuildQueue( projectGroupId, scmRootId ) )
+                    {
+                        return true;
+                    }
+                }
+
+                return false;
+            }
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException(
+                "Unable to check if projectGroupId " + projectGroupId + " with scmRootId " + scmRootId +
+                    " is in prepare build queue", e );
+        }
+    }
+
+    /**
+     * @see BuildsManager#isProjectInAnyCurrentBuild(int)
+     */
+    public boolean isProjectInAnyCurrentBuild( int projectId )
+        throws BuildManagerException
+    {
+        synchronized ( overallBuildQueues )
+        {
+            Set<Integer> keys = overallBuildQueues.keySet();
+            for ( Integer key : keys )
+            {
+                OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
+                BuildProjectTask task =
+                    (BuildProjectTask) overallBuildQueue.getBuildTaskQueueExecutor().getCurrentTask();
+                if ( task != null && task.getProjectId() == projectId )
+                {
+                    log.info( "Project " + projectId + " is currently building in " + overallBuildQueue.getName() );
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    /**
+     * @see BuildsManager#prepareBuildProjects(Map, BuildTrigger, int, String, String, int)
+     */
+    public void prepareBuildProjects( Map<Integer, Integer> projectsBuildDefinitionsMap, BuildTrigger buildTrigger,
+                                      int projectGroupId, String projectGroupName, String scmRootAddress,
+                                      int scmRootId )
+        throws BuildManagerException
+    {
+        if ( isInPrepareBuildQueue( projectGroupId, scmRootId ) )
+        {
+            log.warn(
+                "Project group {} with scm root id {} is already in prepare build queue. Will not queue anymore." );
+            return;
+        }
+
+        Collection<Integer> buildDefs = projectsBuildDefinitionsMap.values();
+        BuildDefinition buildDef = null;
+
+        // get the first build definition
+        try
+        {
+            for ( Integer buildDefId : buildDefs )
+            {
+                buildDef = buildDefinitionDao.getBuildDefinition( buildDefId );
+            }
+        }
+        catch ( ContinuumStoreException e )
+        {
+            throw new BuildManagerException(
+                "Error occurred while retrieving build definition of project group " + projectGroupId, e );
+        }
+
+        OverallBuildQueue overallBuildQueue = getOverallBuildQueue( PREPARE_BUILD_QUEUE,
+                                                                    buildDef.getSchedule().getBuildQueues() );
+
+        PrepareBuildProjectsTask task = new PrepareBuildProjectsTask( projectsBuildDefinitionsMap, buildTrigger,
+                                                                      projectGroupId, projectGroupName, scmRootAddress,
+                                                                      scmRootId );
+
+        try
+        {
+            if ( overallBuildQueue != null )
+            {
+                log.info( "Project group '{}' added to overall build queue '{}'", projectGroupId,
+                          overallBuildQueue.getName() );
+                overallBuildQueue.addToPrepareBuildQueue( task );
+            }
+            else
+            {
+                throw new BuildManagerException(
+                    "Unable to add project to prepare build queue. No overall build queue configured." );
+            }
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException(
+                "Error occurred while adding project to prepare build queue: " + e.getMessage() );
+        }
+    }
+
+    /**
+     * @see BuildsManager#removeProjectFromBuildQueue(int)
+     */
+    public void removeProjectFromBuildQueue( int projectId )
+        throws BuildManagerException
+    {
+        try
+        {
+            OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId, BUILD_QUEUE );
+            if ( overallBuildQueue != null )
+            {
+                overallBuildQueue.removeProjectFromBuildQueue( projectId );
+            }
+            else
+            {
+                log.info( "Project '" + projectId + "' not found in any of the build queues." );
+            }
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException(
+                "Error occurred while removing project from build queue: " + e.getMessage() );
+        }
+    }
+
+    /**
+     * @see BuildsManager#removeProjectFromBuildQueue(int, int, BuildTrigger, String, int)
+     */
+    public void removeProjectFromBuildQueue( int projectId, int buildDefinitionId, BuildTrigger buildTrigger,
+                                             String projectName, int projectGroupId )
+        throws BuildManagerException
+    {
+        try
+        {
+            OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId, BUILD_QUEUE );
+            if ( overallBuildQueue != null )
+            {
+                overallBuildQueue.removeProjectFromBuildQueue( projectId, buildDefinitionId, buildTrigger, projectName,
+                                                               projectGroupId );
+            }
+            else
+            {
+                log.info( "Project '" + projectId + "' not found in any of the build queues." );
+            }
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException(
+                "Error occurred while removing project from build queue: " + e.getMessage() );
+        }
+    }
+
+    /**
+     * @see BuildsManager#removeProjectFromCheckoutQueue(int)
+     */
+    public void removeProjectFromCheckoutQueue( int projectId )
+        throws BuildManagerException
+    {
+        try
+        {
+            OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId, CHECKOUT_QUEUE );
+            if ( overallBuildQueue != null )
+            {
+                overallBuildQueue.removeProjectFromCheckoutQueue( projectId );
+            }
+            else
+            {
+                log.info( "Project '" + projectId + "' not found in any of the checkout queues." );
+            }
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException(
+                "Error occurred while removing project from checkout queue: " + e.getMessage() );
+        }
+    }
+
+    /**
+     * @see BuildsManager#removeProjectsFromBuildQueue(int[])
+     */
+    public void removeProjectsFromBuildQueue( int[] projectIds )
+    {
+        for ( int projectId : projectIds )
+        {
+            try
+            {
+                OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId,
+                                                                                                BUILD_QUEUE );
+                if ( overallBuildQueue != null )
+                {
+                    overallBuildQueue.removeProjectFromBuildQueue( projectId );
+                }
+                else
+                {
+                    log.error( "Project '" + projectId + "' not found in any of the build queues." );
+                }
+            }
+            catch ( TaskQueueException e )
+            {
+                log.error( "Error occurred while removing project '" + projectId + "' from build queue." );
+            }
+        }
+    }
+
+    /**
+     * @see BuildsManager#removeProjectsFromCheckoutQueue(int[])
+     */
+    public void removeProjectsFromCheckoutQueue( int[] projectIds )
+    {
+        for ( int projectId : projectIds )
+        {
+            try
+            {
+                OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId,
+                                                                                                CHECKOUT_QUEUE );
+                if ( overallBuildQueue != null )
+                {
+                    overallBuildQueue.removeProjectFromCheckoutQueue( projectId );
+                }
+                else
+                {
+                    log.error( "Project '" + projectId + "' not found in any of the checkout queues." );
+                }
+            }
+            catch ( TaskQueueException e )
+            {
+                log.error( "Error occurred while removing project '" + projectId + "' from checkout queue." );
+            }
+        }
+    }
+
+    /**
+     * @see BuildsManager#removeProjectsFromCheckoutQueueWithHashcodes(int[])
+     */
+    public void removeProjectsFromCheckoutQueueWithHashcodes( int[] hashcodes )
+        throws BuildManagerException
+    {
+        try
+        {
+            synchronized ( overallBuildQueues )
+            {
+                Set<Integer> keySet = overallBuildQueues.keySet();
+                for ( Integer key : keySet )
+                {
+                    OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
+                    overallBuildQueue.removeTasksFromCheckoutQueueWithHashCodes( hashcodes );
+                }
+            }
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException( "Error encountered while removing project(s) from checkout queue.", e );
+        }
+    }
+
+    /**
+     * @see BuildsManager#removeProjectsFromBuildQueueWithHashcodes(int[])
+     */
+    public void removeProjectsFromBuildQueueWithHashcodes( int[] hashcodes )
+        throws BuildManagerException
+    {
+        try
+        {
+            synchronized ( overallBuildQueues )
+            {
+                Set<Integer> keySet = overallBuildQueues.keySet();
+                for ( Integer key : keySet )
+                {
+                    OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
+                    overallBuildQueue.removeProjectsFromBuildQueueWithHashCodes( hashcodes );
+                }
+            }
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException( "Error encountered while removing project(s) from build queue.", e );
+        }
+    }
+
+    public boolean removeProjectGroupFromPrepareBuildQueue( int projectGroupId, String scmRootAddress )
+        throws BuildManagerException
+    {
+        try
+        {
+            OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectGroupIsQueued( projectGroupId,
+                                                                                                 scmRootAddress );
+            if ( overallBuildQueue != null )
+            {
+                overallBuildQueue.removeProjectFromPrepareBuildQueue( projectGroupId, scmRootAddress );
+            }
+            else
+            {
+                log.info( "Project group '{}' with scm '{}' not found in any of the build queues.", projectGroupId,
+                          scmRootAddress );
+            }
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException(
+                "Error occurred while removing project group from prepare build queue: " + e.getMessage() );
+        }
+
+        return true;
+    }
+
+    /**
+     * @see BuildsManager#addOverallBuildQueue(BuildQueue)
+     */
+    public void addOverallBuildQueue( BuildQueue buildQueue )
+        throws BuildManagerException
+    {
+        synchronized ( overallBuildQueues )
+        {
+            try
+            {
+                OverallBuildQueue overallBuildQueue = (OverallBuildQueue) container.lookup( OverallBuildQueue.class );
+                overallBuildQueue.setId( buildQueue.getId() );
+                overallBuildQueue.setName( buildQueue.getName() );
+
+                if ( overallBuildQueues.get( buildQueue.getId() ) == null )
+                {
+                    log.info( "Adding overall build queue to map : " + overallBuildQueue.getName() );
+                    overallBuildQueues.put( overallBuildQueue.getId(), overallBuildQueue );
+                }
+                else
+                {
+                    log.warn( "Overall build queue already in the map." );
+                }
+            }
+            catch ( ComponentLookupException e )
+            {
+                throw new BuildManagerException( "Error creating overall build queue.", e );
+            }
+        }
+    }
+
+    /**
+     * @see BuildsManager#removeOverallBuildQueue(int)
+     */
+    public void removeOverallBuildQueue( int overallBuildQueueId )
+        throws BuildManagerException
+    {
+        List<BuildProjectTask> tasks;
+        List<CheckOutTask> checkoutTasks;
+        List<PrepareBuildProjectsTask> prepareBuildTasks;
+
+        synchronized ( overallBuildQueues )
+        {
+            OverallBuildQueue overallBuildQueue = overallBuildQueues.get( overallBuildQueueId );
+            if ( overallBuildQueue.getName().equals( ConfigurationService.DEFAULT_BUILD_QUEUE_NAME ) )
+            {
+                throw new BuildManagerException( "Cannot remove default build queue." );
+            }
+
+            try
+            {
+                if ( overallBuildQueue.getBuildTaskQueueExecutor().getCurrentTask() != null ||
+                    overallBuildQueue.getCheckoutTaskQueueExecutor().getCurrentTask() != null ||
+                    overallBuildQueue.getPrepareBuildTaskQueueExecutor().getCurrentTask() != null )
+                {
+                    throw new BuildManagerException( "Cannot remove build queue. A task is currently executing." );
+                }
+
+                tasks = overallBuildQueue.getProjectsInBuildQueue();
+                checkoutTasks = overallBuildQueue.getProjectsInCheckoutQueue();
+                prepareBuildTasks = overallBuildQueue.getProjectsInPrepareBuildQueue();
+
+                overallBuildQueue.getBuildQueue().removeAll( tasks );
+                overallBuildQueue.getCheckoutQueue().removeAll( checkoutTasks );
+                overallBuildQueue.getPrepareBuildQueue().removeAll( prepareBuildTasks );
+
+                ( (ParallelBuildsThreadedTaskQueueExecutor) overallBuildQueue.getBuildTaskQueueExecutor() ).stop();
+                ( (ParallelBuildsThreadedTaskQueueExecutor) overallBuildQueue.getCheckoutTaskQueueExecutor() ).stop();
+                ( (ParallelBuildsThreadedTaskQueueExecutor) overallBuildQueue.getPrepareBuildTaskQueueExecutor() ).stop();
+                container.release( overallBuildQueue );
+            }
+            catch ( TaskQueueException e )
+            {
+                throw new BuildManagerException(
+                    "Cannot remove build queue. An error occurred while retrieving queued tasks." );
+            }
+            catch ( ComponentLifecycleException e )
+            {
+                throw new BuildManagerException(
+                    "Cannot remove build queue. An error occurred while destroying the build queue: " +
+                        e.getMessage() );
+            }
+            catch ( StoppingException e )
+            {
+                throw new BuildManagerException(
+                    "Cannot remove build queue. An error occurred while stopping the build queue: " + e.getMessage() );
+            }
+
+            this.overallBuildQueues.remove( overallBuildQueueId );
+            log.info( "Removed overall build queue '" + overallBuildQueueId + "' from build queues map." );
+        }
+
+        for ( BuildProjectTask buildTask : tasks )
+        {
+            try
+            {
+                BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition(
+                    buildTask.getBuildDefinitionId() );
+
+                buildProject( buildTask.getProjectId(), buildDefinition, buildTask.getProjectName(),
+                              buildTask.getBuildTrigger(), buildTask.getScmResult(), buildTask.getProjectGroupId() );
+            }
+            catch ( ContinuumStoreException e )
+            {
+                log.error( "Unable to queue build task for project '" + buildTask.getProjectName() + "'" );
+            }
+        }
+
+        for ( CheckOutTask task : checkoutTasks )
+        {
+            try
+            {
+                BuildDefinition buildDefinition = buildDefinitionDao.getDefaultBuildDefinition( task.getProjectId() );
+                checkoutProject( task.getProjectId(), task.getProjectName(), task.getWorkingDirectory(),
+                                 task.getScmRootUrl(), task.getScmUserName(), task.getScmPassword(), buildDefinition,
+                                 task.getProjectsWithCommonScmRoot() );
+            }
+            catch ( ContinuumStoreException e )
+            {
+                log.error( "Unable to queue checkout task for project '" + task.getProjectName() + "'" );
+            }
+        }
+
+        for ( PrepareBuildProjectsTask prepareTask : prepareBuildTasks )
+        {
+            prepareBuildProjects( prepareTask.getProjectsBuildDefinitionsMap(), prepareTask.getBuildTrigger(),
+                                  prepareTask.getProjectGroupId(), prepareTask.getProjectGroupName(),
+                                  prepareTask.getScmRootAddress(), prepareTask.getProjectScmRootId() );
+        }
+    }
+
+    public Map<Integer, OverallBuildQueue> getOverallBuildQueues()
+    {
+        return overallBuildQueues;
+    }
+
+    /**
+     * @see BuildsManager#getCurrentBuilds()
+     */
+    public Map<String, BuildProjectTask> getCurrentBuilds()
+        throws BuildManagerException
+    {
+        synchronized ( overallBuildQueues )
+        {
+            Map<String, BuildProjectTask> currentBuilds = new HashMap<String, BuildProjectTask>();
+            Set<Integer> keys = overallBuildQueues.keySet();
+            for ( Integer key : keys )
+            {
+                OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
+                BuildProjectTask task =
+                    (BuildProjectTask) overallBuildQueue.getBuildTaskQueueExecutor().getCurrentTask();
+                if ( task != null )
+                {
+                    currentBuilds.put( overallBuildQueue.getName(), task );
+                }
+            }
+            return currentBuilds;
+        }
+    }
+
+    /**
+     * @see BuildsManager#getCurrentCheckouts()
+     */
+    public Map<String, CheckOutTask> getCurrentCheckouts()
+        throws BuildManagerException
+    {
+        synchronized ( overallBuildQueues )
+        {
+            Map<String, CheckOutTask> currentCheckouts = new HashMap<String, CheckOutTask>();
+            Set<Integer> keys = overallBuildQueues.keySet();
+            for ( Integer key : keys )
+            {
+                OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
+                CheckOutTask task = (CheckOutTask) overallBuildQueue.getCheckoutTaskQueueExecutor().getCurrentTask();
+                if ( task != null )
+                {
+                    currentCheckouts.put( overallBuildQueue.getName(), task );
+                }
+            }
+            return currentCheckouts;
+        }
+    }
+
+    /**
+     * @see BuildsManager#getProjectsInBuildQueues()
+     */
+    public Map<String, List<BuildProjectTask>> getProjectsInBuildQueues()
+        throws BuildManagerException
+    {
+        synchronized ( overallBuildQueues )
+        {
+            Map<String, List<BuildProjectTask>> queuedBuilds = new HashMap<String, List<BuildProjectTask>>();
+            Set<Integer> keySet = overallBuildQueues.keySet();
+            for ( Integer key : keySet )
+            {
+                OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
+                try
+                {
+                    queuedBuilds.put( overallBuildQueue.getName(), overallBuildQueue.getProjectsInBuildQueue() );
+                }
+                catch ( TaskQueueException e )
+                {
+                    throw new BuildManagerException(
+                        "Error occurred while getting projects in build queue '" + overallBuildQueue.getName() + "'.",
+                        e );
+                }
+            }
+            return queuedBuilds;
+        }
+    }
+
+    /**
+     * @see BuildsManager#getProjectsInCheckoutQueues()
+     */
+    public Map<String, List<CheckOutTask>> getProjectsInCheckoutQueues()
+        throws BuildManagerException
+    {
+        synchronized ( overallBuildQueues )
+        {
+            Map<String, List<CheckOutTask>> queuedCheckouts = new HashMap<String, List<CheckOutTask>>();
+            Set<Integer> keySet = overallBuildQueues.keySet();
+            for ( Integer key : keySet )
+            {
+                OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
+                try
+                {
+                    queuedCheckouts.put( overallBuildQueue.getName(), overallBuildQueue.getProjectsInCheckoutQueue() );
+                }
+                catch ( TaskQueueException e )
+                {
+                    throw new BuildManagerException(
+                        "Error occurred while getting projects in build queue '" + overallBuildQueue.getName() + "'.",
+                        e );
+                }
+            }
+            return queuedCheckouts;
+        }
+    }
+
+    /**
+     * @see BuildsManager#cancelAllPrepareBuilds()
+     */
+    public boolean cancelAllPrepareBuilds()
+        throws BuildManagerException
+    {
+        synchronized ( overallBuildQueues )
+        {
+            Set<Integer> keySet = overallBuildQueues.keySet();
+            OverallBuildQueue overallBuildQueue = null;
+            for ( Integer key : keySet )
+            {
+                overallBuildQueue = overallBuildQueues.get( key );
+                overallBuildQueue.cancelCurrentPrepareBuild();
+            }
+
+            return true;
+        }
+    }
+
+    /**
+     * @see BuildsManager#isBuildInProgress()
+     */
+    public boolean isBuildInProgress()
+    {
+        synchronized ( overallBuildQueues )
+        {
+            Set<Integer> keySet = overallBuildQueues.keySet();
+            for ( Integer key : keySet )
+            {
+                OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
+                if ( overallBuildQueue.getBuildTaskQueueExecutor().getCurrentTask() != null )
+                {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    public boolean isProjectCurrentlyPreparingBuild( int projectId )
+        throws BuildManagerException
+    {
+        Map<String, PrepareBuildProjectsTask> tasks = getCurrentProjectInPrepareBuild();
+
+        if ( tasks != null )
+        {
+            for ( PrepareBuildProjectsTask task : tasks.values() )
+            {
+                Map<Integer, Integer> map = task.getProjectsBuildDefinitionsMap();
+
+                if ( map.size() > 0 )
+                {
+                    Set<Integer> projectIds = map.keySet();
+
+                    if ( projectIds.contains( new Integer( projectId ) ) )
+                    {
+                        log.info( "Project '{}' is currently preparing build", projectId );
+                        return true;
+                    }
+                }
+            }
+        }
+
+        return false;
+    }
+
+    public boolean isProjectGroupCurrentlyPreparingBuild( int projectGroupId, int scmRootId )
+        throws BuildManagerException
+    {
+        Map<String, PrepareBuildProjectsTask> tasks = getCurrentProjectInPrepareBuild();
+
+        if ( tasks != null )
+        {
+            for ( PrepareBuildProjectsTask task : tasks.values() )
+            {
+                if ( task != null && task.getProjectGroupId() == projectGroupId &&
+                    task.getProjectScmRootId() == scmRootId )
+                {
+                    log.info( "Project group '{}' with scm root '{}' is currently preparing build", projectGroupId,
+                              scmRootId );
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    public Map<String, PrepareBuildProjectsTask> getCurrentProjectInPrepareBuild()
+        throws BuildManagerException
+    {
+        synchronized ( overallBuildQueues )
+        {
+            Map<String, PrepareBuildProjectsTask> currentBuilds = new HashMap<String, PrepareBuildProjectsTask>();
+            Set<Integer> keys = overallBuildQueues.keySet();
+            for ( Integer key : keys )
+            {
+                OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
+                PrepareBuildProjectsTask task =
+                    (PrepareBuildProjectsTask) overallBuildQueue.getPrepareBuildTaskQueueExecutor().getCurrentTask();
+                if ( task != null )
+                {
+                    currentBuilds.put( overallBuildQueue.getName(), task );
+                }
+            }
+            return currentBuilds;
+        }
+    }
+
+    public Map<String, List<PrepareBuildProjectsTask>> getProjectsInPrepareBuildQueue()
+        throws BuildManagerException
+    {
+        synchronized ( overallBuildQueues )
+        {
+            Map<String, List<PrepareBuildProjectsTask>> queuedPrepareBuilds =
+                new HashMap<String, List<PrepareBuildProjectsTask>>();
+            Set<Integer> keySet = overallBuildQueues.keySet();
+            for ( Integer key : keySet )
+            {
+                OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
+                try
+                {
+                    queuedPrepareBuilds.put( overallBuildQueue.getName(),
+                                             overallBuildQueue.getProjectsInPrepareBuildQueue() );
+                }
+                catch ( TaskQueueException e )
+                {
+                    throw new BuildManagerException(
+                        "Error occurred while getting projects in prepare build queue '" + overallBuildQueue.getName() +
+                            "'.", e );
+                }
+            }
+            return queuedPrepareBuilds;
+        }
+    }
+
+    public boolean removeProjectFromPrepareBuildQueue( int projectGroupId, int scmRootId )
+        throws BuildManagerException
+    {
+        try
+        {
+            OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectGroupIsQueued( projectGroupId,
+                                                                                                 scmRootId );
+            if ( overallBuildQueue != null )
+            {
+                overallBuildQueue.removeProjectFromPrepareBuildQueue( projectGroupId, scmRootId );
+            }
+            else
+            {
+                log.info( "Project group '{}' with scm '{}' not found in any of the build queues.", projectGroupId,
+                          scmRootId );
+            }
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException(
+                "Error occurred while removing project group from prepare build queue: " + e.getMessage() );
+        }
+
+        return true;
+    }
+
+    public void removeProjectsFromPrepareBuildQueueWithHashCodes( int[] hashCodes )
+        throws BuildManagerException
+    {
+        try
+        {
+            synchronized ( overallBuildQueues )
+            {
+                Set<Integer> keySet = overallBuildQueues.keySet();
+                for ( Integer key : keySet )
+                {
+                    OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
+                    overallBuildQueue.removeProjectsFromPrepareBuildQueueWithHashCodes( hashCodes );
+                }
+            }
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException( "Error encountered while removing project group(s) from build queue.", e );
+        }
+    }
+
+    private boolean isInQueue( int projectId, int typeOfQueue, int buildDefinitionId )
+        throws TaskQueueException
+    {
+        synchronized ( overallBuildQueues )
+        {
+            Set<Integer> keySet = overallBuildQueues.keySet();
+            for ( Integer key : keySet )
+            {
+                OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
+                if ( typeOfQueue == BUILD_QUEUE )
+                {
+                    if ( buildDefinitionId < 0 )
+                    {
+                        if ( overallBuildQueue.isInBuildQueue( projectId ) )
+                        {
+                            log.info( "Project " + projectId + " is in build queue " + overallBuildQueue.getName() );
+                            return true;
+                        }
+                    }
+                    else
+                    {
+                        if ( overallBuildQueue.isInBuildQueue( projectId, buildDefinitionId ) )
+                        {
+                            log.info( "Project " + projectId + " is in build queue " + overallBuildQueue.getName() );
+                            return true;
+                        }
+                    }
+                }
+                else if ( typeOfQueue == CHECKOUT_QUEUE )
+                {
+                    if ( overallBuildQueue.isInCheckoutQueue( projectId ) )
+                    {
+                        log.info( "Project " + projectId + " is in checkout queue " + overallBuildQueue.getName() );
+                        return true;
+                    }
+                }
+            }
+
+            return false;
+        }
+    }
+
+    // get overall queue where project is queued
+    private OverallBuildQueue getOverallBuildQueueWhereProjectIsQueued( int projectId, int typeOfQueue )
+        throws TaskQueueException
+    {
+        synchronized ( overallBuildQueues )
+        {
+            OverallBuildQueue whereQueued = null;
+            Set<Integer> keySet = overallBuildQueues.keySet();
+
+            for ( Integer key : keySet )
+            {
+                OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
+                if ( typeOfQueue == BUILD_QUEUE )
+                {
+                    if ( overallBuildQueue.isInBuildQueue( projectId ) )
+                    {
+                        whereQueued = overallBuildQueue;
+                        break;
+                    }
+                }
+                else if ( typeOfQueue == CHECKOUT_QUEUE )
+                {
+                    if ( overallBuildQueue.isInCheckoutQueue( projectId ) )
+                    {
+                        whereQueued = overallBuildQueue;
+                        break;
+                    }
+                }
+                else if ( typeOfQueue == PREPARE_BUILD_QUEUE )
+                {
+                    if ( overallBuildQueue.isInPrepareBuildQueue( projectId ) )
+                    {
+                        whereQueued = overallBuildQueue;
+                        break;
+                    }
+                }
+            }
+
+            return whereQueued;
+        }
+    }
+
+    // get overall queue where project will be queued
+    private OverallBuildQueue getOverallBuildQueue( int typeOfQueue, List<BuildQueue> buildQueues )
+        throws BuildManagerException
+    {
+        OverallBuildQueue whereToBeQueued = null;
+        synchronized ( overallBuildQueues )
+        {
+            if ( overallBuildQueues == null || overallBuildQueues.isEmpty() )
+            {
+                throw new BuildManagerException( "No build queues configured." );
+            }
+
+            int size = 0;
+            int idx = 0;
+            int allowedBuilds = configurationService.getNumberOfBuildsInParallel();
+
+            try
+            {
+                int count = 1;
+                for ( BuildQueue buildQueue : buildQueues )
+                {
+                    if ( count <= allowedBuilds )
+                    {
+                        OverallBuildQueue overallBuildQueue = overallBuildQueues.get( buildQueue.getId() );
+                        if ( overallBuildQueue != null )
+                        {
+                            TaskQueue taskQueue = null;
+                            TaskQueueExecutor taskQueueExecutor = null;
+                            int tempSize = 0;
+                            if ( typeOfQueue == BUILD_QUEUE )
+                            {
+                                taskQueue = overallBuildQueue.getBuildQueue();
+                                taskQueueExecutor = overallBuildQueue.getBuildTaskQueueExecutor();
+                            }
+                            else if ( typeOfQueue == CHECKOUT_QUEUE )
+                            {
+                                taskQueue = overallBuildQueue.getCheckoutQueue();
+                                taskQueueExecutor = overallBuildQueue.getCheckoutTaskQueueExecutor();
+                            }
+                            else if ( typeOfQueue == PREPARE_BUILD_QUEUE )
+                            {
+                                taskQueue = overallBuildQueue.getPrepareBuildQueue();
+                                taskQueueExecutor = overallBuildQueue.getPrepareBuildTaskQueueExecutor();
+                            }
+
+                            tempSize = taskQueue.getQueueSnapshot().size();
+                            if ( taskQueueExecutor.getCurrentTask() != null )
+                            {
+                                tempSize++;
+                            }
+
+                            if ( idx == 0 )
+                            {
+                                whereToBeQueued = overallBuildQueue;
+                                size = tempSize;
+                            }
+
+                            if ( tempSize < size )
+                            {
+                                whereToBeQueued = overallBuildQueue;
+                                size = tempSize;
+                            }
+
+                            idx++;
+                        }
+                        else
+                        {
+                            log.error( "Build queue not found." );
+                        }
+                        count++;
+                    }
+                    else
+                    {
+                        break;
+                    }
+                }
+            }
+            catch ( TaskQueueException e )
+            {
+                throw new BuildManagerException( "Error occurred while retrieving task quueue: " + e.getMessage() );
+            }
+        }
+
+        // use default overall build queue if none is configured
+        if ( whereToBeQueued == null )
+        {
+            Set<Integer> keySet = overallBuildQueues.keySet();
+            for ( Integer key : keySet )
+            {
+                OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
+                if ( overallBuildQueue.getName().equals( ConfigurationService.DEFAULT_BUILD_QUEUE_NAME ) )
+                {
+                    return overallBuildQueue;
+                }
+            }
+        }
+
+        return whereToBeQueued;
+    }
+
+    public OverallBuildQueue getOverallBuildQueueWhereProjectsInGroupAreQueued( int projectGroupId )
+        throws BuildManagerException
+    {
+        OverallBuildQueue whereToBeQueued = null;
+
+        try
+        {
+            List<Project> projects = projectDao.getProjectsInGroup( projectGroupId );
+
+            if ( projects != null )
+            {
+                for ( Project project : projects )
+                {
+                    whereToBeQueued = getOverallBuildQueueWhereProjectIsQueued( project.getId(), BUILD_QUEUE );
+
+                    if ( whereToBeQueued == null )
+                    {
+                        whereToBeQueued = getOverallBuildQueueWhereProjectIsBuilding( project.getId() );
+                    }
+
+                    if ( whereToBeQueued != null )
+                    {
+                        break;
+                    }
+                }
+            }
+        }
+        catch ( ContinuumStoreException e )
+        {
+            throw new BuildManagerException(
+                "Error while retrieving overall build queue for project: " + e.getMessage() );
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new BuildManagerException(
+                "Error while retrieving overall build queue for project: " + e.getMessage() );
+        }
+
+        return whereToBeQueued;
+    }
+
+    private OverallBuildQueue getOverallBuildQueueWhereProjectGroupIsQueued( int projectGroupId, int scmRootId )
+        throws TaskQueueException
+    {
+        synchronized ( overallBuildQueues )
+        {
+            OverallBuildQueue whereQueued = null;
+            Set<Integer> keySet = overallBuildQueues.keySet();
+
+            for ( Integer key : keySet )
+            {
+                OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
+
+                if ( overallBuildQueue.isInPrepareBuildQueue( projectGroupId, scmRootId ) )
+                {
+                    whereQueued = overallBuildQueue;
+                }
+            }
+
+            return whereQueued;
+        }
+    }
+
+    private OverallBuildQueue getOverallBuildQueueWhereProjectGroupIsQueued( int projectGroupId, String scmRootAddress )
+        throws TaskQueueException
+    {
+        synchronized ( overallBuildQueues )
+        {
+            OverallBuildQueue whereQueued = null;
+            Set<Integer> keySet = overallBuildQueues.keySet();
+
+            for ( Integer key : keySet )
+            {
+                OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
+
+                if ( overallBuildQueue.isInPrepareBuildQueue( projectGroupId, scmRootAddress ) )
+                {
+                    whereQueued = overallBuildQueue;
+                }
+            }
+
+            return whereQueued;
+        }
+    }
+
+    private OverallBuildQueue getOverallBuildQueueWhereProjectIsBuilding( int projectId )
+    {
+        synchronized ( overallBuildQueues )
+        {
+            for ( Integer key : overallBuildQueues.keySet() )
+            {
+                OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key );
+                BuildProjectTask task =
+                    (BuildProjectTask) overallBuildQueue.getBuildTaskQueueExecutor().getCurrentTask();
+                if ( task != null && task.getProjectId() == projectId )
+                {
+                    return overallBuildQueue;
+                }
+            }
+            return null;
+        }
+    }
+
+    public boolean isProjectCurrentlyBeingCheckedOut( int projectId )
+        throws BuildManagerException
+    {
+        Map<String, CheckOutTask> checkouts = getCurrentCheckouts();
+        for ( String key : checkouts.keySet() )
+        {
+            CheckOutTask task = checkouts.get( key );
+            if ( task.getProjectId() == projectId )
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    public boolean isAnyProjectCurrentlyBuilding( int[] projectIds )
+        throws BuildManagerException
+    {
+        for ( int i = 0; i < projectIds.length; i++ )
+        {
+            if ( isProjectInAnyCurrentBuild( projectIds[i] ) )
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    public boolean isAnyProjectCurrentlyPreparingBuild( int[] projectIds )
+        throws BuildManagerException
+    {
+        for ( int i = 0; i < projectIds.length; i++ )
+        {
+            if ( isProjectCurrentlyPreparingBuild( projectIds[i] ) )
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    public void contextualize( Context context )
+        throws ContextException
+    {
+        container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
+
+        synchronized ( overallBuildQueues )
+        {
+            try
+            {
+                // create all the build queues configured in the database, not just the default!               
+                List<BuildQueue> buildQueues = buildQueueService.getAllBuildQueues();
+                for ( BuildQueue buildQueue : buildQueues )
+                {
+                    createOverallBuildQueue( buildQueue );
+                }
+
+                // add default overall build queue if not yet added to the map
+                BuildQueue defaultBuildQueue = configurationService.getDefaultBuildQueue();
+                if ( overallBuildQueues.get( defaultBuildQueue.getId() ) == null )
+                {
+                    createOverallBuildQueue( defaultBuildQueue );
+                }
+            }
+            catch ( ComponentLookupException e )
+            {
+                log.error( "Cannot create overall build queue: " + e.getMessage() );
+            }
+            catch ( BuildQueueServiceException e )
+            {
+                log.error( "Cannot create overall build queue: " + e.getMessage() );
+            }
+        }
+    }
+
+    public void setContainer( PlexusContainer container )
+    {
+        this.container = container;
+    }
+
+    private void createOverallBuildQueue( BuildQueue defaultBuildQueue )
+        throws ComponentLookupException
+    {
+        OverallBuildQueue overallBuildQueue = (OverallBuildQueue) container.lookup( OverallBuildQueue.class );
+        overallBuildQueue.setId( defaultBuildQueue.getId() );
+        overallBuildQueue.setName( defaultBuildQueue.getName() );
+
+        overallBuildQueues.put( overallBuildQueue.getId(), overallBuildQueue );
+    }
+
+    // for unit tests.. 
+
+    public void setOverallBuildQueues( Map<Integer, OverallBuildQueue> overallBuildQueues )
+    {
+        this.overallBuildQueues = overallBuildQueues;
+    }
+
+    public void setConfigurationService( ConfigurationService configurationService )
+    {
+        this.configurationService = configurationService;
+    }
+
+    public void setBuildQueueService( BuildQueueService buildQueueService )
+    {
+        this.buildQueueService = buildQueueService;
+    }
+
+    public void setBuildDefinitionDao( BuildDefinitionDao buildDefinitionDao )
+    {
+        this.buildDefinitionDao = buildDefinitionDao;
+    }
+
+    public void setProjectDao( ProjectDao projectDao )
+    {
+        this.projectDao = projectDao;
+    }
+}
diff --git a/continuum-core/src/main/java/org/apache/continuum/purge/DefaultContinuumPurgeManager.java b/continuum-core/src/main/java/org/apache/continuum/purge/DefaultContinuumPurgeManager.java
index 78f33c9..302f915 100644
--- a/continuum-core/src/main/java/org/apache/continuum/purge/DefaultContinuumPurgeManager.java
+++ b/continuum-core/src/main/java/org/apache/continuum/purge/DefaultContinuumPurgeManager.java
@@ -19,15 +19,20 @@
  * under the License.
  */
 
-import org.apache.continuum.dao.ProjectDao;
+import org.apache.continuum.buildmanager.BuildsManager;
 import org.apache.continuum.model.repository.DirectoryPurgeConfiguration;
+import org.apache.continuum.model.repository.DistributedDirectoryPurgeConfiguration;
 import org.apache.continuum.model.repository.LocalRepository;
 import org.apache.continuum.model.repository.RepositoryPurgeConfiguration;
 import org.apache.continuum.purge.task.PurgeTask;
 import org.apache.continuum.taskqueue.manager.TaskQueueManager;
 import org.apache.continuum.taskqueue.manager.TaskQueueManagerException;
+import org.apache.maven.continuum.build.settings.SchedulesActivationException;
+import org.apache.maven.continuum.build.settings.SchedulesActivator;
 import org.apache.maven.continuum.model.project.Schedule;
 import org.codehaus.plexus.taskqueue.TaskQueueException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.List;
 
@@ -42,10 +47,12 @@
 public class DefaultContinuumPurgeManager
     implements ContinuumPurgeManager
 {
+    private static final Logger log = LoggerFactory.getLogger( DefaultContinuumPurgeManager.class );
+
     /**
      * @plexus.requirement
      */
-    private ProjectDao projectDao;
+    private SchedulesActivator schedulesActivator;
 
     /**
      * @plexus.requirement
@@ -56,17 +63,29 @@
      * @plexus.requirement
      */
     private TaskQueueManager taskQueueManager;
-    
+
+    /**
+     * @plexus.requirement role-hint="parallel"
+     */
+    private BuildsManager parallelBuildsManager;
+
     public void purge( Schedule schedule )
         throws ContinuumPurgeManagerException
     {
         List<RepositoryPurgeConfiguration> repoPurgeList = null;
         List<DirectoryPurgeConfiguration> dirPurgeList = null;
+        List<DistributedDirectoryPurgeConfiguration> distributedDirPurgeList = null;
 
-        repoPurgeList = purgeConfigurationService.getRepositoryPurgeConfigurationsBySchedule( schedule.getId() );
-        dirPurgeList = purgeConfigurationService.getDirectoryPurgeConfigurationsBySchedule( schedule.getId() );
+        repoPurgeList = purgeConfigurationService.getEnableRepositoryPurgeConfigurationsBySchedule( schedule.getId() );
+        dirPurgeList = purgeConfigurationService.getEnableDirectoryPurgeConfigurationsBySchedule( schedule.getId() );
+        distributedDirPurgeList = purgeConfigurationService.getEnableDistributedDirectoryPurgeConfigurationsBySchedule(
+            schedule.getId() );
 
-        if ( repoPurgeList != null && repoPurgeList.size() > 0 )
+        boolean hasRepoPurge = repoPurgeList != null && repoPurgeList.size() > 0;
+        boolean hasDirPurge = dirPurgeList != null && dirPurgeList.size() > 0;
+        boolean hasDitributedDirPurge = distributedDirPurgeList != null && distributedDirPurgeList.size() > 0;
+
+        if ( hasRepoPurge )
         {
             for ( RepositoryPurgeConfiguration repoPurge : repoPurgeList )
             {
@@ -74,13 +93,35 @@
             }
         }
 
-        if ( dirPurgeList != null && dirPurgeList.size() > 0 )
+        if ( hasDirPurge )
         {
             for ( DirectoryPurgeConfiguration dirPurge : dirPurgeList )
             {
                 purgeDirectory( dirPurge );
             }
         }
+
+        if ( hasDitributedDirPurge )
+        {
+            for ( DistributedDirectoryPurgeConfiguration dirPurge : distributedDirPurgeList )
+            {
+                purgeDistributedDirectory( dirPurge );
+            }
+        }
+
+        if ( !hasRepoPurge && !hasDirPurge && !hasDitributedDirPurge )
+        {
+            // This purge is not enable for a purge process.
+            try
+            {
+                schedulesActivator.unactivateOrphanPurgeSchedule( schedule );
+            }
+            catch ( SchedulesActivationException e )
+            {
+                log.debug( String.format( "Can't unactivate orphan schedule '%s' for purgeConfiguration",
+                                          schedule.getName() ) );
+            }
+        }
     }
 
     public void purgeRepository( RepositoryPurgeConfiguration repoPurge )
@@ -91,8 +132,8 @@
             LocalRepository repository = repoPurge.getRepository();
 
             // do not purge if repository is in use and if repository is already in purge queue
-            if ( !taskQueueManager.isRepositoryInUse( repository.getId() ) && 
-                 !taskQueueManager.isInPurgeQueue( repoPurge.getId() ) )
+            if ( !taskQueueManager.isRepositoryInUse( repository.getId() ) && !taskQueueManager.isInPurgeQueue(
+                repoPurge.getId() ) )
             {
                 taskQueueManager.getPurgeQueue().put( new PurgeTask( repoPurge.getId() ) );
             }
@@ -115,8 +156,7 @@
             if ( "releases".equals( dirPurge.getDirectoryType() ) )
             {
                 // do not purge if release in progress
-                if ( !taskQueueManager.releaseInProgress() && 
-                     !taskQueueManager.isInPurgeQueue( dirPurge.getId() ) )
+                if ( !taskQueueManager.releaseInProgress() && !taskQueueManager.isInPurgeQueue( dirPurge.getId() ) )
                 {
                     taskQueueManager.getPurgeQueue().put( new PurgeTask( dirPurge.getId() ) );
                 }
@@ -124,8 +164,8 @@
             else if ( "buildOutput".equals( dirPurge.getDirectoryType() ) )
             {
                 // do not purge if build in progress
-                if ( !taskQueueManager.buildInProgress() && 
-                     !taskQueueManager.isInPurgeQueue( dirPurge.getId() ) )
+                if ( !parallelBuildsManager.isBuildInProgress() && !taskQueueManager.isInPurgeQueue(
+                    dirPurge.getId() ) )
                 {
                     taskQueueManager.getPurgeQueue().put( new PurgeTask( dirPurge.getId() ) );
                 }
@@ -134,7 +174,7 @@
         }
         catch ( TaskQueueException e )
         {
-            throw new ContinuumPurgeManagerException( "Error while enqueuing repository", e );
+            throw new ContinuumPurgeManagerException( "Error while enqueuing directory", e );
         }
         catch ( TaskQueueManagerException e )
         {
@@ -142,4 +182,17 @@
         }
     }
 
+    public void purgeDistributedDirectory( DistributedDirectoryPurgeConfiguration dirPurge )
+        throws ContinuumPurgeManagerException
+    {
+        try
+        {
+            taskQueueManager.getPurgeQueue().put( new PurgeTask( dirPurge.getId() ) );
+        }
+        catch ( TaskQueueException e )
+        {
+            throw new ContinuumPurgeManagerException( "Error while enqueuing distributed directory", e );
+        }
+    }
+
 }
\ No newline at end of file
diff --git a/continuum-core/src/main/java/org/apache/continuum/release/distributed/DistributedReleaseUtil.java b/continuum-core/src/main/java/org/apache/continuum/release/distributed/DistributedReleaseUtil.java
new file mode 100644
index 0000000..d285ced
--- /dev/null
+++ b/continuum-core/src/main/java/org/apache/continuum/release/distributed/DistributedReleaseUtil.java
@@ -0,0 +1,316 @@
+package org.apache.continuum.release.distributed;
+
+/*
+ * 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.Arrays;
+import java.util.List;
+import java.util.Map;
+
+public class DistributedReleaseUtil
+{
+    public static final String KEY_SCM_TAG = "scm-tag";
+
+    public static final String KEY_SCM_TAGBASE = "scm-tagbase";
+
+    public static final String KEY_SCM_USERNAME = "scm-username";
+
+    public static final String KEY_SCM_PASSWORD = "scm-password";
+
+    public static final String KEY_ARGUMENTS = "arguments";
+
+    public static final String KEY_PREPARE_GOALS = "preparation-goals";
+
+    public static final String KEY_PERFORM_GOALS = "perform-goals";
+
+    public static final String KEY_SCM_COMMENT_PREFIX = "scm-comment-prefix";
+
+    public static final String KEY_AUTO_VERSION_SUBMODULES = "auto-version-submodules";
+
+    public static final String KEY_ADD_SCHEMA = "add-schema";
+
+    public static final String KEY_PROJECT = "project";
+
+    public static final String KEY_PROFILE = "profile";
+
+    public static final String KEY_PROPERTIES = "properties";
+
+    public static final String KEY_RELEASE_VERSION = "releaseVersion";
+
+    public static final String KEY_DEVELOPMENT_VERSION = "developmentVersion";
+
+    public static final String KEY_PROJECT_ID = "project-id";
+
+    public static final String KEY_GROUP_ID = "group-id";
+
+    public static final String KEY_ARTIFACT_ID = "artifact-id";
+
+    public static final String KEY_SCM_URL = "scm-url";
+
+    public static final String KEY_LOCAL_REPOSITORY = "local-repository";
+
+    public static final String KEY_USE_EDIT_MODE = "use-edit-mode";
+
+    public static final String KEY_ENVIRONMENTS = "environments";
+
+    public static final String KEY_START_TIME = "start-time";
+
+    public static final String KEY_END_TIME = "end-time";
+
+    public static final String KEY_RELEASE_RESULT_CODE = "release-result-code";
+
+    public static final String KEY_RELEASE_OUTPUT = "release-output";
+
+    public static final String KEY_RELEASE_STATE = "state";
+
+    public static final String KEY_RELEASE_PHASES = "release-phases";
+
+    public static final String KEY_COMPLETED_RELEASE_PHASES = "completed-release-phases";
+
+    public static final String KEY_RELEASE_IN_PROGRESS = "release-in-progress";
+
+    public static final String KEY_RELEASE_ERROR = "release-error";
+
+    public static final String KEY_USE_RELEASE_PROFILE = "use-release-profile";
+
+    public static final String KEY_GOALS = "goals";
+
+    public static final String KEY_RELEASE_ID = "release-id";
+
+    public static final String KEY_LOCAL_REPOSITORY_NAME = "repo-name";
+
+    public static final String KEY_LOCAL_REPOSITORY_LAYOUT = "repo-layout";
+
+    public static final String KEY_RELEASE_GOAL = "release-goal";
+
+    public static final String KEY_BUILD_AGENT_URL = "build-agent-url";
+
+    public static final String KEY_USERNAME = "username";
+
+    public static String getScmTag( Map<String, Object> context, String defaultValue )
+    {
+        return getString( context, KEY_SCM_TAG, defaultValue );
+    }
+
+    public static String getScmTagBase( Map<String, Object> context, String defaultValue )
+    {
+        return getString( context, KEY_SCM_TAGBASE, defaultValue );
+    }
+
+    public static String getArguments( Map<String, Object> context, String defaultValue )
+    {
+        return getString( context, KEY_ARGUMENTS, defaultValue );
+    }
+
+    public static String getPrepareGoals( Map<String, Object> context, String defaultValue )
+    {
+        return getString( context, KEY_PREPARE_GOALS, defaultValue );
+    }
+
+    public static String getPerformGoals( Map<String, Object> context, String defaultValue )
+    {
+        return getString( context, KEY_PERFORM_GOALS, defaultValue );
+    }
+
+    public static String getScmCommentPrefix( Map<String, Object> context, String defaultValue )
+    {
+        return getString( context, KEY_SCM_COMMENT_PREFIX, defaultValue );
+    }
+
+    public static Boolean getAutoVersionSubmodules( Map<String, Object> context, boolean defaultValue )
+    {
+        return getBoolean( context, KEY_AUTO_VERSION_SUBMODULES, defaultValue );
+    }
+
+    public static Boolean getAddSchema( Map<String, Object> context, boolean defaultValue )
+    {
+        return getBoolean( context, KEY_ADD_SCHEMA, defaultValue );
+    }
+
+    public static Long getStartTime( Map<String, Object> context )
+    {
+        return new Long( getString( context, KEY_START_TIME ) );
+    }
+
+    public static Long getEndTime( Map<String, Object> context )
+    {
+        return new Long( getString( context, KEY_END_TIME ) );
+    }
+
+    public static int getReleaseResultCode( Map<String, Object> context )
+    {
+        return getInteger( context, KEY_RELEASE_RESULT_CODE );
+    }
+
+    public static String getReleaseOutput( Map<String, Object> context )
+    {
+        return getString( context, KEY_RELEASE_OUTPUT );
+    }
+
+    public static int getReleaseState( Map<String, Object> context )
+    {
+        return getInteger( context, KEY_RELEASE_STATE );
+    }
+
+    public static List getReleasePhases( Map<String, Object> context )
+    {
+        return getList( context, KEY_RELEASE_PHASES, new ArrayList() );
+    }
+
+    public static List getCompletedReleasePhases( Map<String, Object> context )
+    {
+        return getList( context, KEY_COMPLETED_RELEASE_PHASES, new ArrayList() );
+    }
+
+    public static String getReleaseInProgress( Map<String, Object> context )
+    {
+        return getString( context, KEY_RELEASE_IN_PROGRESS, "" );
+    }
+
+    public static String getReleaseError( Map<String, Object> context )
+    {
+        return getString( context, KEY_RELEASE_ERROR, null );
+    }
+
+    public static boolean getUseReleaseProfile( Map<String, Object> context, boolean defaultValue )
+    {
+        return getBoolean( context, KEY_USE_RELEASE_PROFILE, defaultValue );
+    }
+
+    public static String getGoals( Map<String, Object> context, String defaultValue )
+    {
+        return getString( context, KEY_GOALS, defaultValue );
+    }
+
+    public static String getReleaseId( Map<String, Object> context )
+    {
+        return getString( context, KEY_RELEASE_ID );
+    }
+
+    public static String getReleaseGoal( Map<String, Object> context )
+    {
+        return getString( context, KEY_RELEASE_GOAL );
+    }
+
+    public static String getBuildAgentUrl( Map<String, Object> context )
+    {
+        return getString( context, KEY_BUILD_AGENT_URL );
+    }
+
+    public static int getProjectId( Map<String, Object> context )
+    {
+        return getInteger( context, KEY_PROJECT_ID );
+    }
+
+    public static String getUsername( Map<String, Object> context )
+    {
+        return getString( context, KEY_USERNAME, "" );
+    }
+
+    // ----------------------------------------------------------------------
+    //
+    // ----------------------------------------------------------------------
+
+    public static Integer getInteger( Map<String, Object> context, String key )
+    {
+        return (Integer) getObject( context, key );
+    }
+
+    public static Integer getInteger( Map<String, Object> context, String key, Object defaultValue )
+    {
+        return (Integer) getObject( context, key, defaultValue );
+    }
+
+    public static String getString( Map<String, Object> context, String key )
+    {
+        return (String) getObject( context, key );
+    }
+
+    public static String getString( Map<String, Object> context, String key, String defaultValue )
+    {
+        return (String) getObject( context, key, defaultValue );
+    }
+
+    public static boolean getBoolean( Map<String, Object> context, String key )
+    {
+        return (Boolean) getObject( context, key );
+    }
+
+    public static boolean getBoolean( Map<String, Object> context, String key, boolean defaultValue )
+    {
+        return (Boolean) getObject( context, key, defaultValue );
+    }
+
+    public static List getList( Map<String, Object> context, String key, Object defaultValue )
+    {
+        Object obj = getObject( context, key, defaultValue );
+
+        if ( obj == null )
+        {
+            return null;
+        }
+        else
+        {
+            List<Object> list = new ArrayList<Object>();
+
+            if ( obj instanceof Object[] )
+            {
+                Object[] objA = (Object[]) obj;
+
+                list.addAll( Arrays.asList( objA ) );
+            }
+            else
+            {
+                list = (List<Object>) obj;
+            }
+
+            return list;
+        }
+    }
+
+    protected static Object getObject( Map<String, Object> context, String key )
+    {
+        if ( !context.containsKey( key ) )
+        {
+            throw new RuntimeException( "Missing key '" + key + "'." );
+        }
+
+        Object value = context.get( key );
+
+        if ( value == null )
+        {
+            throw new RuntimeException( "Missing value for key '" + key + "'." );
+        }
+
+        return value;
+    }
+
+    protected static Object getObject( Map<String, Object> context, String key, Object defaultValue )
+    {
+        Object value = context.get( key );
+
+        if ( value == null )
+        {
+            return defaultValue;
+        }
+
+        return value;
+    }
+}
\ No newline at end of file
diff --git a/continuum-core/src/main/java/org/apache/continuum/release/distributed/manager/DefaultDistributedReleaseManager.java b/continuum-core/src/main/java/org/apache/continuum/release/distributed/manager/DefaultDistributedReleaseManager.java
new file mode 100644
index 0000000..ed77675
--- /dev/null
+++ b/continuum-core/src/main/java/org/apache/continuum/release/distributed/manager/DefaultDistributedReleaseManager.java
@@ -0,0 +1,925 @@
+package org.apache.continuum.release.distributed.manager;
+
+/*
+ * 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 org.apache.continuum.builder.distributed.manager.DistributedBuildManager;
+import org.apache.continuum.configuration.BuildAgentConfiguration;
+import org.apache.continuum.configuration.BuildAgentConfigurationException;
+import org.apache.continuum.dao.BuildResultDao;
+import org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportClient;
+import org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportService;
+import org.apache.continuum.model.repository.LocalRepository;
+import org.apache.continuum.release.distributed.DistributedReleaseUtil;
+import org.apache.continuum.release.model.PreparedRelease;
+import org.apache.continuum.release.model.PreparedReleaseModel;
+import org.apache.continuum.release.model.io.stax.ContinuumPrepareReleasesModelStaxReader;
+import org.apache.continuum.release.model.io.stax.ContinuumPrepareReleasesModelStaxWriter;
+import org.apache.maven.artifact.ArtifactUtils;
+import org.apache.maven.continuum.configuration.ConfigurationService;
+import org.apache.maven.continuum.installation.InstallationService;
+import org.apache.maven.continuum.model.project.BuildResult;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.release.ContinuumReleaseException;
+import org.apache.maven.shared.release.ReleaseResult;
+import org.codehaus.plexus.util.IOUtil;
+import org.codehaus.plexus.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import javax.xml.stream.XMLStreamException;
+
+/**
+ * @plexus.component role="org.apache.continuum.release.distributed.manager.DistributedReleaseManager"
+ */
+public class DefaultDistributedReleaseManager
+    implements DistributedReleaseManager
+{
+    private static final Logger log = LoggerFactory.getLogger( DefaultDistributedReleaseManager.class );
+
+    public final String PREPARED_RELEASES_FILENAME = "prepared-releases.xml";
+
+    /**
+     * @plexus.requirement
+     */
+    BuildResultDao buildResultDao;
+
+    /**
+     * @plexus.requirement
+     */
+    InstallationService installationService;
+
+    /**
+     * @plexus.requirement
+     */
+    ConfigurationService configurationService;
+
+    /**
+     * @plexus.requirement
+     */
+    DistributedBuildManager distributedBuildManager;
+
+    private Map<String, Map<String, Object>> releasesInProgress;
+
+    public Map getReleasePluginParameters( int projectId, String pomFilename )
+        throws ContinuumReleaseException, BuildAgentConfigurationException
+    {
+        String buildAgentUrl = getDefaultBuildagent( projectId );
+
+        if ( !checkBuildAgent( buildAgentUrl ) )
+        {
+            throw new BuildAgentConfigurationException( buildAgentUrl );
+        }
+
+        try
+        {
+            if ( distributedBuildManager.isAgentAvailable( buildAgentUrl ) )
+            {
+                SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                    buildAgentUrl );
+                return client.getReleasePluginParameters( projectId, pomFilename );
+            }
+
+            // call reload in case we disable the build agent
+            distributedBuildManager.reload();
+
+            throw new ContinuumReleaseException(
+                "Failed to retrieve release plugin parameters because build agent " + buildAgentUrl +
+                    " is not available" );
+        }
+        catch ( MalformedURLException e )
+        {
+            log.error( "Invalid build agent url " + buildAgentUrl );
+            throw new ContinuumReleaseException( "Invalid build agent url " + buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to retrieve release plugin parameters", e );
+            throw new ContinuumReleaseException( "Failed to retrieve release plugin parameters", e );
+        }
+    }
+
+    public List<Map<String, String>> processProject( int projectId, String pomFilename, boolean autoVersionSubmodules )
+        throws ContinuumReleaseException, BuildAgentConfigurationException
+    {
+        BuildResult buildResult = buildResultDao.getLatestBuildResultForProject( projectId );
+
+        String buildAgentUrl = buildResult.getBuildUrl();
+
+        if ( !checkBuildAgent( buildAgentUrl ) )
+        {
+            throw new BuildAgentConfigurationException( buildAgentUrl );
+        }
+
+        try
+        {
+            if ( distributedBuildManager.isAgentAvailable( buildAgentUrl ) )
+            {
+                SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                    buildAgentUrl );
+                return client.processProject( projectId, pomFilename, autoVersionSubmodules );
+            }
+
+            // call reload in case we disable the build agent
+            distributedBuildManager.reload();
+
+            throw new ContinuumReleaseException(
+                "Failed to process project for releasing because build agent " + buildAgentUrl + " is unavailable" );
+        }
+        catch ( MalformedURLException e )
+        {
+            log.error( "Invalid build agent url " + buildAgentUrl );
+            throw new ContinuumReleaseException( "Invalid build agent url " + buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to process project for releasing", e );
+            throw new ContinuumReleaseException( "Failed to process project for releasing", e );
+        }
+    }
+
+    public String releasePrepare( Project project, Properties releaseProperties, Map<String, String> releaseVersion,
+                                  Map<String, String> developmentVersion, Map<String, String> environments,
+                                  String username )
+        throws ContinuumReleaseException, BuildAgentConfigurationException
+    {
+        String buildAgentUrl = environments.get( DistributedReleaseUtil.KEY_BUILD_AGENT_URL );
+
+        if ( !checkBuildAgent( buildAgentUrl ) )
+        {
+            throw new BuildAgentConfigurationException( buildAgentUrl );
+        }
+
+        try
+        {
+            if ( distributedBuildManager.isAgentAvailable( buildAgentUrl ) )
+            {
+                SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                    buildAgentUrl );
+
+                String releaseId = client.releasePrepare( createProjectMap( project ), releaseProperties,
+                                                          releaseVersion, developmentVersion, environments, username );
+
+                String key = ArtifactUtils.versionlessKey( project.getGroupId(), project.getArtifactId() );
+                addReleasePrepare( releaseId, buildAgentUrl, releaseVersion.get( key ), "prepare",
+                                   releaseProperties.getProperty( "preparation-goals" ), username );
+
+                addReleaseInProgress( releaseId, "prepare", project.getId(), username );
+
+                return releaseId;
+            }
+
+            // call reload in case we disable the build agent
+            distributedBuildManager.reload();
+
+            throw new ContinuumReleaseException(
+                "Failed to prepare release project because the build agent " + buildAgentUrl + " is not available" );
+        }
+        catch ( MalformedURLException e )
+        {
+            log.error( "Invalid build agent url " + buildAgentUrl );
+            throw new ContinuumReleaseException( "Invalid build agent url " + buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to prepare release project " + project.getName(), e );
+            throw new ContinuumReleaseException( "Failed to prepare release project " + project.getName(), e );
+        }
+    }
+
+    public ReleaseResult getReleaseResult( String releaseId )
+        throws ContinuumReleaseException, BuildAgentConfigurationException
+    {
+        String buildAgentUrl = getBuildAgentUrl( releaseId );
+
+        if ( !checkBuildAgent( buildAgentUrl ) )
+        {
+            throw new BuildAgentConfigurationException( buildAgentUrl );
+        }
+
+        try
+        {
+            if ( distributedBuildManager.isAgentAvailable( buildAgentUrl ) )
+            {
+                SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                    buildAgentUrl );
+                Map<String, Object> result = client.getReleaseResult( releaseId );
+
+                ReleaseResult releaseResult = new ReleaseResult();
+                releaseResult.setStartTime( DistributedReleaseUtil.getStartTime( result ) );
+                releaseResult.setEndTime( DistributedReleaseUtil.getEndTime( result ) );
+                releaseResult.setResultCode( DistributedReleaseUtil.getReleaseResultCode( result ) );
+                releaseResult.getOutputBuffer().append( DistributedReleaseUtil.getReleaseOutput( result ) );
+
+                return releaseResult;
+            }
+
+            // call reload in case we disable a build agent
+            distributedBuildManager.reload();
+
+            throw new ContinuumReleaseException( "Failed to get release result of " + releaseId +
+                                                     " because the build agent " + buildAgentUrl +
+                                                     " is not available" );
+        }
+        catch ( MalformedURLException e )
+        {
+            log.error( "Invalid build agent url " + buildAgentUrl );
+            throw new ContinuumReleaseException( "Invalid build agent url " + buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to get release result of " + releaseId, e );
+            throw new ContinuumReleaseException( "Failed to get release result of " + releaseId, e );
+        }
+    }
+
+    public Map<String, Object> getListener( String releaseId )
+        throws ContinuumReleaseException, BuildAgentConfigurationException
+    {
+        String buildAgentUrl = getBuildAgentUrl( releaseId );
+
+        if ( !checkBuildAgent( buildAgentUrl ) )
+        {
+            throw new BuildAgentConfigurationException( buildAgentUrl );
+        }
+
+        try
+        {
+            if ( distributedBuildManager.isAgentAvailable( buildAgentUrl ) )
+            {
+                SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                    buildAgentUrl );
+                return client.getListener( releaseId );
+            }
+
+            // call reload in case we disable the build agent
+            distributedBuildManager.reload();
+
+            throw new ContinuumReleaseException( "Failed to get listener for " + releaseId +
+                                                     " because the build agent " + buildAgentUrl +
+                                                     " is not available" );
+        }
+        catch ( MalformedURLException e )
+        {
+            log.error( "Invalid build agent url " + buildAgentUrl );
+            throw new ContinuumReleaseException( "Invalid build agent url " + buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to get listener for " + releaseId, e );
+            throw new ContinuumReleaseException( "Failed to get listener for " + releaseId, e );
+        }
+    }
+
+    public void removeListener( String releaseId )
+        throws ContinuumReleaseException, BuildAgentConfigurationException
+    {
+        String buildAgentUrl = getBuildAgentUrl( releaseId );
+
+        if ( !checkBuildAgent( buildAgentUrl ) )
+        {
+            throw new BuildAgentConfigurationException( buildAgentUrl );
+        }
+
+        try
+        {
+            if ( distributedBuildManager.isAgentAvailable( buildAgentUrl ) )
+            {
+                SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                    buildAgentUrl );
+                client.removeListener( releaseId );
+            }
+
+            // call reload in case we disable the build agent
+            distributedBuildManager.reload();
+
+            throw new ContinuumReleaseException( "Failed to remove listener of " + releaseId +
+                                                     " because the build agent " + buildAgentUrl +
+                                                     " is not available" );
+        }
+        catch ( MalformedURLException e )
+        {
+            log.error( "Invalid build agent url " + buildAgentUrl );
+            throw new ContinuumReleaseException( "Invalid build agent url " + buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to remove listener of " + releaseId, e );
+            throw new ContinuumReleaseException( "Failed to remove listener of " + releaseId, e );
+        }
+    }
+
+    public String getPreparedReleaseName( String releaseId )
+        throws ContinuumReleaseException
+    {
+        String buildAgentUrl = getBuildAgentUrl( releaseId );
+
+        if ( StringUtils.isBlank( buildAgentUrl ) )
+        {
+            log.info( "Unable to get prepared release name because no build agent found for " + releaseId );
+            return null;
+        }
+
+        try
+        {
+            if ( distributedBuildManager.isAgentAvailable( buildAgentUrl ) )
+            {
+                SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                    buildAgentUrl );
+                return client.getPreparedReleaseName( releaseId );
+            }
+
+            // call reload in case we disable the build agent
+            distributedBuildManager.reload();
+
+            throw new ContinuumReleaseException( "Failed to get prepared release name of " + releaseId +
+                                                     " because the build agent " + buildAgentUrl +
+                                                     " is not available" );
+        }
+        catch ( MalformedURLException e )
+        {
+            log.error( "Invalid build agent url " + buildAgentUrl );
+            throw new ContinuumReleaseException( "Invalid build agent url " + buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to get prepared release name of " + releaseId, e );
+            throw new ContinuumReleaseException( "Failed to get prepared release name of " + releaseId, e );
+        }
+    }
+
+    public Map<String, String> getPreparedReleases( String groupId, String artifactId )
+        throws ContinuumReleaseException
+    {
+        String releaseId = ArtifactUtils.versionlessKey( groupId, artifactId );
+
+        Map<String, String> projectPreparedReleases = new LinkedHashMap<String, String>();
+        for ( PreparedRelease release : getPreparedReleases() )
+        {
+            // get exact match, or one with a timestamp appended
+            String id = release.getReleaseId();
+            if ( id.equals( releaseId ) || id.startsWith( releaseId + ":" ) )
+            {
+                projectPreparedReleases.put( id, release.getReleaseName() );
+            }
+        }
+        return projectPreparedReleases;
+    }
+
+    public void releasePerform( int projectId, String releaseId, String goals, String arguments,
+                                boolean useReleaseProfile, LocalRepository repository, String username )
+        throws ContinuumReleaseException, BuildAgentConfigurationException
+    {
+        List<PreparedRelease> releases = getPreparedReleases();
+
+        for ( PreparedRelease release : releases )
+        {
+            if ( release.getReleaseId().equals( releaseId ) )
+            {
+                release.setReleaseType( "perform" );
+                savePreparedReleases( releases );
+                break;
+            }
+        }
+
+        String buildAgentUrl = getBuildAgentUrl( releaseId );
+
+        if ( !checkBuildAgent( buildAgentUrl ) )
+        {
+            throw new BuildAgentConfigurationException( buildAgentUrl );
+        }
+
+        if ( goals == null )
+        {
+            goals = "";
+        }
+
+        if ( arguments == null )
+        {
+            arguments = "";
+        }
+
+        Map<String, String> map = new HashMap<String, String>();
+        map.put( DistributedReleaseUtil.KEY_USERNAME, username );
+
+        if ( repository != null )
+        {
+            map.put( DistributedReleaseUtil.KEY_LOCAL_REPOSITORY_NAME, repository.getName() );
+        }
+
+        try
+        {
+            if ( distributedBuildManager.isAgentAvailable( buildAgentUrl ) )
+            {
+                SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                    buildAgentUrl );
+                client.releasePerform( releaseId, goals, arguments, useReleaseProfile, map, username );
+
+                addReleaseInProgress( releaseId, "perform", projectId, username );
+            }
+            else
+            {
+                // call reload in case we disable the build agent
+                distributedBuildManager.reload();
+
+                throw new ContinuumReleaseException( "Failed to perform release of " + releaseId +
+                                                         " because the build agent " + buildAgentUrl +
+                                                         " is not available" );
+            }
+        }
+        catch ( MalformedURLException e )
+        {
+            log.error( "Invalid build agent url " + buildAgentUrl );
+            throw new ContinuumReleaseException( "Invalid build agent url " + buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to perform release of " + releaseId, e );
+            throw new ContinuumReleaseException( "Failed to perform release of " + releaseId, e );
+        }
+    }
+
+    public String releasePerformFromScm( int projectId, String goals, String arguments, boolean useReleaseProfile,
+                                         LocalRepository repository, String scmUrl, String scmUsername,
+                                         String scmPassword, String scmTag, String scmTagBase, Map environments,
+                                         String username )
+        throws ContinuumReleaseException, BuildAgentConfigurationException
+    {
+        String buildAgentUrl = (String) environments.get( DistributedReleaseUtil.KEY_BUILD_AGENT_URL );
+
+        if ( !checkBuildAgent( buildAgentUrl ) )
+        {
+            throw new BuildAgentConfigurationException( buildAgentUrl );
+        }
+
+        if ( goals == null )
+        {
+            goals = "";
+        }
+
+        if ( arguments == null )
+        {
+            arguments = "";
+        }
+
+        Map<String, String> map = new HashMap<String, String>();
+        map.put( DistributedReleaseUtil.KEY_USERNAME, username );
+
+        if ( repository != null )
+        {
+            map.put( DistributedReleaseUtil.KEY_LOCAL_REPOSITORY_NAME, repository.getName() );
+        }
+
+        try
+        {
+            if ( distributedBuildManager.isAgentAvailable( buildAgentUrl ) )
+            {
+                SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                    buildAgentUrl );
+                String releaseId = client.releasePerformFromScm( goals, arguments, useReleaseProfile, map, scmUrl,
+                                                                 scmUsername, scmPassword, scmTag, scmTagBase,
+                                                                 environments, username );
+
+                addReleasePrepare( releaseId, buildAgentUrl, scmTag, "perform", goals, username );
+                addReleaseInProgress( releaseId, "perform", projectId, username );
+
+                return releaseId;
+            }
+
+            // call reload in case we disable the build agent
+            distributedBuildManager.reload();
+
+            throw new ContinuumReleaseException(
+                "Failed to perform release because the build agent " + buildAgentUrl + " is not available" );
+        }
+        catch ( MalformedURLException e )
+        {
+            log.error( "Invalid build agent url " + buildAgentUrl );
+            throw new ContinuumReleaseException( "Invalid build agent url " + buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to perform release", e );
+            throw new ContinuumReleaseException( "Failed to perform release", e );
+        }
+    }
+
+    public void releaseRollback( String releaseId, int projectId )
+        throws ContinuumReleaseException, BuildAgentConfigurationException
+    {
+        String buildAgentUrl = getBuildAgentUrl( releaseId );
+
+        if ( !checkBuildAgent( buildAgentUrl ) )
+        {
+            throw new BuildAgentConfigurationException( buildAgentUrl );
+        }
+
+        try
+        {
+            if ( distributedBuildManager.isAgentAvailable( buildAgentUrl ) )
+            {
+                SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                    buildAgentUrl );
+                client.releaseRollback( releaseId, projectId );
+                return;
+            }
+
+            // call reload in case we disable the build agent
+            distributedBuildManager.reload();
+
+            throw new ContinuumReleaseException( "Unable to rollback release " + releaseId +
+                                                     " because the build agent " + buildAgentUrl +
+                                                     " is not available" );
+        }
+        catch ( MalformedURLException e )
+        {
+            log.error( "Invalid build agent url " + buildAgentUrl );
+            throw new ContinuumReleaseException( "Invalid build agent url " + buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Unable to rollback release " + releaseId, e );
+            throw new ContinuumReleaseException( e );
+        }
+    }
+
+    public String releaseCleanup( String releaseId )
+        throws ContinuumReleaseException, BuildAgentConfigurationException
+    {
+        String buildAgentUrl = getBuildAgentUrl( releaseId );
+
+        if ( !checkBuildAgent( buildAgentUrl ) )
+        {
+            throw new BuildAgentConfigurationException( buildAgentUrl );
+        }
+
+        try
+        {
+            if ( distributedBuildManager.isAgentAvailable( buildAgentUrl ) )
+            {
+                removeFromReleaseInProgress( releaseId );
+                removeFromPreparedReleases( releaseId );
+
+                SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                    buildAgentUrl );
+                String result = client.releaseCleanup( releaseId );
+
+                return result;
+            }
+
+            // call reload in case we disable the build agent
+            distributedBuildManager.reload();
+
+            throw new ContinuumReleaseException( "Failed to cleanup release of " + releaseId +
+                                                     " because the build agent " + buildAgentUrl +
+                                                     " is not available" );
+        }
+        catch ( MalformedURLException e )
+        {
+            log.error( "Invalid build agent url " + buildAgentUrl );
+            throw new ContinuumReleaseException( "Invalid build agent url " + buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to cleanup release of " + releaseId, e );
+            throw new ContinuumReleaseException( "Failed to cleanup release of " + releaseId, e );
+        }
+    }
+
+    public List<Map<String, Object>> getAllReleasesInProgress()
+        throws ContinuumReleaseException, BuildAgentConfigurationException
+    {
+        List<Map<String, Object>> releases = new ArrayList<Map<String, Object>>();
+        Map<String, Map<String, Object>> releasesMap = new HashMap<String, Map<String, Object>>();
+
+        if ( releasesInProgress != null && !releasesInProgress.isEmpty() )
+        {
+            for ( String releaseId : releasesInProgress.keySet() )
+            {
+                String buildAgentUrl = getBuildAgentUrl( releaseId );
+
+                if ( StringUtils.isNotBlank( buildAgentUrl ) )
+                {
+                    if ( !checkBuildAgent( buildAgentUrl ) )
+                    {
+                        throw new BuildAgentConfigurationException( buildAgentUrl );
+                    }
+
+                    try
+                    {
+                        if ( distributedBuildManager.isAgentAvailable( buildAgentUrl ) )
+                        {
+                            SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection(
+                                buildAgentUrl );
+                            Map map = client.getListener( releaseId );
+
+                            if ( map != null && !map.isEmpty() )
+                            {
+                                Map<String, Object> release = releasesInProgress.get( releaseId );
+                                release.put( DistributedReleaseUtil.KEY_RELEASE_ID, releaseId );
+                                release.put( DistributedReleaseUtil.KEY_BUILD_AGENT_URL, buildAgentUrl );
+
+                                releases.add( release );
+
+                                releasesMap.put( releaseId, releasesInProgress.get( releaseId ) );
+                            }
+                        }
+                    }
+                    catch ( MalformedURLException e )
+                    {
+                        log.error( "Invalid build agent url " + buildAgentUrl );
+                        throw new ContinuumReleaseException( "Invalid build agent url " + buildAgentUrl );
+                    }
+                    catch ( Exception e )
+                    {
+                        log.error( "Failed to get all releases in progress ", e );
+                        throw new ContinuumReleaseException( "Failed to get all releases in progress ", e );
+                    }
+                }
+            }
+
+            releasesInProgress = releasesMap;
+        }
+
+        try
+        {
+            // call reload in case we disable a build agent
+            distributedBuildManager.reload();
+        }
+        catch ( Exception e )
+        {
+            throw new ContinuumReleaseException( e.getMessage(), e );
+        }
+
+        return releases;
+    }
+
+    public String getDefaultBuildagent( int projectId )
+    {
+        BuildResult buildResult = buildResultDao.getLatestBuildResultForProject( projectId );
+
+        return buildResult != null ? buildResult.getBuildUrl() : null;
+    }
+
+    public PreparedRelease getPreparedRelease( String releaseId, String releaseType )
+        throws ContinuumReleaseException
+    {
+        List<PreparedRelease> releases = getPreparedReleases();
+
+        for ( PreparedRelease release : releases )
+        {
+            if ( release.getReleaseId().equals( releaseId ) && release.getReleaseType().equals( releaseType ) )
+            {
+                return release;
+            }
+        }
+
+        return null;
+    }
+
+    public SlaveBuildAgentTransportService createSlaveBuildAgentTransportClientConnection( String buildAgentUrl )
+        throws MalformedURLException, Exception
+    {
+        return new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ), "",
+                                                   configurationService.getSharedSecretPassword() );
+    }
+
+    private Map createProjectMap( Project project )
+    {
+        Map<String, Object> map = new HashMap<String, Object>();
+
+        map.put( DistributedReleaseUtil.KEY_PROJECT_ID, project.getId() );
+        map.put( DistributedReleaseUtil.KEY_GROUP_ID, project.getGroupId() );
+        map.put( DistributedReleaseUtil.KEY_ARTIFACT_ID, project.getArtifactId() );
+        map.put( DistributedReleaseUtil.KEY_SCM_URL, project.getScmUrl() );
+        if ( project.getProjectGroup().getLocalRepository() != null )
+        {
+            map.put( DistributedReleaseUtil.KEY_LOCAL_REPOSITORY_NAME,
+                     project.getProjectGroup().getLocalRepository().getName() );
+        }
+
+        return map;
+    }
+
+    private List<PreparedRelease> getPreparedReleases()
+        throws ContinuumReleaseException
+    {
+        File file = getPreparedReleasesFile();
+
+        if ( file.exists() )
+        {
+            FileInputStream fis = null;
+            try
+            {
+                fis = new FileInputStream( file );
+                ContinuumPrepareReleasesModelStaxReader reader = new ContinuumPrepareReleasesModelStaxReader();
+                PreparedReleaseModel model = reader.read( new InputStreamReader( fis ) );
+
+                return model.getPreparedReleases();
+            }
+            catch ( IOException e )
+            {
+                log.error( e.getMessage(), e );
+                throw new ContinuumReleaseException( "Unable to get prepared releases", e );
+            }
+            catch ( XMLStreamException e )
+            {
+                log.error( e.getMessage(), e );
+                throw new ContinuumReleaseException( e.getMessage(), e );
+            }
+            finally
+            {
+                if ( fis != null )
+                {
+                    IOUtil.close( fis );
+                }
+            }
+        }
+
+        return new ArrayList<PreparedRelease>();
+    }
+
+    private void addReleasePrepare( String releaseId, String buildAgentUrl, String releaseName, String releaseType,
+                                    String releaseGoals, String username )
+        throws ContinuumReleaseException
+    {
+        PreparedRelease release = new PreparedRelease();
+        release.setReleaseId( releaseId );
+        release.setBuildAgentUrl( buildAgentUrl );
+        release.setReleaseName( releaseName );
+        release.setReleaseType( releaseType );
+        release.setReleaseGoals( releaseGoals );
+        release.setReleaseBy( username );
+
+        List<PreparedRelease> preparedReleases = getPreparedReleases();
+
+        if ( preparedReleases == null )
+        {
+            preparedReleases = new ArrayList<PreparedRelease>();
+        }
+
+        for ( PreparedRelease preparedRelease : preparedReleases )
+        {
+            if ( preparedRelease.getReleaseId().equals( release.getReleaseId() ) )
+            {
+                preparedReleases.remove( preparedRelease );
+                break;
+            }
+        }
+
+        preparedReleases.add( release );
+
+        savePreparedReleases( preparedReleases );
+    }
+
+    private void addReleaseInProgress( String releaseId, String releaseType, int projectId, String username )
+    {
+        if ( releasesInProgress == null )
+        {
+            releasesInProgress = new HashMap<String, Map<String, Object>>();
+        }
+
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put( DistributedReleaseUtil.KEY_RELEASE_GOAL, releaseType );
+        map.put( DistributedReleaseUtil.KEY_PROJECT_ID, projectId );
+        map.put( DistributedReleaseUtil.KEY_USERNAME, username );
+
+        releasesInProgress.put( releaseId, map );
+    }
+
+    private void removeFromReleaseInProgress( String releaseId )
+    {
+        if ( releasesInProgress != null && releasesInProgress.containsKey( releaseId ) )
+        {
+            releasesInProgress.remove( releaseId );
+        }
+    }
+
+    private String getBuildAgentUrl( String releaseId )
+        throws ContinuumReleaseException
+    {
+        List<PreparedRelease> preparedReleases = getPreparedReleases();
+
+        if ( preparedReleases != null )
+        {
+            for ( PreparedRelease preparedRelease : preparedReleases )
+            {
+                if ( preparedRelease.getReleaseId().equals( releaseId ) )
+                {
+                    return preparedRelease.getBuildAgentUrl();
+                }
+            }
+        }
+
+        return null;
+    }
+
+    private File getPreparedReleasesFile()
+    {
+        return new File( System.getProperty( "appserver.base" ) + File.separator + "conf" + File.separator +
+                             PREPARED_RELEASES_FILENAME );
+    }
+
+    private boolean checkBuildAgent( String buildAgentUrl )
+    {
+        BuildAgentConfiguration buildAgent = configurationService.getBuildAgent( buildAgentUrl );
+
+        if ( buildAgent != null && buildAgent.isEnabled() )
+        {
+            return true;
+        }
+
+        log.info( "Build agent: " + buildAgentUrl + " is either disabled or removed" );
+        return false;
+    }
+
+    private void removeFromPreparedReleases( String releaseId )
+        throws ContinuumReleaseException
+    {
+        List<PreparedRelease> releases = getPreparedReleases();
+
+        for ( PreparedRelease release : releases )
+        {
+            if ( release.getReleaseId().equals( releaseId ) )
+            {
+                if ( release.getReleaseType().equals( "perform" ) )
+                {
+                    releases.remove( release );
+                    savePreparedReleases( releases );
+                    break;
+                }
+            }
+        }
+    }
+
+    private void savePreparedReleases( List<PreparedRelease> preparedReleases )
+        throws ContinuumReleaseException
+    {
+        File file = getPreparedReleasesFile();
+
+        if ( !file.exists() )
+        {
+            file.getParentFile().mkdirs();
+        }
+
+        PreparedReleaseModel model = new PreparedReleaseModel();
+        model.setPreparedReleases( preparedReleases );
+
+        FileWriter fileWriter = null;
+        try
+        {
+            ContinuumPrepareReleasesModelStaxWriter writer = new ContinuumPrepareReleasesModelStaxWriter();
+            fileWriter = new FileWriter( file );
+            writer.write( fileWriter, model );
+            fileWriter.flush();
+        }
+        catch ( IOException e )
+        {
+            throw new ContinuumReleaseException( "Failed to write prepared releases in file", e );
+        }
+        catch ( XMLStreamException e )
+        {
+            throw new ContinuumReleaseException( "Failed to write prepared releases in file", e );
+        }
+        finally
+        {
+            IOUtil.close( fileWriter );
+        }
+    }
+
+    // for unit test
+
+    public void setBuildResultDao( BuildResultDao buildResultDao )
+    {
+        this.buildResultDao = buildResultDao;
+    }
+}
diff --git a/continuum-core/src/main/java/org/apache/continuum/repository/DefaultRepositoryService.java b/continuum-core/src/main/java/org/apache/continuum/repository/DefaultRepositoryService.java
index 928b876..5fbdb24 100644
--- a/continuum-core/src/main/java/org/apache/continuum/repository/DefaultRepositoryService.java
+++ b/continuum-core/src/main/java/org/apache/continuum/repository/DefaultRepositoryService.java
@@ -45,7 +45,7 @@
 public class DefaultRepositoryService
     implements RepositoryService
 {
-    private Logger log = LoggerFactory.getLogger( DefaultRepositoryService.class );
+    private static final Logger log = LoggerFactory.getLogger( DefaultRepositoryService.class );
 
     /**
      * @plexus.requirement
@@ -81,7 +81,7 @@
                 {
                     throw new RepositoryServiceException( "Local repository name must be unique" );
                 }
-                
+
                 if ( repo.getLocation().equals( localRepository.getLocation() ) )
                 {
                     throw new RepositoryServiceException( "Local repository location must be unique" );
@@ -216,6 +216,23 @@
         }
     }
 
+    public LocalRepository getLocalRepositoryByName( String repositoryName )
+        throws RepositoryServiceException
+    {
+        try
+        {
+            return localRepositoryDao.getLocalRepositoryByName( repositoryName );
+        }
+        catch ( ContinuumObjectNotFoundException e )
+        {
+            throw new RepositoryServiceException( "No repository found with name: " + repositoryName, e );
+        }
+        catch ( ContinuumStoreException e )
+        {
+            throw new RepositoryServiceException( "Unable to retrieve local repository: " + repositoryName, e );
+        }
+    }
+
     private void removePurgeConfigurationsOfRepository( int repositoryId )
         throws RepositoryServiceException
     {
diff --git a/continuum-core/src/main/java/org/apache/continuum/taskqueue/DefaultOverallBuildQueue.java b/continuum-core/src/main/java/org/apache/continuum/taskqueue/DefaultOverallBuildQueue.java
new file mode 100644
index 0000000..e8b1d2c
--- /dev/null
+++ b/continuum-core/src/main/java/org/apache/continuum/taskqueue/DefaultOverallBuildQueue.java
@@ -0,0 +1,716 @@
+package org.apache.continuum.taskqueue;
+
+/*
+ * 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 org.apache.commons.lang.ArrayUtils;
+import org.apache.continuum.dao.BuildDefinitionDao;
+import org.apache.continuum.taskqueueexecutor.ParallelBuildsThreadedTaskQueueExecutor;
+import org.apache.continuum.utils.build.BuildTrigger;
+import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.store.ContinuumStoreException;
+import org.codehaus.plexus.taskqueue.Task;
+import org.codehaus.plexus.taskqueue.TaskQueue;
+import org.codehaus.plexus.taskqueue.TaskQueueException;
+import org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor;
+import org.codehaus.plexus.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.annotation.Resource;
+
+/**
+ * "Overall" build queue which has a checkout queue and a build queue.
+ *
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ * @version $Id$
+ */
+public class DefaultOverallBuildQueue
+    implements OverallBuildQueue
+{
+    private static final Logger log = LoggerFactory.getLogger( DefaultOverallBuildQueue.class );
+
+    @Resource
+    private BuildDefinitionDao buildDefinitionDao;
+
+    private TaskQueueExecutor buildTaskQueueExecutor;
+
+    private TaskQueueExecutor checkoutTaskQueueExecutor;
+
+    private TaskQueueExecutor prepareBuildTaskQueueExecutor;
+
+    private int id;
+
+    private String name;
+
+    public int getId()
+    {
+        return id;
+    }
+
+    public void setId( int id )
+    {
+        this.id = id;
+    }
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName( String name )
+    {
+        this.name = name;
+    }
+
+    /**
+     * @see OverallBuildQueue#addToCheckoutQueue(CheckOutTask)
+     */
+    public void addToCheckoutQueue( CheckOutTask checkoutTask )
+        throws TaskQueueException
+    {
+        getCheckoutQueue().put( checkoutTask );
+    }
+
+    /**
+     * @see OverallBuildQueue#addToCheckoutQueue(List)
+     */
+    public void addToCheckoutQueue( List<CheckOutTask> checkoutTasks )
+        throws TaskQueueException
+    {
+        for ( CheckOutTask checkoutTask : checkoutTasks )
+        {
+            getCheckoutQueue().put( checkoutTask );
+        }
+    }
+
+    /**
+     * @see OverallBuildQueue#getProjectsInCheckoutQueue()
+     */
+    public List<CheckOutTask> getProjectsInCheckoutQueue()
+        throws TaskQueueException
+    {
+        return getCheckoutQueue().getQueueSnapshot();
+    }
+
+    /**
+     * @see OverallBuildQueue#isInCheckoutQueue(int)
+     */
+    public boolean isInCheckoutQueue( int projectId )
+        throws TaskQueueException
+    {
+        List<CheckOutTask> queue = getProjectsInCheckoutQueue();
+
+        for ( CheckOutTask task : queue )
+        {
+            if ( task != null && task.getProjectId() == projectId )
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * @see OverallBuildQueue#removeProjectFromCheckoutQueue(int)
+     */
+    public boolean removeProjectFromCheckoutQueue( int projectId )
+        throws TaskQueueException
+    {
+        List<CheckOutTask> queue = getProjectsInCheckoutQueue();
+
+        for ( CheckOutTask task : queue )
+        {
+            if ( task != null && task.getProjectId() == projectId )
+            {
+                return getCheckoutQueue().remove( task );
+            }
+        }
+        return false;
+    }
+
+    /**
+     * @see OverallBuildQueue#removeProjectsFromCheckoutQueue(int[])
+     */
+    public boolean removeProjectsFromCheckoutQueue( int[] projectsId )
+        throws TaskQueueException
+    {
+        if ( projectsId == null )
+        {
+            return false;
+        }
+        if ( projectsId.length < 1 )
+        {
+            return false;
+        }
+        List<CheckOutTask> queue = getProjectsInCheckoutQueue();
+
+        List<CheckOutTask> tasks = new ArrayList<CheckOutTask>();
+
+        for ( CheckOutTask task : queue )
+        {
+            if ( task != null )
+            {
+                if ( ArrayUtils.contains( projectsId, task.getProjectId() ) )
+                {
+                    tasks.add( task );
+                }
+            }
+        }
+        return !tasks.isEmpty() && getCheckoutQueue().removeAll( tasks );
+    }
+
+    /**
+     * @see OverallBuildQueue#removeTasksFromCheckoutQueueWithHashCodes(int[])
+     */
+    public void removeTasksFromCheckoutQueueWithHashCodes( int[] hashCodes )
+        throws TaskQueueException
+    {
+        List<CheckOutTask> queue = getProjectsInCheckoutQueue();
+
+        for ( CheckOutTask task : queue )
+        {
+            if ( ArrayUtils.contains( hashCodes, task.hashCode() ) )
+            {
+                getCheckoutQueue().remove( task );
+            }
+        }
+    }
+
+    /**
+     * @see OverallBuildQueue#addToBuildQueue(BuildProjectTask)
+     */
+    public void addToBuildQueue( BuildProjectTask buildTask )
+        throws TaskQueueException
+    {
+        getBuildQueue().put( buildTask );
+    }
+
+    /**
+     * @see OverallBuildQueue#addToBuildQueue(List)
+     */
+    public void addToBuildQueue( List<BuildProjectTask> buildTasks )
+        throws TaskQueueException
+    {
+        for ( BuildProjectTask buildTask : buildTasks )
+        {
+            getBuildQueue().put( buildTask );
+        }
+    }
+
+    /**
+     * @see OverallBuildQueue#getProjectsInBuildQueue()
+     */
+    public List<BuildProjectTask> getProjectsInBuildQueue()
+        throws TaskQueueException
+    {
+        return getBuildQueue().getQueueSnapshot();
+    }
+
+    /**
+     * @see OverallBuildQueue#isInBuildQueue(int)
+     */
+    public boolean isInBuildQueue( int projectId )
+        throws TaskQueueException
+    {
+        return isInBuildQueue( projectId, -1 );
+    }
+
+    /**
+     * @see OverallBuildQueue#isInBuildQueue(int, int)
+     */
+    public boolean isInBuildQueue( int projectId, int buildDefinitionId )
+        throws TaskQueueException
+    {
+        List<BuildProjectTask> queue = getProjectsInBuildQueue();
+        for ( BuildProjectTask buildTask : queue )
+        {
+            if ( buildTask != null )
+            {
+                if ( buildDefinitionId < 0 )
+                {
+                    if ( buildTask.getProjectId() == projectId )
+                    {
+                        return true;
+                    }
+                }
+                else
+                {
+                    if ( buildTask.getProjectId() == projectId &&
+                        buildTask.getBuildDefinitionId() == buildDefinitionId )
+                    {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * @see OverallBuildQueue#cancelBuildTask(int)
+     */
+    public void cancelBuildTask( int projectId )
+    {
+        BuildProjectTask task = (BuildProjectTask) buildTaskQueueExecutor.getCurrentTask();
+        if ( task != null && task.getProjectId() == projectId )
+        {
+            log.info(
+                "Cancelling build task for project '" + projectId + "' in task executor '" + buildTaskQueueExecutor );
+            buildTaskQueueExecutor.cancelTask( task );
+        }
+    }
+
+    /**
+     * @see OverallBuildQueue#cancelCheckoutTask(int)
+     */
+    public void cancelCheckoutTask( int projectId )
+        throws TaskQueueException
+    {
+        CheckOutTask task = (CheckOutTask) checkoutTaskQueueExecutor.getCurrentTask();
+        if ( task != null && task.getProjectId() == projectId )
+        {
+            log.info( "Cancelling checkout task for project '" + projectId + "' in task executor '" +
+                          checkoutTaskQueueExecutor );
+            checkoutTaskQueueExecutor.cancelTask( task );
+        }
+    }
+
+    /**
+     * @see OverallBuildQueue#cancelCurrentBuild()
+     */
+    public boolean cancelCurrentBuild()
+    {
+        Task task = buildTaskQueueExecutor.getCurrentTask();
+        if ( task != null )
+        {
+            return buildTaskQueueExecutor.cancelTask( task );
+        }
+
+        log.info( "No build task currently executing on build executor: " + buildTaskQueueExecutor );
+        return false;
+    }
+
+    /**
+     * @see OverallBuildQueue#cancelCurrentCheckout()
+     */
+    public boolean cancelCurrentCheckout()
+    {
+        Task task = checkoutTaskQueueExecutor.getCurrentTask();
+        if ( task != null )
+        {
+            return checkoutTaskQueueExecutor.cancelTask( task );
+        }
+
+        log.info( "No checkout task currently executing on checkout task executor: " + checkoutTaskQueueExecutor );
+        return false;
+    }
+
+    /**
+     * @see OverallBuildQueue#removeProjectFromBuildQueue(int, int, BuildTrigger, String, int)
+     */
+    public boolean removeProjectFromBuildQueue( int projectId, int buildDefinitionId, BuildTrigger buildTrigger,
+                                                String projectName, int projectGroupId )
+        throws TaskQueueException
+    {
+        BuildDefinition buildDefinition;
+
+        // maybe we could just pass the label as a parameter to eliminate dependency to BuildDefinitionDAO?
+        try
+        {
+            buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
+        }
+        catch ( ContinuumStoreException e )
+        {
+            throw new TaskQueueException( "Error while removing project from build queue: " + projectName, e );
+        }
+
+        String buildDefinitionLabel = buildDefinition.getDescription();
+        if ( StringUtils.isEmpty( buildDefinitionLabel ) )
+        {
+            buildDefinitionLabel = buildDefinition.getGoals();
+        }
+
+        BuildProjectTask buildProjectTask = new BuildProjectTask( projectId, buildDefinitionId, buildTrigger,
+                                                                  projectName, buildDefinitionLabel, null,
+                                                                  projectGroupId );
+
+        return getBuildQueue().remove( buildProjectTask );
+    }
+
+    /**
+     * @see OverallBuildQueue#removeProjectsFromBuildQueue(int[])
+     */
+    public boolean removeProjectsFromBuildQueue( int[] projectIds )
+        throws TaskQueueException
+    {
+        if ( projectIds == null )
+        {
+            return false;
+        }
+        if ( projectIds.length < 1 )
+        {
+            return false;
+        }
+        List<BuildProjectTask> queue = getProjectsInBuildQueue();
+
+        List<BuildProjectTask> tasks = new ArrayList<BuildProjectTask>();
+
+        for ( BuildProjectTask buildTask : queue )
+        {
+            if ( buildTask != null )
+            {
+                if ( ArrayUtils.contains( projectIds, buildTask.getProjectId() ) )
+                {
+                    tasks.add( buildTask );
+                }
+            }
+        }
+
+        for ( BuildProjectTask buildProjectTask : tasks )
+        {
+            log.info( "cancel build for project " + buildProjectTask.getProjectId() );
+        }
+
+        return !tasks.isEmpty() && getBuildQueue().removeAll( tasks );
+    }
+
+    /**
+     * @see OverallBuildQueue#removeProjectFromBuildQueue(int)
+     */
+    public boolean removeProjectFromBuildQueue( int projectId )
+        throws TaskQueueException
+    {
+        List<BuildProjectTask> queue = getProjectsInBuildQueue();
+
+        for ( BuildProjectTask buildTask : queue )
+        {
+            if ( buildTask != null && buildTask.getProjectId() == projectId )
+            {
+                return getBuildQueue().remove( buildTask );
+            }
+        }
+        return false;
+    }
+
+    /**
+     * @see OverallBuildQueue#removeProjectsFromBuildQueueWithHashCodes(int[])
+     */
+    public void removeProjectsFromBuildQueueWithHashCodes( int[] hashCodes )
+        throws TaskQueueException
+    {
+        List<BuildProjectTask> queue = getProjectsInBuildQueue();
+        for ( BuildProjectTask task : queue )
+        {
+            if ( ArrayUtils.contains( hashCodes, task.hashCode() ) )
+            {
+                getBuildQueue().remove( task );
+            }
+        }
+    }
+
+    /* Prepare Build */
+
+    /**
+     * @see OverallBuildQueue#addToPrepareBuildQueue(PrepareBuildProjectsTask)
+     */
+    public void addToPrepareBuildQueue( PrepareBuildProjectsTask prepareBuildTask )
+        throws TaskQueueException
+    {
+        getPrepareBuildQueue().put( prepareBuildTask );
+    }
+
+    /**
+     * @see OverallBuildQueue#addToPrepareBuildQueue(List)
+     */
+    public void addToPrepareBuildQueue( List<PrepareBuildProjectsTask> prepareBuildTasks )
+        throws TaskQueueException
+    {
+        for ( PrepareBuildProjectsTask prepareBuildTask : prepareBuildTasks )
+        {
+            getPrepareBuildQueue().put( prepareBuildTask );
+        }
+    }
+
+    /**
+     * @see OverallBuildQueue#getProjectsInPrepareBuildQueue()
+     */
+    public List<PrepareBuildProjectsTask> getProjectsInPrepareBuildQueue()
+        throws TaskQueueException
+    {
+        return getPrepareBuildQueue().getQueueSnapshot();
+    }
+
+    /**
+     * @see OverallBuildQueue#isInPrepareBuildQueue(int)
+     */
+    public boolean isInPrepareBuildQueue( int projectId )
+        throws TaskQueueException
+    {
+        List<PrepareBuildProjectsTask> queue = getProjectsInPrepareBuildQueue();
+        for ( PrepareBuildProjectsTask task : queue )
+        {
+            if ( task != null )
+            {
+                Map<Integer, Integer> map = task.getProjectsBuildDefinitionsMap();
+
+                if ( map.size() > 0 )
+                {
+                    Set<Integer> projectIds = map.keySet();
+
+                    if ( projectIds.contains( new Integer( projectId ) ) )
+                    {
+                        log.info( "Project {} is already in prepare build queue", projectId );
+                        return true;
+                    }
+                }
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * @see OverallBuildQueue#isInPrepareBuildQueue(int, int)
+     */
+    public boolean isInPrepareBuildQueue( int projectGroupId, int scmRootId )
+        throws TaskQueueException
+    {
+        List<PrepareBuildProjectsTask> queue = getProjectsInPrepareBuildQueue();
+        for ( PrepareBuildProjectsTask task : queue )
+        {
+            if ( task != null && task.getProjectGroupId() == projectGroupId && task.getProjectScmRootId() == scmRootId )
+            {
+                log.info( "Project group {} with scm root {} is in prepare build queue {}",
+                          new Object[]{projectGroupId, scmRootId, task} );
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * @see OverallBuildQueue#isInPrepareBuildQueue(int, String)
+     */
+    public boolean isInPrepareBuildQueue( int projectGroupId, String scmRootAddress )
+        throws TaskQueueException
+    {
+        List<PrepareBuildProjectsTask> queue = getProjectsInPrepareBuildQueue();
+        for ( PrepareBuildProjectsTask task : queue )
+        {
+            if ( task != null && task.getProjectGroupId() == projectGroupId && task.getScmRootAddress().equals(
+                scmRootAddress ) )
+            {
+                log.info( "Project group {} with scm root {} is in prepare build queue {}",
+                          new Object[]{projectGroupId, scmRootAddress, task} );
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * @see OverallBuildQueue#cancelPrepareBuildTask(int, int)
+     */
+    public void cancelPrepareBuildTask( int projectGroupId, int scmRootId )
+    {
+        PrepareBuildProjectsTask task = (PrepareBuildProjectsTask) prepareBuildTaskQueueExecutor.getCurrentTask();
+        if ( task != null && task.getProjectGroupId() == projectGroupId && task.getProjectScmRootId() == scmRootId )
+        {
+            log.info( "Cancelling prepare build task for project group '{}' with scmRootId '{}' in task executor '{}'",
+                      new Object[]{projectGroupId, scmRootId, prepareBuildTaskQueueExecutor} );
+            prepareBuildTaskQueueExecutor.cancelTask( task );
+        }
+    }
+
+    /**
+     * @see OverallBuildQueue#cancelPrepareBuildTask(int)
+     */
+    public void cancelPrepareBuildTask( int projectId )
+    {
+        PrepareBuildProjectsTask task = (PrepareBuildProjectsTask) prepareBuildTaskQueueExecutor.getCurrentTask();
+        if ( task != null )
+        {
+            Map<Integer, Integer> map = task.getProjectsBuildDefinitionsMap();
+
+            if ( map.size() > 0 )
+            {
+                Set<Integer> projectIds = map.keySet();
+
+                if ( projectIds.contains( new Integer( projectId ) ) )
+                {
+                    log.info( "Cancelling prepare build task for project '{}' in task executor '{}'", projectId,
+                              prepareBuildTaskQueueExecutor );
+                    prepareBuildTaskQueueExecutor.cancelTask( task );
+                }
+            }
+        }
+    }
+
+    /**
+     * @see OverallBuildQueue#cancelCurrentPrepareBuild()
+     */
+    public boolean cancelCurrentPrepareBuild()
+    {
+        Task task = prepareBuildTaskQueueExecutor.getCurrentTask();
+        if ( task != null )
+        {
+            return prepareBuildTaskQueueExecutor.cancelTask( task );
+        }
+
+        log.info( "No prepare build task currently executing on build executor: {}", buildTaskQueueExecutor );
+        return false;
+    }
+
+    /**
+     * @see OverallBuildQueue#removeProjectFromPrepareBuildQueue(int, int)
+     */
+    public boolean removeProjectFromPrepareBuildQueue( int projectGroupId, int scmRootId )
+        throws TaskQueueException
+    {
+        List<PrepareBuildProjectsTask> tasks = getProjectsInPrepareBuildQueue();
+
+        if ( tasks != null )
+        {
+            for ( PrepareBuildProjectsTask task : tasks )
+            {
+                if ( task.getProjectGroupId() == projectGroupId && task.getProjectScmRootId() == scmRootId )
+                {
+                    return getPrepareBuildQueue().remove( task );
+                }
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * @see OverallBuildQueue#removeProjectFromPrepareBuildQueue(int, String)
+     */
+    public boolean removeProjectFromPrepareBuildQueue( int projectGroupId, String scmRootAddress )
+        throws TaskQueueException
+    {
+        List<PrepareBuildProjectsTask> queue = getProjectsInPrepareBuildQueue();
+
+        for ( PrepareBuildProjectsTask task : queue )
+        {
+            if ( task != null && task.getProjectGroupId() == projectGroupId &&
+                task.getScmRootAddress().equals( scmRootAddress ) )
+            {
+                return getPrepareBuildQueue().remove( task );
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * @see OverallBuildQueue#removeProjectsFromPrepareBuildQueueWithHashCodes(int[])
+     */
+    public void removeProjectsFromPrepareBuildQueueWithHashCodes( int[] hashCodes )
+        throws TaskQueueException
+    {
+        List<PrepareBuildProjectsTask> tasks = getProjectsInPrepareBuildQueue();
+
+        if ( tasks != null )
+        {
+            for ( PrepareBuildProjectsTask task : tasks )
+            {
+                if ( ArrayUtils.contains( hashCodes, task.getHashCode() ) )
+                {
+                    getPrepareBuildQueue().remove( task );
+                }
+            }
+        }
+    }
+
+    /**
+     * @see OverallBuildQueue#getCheckoutQueue()
+     */
+    public TaskQueue getCheckoutQueue()
+    {
+        return ( (ParallelBuildsThreadedTaskQueueExecutor) checkoutTaskQueueExecutor ).getQueue();
+    }
+
+    /**
+     * @see OverallBuildQueue#getBuildQueue()
+     */
+    public TaskQueue getBuildQueue()
+    {
+        return ( (ParallelBuildsThreadedTaskQueueExecutor) buildTaskQueueExecutor ).getQueue();
+    }
+
+    /**
+     * @see OverallBuildQueue#getPrepareBuildQueue()
+     */
+    public TaskQueue getPrepareBuildQueue()
+    {
+        return ( (ParallelBuildsThreadedTaskQueueExecutor) prepareBuildTaskQueueExecutor ).getQueue();
+    }
+
+    /**
+     * @see OverallBuildQueue#getBuildTaskQueueExecutor()
+     */
+    public TaskQueueExecutor getBuildTaskQueueExecutor()
+    {
+        return buildTaskQueueExecutor;
+    }
+
+    /**
+     * @see OverallBuildQueue#getCheckoutTaskQueueExecutor()
+     */
+    public TaskQueueExecutor getCheckoutTaskQueueExecutor()
+    {
+        return checkoutTaskQueueExecutor;
+    }
+
+    /**
+     * @see OverallBuildQueue#getPrepareBuildTaskQueueExecutor()
+     */
+    public TaskQueueExecutor getPrepareBuildTaskQueueExecutor()
+    {
+        return prepareBuildTaskQueueExecutor;
+    }
+
+    public void setBuildDefinitionDao( BuildDefinitionDao buildDefinitionDao )
+    {
+        this.buildDefinitionDao = buildDefinitionDao;
+    }
+
+    public void setBuildTaskQueueExecutor( TaskQueueExecutor buildTaskQueueExecutor )
+    {
+        this.buildTaskQueueExecutor = buildTaskQueueExecutor;
+    }
+
+    public void setCheckoutTaskQueueExecutor( TaskQueueExecutor checkoutTaskQueueExecutor )
+    {
+        this.checkoutTaskQueueExecutor = checkoutTaskQueueExecutor;
+    }
+
+    public void setPrepareBuildTaskQueueExecutor( TaskQueueExecutor prepareBuildTaskQueueExecutor )
+    {
+        this.prepareBuildTaskQueueExecutor = prepareBuildTaskQueueExecutor;
+    }
+}
diff --git a/continuum-core/src/main/java/org/apache/continuum/taskqueue/manager/DefaultTaskQueueManager.java b/continuum-core/src/main/java/org/apache/continuum/taskqueue/manager/DefaultTaskQueueManager.java
index 9313e13..63df794 100644
--- a/continuum-core/src/main/java/org/apache/continuum/taskqueue/manager/DefaultTaskQueueManager.java
+++ b/continuum-core/src/main/java/org/apache/continuum/taskqueue/manager/DefaultTaskQueueManager.java
@@ -19,24 +19,19 @@
  * under the License.
  */
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
 import org.apache.commons.lang.ArrayUtils;
-import org.apache.continuum.dao.BuildDefinitionDao;
+import org.apache.continuum.buildmanager.BuildManagerException;
+import org.apache.continuum.buildmanager.BuildsManager;
 import org.apache.continuum.dao.ProjectDao;
 import org.apache.continuum.model.repository.LocalRepository;
 import org.apache.continuum.model.repository.RepositoryPurgeConfiguration;
 import org.apache.continuum.purge.PurgeConfigurationService;
 import org.apache.continuum.purge.task.PurgeTask;
 import org.apache.continuum.taskqueue.BuildProjectTask;
-import org.apache.continuum.taskqueue.CheckOutTask;
 import org.apache.continuum.taskqueue.PrepareBuildProjectsTask;
-import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.release.tasks.PerformReleaseProjectTask;
+import org.apache.maven.continuum.release.tasks.PrepareReleaseProjectTask;
 import org.apache.maven.continuum.store.ContinuumStoreException;
 import org.codehaus.plexus.PlexusConstants;
 import org.codehaus.plexus.PlexusContainer;
@@ -48,10 +43,14 @@
 import org.codehaus.plexus.taskqueue.TaskQueue;
 import org.codehaus.plexus.taskqueue.TaskQueueException;
 import org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor;
-import org.codehaus.plexus.util.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 /**
  * @author <a href="mailto:ctan@apache.org">Maria Catherine Tan</a>
  * @plexus.component role="org.apache.continuum.taskqueue.manager.TaskQueueManager" role-hint="default"
@@ -59,33 +58,28 @@
 public class DefaultTaskQueueManager
     implements TaskQueueManager, Contextualizable
 {
-    private Logger log = LoggerFactory.getLogger( DefaultTaskQueueManager.class );
+    private static final Logger log = LoggerFactory.getLogger( DefaultTaskQueueManager.class );
 
     /**
-     * @plexus.requirement role-hint="build-project"
+     * @plexus.requirement role-hint="distributed-build-project"
      */
-    private TaskQueue buildQueue;
-
-    /**
-     * @plexus.requirement role-hint="check-out-project"
-     */
-    private TaskQueue checkoutQueue;
-
-    /**
-     * @plexus.requirement role-hint="prepare-build-project"
-     */
-    private TaskQueue prepareBuildQueue;
+    private TaskQueue distributedBuildQueue;
 
     /**
      * @plexus.requirement role-hint="purge"
      */
     private TaskQueue purgeQueue;
-    
+
     /**
-     * @plexus.requirement
+     * @plexus.requirement role-hint="prepare-release"
      */
-    private BuildDefinitionDao buildDefinitionDao;
-    
+    private TaskQueue prepareReleaseQueue;
+
+    /**
+     * @plexus.requirement role-hint="perform-release"
+     */
+    private TaskQueue performReleaseQueue;
+
     /**
      * @plexus.requirement
      */
@@ -95,176 +89,13 @@
      * @plexus.requirement
      */
     private PurgeConfigurationService purgeConfigurationService;
-    
-    private PlexusContainer container;
 
     /**
-     * @plexus.requirement role-hint="distributed-build-project"
+     * @plexus.requirement role-hint="parallel"
      */
-    private TaskQueue distributedBuildQueue;
+    private BuildsManager buildsManager;
 
-    public boolean buildInProgress()
-        throws TaskQueueManagerException
-    {
-        Task task = getCurrentTask( "build-project" );
-    
-        if ( task != null && task instanceof BuildProjectTask )
-        {
-            return true;
-        }
-    
-        return false;
-    }
-    
-    public void cancelBuildTask( int projectId )
-        throws TaskQueueManagerException
-    {
-        Task currentTask = getBuildTaskQueueExecutor().getCurrentTask();
-        
-        if ( currentTask != null )
-        {
-            if ( currentTask instanceof BuildProjectTask )
-            {
-                if ( ( (BuildProjectTask) currentTask ).getProjectId() == projectId )
-                {
-                    log.info( "Cancelling task for project " + projectId );
-                    getBuildTaskQueueExecutor().cancelTask( currentTask );
-                }
-                else
-                {
-                    log.warn( "Current task is not for the given projectId (" + projectId + "): "
-                                          + ( (BuildProjectTask) currentTask ).getProjectId() + "; not cancelling" );
-                }
-            }
-            else
-            {
-                log.warn( "Current task not a BuildProjectTask - not cancelling" );
-            }
-        }
-        else
-        {
-            log.warn( "No task running - not cancelling" );
-        }
-    }
-
-    public boolean cancelCheckout( int projectId )
-        throws TaskQueueManagerException
-    {
-        Task task = getCheckoutTaskQueueExecutor().getCurrentTask();
-
-        if ( task != null )
-        {
-            if ( task instanceof CheckOutTask )
-            {
-                if ( ( (CheckOutTask) task ).getProjectId() == projectId )
-                {
-                    log.info( "Cancelling checkout for project " + projectId );
-                    return getCheckoutTaskQueueExecutor().cancelTask( task );
-                }
-                else
-                {
-                    log.warn( "Current task is not for the given projectId (" + projectId + "): "
-                                          + ( (CheckOutTask) task ).getProjectId() + "; not cancelling checkout" );
-                }
-            }
-            else
-            {
-                log.warn( "Current task not a CheckOutTask - not cancelling checkout" );
-            }
-        }
-        else
-        {
-            log.warn( "No task running - not cancelling checkout" );
-        }
-        return false;
-    }
-
-    public boolean cancelCurrentBuild()
-        throws TaskQueueManagerException
-    {
-        Task task = getBuildTaskQueueExecutor().getCurrentTask();
-        
-        if ( task != null )
-        {
-            if ( task instanceof BuildProjectTask )
-            {
-                log.info( "Cancelling current build task" );
-                return getBuildTaskQueueExecutor().cancelTask( task );
-            }
-            else
-            {
-                log.warn( "Current task not a BuildProjectTask - not cancelling" );
-            }
-        }
-        else
-        {
-            log.warn( "No task running - not cancelling" );
-        }
-        return false;
-    }
-
-    public TaskQueue getBuildQueue()
-    {
-        return buildQueue;
-    }
-
-    public TaskQueueExecutor getBuildTaskQueueExecutor()
-        throws TaskQueueManagerException
-    {
-        try
-        {
-            return (TaskQueueExecutor) container.lookup( TaskQueueExecutor.class, "build-project" );
-        }
-        catch ( ComponentLookupException e )
-        {
-            throw new TaskQueueManagerException( e.getMessage(), e );
-        }
-    }
-
-    public TaskQueueExecutor getCheckoutTaskQueueExecutor()
-        throws TaskQueueManagerException
-    {
-        try
-        {
-            return (TaskQueueExecutor) container.lookup( TaskQueueExecutor.class, "check-out-project" );
-        }
-        catch ( ComponentLookupException e )
-        {
-            throw new TaskQueueManagerException( e.getMessage(), e );
-        }
-    }
-
-    public TaskQueue getCheckoutQueue()
-    {
-        return checkoutQueue;
-    }
-    
-    public List<CheckOutTask> getCheckOutTasksInQueue()
-        throws TaskQueueManagerException
-    {
-        try
-        {
-            return checkoutQueue.getQueueSnapshot();
-        }
-        catch ( TaskQueueException e )
-        {
-            throw new TaskQueueManagerException( "Error while getting the checkout queue.", e );
-        }
-    }
-
-    public int getCurrentProjectIdBuilding()
-        throws TaskQueueManagerException
-    {
-        Task task = getBuildTaskQueueExecutor().getCurrentTask();
-        if ( task != null )
-        {
-            if ( task instanceof BuildProjectTask )
-            {
-                return ( (BuildProjectTask) task ).getProjectId();
-            }
-        }
-        return -1;
-    }
+    private PlexusContainer container;
 
     public TaskQueue getDistributedBuildQueue()
     {
@@ -284,115 +115,10 @@
         }
     }
 
-    public TaskQueue getPrepareBuildQueue()
-    {
-        return prepareBuildQueue;
-    }   
-
-    public TaskQueueExecutor getPrepareBuildTaskQueueExecutor()
-        throws TaskQueueManagerException
-    {
-        try
-        {
-            return (TaskQueueExecutor) container.lookup( TaskQueueExecutor.class, "prepare-build-project" );
-        }
-        catch ( ComponentLookupException e )
-        {
-            throw new TaskQueueManagerException( e.getMessage(), e );
-        }
-    }
-
-    public List<BuildProjectTask> getProjectsInBuildQueue()
-        throws TaskQueueManagerException
-    {
-        try
-        {
-            return buildQueue.getQueueSnapshot();
-        }
-        catch ( TaskQueueException e )
-        {
-            throw new TaskQueueManagerException( "Error while getting the building queue.", e );
-        }
-    }
-    
     public TaskQueue getPurgeQueue()
     {
         return purgeQueue;
     }
-    
-    public boolean isInBuildingQueue( int projectId )
-        throws TaskQueueManagerException
-    {
-        return isInBuildingQueue( projectId, -1 );
-    }
-    
-    public boolean isInBuildingQueue( int projectId, int buildDefinitionId )
-        throws TaskQueueManagerException
-    {
-        List<BuildProjectTask> queue = getProjectsInBuildQueue();
-    
-        for ( BuildProjectTask task : queue )
-        {
-            if ( task != null )
-            {
-                if ( buildDefinitionId < 0 )
-                {
-                    if ( task.getProjectId() == projectId )
-                    {
-                        return true;
-                    }
-                }
-                else
-                {
-                    if ( task.getProjectId() == projectId && task.getBuildDefinitionId() == buildDefinitionId )
-                    {
-                        return true;
-                    }
-                }
-            }
-        }
-    
-        return false;
-    }
-    
-    public boolean isInCheckoutQueue( int projectId )
-        throws TaskQueueManagerException
-    {
-        List<CheckOutTask> queue = getCheckOutTasksInQueue();
-    
-        for ( CheckOutTask task : queue )
-        {
-            if ( task != null && task.getProjectId() == projectId )
-            {
-                return true;
-            }
-        }
-    
-        return false;
-    }
-
-    public boolean isInCurrentPrepareBuildTask( int projectId )
-        throws TaskQueueManagerException
-    {
-        Task task = getPrepareBuildTaskQueueExecutor().getCurrentTask();
-
-        if ( task != null &&  task instanceof PrepareBuildProjectsTask )
-        {
-            Map<Integer, Integer> map = ( (PrepareBuildProjectsTask) task).getProjectsBuildDefinitionsMap();
-            
-            if ( map.size() > 0 )
-            {
-                Set<Integer> projectIds = map.keySet();
-                
-                if ( projectIds.contains( new Integer( projectId ) ) )
-                {
-                    return true;
-                }
-            }
-        }
-        
-        return false;
-    }
 
     public boolean isInDistributedBuildQueue( int projectGroupId, String scmRootAddress )
         throws TaskQueueManagerException
@@ -405,7 +131,8 @@
             {
                 if ( task != null )
                 {
-                    if ( task.getProjectGroupId() == projectGroupId && task.getScmRootAddress().equals( scmRootAddress ) )
+                    if ( task.getProjectGroupId() == projectGroupId && task.getScmRootAddress().equals(
+                        scmRootAddress ) )
                     {
                         return true;
                     }
@@ -420,44 +147,11 @@
         }
     }
 
-    public boolean isInPrepareBuildQueue( int projectId )
-        throws TaskQueueManagerException
-    {
-        try
-        {
-            List<PrepareBuildProjectsTask> queue = prepareBuildQueue.getQueueSnapshot();
-            
-            for ( PrepareBuildProjectsTask task : queue )
-            {
-                if ( task != null )
-                {
-                    Map<Integer, Integer> map = task.getProjectsBuildDefinitionsMap();
-                    
-                    if ( map.size() > 0 )
-                    {
-                        Set<Integer> projectIds = map.keySet();
-                        
-                        if ( projectIds.contains( new Integer( projectId ) ) )
-                        {
-                            return true;
-                        }
-                    }
-                }
-            }
-            
-            return false;
-        }
-        catch ( TaskQueueException e )
-        {
-            throw new TaskQueueManagerException( "Error while getting the tasks in prepare build queue", e );
-        }
-    }
-    
     public boolean isInPurgeQueue( int purgeConfigId )
         throws TaskQueueManagerException
     {
         List<PurgeTask> queue = getAllPurgeConfigurationsInPurgeQueue();
-    
+
         for ( PurgeTask task : queue )
         {
             if ( task != null && task.getPurgeConfigurationId() == purgeConfigId )
@@ -467,13 +161,13 @@
         }
         return false;
     }
-    
+
     public boolean isRepositoryInPurgeQueue( int repositoryId )
         throws TaskQueueManagerException
     {
         List<RepositoryPurgeConfiguration> repoPurgeConfigs =
             purgeConfigurationService.getRepositoryPurgeConfigurationsByRepository( repositoryId );
-    
+
         for ( RepositoryPurgeConfiguration repoPurge : repoPurgeConfigs )
         {
             if ( isInPurgeQueue( repoPurge.getId() ) )
@@ -483,91 +177,135 @@
         }
         return false;
     }
-    
+
     public boolean isRepositoryInUse( int repositoryId )
         throws TaskQueueManagerException
     {
         try
         {
-            Task task = getCurrentTask( "build-project" );
-    
-            if ( task != null && task instanceof BuildProjectTask )
+            Map<String, BuildProjectTask> currentBuilds = buildsManager.getCurrentBuilds();
+            Set<String> keys = currentBuilds.keySet();
+
+            for ( String key : keys )
             {
-                int projectId = ( (BuildProjectTask) task ).getProjectId();
-    
-                Project project = projectDao.getProject( projectId );
-                LocalRepository repository = project.getProjectGroup().getLocalRepository();
-    
-                if ( repository != null && repository.getId() == repositoryId )
+                BuildProjectTask task = currentBuilds.get( key );
+                if ( task != null )
                 {
-                    return true;
+                    int projectId = task.getProjectId();
+
+                    Project project = projectDao.getProject( projectId );
+                    LocalRepository repository = project.getProjectGroup().getLocalRepository();
+
+                    if ( repository != null && repository.getId() == repositoryId )
+                    {
+                        return true;
+                    }
                 }
             }
+
             return false;
         }
+        catch ( BuildManagerException e )
+        {
+            log.error( "Error occured while getting current builds: " + e.getMessage() );
+            throw new TaskQueueManagerException( e.getMessage(), e );
+        }
         catch ( ContinuumStoreException e )
         {
+            log.error( "Error occured while getting project details: " + e.getMessage() );
             throw new TaskQueueManagerException( e.getMessage(), e );
         }
     }
 
+    public boolean isProjectInReleaseStage( String releaseId )
+        throws TaskQueueManagerException
+    {
+        Task prepareTask = getCurrentTask( "prepare-release" );
+        if ( prepareTask != null && prepareTask instanceof PrepareReleaseProjectTask )
+        {
+            if ( ( (PrepareReleaseProjectTask) prepareTask ).getReleaseId().equals( releaseId ) )
+            {
+                return true;
+            }
+            else
+            {
+                try
+                {
+                    // check if in queue
+                    List<Task> tasks = prepareReleaseQueue.getQueueSnapshot();
+                    for ( Task prepareReleaseTask : tasks )
+                    {
+                        if ( ( (PrepareReleaseProjectTask) prepareReleaseTask ).getReleaseId().equals( releaseId ) )
+                        {
+                            return true;
+                        }
+                    }
+                }
+                catch ( TaskQueueException e )
+                {
+                    throw new TaskQueueManagerException( e );
+                }
+            }
+        }
+
+        Task performTask = getCurrentTask( "perform-release" );
+        if ( performTask != null && performTask instanceof PerformReleaseProjectTask )
+        {
+            if ( ( (PerformReleaseProjectTask) performTask ).getReleaseId().equals( releaseId ) )
+            {
+                return true;
+            }
+            else
+            {
+                try
+                {
+                    // check if in queue
+                    List<Task> tasks = performReleaseQueue.getQueueSnapshot();
+                    for ( Task performReleaseTask : tasks )
+                    {
+                        if ( ( (PerformReleaseProjectTask) performReleaseTask ).getReleaseId().equals( releaseId ) )
+                        {
+                            return true;
+                        }
+                    }
+                }
+                catch ( TaskQueueException e )
+                {
+                    throw new TaskQueueManagerException( e );
+                }
+            }
+        }
+
+        return false;
+    }
+
     public boolean releaseInProgress()
         throws TaskQueueManagerException
     {
         Task task = getCurrentTask( "perform-release" );
-    
-        if ( task != null && task instanceof PerformReleaseProjectTask )
-        {
-            return true;
-        }
-    
-        return false;
+
+        return task != null && task instanceof PerformReleaseProjectTask;
     }
 
-    public boolean removeFromBuildingQueue( int projectId, int buildDefinitionId, int trigger, String projectName )
-        throws TaskQueueManagerException
-    {
-        BuildDefinition buildDefinition;
-        
-        try
-        {
-            buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
-        }
-        catch ( ContinuumStoreException e )
-        {
-            throw new TaskQueueManagerException( "Error while removing project from build queue: " + projectName, e );
-        }
-        
-        String buildDefinitionLabel = buildDefinition.getDescription();
-        if ( StringUtils.isEmpty( buildDefinitionLabel ) )
-        {
-            buildDefinitionLabel = buildDefinition.getGoals();
-        }
-        BuildProjectTask buildProjectTask =
-            new BuildProjectTask( projectId, buildDefinitionId, trigger, projectName, buildDefinitionLabel );
-        return this.buildQueue.remove( buildProjectTask );
-    }
-
-    public boolean removeFromDistributedBuildQueue( int projectGroupId, String scmRootAddress )
+    public void removeFromDistributedBuildQueue( int projectGroupId, String scmRootAddress )
         throws TaskQueueManagerException
     {
         List<PrepareBuildProjectsTask> queue = getDistributedBuildProjectsInQueue();
 
         for ( PrepareBuildProjectsTask task : queue )
         {
-            if ( task != null && task.getProjectGroupId() == projectGroupId && task.getScmRootAddress().equals( scmRootAddress ) )
+            if ( task.getProjectGroupId() == projectGroupId && task.getScmRootAddress().equals( scmRootAddress ) )
             {
-                return distributedBuildQueue.remove( task );
+                distributedBuildQueue.remove( task );
             }
         }
-        return false;
     }
 
     public boolean removeFromPurgeQueue( int purgeConfigId )
         throws TaskQueueManagerException
     {
         List<PurgeTask> queue = getAllPurgeConfigurationsInPurgeQueue();
-    
+
         for ( PurgeTask task : queue )
         {
             if ( task != null && task.getPurgeConfigurationId() == purgeConfigId )
@@ -578,7 +316,6 @@
         return false;
     }
 
-
     public boolean removeFromPurgeQueue( int[] purgeConfigIds )
         throws TaskQueueManagerException
     {
@@ -586,16 +323,16 @@
         {
             return false;
         }
-    
+
         if ( purgeConfigIds.length < 1 )
         {
             return false;
         }
-    
+
         List<PurgeTask> queue = getAllPurgeConfigurationsInPurgeQueue();
-    
+
         List<PurgeTask> tasks = new ArrayList<PurgeTask>();
-    
+
         for ( PurgeTask task : queue )
         {
             if ( task != null )
@@ -606,185 +343,42 @@
                 }
             }
         }
-    
-        if ( !tasks.isEmpty() )
-        {
-            return purgeQueue.removeAll( tasks );
-        }
-    
-        return false;
-    }
-    
-    public boolean removeProjectsFromBuildingQueue( int[] projectsId )
-        throws TaskQueueManagerException
-    {
-        if ( projectsId == null )
-        {
-            return false;
-        }
-        if ( projectsId.length < 1 )
-        {
-            return false;
-        }
-        List<BuildProjectTask> queue = getProjectsInBuildQueue();
-    
-        List<BuildProjectTask> tasks = new ArrayList<BuildProjectTask>();
-    
-        for ( BuildProjectTask task : queue )
-        {
-            if ( task != null )
-            {
-                if ( ArrayUtils.contains( projectsId, task.getProjectId() ) )
-                {
-                    tasks.add( task );
-                }
-            }
-        }
 
-        for ( BuildProjectTask buildProjectTask : tasks )
-        {
-            log.info( "cancel build for project " + buildProjectTask.getProjectId() );
-        }
-        if ( !tasks.isEmpty() )
-        {
-            return buildQueue.removeAll( tasks );
-        }
-    
-        return false;
+        return !tasks.isEmpty() && purgeQueue.removeAll( tasks );
     }
-    
-    public boolean removeProjectFromBuildingQueue( int projectId )
-        throws TaskQueueManagerException
-    {
-        List<BuildProjectTask> queue = getProjectsInBuildQueue();
-    
-        for ( BuildProjectTask task : queue )
-        {
-            if ( task != null && task.getProjectId() == projectId )
-            {
-                return buildQueue.remove( task );
-            }
-        }
-    
-        return false;
-    }
-    
-    public boolean removeProjectsFromCheckoutQueue( int[] projectsId )
-        throws TaskQueueManagerException
-    {
-        if ( projectsId == null )
-        {
-            return false;
-        }
-        if ( projectsId.length < 1 )
-        {
-            return false;
-        }
-        List<CheckOutTask> queue = getCheckOutTasksInQueue();
-    
-        List<CheckOutTask> tasks = new ArrayList<CheckOutTask>();
-    
-        for ( CheckOutTask task : queue )
-        {
-            if ( task != null )
-            {
-                if ( ArrayUtils.contains( projectsId, task.getProjectId() ) )
-                {
-                    tasks.add( task );
-                }
-            }
-        }
-        if ( !tasks.isEmpty() )
-        {
-            return checkoutQueue.removeAll( tasks );
-        }
-        return false;
-    }
-    
-    public void removeProjectsFromBuildingQueueWithHashCodes( int[] hashCodes )
-        throws TaskQueueManagerException
-    {
-        List<BuildProjectTask> queue = getProjectsInBuildQueue();
-    
-        for ( BuildProjectTask task : queue )
-        {
-            if ( ArrayUtils.contains( hashCodes, task.hashCode() ) )
-            {
-                buildQueue.remove( task );
-            }
-        }
-    }
-    
-    public boolean removeProjectFromCheckoutQueue( int projectId )
-        throws TaskQueueManagerException
-    {
-        List<CheckOutTask> queue = getCheckOutTasksInQueue();
-    
-        for ( CheckOutTask task : queue )
-        {
-            if ( task != null && task.getProjectId() == projectId )
-            {
-                return checkoutQueue.remove( task );
-            }
-        }
-    
-        return false;
-    }
-    
+
     public void removeRepositoryFromPurgeQueue( int repositoryId )
         throws TaskQueueManagerException
     {
         List<RepositoryPurgeConfiguration> repoPurgeConfigs =
             purgeConfigurationService.getRepositoryPurgeConfigurationsByRepository( repositoryId );
-    
+
         for ( RepositoryPurgeConfiguration repoPurge : repoPurgeConfigs )
         {
             removeFromPurgeQueue( repoPurge.getId() );
         }
     }
 
-    public void removeTasksFromCheckoutQueueWithHashCodes( int[] hashCodes )
+    public void removeTasksFromDistributedBuildQueueWithHashCodes( int[] hashCodes )
         throws TaskQueueManagerException
     {
-        List<CheckOutTask> queue = getCheckOutTasksInQueue();
-    
-        for ( CheckOutTask task : queue )
+        List<PrepareBuildProjectsTask> queue = getDistributedBuildProjectsInQueue();
+
+        for ( PrepareBuildProjectsTask task : queue )
         {
             if ( ArrayUtils.contains( hashCodes, task.hashCode() ) )
             {
-                checkoutQueue.remove( task );
+                distributedBuildQueue.remove( task );
             }
         }
     }
 
-    public boolean removeFromPrepareBuildQueue( int projectGroupId, String scmRootAddress )
-        throws TaskQueueManagerException
-    {
-        try
-        {
-            List<PrepareBuildProjectsTask> queue = prepareBuildQueue.getQueueSnapshot();
-            
-            for ( PrepareBuildProjectsTask task : queue )
-            {
-                if ( task != null && task.getProjectGroupId() == projectGroupId && task.getScmRootAddress().equals( scmRootAddress ) )
-                {
-                    return prepareBuildQueue.remove( task );
-                }
-            }
-            return false;
-        }
-        catch ( TaskQueueException e )
-        {
-            throw new TaskQueueManagerException( "Error while getting the prepare build projects task in queue", e );
-        }
-    }
-    
     public void contextualize( Context context )
         throws ContextException
     {
         container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
     }
-    
+
     private List<PurgeTask> getAllPurgeConfigurationsInPurgeQueue()
         throws TaskQueueManagerException
     {
@@ -797,7 +391,7 @@
             throw new TaskQueueManagerException( "Error while getting the purge configs in purge queue", e );
         }
     }
-    
+
     private Task getCurrentTask( String task )
         throws TaskQueueManagerException
     {
@@ -811,18 +405,4 @@
             throw new TaskQueueManagerException( "Unable to lookup current task", e );
         }
     }
-
-    public void removeTasksFromDistributedBuildQueueWithHashCodes( int[] hashCodes )
-        throws TaskQueueManagerException
-    {
-        List<PrepareBuildProjectsTask> queue = getDistributedBuildProjectsInQueue();
-        
-        for ( PrepareBuildProjectsTask task : queue )
-        {
-            if ( ArrayUtils.contains( hashCodes, task.hashCode() ) )
-            {
-                distributedBuildQueue.remove( task );
-            }
-        }
-    }
 }
diff --git a/continuum-core/src/main/java/org/apache/continuum/taskqueueexecutor/ParallelBuildsThreadedTaskQueueExecutor.java b/continuum-core/src/main/java/org/apache/continuum/taskqueueexecutor/ParallelBuildsThreadedTaskQueueExecutor.java
new file mode 100644
index 0000000..5db4b8f
--- /dev/null
+++ b/continuum-core/src/main/java/org/apache/continuum/taskqueueexecutor/ParallelBuildsThreadedTaskQueueExecutor.java
@@ -0,0 +1,362 @@
+package org.apache.continuum.taskqueueexecutor;
+
+/*
+ * 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 edu.emory.mathcs.backport.java.util.concurrent.CancellationException;
+import edu.emory.mathcs.backport.java.util.concurrent.ExecutionException;
+import edu.emory.mathcs.backport.java.util.concurrent.ExecutorService;
+import edu.emory.mathcs.backport.java.util.concurrent.Executors;
+import edu.emory.mathcs.backport.java.util.concurrent.Future;
+import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
+import edu.emory.mathcs.backport.java.util.concurrent.TimeoutException;
+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;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.StartingException;
+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.execution.TaskExecutionException;
+import org.codehaus.plexus.taskqueue.execution.TaskExecutor;
+import org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor;
+import org.codehaus.plexus.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Modified plexus ThreadedTaskQueueExecutor
+ */
+public class ParallelBuildsThreadedTaskQueueExecutor
+    implements TaskQueueExecutor, Initializable, Startable
+{
+    private static final Logger log = LoggerFactory.getLogger( ParallelBuildsThreadedTaskQueueExecutor.class );
+
+    private static final int SHUTDOWN = 1;
+
+    private static final int CANCEL_TASK = 2;
+
+    /**
+     * @requirement
+     */
+    private TaskQueue queue;
+
+    /**
+     * @requirement
+     */
+    private TaskExecutor executor;
+
+    /**
+     * @configuration
+     */
+    private String name;
+
+    // ----------------------------------------------------------------------
+    //
+    // ----------------------------------------------------------------------
+
+    private ExecutorRunnable executorRunnable;
+
+    private ExecutorService executorService;
+
+    private Task currentTask;
+
+    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 );
+                }
+                catch ( InterruptedException e )
+                {
+                    log.info( "Executor thread interrupted, command: " + ( command == SHUTDOWN
+                        ? "Shutdown"
+                        : command == CANCEL_TASK ? "Cancel task" : "Unknown" ) );
+                    continue;
+                }
+
+                if ( task == null )
+                {
+                    continue;
+                }
+
+                currentTask = task;
+
+                Future future = executorService.submit( new Runnable()
+                {
+                    public void run()
+                    {
+                        try
+                        {
+                            executor.executeTask( task );
+                        }
+                        catch ( TaskExecutionException e )
+                        {
+                            log.error( "Error executing task", e );
+                        }
+                    }
+                } );
+
+                try
+                {
+                    waitForTask( task, future );
+                }
+                catch ( ExecutionException e )
+                {
+                    log.error( "Error executing task", e );
+                }
+            }
+
+            currentTask = null;
+
+            log.info( "Executor thread '" + name + "' exited." );
+
+            done = true;
+
+            synchronized ( this )
+            {
+                notifyAll();
+            }
+        }
+
+        private void waitForTask( Task task, Future future )
+            throws ExecutionException
+        {
+            boolean stop = false;
+
+            while ( !stop )
+            {
+                try
+                {
+                    if ( task.getMaxExecutionTime() == 0 )
+                    {
+                        log.debug( "Waiting indefinitely for task to complete" );
+                        future.get();
+                        return;
+                    }
+                    else
+                    {
+                        log.debug( "Waiting at most " + task.getMaxExecutionTime() + "ms for task completion" );
+                        future.get( task.getMaxExecutionTime(), TimeUnit.MILLISECONDS );
+                        log.debug( "Task completed within " + task.getMaxExecutionTime() + "ms" );
+                        return;
+                    }
+                }
+                catch ( InterruptedException e )
+                {
+                    switch ( command )
+                    {
+                        case SHUTDOWN:
+                        {
+                            log.info( "Shutdown command received. Cancelling task." );
+                            cancel( future );
+                            return;
+                        }
+
+                        case CANCEL_TASK:
+                        {
+                            command = 0;
+                            log.info( "Cancelling task" );
+                            cancel( future );
+                            return;
+                        }
+
+                        default:
+                            // when can this thread be interrupted, and should we ignore it if shutdown = false?
+                            log.warn( "Interrupted while waiting for task to complete; ignoring", e );
+                            break;
+                    }
+                }
+                catch ( TimeoutException e )
+                {
+                    log.warn( "Task " + task + " didn't complete within time, cancelling it." );
+                    cancel( future );
+                    return;
+                }
+                catch ( CancellationException e )
+                {
+                    log.warn( "The task was cancelled", e );
+                    return;
+                }
+            }
+        }
+
+        private void cancel( Future future )
+        {
+            if ( !future.cancel( true ) )
+            {
+                if ( !future.isDone() && !future.isCancelled() )
+                {
+                    log.warn( "Unable to cancel task" );
+                }
+                else
+                {
+                    log.warn(
+                        "Task not cancelled (Flags: done: " + future.isDone() + " cancelled: " + future.isCancelled() +
+                            ")" );
+                }
+            }
+            else
+            {
+                log.debug( "Task successfully cancelled" );
+            }
+        }
+
+        public synchronized void shutdown()
+        {
+            log.debug( "Signalling executor thread to shutdown" );
+
+            command = SHUTDOWN;
+
+            interrupt();
+        }
+
+        public synchronized boolean cancelTask( Task task )
+        {
+            if ( !task.equals( currentTask ) )
+            {
+                log.debug( "Not cancelling task - it is not running" );
+                return false;
+            }
+
+            if ( command != SHUTDOWN )
+            {
+                log.debug( "Signalling executor thread to cancel task" );
+
+                command = CANCEL_TASK;
+
+                interrupt();
+            }
+            else
+            {
+                log.debug( "Executor thread already stopping; task will be cancelled automatically" );
+            }
+
+            return true;
+        }
+
+        public boolean isDone()
+        {
+            return done;
+        }
+    }
+
+    // ----------------------------------------------------------------------
+    // Component lifecycle
+    // ----------------------------------------------------------------------
+
+    public void initialize()
+        throws InitializationException
+    {
+        if ( StringUtils.isEmpty( name ) )
+        {
+            throw new IllegalArgumentException( "'name' must be set." );
+        }
+    }
+
+    public void start()
+        throws StartingException
+    {
+        log.info( "Starting task executor, thread name '" + name + "'." );
+
+        this.executorService = Executors.newCachedThreadPool();
+
+        executorRunnable = new ExecutorRunnable();
+
+        executorRunnable.setDaemon( true );
+
+        executorRunnable.start();
+    }
+
+    public void stop()
+        throws StoppingException
+    {
+        executorRunnable.shutdown();
+
+        int maxSleep = 10 * 1000; // 10 seconds
+
+        int interval = 1000;
+
+        long endTime = System.currentTimeMillis() + maxSleep;
+
+        while ( !executorRunnable.isDone() && executorRunnable.isAlive() )
+        {
+            if ( System.currentTimeMillis() > endTime )
+            {
+                log.warn( "Timeout waiting for executor thread '" + name + "' to stop, aborting" );
+                break;
+            }
+
+            log.info( "Waiting until task executor '" + name + "' is idling..." );
+
+            try
+            {
+                synchronized ( executorRunnable )
+                {
+                    executorRunnable.wait( interval );
+                }
+            }
+            catch ( InterruptedException ex )
+            {
+                // ignore
+            }
+
+            // notify again, just in case.
+            executorRunnable.shutdown();
+        }
+    }
+
+    public Task getCurrentTask()
+    {
+        return currentTask;
+    }
+
+    public synchronized boolean cancelTask( Task task )
+    {
+        return executorRunnable.cancelTask( task );
+    }
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName( String name )
+    {
+        this.name = name;
+    }
+
+    public TaskQueue getQueue()
+    {
+        return queue;
+    }
+}
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/DefaultContinuum.java b/continuum-core/src/main/java/org/apache/maven/continuum/DefaultContinuum.java
index 22bae9d..10b6f7d 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/DefaultContinuum.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/DefaultContinuum.java
@@ -19,20 +19,14 @@
  * under the License.
  */
 
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
+import org.apache.continuum.buildagent.NoBuildAgentException;
+import org.apache.continuum.buildagent.NoBuildAgentInGroupException;
+import org.apache.continuum.builder.distributed.manager.DistributedBuildManager;
+import org.apache.continuum.buildmanager.BuildManagerException;
+import org.apache.continuum.buildmanager.BuildsManager;
+import org.apache.continuum.buildqueue.BuildQueueService;
+import org.apache.continuum.buildqueue.BuildQueueServiceException;
+import org.apache.continuum.configuration.BuildAgentConfigurationException;
 import org.apache.continuum.configuration.ContinuumConfigurationException;
 import org.apache.continuum.dao.BuildDefinitionDao;
 import org.apache.continuum.dao.BuildResultDao;
@@ -43,15 +37,19 @@
 import org.apache.continuum.dao.ProjectGroupDao;
 import org.apache.continuum.dao.ProjectScmRootDao;
 import org.apache.continuum.dao.ScheduleDao;
+import org.apache.continuum.model.project.ProjectGroupSummary;
 import org.apache.continuum.model.project.ProjectScmRoot;
 import org.apache.continuum.model.release.ContinuumReleaseResult;
 import org.apache.continuum.purge.ContinuumPurgeManager;
 import org.apache.continuum.purge.PurgeConfigurationService;
+import org.apache.continuum.release.config.ContinuumReleaseDescriptor;
+import org.apache.continuum.release.distributed.manager.DistributedReleaseManager;
+import org.apache.continuum.release.model.PreparedRelease;
 import org.apache.continuum.repository.RepositoryService;
-import org.apache.continuum.taskqueue.PrepareBuildProjectsTask;
 import org.apache.continuum.taskqueue.manager.TaskQueueManager;
 import org.apache.continuum.taskqueue.manager.TaskQueueManagerException;
 import org.apache.continuum.utils.ProjectSorter;
+import org.apache.continuum.utils.build.BuildTrigger;
 import org.apache.maven.continuum.build.settings.SchedulesActivationException;
 import org.apache.maven.continuum.build.settings.SchedulesActivator;
 import org.apache.maven.continuum.builddefinition.BuildDefinitionService;
@@ -60,7 +58,9 @@
 import org.apache.maven.continuum.configuration.ConfigurationLoadingException;
 import org.apache.maven.continuum.configuration.ConfigurationService;
 import org.apache.maven.continuum.core.action.AbstractContinuumAction;
+import org.apache.maven.continuum.core.action.CheckoutProjectContinuumAction;
 import org.apache.maven.continuum.core.action.CreateProjectsFromMetadataAction;
+import org.apache.maven.continuum.core.action.StoreProjectAction;
 import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
 import org.apache.maven.continuum.execution.manager.BuildExecutorManager;
 import org.apache.maven.continuum.initialization.ContinuumInitializationException;
@@ -68,6 +68,7 @@
 import org.apache.maven.continuum.installation.InstallationService;
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.BuildDefinitionTemplate;
+import org.apache.maven.continuum.model.project.BuildQueue;
 import org.apache.maven.continuum.model.project.BuildResult;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.project.ProjectGroup;
@@ -80,30 +81,45 @@
 import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
 import org.apache.maven.continuum.project.builder.maven.MavenOneContinuumProjectBuilder;
 import org.apache.maven.continuum.project.builder.maven.MavenTwoContinuumProjectBuilder;
+import org.apache.maven.continuum.release.ContinuumReleaseException;
 import org.apache.maven.continuum.release.ContinuumReleaseManager;
 import org.apache.maven.continuum.store.ContinuumObjectNotFoundException;
 import org.apache.maven.continuum.store.ContinuumStoreException;
 import org.apache.maven.continuum.utils.ContinuumUrlValidator;
 import org.apache.maven.continuum.utils.WorkingDirectoryService;
-import org.codehaus.plexus.PlexusConstants;
-import org.codehaus.plexus.PlexusContainer;
+import org.apache.maven.shared.release.ReleaseResult;
 import org.codehaus.plexus.action.Action;
 import org.codehaus.plexus.action.ActionManager;
 import org.codehaus.plexus.action.ActionNotFoundException;
-import org.codehaus.plexus.context.Context;
-import org.codehaus.plexus.context.ContextException;
-import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
 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;
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.StartingException;
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.StoppingException;
-import org.codehaus.plexus.taskqueue.TaskQueueException;
 import org.codehaus.plexus.util.FileUtils;
+import org.codehaus.plexus.util.IOUtil;
 import org.codehaus.plexus.util.StringUtils;
-import org.codehaus.plexus.util.dag.CycleDetectedException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeanUtils;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
@@ -112,9 +128,9 @@
  * @plexus.component role="org.apache.maven.continuum.Continuum" role-hint="default"
  */
 public class DefaultContinuum
-    implements Continuum, Contextualizable, Initializable, Startable
+    implements Continuum, Initializable, Startable
 {
-    private Logger log = LoggerFactory.getLogger( DefaultContinuum.class );
+    private static final Logger log = LoggerFactory.getLogger( DefaultContinuum.class );
 
     /**
      * @plexus.requirement
@@ -170,7 +186,7 @@
      * @plexus.requirement
      */
     private ProjectScmRootDao projectScmRootDao;
-    
+
     /**
      * @plexus.requirement
      */
@@ -206,11 +222,6 @@
     private ContinuumReleaseManager releaseManager;
 
     /**
-     * @plexus.configuration default-value="${plexus.home}/temp"
-     */
-    private String workingDirectory;
-
-    /**
      * @plexus.requirement
      */
     private WorkingDirectoryService workingDirectoryService;
@@ -220,8 +231,6 @@
      */
     private BuildExecutorManager executorManager;
 
-    private PlexusContainer container;
-
     /**
      * @plexus.requirement role-hint="continuumUrl"
      */
@@ -249,20 +258,34 @@
      */
     private TaskQueueManager taskQueueManager;
 
+    /**
+     * @plexus.requirement role-hint="parallel"
+     */
+    private BuildsManager parallelBuildsManager;
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildQueueService buildQueueService;
+
+    /**
+     * @plexus.requirement
+     */
+    private DistributedBuildManager distributedBuildManager;
+
+    /**
+     * @plexus.requirement
+     */
+    private DistributedReleaseManager distributedReleaseManager;
+
     public DefaultContinuum()
     {
         Runtime.getRuntime().addShutdownHook( new Thread()
         {
+            @Override
             public void run()
             {
-                try
-                {
-                    stopContinuum();
-                }
-                catch ( StoppingException e )
-                {
-                    e.printStackTrace();
-                }
+                stopContinuum();
             }
         } );
     }
@@ -272,16 +295,6 @@
         return releaseManager;
     }
 
-    public void setActionManager( ActionManager actionManager )
-    {
-        this.actionManager = actionManager;
-    }
-
-    public ActionManager getActionManager()
-    {
-        return actionManager;
-    }
-
     public ContinuumPurgeManager getPurgeManager()
     {
         return purgeManager;
@@ -291,7 +304,7 @@
     {
         return repositoryService;
     }
-    
+
     public TaskQueueManager getTaskQueueManager()
     {
         return taskQueueManager;
@@ -302,6 +315,16 @@
         return purgeConfigurationService;
     }
 
+    public BuildsManager getBuildsManager()
+    {
+        return parallelBuildsManager;
+    }
+
+    public DistributedReleaseManager getDistributedReleaseManager()
+    {
+        return distributedReleaseManager;
+    }
+
     // ----------------------------------------------------------------------
     // Project Groups
     // ----------------------------------------------------------------------
@@ -355,33 +378,70 @@
 
         if ( projectGroup != null )
         {
-            for ( Object o : projectGroup.getProjects() )
+            List<Project> projects = projectGroup.getProjects();
+            int[] projectIds = new int[projects.size()];
+
+            int idx = 0;
+            for ( Project project : projects )
             {
-                removeProject( ( (Project) o ).getId() );
+                projectIds[idx] = project.getId();
+                idx++;
             }
 
-            List<ProjectScmRoot> projectScmRoots = getProjectScmRootByProjectGroup( projectGroupId );
-
-            for ( ProjectScmRoot projectScmRoot : projectScmRoots )
+            // check if any project is still being checked out
+            // canceling the checkout and proceeding with the delete results to a cannot delete directory error!
+            try
             {
-                try
+                if ( parallelBuildsManager.isAnyProjectCurrentlyBeingCheckedOut( projectIds ) )
                 {
-                    projectScmRootDao.removeProjectScmRoot( projectScmRoot );
+                    throw new ContinuumException(
+                        "Unable to delete group. At least one project in group is still being checked out." );
                 }
-                catch ( ContinuumStoreException e )
+
+                if ( parallelBuildsManager.isAnyProjectCurrentlyPreparingBuild( projectIds ) )
                 {
-                    throw new ContinuumException( "unable to delete project scm root: " + projectScmRoot.getScmRootAddress() );
+                    throw new ContinuumException(
+                        "Unable to delete group. The project group is still preparing build." );
+                }
+
+                if ( parallelBuildsManager.isAnyProjectCurrentlyBuilding( projectIds ) )
+                {
+                    throw new ContinuumException(
+                        "Unable to delete group. At least one project in group is still building." );
+                }
+
+                if ( isAnyProjectsInReleaseStage( projects ) )
+                {
+                    throw new ContinuumException(
+                        "Unable to delete group. At least one project in group is in release stage" );
                 }
             }
+            catch ( BuildManagerException e )
+            {
+                throw new ContinuumException( "Unable to delete group.", e );
+            }
+
+            for ( int projectId : projectIds )
+            {
+                removeProject( projectId );
+            }
+
+            // check if there are any project scm root left
+            List<ProjectScmRoot> scmRoots = getProjectScmRootByProjectGroup( projectGroupId );
+
+            for ( ProjectScmRoot scmRoot : scmRoots )
+            {
+                removeProjectScmRoot( scmRoot );
+            }
+
+            log.info( "Remove project group " + projectGroup.getName() + "(" + projectGroup.getId() + ")" );
+
+            Map<String, Object> context = new HashMap<String, Object>();
+            AbstractContinuumAction.setProjectGroupId( context, projectGroup.getId() );
+            executeAction( "remove-assignable-roles", context );
+
+            projectGroupDao.removeProjectGroup( projectGroup );
         }
-
-        log.info( "Remove project group " + projectGroup.getName() + "(" + projectGroup.getId() + ")" );
-
-        Map context = new HashMap();
-        context.put( AbstractContinuumAction.KEY_PROJECT_GROUP_ID, new Integer( projectGroup.getId() ) );
-        executeAction( "remove-assignable-roles", context );
-
-        projectGroupDao.removeProjectGroup( projectGroup );
     }
 
     public void addProjectGroup( ProjectGroup projectGroup )
@@ -411,11 +471,11 @@
             {
                 ProjectGroup new_pg = projectGroupDao.addProjectGroup( projectGroup );
 
-                buildDefinitionService.addBuildDefinitionTemplateToProjectGroup( new_pg.getId(), buildDefinitionService
-                    .getDefaultMavenTwoBuildDefinitionTemplate() );
+                buildDefinitionService.addBuildDefinitionTemplateToProjectGroup( new_pg.getId(),
+                                                                                 buildDefinitionService.getDefaultMavenTwoBuildDefinitionTemplate() );
 
-                Map context = new HashMap();
-                context.put( AbstractContinuumAction.KEY_PROJECT_GROUP_ID, new Integer( new_pg.getId() ) );
+                Map<String, Object> context = new HashMap<String, Object>();
+                AbstractContinuumAction.setProjectGroupId( context, new_pg.getId() );
                 executeAction( "add-assignable-roles", context );
 
                 log.info( "Added new project group: " + new_pg.getName() );
@@ -485,12 +545,18 @@
     // Projects
     // ----------------------------------------------------------------------
 
+    /**
+     * TODO: Remove this method
+     */
     public Collection<Project> getProjects()
         throws ContinuumException
     {
         return projectDao.getAllProjectsByName();
     }
 
+    /**
+     * TODO: Remove this method
+     */
     public Collection<Project> getProjectsWithDependencies()
         throws ContinuumException
     {
@@ -509,18 +575,6 @@
         return result;
     }
 
-    public Map<Integer, BuildResult> getLatestBuildResults()
-    {
-        Map<Integer, BuildResult> result = buildResultDao.getLatestBuildResults();
-
-        if ( result == null )
-        {
-            result = new HashMap<Integer, BuildResult>();
-        }
-
-        return result;
-    }
-
     public Map<Integer, BuildResult> getBuildResultsInSuccess( int projectGroupId )
     {
         Map<Integer, BuildResult> result = buildResultDao.getBuildResultsInSuccessByProjectGroupId( projectGroupId );
@@ -533,18 +587,6 @@
         return result;
     }
 
-    public Map<Integer, BuildResult> getBuildResultsInSuccess()
-    {
-        Map<Integer, BuildResult> result = buildResultDao.getBuildResultsInSuccess();
-
-        if ( result == null )
-        {
-            result = new HashMap<Integer, BuildResult>();
-        }
-
-        return result;
-    }
-
     public BuildResult getLatestBuildResultForProject( int projectId )
     {
         return buildResultDao.getLatestBuildResultForProject( projectId );
@@ -555,14 +597,13 @@
     {
         List<BuildResult> builds = buildResultDao.getBuildResultByBuildNumber( projectId, buildNumber );
 
-        if ( builds.isEmpty() )
-        {
-            return null;
-        }
-        else
-        {
-            return builds.get( 0 );
-        }
+        return ( builds.isEmpty() ? null : builds.get( 0 ) );
+    }
+
+    public List<BuildResult> getBuildResultsInRange( int projectGroupId, Date fromDate, Date toDate, int state,
+                                                     String triggeredBy )
+    {
+        return buildResultDao.getBuildResultsInRange( fromDate, toDate, state, triggeredBy, projectGroupId );
     }
 
     // ----------------------------------------------------------------------
@@ -574,9 +615,48 @@
     {
         try
         {
-            Project project = getProjectWithBuilds( projectId );
+            Project project = getProject( projectId );
 
-            List<ContinuumReleaseResult> releaseResults = releaseResultDao.getContinuumReleaseResultsByProject( projectId );
+            try
+            {
+                if ( parallelBuildsManager.isProjectCurrentlyBeingCheckedOut( projectId ) )
+                {
+                    throw new ContinuumException(
+                        "Unable to remove project " + projectId + " because it is currently being checked out" );
+                }
+
+                if ( parallelBuildsManager.isProjectInAnyCurrentBuild( projectId ) )
+                {
+                    throw new ContinuumException(
+                        "Unable to remove project " + projectId + " because it is currently building" );
+                }
+            }
+            catch ( BuildManagerException e )
+            {
+                throw new ContinuumException( e.getMessage(), e );
+            }
+
+            if ( isProjectInReleaseStage( project ) )
+            {
+                throw new ContinuumException(
+                    "Unable to remove project " + projectId + " because it is in release stage" );
+            }
+
+            try
+            {
+                parallelBuildsManager.removeProjectFromCheckoutQueue( projectId );
+
+                parallelBuildsManager.removeProjectFromBuildQueue( projectId );
+            }
+            catch ( BuildManagerException e )
+            {
+                throw new ContinuumException( e.getMessage(), e );
+            }
+
+            List<ContinuumReleaseResult> releaseResults = releaseResultDao.getContinuumReleaseResultsByProject(
+                projectId );
+
+            ProjectScmRoot scmRoot = getProjectScmRootByProject( projectId );
 
             try
             {
@@ -585,7 +665,8 @@
                     releaseResultDao.removeContinuumReleaseResult( releaseResult );
                 }
 
-                File releaseOutputDirectory = configurationService.getReleaseOutputDirectory( project.getProjectGroup().getId() );
+                File releaseOutputDirectory = configurationService.getReleaseOutputDirectory(
+                    project.getProjectGroup().getId() );
 
                 if ( releaseOutputDirectory != null )
                 {
@@ -603,40 +684,19 @@
 
             log.info( "Remove project " + project.getName() + "(" + projectId + ")" );
 
-            try
-            {
-                if ( taskQueueManager.isInPrepareBuildQueue( projectId ) )
-                {
-                    taskQueueManager.removeFromPrepareBuildQueue( project.getProjectGroup().getId(), 
-                                                                  getProjectScmRootByProject( projectId ).getScmRootAddress() );
-                }
+            // remove dependencies first to avoid key clash with build results
+            project = projectDao.getProjectWithDependencies( projectId );
+            project.setParent( null );
+            project.getDependencies().clear();
+            projectDao.updateProject( project );
 
-                if ( taskQueueManager.isInCheckoutQueue( projectId ) )
-                {
-                    taskQueueManager.removeProjectFromCheckoutQueue( projectId );
-                }
-                
-                if ( taskQueueManager.isInBuildingQueue( projectId ) )
-                {
-                    taskQueueManager.removeProjectFromBuildingQueue( projectId );
-                }
-                
-                // cancel if currently building
-                if ( taskQueueManager.getCurrentProjectIdBuilding() == projectId )
-                {
-                    taskQueueManager.cancelBuildTask( projectId );
-                }
-            }
-            catch ( TaskQueueManagerException e )
-            {
-                throw new ContinuumException( e.getMessage(), e );
-            }
+            Collection<BuildResult> buildResults = getBuildResultsForProject( projectId );
 
-            for ( Object o : project.getBuildResults() )
+            for ( BuildResult br : buildResults )
             {
-                BuildResult br = (BuildResult) o;
+                br.setBuildDefinition( null );
                 //Remove all modified dependencies to prevent SQL errors
-                br.setModifiedDependencies( null );
+                br.getModifiedDependencies().clear();
                 buildResultDao.updateBuildResult( br );
                 removeBuildResult( br );
             }
@@ -650,6 +710,8 @@
             FileUtils.deleteDirectory( buildOutputDirectory );
 
             projectDao.removeProject( projectDao.getProject( projectId ) );
+
+            removeProjectScmRoot( scmRoot );
         }
         catch ( ContinuumStoreException ex )
         {
@@ -669,9 +731,19 @@
     {
         Map<String, Object> context = new HashMap<String, Object>();
 
-        context.put( AbstractContinuumAction.KEY_PROJECT_ID, new Integer( projectId ) );
+        AbstractContinuumAction.setProjectId( context, projectId );
 
-        executeAction( "add-project-to-checkout-queue", context );
+        try
+        {
+            BuildDefinition buildDefinition = buildDefinitionDao.getDefaultBuildDefinition( projectId );
+            AbstractContinuumAction.setBuildDefinition( context, buildDefinition );
+
+            executeAction( "add-project-to-checkout-queue", context );
+        }
+        catch ( ContinuumStoreException e )
+        {
+            throw new ContinuumException( e.getMessage(), e );
+        }
     }
 
     public Project getProject( int projectId )
@@ -700,105 +772,74 @@
         }
     }
 
-    public Collection<Project> getAllProjects( int start, int end )
-        throws ContinuumException
+    public Map<Integer, ProjectGroupSummary> getProjectsSummaryByGroups()
     {
-        return projectDao.getAllProjectsByName();
+        return projectDao.getProjectsSummary();
     }
 
     // ----------------------------------------------------------------------
     // Building
     // ----------------------------------------------------------------------
 
-    public void buildProjects()
-        throws ContinuumException
+    public void buildProjects( String username )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException
     {
-        buildProjects( ContinuumProjectState.TRIGGER_FORCED );
-    }
-
-    public void buildProjectsWithBuildDefinition( int buildDefinitionId )
-        throws ContinuumException
-    {
-        buildProjects( ContinuumProjectState.TRIGGER_FORCED, buildDefinitionId );
+        buildProjects( new BuildTrigger( ContinuumProjectState.TRIGGER_FORCED, username ) );
     }
 
     public void buildProjectsWithBuildDefinition( List<Project> projects, List<BuildDefinition> bds )
-        throws ContinuumException
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException
     {
-        prepareBuildProjects( projects, bds, true, ContinuumProjectState.TRIGGER_FORCED );
+        Collection<Project> filteredProjectsList = getProjectsNotInReleaseStage( projects );
+
+        prepareBuildProjects( filteredProjectsList, bds, true, new BuildTrigger( ContinuumProjectState.TRIGGER_FORCED,
+                                                                                 "" ) );
     }
 
     public void buildProjectsWithBuildDefinition( List<Project> projects, int buildDefinitionId )
-        throws ContinuumException
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException
     {
-        prepareBuildProjects( projects, buildDefinitionId, ContinuumProjectState.TRIGGER_FORCED );
+        Collection<Project> filteredProjectsList = getProjectsNotInReleaseStage( projects );
+
+        prepareBuildProjects( filteredProjectsList, buildDefinitionId, new BuildTrigger(
+            ContinuumProjectState.TRIGGER_FORCED, "" ) );
     }
 
     /**
      * fire of the builds of all projects across all project groups using their default build definitions
+     * TODO:Remove this method
      *
-     * @param trigger
+     * @param buildTrigger
      * @throws ContinuumException
      */
-    public void buildProjects( int trigger )
-        throws ContinuumException
+    public void buildProjects( BuildTrigger buildTrigger )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException
     {
-        Collection<Project> projectsList;
+        Collection<Project> projectsList = getProjectsInBuildOrder();
 
-        try
-        {
-            projectsList = getProjectsInBuildOrder();
-        }
-        catch ( CycleDetectedException e )
-        {
-            log.warn( "Cycle detected while sorting projects for building, falling back to unsorted build." );
+        Collection<Project> filteredProjectsList = getProjectsNotInReleaseStage( projectsList );
 
-            projectsList = getProjects();
-        }
-
-        prepareBuildProjects( projectsList, null, true, trigger );
-    }
-
-    /**
-     * fire of the builds of all projects across all project groups using the group build definition
-     *
-     * @param trigger
-     * @param buildDefinitionId
-     * @throws ContinuumException
-     */
-    public void buildProjects( int trigger, int buildDefinitionId )
-        throws ContinuumException
-    {
-        Collection<Project> projectsList;
-
-        try
-        {
-            projectsList = getProjectsInBuildOrder();
-        }
-        catch ( CycleDetectedException e )
-        {
-            log.warn( "Cycle detected while sorting projects for building, falling back to unsorted build." );
-
-            projectsList = getProjects();
-        }
-
-        prepareBuildProjects( projectsList, buildDefinitionId, trigger );
+        prepareBuildProjects( filteredProjectsList, null, true, buildTrigger );
     }
 
     /**
      * fire off a build for all of the projects in a project group using their default builds
      *
      * @param projectGroupId
+     * @param buildTrigger
      * @throws ContinuumException
      */
-    public void buildProjectGroup( int projectGroupId )
-        throws ContinuumException
+    public void buildProjectGroup( int projectGroupId, BuildTrigger buildTrigger )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException
     {
-        List<BuildDefinition> groupDefaultBDs = null;
+        List<BuildDefinition> groupDefaultBDs;
 
-        groupDefaultBDs = getDefaultBuildDefinitionsForProjectGroup( projectGroupId );
+        if ( !isAnyProjectInGroupInReleaseStage( projectGroupId ) )
+        {
+            groupDefaultBDs = getDefaultBuildDefinitionsForProjectGroup( projectGroupId );
 
-        buildProjectGroupWithBuildDefinition( projectGroupId, groupDefaultBDs, true );
+            buildProjectGroupWithBuildDefinition( projectGroupId, groupDefaultBDs, true, buildTrigger );
+        }
     }
 
     /**
@@ -806,52 +847,58 @@
      *
      * @param projectGroupId    the project group id
      * @param buildDefinitionId the build definition id to use
+     * @param buildTrigger      the trigger state and the username
      * @throws ContinuumException
      */
-    public void buildProjectGroupWithBuildDefinition( int projectGroupId, int buildDefinitionId )
-        throws ContinuumException
+    public void buildProjectGroupWithBuildDefinition( int projectGroupId, int buildDefinitionId,
+                                                      BuildTrigger buildTrigger )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException
     {
-        List<BuildDefinition> bds = new ArrayList<BuildDefinition>();
-        BuildDefinition bd = getBuildDefinition( buildDefinitionId );
-        if ( bd != null )
+        if ( !isAnyProjectInGroupInReleaseStage( projectGroupId ) )
         {
-            bds.add( bd );
+            List<BuildDefinition> bds = new ArrayList<BuildDefinition>();
+            BuildDefinition bd = getBuildDefinition( buildDefinitionId );
+            if ( bd != null )
+            {
+                bds.add( bd );
+            }
+            buildProjectGroupWithBuildDefinition( projectGroupId, bds, false, buildTrigger );
         }
-        buildProjectGroupWithBuildDefinition( projectGroupId, bds, false );
     }
 
     /**
      * fire off a build for all of the projects in a project group using their default builds
      *
      * @param projectGroupId
+     * @param bds
+     * @param checkDefaultBuildDefinitionForProject
+     *
+     * @param buildTrigger
      * @throws ContinuumException
      */
     private void buildProjectGroupWithBuildDefinition( int projectGroupId, List<BuildDefinition> bds,
-                                                       boolean checkDefaultBuildDefinitionForProject )
-        throws ContinuumException
+                                                       boolean checkDefaultBuildDefinitionForProject,
+                                                       BuildTrigger buildTrigger )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException
     {
-        Collection<Project> projectsList;
-
-        try
+        if ( !isAnyProjectInGroupInReleaseStage( projectGroupId ) )
         {
+            Collection<Project> projectsList;
+
             projectsList = getProjectsInBuildOrder( projectDao.getProjectsWithDependenciesByGroupId( projectGroupId ) );
-        }
-        catch ( CycleDetectedException e )
-        {
-            log.warn( "Cycle detected while sorting projects for building, falling back to unsorted build." );
 
-            projectsList = getProjects();
-        }
+            buildTrigger.setTrigger( ContinuumProjectState.TRIGGER_FORCED );
 
-        prepareBuildProjects( projectsList, bds, checkDefaultBuildDefinitionForProject, ContinuumProjectState.TRIGGER_FORCED );
+            prepareBuildProjects( projectsList, bds, checkDefaultBuildDefinitionForProject, buildTrigger );
+        }
     }
 
     /**
      * takes a given schedule and determines which projects need to build
      * <p/>
-     * The build order is determined by the
+     * The build order is determined by the dependencies
      *
-     * @param schedule
+     * @param schedule The schedule
      * @throws ContinuumException
      */
     public void buildProjects( Schedule schedule )
@@ -859,7 +906,7 @@
     {
         Collection<Project> projectsList;
 
-        Map projectsMap = null;
+        Map<Integer, Object> projectsMap;
 
         try
         {
@@ -868,130 +915,166 @@
             if ( projectsMap == null || projectsMap.size() == 0 )
             {
                 log.debug( "no builds attached to schedule" );
-                // We don't have projects attached to this schedule
+                try
+                {
+                    schedulesActivator.unactivateOrphanBuildSchedule( schedule );
+                }
+                catch ( SchedulesActivationException e )
+                {
+                    log.debug( "Can't unactivate orphan shcedule for buildDefinitions" );
+                }
+                // We don't have projects attached to this schedule. This is because it's only is setting for a
+                // templateBuildDefinition
                 return;
             }
 
+            //TODO: As all projects are built in the same queue for a project group, it would be better to get them by
+            // project group and add them in queues in parallel to save few seconds
             projectsList = getProjectsInBuildOrder();
         }
         catch ( ContinuumStoreException e )
         {
             throw new ContinuumException( "Can't get project list for schedule " + schedule.getName(), e );
         }
-        catch ( CycleDetectedException e )
-        {
-            log.warn( "Cycle detected while sorting projects for building, falling back to unsorted build." );
-
-            projectsList = getProjects();
-        }
 
         Map<ProjectScmRoot, Map<Integer, Integer>> map = new HashMap<ProjectScmRoot, Map<Integer, Integer>>();
+        List<ProjectScmRoot> sortedScmRoot = new ArrayList<ProjectScmRoot>();
 
         for ( Project project : projectsList )
         {
-            List<Integer> buildDefIds = (List<Integer>) projectsMap.get( new Integer( project.getId() ) );
+            List<Integer> buildDefIds = (List<Integer>) projectsMap.get( project.getId() );
+            int projectId = project.getId();
 
             if ( buildDefIds != null && !buildDefIds.isEmpty() )
             {
                 for ( Integer buildDefId : buildDefIds )
                 {
-                    try
+                    if ( isProjectOkToBuild( project.getId(), buildDefId ) )
                     {
-                        if ( buildDefId != null && !taskQueueManager.isInBuildingQueue( project.getId(), buildDefId.intValue() ) &&
-                            !taskQueueManager.isInCheckoutQueue( project.getId() ) && !taskQueueManager.isInPrepareBuildQueue( project.getId() ) )
-                        {
-                            ProjectScmRoot scmRoot = getProjectScmRootByProject( project.getId() );
+                        ProjectScmRoot scmRoot = getProjectScmRootByProject( project.getId() );
 
-                            Map<Integer, Integer> projectsAndBuildDefinitionsMap = map.get( scmRoot );
-                            
-                            if ( projectsAndBuildDefinitionsMap == null )
-                            {
-                                projectsAndBuildDefinitionsMap = new HashMap<Integer, Integer>();
-                            }
-                            
-                            projectsAndBuildDefinitionsMap.put( project.getId(), buildDefId );
-                            
-                            map.put( scmRoot, projectsAndBuildDefinitionsMap );
+                        Map<Integer, Integer> projectsAndBuildDefinitionsMap = map.get( scmRoot );
+
+                        if ( projectsAndBuildDefinitionsMap == null )
+                        {
+                            projectsAndBuildDefinitionsMap = new HashMap<Integer, Integer>();
                         }
-                    } 
-                    catch ( TaskQueueManagerException e )
+
+                        projectsAndBuildDefinitionsMap.put( projectId, buildDefId );
+
+                        map.put( scmRoot, projectsAndBuildDefinitionsMap );
+
+                        if ( !sortedScmRoot.contains( scmRoot ) )
+                        {
+                            sortedScmRoot.add( scmRoot );
+                        }
+                    }
+                    else
                     {
-                        throw new ContinuumException( e.getMessage(), e );
+                        log.info(
+                            "Not queueing the build with projectId={} and buildDefinitionId={} because it is already building",
+                            projectId, buildDefId );
                     }
                 }
             }
         }
 
-        prepareBuildProjects( map, ContinuumProjectState.TRIGGER_SCHEDULED );
+        BuildTrigger buildTrigger = new BuildTrigger( ContinuumProjectState.TRIGGER_SCHEDULED, schedule.getName() );
+
+        for ( ProjectScmRoot scmRoot : sortedScmRoot )
+        {
+            try
+            {
+                prepareBuildProjects( map.get( scmRoot ), buildTrigger, scmRoot.getScmRootAddress(),
+                                      scmRoot.getProjectGroup().getId(), scmRoot.getId(), sortedScmRoot );
+            }
+            catch ( NoBuildAgentException e )
+            {
+                log.error( "Unable to build projects in project group " + scmRoot.getProjectGroup().getName() +
+                               " because there is no build agent configured" );
+            }
+            catch ( NoBuildAgentInGroupException e )
+            {
+                log.error( "Unable to build projects in project group " + scmRoot.getProjectGroup().getName() +
+                               " because there is no build agent configured in build agent group" );
+            }
+        }
     }
 
-    public void buildProject( int projectId )
-        throws ContinuumException
+    public void buildProject( int projectId, String username )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException
     {
-        buildProject( projectId, ContinuumProjectState.TRIGGER_FORCED );
+        buildProject( projectId, new BuildTrigger( ContinuumProjectState.TRIGGER_FORCED, username ) );
     }
 
-    public void buildProjectWithBuildDefinition( int projectId, int buildDefinitionId )
-        throws ContinuumException
+    public void buildProjectWithBuildDefinition( int projectId, int buildDefinitionId, BuildTrigger buildTrigger )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException
     {
-        buildProject( projectId, buildDefinitionId, ContinuumProjectState.TRIGGER_FORCED );
+        buildTrigger.setTrigger( ContinuumProjectState.TRIGGER_FORCED );
+        buildProject( projectId, buildDefinitionId, buildTrigger );
     }
 
-    public void buildProject( int projectId, int trigger )
-        throws ContinuumException
+    public void buildProject( int projectId, BuildTrigger buildTrigger )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException
     {
+        Project project = getProject( projectId );
+        if ( isProjectInReleaseStage( project ) )
+        {
+            throw new ContinuumException( "Project (id=" + projectId + ") is currently in release stage." );
+        }
+
         BuildDefinition buildDef = getDefaultBuildDefinition( projectId );
 
         if ( buildDef == null )
         {
-            throw new ContinuumException( "Project (id=" + projectId + " doens't have a default build definition." );
+            throw new ContinuumException( "Project (id=" + projectId + ") doesn't have a default build definition." );
         }
 
-        try
+        if ( !isProjectOkToBuild( projectId, buildDef.getId() ) )
         {
-            if ( taskQueueManager.isInBuildingQueue( projectId, buildDef.getId() ) || 
-                 taskQueueManager.isInCheckoutQueue( projectId ) ||
-                 taskQueueManager.isInPrepareBuildQueue( projectId ))
-            {
-                return;
-            }
-        }
-        catch ( TaskQueueManagerException e )
-        {
-            throw new ContinuumException( e.getMessage(), e );
+            log.info(
+                "Not queueing the build with projectId={} and buildDefinitionId={} because it is already building",
+                projectId, buildDef.getId() );
+            return;
         }
 
         Map<Integer, Integer> projectsBuildDefinitionsMap = new HashMap<Integer, Integer>();
         projectsBuildDefinitionsMap.put( projectId, buildDef.getId() );
-        
+
         ProjectScmRoot scmRoot = getProjectScmRootByProject( projectId );
-        prepareBuildProjects( projectsBuildDefinitionsMap, trigger, scmRoot.getScmRootAddress(), 
-                              scmRoot.getProjectGroup().getId(), scmRoot.getId() );
+        List<ProjectScmRoot> sortedScmRoot = new ArrayList<ProjectScmRoot>();
+        sortedScmRoot.add( scmRoot );
+
+        prepareBuildProjects( projectsBuildDefinitionsMap, buildTrigger, scmRoot.getScmRootAddress(),
+                              scmRoot.getProjectGroup().getId(), scmRoot.getId(), sortedScmRoot );
     }
 
-    public void buildProject( int projectId, int buildDefinitionId, int trigger )
-        throws ContinuumException
+    public void buildProject( int projectId, int buildDefinitionId, BuildTrigger buildTrigger )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException
     {
-        try
+        Project project = getProject( projectId );
+        if ( isProjectInReleaseStage( project ) )
         {
-            if ( taskQueueManager.isInBuildingQueue( projectId, buildDefinitionId ) || 
-                 taskQueueManager.isInCheckoutQueue( projectId ) ||
-                 taskQueueManager.isInPrepareBuildQueue( projectId ))
-            {
-                return;
-            }
+            throw new ContinuumException( "Project (id=" + projectId + ") is currently in release stage." );
         }
-        catch ( TaskQueueManagerException e )
+
+        if ( !isProjectOkToBuild( projectId, buildDefinitionId ) )
         {
-            throw new ContinuumException( e.getMessage(), e );
+            log.info(
+                "Not queueing the build with projectId={} and buildDefinitionId={} because it is already building",
+                projectId, buildDefinitionId );
+            return;
         }
 
         Map<Integer, Integer> projectsBuildDefinitionsMap = new HashMap<Integer, Integer>();
         projectsBuildDefinitionsMap.put( projectId, buildDefinitionId );
 
         ProjectScmRoot scmRoot = getProjectScmRootByProject( projectId );
-        prepareBuildProjects( projectsBuildDefinitionsMap, trigger, scmRoot.getScmRootAddress(), 
-                              scmRoot.getProjectGroup().getId(), scmRoot.getId() );
+        List<ProjectScmRoot> sortedScmRoot = new ArrayList<ProjectScmRoot>();
+        sortedScmRoot.add( scmRoot );
+
+        prepareBuildProjects( projectsBuildDefinitionsMap, buildTrigger, scmRoot.getScmRootAddress(),
+                              scmRoot.getProjectGroup().getId(), scmRoot.getId(), sortedScmRoot );
     }
 
     public BuildResult getBuildResult( int buildId )
@@ -1011,12 +1094,42 @@
         throws ContinuumException
     {
         BuildResult buildResult = getBuildResult( buildId );
+
+        // check first if build result is currently being used by a building project
+        Project project = buildResult.getProject();
+        BuildResult bResult = getLatestBuildResultForProject( project.getId() );
+
+        try
+        {
+            if ( bResult != null && buildResult.getId() == bResult.getId() &&
+                parallelBuildsManager.isProjectInAnyCurrentBuild( project.getId() ) )
+            {
+                throw new ContinuumException(
+                    "Unable to remove build result because it is currently being used by" + "a building project " +
+                        project.getId() );
+            }
+        }
+        catch ( BuildManagerException e )
+        {
+            throw new ContinuumException( e.getMessage(), e );
+        }
+
+        buildResult.getModifiedDependencies().clear();
+        buildResult.setBuildDefinition( null );
+
+        try
+        {
+            buildResultDao.updateBuildResult( buildResult );
+        }
+        catch ( ContinuumStoreException e )
+        {
+            throw logAndCreateException( "Error while removing build result in database.", e );
+        }
         removeBuildResult( buildResult );
     }
 
 
     private void removeBuildResult( BuildResult buildResult )
-        throws ContinuumException
     {
         buildResultDao.removeBuildResult( buildResult );
 
@@ -1030,11 +1143,11 @@
             {
                 FileUtils.deleteDirectory( buildDirectory );
             }
-            File buildOutputFile =
-                getConfiguration().getBuildOutputFile( buildResult.getId(), buildResult.getProject().getId() );
+            File buildOutputFile = getConfiguration().getBuildOutputFile( buildResult.getId(),
+                                                                          buildResult.getProject().getId() );
             if ( buildOutputFile.exists() )
             {
-                buildOutputFile.delete();
+                FileUtils.forceDelete( buildOutputFile );
             }
         }
         catch ( ConfigurationException e )
@@ -1061,11 +1174,24 @@
         }
     }
 
+    /**
+     * TODO: Must be done by build definition
+     */
     public List<ChangeSet> getChangesSinceLastSuccess( int projectId, int buildResultId )
         throws ContinuumException
     {
-        ArrayList<BuildResult> buildResults =
-            new ArrayList<BuildResult>( buildResultDao.getBuildResultsForProject( projectId, 0 ) );
+        BuildResult previousBuildResult = null;
+        try
+        {
+            previousBuildResult = buildResultDao.getPreviousBuildResultInSuccess( projectId, buildResultId );
+        }
+        catch ( ContinuumStoreException e )
+        {
+            //No previous build in success, Nothing to do
+        }
+        long startTime = previousBuildResult == null ? 0 : previousBuildResult.getStartTime();
+        ArrayList<BuildResult> buildResults = new ArrayList<BuildResult>(
+            buildResultDao.getBuildResultsForProjectWithDetails( projectId, startTime, buildResultId ) );
 
         Collections.reverse( buildResults );
 
@@ -1073,11 +1199,12 @@
 
         boolean stop = false;
 
+        //TODO: Shouldn't be used now with the previous call of buildResultDao.getBuildResultsForProjectWithDetails
         while ( !stop )
         {
             if ( buildResultsIterator.hasNext() )
             {
-                BuildResult buildResult = (BuildResult) buildResultsIterator.next();
+                BuildResult buildResult = buildResultsIterator.next();
 
                 if ( buildResult.getId() == buildResultId )
                 {
@@ -1095,7 +1222,7 @@
             return null;
         }
 
-        BuildResult buildResult = (BuildResult) buildResultsIterator.next();
+        BuildResult buildResult = buildResultsIterator.next();
 
         List<ChangeSet> changes = null;
 
@@ -1118,7 +1245,7 @@
                 return changes;
             }
 
-            buildResult = (BuildResult) buildResultsIterator.next();
+            buildResult = buildResultsIterator.next();
         }
 
         if ( changes == null )
@@ -1129,38 +1256,15 @@
         return changes;
     }
 
-    public List<ChangeSet> getChangesSinceLastUpdate( int projectId )
-        throws ContinuumException
-    {
-        List<ChangeSet> changes = new ArrayList<ChangeSet>();
-        
-        Project project;
-        
-        try
-        {
-            project = projectDao.getProjectWithScmDetails( projectId );
-        }
-        catch ( ContinuumStoreException e )
-        {
-            throw new ContinuumException( "", e );
-        }
-        
-        ScmResult scmResult = project.getScmResult();
-        
-        if ( scmResult != null )
-        {
-            changes.addAll( scmResult.getChanges() );
-        }
-        
-        return changes;
-    }
-
     // ----------------------------------------------------------------------
     //
     // ----------------------------------------------------------------------
 
-    public List<Project> getProjectsInBuildOrder()
-        throws CycleDetectedException, ContinuumException
+    /**
+     * TODO: Remove this method when it won't be used
+     */
+    private List<Project> getProjectsInBuildOrder()
+        throws ContinuumException
     {
         return getProjectsInBuildOrder( getProjectsWithDependencies() );
     }
@@ -1170,10 +1274,8 @@
      *
      * @param projects
      * @return
-     * @throws CycleDetectedException
      */
     public List<Project> getProjectsInBuildOrder( Collection<Project> projects )
-        throws CycleDetectedException
     {
         if ( projects == null || projects.isEmpty() )
         {
@@ -1187,28 +1289,6 @@
     // Maven 1.x projects
     // ----------------------------------------------------------------------
 
-    public ContinuumProjectBuildingResult addMavenOneProject( String metadataUrl )
-        throws ContinuumException
-    {
-        return addMavenOneProject( metadataUrl, true );
-    }
-
-    public ContinuumProjectBuildingResult addMavenOneProject( String metadataUrl, boolean checkProtocol )
-        throws ContinuumException
-    {
-        try
-        {
-            return executeAddProjectsFromMetadataActivity( metadataUrl, MavenOneContinuumProjectBuilder.ID,
-                                                           getDefaultProjectGroup().getId(), checkProtocol,
-                                                           buildDefinitionService
-                                                               .getDefaultMavenOneBuildDefinitionTemplate().getId() );
-        }
-        catch ( BuildDefinitionServiceException e )
-        {
-            throw new ContinuumException( e.getMessage(), e );
-        }
-    }
-
     public ContinuumProjectBuildingResult addMavenOneProject( String metadataUrl, int projectGroupId )
         throws ContinuumException
     {
@@ -1239,12 +1319,12 @@
 
     public ContinuumProjectBuildingResult addMavenOneProject( String metadataUrl, int projectGroupId,
                                                               boolean checkProtocol, boolean useCredentialsCache,
-                                                              int buildDefintionTemplateId )
+                                                              int buildDefinitionTemplateId )
         throws ContinuumException
     {
         return executeAddProjectsFromMetadataActivity( metadataUrl, MavenOneContinuumProjectBuilder.ID, projectGroupId,
                                                        checkProtocol, useCredentialsCache, true,
-                                                       buildDefintionTemplateId );
+                                                       buildDefinitionTemplateId, false );
     }
 
     // ----------------------------------------------------------------------
@@ -1263,8 +1343,8 @@
         try
         {
             return executeAddProjectsFromMetadataActivity( metadataUrl, MavenTwoContinuumProjectBuilder.ID, -1,
-                                                           checkProtocol, buildDefinitionService
-                .getDefaultMavenTwoBuildDefinitionTemplate().getId() );
+                                                           checkProtocol,
+                                                           buildDefinitionService.getDefaultMavenTwoBuildDefinitionTemplate().getId() );
         }
         catch ( BuildDefinitionServiceException e )
         {
@@ -1293,8 +1373,8 @@
         {
             return executeAddProjectsFromMetadataActivity( metadataUrl, MavenTwoContinuumProjectBuilder.ID,
                                                            projectGroupId, checkProtocol, useCredentialsCache, true,
-                                                           buildDefinitionService.getDefaultMavenTwoBuildDefinitionTemplate()
-                                                               .getId() );
+                                                           buildDefinitionService.getDefaultMavenTwoBuildDefinitionTemplate().getId(),
+                                                           false );
         }
         catch ( BuildDefinitionServiceException e )
         {
@@ -1311,8 +1391,9 @@
         {
             return executeAddProjectsFromMetadataActivity( metadataUrl, MavenTwoContinuumProjectBuilder.ID,
                                                            projectGroupId, checkProtocol, useCredentialsCache,
-                                                           recursiveProjects, buildDefinitionService
-                .getDefaultMavenTwoBuildDefinitionTemplate().getId() );
+                                                           recursiveProjects,
+                                                           buildDefinitionService.getDefaultMavenTwoBuildDefinitionTemplate().getId(),
+                                                           false );
         }
         catch ( BuildDefinitionServiceException e )
         {
@@ -1322,27 +1403,19 @@
 
     public ContinuumProjectBuildingResult addMavenTwoProject( String metadataUrl, int projectGroupId,
                                                               boolean checkProtocol, boolean useCredentialsCache,
-                                                              boolean recursiveProjects, int buildDefintionTemplateId )
+                                                              boolean recursiveProjects, int buildDefinitionTemplateId,
+                                                              boolean checkoutInSingleDirectory )
         throws ContinuumException
     {
         return executeAddProjectsFromMetadataActivity( metadataUrl, MavenTwoContinuumProjectBuilder.ID, projectGroupId,
                                                        checkProtocol, useCredentialsCache, recursiveProjects,
-                                                       buildDefintionTemplateId );
+                                                       buildDefinitionTemplateId, checkoutInSingleDirectory );
     }
 
     // ----------------------------------------------------------------------
     // Shell projects
     // ----------------------------------------------------------------------
 
-    /**
-     * @see org.apache.maven.continuum.Continuum#addProject(org.apache.maven.continuum.model.project.Project, java.lang.String)
-     */
-    public int addProject( Project project, String executorId )
-        throws ContinuumException
-    {
-        return addProject( project, executorId, getDefaultProjectGroup().getId() );
-    }
-
     public int addProject( Project project, String executorId, int groupId )
         throws ContinuumException
     {
@@ -1352,106 +1425,139 @@
     /**
      * @see org.apache.maven.continuum.Continuum#addProject(org.apache.maven.continuum.model.project.Project, java.lang.String, int, int)
      */
-    public int addProject( Project project, String executorId, int groupId, int buildDefintionTemplateId )
+    public int addProject( Project project, String executorId, int groupId, int buildDefinitionTemplateId )
         throws ContinuumException
     {
         project.setExecutorId( executorId );
 
-        List<BuildDefinition> buildDefinitions = Collections.EMPTY_LIST;
-
-        try
-        {
-            if ( executorId.equalsIgnoreCase( ContinuumBuildExecutorConstants.ANT_BUILD_EXECUTOR ) )
-            {
-                BuildDefinitionTemplate bdt = null;
-                if ( buildDefintionTemplateId <= 0 )
-                {
-                    bdt = buildDefinitionService.getDefaultAntBuildDefinitionTemplate();
-                }
-                else
-                {
-                    bdt = buildDefinitionService.getBuildDefinitionTemplate( buildDefintionTemplateId );
-                }
-                buildDefinitions = bdt.getBuildDefinitions();
-            }
-            else
-            {
-                //shell default
-
-                BuildDefinitionTemplate bdt = null;
-                if ( buildDefintionTemplateId <= 0 )
-                {
-                    bdt = buildDefinitionService.getDefaultShellBuildDefinitionTemplate();
-                }
-                else
-                {
-                    bdt = buildDefinitionService.getBuildDefinitionTemplate( buildDefintionTemplateId );
-                }
-                buildDefinitions = bdt.getBuildDefinitions();
-            }
-            for ( BuildDefinition buildDefinition : buildDefinitions )
-            {
-
-                BuildDefinition cloned = buildDefinitionService.cloneBuildDefinition( buildDefinition );
-                cloned.setTemplate( false );
-                project.addBuildDefinition( buildDefinitionService.addBuildDefinition( cloned ) );
-            }
-        }
-        catch ( BuildDefinitionServiceException e )
-        {
-            throw new ContinuumException( e.getMessage(), e );
-        }
-
-        return executeAddProjectFromScmActivity( project, groupId );
+        return executeAddProjectFromScmActivity( project, groupId, buildDefinitionTemplateId );
     }
 
     // ----------------------------------------------------------------------
     // Activities. These should end up as workflows in werkflow
     // ----------------------------------------------------------------------
 
-    @SuppressWarnings("unchecked")
-    private int executeAddProjectFromScmActivity( Project project, int groupId )
+    private int executeAddProjectFromScmActivity( Project project, int groupId, int buildDefinitionTemplateId )
         throws ContinuumException
     {
+        String executorId = project.getExecutorId();
+
         ProjectGroup projectGroup = getProjectGroupWithBuildDetails( groupId );
 
-        Map context = new HashMap();
+        Map<String, Object> context = new HashMap<String, Object>();
+
+        String scmUrl = project.getScmUrl();
+
+        List<ProjectScmRoot> scmRoots = getProjectScmRootByProjectGroup( groupId );
+
+        boolean found = false;
+
+        for ( ProjectScmRoot scmRoot : scmRoots )
+        {
+            if ( scmUrl.startsWith( scmRoot.getScmRootAddress() ) )
+            {
+                found = true;
+                break;
+            }
+        }
+
+        if ( !found )
+        {
+            createProjectScmRoot( projectGroup, scmUrl );
+        }
 
         // ----------------------------------------------------------------------
         //
         // ----------------------------------------------------------------------
 
-        context.put( AbstractContinuumAction.KEY_WORKING_DIRECTORY, getWorkingDirectory() );
+        AbstractContinuumAction.setWorkingDirectory( context, getWorkingDirectory() );
 
-        context.put( AbstractContinuumAction.KEY_UNVALIDATED_PROJECT, project );
+        AbstractContinuumAction.setUnvalidatedProject( context, project );
 
-        context.put( AbstractContinuumAction.KEY_UNVALIDATED_PROJECT_GROUP, projectGroup );
+        AbstractContinuumAction.setUnvalidatedProjectGroup( context, projectGroup );
 
-        context.put( AbstractContinuumAction.KEY_PROJECT_GROUP_ID, new Integer( projectGroup.getId() ) );
+        AbstractContinuumAction.setProjectGroupId( context, projectGroup.getId() );
+
+        StoreProjectAction.setUseScmCredentialsCache( context, project.isScmUseCache() );
+
+        // set for initial checkout
+        String scmUsername = project.getScmUsername();
+        String scmPassword = project.getScmPassword();
+
+        if ( scmUsername != null && !StringUtils.isEmpty( scmUsername ) )
+        {
+            CheckoutProjectContinuumAction.setScmUsername( context, scmUsername );
+        }
+
+        if ( scmPassword != null && !StringUtils.isEmpty( scmPassword ) )
+        {
+            CheckoutProjectContinuumAction.setScmPassword( context, scmPassword );
+        }
 
         executeAction( "validate-project", context );
 
         executeAction( "store-project", context );
 
+        try
+        {
+            BuildDefinitionTemplate bdt;
+
+            if ( executorId.equalsIgnoreCase( ContinuumBuildExecutorConstants.ANT_BUILD_EXECUTOR ) )
+            {
+                if ( buildDefinitionTemplateId <= 0 )
+                {
+                    bdt = buildDefinitionService.getDefaultAntBuildDefinitionTemplate();
+                }
+                else
+                {
+                    bdt = buildDefinitionService.getBuildDefinitionTemplate( buildDefinitionTemplateId );
+                }
+            }
+            else
+            {
+                //shell default
+                if ( buildDefinitionTemplateId <= 0 )
+                {
+                    bdt = buildDefinitionService.getDefaultShellBuildDefinitionTemplate();
+                }
+                else
+                {
+                    bdt = buildDefinitionService.getBuildDefinitionTemplate( buildDefinitionTemplateId );
+                }
+            }
+
+            buildDefinitionService.addTemplateInProject( bdt.getId(), getProject( AbstractContinuumAction.getProjectId(
+                context ) ) );
+        }
+        catch ( BuildDefinitionServiceException e )
+        {
+            throw new ContinuumException( e.getMessage(), e );
+        }
+
         if ( !configurationService.isDistributedBuildEnabled() )
         {
+            // used by BuildManager to determine on which build queue will the project be put
+            BuildDefinition bd = (BuildDefinition) getProjectWithBuildDetails( AbstractContinuumAction.getProjectId(
+                context ) ).getBuildDefinitions().get( 0 );
+            AbstractContinuumAction.setBuildDefinition( context, bd );
+
             executeAction( "add-project-to-checkout-queue", context );
         }
 
         executeAction( "add-assignable-roles", context );
 
-        return ( (Integer) context.get( AbstractContinuumAction.KEY_PROJECT_ID ) ).intValue();
+        return AbstractContinuumAction.getProjectId( context );
     }
 
     private ContinuumProjectBuildingResult executeAddProjectsFromMetadataActivity( String metadataUrl,
                                                                                    String projectBuilderId,
                                                                                    int projectGroupId,
                                                                                    boolean checkProtocol,
-                                                                                   int buildDefintionTemplateId )
+                                                                                   int buildDefinitionTemplateId )
         throws ContinuumException
     {
         return executeAddProjectsFromMetadataActivity( metadataUrl, projectBuilderId, projectGroupId, checkProtocol,
-                                                       false, false, buildDefintionTemplateId );
+                                                       false, false, buildDefinitionTemplateId, false );
     }
 
 
@@ -1461,8 +1567,9 @@
                                                                                      boolean checkProtocol,
                                                                                      boolean useCredentialsCache,
                                                                                      boolean loadRecursiveProjects,
-                                                                                     int buildDefintionTemplateId,
-                                                                                     boolean addAssignableRoles )
+                                                                                     int buildDefinitionTemplateId,
+                                                                                     boolean addAssignableRoles,
+                                                                                     boolean checkoutInSingleDirectory )
         throws ContinuumException
     {
         if ( checkProtocol )
@@ -1475,27 +1582,28 @@
             }
         }
 
-        Map context = new HashMap();
+        Map<String, Object> context = new HashMap<String, Object>();
 
-        context.put( CreateProjectsFromMetadataAction.KEY_PROJECT_BUILDER_ID, projectBuilderId );
+        CreateProjectsFromMetadataAction.setProjectBuilderId( context, projectBuilderId );
 
-        context.put( CreateProjectsFromMetadataAction.KEY_URL, metadataUrl );
+        CreateProjectsFromMetadataAction.setUrl( context, metadataUrl );
 
-        context.put( CreateProjectsFromMetadataAction.KEY_LOAD_RECURSIVE_PROJECTS, Boolean
-            .valueOf( loadRecursiveProjects ) );
+        CreateProjectsFromMetadataAction.setLoadRecursiveProject( context, loadRecursiveProjects );
 
-        context.put( CreateProjectsFromMetadataAction.KEY_SCM_USE_CREDENTIALS_CACHE, Boolean
-            .valueOf( useCredentialsCache ) );
+        StoreProjectAction.setUseScmCredentialsCache( context, useCredentialsCache );
 
-        context.put( AbstractContinuumAction.KEY_WORKING_DIRECTORY, getWorkingDirectory() );
+        AbstractContinuumAction.setWorkingDirectory( context, getWorkingDirectory() );
+
+        CreateProjectsFromMetadataAction.setCheckoutProjectsInSingleDirectory( context, checkoutInSingleDirectory );
 
         // CreateProjectsFromMetadataAction will check null and use default
-        if ( buildDefintionTemplateId > 0 )
+        if ( buildDefinitionTemplateId > 0 )
         {
             try
             {
-                context.put( AbstractContinuumAction.KEY_BUILD_DEFINITION_TEMPLATE, buildDefinitionService
-                    .getBuildDefinitionTemplate( buildDefintionTemplateId ) );
+                AbstractContinuumAction.setBuildDefinitionTemplate( context,
+                                                                    buildDefinitionService.getBuildDefinitionTemplate(
+                                                                        buildDefinitionTemplateId ) );
             }
             catch ( BuildDefinitionServiceException e )
             {
@@ -1506,10 +1614,16 @@
         // Create the projects from the URL
         // ----------------------------------------------------------------------
 
+        ProjectGroup projectGroup;
+
+        if ( projectGroupId != -1 )
+        {
+            CreateProjectsFromMetadataAction.setProjectGroupId( context, projectGroupId );
+        }
+
         executeAction( "create-projects-from-metadata", context );
 
-        ContinuumProjectBuildingResult result = (ContinuumProjectBuildingResult) context
-            .get( CreateProjectsFromMetadataAction.KEY_PROJECT_BUILDING_RESULT );
+        ContinuumProjectBuildingResult result = CreateProjectsFromMetadataAction.getProjectBuildingResult( context );
 
         if ( log.isInfoEnabled() )
         {
@@ -1545,58 +1659,63 @@
             throw new ContinuumException( "The project building result has to contain exactly one project group." );
         }
 
-        ProjectGroup projectGroup = (ProjectGroup) result.getProjectGroups().iterator().next();
-
-
-        ProjectScmRoot projectScmRoot;
-
-
         boolean projectGroupCreation = false;
-        
 
         try
         {
             if ( projectGroupId == -1 )
             {
+                projectGroup = result.getProjectGroups().iterator().next();
+
                 try
                 {
                     projectGroup = projectGroupDao.getProjectGroupByGroupId( projectGroup.getGroupId() );
 
                     projectGroupId = projectGroup.getId();
 
-                    log.info(
-                        "Using existing project group with the group id: '" + projectGroup.getGroupId() + "'." );
+                    log.info( "Using existing project group with the group id: '" + projectGroup.getGroupId() + "'." );
                 }
                 catch ( ContinuumObjectNotFoundException e )
                 {
-                    log.info(
-                        "Creating project group with the group id: '" + projectGroup.getGroupId() + "'." );
+                    log.info( "Creating project group with the group id: '" + projectGroup.getGroupId() + "'." );
 
-                    Map pgContext = new HashMap();
+                    Map<String, Object> pgContext = new HashMap<String, Object>();
 
-                    pgContext.put( AbstractContinuumAction.KEY_WORKING_DIRECTORY, getWorkingDirectory() );
+                    AbstractContinuumAction.setWorkingDirectory( pgContext, getWorkingDirectory() );
 
-                    pgContext.put( AbstractContinuumAction.KEY_UNVALIDATED_PROJECT_GROUP, projectGroup );
+                    AbstractContinuumAction.setUnvalidatedProjectGroup( pgContext, projectGroup );
 
                     executeAction( "validate-project-group", pgContext );
 
                     executeAction( "store-project-group", pgContext );
 
                     projectGroupId = AbstractContinuumAction.getProjectGroupId( pgContext );
-                    
+
                     projectGroupCreation = true;
                 }
             }
 
             projectGroup = projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId( projectGroupId );
 
-            String url = (String) context.get( CreateProjectsFromMetadataAction.KEY_URL );
-            
-            projectScmRoot = getProjectScmRootByProjectGroupAndScmRootAddress( projectGroup.getId(), url );
-            
-            if ( projectScmRoot == null )
+            //String url = CreateProjectsFromMetadataAction.getUrl( context );
+            String url = AbstractContinuumAction.getProjectScmRootUrl( context, null );
+
+            List<ProjectScmRoot> scmRoots = getProjectScmRootByProjectGroup( projectGroup.getId() );
+
+            boolean found = false;
+
+            for ( ProjectScmRoot scmRoot : scmRoots )
             {
-                projectScmRoot = createProjectScmRoot( projectGroup, url );
+                if ( url.startsWith( scmRoot.getScmRootAddress() ) )
+                {
+                    found = true;
+                    break;
+                }
+            }
+
+            if ( !found )
+            {
+                createProjectScmRoot( projectGroup, url );
             }
 
             /* add the project group loaded from database, which has more info, like id */
@@ -1620,9 +1739,18 @@
 
         for ( Project project : projects )
         {
+            checkForDuplicateProjectInGroup( projectGroup, project, result );
+
+            if ( result.hasErrors() )
+            {
+                log.info( result.getErrors().size() + " errors during project add: " );
+                log.info( result.getErrorsAsString() );
+                return result;
+            }
+
             project.setScmUseCache( useCredentialsCache );
 
-            // values backup for first 
+            // values backup for first checkout
             scmUserName = project.getScmUsername();
             scmPassword = project.getScmPassword();
             // CONTINUUM-1792 : we don't store it
@@ -1639,43 +1767,44 @@
         {
             projectGroupDao.updateProjectGroup( projectGroup );
 
-            for ( Project project : projects )
+            if ( !checkoutInSingleDirectory )
             {
-                context = new HashMap();
+                for ( Project project : projects )
+                {
+                    context = new HashMap<String, Object>();
 
-                // CONTINUUM-1953 olamy : attached buildDefs from template here
-                // if no group creation 
-                if ( !projectGroupCreation && buildDefintionTemplateId > 0 )
-                {
-                    buildDefinitionService.addTemplateInProject( buildDefintionTemplateId, projectDao
-                        .getProject( project.getId() ) );
-                }                
-                
-                context.put( AbstractContinuumAction.KEY_UNVALIDATED_PROJECT, project );
-                //
-                //            executeAction( "validate-project", context );
-                //
-                //            executeAction( "store-project", context );
-                //
-                context.put( AbstractContinuumAction.KEY_PROJECT_ID, new Integer( project.getId() ) );
+                    Project fetchedProject = projectDao.getProjectWithBuildDetails( project.getId() );
 
-                if ( !StringUtils.isEmpty( scmUserName ) )
-                {
-                    project.setScmUsername( scmUserName );
-                    context.put( AbstractContinuumAction.KEY_SCM_USERNAME, scmUserName );
+                    addProjectToCheckoutQueue( projectBuilderId, buildDefinitionTemplateId, context,
+                                               projectGroupCreation, scmUserName, scmPassword, project,
+                                               isDefaultProjectBuildDefSet( fetchedProject ) );
                 }
-                if ( !StringUtils.isEmpty( scmPassword ) )
+            }
+            else
+            {
+                Project project = result.getRootProject();
+
+                if ( project != null )
                 {
-                    project.setScmPassword( scmPassword );
-                    context.put( AbstractContinuumAction.KEY_SCM_PASSWORD, scmPassword );
-                }
-                // FIXME
-                // olamy  : read again the project to have values because store.updateProjectGroup( projectGroup ); 
-                // remove object data -> we don't display the project name in the build queue
-                context.put( AbstractContinuumAction.KEY_PROJECT, projectDao.getProject( project.getId() ) );
-                if ( !configurationService.isDistributedBuildEnabled() )
-                {
-                    executeAction( "add-project-to-checkout-queue", context );
+                    String scmRootUrl = AbstractContinuumAction.getProjectScmRootUrl( context, null );
+                    context = new HashMap<String, Object>();
+
+                    AbstractContinuumAction.setProjectScmRootUrl( context, scmRootUrl );
+
+                    List<Project> projectsWithSimilarScmRoot = new ArrayList<Project>();
+                    for ( Project projectWithSimilarScmRoot : projects )
+                    {
+                        projectsWithSimilarScmRoot.add( projectWithSimilarScmRoot );
+                    }
+
+                    AbstractContinuumAction.setListOfProjectsInGroupWithCommonScmRoot( context,
+                                                                                       projectsWithSimilarScmRoot );
+
+                    Project fetchedProject = projectDao.getProjectWithBuildDetails( project.getId() );
+
+                    addProjectToCheckoutQueue( projectBuilderId, buildDefinitionTemplateId, context,
+                                               projectGroupCreation, scmUserName, scmPassword, project,
+                                               isDefaultProjectBuildDefSet( fetchedProject ) );
                 }
             }
         }
@@ -1688,8 +1817,8 @@
             throw new ContinuumException( "Error adding projects from modules", e );
         }
 
-        context.put( AbstractContinuumAction.KEY_PROJECT_GROUP_ID, new Integer( projectGroup.getId() ) );
-        // add the relevent security administration roles for this project
+        AbstractContinuumAction.setProjectGroupId( context, projectGroup.getId() );
+        // add the relevant security administration roles for this project
         if ( addAssignableRoles )
         {
             executeAction( "add-assignable-roles", context );
@@ -1697,18 +1826,110 @@
         return result;
     }
 
-    protected ContinuumProjectBuildingResult executeAddProjectsFromMetadataActivity( String metadataUrl,
-                                                                                     String projectBuilderId,
-                                                                                     int projectGroupId,
-                                                                                     boolean checkProtocol,
-                                                                                     boolean useCredentialsCache,
-                                                                                     boolean loadRecursiveProjects,
-                                                                                     int buildDefintionTemplateId )
+    private boolean isDefaultProjectBuildDefSet( Project project )
+    {
+        for ( BuildDefinition bd : project.getBuildDefinitions() )
+        {
+            if ( bd.isDefaultForProject() )
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    private void addProjectToCheckoutQueue( String projectBuilderId, int buildDefinitionTemplateId,
+                                            Map<String, Object> context, boolean projectGroupCreation,
+                                            String scmUserName, String scmPassword, Project project,
+                                            boolean defaultProjectBuildDefSet )
+        throws BuildDefinitionServiceException, ContinuumStoreException, ContinuumException
+    {
+        // CONTINUUM-1953 olamy : attached buildDefs from template here
+        // if no group creation
+        if ( !projectGroupCreation && buildDefinitionTemplateId > 0 && !defaultProjectBuildDefSet )
+        {
+            buildDefinitionService.addTemplateInProject( buildDefinitionTemplateId, projectDao.getProject(
+                project.getId() ) );
+        }
+
+        AbstractContinuumAction.setUnvalidatedProject( context, project );
+        //
+        //            executeAction( "validate-project", context );
+        //
+        //            executeAction( "store-project", context );
+        //
+
+        AbstractContinuumAction.setProjectId( context, project.getId() );
+
+        // does the scm username & password really have to be set in the project?
+        if ( !StringUtils.isEmpty( scmUserName ) )
+        {
+            project.setScmUsername( scmUserName );
+            CheckoutProjectContinuumAction.setScmUsername( context, scmUserName );
+        }
+        if ( !StringUtils.isEmpty( scmPassword ) )
+        {
+            project.setScmPassword( scmPassword );
+            CheckoutProjectContinuumAction.setScmPassword( context, scmPassword );
+        }
+        //FIXME
+        // olamy  : read again the project to have values because store.updateProjectGroup( projectGroup );
+        // remove object data -> we don't display the project name in the build queue
+        AbstractContinuumAction.setProject( context, projectDao.getProject( project.getId() ) );
+
+        BuildDefinition defaultBuildDefinition = null;
+        BuildDefinitionTemplate template = null;
+        if ( projectBuilderId.equals( MavenTwoContinuumProjectBuilder.ID ) )
+        {
+            template = buildDefinitionService.getDefaultMavenTwoBuildDefinitionTemplate();
+
+            if ( template != null && template.getBuildDefinitions().size() > 0 )
+            {
+                defaultBuildDefinition = template.getBuildDefinitions().get( 0 );
+            }
+        }
+        else if ( projectBuilderId.equals( MavenOneContinuumProjectBuilder.ID ) )
+        {
+            template = buildDefinitionService.getDefaultMavenOneBuildDefinitionTemplate();
+
+            if ( template != null && template.getBuildDefinitions().size() > 0 )
+            {
+                defaultBuildDefinition = template.getBuildDefinitions().get( 0 );
+            }
+        }
+
+        if ( defaultBuildDefinition == null )
+        {
+            // do not throw exception
+            // project already added so might as well continue with the rest
+            log.warn( "No default build definition found in the template. Project cannot be checked out." );
+        }
+        else
+        {
+            // used by BuildManager to determine on which build queue will the project be put
+            AbstractContinuumAction.setBuildDefinition( context, defaultBuildDefinition );
+
+            if ( !configurationService.isDistributedBuildEnabled() )
+            {
+                executeAction( "add-project-to-checkout-queue", context );
+            }
+        }
+    }
+
+    private ContinuumProjectBuildingResult executeAddProjectsFromMetadataActivity( String metadataUrl,
+                                                                                   String projectBuilderId,
+                                                                                   int projectGroupId,
+                                                                                   boolean checkProtocol,
+                                                                                   boolean useCredentialsCache,
+                                                                                   boolean loadRecursiveProjects,
+                                                                                   int buildDefinitionTemplateId,
+                                                                                   boolean checkoutInSingleDirectory )
         throws ContinuumException
     {
         return executeAddProjectsFromMetadataActivity( metadataUrl, projectBuilderId, projectGroupId, checkProtocol,
                                                        useCredentialsCache, loadRecursiveProjects,
-                                                       buildDefintionTemplateId, true );
+                                                       buildDefinitionTemplateId, true, checkoutInSingleDirectory );
     }
 
     // ----------------------------------------------------------------------
@@ -1799,52 +2020,6 @@
         return addGroupNotifier( projectGroupId, notifier );
     }
 
-    /*
-    public ProjectNotifier updateNotifier( int projectId, int notifierId, Map configuration )
-        throws ContinuumException
-    {
-        Project project = getProjectWithAllDetails( projectId );
-
-        ProjectNotifier notifier = getNotifier( projectId, notifierId );
-
-        String notifierType = notifier.getType();
-
-        // I remove notifier then add it instead of update it due to a ClassCastException in jpox
-        project.removeNotifier( notifier );
-
-        updateProject( project );
-
-        return addNotifier( projectId, notifierType, configuration );
-    }
-
-    private Properties createNotifierProperties( Map configuration )
-    {
-        Properties notifierProperties = new Properties();
-
-        for ( Iterator i = configuration.keySet().iterator(); i.hasNext(); )
-        {
-            Object key = i.next();
-
-            Object value = configuration.get( key );
-
-            if ( value instanceof String )
-            {
-                String val = (String) value;
-                if ( !"sendOnSuccess".equals( val ) && !"sendOnFailure".equals( val ) && !"sendOnError".equals( val ) &&
-                    !"sendOnWarning".equals( val ) )
-                {
-                    if ( !StringUtils.isEmpty( val ) )
-                    {
-                        notifierProperties.setProperty( (String) key, val );
-                    }
-                }
-            }
-        }
-
-        return notifierProperties;
-    }
-    */
-
     public ProjectNotifier addNotifier( int projectId, ProjectNotifier notifier )
         throws ContinuumException
     {
@@ -1911,42 +2086,6 @@
         return notif;
     }
 
-    /*
-    public ProjectNotifier addNotifier( int projectId, String notifierType, Map configuration )
-        throws ContinuumException
-    {
-        ProjectNotifier notifier = new ProjectNotifier();
-
-        notifier.setType( notifierType );
-
-        // ----------------------------------------------------------------------
-        // Needs to be properties ... but data comes in via a Map
-        // ----------------------------------------------------------------------
-
-        Properties notifierProperties = createNotifierProperties( configuration );
-
-        boolean sendOnSuccess = convertBoolean( (String) configuration.get( "sendOnSuccess" ) );
-
-        notifier.setSendOnSuccess( sendOnSuccess );
-
-        boolean sendOnFailure = convertBoolean( (String) configuration.get( "sendOnFailure" ) );
-
-        notifier.setSendOnFailure( sendOnFailure );
-
-        boolean sendOnError = convertBoolean( (String) configuration.get( "sendOnError" ) );
-
-        notifier.setSendOnError( sendOnError );
-
-        boolean sendOnWarning = convertBoolean( (String) configuration.get( "sendOnWarning" ) );
-
-        notifier.setSendOnWarning( sendOnWarning );
-
-        notifier.setConfiguration( notifierProperties );
-
-        return addNotifier( projectId, notifier );
-    }
-    */
-
     public void removeNotifier( int projectId, int notifierId )
         throws ContinuumException
     {
@@ -2061,12 +2200,12 @@
         catch ( ContinuumObjectNotFoundException cne )
         {
             throw new ContinuumException( "Project Group (id=" + projectGroupId +
-                " doens't have a default build definition, this should be impossible, it should always have a default definition set." );
+                                              ") doesn't have a default build definition, this should be impossible, it should always have a default definition set." );
         }
         catch ( ContinuumStoreException cse )
         {
             throw new ContinuumException( "Project Group (id=" + projectGroupId +
-                " doens't have a default build definition, this should be impossible, it should always have a default definition set." );
+                                              ") doesn't have a default build definition, this should be impossible, it should always have a default definition set." );
         }
     }
 
@@ -2107,23 +2246,27 @@
     public BuildDefinition addBuildDefinitionToProject( int projectId, BuildDefinition buildDefinition )
         throws ContinuumException
     {
-        HashMap context = new HashMap();
+        HashMap<String, Object> context = new HashMap<String, Object>();
+        Schedule schedule = buildDefinition.getSchedule();
 
-        context.put( AbstractContinuumAction.KEY_BUILD_DEFINITION, buildDefinition );
-        context.put( AbstractContinuumAction.KEY_PROJECT_ID, new Integer( projectId ) );
+        AbstractContinuumAction.setBuildDefinition( context, buildDefinition );
+        AbstractContinuumAction.setProjectId( context, projectId );
 
         executeAction( "add-build-definition-to-project", context );
 
-        return (BuildDefinition) context.get( AbstractContinuumAction.KEY_BUILD_DEFINITION );
+        activeBuildDefinitionSchedule( schedule );
+
+        return AbstractContinuumAction.getBuildDefinition( context );
     }
 
     public void removeBuildDefinitionFromProject( int projectId, int buildDefinitionId )
         throws ContinuumException
     {
-        HashMap context = new HashMap();
+        HashMap<String, Object> context = new HashMap<String, Object>();
+        BuildDefinition buildDefinition = getBuildDefinition( buildDefinitionId );
 
-        context.put( AbstractContinuumAction.KEY_BUILD_DEFINITION, getBuildDefinition( buildDefinitionId ) );
-        context.put( AbstractContinuumAction.KEY_PROJECT_ID, new Integer( projectId ) );
+        AbstractContinuumAction.setBuildDefinition( context, buildDefinition );
+        AbstractContinuumAction.setProjectId( context, projectId );
 
         executeAction( "remove-build-definition-from-project", context );
     }
@@ -2131,36 +2274,42 @@
     public BuildDefinition updateBuildDefinitionForProject( int projectId, BuildDefinition buildDefinition )
         throws ContinuumException
     {
-        HashMap context = new HashMap();
+        HashMap<String, Object> context = new HashMap<String, Object>();
+        Schedule schedule = buildDefinition.getSchedule();
 
-        context.put( AbstractContinuumAction.KEY_BUILD_DEFINITION, buildDefinition );
-        context.put( AbstractContinuumAction.KEY_PROJECT_ID, new Integer( projectId ) );
+        AbstractContinuumAction.setBuildDefinition( context, buildDefinition );
+        AbstractContinuumAction.setProjectId( context, projectId );
 
         executeAction( "update-build-definition-from-project", context );
 
-        return (BuildDefinition) context.get( AbstractContinuumAction.KEY_BUILD_DEFINITION );
+        activeBuildDefinitionSchedule( schedule );
+
+        return AbstractContinuumAction.getBuildDefinition( context );
     }
 
     public BuildDefinition addBuildDefinitionToProjectGroup( int projectGroupId, BuildDefinition buildDefinition )
         throws ContinuumException
     {
-        HashMap context = new HashMap();
+        HashMap<String, Object> context = new HashMap<String, Object>();
+        Schedule schedule = buildDefinition.getSchedule();
 
-        context.put( AbstractContinuumAction.KEY_BUILD_DEFINITION, buildDefinition );
-        context.put( AbstractContinuumAction.KEY_PROJECT_GROUP_ID, new Integer( projectGroupId ) );
+        AbstractContinuumAction.setBuildDefinition( context, buildDefinition );
+        AbstractContinuumAction.setProjectGroupId( context, projectGroupId );
 
         executeAction( "add-build-definition-to-project-group", context );
 
-        return (BuildDefinition) context.get( AbstractContinuumAction.KEY_BUILD_DEFINITION );
+        activeBuildDefinitionSchedule( schedule );
+
+        return AbstractContinuumAction.getBuildDefinition( context );
     }
 
     public void removeBuildDefinitionFromProjectGroup( int projectGroupId, int buildDefinitionId )
         throws ContinuumException
     {
-        HashMap context = new HashMap();
+        HashMap<String, Object> context = new HashMap<String, Object>();
 
-        context.put( AbstractContinuumAction.KEY_BUILD_DEFINITION, getBuildDefinition( buildDefinitionId ) );
-        context.put( AbstractContinuumAction.KEY_PROJECT_GROUP_ID, new Integer( projectGroupId ) );
+        AbstractContinuumAction.setBuildDefinition( context, getBuildDefinition( buildDefinitionId ) );
+        AbstractContinuumAction.setProjectGroupId( context, projectGroupId );
 
         executeAction( "remove-build-definition-from-project-group", context );
     }
@@ -2168,14 +2317,17 @@
     public BuildDefinition updateBuildDefinitionForProjectGroup( int projectGroupId, BuildDefinition buildDefinition )
         throws ContinuumException
     {
-        HashMap context = new HashMap();
+        HashMap<String, Object> context = new HashMap<String, Object>();
+        Schedule schedule = buildDefinition.getSchedule();
 
-        context.put( AbstractContinuumAction.KEY_BUILD_DEFINITION, buildDefinition );
-        context.put( AbstractContinuumAction.KEY_PROJECT_GROUP_ID, new Integer( projectGroupId ) );
+        AbstractContinuumAction.setBuildDefinition( context, buildDefinition );
+        AbstractContinuumAction.setProjectGroupId( context, projectGroupId );
 
         executeAction( "update-build-definition-from-project-group", context );
 
-        return (BuildDefinition) context.get( AbstractContinuumAction.KEY_BUILD_DEFINITION );
+        activeBuildDefinitionSchedule( schedule );
+
+        return AbstractContinuumAction.getBuildDefinition( context );
     }
 
     public void removeBuildDefinition( int projectId, int buildDefinitionId )
@@ -2193,19 +2345,6 @@
         }
     }
 
-    public void removeBuildDefinition( BuildDefinition buildDefinition )
-        throws ContinuumException
-    {
-        try
-        {
-            buildDefinitionDao.removeBuildDefinition( buildDefinition );
-        }
-        catch ( ContinuumStoreException ex )
-        {
-            throw logAndCreateException( "Error while removing build definition.", ex );
-        }
-    }
-
     // ----------------------------------------------------------------------
     // Schedule
     // ----------------------------------------------------------------------
@@ -2275,6 +2414,9 @@
     private void updateSchedule( Schedule schedule, boolean updateScheduler )
         throws ContinuumException
     {
+
+        Schedule old = getSchedule( schedule.getId() );
+
         storeSchedule( schedule );
 
         if ( updateScheduler )
@@ -2283,14 +2425,15 @@
             {
                 if ( schedule.isActive() )
                 {
-                    // I unactivate it before if it's already active
-                    schedulesActivator.unactivateSchedule( schedule, this );
+                    // I unactivate old shcedule (could change name) before if it's already active
+                    schedulesActivator.unactivateSchedule( old, this );
 
                     schedulesActivator.activateSchedule( schedule, this );
                 }
                 else
                 {
-                    schedulesActivator.unactivateSchedule( schedule, this );
+                    // Unactivate old because could change name in new schedule
+                    schedulesActivator.unactivateSchedule( old, this );
                 }
             }
             catch ( SchedulesActivationException e )
@@ -2313,7 +2456,7 @@
 
         schedule.setDelay( Integer.parseInt( configuration.get( "schedule.delay" ) ) );
 
-        schedule.setActive( Boolean.valueOf( configuration.get( "schedule.active" ) ).booleanValue() );
+        schedule.setActive( Boolean.valueOf( configuration.get( "schedule.active" ) ) );
 
         updateSchedule( schedule, true );
     }
@@ -2352,7 +2495,7 @@
         }
     }
 
-    public Schedule storeSchedule( Schedule schedule )
+    private Schedule storeSchedule( Schedule schedule )
         throws ContinuumException
     {
         try
@@ -2365,6 +2508,29 @@
         }
     }
 
+    public void activePurgeSchedule( Schedule schedule )
+    {
+        try
+        {
+            schedulesActivator.activatePurgeSchedule( schedule, this );
+        }
+        catch ( SchedulesActivationException e )
+        {
+            log.error( "Can't activate schedule for purgeConfiguration" );
+        }
+    }
+
+    public void activeBuildDefinitionSchedule( Schedule schedule )
+    {
+        try
+        {
+            schedulesActivator.activateBuildSchedule( schedule, this );
+        }
+        catch ( SchedulesActivationException e )
+        {
+            log.error( "Can't activate schedule for buildDefinition" );
+        }
+    }
     // ----------------------------------------------------------------------
     // Working copy
     // ----------------------------------------------------------------------
@@ -2433,6 +2599,7 @@
         }
 
         String[] files = workingDirectory.list();
+        Arrays.sort( files, String.CASE_INSENSITIVE_ORDER );
 
         if ( files != null )
         {
@@ -2498,25 +2665,6 @@
     {
         log.info( "Initializing Continuum." );
 
-        File wdFile = new File( workingDirectory );
-
-        if ( wdFile.exists() )
-        {
-            if ( !wdFile.isDirectory() )
-            {
-                throw new InitializationException(
-                    "The specified working directory isn't a directory: " + "'" + wdFile.getAbsolutePath() + "'." );
-            }
-        }
-        else
-        {
-            if ( !wdFile.mkdirs() )
-            {
-                throw new InitializationException(
-                    "Could not making the working directory: " + "'" + wdFile.getAbsolutePath() + "'." );
-            }
-        }
-
         log.info( "Showing all groups:" );
         try
         {
@@ -2562,8 +2710,8 @@
 
                 try
                 {
-                    log.info( "Fix project state for project " + project.getId() + ":" + project.getName() +
-                        ":" + project.getVersion() );
+                    log.info( "Fix project state for project " + project.getId() + ":" + project.getName() + ":" +
+                                  project.getVersion() );
 
                     projectDao.updateProject( project );
 
@@ -2581,7 +2729,7 @@
             }
 
             log.info( " " + project.getId() + ":" + project.getName() + ":" + project.getVersion() + ":" +
-                project.getExecutorId() );
+                          project.getExecutorId() );
         }
 
         for ( ProjectScmRoot projectScmRoot : projectScmRootDao.getAllProjectScmRoots() )
@@ -2595,7 +2743,7 @@
                 try
                 {
                     log.info( "Fix state for projectScmRoot " + projectScmRoot.getScmRootAddress() );
-                    
+
                     projectScmRootDao.updateProjectScmRoot( projectScmRoot );
                 }
                 catch ( ContinuumStoreException e )
@@ -2609,12 +2757,6 @@
     // --------------------------------
     //  Plexus Lifecycle
     // --------------------------------
-    public void contextualize( Context context )
-        throws ContextException
-    {
-        container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
-    }
-
     public void start()
         throws StartingException
     {
@@ -2681,9 +2823,9 @@
         }
     }
 
-    public void stopContinuum()
-        throws StoppingException
+    private void stopContinuum()
     {
+        //TODO: Remove all projects from queues, stop scheduler and wait the end of current builds so build results will be ok
         if ( stopped )
         {
             return;
@@ -2723,7 +2865,7 @@
     // Workflow
     // ----------------------------------------------------------------------
 
-    protected void executeAction( String actionName, Map context )
+    protected void executeAction( String actionName, Map<String, Object> context )
         throws ContinuumException
     {
         try
@@ -2778,10 +2920,17 @@
             boolean removeWorkingDirectory = false;
 
             Project p = projectDao.getProject( project.getId() );
+            ProjectScmRoot projectScmRoot = null;
 
             if ( !p.getScmUrl().equals( project.getScmUrl() ) )
             {
                 removeWorkingDirectory = true;
+                projectScmRoot = getProjectScmRootByProject( project.getId() );
+            }
+
+            if ( !p.getProjectGroup().equals( project.getProjectGroup() ) )
+            {
+                projectScmRoot = getProjectScmRootByProject( project.getId() );
             }
 
             if ( StringUtils.isEmpty( p.getScmTag() ) && !StringUtils.isEmpty( project.getScmTag() ) )
@@ -2810,6 +2959,11 @@
             }
 
             projectDao.updateProject( project );
+
+            if ( projectScmRoot != null )
+            {
+                updateProjectScmRoot( projectScmRoot, project );
+            }
         }
         catch ( ContinuumStoreException ex )
         {
@@ -2836,20 +2990,7 @@
         }
     }
 
-    public void removeNotifier( ProjectNotifier notifier )
-        throws ContinuumException
-    {
-        try
-        {
-            notifierDao.removeNotifier( notifier );
-        }
-        catch ( ContinuumStoreException ex )
-        {
-            throw logAndCreateException( "Error while removing notifier.", ex );
-        }
-    }
-
-    public ProjectNotifier storeNotifier( ProjectNotifier notifier )
+    private ProjectNotifier storeNotifier( ProjectNotifier notifier )
         throws ContinuumException
     {
         try
@@ -2862,9 +3003,9 @@
         }
     }
 
-    public String getWorkingDirectory()
+    private String getWorkingDirectory()
     {
-        return workingDirectory;
+        return configurationService.getWorkingDirectory().getAbsolutePath();
     }
 
     public Project getProjectWithCheckoutResult( int projectId )
@@ -2884,11 +3025,6 @@
         }
     }
 
-    public List<Project> getAllProjectsWithAllDetails( int start, int end )
-    {
-        return projectDao.getAllProjectsWithAllDetails();
-    }
-
     public Project getProjectWithAllDetails( int projectId )
         throws ContinuumException
     {
@@ -2940,12 +3076,6 @@
         }
     }
 
-    public Collection<ProjectGroup> getAllProjectGroupsWithProjects()
-    {
-        //TODO: check why this interface isn't throwing exceptions on this guy
-        return projectGroupDao.getAllProjectGroupsWithProjects();
-    }
-
     public List<ProjectGroup> getAllProjectGroupsWithBuildDetails()
     {
         return projectGroupDao.getAllProjectGroupsWithBuildDetails();
@@ -3025,13 +3155,14 @@
 
     private String getVersion()
     {
+        InputStream resourceAsStream = null;
         try
         {
             Properties properties = new Properties();
 
-            String name = "META-INF/maven/org.apache.maven.continuum/continuum-core/pom.properties";
+            String name = "META-INF/maven/org.apache.continuum/continuum-core/pom.properties";
 
-            InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream( name );
+            resourceAsStream = getClass().getClassLoader().getResourceAsStream( name );
 
             if ( resourceAsStream == null )
             {
@@ -3046,23 +3177,12 @@
         {
             return "unknown";
         }
-    }
-
-    private ProjectGroup getDefaultProjectGroup()
-        throws ContinuumException
-    {
-        try
+        finally
         {
-            return projectGroupDao.getProjectGroupByGroupIdWithProjects( Continuum.DEFAULT_PROJECT_GROUP_GROUP_ID );
-        }
-        catch ( ContinuumObjectNotFoundException e )
-        {
-            throw new ContinuumException( "Continuum is not properly initialized, default project group does not exist",
-                                          e );
-        }
-        catch ( ContinuumStoreException ex )
-        {
-            throw logAndCreateException( "Exception while getting default project group.", ex );
+            if ( resourceAsStream != null )
+            {
+                IOUtil.close( resourceAsStream );
+            }
         }
     }
 
@@ -3081,6 +3201,93 @@
         return buildDefinitionService;
     }
 
+    public ContinuumReleaseResult addContinuumReleaseResult( int projectId, String releaseId, String releaseType )
+        throws ContinuumException
+    {
+        ReleaseResult result;
+        String releaseBy = "";
+
+        if ( getConfiguration().isDistributedBuildEnabled() )
+        {
+            try
+            {
+                result = (ReleaseResult) distributedReleaseManager.getReleaseResult( releaseId );
+                PreparedRelease preparedRelease = distributedReleaseManager.getPreparedRelease( releaseId,
+                                                                                                releaseType );
+                if ( preparedRelease != null )
+                {
+                    releaseBy = preparedRelease.getReleaseBy();
+                }
+            }
+            catch ( ContinuumReleaseException e )
+            {
+                throw new ContinuumException( "Failed to release project: " + projectId, e );
+            }
+            catch ( BuildAgentConfigurationException e )
+            {
+                throw new ContinuumException( "Failed to release project: " + projectId, e );
+            }
+        }
+        else
+        {
+            result = (ReleaseResult) releaseManager.getReleaseResults().get( releaseId );
+            ContinuumReleaseDescriptor descriptor =
+                (ContinuumReleaseDescriptor) releaseManager.getPreparedReleases().get( releaseId );
+            if ( descriptor != null )
+            {
+                releaseBy = descriptor.getReleaseBy();
+            }
+        }
+
+        if ( result != null && getContinuumReleaseResult( projectId, releaseType, result.getStartTime(),
+                                                          result.getEndTime() ) == null )
+        {
+            ContinuumReleaseResult releaseResult = createContinuumReleaseResult( projectId, releaseType, result,
+                                                                                 releaseBy );
+            return addContinuumReleaseResult( releaseResult );
+        }
+
+        return null;
+    }
+
+    private ContinuumReleaseResult createContinuumReleaseResult( int projectId, String releaseGoals,
+                                                                 ReleaseResult result, String releaseBy )
+        throws ContinuumException
+    {
+        ContinuumReleaseResult releaseResult = new ContinuumReleaseResult();
+        releaseResult.setStartTime( result.getStartTime() );
+        releaseResult.setEndTime( result.getEndTime() );
+        releaseResult.setResultCode( result.getResultCode() );
+
+        Project project = getProject( projectId );
+        ProjectGroup projectGroup = project.getProjectGroup();
+        releaseResult.setProjectGroup( projectGroup );
+        releaseResult.setProject( project );
+        releaseResult.setReleaseGoal( releaseGoals );
+        releaseResult.setUsername( releaseBy );
+
+        String releaseName = "releases-" + result.getStartTime();
+
+        try
+        {
+            File logFile = getConfiguration().getReleaseOutputFile( projectGroup.getId(), releaseName );
+
+            PrintWriter writer = new PrintWriter( new FileWriter( logFile ) );
+            writer.write( result.getOutput() );
+            writer.close();
+        }
+        catch ( ConfigurationException e )
+        {
+            throw new ContinuumException( e.getMessage(), e );
+        }
+        catch ( IOException e )
+        {
+            throw new ContinuumException( "Unable to write output to file", e );
+        }
+
+        return releaseResult;
+    }
+
     public ContinuumReleaseResult addContinuumReleaseResult( ContinuumReleaseResult releaseResult )
         throws ContinuumException
     {
@@ -3118,7 +3325,14 @@
 
             if ( releaseFile.exists() )
             {
-                releaseFile.delete();
+                try
+                {
+                    FileUtils.forceDelete( releaseFile );
+                }
+                catch ( IOException e )
+                {
+                    throw new ContinuumException( "Can't delete " + releaseFile.getAbsolutePath(), e );
+                }
             }
         }
         catch ( ConfigurationException e )
@@ -3154,7 +3368,8 @@
         return releaseResultDao.getContinuumReleaseResultsByProjectGroup( projectGroupId );
     }
 
-    public ContinuumReleaseResult getContinuumReleaseResult( int projectId, String releaseGoal, long startTime, long endTime )
+    public ContinuumReleaseResult getContinuumReleaseResult( int projectId, String releaseGoal, long startTime,
+                                                             long endTime )
         throws ContinuumException
     {
         try
@@ -3163,7 +3378,9 @@
         }
         catch ( ContinuumStoreException e )
         {
-            throw new ContinuumException( "Error while retrieving continuumReleaseResult of projectId " + projectId + " with releaseGoal: " + releaseGoal, e);
+            throw new ContinuumException(
+                "Error while retrieving continuumReleaseResult of projectId " + projectId + " with releaseGoal: " +
+                    releaseGoal, e );
         }
     }
 
@@ -3176,7 +3393,8 @@
 
         try
         {
-            return configurationService.getReleaseOutput( projectGroup.getId(), "releases-" + releaseResult.getStartTime() );
+            return configurationService.getReleaseOutput( projectGroup.getId(),
+                                                          "releases-" + releaseResult.getStartTime() );
         }
         catch ( ConfigurationException e )
         {
@@ -3211,12 +3429,12 @@
     {
         Project project = getProject( projectId );
         ProjectGroup group = getProjectGroupByProjectId( projectId );
-        
+
         List<ProjectScmRoot> scmRoots = getProjectScmRootByProjectGroup( group.getId() );
-        
+
         for ( ProjectScmRoot scmRoot : scmRoots )
         {
-            if( project.getScmUrl() != null && project.getScmUrl().startsWith( scmRoot.getScmRootAddress() ) )
+            if ( project.getScmUrl() != null && project.getScmUrl().startsWith( scmRoot.getScmRootAddress() ) )
             {
                 return scmRoot;
             }
@@ -3237,34 +3455,139 @@
         }
     }
 
-    private void prepareBuildProjects( Collection<Project> projects, List<BuildDefinition> bds,
-                                      boolean checkDefaultBuildDefinitionForProject, int trigger )
+    private void removeProjectScmRoot( ProjectScmRoot projectScmRoot )
         throws ContinuumException
     {
+        if ( projectScmRoot == null )
+        {
+            return;
+        }
+
+        //get all projects in the group
+        ProjectGroup group = getProjectGroupWithProjects( projectScmRoot.getProjectGroup().getId() );
+
+        List<Project> projects = group.getProjects();
+
+        boolean found = false;
+        for ( Project project : projects )
+        {
+            if ( project.getScmUrl() != null && project.getScmUrl().startsWith( projectScmRoot.getScmRootAddress() ) )
+            {
+                found = true;
+                break;
+            }
+        }
+
+        if ( !found )
+        {
+            log.info( "Removing project scm root '" + projectScmRoot.getScmRootAddress() + "'" );
+            try
+            {
+                projectScmRootDao.removeProjectScmRoot( projectScmRoot );
+            }
+            catch ( ContinuumStoreException e )
+            {
+                log.error( "Failed to remove project scm root '" + projectScmRoot.getScmRootAddress() + "'", e );
+                throw new ContinuumException(
+                    "Error while removing project scm root '" + projectScmRoot.getScmRootAddress() + "'", e );
+            }
+        }
+        else
+        {
+            log.info(
+                "Project scm root '" + projectScmRoot.getScmRootAddress() + "' still has projects, not removing" );
+        }
+    }
+
+    public BuildQueue addBuildQueue( BuildQueue buildQueue )
+        throws ContinuumException
+    {
+        try
+        {
+            return buildQueueService.addBuildQueue( buildQueue );
+        }
+        catch ( BuildQueueServiceException e )
+        {
+            throw new ContinuumException( "Error adding build queue to the database.", e );
+        }
+    }
+
+    public BuildQueue getBuildQueue( int buildQueueId )
+        throws ContinuumException
+    {
+        try
+        {
+            return buildQueueService.getBuildQueue( buildQueueId );
+        }
+        catch ( BuildQueueServiceException e )
+        {
+            throw new ContinuumException( "Error retrieving build queue.", e );
+        }
+    }
+
+    public BuildQueue getBuildQueueByName( String buildQueueName )
+        throws ContinuumException
+    {
+        try
+        {
+            return buildQueueService.getBuildQueueByName( buildQueueName );
+        }
+        catch ( BuildQueueServiceException e )
+        {
+            throw new ContinuumException( "Error retrieving build queue.", e );
+        }
+    }
+
+    public void removeBuildQueue( BuildQueue buildQueue )
+        throws ContinuumException
+    {
+        try
+        {
+            buildQueueService.removeBuildQueue( buildQueue );
+        }
+        catch ( BuildQueueServiceException e )
+        {
+            throw new ContinuumException( "Error deleting build queue from database.", e );
+        }
+    }
+
+    public BuildQueue storeBuildQueue( BuildQueue buildQueue )
+        throws ContinuumException
+    {
+        try
+        {
+            return buildQueueService.updateBuildQueue( buildQueue );
+        }
+        catch ( BuildQueueServiceException e )
+        {
+            throw new ContinuumException( "Error updating build queue.", e );
+        }
+    }
+
+    public List<BuildQueue> getAllBuildQueues()
+        throws ContinuumException
+    {
+        try
+        {
+            return buildQueueService.getAllBuildQueues();
+        }
+        catch ( BuildQueueServiceException e )
+        {
+            throw new ContinuumException( "Error adding build queue.", e );
+        }
+    }
+
+    private void prepareBuildProjects( Collection<Project> projects, List<BuildDefinition> bds,
+                                       boolean checkDefaultBuildDefinitionForProject, BuildTrigger buildTrigger )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException
+    {
         Map<ProjectScmRoot, Map<Integer, Integer>> map = new HashMap<ProjectScmRoot, Map<Integer, Integer>>();
+        List<ProjectScmRoot> sortedScmRoot = new ArrayList<ProjectScmRoot>();
 
         for ( Project project : projects )
         {
             int projectId = project.getId();
-            
-            try
-            {
-                // check if project already in queue
-                if ( taskQueueManager.isInBuildingQueue( projectId ) || taskQueueManager.getCurrentProjectIdBuilding() == projectId )
-                {
-                    continue;
-                }
-                
-                if ( taskQueueManager.isInCheckoutQueue( projectId ) )
-                {
-                    taskQueueManager.removeProjectFromCheckoutQueue( projectId );
-                }
-            }
-            catch ( TaskQueueManagerException e )
-            {
-                throw new ContinuumException( e.getMessage(), e );
-            }
-            
+
             int buildDefId = -1;
 
             if ( bds != null )
@@ -3300,14 +3623,23 @@
                 {
                     buildDefId = projectDefaultBD.getId();
                     log.debug( "Project " + project.getId() +
-                        " has own default build definition, will use it instead of group's." );
+                                   " has own default build definition, will use it instead of group's." );
                 }
             }
 
             if ( buildDefId == -1 )
             {
                 log.info( "Project " + projectId +
-                    " don't have a default build definition defined in the project or project group, will not be included in group prepare." );
+                              " don't have a default build definition defined in the project or project group, will not be included in group build." );
+                continue;
+            }
+
+            // check if project already in queue
+            if ( !isProjectOkToBuild( projectId, buildDefId ) )
+            {
+                log.info(
+                    "Not queueing the build with projectId={} and buildDefinitionId={} because it is already building",
+                    projectId, buildDefId );
                 continue;
             }
 
@@ -3323,94 +3655,89 @@
             projectsAndBuildDefinitionsMap.put( projectId, buildDefId );
 
             map.put( scmRoot, projectsAndBuildDefinitionsMap );
+
+            if ( !sortedScmRoot.contains( scmRoot ) )
+            {
+                sortedScmRoot.add( scmRoot );
+            }
         }
 
-        prepareBuildProjects( map, trigger );
+        prepareBuildProjects( map, buildTrigger, sortedScmRoot );
     }
 
-    private void prepareBuildProjects( Collection<Project> projects, int buildDefinitionId, int trigger )
-        throws ContinuumException
+    private void prepareBuildProjects( Collection<Project> projects, int buildDefinitionId, BuildTrigger buildTrigger )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException
     {
-        Map<ProjectScmRoot, Map<Integer,Integer>> map = new HashMap<ProjectScmRoot, Map<Integer, Integer>>();
+        Map<ProjectScmRoot, Map<Integer, Integer>> map = new HashMap<ProjectScmRoot, Map<Integer, Integer>>();
+        List<ProjectScmRoot> sortedScmRoot = new ArrayList<ProjectScmRoot>();
 
         for ( Project project : projects )
         {
             int projectId = project.getId();
 
-            try
+            // check if project already in queue
+            if ( !isProjectOkToBuild( projectId, buildDefinitionId ) )
             {
-                // check if project already in queue
-                if ( taskQueueManager.isInBuildingQueue( projectId ) || taskQueueManager.getCurrentProjectIdBuilding() == projectId )
-                {
-                    continue;
-                }
-                
-                if ( taskQueueManager.isInCheckoutQueue( projectId ) )
-                {
-                    taskQueueManager.removeProjectFromCheckoutQueue( projectId );
-                }
-                
-                ProjectScmRoot scmRoot = getProjectScmRootByProject( projectId );
-
-                Map<Integer, Integer> projectsAndBuildDefinitionsMap = map.get( scmRoot );
-                
-                if ( projectsAndBuildDefinitionsMap == null )
-                {
-                    projectsAndBuildDefinitionsMap = new HashMap<Integer, Integer>();
-                }
-                
-                projectsAndBuildDefinitionsMap.put( projectId, buildDefinitionId );
-                
-                map.put( scmRoot, projectsAndBuildDefinitionsMap );
+                log.info(
+                    "Not queueing the build with projectId={} and buildDefinitionId={} because it is already building",
+                    projectId, buildDefinitionId );
+                continue;
             }
-            catch ( TaskQueueManagerException e )
+
+            ProjectScmRoot scmRoot = getProjectScmRootByProject( projectId );
+
+            Map<Integer, Integer> projectsAndBuildDefinitionsMap = map.get( scmRoot );
+
+            if ( projectsAndBuildDefinitionsMap == null )
             {
-                throw new ContinuumException( e.getMessage(), e );
+                projectsAndBuildDefinitionsMap = new HashMap<Integer, Integer>();
+            }
+
+            projectsAndBuildDefinitionsMap.put( projectId, buildDefinitionId );
+
+            map.put( scmRoot, projectsAndBuildDefinitionsMap );
+
+            if ( !sortedScmRoot.contains( scmRoot ) )
+            {
+                sortedScmRoot.add( scmRoot );
             }
         }
 
-        prepareBuildProjects( map, trigger );
+        prepareBuildProjects( map, buildTrigger, sortedScmRoot );
     }
 
-    private void prepareBuildProjects( Map<ProjectScmRoot, Map<Integer, Integer>> map, int trigger )
-        throws ContinuumException
+    private void prepareBuildProjects( Map<ProjectScmRoot, Map<Integer, Integer>> map, BuildTrigger buildTrigger,
+                                       List<ProjectScmRoot> scmRoots )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException
     {
-        for ( ProjectScmRoot scmRoot : map.keySet() )
+        for ( ProjectScmRoot scmRoot : scmRoots )
         {
-            prepareBuildProjects( map.get( scmRoot ), trigger, scmRoot.getScmRootAddress(), 
-                                  scmRoot.getProjectGroup().getId(), scmRoot.getId() );
+            prepareBuildProjects( map.get( scmRoot ), buildTrigger, scmRoot.getScmRootAddress(),
+                                  scmRoot.getProjectGroup().getId(), scmRoot.getId(), scmRoots );
         }
     }
 
-    private void prepareBuildProjects( Map<Integer, Integer> projectsBuildDefinitionsMap, int trigger, 
-                                       String scmRootAddress, int projectGroupId, int scmRootId )
-        throws ContinuumException
+    private void prepareBuildProjects( Map<Integer, Integer> projectsBuildDefinitionsMap, BuildTrigger buildTrigger,
+                                       String scmRootAddress, int projectGroupId, int scmRootId,
+                                       List<ProjectScmRoot> scmRoots )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException
     {
         ProjectGroup group = getProjectGroup( projectGroupId );
-        PrepareBuildProjectsTask task = new PrepareBuildProjectsTask( projectsBuildDefinitionsMap, trigger,
-                                                                      projectGroupId, group.getName(), 
-                                                                      scmRootAddress, scmRootId );
 
         try
         {
             if ( configurationService.isDistributedBuildEnabled() )
             {
-                // check if 
-                if ( !taskQueueManager.isInDistributedBuildQueue( projectGroupId, scmRootAddress ) )
-                {
-                    taskQueueManager.getDistributedBuildQueue().put( task );
-                }
+                distributedBuildManager.prepareBuildProjects( projectsBuildDefinitionsMap, buildTrigger, projectGroupId,
+                                                              group.getName(), scmRootAddress, scmRootId, scmRoots );
             }
             else
             {
-                taskQueueManager.getPrepareBuildQueue().put( task );
+                parallelBuildsManager.prepareBuildProjects( projectsBuildDefinitionsMap, buildTrigger, projectGroupId,
+                                                            group.getName(), scmRootAddress, scmRootId );
             }
         }
-        catch ( TaskQueueManagerException e )
-        {
-            throw logAndCreateException( e.getMessage(), e );
-        }
-        catch ( TaskQueueException e )
+        catch ( BuildManagerException e )
         {
             throw logAndCreateException( "Error while creating enqueuing object.", e );
         }
@@ -3421,34 +3748,51 @@
     {
         List<Project> projectsList;
 
-        try
-        {
-            projectsList = getProjectsInBuildOrder( projectDao.getProjectsWithDependenciesByGroupId( projectGroup.getId() ) );
-        }
-        catch ( CycleDetectedException e )
-        {
-            throw new ContinuumException( "Error while retrieving projects", e );
-        }
+        projectsList = getProjectsInBuildOrder( projectDao.getProjectsWithDependenciesByGroupId(
+            projectGroup.getId() ) );
+
+        List<ProjectScmRoot> scmRoots = getProjectScmRootByProjectGroup( projectGroup.getId() );
 
         String url = "";
 
         for ( Project project : projectsList )
         {
-            if ( !project.getScmUrl().startsWith( url ) )
+            boolean found = false;
+
+            if ( StringUtils.isEmpty( url ) || !project.getScmUrl().startsWith( url ) )
             {
-                // this is a root
+                // this is a root project or the project is part of a flat multi module
                 url = project.getScmUrl();
-                createProjectScmRoot( projectGroup, url );
+                //createProjectScmRoot( projectGroup, url );
+
+                for ( ProjectScmRoot scmRoot : scmRoots )
+                {
+                    if ( url.startsWith( scmRoot.getScmRootAddress() ) )
+                    {
+                        found = true;
+                    }
+                }
+
+                if ( !found )
+                {
+                    createProjectScmRoot( projectGroup, url );
+                }
             }
         }
     }
-    
+
     private ProjectScmRoot createProjectScmRoot( ProjectGroup projectGroup, String url )
         throws ContinuumException
     {
+        if ( StringUtils.isEmpty( url ) )
+        {
+            return null;
+        }
+
         try
         {
-            ProjectScmRoot scmRoot = getProjectScmRootByProjectGroupAndScmRootAddress( projectGroup.getId(), url );
+            ProjectScmRoot scmRoot = projectScmRootDao.getProjectScmRootByProjectGroupAndScmRootAddress(
+                projectGroup.getId(), url );
 
             if ( scmRoot != null )
             {
@@ -3468,4 +3812,174 @@
             throw new ContinuumException( "Error while creating project scm root with scm root address:" + url );
         }
     }
+
+    private void updateProjectScmRoot( ProjectScmRoot oldScmRoot, Project project )
+        throws ContinuumException
+    {
+        try
+        {
+            removeProjectScmRoot( oldScmRoot );
+            ProjectScmRoot scmRoot = projectScmRootDao.getProjectScmRootByProjectGroupAndScmRootAddress(
+                project.getProjectGroup().getId(), project.getScmUrl() );
+            if ( scmRoot == null )
+            {
+                ProjectScmRoot newScmRoot = new ProjectScmRoot();
+                if ( project.getScmUrl().equals( oldScmRoot.getScmRootAddress() ) )
+                {
+                    BeanUtils.copyProperties( oldScmRoot, newScmRoot, new String[]{"id", "projectGroup"} );
+                }
+                else
+                {
+                    newScmRoot.setScmRootAddress( project.getScmUrl() );
+                }
+                newScmRoot.setProjectGroup( project.getProjectGroup() );
+                projectScmRootDao.addProjectScmRoot( newScmRoot );
+            }
+        }
+        catch ( ContinuumStoreException ex )
+        {
+            throw logAndCreateException( "Error while updating project.", ex );
+        }
+    }
+
+    private boolean isProjectInReleaseStage( Project project )
+        throws ContinuumException
+    {
+        String releaseId = project.getGroupId() + ":" + project.getArtifactId();
+        try
+        {
+            return taskQueueManager.isProjectInReleaseStage( releaseId );
+        }
+        catch ( TaskQueueManagerException e )
+        {
+            throw new ContinuumException( "Error occurred while checking if project is currently being released.", e );
+        }
+    }
+
+    private boolean isAnyProjectInGroupInReleaseStage( int projectGroupId )
+        throws ContinuumException
+    {
+        Collection<Project> projects = getProjectsInGroup( projectGroupId );
+        for ( Project project : projects )
+        {
+            if ( isProjectInReleaseStage( project ) )
+            {
+                throw new ContinuumException( "Cannot build project group. Project (id=" + project.getId() +
+                                                  ") in group is currently in release stage." );
+            }
+        }
+        return false;
+    }
+
+    private boolean isAnyProjectsInReleaseStage( List<Project> projects )
+        throws ContinuumException
+    {
+        for ( Project project : projects )
+        {
+            if ( isProjectInReleaseStage( project ) )
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    private Collection<Project> getProjectsNotInReleaseStage( Collection<Project> projectsList )
+        throws ContinuumException
+    {
+        // filter the projects to be built
+        // projects that are in the release stage will not be built
+        Collection<Project> filteredProjectsList = new ArrayList<Project>();
+        for ( Project project : projectsList )
+        {
+            if ( !isProjectInReleaseStage( project ) )
+            {
+                filteredProjectsList.add( project );
+            }
+            else
+            {
+                log.warn(
+                    "Project (id=" + project.getId() + ") will not be built. It is currently in the release stage." );
+            }
+        }
+        return filteredProjectsList;
+    }
+
+    private void checkForDuplicateProjectInGroup( ProjectGroup projectGroup, Project projectToCheck,
+                                                  ContinuumProjectBuildingResult result )
+    {
+        List<Project> projectsInGroup = projectGroup.getProjects();
+
+        if ( projectsInGroup == null )
+        {
+            return;
+        }
+
+        for ( Project project : projectGroup.getProjects() )
+        {
+            // projectToCheck is first in the equals check, as projectToCheck must be a Maven project and will have
+            // non-null values for each. project may be an Ant or Shell project and have null values.
+            if ( projectToCheck.getGroupId().equals( project.getGroupId() ) && projectToCheck.getArtifactId().equals(
+                project.getArtifactId() ) && projectToCheck.getVersion().equals( project.getVersion() ) )
+            {
+                result.addError( ContinuumProjectBuildingResult.ERROR_DUPLICATE_PROJECTS );
+                return;
+            }
+        }
+    }
+
+    private boolean isProjectOkToBuild( int projectId, int buildDefinitionId )
+        throws ContinuumException
+    {
+        if ( configurationService.isDistributedBuildEnabled() )
+        {
+            if ( !distributedBuildManager.isProjectInAnyPrepareBuildQueue( projectId, buildDefinitionId ) &&
+                !distributedBuildManager.isProjectInAnyBuildQueue( projectId, buildDefinitionId ) &&
+                !distributedBuildManager.isProjectCurrentlyPreparingBuild( projectId, buildDefinitionId ) &&
+                !distributedBuildManager.isProjectCurrentlyBuilding( projectId, buildDefinitionId ) )
+            {
+                return true;
+            }
+        }
+        else
+        {
+            try
+            {
+                if ( !parallelBuildsManager.isInAnyBuildQueue( projectId, buildDefinitionId ) &&
+                    !parallelBuildsManager.isInAnyCheckoutQueue( projectId ) &&
+                    !parallelBuildsManager.isInPrepareBuildQueue( projectId ) &&
+                    !parallelBuildsManager.isProjectCurrentlyPreparingBuild( projectId ) )
+                {
+                    if ( parallelBuildsManager.isInAnyCheckoutQueue( projectId ) )
+                    {
+                        parallelBuildsManager.removeProjectFromCheckoutQueue( projectId );
+                    }
+
+                    return true;
+                }
+            }
+            catch ( BuildManagerException e )
+            {
+                throw new ContinuumException( e.getMessage(), e );
+            }
+        }
+
+        return false;
+    }
+
+    void setTaskQueueManager( TaskQueueManager taskQueueManager )
+    {
+        this.taskQueueManager = taskQueueManager;
+    }
+
+    void setProjectDao( ProjectDao projectDao )
+    {
+        this.projectDao = projectDao;
+    }
+
+    public DistributedBuildManager getDistributedBuildManager()
+    {
+        return distributedBuildManager;
+    }
 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/build/settings/DefaultSchedulesActivator.java b/continuum-core/src/main/java/org/apache/maven/continuum/build/settings/DefaultSchedulesActivator.java
index a4ae88b..bf1c0dd 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/build/settings/DefaultSchedulesActivator.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/build/settings/DefaultSchedulesActivator.java
@@ -21,9 +21,11 @@
 
 import org.apache.continuum.dao.BuildDefinitionDao;
 import org.apache.continuum.dao.DirectoryPurgeConfigurationDao;
+import org.apache.continuum.dao.DistributedDirectoryPurgeConfigurationDao;
 import org.apache.continuum.dao.RepositoryPurgeConfigurationDao;
 import org.apache.continuum.dao.ScheduleDao;
 import org.apache.continuum.model.repository.DirectoryPurgeConfiguration;
+import org.apache.continuum.model.repository.DistributedDirectoryPurgeConfiguration;
 import org.apache.continuum.model.repository.RepositoryPurgeConfiguration;
 import org.apache.maven.continuum.Continuum;
 import org.apache.maven.continuum.model.project.BuildDefinition;
@@ -55,7 +57,7 @@
 public class DefaultSchedulesActivator
     implements SchedulesActivator
 {
-    private Logger log = LoggerFactory.getLogger( DefaultSchedulesActivator.class );
+    private static final Logger log = LoggerFactory.getLogger( DefaultSchedulesActivator.class );
 
     /**
      * @plexus.requirement
@@ -70,6 +72,12 @@
     /**
      * @plexus.requirement
      */
+    private DistributedDirectoryPurgeConfigurationDao distributedDirectoryPurgeConfigurationDao;
+
+
+    /**
+     * @plexus.requirement
+     */
     private BuildDefinitionDao buildDefinitionDao;
 
     /**
@@ -82,8 +90,8 @@
      */
     private Scheduler scheduler;
 
-    //private int delay = 3600;
-    private int delay = 1;
+    // private int delay = 3600;
+    private static final int delay = 1;
 
     public void activateSchedules( Continuum continuum )
         throws SchedulesActivationException
@@ -94,42 +102,27 @@
 
         for ( Schedule schedule : schedules )
         {
-            if ( StringUtils.isEmpty( schedule.getCronExpression() ) )
+            if ( schedule.isActive() )
             {
-                // TODO: this can possibly be removed but it's here now to
-                // weed out any bugs
-                log.info( "Not scheduling " + schedule.getName() );
-
-                continue;
-            }
-
-            try
-            {
-                // check schedule job class
-                if ( isScheduleFromBuildJob( schedule ) )
-                {
-                    schedule( schedule, continuum, ContinuumBuildJob.class );
-                }
-
-                if ( isScheduleFromPurgeJob( schedule ) )
-                {
-                    schedule( schedule, continuum, ContinuumPurgeJob.class );
-                }
-            }
-            catch ( SchedulesActivationException e )
-            {
-                log.error( "Can't activate schedule '" + schedule.getName() + "'", e );
-
-                schedule.setActive( false );
-
                 try
                 {
-                    scheduleDao.storeSchedule( schedule );
+                    activateSchedule( schedule, continuum );
                 }
-                catch ( ContinuumStoreException e1 )
+                catch ( SchedulesActivationException e )
                 {
-                    throw new SchedulesActivationException( "Can't desactivate schedule '" + schedule.getName() + "'",
-                                                            e );
+                    log.error( "Can't activate schedule '" + schedule.getName() + "'", e );
+
+                    schedule.setActive( false );
+
+                    try
+                    {
+                        scheduleDao.storeSchedule( schedule );
+                    }
+                    catch ( ContinuumStoreException e1 )
+                    {
+                        throw new SchedulesActivationException(
+                            "Can't desactivate schedule '" + schedule.getName() + "'", e );
+                    }
                 }
             }
         }
@@ -138,16 +131,31 @@
     public void activateSchedule( Schedule schedule, Continuum continuum )
         throws SchedulesActivationException
     {
-        log.info( "Activating schedule " + schedule.getName() );
-
-        if ( isScheduleFromBuildJob( schedule ) )
+        if ( schedule != null )
         {
-            schedule( schedule, continuum, ContinuumBuildJob.class );
+            log.info( "Activating schedule " + schedule.getName() );
+
+            activateBuildSchedule( schedule, continuum );
+
+            activatePurgeSchedule( schedule, continuum );
         }
+    }
 
-        if ( isScheduleFromPurgeJob( schedule ) )
+    public void activateBuildSchedule( Schedule schedule, Continuum continuum )
+        throws SchedulesActivationException
+    {
+        if ( schedule != null && schedule.isActive() && isScheduleFromBuildJob( schedule ) )
         {
-            schedule( schedule, continuum, ContinuumPurgeJob.class );
+            schedule( schedule, continuum, ContinuumBuildJob.class, ContinuumBuildJob.BUILD_GROUP );
+        }
+    }
+
+    public void activatePurgeSchedule( Schedule schedule, Continuum continuum )
+        throws SchedulesActivationException
+    {
+        if ( schedule != null && schedule.isActive() && isScheduleFromPurgeJob( schedule ) )
+        {
+            schedule( schedule, continuum, ContinuumPurgeJob.class, ContinuumPurgeJob.PURGE_GROUP );
         }
     }
 
@@ -156,16 +164,50 @@
     {
         log.info( "Deactivating schedule " + schedule.getName() );
 
-        unschedule( schedule, continuum );
+        unactivateBuildSchedule( schedule );
+        unactivatePurgeSchedule( schedule );
     }
 
-    protected void schedule( Schedule schedule, Continuum continuum, Class jobClass )
+    public void unactivateOrphanBuildSchedule( Schedule schedule )
         throws SchedulesActivationException
     {
-        if ( !schedule.isActive() )
+        if ( schedule != null && !isScheduleFromBuildJob( schedule ) )
         {
-            log.info( "Schedule \"" + schedule.getName() + "\" is disabled." );
+            unactivateBuildSchedule( schedule );
+        }
+    }
 
+    public void unactivateOrphanPurgeSchedule( Schedule schedule )
+        throws SchedulesActivationException
+    {
+        if ( schedule != null && !isScheduleFromPurgeJob( schedule ) )
+        {
+            unactivatePurgeSchedule( schedule );
+        }
+    }
+
+    private void unactivateBuildSchedule( Schedule schedule )
+        throws SchedulesActivationException
+    {
+        log.debug( "Deactivating schedule " + schedule.getName() + " for Build Process" );
+
+        unschedule( schedule, ContinuumBuildJob.BUILD_GROUP );
+    }
+
+    private void unactivatePurgeSchedule( Schedule schedule )
+        throws SchedulesActivationException
+    {
+        log.debug( "Deactivating schedule " + schedule.getName() + " for Purge Process" );
+
+        unschedule( schedule, ContinuumPurgeJob.PURGE_GROUP );
+    }
+
+    protected void schedule( Schedule schedule, Continuum continuum, Class jobClass, String group )
+        throws SchedulesActivationException
+    {
+        if ( StringUtils.isEmpty( schedule.getCronExpression() ) )
+        {
+            log.info( "Not scheduling " + schedule.getName() );
             return;
         }
 
@@ -177,9 +219,9 @@
 
         dataMap.put( ContinuumSchedulerConstants.SCHEDULE, schedule );
 
-        //the name + group makes the job unique
+        // the name + group makes the job unique
 
-        JobDetail jobDetail = new JobDetail( schedule.getName(), org.quartz.Scheduler.DEFAULT_GROUP, jobClass );
+        JobDetail jobDetail = new JobDetail( schedule.getName(), group, jobClass );
 
         jobDetail.setJobDataMap( dataMap );
 
@@ -189,7 +231,7 @@
 
         trigger.setName( schedule.getName() );
 
-        trigger.setGroup( org.quartz.Scheduler.DEFAULT_GROUP );
+        trigger.setGroup( group );
 
         Date startTime = new Date( System.currentTimeMillis() + delay * 1000 );
 
@@ -218,7 +260,7 @@
         }
     }
 
-    protected void unschedule( Schedule schedule, Continuum continuum )
+    private void unschedule( Schedule schedule, String group )
         throws SchedulesActivationException
     {
         try
@@ -227,10 +269,10 @@
             {
                 log.info( "Stopping active schedule \"" + schedule.getName() + "\"." );
 
-                scheduler.interruptSchedule( schedule.getName(), org.quartz.Scheduler.DEFAULT_GROUP );
+                scheduler.interruptSchedule( schedule.getName(), group );
             }
 
-            scheduler.unscheduleJob( schedule.getName(), org.quartz.Scheduler.DEFAULT_GROUP );
+            scheduler.unscheduleJob( schedule.getName(), group );
         }
         catch ( SchedulerException e )
         {
@@ -241,27 +283,24 @@
     private boolean isScheduleFromBuildJob( Schedule schedule )
     {
         List<BuildDefinition> buildDef = buildDefinitionDao.getBuildDefinitionsBySchedule( schedule.getId() );
+        // Take account templateBuildDefinition too.
+        // A improvement will be add schedule only for active buildDefinition, but it would need activate
+        // schedule job in add project and add group process
+        return buildDef.size() > 0;
 
-        if ( buildDef.size() > 0 )
-        {
-            return true;
-        }
-
-        return false;
     }
 
     private boolean isScheduleFromPurgeJob( Schedule schedule )
     {
         List<RepositoryPurgeConfiguration> repoPurgeConfigs =
-            repositoryPurgeConfigurationDao.getRepositoryPurgeConfigurationsBySchedule( schedule.getId() );
+            repositoryPurgeConfigurationDao.getEnableRepositoryPurgeConfigurationsBySchedule( schedule.getId() );
         List<DirectoryPurgeConfiguration> dirPurgeConfigs =
-            directoryPurgeConfigurationDao.getDirectoryPurgeConfigurationsBySchedule( schedule.getId() );
+            directoryPurgeConfigurationDao.getEnableDirectoryPurgeConfigurationsBySchedule( schedule.getId() );
+        List<DistributedDirectoryPurgeConfiguration> distriDirPurgeConfigs =
+            distributedDirectoryPurgeConfigurationDao.getEnableDistributedDirectoryPurgeConfigurationsBySchedule(
+                schedule.getId() );
 
-        if ( repoPurgeConfigs.size() > 0 || dirPurgeConfigs.size() > 0 )
-        {
-            return true;
-        }
+        return repoPurgeConfigs.size() > 0 || dirPurgeConfigs.size() > 0 || distriDirPurgeConfigs.size() > 0;
 
-        return false;
     }
 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/buildcontroller/BuildContext.java b/continuum-core/src/main/java/org/apache/maven/continuum/buildcontroller/BuildContext.java
index 4a9ef64..f5875c7 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/buildcontroller/BuildContext.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/buildcontroller/BuildContext.java
@@ -19,6 +19,7 @@
  * under the License.
  */
 
+import org.apache.continuum.utils.build.BuildTrigger;
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.BuildResult;
 import org.apache.maven.continuum.model.project.Project;
@@ -51,7 +52,7 @@
 
     private ScmResult scmResult;
 
-    private int trigger;
+    private BuildTrigger buildTrigger;
 
     private BuildResult buildResult;
 
@@ -138,14 +139,14 @@
         return actionContext;
     }
 
-    public int getTrigger()
+    public BuildTrigger getBuildTrigger()
     {
-        return trigger;
+        return buildTrigger;
     }
 
-    public void setTrigger( int trigger )
+    public void setBuildTrigger( BuildTrigger buildTrigger )
     {
-        this.trigger = trigger;
+        this.buildTrigger = buildTrigger;
     }
 
     public List<ProjectDependency> getModifiedDependencies()
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/buildcontroller/BuildController.java b/continuum-core/src/main/java/org/apache/maven/continuum/buildcontroller/BuildController.java
index 5d4add7..7383172 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/buildcontroller/BuildController.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/buildcontroller/BuildController.java
@@ -19,6 +19,8 @@
  * under the License.
  */
 
+import org.apache.continuum.utils.build.BuildTrigger;
+import org.apache.maven.continuum.model.scm.ScmResult;
 import org.codehaus.plexus.taskqueue.execution.TaskExecutionException;
 
 /**
@@ -29,6 +31,6 @@
 {
     String ROLE = BuildController.class.getName();
 
-    void build( int projectId, int buildDefinitionId, int trigger )
+    void build( int projectId, int buildDefinitionId, BuildTrigger buildTrigger, ScmResult scmResult )
         throws TaskExecutionException;
 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/buildcontroller/BuildProjectTaskExecutor.java b/continuum-core/src/main/java/org/apache/maven/continuum/buildcontroller/BuildProjectTaskExecutor.java
index 6dd9c4d..ad39517 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/buildcontroller/BuildProjectTaskExecutor.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/buildcontroller/BuildProjectTaskExecutor.java
@@ -45,7 +45,7 @@
     {
         BuildProjectTask buildProjectTask = (BuildProjectTask) task;
 
-        controller.build( buildProjectTask.getProjectId(), buildProjectTask.getBuildDefinitionId(), buildProjectTask
-            .getTrigger() );
+        controller.build( buildProjectTask.getProjectId(), buildProjectTask.getBuildDefinitionId(),
+                          buildProjectTask.getBuildTrigger(), buildProjectTask.getScmResult() );
     }
 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/buildcontroller/DefaultBuildController.java b/continuum-core/src/main/java/org/apache/maven/continuum/buildcontroller/DefaultBuildController.java
index 5c94bba..3b48815 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/buildcontroller/DefaultBuildController.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/buildcontroller/DefaultBuildController.java
@@ -26,7 +26,9 @@
 import org.apache.continuum.dao.ProjectScmRootDao;
 import org.apache.continuum.model.project.ProjectScmRoot;
 import org.apache.continuum.utils.ContinuumUtils;
+import org.apache.continuum.utils.build.BuildTrigger;
 import org.apache.maven.continuum.core.action.AbstractContinuumAction;
+import org.apache.maven.continuum.core.action.ExecuteBuilderContinuumAction;
 import org.apache.maven.continuum.execution.ContinuumBuildExecutor;
 import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
 import org.apache.maven.continuum.execution.manager.BuildExecutorManager;
@@ -34,8 +36,10 @@
 import org.apache.maven.continuum.model.project.BuildResult;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.project.ProjectDependency;
+import org.apache.maven.continuum.model.project.ProjectGroup;
 import org.apache.maven.continuum.model.scm.ChangeFile;
 import org.apache.maven.continuum.model.scm.ChangeSet;
+import org.apache.maven.continuum.model.scm.ScmResult;
 import org.apache.maven.continuum.notification.ContinuumNotificationDispatcher;
 import org.apache.maven.continuum.project.ContinuumProjectState;
 import org.apache.maven.continuum.store.ContinuumObjectNotFoundException;
@@ -62,7 +66,7 @@
 public class DefaultBuildController
     implements BuildController
 {
-    private Logger log = LoggerFactory.getLogger( DefaultBuildController.class );
+    private static final Logger log = LoggerFactory.getLogger( DefaultBuildController.class );
 
     /**
      * @plexus.requirement
@@ -78,12 +82,12 @@
      * @plexus.requirement
      */
     private ProjectDao projectDao;
-    
+
     /**
      * @plexus.requirement
      */
     private ProjectGroupDao projectGroupDao;
-    
+
     /**
      * @plexus.requirement
      */
@@ -116,14 +120,15 @@
     /**
      * @param projectId
      * @param buildDefinitionId
-     * @param trigger
+     * @param buildTrigger
+     * @param scmResult
      * @throws TaskExecutionException
      */
-    public void build( int projectId, int buildDefinitionId, int trigger )
+    public void build( int projectId, int buildDefinitionId, BuildTrigger buildTrigger, ScmResult scmResult )
         throws TaskExecutionException
     {
         log.info( "Initializing build" );
-        BuildContext context = initializeBuildContext( projectId, buildDefinitionId, trigger );
+        BuildContext context = initializeBuildContext( projectId, buildDefinitionId, buildTrigger, scmResult );
 
         // ignore this if AlwaysBuild ?
         if ( !checkScmResult( context ) )
@@ -131,7 +136,7 @@
             log.info( "Error updating from SCM, not building" );
             return;
         }
-        
+
         log.info( "Starting build of " + context.getProject().getName() );
         startBuild( context );
 
@@ -144,7 +149,7 @@
                 return;
             }
 
-            Map actionContext = context.getActionContext();
+            Map<String, Object> actionContext = context.getActionContext();
 
             try
             {
@@ -162,9 +167,9 @@
 
             performAction( "deploy-artifact", context );
 
-            context.setCancelled( (Boolean) actionContext.get( AbstractContinuumAction.KEY_CANCELLED ) );
+            context.setCancelled( ExecuteBuilderContinuumAction.isCancelled( actionContext ) );
 
-            String s = (String) actionContext.get( AbstractContinuumAction.KEY_BUILD_ID );
+            String s = AbstractContinuumAction.getBuildId( actionContext, null );
 
             if ( s != null && !context.isCancelled() )
             {
@@ -212,19 +217,14 @@
             {
                 try
                 {
-                    String s = (String) context.getActionContext().get( AbstractContinuumAction.KEY_BUILD_ID );
+                    String s = AbstractContinuumAction.getBuildId( context.getActionContext(), null );
 
                     if ( s != null )
                     {
                         BuildResult buildResult = buildResultDao.getBuildResult( Integer.valueOf( s ) );
                         project.setState( buildResult.getState() );
+                        projectDao.updateProject( project );
                     }
-                    else
-                    {
-                        project.setState( ContinuumProjectState.ERROR );
-                    }
-
-                    projectDao.updateProject( project );
                 }
                 catch ( ContinuumStoreException e )
                 {
@@ -284,6 +284,11 @@
 
     private void updateBuildResult( BuildResult build, BuildContext context )
     {
+        if ( build.getScmResult() == null && context.getScmResult() != null )
+        {
+            build.setScmResult( context.getScmResult() );
+        }
+
         if ( build.getModifiedDependencies() == null && context.getModifiedDependencies() != null )
         {
             build.setModifiedDependencies( context.getModifiedDependencies() );
@@ -318,36 +323,80 @@
      *
      * @param projectId
      * @param buildDefinitionId
-     * @param trigger
+     * @param buildTrigger
+     * @param scmResult
      * @return
      * @throws TaskExecutionException
      */
-    protected BuildContext initializeBuildContext( int projectId, int buildDefinitionId, int trigger )
+    @SuppressWarnings( "unchecked" )
+    protected BuildContext initializeBuildContext( int projectId, int buildDefinitionId, BuildTrigger buildTrigger,
+                                                   ScmResult scmResult )
         throws TaskExecutionException
     {
         BuildContext context = new BuildContext();
 
         context.setStartTime( System.currentTimeMillis() );
 
-        context.setTrigger( trigger );
+        Map actionContext = context.getActionContext();
 
         try
         {
-            Project project = projectDao.getProjectWithScmDetails( projectId );
+            Project project = projectDao.getProject( projectId );
 
             context.setProject( project );
 
             BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
 
+            BuildTrigger newBuildTrigger = buildTrigger;
+
+            if ( newBuildTrigger.getTrigger() == ContinuumProjectState.TRIGGER_SCHEDULED )
+            {
+                newBuildTrigger.setTriggeredBy( buildDefinition.getSchedule().getName() );
+            }
+
+            context.setBuildTrigger( newBuildTrigger );
+
             context.setBuildDefinition( buildDefinition );
 
-            BuildResult oldBuildResult =
-                buildResultDao.getLatestBuildResultForBuildDefinition( projectId, buildDefinitionId );
+            BuildResult oldBuildResult = buildResultDao.getLatestBuildResultForBuildDefinition( projectId,
+                                                                                                buildDefinitionId );
 
             context.setOldBuildResult( oldBuildResult );
 
-		    context.setScmResult( project.getScmResult() );
-		    
+            context.setScmResult( scmResult );
+
+            // CONTINUUM-2193
+            ProjectGroup projectGroup = project.getProjectGroup();
+            List<ProjectScmRoot> scmRoots = projectScmRootDao.getProjectScmRootByProjectGroup( projectGroup.getId() );
+            String projectScmUrl = project.getScmUrl();
+            String projectScmRootAddress = "";
+
+            for ( ProjectScmRoot projectScmRoot : scmRoots )
+            {
+                projectScmRootAddress = projectScmRoot.getScmRootAddress();
+                if ( projectScmUrl.startsWith( projectScmRoot.getScmRootAddress() ) )
+                {
+                    AbstractContinuumAction.setProjectScmRootUrl( actionContext, projectScmRoot.getScmRootAddress() );
+                    break;
+                }
+            }
+
+            if ( project.isCheckedOutInSingleDirectory() )
+            {
+                List<Project> projectsInGroup = projectGroupDao.getProjectGroupWithProjects(
+                    projectGroup.getId() ).getProjects();
+                List<Project> projectsWithCommonScmRoot = new ArrayList<Project>();
+                for ( Project projectInGroup : projectsInGroup )
+                {
+                    if ( projectInGroup.getScmUrl().startsWith( projectScmRootAddress ) )
+                    {
+                        projectsWithCommonScmRoot.add( projectInGroup );
+                    }
+                }
+                AbstractContinuumAction.setListOfProjectsInGroupWithCommonScmRoot( actionContext,
+                                                                                   projectsWithCommonScmRoot );
+            }
+
             // CONTINUUM-1871 olamy if continuum is killed during building oldBuildResult will have a endTime 0
             // this means all changes since the project has been loaded in continuum will be in memory
             // now we will load all BuildResult with an Id bigger or equals than the oldBuildResult one
@@ -362,23 +411,23 @@
             throw new TaskExecutionException( "Error initializing the build context", e );
         }
 
-        Map actionContext = context.getActionContext();
+        // Map<String, Object> actionContext = context.getActionContext();
 
-        actionContext.put( AbstractContinuumAction.KEY_PROJECT_ID, projectId );
+        AbstractContinuumAction.setProjectId( actionContext, projectId );
 
-        actionContext.put( AbstractContinuumAction.KEY_PROJECT, context.getProject() );
+        AbstractContinuumAction.setProject( actionContext, context.getProject() );
 
-        actionContext.put( AbstractContinuumAction.KEY_BUILD_DEFINITION_ID, buildDefinitionId );
+        AbstractContinuumAction.setBuildDefinitionId( actionContext, buildDefinitionId );
 
-        actionContext.put( AbstractContinuumAction.KEY_BUILD_DEFINITION, context.getBuildDefinition() );
+        AbstractContinuumAction.setBuildDefinition( actionContext, context.getBuildDefinition() );
 
-        actionContext.put( AbstractContinuumAction.KEY_TRIGGER, trigger );
+        AbstractContinuumAction.setBuildTrigger( actionContext, buildTrigger );
 
-        actionContext.put( AbstractContinuumAction.KEY_FIRST_RUN, context.getOldBuildResult() == null );
+        AbstractContinuumAction.setScmResult( actionContext, context.getScmResult() );
 
         if ( context.getOldBuildResult() != null )
         {
-            actionContext.put( AbstractContinuumAction.KEY_OLD_BUILD_ID, context.getOldBuildResult().getId() );
+            AbstractContinuumAction.setOldBuildId( actionContext, context.getOldBuildResult().getId() );
         }
 
         return context;
@@ -387,8 +436,8 @@
     private void performAction( String actionName, BuildContext context )
         throws TaskExecutionException
     {
-        String error = null;
-        TaskExecutionException exception = null;
+        String error;
+        TaskExecutionException exception;
 
         try
         {
@@ -442,11 +491,6 @@
         throws TaskExecutionException
     {
         BuildDefinition buildDefinition = context.getBuildDefinition();
-        if ( buildDefinition.isBuildFresh() )
-        {
-            log.info( "FreshBuild configured, building" );
-            return true;
-        }
         if ( buildDefinition.isAlwaysBuild() )
         {
             log.info( "AlwaysBuild configured, building" );
@@ -454,7 +498,7 @@
         }
         if ( context.getOldBuildResult() == null )
         {
-            log.info( "The project was never be built with the current build definition, building" );
+            log.info( "The project has never been built with the current build definition, building" );
             return true;
         }
 
@@ -468,7 +512,7 @@
             return true;
         }
 
-        if ( context.getTrigger() == ContinuumProjectState.TRIGGER_FORCED )
+        if ( context.getBuildTrigger().getTrigger() == ContinuumProjectState.TRIGGER_FORCED )
         {
             log.info( "The project build is forced, building" );
             return true;
@@ -480,15 +524,18 @@
 
         if ( project.getOldState() != ContinuumProjectState.NEW &&
             project.getOldState() != ContinuumProjectState.CHECKEDOUT &&
-            context.getTrigger() != ContinuumProjectState.TRIGGER_FORCED &&
+            context.getBuildTrigger().getTrigger() != ContinuumProjectState.TRIGGER_FORCED &&
             project.getState() != ContinuumProjectState.NEW && project.getState() != ContinuumProjectState.CHECKEDOUT )
         {
             // Check SCM changes
-            allChangesUnknown = checkAllChangesUnknown( context.getScmResult().getChanges() );
+            if ( context.getScmResult() != null )
+            {
+                allChangesUnknown = checkAllChangesUnknown( context.getScmResult().getChanges() );
+            }
 
             if ( allChangesUnknown )
             {
-                if ( !context.getScmResult().getChanges().isEmpty() )
+                if ( context.getScmResult() != null && !context.getScmResult().getChanges().isEmpty() )
                 {
                     log.info(
                         "The project was not built because all changes are unknown (maybe local modifications or ignored files not defined in your SCM tool." );
@@ -509,15 +556,33 @@
         }
 
         // Check changes
-        if ( !shouldBuild && ( ( !allChangesUnknown && !context.getScmResult().getChanges().isEmpty() ) ||
-            project.getExecutorId().equals( ContinuumBuildExecutorConstants.MAVEN_TWO_BUILD_EXECUTOR ) ) )
+        if ( !shouldBuild && ( ( !allChangesUnknown && context.getScmResult() != null &&
+            !context.getScmResult().getChanges().isEmpty() ) || project.getExecutorId().equals(
+            ContinuumBuildExecutorConstants.MAVEN_TWO_BUILD_EXECUTOR ) ) )
         {
             try
             {
                 ContinuumBuildExecutor executor = buildExecutorManager.getBuildExecutor( project.getExecutorId() );
-                shouldBuild = executor.shouldBuild( context.getScmResult().getChanges(), project,
-                                                    workingDirectoryService.getWorkingDirectory( project ),
-                                                    context.getBuildDefinition() );
+
+                Map<String, Object> actionContext = context.getActionContext();
+                List<Project> projectsWithCommonScmRoot =
+                    AbstractContinuumAction.getListOfProjectsInGroupWithCommonScmRoot( actionContext );
+                String projectScmRootUrl = AbstractContinuumAction.getProjectScmRootUrl( actionContext,
+                                                                                         project.getScmUrl() );
+
+                if ( executor == null )
+                {
+                    log.warn( "No continuum build executor found for project " + project.getId() +
+                                  " with executor '" + project.getExecutorId() + "'" );
+                }
+                else if ( context.getScmResult() != null )
+                {
+                    shouldBuild = executor.shouldBuild( context.getScmResult().getChanges(), project,
+                                                        workingDirectoryService.getWorkingDirectory( project,
+                                                                                                     projectScmRootUrl,
+                                                                                                     projectsWithCommonScmRoot ),
+                                                        context.getBuildDefinition() );
+                }
             }
             catch ( Exception e )
             {
@@ -599,7 +664,7 @@
 
         try
         {
-            Project project = projectDao.getProjectWithAllDetails( context.getProject().getId() );
+            Project project = projectDao.getProjectWithDependencies( context.getProject().getId() );
             List<ProjectDependency> dependencies = project.getDependencies();
 
             if ( dependencies == null )
@@ -621,34 +686,34 @@
 
             for ( ProjectDependency dep : dependencies )
             {
-                Project dependencyProject =
-                    projectDao.getProject( dep.getGroupId(), dep.getArtifactId(), dep.getVersion() );
+                Project dependencyProject = projectDao.getProject( dep.getGroupId(), dep.getArtifactId(),
+                                                                   dep.getVersion() );
 
                 if ( dependencyProject != null )
                 {
-                    List buildResults = buildResultDao.getBuildResultsInSuccessForProject( dependencyProject.getId(),
-                                                                                           context.getOldBuildResult().getEndTime() );
-                    if ( buildResults != null && !buildResults.isEmpty() )
+                    long nbBuild = buildResultDao.getNbBuildResultsInSuccessForProject( dependencyProject.getId(),
+                                                                                        context.getOldBuildResult().getEndTime() );
+                    if ( nbBuild > 0 )
                     {
                         log.debug( "Dependency changed: " + dep.getGroupId() + ":" + dep.getArtifactId() + ":" +
-                            dep.getVersion() );
+                                       dep.getVersion() );
                         modifiedDependencies.add( dep );
                     }
                     else
                     {
-                        log.debug( "Dependency not changed: " + dep.getGroupId() + ":" + dep.getArtifactId() +
-                            ":" + dep.getVersion() );
+                        log.debug( "Dependency not changed: " + dep.getGroupId() + ":" + dep.getArtifactId() + ":" +
+                                       dep.getVersion() );
                     }
                 }
                 else
                 {
-                    log.debug( "Skip non Continuum project: " + dep.getGroupId() + ":" + dep.getArtifactId() +
-                        ":" + dep.getVersion() );
+                    log.debug( "Skip non Continuum project: " + dep.getGroupId() + ":" + dep.getArtifactId() + ":" +
+                                   dep.getVersion() );
                 }
             }
 
             context.setModifiedDependencies( modifiedDependencies );
-            context.getActionContext().put( AbstractContinuumAction.KEY_UPDATE_DEPENDENCIES, modifiedDependencies );
+            AbstractContinuumAction.setUpdatedDependencies( context.getActionContext(), modifiedDependencies );
         }
         catch ( ContinuumStoreException e )
         {
@@ -670,7 +735,9 @@
 
         build.setState( ContinuumProjectState.ERROR );
 
-        build.setTrigger( context.getTrigger() );
+        build.setTrigger( context.getBuildTrigger().getTrigger() );
+
+        build.setUsername( context.getBuildTrigger().getTriggeredBy() );
 
         build.setStartTime( context.getStartTime() );
 
@@ -678,6 +745,8 @@
 
         updateBuildResult( build, context );
 
+        build.setScmResult( context.getScmResult() );
+
         build.setBuildDefinition( context.getBuildDefinition() );
 
         if ( error != null )
@@ -732,5 +801,4 @@
 
         return false;
     }
-
 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/builddefinition/DefaultBuildDefinitionService.java b/continuum-core/src/main/java/org/apache/maven/continuum/builddefinition/DefaultBuildDefinitionService.java
index aeba189..0cda6a1 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/builddefinition/DefaultBuildDefinitionService.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/builddefinition/DefaultBuildDefinitionService.java
@@ -1,3 +1,5 @@
+package org.apache.maven.continuum.builddefinition;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,8 +18,8 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.continuum.builddefinition;
 
+import org.apache.continuum.buildqueue.BuildQueueServiceException;
 import org.apache.continuum.configuration.ContinuumConfigurationException;
 import org.apache.continuum.dao.BuildDefinitionDao;
 import org.apache.continuum.dao.BuildDefinitionTemplateDao;
@@ -39,7 +41,6 @@
 import org.slf4j.LoggerFactory;
 
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
 
 /**
@@ -52,7 +53,7 @@
 public class DefaultBuildDefinitionService
     implements BuildDefinitionService, Initializable
 {
-    private Logger log = LoggerFactory.getLogger( DefaultBuildDefinitionService.class );
+    private static final Logger log = LoggerFactory.getLogger( DefaultBuildDefinitionService.class );
 
     /**
      * @plexus.configuration default-value=""
@@ -195,6 +196,7 @@
             storedBuildDefinition.setProfile( buildDefinition.getProfile() );
             storedBuildDefinition.setSchedule( buildDefinition.getSchedule() );
             storedBuildDefinition.setType( buildDefinition.getType() );
+            storedBuildDefinition.setUpdatePolicy( buildDefinition.getUpdatePolicy() );
             buildDefinitionDao.storeBuildDefinition( storedBuildDefinition );
         }
         catch ( ContinuumStoreException e )
@@ -248,9 +250,35 @@
         cloned.setSchedule( buildDefinition.getSchedule() );
         cloned.setType( buildDefinition.getType() );
         cloned.setTemplate( buildDefinition.isTemplate() );
+        cloned.setUpdatePolicy( buildDefinition.getUpdatePolicy() );
         return cloned;
     }
 
+    public boolean isBuildDefinitionInUse( BuildDefinition buildDefinition )
+        throws BuildDefinitionServiceException
+    {
+        boolean inUse = false;
+        List<BuildDefinitionTemplate> buildDefinitionTemplates = getAllBuildDefinitionTemplate();
+
+        for ( BuildDefinitionTemplate template : buildDefinitionTemplates )
+        {
+            for ( BuildDefinition definition : (List<BuildDefinition>) template.getBuildDefinitions() )
+            {
+                if ( buildDefinition.getId() == definition.getId() )
+                {
+                    inUse = true;
+                    break;
+                }
+            }
+
+            if ( inUse )
+            {
+                break;
+            }
+        }
+
+        return inUse;
+    }
 
     public BuildDefinitionTemplate getContinuumDefaultWithType( String type )
         throws BuildDefinitionServiceException
@@ -268,8 +296,8 @@
     public BuildDefinitionTemplate getDefaultAntBuildDefinitionTemplate()
         throws BuildDefinitionServiceException
     {
-        BuildDefinitionTemplate template =
-            getContinuumDefaultWithType( ContinuumBuildExecutorConstants.ANT_BUILD_EXECUTOR );
+        BuildDefinitionTemplate template = getContinuumDefaultWithType(
+            ContinuumBuildExecutorConstants.ANT_BUILD_EXECUTOR );
         if ( template != null )
         {
             return template;
@@ -305,8 +333,8 @@
     public BuildDefinitionTemplate getDefaultMavenOneBuildDefinitionTemplate()
         throws BuildDefinitionServiceException
     {
-        BuildDefinitionTemplate template =
-            getContinuumDefaultWithType( ContinuumBuildExecutorConstants.MAVEN_ONE_BUILD_EXECUTOR );
+        BuildDefinitionTemplate template = getContinuumDefaultWithType(
+            ContinuumBuildExecutorConstants.MAVEN_ONE_BUILD_EXECUTOR );
         if ( template != null )
         {
             log.debug( "found default maven template " + template.getType() );
@@ -344,8 +372,8 @@
     public BuildDefinitionTemplate getDefaultMavenTwoBuildDefinitionTemplate()
         throws BuildDefinitionServiceException
     {
-        BuildDefinitionTemplate template =
-            getContinuumDefaultWithType( ContinuumBuildExecutorConstants.MAVEN_TWO_BUILD_EXECUTOR );
+        BuildDefinitionTemplate template = getContinuumDefaultWithType(
+            ContinuumBuildExecutorConstants.MAVEN_TWO_BUILD_EXECUTOR );
         if ( template != null )
         {
             return template;
@@ -353,7 +381,7 @@
         log.info( "create default MavenTwoBuildDefinitionTemplate" );
         template = new BuildDefinitionTemplate();
         template.setContinuumDefault( true );
-        template.setName( "Default Maven 2 Template" );
+        template.setName( "Default Maven Template" );
         template.setType( ContinuumBuildExecutorConstants.MAVEN_TWO_BUILD_EXECUTOR );
 
         template = addBuildDefinitionTemplate( template );
@@ -372,7 +400,7 @@
 
         bd.setType( ContinuumBuildExecutorConstants.MAVEN_TWO_BUILD_EXECUTOR );
 
-        bd.setDescription( "Default Maven 2 Build Definition" );
+        bd.setDescription( "Default Maven Build Definition" );
 
         bd.setTemplate( true );
 
@@ -382,8 +410,8 @@
     public BuildDefinitionTemplate getDefaultShellBuildDefinitionTemplate()
         throws BuildDefinitionServiceException
     {
-        BuildDefinitionTemplate template =
-            getContinuumDefaultWithType( ContinuumBuildExecutorConstants.SHELL_BUILD_EXECUTOR );
+        BuildDefinitionTemplate template = getContinuumDefaultWithType(
+            ContinuumBuildExecutorConstants.SHELL_BUILD_EXECUTOR );
         if ( template != null )
         {
             return template;
@@ -430,6 +458,10 @@
         {
             throw new BuildDefinitionServiceException( e.getMessage(), e );
         }
+        catch ( BuildQueueServiceException e )
+        {
+            throw new BuildDefinitionServiceException( e.getMessage(), e );
+        }
     }
 
     // ------------------------------------------------------
@@ -470,8 +502,8 @@
             // first remove links to buildDefs
             // TODO in the same db transaction ?
             buildDefinitionTemplate.setBuildDefinitions( null );
-            buildDefinitionTemplate =
-                buildDefinitionTemplateDao.updateBuildDefinitionTemplate( buildDefinitionTemplate );
+            buildDefinitionTemplate = buildDefinitionTemplateDao.updateBuildDefinitionTemplate(
+                buildDefinitionTemplate );
             buildDefinitionTemplateDao.removeBuildDefinitionTemplate( buildDefinitionTemplate );
         }
         catch ( ContinuumStoreException e )
@@ -485,15 +517,20 @@
     {
         try
         {
-            BuildDefinitionTemplate stored = getBuildDefinitionTemplate( buildDefinitionTemplate.getId() );
-            stored.setName( buildDefinitionTemplate.getName() );
-            stored.setBuildDefinitions( buildDefinitionTemplate.getBuildDefinitions() );
-            return buildDefinitionTemplateDao.updateBuildDefinitionTemplate( stored );
+            if ( !hasDuplicateTemplateName( buildDefinitionTemplate ) )
+            {
+                BuildDefinitionTemplate stored = getBuildDefinitionTemplate( buildDefinitionTemplate.getId() );
+                stored.setName( buildDefinitionTemplate.getName() );
+                stored.setBuildDefinitions( buildDefinitionTemplate.getBuildDefinitions() );
+                return buildDefinitionTemplateDao.updateBuildDefinitionTemplate( stored );
+            }
         }
         catch ( ContinuumStoreException e )
         {
             throw new BuildDefinitionServiceException( e.getMessage(), e );
         }
+
+        return null;
     }
 
     public BuildDefinitionTemplate addBuildDefinitionTemplate( BuildDefinitionTemplate buildDefinitionTemplate )
@@ -501,12 +538,17 @@
     {
         try
         {
-            return buildDefinitionTemplateDao.addBuildDefinitionTemplate( buildDefinitionTemplate );
+            if ( !hasDuplicateTemplateName( buildDefinitionTemplate ) )
+            {
+                return buildDefinitionTemplateDao.addBuildDefinitionTemplate( buildDefinitionTemplate );
+            }
         }
         catch ( ContinuumStoreException e )
         {
             throw new BuildDefinitionServiceException( e.getMessage(), e );
         }
+
+        return null;
     }
 
     public BuildDefinitionTemplate addBuildDefinitionInTemplate( BuildDefinitionTemplate buildDefinitionTemplate,
@@ -571,10 +613,9 @@
                 return;
             }
             project = projectDao.getProjectWithBuildDetails( project.getId() );
-            List<BuildDefinition> buildDefs = new ArrayList<BuildDefinition>();
-            for ( Iterator<BuildDefinition> iterator = template.getBuildDefinitions().iterator(); iterator.hasNext(); )
+
+            for ( BuildDefinition bd : (List<BuildDefinition>) template.getBuildDefinitions() )
             {
-                BuildDefinition bd = iterator.next();
                 bd = cloneBuildDefinition( bd );
                 bd.setTemplate( false );
                 bd = buildDefinitionDao.addBuildDefinition( bd );
@@ -594,16 +635,16 @@
     {
         try
         {
-            ProjectGroup projectGroup =
-                projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId( projectGroupId );
+            ProjectGroup projectGroup = projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId(
+                projectGroupId );
             if ( template.getBuildDefinitions().isEmpty() )
             {
                 return null;
             }
-            List<BuildDefinition> buildDefs = new ArrayList<BuildDefinition>();
-            for ( Iterator<BuildDefinition> iterator = template.getBuildDefinitions().iterator(); iterator.hasNext(); )
+
+            for ( BuildDefinition bd : (List<BuildDefinition>) template.getBuildDefinitions() )
             {
-                BuildDefinition bd = iterator.next();
+                bd.setTemplate( false );
                 bd = buildDefinitionDao.addBuildDefinition( cloneBuildDefinition( bd ) );
                 projectGroup.addBuildDefinition( bd );
             }
@@ -642,4 +683,23 @@
             throw new BuildDefinitionServiceException( e.getMessage(), e );
         }
     }
+
+    private boolean hasDuplicateTemplateName( BuildDefinitionTemplate buildDefinitionTemplate )
+        throws BuildDefinitionServiceException
+    {
+        boolean isDuplicate = false;
+        List<BuildDefinitionTemplate> allBuildDefinitionTemplate = this.getAllBuildDefinitionTemplate();
+
+        for ( BuildDefinitionTemplate template : allBuildDefinitionTemplate )
+        {
+            String name = buildDefinitionTemplate.getName();
+            if ( ( template.getId() != buildDefinitionTemplate.getId() ) && ( template.getName().equals( name ) ) )
+            {
+                isDuplicate = true;
+                break;
+            }
+        }
+        return isDuplicate;
+    }
+
 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/buildqueue/evaluator/BuildProjectTaskViabilityEvaluator.java b/continuum-core/src/main/java/org/apache/maven/continuum/buildqueue/evaluator/BuildProjectTaskViabilityEvaluator.java
index fd48ae0..46aba3c 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/buildqueue/evaluator/BuildProjectTaskViabilityEvaluator.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/buildqueue/evaluator/BuildProjectTaskViabilityEvaluator.java
@@ -26,7 +26,6 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
@@ -71,9 +70,9 @@
 
         for ( BuildProjectTask task : (Collection<BuildProjectTask>) tasks )
         {
-            Integer key = new Integer( task.getProjectId() );
+            int key = task.getProjectId();
 
-            List<BuildProjectTask> projectTasks = (List<BuildProjectTask>) projects.get( key );
+            List<BuildProjectTask> projectTasks = projects.get( key );
 
             if ( projectTasks == null )
             {
@@ -87,9 +86,9 @@
 
         List<BuildProjectTask> toBeRemoved = new ArrayList<BuildProjectTask>();
 
-        for ( Iterator it = projects.values().iterator(); it.hasNext(); )
+        for ( List<BuildProjectTask> projectTasks : projects.values() )
         {
-            toBeRemoved.addAll( checkTasks( (List) it.next() ) );
+            toBeRemoved.addAll( checkTasks( projectTasks ) );
         }
 
         return toBeRemoved;
@@ -118,7 +117,7 @@
                 // If this build is forces, don't remove it
                 // ----------------------------------------------------------------------
 
-                if ( task.getTrigger() == ContinuumProjectState.TRIGGER_FORCED )
+                if ( task.getBuildTrigger().getTrigger() == ContinuumProjectState.TRIGGER_FORCED )
                 {
                     continue;
                 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/AbstractBuildDefinitionContinuumAction.java b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/AbstractBuildDefinitionContinuumAction.java
index 23fb49c..88f8d53 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/AbstractBuildDefinitionContinuumAction.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/AbstractBuildDefinitionContinuumAction.java
@@ -59,8 +59,8 @@
             // if buildDefinition passed in is not default then we are done
             if ( buildDefinition.isDefaultForProject() )
             {
-                BuildDefinition storedDefinition =
-                    buildDefinitionDao.getDefaultBuildDefinitionForProject( project.getId() );
+                BuildDefinition storedDefinition = buildDefinitionDao.getDefaultBuildDefinitionForProject(
+                    project.getId() );
 
                 if ( storedDefinition != null )
                 {
@@ -73,7 +73,7 @@
         catch ( ContinuumObjectNotFoundException nfe )
         {
             getLogger().debug( getClass().getName() +
-                ": safely ignoring the resetting of old build definition becuase it didn't exist" );
+                                   ": safely ignoring the resetting of old build definition becuase it didn't exist" );
         }
         catch ( ContinuumStoreException cse )
         {
@@ -99,8 +99,8 @@
     {
         try
         {
-            List<BuildDefinition> storedDefinitions =
-                buildDefinitionDao.getDefaultBuildDefinitionsForProjectGroup( projectGroup.getId() );
+            List<BuildDefinition> storedDefinitions = buildDefinitionDao.getDefaultBuildDefinitionsForProjectGroup(
+                projectGroup.getId() );
 
             for ( BuildDefinition storedDefinition : storedDefinitions )
             {
@@ -109,8 +109,8 @@
                 {
                     if ( storedDefinition != null && storedDefinition.getId() != buildDefinition.getId() )
                     {
-                        if ( buildDefinition.getType() != null &&
-                            buildDefinition.getType().equals( storedDefinition.getType() ) )
+                        if ( buildDefinition.getType() != null && buildDefinition.getType().equals(
+                            storedDefinition.getType() ) )
                         {
                             //Required to get build def from store because storedDefinition is readonly
                             BuildDefinition def = buildDefinitionDao.getBuildDefinition( storedDefinition.getId() );
@@ -148,8 +148,8 @@
      * @param buildDefinition
      * @throws ContinuumException
      */
-    protected BuildDefinition updateBuildDefinitionInList( List<BuildDefinition> buildDefinitions,
-                                                           BuildDefinition buildDefinition )
+    protected void updateBuildDefinitionInList( List<BuildDefinition> buildDefinitions,
+                                                BuildDefinition buildDefinition )
         throws ContinuumException
     {
         try
@@ -170,6 +170,7 @@
                 storedDefinition.setArguments( buildDefinition.getArguments() );
                 storedDefinition.setBuildFile( buildDefinition.getBuildFile() );
                 storedDefinition.setBuildFresh( buildDefinition.isBuildFresh() );
+                storedDefinition.setUpdatePolicy( buildDefinition.getUpdatePolicy() );
 
                 // special case of this is resolved in the resolveDefaultBuildDefinitionsForProjectGroup method
                 storedDefinition.setDefaultForProject( buildDefinition.isDefaultForProject() );
@@ -202,8 +203,6 @@
                 storedDefinition.setAlwaysBuild( buildDefinition.isAlwaysBuild() );
 
                 buildDefinitionDao.storeBuildDefinition( storedDefinition );
-
-                return storedDefinition;
             }
             else
             {
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/AbstractContinuumAction.java b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/AbstractContinuumAction.java
index 90d0bc6..37d6e59 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/AbstractContinuumAction.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/AbstractContinuumAction.java
@@ -20,15 +20,17 @@
  */
 
 import org.apache.continuum.model.project.ProjectScmRoot;
+import org.apache.continuum.utils.build.BuildTrigger;
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.BuildDefinitionTemplate;
 import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.project.ProjectDependency;
 import org.apache.maven.continuum.model.project.ProjectGroup;
 import org.apache.maven.continuum.model.scm.ScmResult;
 import org.codehaus.plexus.action.AbstractAction;
-import org.codehaus.plexus.util.StringUtils;
 
 import java.io.File;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
@@ -43,223 +45,350 @@
     // Keys for the values that can be in the context
     // ----------------------------------------------------------------------
 
-    public static final String KEY_PROJECT_ID = "project-id";
+    private static final String KEY_PROJECT_ID = "project-id";
 
-    public static final String KEY_PROJECT = "project";
+    private static final String KEY_PROJECT = "project";
 
-    public static final String KEY_BUILD_DEFINITION_TEMPLATE = "build-definition-template";
+    private static final String KEY_PROJECTS = "projects";
 
-    public static final String KEY_BUILD_DEFINITION = "build-definition";
+    private static final String KEY_PROJECTS_BUILD_DEFINITIONS_MAP = "projects-build-definitions";
 
-    public static final String KEY_BUILD_DEFINITION_ID = "build-definition-id";
+    private static final String KEY_BUILD_DEFINITION_TEMPLATE = "build-definition-template";
 
-    public static final String KEY_UNVALIDATED_PROJECT = "unvalidated-project";
+    private static final String KEY_BUILD_DEFINITION = "build-definition";
 
-    public static final String KEY_PROJECT_GROUP_ID = "project-group-id";
+    private static final String KEY_BUILD_DEFINITION_ID = "build-definition-id";
 
-    public static final String KEY_UNVALIDATED_PROJECT_GROUP = "unvalidated-project-group";
+    private static final String KEY_UNVALIDATED_PROJECT = "unvalidated-project";
 
-    public static final String KEY_BUILD_ID = "build-id";
+    private static final String KEY_PROJECT_GROUP_ID = "project-group-id";
 
-    public static final String KEY_WORKING_DIRECTORY = "working-directory";
+    private static final String KEY_UNVALIDATED_PROJECT_GROUP = "unvalidated-project-group";
 
-    public static final String KEY_WORKING_DIRECTORY_EXISTS = "working-directory-exists";
+    private static final String KEY_BUILD_ID = "build-id";
 
-    public static final String KEY_CHECKOUT_SCM_RESULT = "checkout-result";
+    private static final String KEY_WORKING_DIRECTORY = "working-directory";
 
-    public static final String KEY_UPDATE_SCM_RESULT = "update-result";
+    private static final String KEY_UPDATE_DEPENDENCIES = "update-dependencies";
 
-    public static final String KEY_UPDATE_DEPENDENCIES = "update-dependencies";
+    private static final String KEY_BUILD_TRIGGER = "buildTrigger";
 
-    public static final String KEY_TRIGGER = "trigger";
+    private static final String KEY_SCM_RESULT = "scmResult";
 
-    public static final String KEY_FIRST_RUN = "first-run";
+    private static final String KEY_OLD_SCM_RESULT = "old-scmResult";
 
-    public static final String KEY_PROJECT_RELATIVE_PATH = "project-relative-path";
-    
-    public static final String KEY_SCM_USE_CREDENTIALS_CACHE = "useCredentialsCache";
-    
-    public static final String KEY_SCM_USERNAME = "scmUserName";
-    
-    public static final String KEY_SCM_PASSWORD = "scmUserPassword";
+    private static final String KEY_PROJECT_SCM_ROOT = "projectScmRoot";
 
-    public static final String KEY_SCM_RESULT = "scmResult";
+    /**
+     * SCM root url. Used in these actions add-project-to-checkout-queue, checkout-project, clean-working-directory,
+     * create-projects-from-metadata, update-project-from-working-directory,
+     * update-working-directory-from-scm
+     */
+    private static final String KEY_PROJECT_SCM_ROOT_URL = "projectScmRootUrl";
 
-    public static final String KEY_OLD_SCM_RESULT = "old-scmResult";
+    /**
+     * List of projects in a project group with a common scm root url.
+     */
+    private static final String KEY_PROJECTS_IN_GROUP_WITH_COMMON_SCM_ROOT = "projects-in-group-with-common-scm-root";
 
-    public static final String KEY_PROJECT_SCM_ROOT = "projectScmRoot";
+    private static final String KEY_OLD_BUILD_ID = "old-buildResult-id";
 
-    public static final String KEY_OLD_BUILD_ID = "old-buildResult-id";
+    private static final String KEY_SCM_RESULT_MAP = "scm-result-map";
 
-    public static final String KEY_CANCELLED = "cancelled";
-
-    // ----------------------------------------------------------------------
-    // Utils
-    // ----------------------------------------------------------------------
-
-    protected String nullIfEmpty( String string )
-    {
-        if ( StringUtils.isEmpty( string ) )
-        {
-            return null;
-        }
-
-        return string;
-    }
+    private static final String KEY_ROOT_DIRECTORY = "root-directory";
 
     // ----------------------------------------------------------------------
     //
     // ----------------------------------------------------------------------
 
-    public static int getProjectId( Map context )
+    public static int getProjectId( Map<String, Object> context )
     {
         return getInteger( context, KEY_PROJECT_ID );
     }
 
-    public static Project getProject( Map context )
+    public static void setProjectId( Map<String, Object> context, int projectId )
+    {
+        context.put( KEY_PROJECT_ID, projectId );
+    }
+
+    public static Project getProject( Map<String, Object> context )
     {
         return (Project) getObject( context, KEY_PROJECT );
     }
 
-    public static int getProjectGroupId( Map context )
+    public static Project getProject( Map<String, Object> context, Project defaultValue )
+    {
+        return (Project) getObject( context, KEY_PROJECT, defaultValue );
+    }
+
+    public static void setProject( Map<String, Object> context, Project p )
+    {
+        context.put( KEY_PROJECT, p );
+    }
+
+    public static int getProjectGroupId( Map<String, Object> context )
     {
         return getInteger( context, KEY_PROJECT_GROUP_ID );
     }
 
-    public static BuildDefinitionTemplate getBuildDefinitionTemplate( Map context )
+    public static void setProjectGroupId( Map<String, Object> context, int projectGroupId )
+    {
+        context.put( KEY_PROJECT_GROUP_ID, projectGroupId );
+    }
+
+    public static BuildDefinitionTemplate getBuildDefinitionTemplate( Map<String, Object> context )
     {
         return (BuildDefinitionTemplate) getObject( context, KEY_BUILD_DEFINITION_TEMPLATE, null );
     }
 
-    public static BuildDefinition getBuildDefinition( Map context )
+    public static void setBuildDefinitionTemplate( Map<String, Object> context, BuildDefinitionTemplate bdt )
+    {
+        context.put( KEY_BUILD_DEFINITION_TEMPLATE, bdt );
+    }
+
+    public static BuildDefinition getBuildDefinition( Map<String, Object> context )
     {
         return (BuildDefinition) getObject( context, KEY_BUILD_DEFINITION, null );
     }
 
-    public static int getBuildDefinitionId( Map context )
+    public static void setBuildDefinition( Map<String, Object> context, BuildDefinition bd )
+    {
+        context.put( KEY_BUILD_DEFINITION, bd );
+    }
+
+    public static int getBuildDefinitionId( Map<String, Object> context )
     {
         return getInteger( context, KEY_BUILD_DEFINITION_ID );
     }
 
-    public static String getBuildId( Map context )
+    public static void setBuildDefinitionId( Map<String, Object> context, int buildDefintionId )
+    {
+        context.put( KEY_BUILD_DEFINITION_ID, buildDefintionId );
+    }
+
+    public static String getBuildId( Map<String, Object> context )
     {
         return getString( context, KEY_BUILD_ID );
     }
 
-    public static int getTrigger( Map context )
+    public static String getBuildId( Map<String, Object> context, String defaultValue )
     {
-        return getInteger( context, KEY_TRIGGER );
+        return getString( context, KEY_BUILD_ID, defaultValue );
     }
 
-    public static Project getUnvalidatedProject( Map context )
+    public static void setBuildId( Map<String, Object> context, String buildId )
+    {
+        context.put( KEY_BUILD_ID, buildId );
+    }
+
+    public static BuildTrigger getBuildTrigger( Map<String, Object> context )
+    {
+        BuildTrigger defaultValue = new BuildTrigger( 0, "" );
+        return (BuildTrigger) getObject( context, KEY_BUILD_TRIGGER, defaultValue );
+    }
+
+    public static void setBuildTrigger( Map<String, Object> context, BuildTrigger buildTrigger )
+    {
+        context.put( KEY_BUILD_TRIGGER, buildTrigger );
+    }
+
+    public static Project getUnvalidatedProject( Map<String, Object> context )
     {
         return (Project) getObject( context, KEY_UNVALIDATED_PROJECT );
     }
 
-    public static ProjectGroup getUnvalidatedProjectGroup( Map context )
+    public static void setUnvalidatedProject( Map<String, Object> context, Project p )
+    {
+        context.put( KEY_UNVALIDATED_PROJECT, p );
+    }
+
+    public static ProjectGroup getUnvalidatedProjectGroup( Map<String, Object> context )
     {
         return (ProjectGroup) getObject( context, KEY_UNVALIDATED_PROJECT_GROUP );
     }
 
-    public static File getWorkingDirectory( Map context )
+    public static void setUnvalidatedProjectGroup( Map<String, Object> context, ProjectGroup pg )
+    {
+        context.put( KEY_UNVALIDATED_PROJECT_GROUP, pg );
+    }
+
+    public static File getWorkingDirectory( Map<String, Object> context )
     {
         return new File( getString( context, KEY_WORKING_DIRECTORY ) );
     }
 
-    public static ScmResult getCheckoutResult( Map context, Object defaultValue )
+    public static void setWorkingDirectory( Map<String, Object> context, String workingDirectory )
     {
-        return (ScmResult) getObject( context, KEY_CHECKOUT_SCM_RESULT, defaultValue );
+        context.put( KEY_WORKING_DIRECTORY, workingDirectory );
     }
 
-    public static ScmResult getUpdateScmResult( Map context )
-    {
-        return (ScmResult) getObject( context, KEY_UPDATE_SCM_RESULT );
-    }
-
-    public static ScmResult getUpdateScmResult( Map context, ScmResult defaultValue )
-    {
-        return (ScmResult) getObject( context, KEY_UPDATE_SCM_RESULT, defaultValue );
-    }
-
-    public static List getUpdatedDependencies( Map context )
+    public static List<ProjectDependency> getUpdatedDependencies( Map<String, Object> context )
     {
         return getUpdatedDependencies( context, null );
     }
 
-    public static List getUpdatedDependencies( Map context, List defaultValue )
+    public static List<ProjectDependency> getUpdatedDependencies( Map<String, Object> context,
+                                                                  List<ProjectDependency> defaultValue )
     {
-        return (List) getObject( context, KEY_UPDATE_DEPENDENCIES, defaultValue );
+        return (List<ProjectDependency>) getObject( context, KEY_UPDATE_DEPENDENCIES, defaultValue );
     }
 
-    public static ScmResult getScmResult( Map context )
+    public static void setUpdatedDependencies( Map<String, Object> context, List<ProjectDependency> dependencies )
     {
-        return (ScmResult) getObject( context, KEY_SCM_RESULT );
+        context.put( KEY_UPDATE_DEPENDENCIES, dependencies );
     }
 
-    public static ScmResult getScmResult( Map context, ScmResult defaultValue )
+    public static ScmResult getScmResult( Map<String, Object> context )
+    {
+        return getScmResult( context, null );
+    }
+
+    public static ScmResult getScmResult( Map<String, Object> context, ScmResult defaultValue )
     {
         return (ScmResult) getObject( context, KEY_SCM_RESULT, defaultValue );
     }
 
-    public static ScmResult getOldScmResult( Map context )
+    public static void setScmResult( Map<String, Object> context, ScmResult scmResult )
     {
-        return (ScmResult) getObject( context, KEY_OLD_SCM_RESULT );
+        context.put( KEY_SCM_RESULT, scmResult );
     }
 
-    public static ScmResult getOldScmResult( Map context, ScmResult defaultValue )
+    public static ScmResult getOldScmResult( Map<String, Object> context )
+    {
+        return getOldScmResult( context, null );
+    }
+
+    public static ScmResult getOldScmResult( Map<String, Object> context, ScmResult defaultValue )
     {
         return (ScmResult) getObject( context, KEY_OLD_SCM_RESULT, defaultValue );
     }
 
-    public static ProjectScmRoot getProjectScmRoot( Map context )
+    public static void setOldScmResult( Map<String, Object> context, ScmResult oldScmResult )
+    {
+        context.put( KEY_OLD_SCM_RESULT, oldScmResult );
+    }
+
+    public static ProjectScmRoot getProjectScmRoot( Map<String, Object> context )
     {
         return (ProjectScmRoot) getObject( context, KEY_PROJECT_SCM_ROOT );
     }
 
-    public static int getOldBuildId( Map context )
+    public static void setProjectScmRoot( Map<String, Object> context, ProjectScmRoot projectScmRoot )
     {
-        return getInteger( context, KEY_OLD_BUILD_ID ); 
+        context.put( KEY_PROJECT_SCM_ROOT, projectScmRoot );
+    }
+
+    public static int getOldBuildId( Map<String, Object> context )
+    {
+        return getInteger( context, KEY_OLD_BUILD_ID );
+    }
+
+    public static void setOldBuildId( Map<String, Object> context, int oldBuildId )
+    {
+        context.put( KEY_OLD_BUILD_ID, oldBuildId );
+    }
+
+    public static List<Project> getListOfProjects( Map<String, Object> context )
+    {
+        return (List<Project>) getObject( context, KEY_PROJECTS );
+    }
+
+    public static void setListOfProjects( Map<String, Object> context, List<Project> projects )
+    {
+        context.put( KEY_PROJECTS, projects );
+    }
+
+    public static List<Project> getListOfProjectsInGroupWithCommonScmRoot( Map<String, Object> context )
+    {
+        return (List<Project>) getObject( context, KEY_PROJECTS_IN_GROUP_WITH_COMMON_SCM_ROOT,
+                                          new ArrayList<Integer>() );
+    }
+
+    public static void setListOfProjectsInGroupWithCommonScmRoot( Map<String, Object> context, List<Project> projects )
+    {
+        context.put( KEY_PROJECTS_IN_GROUP_WITH_COMMON_SCM_ROOT, projects );
+    }
+
+    public static Map<Integer, BuildDefinition> getProjectsBuildDefinitionsMap( Map<String, Object> context )
+    {
+        return (Map<Integer, BuildDefinition>) getObject( context, KEY_PROJECTS_BUILD_DEFINITIONS_MAP );
+    }
+
+    public static void setProjectsBuildDefinitionsMap( Map<String, Object> context,
+                                                       Map<Integer, BuildDefinition> projectsBuildDefinitionsMap )
+    {
+        context.put( KEY_PROJECTS_BUILD_DEFINITIONS_MAP, projectsBuildDefinitionsMap );
+    }
+
+    public static Map<Integer, ScmResult> getScmResultMap( Map<String, Object> context )
+    {
+        return (Map<Integer, ScmResult>) getObject( context, KEY_SCM_RESULT_MAP );
+    }
+
+    public static void setScmResultMap( Map<String, Object> context, Map<Integer, ScmResult> scmResultMap )
+    {
+        context.put( KEY_SCM_RESULT_MAP, scmResultMap );
+    }
+
+    public static boolean isRootDirectory( Map<String, Object> context )
+    {
+        return getBoolean( context, KEY_ROOT_DIRECTORY, true );
+    }
+
+    public static void setRootDirectory( Map<String, Object> context, boolean isRootDirectory )
+    {
+        context.put( KEY_ROOT_DIRECTORY, isRootDirectory );
+    }
+
+    public static String getProjectScmRootUrl( Map<String, Object> context, String projectScmRootUrl )
+    {
+        return getString( context, KEY_PROJECT_SCM_ROOT_URL, projectScmRootUrl );
+    }
+
+    public static void setProjectScmRootUrl( Map<String, Object> context, String projectScmRootUrl )
+    {
+        context.put( KEY_PROJECT_SCM_ROOT_URL, projectScmRootUrl );
     }
 
     // ----------------------------------------------------------------------
     //
     // ----------------------------------------------------------------------
 
-    protected static String getString( Map context, String key )
+    public static String getString( Map<String, Object> context, String key )
     {
         return (String) getObject( context, key );
     }
 
-    protected static String getString( Map context, String key, String defaultValue )
+    public static String getString( Map<String, Object> context, String key, String defaultValue )
     {
         return (String) getObject( context, key, defaultValue );
     }
 
-    public static boolean getBoolean( Map context, String key )
+    public static boolean getBoolean( Map<String, Object> context, String key )
     {
-        return ( (Boolean) getObject( context, key ) ).booleanValue();
+        return (Boolean) getObject( context, key );
     }
-    
-    public static boolean getBoolean( Map context, String key, boolean defaultValue )
-    {
-        return ( (Boolean) getObject( context, key, Boolean.valueOf( defaultValue ) ) ).booleanValue();
-    }    
 
-    protected static int getInteger( Map context, String key )
+    public static boolean getBoolean( Map<String, Object> context, String key, boolean defaultValue )
+    {
+        return (Boolean) getObject( context, key, defaultValue );
+    }
+
+    protected static int getInteger( Map<String, Object> context, String key )
     {
         Object obj = getObject( context, key, null );
-        
+
         if ( obj == null )
         {
             return 0;
         }
         else
         {
-            return ( (Integer) obj ).intValue();
+            return (Integer) obj;
         }
     }
 
-    protected static Object getObject( Map context, String key )
+    protected static Object getObject( Map<String, Object> context, String key )
     {
         if ( !context.containsKey( key ) )
         {
@@ -276,7 +405,7 @@
         return value;
     }
 
-    protected static Object getObject( Map context, String key, Object defaultValue )
+    protected static Object getObject( Map<String, Object> context, String key, Object defaultValue )
     {
         Object value = context.get( key );
 
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/AddBuildDefinitionToProjectAction.java b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/AddBuildDefinitionToProjectAction.java
index 2d42a7b..20210cf 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/AddBuildDefinitionToProjectAction.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/AddBuildDefinitionToProjectAction.java
@@ -1,18 +1,22 @@
 package org.apache.maven.continuum.core.action;
 
 /*
- * 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.
+ * 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 org.apache.continuum.dao.ProjectDao;
@@ -20,7 +24,7 @@
 import org.apache.maven.continuum.model.project.BuildDefinitionTemplate;
 import org.apache.maven.continuum.model.project.Project;
 
-import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -39,41 +43,39 @@
      */
     private ProjectDao projectDao;
 
-    public void execute( Map map )
+    public void execute( Map context )
         throws Exception
     {
-        int projectId = getProjectId( map );
+        int projectId = getProjectId( context );
         Project project = projectDao.getProjectWithAllDetails( projectId );
 
-        BuildDefinitionTemplate buildDefinitionTemplate = getBuildDefinitionTemplate( map );
+        BuildDefinitionTemplate buildDefinitionTemplate = getBuildDefinitionTemplate( context );
 
         if ( buildDefinitionTemplate != null )
         {
-            for ( Iterator<BuildDefinition> iterator = buildDefinitionTemplate.getBuildDefinitions().iterator();
-                  iterator.hasNext(); )
+            for ( BuildDefinition buildDefinition : (List<BuildDefinition>) buildDefinitionTemplate.getBuildDefinitions() )
             {
-                BuildDefinition buildDefinition = iterator.next();
                 resolveDefaultBuildDefinitionsForProject( buildDefinition, project );
 
                 project.addBuildDefinition( buildDefinition );
 
-                projectDao.updateProject( project );
                 if ( buildDefinition.isDefaultForProject() )
                 {
-                    map.put( AbstractContinuumAction.KEY_BUILD_DEFINITION, buildDefinition );
+                    AbstractContinuumAction.setBuildDefinition( context, buildDefinition );
                 }
             }
         }
         else
         {
-            BuildDefinition buildDefinition = getBuildDefinition( map );
+            BuildDefinition buildDefinition = getBuildDefinition( context );
             resolveDefaultBuildDefinitionsForProject( buildDefinition, project );
 
             project.addBuildDefinition( buildDefinition );
 
-            projectDao.updateProject( project );
-            map.put( AbstractContinuumAction.KEY_BUILD_DEFINITION, buildDefinition );
+            AbstractContinuumAction.setBuildDefinition( context, buildDefinition );
         }
 
+        // Save the project
+        projectDao.updateProject( project );
     }
 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/AddBuildDefinitionToProjectGroupAction.java b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/AddBuildDefinitionToProjectGroupAction.java
index a45b1b8..2923220 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/AddBuildDefinitionToProjectGroupAction.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/AddBuildDefinitionToProjectGroupAction.java
@@ -24,7 +24,7 @@
 import org.apache.maven.continuum.model.project.BuildDefinitionTemplate;
 import org.apache.maven.continuum.model.project.ProjectGroup;
 
-import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -44,35 +44,33 @@
     private ProjectGroupDao projectGroupDao;
 
 
-    public void execute( Map map )
+    public void execute( Map context )
         throws Exception
     {
-        int projectGroupId = getProjectGroupId( map );
+        int projectGroupId = getProjectGroupId( context );
         ProjectGroup projectGroup = projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId( projectGroupId );
-        BuildDefinitionTemplate buildDefinitionTemplate = getBuildDefinitionTemplate( map );
+        BuildDefinitionTemplate buildDefinitionTemplate = getBuildDefinitionTemplate( context );
         if ( buildDefinitionTemplate != null )
         {
-            for ( Iterator<BuildDefinition> iterator = buildDefinitionTemplate.getBuildDefinitions().iterator();
-                  iterator.hasNext(); )
+            for ( BuildDefinition buildDefinition : (List<BuildDefinition>) buildDefinitionTemplate.getBuildDefinitions() )
             {
-                BuildDefinition buildDefinition = iterator.next();
                 resolveDefaultBuildDefinitionsForProjectGroup( buildDefinition, projectGroup );
 
                 projectGroup.addBuildDefinition( buildDefinition );
-
-                projectGroupDao.updateProjectGroup( projectGroup );
             }
         }
         else
         {
-            BuildDefinition buildDefinition = getBuildDefinition( map );
+            BuildDefinition buildDefinition = getBuildDefinition( context );
 
             resolveDefaultBuildDefinitionsForProjectGroup( buildDefinition, projectGroup );
 
             projectGroup.addBuildDefinition( buildDefinition );
-
-            projectGroupDao.updateProjectGroup( projectGroup );
         }
+
+        // Save the project group
+        projectGroupDao.updateProjectGroup( projectGroup );
+
         //map.put( AbstractContinuumAction.KEY_BUILD_DEFINITION, buildDefinition );
     }
 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/AddProjectToCheckOutQueueAction.java b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/AddProjectToCheckOutQueueAction.java
index aa849e6..43ad6ab 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/AddProjectToCheckOutQueueAction.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/AddProjectToCheckOutQueueAction.java
@@ -19,9 +19,10 @@
  * under the License.
  */
 
+import org.apache.commons.lang.StringUtils;
+import org.apache.continuum.buildmanager.BuildsManager;
 import org.apache.continuum.dao.ProjectDao;
-import org.apache.continuum.taskqueue.CheckOutTask;
-import org.apache.continuum.taskqueue.manager.TaskQueueManager;
+import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.utils.WorkingDirectoryService;
 
@@ -47,24 +48,39 @@
     private ProjectDao projectDao;
 
     /**
-     * @plexus.requirement
+     * @plexus.requirement role-hint="parallel"
      */
-    private TaskQueueManager taskQueueManager;
-    
-    @SuppressWarnings("unchecked")
+    private BuildsManager parallelBuildsManager;
+
+    @SuppressWarnings( "unchecked" )
     public void execute( Map context )
         throws Exception
     {
-
-        Project project = (Project) getObject( context, KEY_PROJECT, null );
+        Project project = getProject( context, null );
         if ( project == null )
         {
             project = projectDao.getProject( getProjectId( context ) );
         }
 
-        CheckOutTask checkOutTask = new CheckOutTask( project.getId(), workingDirectoryService
-            .getWorkingDirectory( project ), project.getName(), project.getScmUsername(), project.getScmPassword() );
+        String scmUsername = project.getScmUsername();
+        String scmPassword = project.getScmPassword();
 
-        taskQueueManager.getCheckoutQueue().put( checkOutTask );
+        if ( scmUsername == null || StringUtils.isEmpty( scmUsername ) )
+        {
+            scmUsername = CheckoutProjectContinuumAction.getScmUsername( context, null );
+        }
+
+        if ( scmPassword == null || StringUtils.isEmpty( scmPassword ) )
+        {
+            scmPassword = CheckoutProjectContinuumAction.getScmPassword( context, null );
+        }
+
+        String scmRootUrl = getProjectScmRootUrl( context, null );
+
+        BuildDefinition defaultBuildDefinition = getBuildDefinition( context );
+        parallelBuildsManager.checkoutProject( project.getId(), project.getName(),
+                                               workingDirectoryService.getWorkingDirectory( project ), scmRootUrl,
+                                               scmUsername, scmPassword, defaultBuildDefinition,
+                                               getListOfProjectsInGroupWithCommonScmRoot( context ) );
     }
 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/CheckWorkingDirectoryAction.java b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/CheckWorkingDirectoryAction.java
index 8884988..64f6b84 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/CheckWorkingDirectoryAction.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/CheckWorkingDirectoryAction.java
@@ -20,10 +20,12 @@
  */
 
 import org.apache.continuum.dao.ProjectDao;
+import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.utils.WorkingDirectoryService;
 
 import java.io.File;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -45,22 +47,46 @@
      */
     private ProjectDao projectDao;
 
+    private static final String KEY_WORKING_DIRECTORY_EXISTS = "working-directory-exists";
+
     public void execute( Map context )
         throws Exception
     {
         Project project = projectDao.getProject( getProjectId( context ) );
+        List<Project> projectsWithCommonScmRoot = getListOfProjectsInGroupWithCommonScmRoot( context );
+        String projectScmRootUrl = getProjectScmRootUrl( context, project.getScmUrl() );
 
-        File workingDirectory = workingDirectoryService.getWorkingDirectory( project );
+        File workingDirectory = workingDirectoryService.getWorkingDirectory( project, projectScmRootUrl,
+                                                                             projectsWithCommonScmRoot );
 
         if ( !workingDirectory.exists() )
         {
-            context.put( KEY_WORKING_DIRECTORY_EXISTS, Boolean.FALSE );
+            setWorkingDirectoryExists( context, false );
 
             return;
         }
 
         File[] files = workingDirectory.listFiles();
 
-        context.put( KEY_WORKING_DIRECTORY_EXISTS, Boolean.valueOf( files.length > 0 ) );
+        if ( files == null )
+        {
+            //workingDirectory isn't a directory but a file. Not possible in theory.
+            String msg = workingDirectory.getAbsolutePath() + " isn't a directory but a file.";
+            getLogger().error( msg );
+            throw new ContinuumException( msg );
+        }
+
+        setWorkingDirectoryExists( context, files.length > 0 );
     }
+
+    public static boolean isWorkingDirectoryExists( Map<String, Object> context )
+    {
+        return getBoolean( context, KEY_WORKING_DIRECTORY_EXISTS, false );
+    }
+
+    public static void setWorkingDirectoryExists( Map<String, Object> context, boolean isWorkingDirectoryExists )
+    {
+        context.put( KEY_WORKING_DIRECTORY_EXISTS, isWorkingDirectoryExists );
+    }
+
 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/CheckoutProjectContinuumAction.java b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/CheckoutProjectContinuumAction.java
index 3cb36fd..68b79fe 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/CheckoutProjectContinuumAction.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/CheckoutProjectContinuumAction.java
@@ -23,13 +23,13 @@
 import org.apache.continuum.dao.ProjectDao;
 import org.apache.continuum.scm.ContinuumScm;
 import org.apache.continuum.scm.ContinuumScmConfiguration;
+import org.apache.continuum.scm.ContinuumScmUtils;
 import org.apache.continuum.utils.ContinuumUtils;
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.scm.ScmResult;
 import org.apache.maven.continuum.notification.ContinuumNotificationDispatcher;
 import org.apache.maven.continuum.project.ContinuumProjectState;
-import org.apache.maven.continuum.store.ContinuumObjectNotFoundException;
 import org.apache.maven.continuum.store.ContinuumStoreException;
 import org.apache.maven.scm.ScmException;
 import org.apache.maven.scm.command.checkout.CheckOutScmResult;
@@ -50,6 +50,14 @@
 public class CheckoutProjectContinuumAction
     extends AbstractContinuumAction
 {
+    private static final String KEY_SCM_USERNAME = "scmUserName";
+
+    private static final String KEY_SCM_PASSWORD = "scmUserPassword";
+
+    private static final String KEY_PROJECT_RELATIVE_PATH = "project-relative-path";
+
+    private static final String KEY_CHECKOUT_SCM_RESULT = "checkout-result";
+
     /**
      * @plexus.requirement
      */
@@ -71,7 +79,7 @@
     private ProjectDao projectDao;
 
     public void execute( Map context )
-        throws ContinuumObjectNotFoundException, ContinuumStoreException
+        throws ContinuumStoreException
     {
         Project project = projectDao.getProject( getProject( context ).getId() );
 
@@ -82,6 +90,8 @@
             buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinition.getId() );
         }
 
+        int originalState = project.getState();
+
         project.setState( ContinuumProjectState.CHECKING_OUT );
 
         projectDao.updateProject( project );
@@ -94,22 +104,27 @@
 
         ScmResult result;
 
+        List<Project> projectsWithCommonScmRoot = getListOfProjectsInGroupWithCommonScmRoot( context );
+
         try
         {
-            String scmUserName = getString( context, KEY_SCM_USERNAME, "" );
-            String scmPassword = getString( context, KEY_SCM_PASSWORD, "" );
-            ContinuumScmConfiguration config =
-                createScmConfiguration( project, workingDirectory, scmUserName, scmPassword );
+            String scmUserName = getScmUsername( context, project.getScmUsername() );
+            String scmPassword = getScmPassword( context, project.getScmPassword() );
+            String scmRootUrl = getProjectScmRootUrl( context, project.getScmUrl() );
+
+            ContinuumScmConfiguration config = createScmConfiguration( project, workingDirectory, scmUserName,
+                                                                       scmPassword, scmRootUrl, isRootDirectory(
+                context ) );
 
             String tag = config.getTag();
-            getLogger().info( "Checking out project: '" + project.getName() + "', id: '" + project.getId() + "' " +
-                "to '" + workingDirectory + "'" + ( tag != null ? " with branch/tag " + tag + "." : "." ) );
+            getLogger().info(
+                "Checking out project: '" + project.getName() + "', id: '" + project.getId() + "' " + "to '" +
+                    workingDirectory + "'" + ( tag != null ? " with branch/tag " + tag + "." : "." ) );
 
             CheckOutScmResult checkoutResult = scm.checkout( config );
             if ( StringUtils.isNotEmpty( checkoutResult.getRelativePathProjectDirectory() ) )
             {
-                context.put( AbstractContinuumAction.KEY_PROJECT_RELATIVE_PATH,
-                             checkoutResult.getRelativePathProjectDirectory() );
+                setProjectRelativePath( context, checkoutResult.getRelativePathProjectDirectory() );
             }
 
             if ( !checkoutResult.isSuccess() )
@@ -177,7 +192,8 @@
         }
         finally
         {
-            String relativePath = (String) getObject( context, KEY_PROJECT_RELATIVE_PATH, "" );
+            String relativePath = getProjectRelativePath( context );
+
             if ( StringUtils.isNotEmpty( relativePath ) )
             {
                 project.setRelativePath( relativePath );
@@ -185,24 +201,56 @@
 
             project = projectDao.getProject( project.getId() );
 
-            project.setState( ContinuumProjectState.CHECKEDOUT );
+            if ( originalState == ContinuumProjectState.NEW )
+            {
+                project.setState( ContinuumProjectState.CHECKEDOUT );
+            }
+            else
+            {
+                project.setState( originalState );
+            }
 
             projectDao.updateProject( project );
 
+            // update state of sub-projects 
+            // if multi-module project was checked out in a single directory, these must not be null            
+            for ( Project projectWithCommonScmRoot : projectsWithCommonScmRoot )
+            {
+                projectWithCommonScmRoot = projectDao.getProject( projectWithCommonScmRoot.getId() );
+                if ( projectWithCommonScmRoot != null && projectWithCommonScmRoot.getId() != project.getId() &&
+                    projectWithCommonScmRoot.getState() == ContinuumProjectState.NEW )
+                {
+                    projectWithCommonScmRoot.setState( ContinuumProjectState.CHECKEDOUT );
+                    projectDao.updateProject( projectWithCommonScmRoot );
+                }
+            }
+
             notifier.checkoutComplete( project, buildDefinition );
         }
 
-        context.put( KEY_CHECKOUT_SCM_RESULT, result );
-        context.put( KEY_PROJECT, project );
+        setCheckoutScmResult( context, result );
+        setProject( context, project );
     }
 
     private ContinuumScmConfiguration createScmConfiguration( Project project, File workingDirectory,
-                                                              String scmUserName, String scmPassword )
+                                                              String scmUserName, String scmPassword, String scmRootUrl,
+                                                              boolean isRootDirectory )
     {
         ContinuumScmConfiguration config = new ContinuumScmConfiguration();
-        config.setUrl( project.getScmUrl() );
-        config.setUsername( scmUserName );
-        config.setPassword( scmPassword );
+
+        if ( project.isCheckedOutInSingleDirectory() && scmRootUrl != null && !"".equals( scmRootUrl ) &&
+            isRootDirectory )
+        {
+            config.setUrl( scmRootUrl );
+        }
+        else
+        {
+            config.setUrl( project.getScmUrl() );
+        }
+
+        // CONTINUUM-2628
+        config = ContinuumScmUtils.setSCMCredentialsforSSH( config, config.getUrl(), scmUserName, scmPassword );
+
         config.setUseCredentialsCache( project.isScmUseCache() );
         config.setWorkingDirectory( workingDirectory );
         config.setTag( project.getScmTag() );
@@ -256,7 +304,7 @@
         {
             for ( Iterator<String> i = messages.iterator(); i.hasNext(); )
             {
-                message.append( (String) i.next() );
+                message.append( i.next() );
 
                 if ( i.hasNext() )
                 {
@@ -266,4 +314,44 @@
         }
         return message.toString();
     }
+
+    public static String getScmUsername( Map<String, Object> context, String defaultValue )
+    {
+        return getString( context, KEY_SCM_USERNAME, defaultValue );
+    }
+
+    public static void setScmUsername( Map<String, Object> context, String scmUsername )
+    {
+        context.put( KEY_SCM_USERNAME, scmUsername );
+    }
+
+    public static String getScmPassword( Map<String, Object> context, String defaultValue )
+    {
+        return getString( context, KEY_SCM_PASSWORD, defaultValue );
+    }
+
+    public static void setScmPassword( Map<String, Object> context, String scmPassword )
+    {
+        context.put( KEY_SCM_PASSWORD, scmPassword );
+    }
+
+    public static String getProjectRelativePath( Map<String, Object> context )
+    {
+        return getString( context, KEY_PROJECT_RELATIVE_PATH, "" );
+    }
+
+    public static void setProjectRelativePath( Map<String, Object> context, String projectRelativePath )
+    {
+        context.put( KEY_PROJECT_RELATIVE_PATH, projectRelativePath );
+    }
+
+    public static ScmResult getCheckoutScmResult( Map<String, Object> context, ScmResult defaultValue )
+    {
+        return (ScmResult) getObject( context, KEY_CHECKOUT_SCM_RESULT, defaultValue );
+    }
+
+    public static void setCheckoutScmResult( Map<String, Object> context, ScmResult scmResult )
+    {
+        context.put( KEY_CHECKOUT_SCM_RESULT, scmResult );
+    }
 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/CleanWorkingDirectoryAction.java b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/CleanWorkingDirectoryAction.java
index 3419f87..00bc13f 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/CleanWorkingDirectoryAction.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/CleanWorkingDirectoryAction.java
@@ -24,8 +24,10 @@
 import org.apache.maven.continuum.utils.WorkingDirectoryService;
 import org.apache.maven.shared.model.fileset.FileSet;
 import org.apache.maven.shared.model.fileset.util.FileSetManager;
+import org.codehaus.plexus.util.FileUtils;
 
 import java.io.File;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -51,18 +53,15 @@
         throws Exception
     {
         Project project = projectDao.getProject( getProjectId( context ) );
+        List<Project> projectsWithCommonScmRoot = getListOfProjectsInGroupWithCommonScmRoot( context );
+        String projectScmRootUrl = getProjectScmRootUrl( context, project.getScmUrl() );
 
-        File workingDirectory = workingDirectoryService.getWorkingDirectory( project );
+        File workingDirectory = workingDirectoryService.getWorkingDirectory( project, projectScmRootUrl,
+                                                                             projectsWithCommonScmRoot );
 
         if ( workingDirectory.exists() )
         {
-            FileSetManager fileSetManager = new FileSetManager();
-            FileSet fileSet = new FileSet();
-            fileSet.setDirectory( workingDirectory.getPath() );
-            fileSet.addInclude( "**/**" );
-            // TODO : this with a configuration option somewhere ?
-            fileSet.setFollowSymlinks( false );
-            fileSetManager.delete( fileSet );
+            FileUtils.deleteDirectory(workingDirectory);
         }
     }
 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/CreateBuildProjectTaskAction.java b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/CreateBuildProjectTaskAction.java
index a5e002f..f381625 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/CreateBuildProjectTaskAction.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/CreateBuildProjectTaskAction.java
@@ -19,21 +19,20 @@
  * under the License.
  */
 
-import java.util.Map;
-
-import org.apache.continuum.dao.BuildDefinitionDao;
+import org.apache.continuum.buildmanager.BuildsManager;
 import org.apache.continuum.dao.ProjectDao;
-import org.apache.continuum.taskqueue.BuildProjectTask;
-import org.apache.continuum.taskqueue.manager.TaskQueueManager;
-import org.apache.maven.continuum.ContinuumException;
+import org.apache.continuum.utils.build.BuildTrigger;
 import org.apache.maven.continuum.execution.ContinuumBuildExecutor;
 import org.apache.maven.continuum.execution.manager.BuildExecutorManager;
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.scm.ScmResult;
 import org.apache.maven.continuum.project.ContinuumProjectState;
 import org.apache.maven.continuum.store.ContinuumStoreException;
-import org.codehaus.plexus.taskqueue.TaskQueueException;
-import org.codehaus.plexus.util.StringUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
 
 /**
  * @author <a href="mailto:ctan@apache.org">Maria Catherine Tan</a>
@@ -46,11 +45,6 @@
     /**
      * @plexus.requirement
      */
-    private TaskQueueManager taskQueueManager;
-
-    /**
-     * @plexus.requirement
-     */
     private BuildExecutorManager executorManager;
 
     /**
@@ -59,90 +53,74 @@
     private ProjectDao projectDao;
 
     /**
-     * @plexus.requirement
+     * @plexus.requirement role-hint="parallel"
      */
-    private BuildDefinitionDao buildDefinitionDao;
-    
+    private BuildsManager parallelBuildsManager;
+
     public synchronized void execute( Map context )
         throws Exception
     {
-        Project project = AbstractContinuumAction.getProject( context );
-        int buildDefinitionId = AbstractContinuumAction.getBuildDefinitionId( context );
-        int trigger = AbstractContinuumAction.getTrigger( context );
-        
-        if ( taskQueueManager.isInBuildingQueue( project.getId(), buildDefinitionId ) )
-        {
-            return;
-        }
+        List<Project> projects = AbstractContinuumAction.getListOfProjects( context );
+        Map<Integer, BuildDefinition> projectsBuildDefinitionsMap =
+            AbstractContinuumAction.getProjectsBuildDefinitionsMap( context );
+        Map<Integer, ScmResult> scmResultMap = AbstractContinuumAction.getScmResultMap( context );
+        List<Project> projectsToBeBuilt = new ArrayList<Project>();
+        BuildTrigger buildTrigger = AbstractContinuumAction.getBuildTrigger( context );
+        int projectGroupId = AbstractContinuumAction.getProjectGroupId( context );
 
-        if ( taskQueueManager.isInCheckoutQueue( project.getId() ) )
+        // update state of each project first
+        for ( Project project : projects )
         {
-            taskQueueManager.removeProjectFromCheckoutQueue( project.getId() );
-        }
-        
-        try
-        {
-            if ( project.getState() != ContinuumProjectState.NEW &&
-                project.getState() != ContinuumProjectState.CHECKEDOUT &&
-                project.getState() != ContinuumProjectState.OK && project.getState() != ContinuumProjectState.FAILED &&
-                project.getState() != ContinuumProjectState.ERROR )
+            BuildDefinition buildDefinition = projectsBuildDefinitionsMap.get( project.getId() );
+
+            if ( parallelBuildsManager.isInAnyBuildQueue( project.getId(), buildDefinition.getId() ) )
             {
-                ContinuumBuildExecutor executor = executorManager.getBuildExecutor( project.getExecutorId() );
-
-                if ( executor.isBuilding( project ) || project.getState() == ContinuumProjectState.UPDATING )
-                {
-                    // project is building
-                    getLogger().info( "Project '" + project.getName() + "' already being built." );
-
-                    return;
-                }
-                else
-                {
-                    project.setOldState( project.getState() );
-
-                    project.setState( ContinuumProjectState.ERROR );
-
-                    projectDao.updateProject( project );
-
-                    project = projectDao.getProject( project.getId() );
-                }
+                getLogger().info( "Project '" + project.getName() + "' is already in build queue." );
+                continue;
             }
-            else
+
+            if ( parallelBuildsManager.isInAnyCheckoutQueue( project.getId() ) )
             {
+                parallelBuildsManager.removeProjectFromCheckoutQueue( project.getId() );
+            }
+
+            try
+            {
+                if ( project.getState() != ContinuumProjectState.NEW &&
+                    project.getState() != ContinuumProjectState.CHECKEDOUT &&
+                    project.getState() != ContinuumProjectState.OK &&
+                    project.getState() != ContinuumProjectState.FAILED &&
+                    project.getState() != ContinuumProjectState.ERROR )
+                {
+                    ContinuumBuildExecutor executor = executorManager.getBuildExecutor( project.getExecutorId() );
+
+                    if ( executor.isBuilding( project ) || project.getState() == ContinuumProjectState.UPDATING )
+                    {
+                        // project is building
+                        getLogger().info( "Project '" + project.getName() + "' already being built." );
+
+                        continue;
+                    }
+                    else
+                    {
+                        project.setState( ContinuumProjectState.ERROR );
+                    }
+                }
                 project.setOldState( project.getState() );
 
                 projectDao.updateProject( project );
 
                 project = projectDao.getProject( project.getId() );
-            }
 
-            BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
-            String buildDefinitionLabel = buildDefinition.getDescription();
-            if ( StringUtils.isEmpty( buildDefinitionLabel ) )
+                projectsToBeBuilt.add( project );
+            }
+            catch ( ContinuumStoreException e )
             {
-                buildDefinitionLabel = buildDefinition.getGoals();
+                getLogger().error( "Error while creating build object", e );
             }
-
-            getLogger().info( "Enqueuing '" + project.getName() + "' with build definition '" + buildDefinitionLabel +
-                "' - id=" + buildDefinitionId + ")." );
-
-            BuildProjectTask task = new BuildProjectTask( project.getId(), buildDefinitionId, trigger, project
-                .getName(), buildDefinitionLabel );
-
-            task.setMaxExecutionTime( buildDefinition.getSchedule()
-                .getMaxJobExecutionTime() * 1000 );
-
-            taskQueueManager.getBuildQueue().put( task );
         }
-        catch ( ContinuumStoreException e )
-        {
-            getLogger().error( "Error while creating build object", e );
-            throw new ContinuumException( "Error while creating build object.", e );
-        }
-        catch ( TaskQueueException e )
-        {
-            getLogger().error( "Error while enqueuing object", e );
-            throw new ContinuumException( "Error while enqueuing object.", e );
-        }
+
+        parallelBuildsManager.buildProjects( projectsToBeBuilt, projectsBuildDefinitionsMap, buildTrigger, scmResultMap,
+                                             projectGroupId );
     }
 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/CreateProjectsFromMetadataAction.java b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/CreateProjectsFromMetadataAction.java
index e0ea1f7..ccd24a4 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/CreateProjectsFromMetadataAction.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/CreateProjectsFromMetadataAction.java
@@ -19,13 +19,6 @@
  * under the License.
  */
 
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.util.List;
-import java.util.Map;
-
 import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.execution.maven.m2.SettingsConfigurationException;
 import org.apache.maven.continuum.model.project.BuildDefinitionTemplate;
@@ -43,6 +36,13 @@
 import org.codehaus.plexus.util.StringUtils;
 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
 
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+
 /**
  * Resolve the project url being passed in and gather authentication information
  * if the url is so configured, then create the projects
@@ -62,6 +62,19 @@
     extends AbstractContinuumAction
 {
     /**
+     * Metadata url for adding projects.
+     */
+    private static final String KEY_URL = "url";
+
+    private static final String KEY_PROJECT_BUILDER_ID = "builderId";
+
+    private static final String KEY_PROJECT_BUILDING_RESULT = "projectBuildingResult";
+
+    private static final String KEY_LOAD_RECURSIVE_PROJECTS = "loadRecursiveProjects";
+
+    public static final String KEY_CHECKOUT_PROJECTS_IN_SINGLE_DIRECTORY = "checkoutProjectsInSingleDirectory";
+
+    /**
      * @plexus.requirement
      */
     private ContinuumProjectBuilderManager projectBuilderManager;
@@ -70,28 +83,24 @@
      * @plexus.requirement
      */
     private MavenSettingsBuilder mavenSettingsBuilder;
-    
+
     /**
      * @plexus.requirement role-hint="continuumUrl"
      */
-    private ContinuumUrlValidator urlValidator;    
-
-    public static final String KEY_URL = "url";
-
-    public static final String KEY_PROJECT_BUILDER_ID = "builderId";
-
-    public static final String KEY_PROJECT_BUILDING_RESULT = "projectBuildingResult";
-
-    public static final String KEY_LOAD_RECURSIVE_PROJECTS = "loadRecursiveProjects";
+    private ContinuumUrlValidator urlValidator;
 
     public void execute( Map context )
         throws ContinuumException, ContinuumProjectBuilderManagerException, ContinuumProjectBuilderException
     {
-        String projectBuilderId = getString( context, KEY_PROJECT_BUILDER_ID );
+        String projectBuilderId = getProjectBuilderId( context );
 
-        boolean loadRecursiveProjects = getBoolean( context, KEY_LOAD_RECURSIVE_PROJECTS );
+        boolean loadRecursiveProjects = isLoadRecursiveProject( context );
 
-        String curl = getString( context, KEY_URL );
+        boolean checkoutProjectsInSingleDirectory = getBoolean( context, KEY_CHECKOUT_PROJECTS_IN_SINGLE_DIRECTORY );
+
+        int projectGroupId = getProjectGroupId( context );
+
+        String curl = getUrl( context );
 
         URL url;
 
@@ -105,13 +114,14 @@
             if ( buildDefinitionTemplate == null )
             {
                 buildDefinitionTemplate = projectBuilder.getDefaultBuildDefinitionTemplate();
-            }            
+            }
             if ( !curl.startsWith( "http" ) )
             {
                 url = new URL( curl );
 
                 result = projectBuilder.buildProjectsFromMetadata( url, null, null, loadRecursiveProjects,
-                                                                   buildDefinitionTemplate );
+                                                                   buildDefinitionTemplate,
+                                                                   checkoutProjectsInSingleDirectory, projectGroupId );
 
             }
             else
@@ -150,7 +160,9 @@
                 {
 
                     result = projectBuilder.buildProjectsFromMetadata( url, username, password, loadRecursiveProjects,
-                                                                       buildDefinitionTemplate );
+                                                                       buildDefinitionTemplate,
+                                                                       checkoutProjectsInSingleDirectory,
+                                                                       projectGroupId );
 
                 }
                 else
@@ -160,11 +172,11 @@
                     result.addError( ContinuumProjectBuildingResult.ERROR_MALFORMED_URL );
                 }
             }
-     
+
             if ( result.getProjects() != null )
             {
                 String scmRootUrl = getScmRootUrl( result.getProjects() );
-         
+
                 if ( scmRootUrl == null || scmRootUrl.equals( "" ) )
                 {
                     if ( curl.indexOf( "pom.xml" ) > 0 )
@@ -177,7 +189,8 @@
                     }
                 }
 
-                context.put( KEY_URL, scmRootUrl );
+                //setUrl( context, scmRootUrl );
+                setProjectScmRootUrl( context, scmRootUrl );
             }
         }
         catch ( MalformedURLException e )
@@ -193,7 +206,7 @@
             result.addError( ContinuumProjectBuildingResult.ERROR_MALFORMED_URL );
         }
 
-        context.put( KEY_PROJECT_BUILDING_RESULT, result );
+        setProjectBuildingResult( context, result );
     }
 
     private String hidePasswordInUrl( String url )
@@ -233,14 +246,14 @@
     private String getScmRootUrl( List<Project> projects )
     {
         String scmRootUrl = "";
-        
+
         for ( Project project : projects )
         {
             String scmUrl = project.getScmUrl();
-            
+
             scmRootUrl = getCommonPath( scmUrl, scmRootUrl );
         }
-        
+
         return scmRootUrl;
     }
 
@@ -253,7 +266,18 @@
         else
         {
             int indexDiff = StringUtils.differenceAt( path1, path2 );
-            return path1.substring( 0, indexDiff );
+            String commonPath = path1.substring( 0, indexDiff );
+
+            if ( commonPath.lastIndexOf( '/' ) != commonPath.length() - 1 && !( path1.contains( new String(
+                commonPath + "/" ) ) || path2.contains( new String( commonPath + "/" ) ) ) )
+            {
+                while ( commonPath.lastIndexOf( '/' ) != commonPath.length() - 1 )
+                {
+                    commonPath = commonPath.substring( 0, commonPath.length() - 1 );
+                }
+            }
+
+            return commonPath;
         }
     }
 
@@ -286,4 +310,55 @@
     {
         this.urlValidator = urlValidator;
     }
+
+    public static String getUrl( Map<String, Object> context )
+    {
+        return getString( context, KEY_URL );
+    }
+
+    public static void setUrl( Map<String, Object> context, String url )
+    {
+        context.put( KEY_URL, url );
+    }
+
+    public static String getProjectBuilderId( Map<String, Object> context )
+    {
+        return getString( context, KEY_PROJECT_BUILDER_ID );
+    }
+
+    public static void setProjectBuilderId( Map<String, Object> context, String projectBuilderId )
+    {
+        context.put( KEY_PROJECT_BUILDER_ID, projectBuilderId );
+    }
+
+    public static ContinuumProjectBuildingResult getProjectBuildingResult( Map<String, Object> context )
+    {
+        return (ContinuumProjectBuildingResult) getObject( context, KEY_PROJECT_BUILDING_RESULT );
+    }
+
+    private static void setProjectBuildingResult( Map<String, Object> context, ContinuumProjectBuildingResult result )
+    {
+        context.put( KEY_PROJECT_BUILDING_RESULT, result );
+    }
+
+    public static boolean isLoadRecursiveProject( Map<String, Object> context )
+    {
+        return getBoolean( context, KEY_LOAD_RECURSIVE_PROJECTS );
+    }
+
+    public static void setLoadRecursiveProject( Map<String, Object> context, boolean loadRecursiveProject )
+    {
+        context.put( KEY_LOAD_RECURSIVE_PROJECTS, loadRecursiveProject );
+    }
+
+    public static boolean isCheckoutProjectsInSingleDirectory( Map<String, Object> context )
+    {
+        return getBoolean( context, KEY_CHECKOUT_PROJECTS_IN_SINGLE_DIRECTORY );
+    }
+
+    public static void setCheckoutProjectsInSingleDirectory( Map<String, Object> context,
+                                                             boolean checkoutProjectsInSingleDirectory )
+    {
+        context.put( KEY_CHECKOUT_PROJECTS_IN_SINGLE_DIRECTORY, checkoutProjectsInSingleDirectory );
+    }
 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/DeployArtifactContinuumAction.java b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/DeployArtifactContinuumAction.java
index 5feacea..e5b4c7c 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/DeployArtifactContinuumAction.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/DeployArtifactContinuumAction.java
@@ -36,7 +36,6 @@
 import org.apache.maven.continuum.utils.WorkingDirectoryService;
 
 import java.io.File;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
@@ -103,16 +102,22 @@
             {
                 BuildDefinition buildDefinition = getBuildDefinition( context );
 
+                String projectScmRootUrl = getProjectScmRootUrl( context, project.getScmUrl() );
+
+                List<Project> projectsWithCommonScmRoot = getListOfProjectsInGroupWithCommonScmRoot( context );
+
                 List<Artifact> artifacts = buildExecutor.getDeployableArtifacts( project,
-                                                                       workingDirectoryService.getWorkingDirectory(
-                                                                           project ), buildDefinition );
+                                                                                 workingDirectoryService.getWorkingDirectory(
+                                                                                     project, projectScmRootUrl,
+                                                                                     projectsWithCommonScmRoot ),
+                                                                                 buildDefinition );
 
                 LocalRepository repository = project.getProjectGroup().getLocalRepository();
-                
+
                 builderHelper.setLocalRepository( repository );
-                
+
                 ArtifactRepository localRepository = builderHelper.getLocalRepository();
-                
+
                 for ( Artifact artifact : artifacts )
                 {
                     ArtifactRepositoryLayout repositoryLayout = new DefaultRepositoryLayout();
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/ExecuteBuilderContinuumAction.java b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/ExecuteBuilderContinuumAction.java
index 9024c1f..ddd18c5 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/ExecuteBuilderContinuumAction.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/ExecuteBuilderContinuumAction.java
@@ -22,6 +22,7 @@
 import org.apache.continuum.dao.BuildResultDao;
 import org.apache.continuum.dao.ProjectDao;
 import org.apache.continuum.utils.ContinuumUtils;
+import org.apache.continuum.utils.build.BuildTrigger;
 import org.apache.maven.continuum.configuration.ConfigurationService;
 import org.apache.maven.continuum.execution.ContinuumBuildCancelledException;
 import org.apache.maven.continuum.execution.ContinuumBuildExecutionResult;
@@ -30,7 +31,8 @@
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.BuildResult;
 import org.apache.maven.continuum.model.project.Project;
-//import org.apache.maven.continuum.model.scm.ScmResult;
+import org.apache.maven.continuum.model.project.ProjectDependency;
+import org.apache.maven.continuum.model.scm.ScmResult;
 import org.apache.maven.continuum.notification.ContinuumNotificationDispatcher;
 import org.apache.maven.continuum.project.ContinuumProjectState;
 
@@ -48,6 +50,8 @@
 public class ExecuteBuilderContinuumAction
     extends AbstractContinuumAction
 {
+    private static final String KEY_CANCELLED = "cancelled";
+
     /**
      * @plexus.requirement
      */
@@ -84,9 +88,11 @@
 
         BuildDefinition buildDefinition = getBuildDefinition( context );
 
-        int trigger = getTrigger( context );
+        BuildTrigger buildTrigger = getBuildTrigger( context );
 
-        List updatedDependencies = getUpdatedDependencies( context );
+        ScmResult scmResult = getScmResult( context );
+
+        List<ProjectDependency> updatedDependencies = getUpdatedDependencies( context );
 
         ContinuumBuildExecutor buildExecutor = buildExecutorManager.getBuildExecutor( project.getExecutorId() );
 
@@ -100,7 +106,11 @@
 
         buildResult.setState( ContinuumProjectState.BUILDING );
 
-        buildResult.setTrigger( trigger );
+        buildResult.setTrigger( buildTrigger.getTrigger() );
+
+        buildResult.setUsername( buildTrigger.getTriggeredBy() );
+
+        buildResult.setScmResult( scmResult );
 
         buildResult.setModifiedDependencies( updatedDependencies );
 
@@ -108,19 +118,23 @@
 
         buildResultDao.addBuildResult( project, buildResult );
 
-        context.put( KEY_BUILD_ID, Integer.toString( buildResult.getId() ) );
+        AbstractContinuumAction.setBuildId( context, Integer.toString( buildResult.getId() ) );
 
-        context.put( KEY_CANCELLED, new Boolean( false ) );
+        setCancelled( context, false );
 
         buildResult = buildResultDao.getBuildResult( buildResult.getId() );
 
+        String projectScmRootUrl = getProjectScmRootUrl( context, project.getScmUrl() );
+        List<Project> projectsWithCommonScmRoot = getListOfProjectsInGroupWithCommonScmRoot( context );
+
         try
         {
             notifier.runningGoals( project, buildDefinition, buildResult );
 
             File buildOutputFile = configurationService.getBuildOutputFile( buildResult.getId(), project.getId() );
 
-            ContinuumBuildExecutionResult result = buildExecutor.build( project, buildDefinition, buildOutputFile );
+            ContinuumBuildExecutionResult result = buildExecutor.build( project, buildDefinition, buildOutputFile,
+                                                                        projectsWithCommonScmRoot, projectScmRootUrl );
 
             buildResult.setState( result.getExitCode() == 0 ? ContinuumProjectState.OK : ContinuumProjectState.FAILED );
 
@@ -129,10 +143,10 @@
         catch ( ContinuumBuildCancelledException e )
         {
             getLogger().info( "Cancelled build" );
-            
+
             buildResult.setState( ContinuumProjectState.CANCELLED );
-            
-            context.put( KEY_CANCELLED, new Boolean( true ) );
+
+            setCancelled( context, true );
         }
         catch ( Throwable e )
         {
@@ -152,7 +166,7 @@
 
                 project.setOldState( 0 );
 
-                int buildResultId = getOldBuildId( context ); 
+                int buildResultId = getOldBuildId( context );
 
                 project.setLatestBuildId( buildResultId );
 
@@ -183,23 +197,36 @@
                 // ----------------------------------------------------------------------
                 // Copy over the buildResult result
                 // ----------------------------------------------------------------------
-    
+
                 buildResultDao.updateBuildResult( buildResult );
-    
+
                 buildResult = buildResultDao.getBuildResult( buildResult.getId() );
 
                 notifier.goalsCompleted( project, buildDefinition, buildResult );
             }
 
-            context.put( KEY_PROJECT, project );
+            AbstractContinuumAction.setProject( context, project );
 
             projectDao.updateProject( project );
 
+            projectScmRootUrl = getProjectScmRootUrl( context, project.getScmUrl() );
+            projectsWithCommonScmRoot = getListOfProjectsInGroupWithCommonScmRoot( context );
+
             // ----------------------------------------------------------------------
             // Backup test result files
             // ----------------------------------------------------------------------
             //TODO: Move as a plugin
-            buildExecutor.backupTestFiles( project, buildResult.getId() );
+            buildExecutor.backupTestFiles( project, buildResult.getId(), projectScmRootUrl, projectsWithCommonScmRoot );
         }
     }
+
+    public static boolean isCancelled( Map<String, Object> context )
+    {
+        return getBoolean( context, KEY_CANCELLED );
+    }
+
+    private static void setCancelled( Map<String, Object> context, boolean cancelled )
+    {
+        context.put( KEY_CANCELLED, cancelled );
+    }
 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/RemoveBuildDefinitionFromProjectAction.java b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/RemoveBuildDefinitionFromProjectAction.java
index dda3935..9e5c769 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/RemoveBuildDefinitionFromProjectAction.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/RemoveBuildDefinitionFromProjectAction.java
@@ -41,11 +41,11 @@
      */
     private ProjectDao projectDao;
 
-    public void execute( Map map )
+    public void execute( Map context )
         throws Exception
     {
-        BuildDefinition buildDefinition = getBuildDefinition( map );
-        int projectId = getProjectId( map );
+        BuildDefinition buildDefinition = getBuildDefinition( context );
+        int projectId = getProjectId( context );
 
         Project project = projectDao.getProjectWithAllDetails( projectId );
 
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/RemoveBuildDefinitionFromProjectGroupAction.java b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/RemoveBuildDefinitionFromProjectGroupAction.java
index bf3238e..20c69f1 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/RemoveBuildDefinitionFromProjectGroupAction.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/RemoveBuildDefinitionFromProjectGroupAction.java
@@ -43,11 +43,11 @@
     private ProjectGroupDao projectGroupDao;
 
 
-    public void execute( Map map )
+    public void execute( Map context )
         throws Exception
     {
-        BuildDefinition buildDefinition = getBuildDefinition( map );
-        int projectGroupId = getProjectGroupId( map );
+        BuildDefinition buildDefinition = getBuildDefinition( context );
+        int projectGroupId = getProjectGroupId( context );
 
         ProjectGroup projectGroup = projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId( projectGroupId );
 
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/StoreCheckOutScmResultAction.java b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/StoreCheckOutScmResultAction.java
index fa0f088..6e049e7 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/StoreCheckOutScmResultAction.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/StoreCheckOutScmResultAction.java
@@ -50,7 +50,7 @@
             //
             // ----------------------------------------------------------------------
 
-            ScmResult scmResult = AbstractContinuumAction.getCheckoutResult( context, null );
+            ScmResult scmResult = CheckoutProjectContinuumAction.getCheckoutScmResult( context, null );
 
             Project project = projectDao.getProject( getProjectId( context ) );
 
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/StoreProjectAction.java b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/StoreProjectAction.java
index 0f3ce2c..2d1fa48 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/StoreProjectAction.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/StoreProjectAction.java
@@ -36,6 +36,8 @@
 public class StoreProjectAction
     extends AbstractContinuumAction
 {
+    private static final String KEY_SCM_USE_CREDENTIALS_CACHE = "useCredentialsCache";
+
     /**
      * @plexus.requirement
      */
@@ -52,20 +54,20 @@
         //
         // ----------------------------------------------------------------------
 
-        boolean useCredentialsCache = getBoolean( context, KEY_SCM_USE_CREDENTIALS_CACHE, false );
+        boolean useCredentialsCache = isUseScmCredentialsCache( context, false );
         // CONTINUUM-1605 don't store username/password
-        if ( !useCredentialsCache )
+        if ( useCredentialsCache )
         {
             project.setScmUsername( null );
             project.setScmPassword( null );
-            project.setScmUseCache( false );
+            project.setScmUseCache( true );
         }
 
         projectGroup.addProject( project );
 
         projectGroupDao.updateProjectGroup( projectGroup );
 
-        context.put( KEY_PROJECT_ID, new Integer( project.getId() ) );
+        setProjectId( context, project.getId() );
 
         // ----------------------------------------------------------------------
         // Set the working directory
@@ -86,4 +88,14 @@
 */
 //        store.updateProject( project );
     }
+
+    public static boolean isUseScmCredentialsCache( Map<String, Object> context, boolean defaultValue )
+    {
+        return getBoolean( context, KEY_SCM_USE_CREDENTIALS_CACHE, defaultValue );
+    }
+
+    public static void setUseScmCredentialsCache( Map<String, Object> context, boolean useScmCredentialsCache )
+    {
+        context.put( KEY_SCM_USE_CREDENTIALS_CACHE, useScmCredentialsCache );
+    }
 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/StoreProjectGroupAction.java b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/StoreProjectGroupAction.java
index 102c092..2566f20 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/StoreProjectGroupAction.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/StoreProjectGroupAction.java
@@ -51,6 +51,6 @@
 
         projectGroup = projectGroupDao.addProjectGroup( projectGroup );
 
-        context.put( KEY_PROJECT_GROUP_ID, new Integer( projectGroup.getId() ) );
+        AbstractContinuumAction.setProjectGroupId( context, projectGroup.getId() );
     }
 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/UpdateBuildDefinitionFromProjectAction.java b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/UpdateBuildDefinitionFromProjectAction.java
index 9720e39..d7d773d 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/UpdateBuildDefinitionFromProjectAction.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/UpdateBuildDefinitionFromProjectAction.java
@@ -41,11 +41,11 @@
      */
     private ProjectDao projectDao;
 
-    public void execute( Map map )
+    public void execute( Map context )
         throws Exception
     {
-        BuildDefinition buildDefinition = getBuildDefinition( map );
-        int projectId = getProjectId( map );
+        BuildDefinition buildDefinition = getBuildDefinition( context );
+        int projectId = getProjectId( context );
 
         Project project = projectDao.getProjectWithAllDetails( projectId );
 
@@ -53,7 +53,7 @@
 
         updateBuildDefinitionInList( project.getBuildDefinitions(), buildDefinition );
 
-        map.put( AbstractContinuumAction.KEY_BUILD_DEFINITION, buildDefinition );
+        AbstractContinuumAction.setBuildDefinition( context, buildDefinition );
     }
 
 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/UpdateBuildDefinitionFromProjectGroupAction.java b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/UpdateBuildDefinitionFromProjectGroupAction.java
index f83d614..86aae8b 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/UpdateBuildDefinitionFromProjectGroupAction.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/UpdateBuildDefinitionFromProjectGroupAction.java
@@ -41,11 +41,11 @@
      */
     private ProjectGroupDao projectGroupDao;
 
-    public void execute( Map map )
+    public void execute( Map context )
         throws Exception
     {
-        BuildDefinition buildDefinition = getBuildDefinition( map );
-        int projectGroupId = getProjectGroupId( map );
+        BuildDefinition buildDefinition = getBuildDefinition( context );
+        int projectGroupId = getProjectGroupId( context );
 
         ProjectGroup projectGroup = projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId( projectGroupId );
 
@@ -53,6 +53,6 @@
 
         updateBuildDefinitionInList( projectGroup.getBuildDefinitions(), buildDefinition );
 
-        map.put( AbstractContinuumAction.KEY_BUILD_DEFINITION, buildDefinition );
+        AbstractContinuumAction.setBuildDefinition( context, buildDefinition );
     }
 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/UpdateProjectFromWorkingDirectoryContinuumAction.java b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/UpdateProjectFromWorkingDirectoryContinuumAction.java
index ee9f04c..13c3f2b 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/UpdateProjectFromWorkingDirectoryContinuumAction.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/UpdateProjectFromWorkingDirectoryContinuumAction.java
@@ -27,9 +27,11 @@
 import org.apache.maven.continuum.execution.manager.BuildExecutorManager;
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.scm.ScmResult;
 import org.apache.maven.continuum.store.ContinuumStoreException;
 import org.apache.maven.continuum.utils.WorkingDirectoryService;
 
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -78,9 +80,13 @@
 
         ContinuumBuildExecutor builder = buildExecutorManager.getBuildExecutor( project.getExecutorId() );
 
-        builder.updateProjectFromCheckOut( workingDirectoryService.getWorkingDirectory( project ), project,
-                                           buildDefinition );
+        ScmResult scmResult = (ScmResult) context.get( "scmResult" );
+        List<Project> projectsWithCommonScmRoot = getListOfProjectsInGroupWithCommonScmRoot( context );
+        String projectScmRootUrl = getProjectScmRootUrl( context, project.getScmUrl() );
 
+        builder.updateProjectFromCheckOut( workingDirectoryService.getWorkingDirectory( project, projectScmRootUrl,
+                                                                                        projectsWithCommonScmRoot ),
+                                           project, buildDefinition, scmResult );
         // ----------------------------------------------------------------------
         // Store the new descriptor
         // ----------------------------------------------------------------------
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/UpdateWorkingDirectoryFromScmContinuumAction.java b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/UpdateWorkingDirectoryFromScmContinuumAction.java
index d4d247d..33dd835 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/core/action/UpdateWorkingDirectoryFromScmContinuumAction.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/core/action/UpdateWorkingDirectoryFromScmContinuumAction.java
@@ -23,6 +23,7 @@
 import org.apache.continuum.dao.ProjectDao;
 import org.apache.continuum.scm.ContinuumScm;
 import org.apache.continuum.scm.ContinuumScmConfiguration;
+import org.apache.continuum.scm.ContinuumScmUtils;
 import org.apache.continuum.utils.ContinuumUtils;
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.BuildResult;
@@ -31,6 +32,7 @@
 import org.apache.maven.continuum.model.scm.ChangeSet;
 import org.apache.maven.continuum.model.scm.ScmResult;
 import org.apache.maven.continuum.notification.ContinuumNotificationDispatcher;
+import org.apache.maven.continuum.project.ContinuumProjectState;
 import org.apache.maven.continuum.store.ContinuumObjectNotFoundException;
 import org.apache.maven.continuum.store.ContinuumStoreException;
 import org.apache.maven.continuum.utils.WorkingDirectoryService;
@@ -54,6 +56,8 @@
 public class UpdateWorkingDirectoryFromScmContinuumAction
     extends AbstractContinuumAction
 {
+    private static final String KEY_UPDATE_SCM_RESULT = "update-result";
+
     /**
      * @plexus.requirement
      */
@@ -87,20 +91,18 @@
 
         BuildDefinition buildDefinition = getBuildDefinition( context );
 
-        // do not set state of project to updating
-
-        //int state = project.getState();
-
-        //project.setState( ContinuumProjectState.UPDATING );
-
-        //projectDao.updateProject( project );
-
         UpdateScmResult scmResult;
 
         ScmResult result;
 
         Date latestUpdateDate = null;
 
+        int originalState = project.getState();
+
+        project.setState( ContinuumProjectState.UPDATING );
+
+        projectDao.updateProject( project );
+
         try
         {
             BuildResult buildResult = buildResultDao.getLatestBuildResultForProject( project.getId() );
@@ -115,13 +117,19 @@
         {
             notifier.checkoutStarted( project, buildDefinition );
 
+            List<Project> projectsWithCommonScmRoot = getListOfProjectsInGroupWithCommonScmRoot( context );
+            String projectScmRootUrl = getProjectScmRootUrl( context, project.getScmUrl() );
+
             // TODO: not sure why this is different to the context, but it all needs to change
-            File workingDirectory = workingDirectoryService.getWorkingDirectory( project );
-            ContinuumScmConfiguration config = createScmConfiguration( project, workingDirectory );
+            File workingDirectory = workingDirectoryService.getWorkingDirectory( project, projectScmRootUrl,
+                                                                                 projectsWithCommonScmRoot );
+
+            ContinuumScmConfiguration config = createScmConfiguration( project, workingDirectory, projectScmRootUrl );
             config.setLatestUpdateDate( latestUpdateDate );
             String tag = config.getTag();
-            String msg = project.getName() + "', id: '" + project.getId() + "' to '" +
-                workingDirectory.getAbsolutePath() + "'" + ( tag != null ? " with branch/tag " + tag + "." : "." );
+            String msg =
+                project.getName() + "', id: '" + project.getId() + "' to '" + workingDirectory.getAbsolutePath() + "'" +
+                    ( tag != null ? " with branch/tag " + tag + "." : "." );
             getLogger().info( "Updating project: " + msg );
             scmResult = scm.update( config );
 
@@ -148,8 +156,8 @@
             result.setSuccess( false );
 
             result.setProviderMessage( e.getMessage() + ": " + getValidationMessages( e ) );
-            
-            getLogger().error( e.getMessage(), e);
+
+            getLogger().error( e.getMessage(), e );
         }
         catch ( NoSuchScmProviderException e )
         {
@@ -159,8 +167,8 @@
             result.setSuccess( false );
 
             result.setProviderMessage( e.getMessage() );
-            
-            getLogger().error( e.getMessage(), e);
+
+            getLogger().error( e.getMessage(), e );
         }
         catch ( ScmException e )
         {
@@ -169,40 +177,51 @@
             result.setSuccess( false );
 
             result.setException( ContinuumUtils.throwableMessagesToString( e ) );
-            
-            getLogger().error( e.getMessage(), e);
+
+            getLogger().error( e.getMessage(), e );
         }
         finally
         {
             // set back to the original state
-            // TODO: transient states!
-            //try
-            //{
-            //    project = projectDao.getProject( project.getId() );
+            try
+            {
+                project = projectDao.getProject( project.getId() );
 
-            //    project.setState( state );
+                project.setState( originalState );
 
-            //    projectDao.updateProject( project );
-            //}
-            //catch ( Exception e )
-            //{
+                projectDao.updateProject( project );
+            }
+            catch ( Exception e )
+            {
                 // nasty nasty, but we're in finally, so just sacrifice the state to keep the original exception
-            //    getLogger().error( e.getMessage(), e );
-            //}
+                getLogger().error( e.getMessage(), e );
+            }
 
             notifier.checkoutComplete( project, buildDefinition );
         }
-        
-        context.put( KEY_UPDATE_SCM_RESULT, result );
-        context.put( KEY_PROJECT, project );
+
+        setUpdateScmResult( context, result );
+        AbstractContinuumAction.setProject( context, project );
     }
 
-    private ContinuumScmConfiguration createScmConfiguration( Project project, File workingDirectory )
+    private ContinuumScmConfiguration createScmConfiguration( Project project, File workingDirectory,
+                                                              String scmRootUrl )
     {
         ContinuumScmConfiguration config = new ContinuumScmConfiguration();
-        config.setUrl( project.getScmUrl() );
-        config.setUsername( project.getScmUsername() );
-        config.setPassword( project.getScmPassword() );
+
+        if ( project.isCheckedOutInSingleDirectory() && scmRootUrl != null && !"".equals( scmRootUrl ) )
+        {
+            config.setUrl( scmRootUrl );
+        }
+        else
+        {
+            config.setUrl( project.getScmUrl() );
+        }
+
+        // CONTINUUM-2628
+        config = ContinuumScmUtils.setSCMCredentialsforSSH( config, config.getUrl(), project.getScmUsername(),
+                                                            project.getScmPassword() );
+
         config.setUseCredentialsCache( project.isScmUseCache() );
         config.setWorkingDirectory( workingDirectory );
         config.setTag( project.getScmTag() );
@@ -315,7 +334,7 @@
 
         return cmd;
     }
-    
+
     private String getValidationMessages( ScmRepositoryException ex )
     {
         List<String> messages = ex.getValidationMessages();
@@ -336,4 +355,14 @@
         }
         return message.toString();
     }
+
+    public static ScmResult getUpdateScmResult( Map<String, Object> context, ScmResult defaultValue )
+    {
+        return (ScmResult) getObject( context, KEY_UPDATE_SCM_RESULT, defaultValue );
+    }
+
+    public static void setUpdateScmResult( Map<String, Object> context, ScmResult scmResult )
+    {
+        context.put( KEY_UPDATE_SCM_RESULT, scmResult );
+    }
 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/execution/AbstractBuildExecutor.java b/continuum-core/src/main/java/org/apache/maven/continuum/execution/AbstractBuildExecutor.java
index 522c558..3f38c04 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/execution/AbstractBuildExecutor.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/execution/AbstractBuildExecutor.java
@@ -22,10 +22,13 @@
 import org.apache.continuum.utils.shell.ExecutionResult;
 import org.apache.continuum.utils.shell.ShellCommandHelper;
 import org.apache.maven.artifact.Artifact;
+import org.apache.maven.continuum.builddefinition.BuildDefinitionUpdatePolicyConstants;
 import org.apache.maven.continuum.installation.InstallationService;
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.scm.ChangeFile;
 import org.apache.maven.continuum.model.scm.ChangeSet;
+import org.apache.maven.continuum.model.scm.ScmResult;
 import org.apache.maven.continuum.model.system.Installation;
 import org.apache.maven.continuum.model.system.Profile;
 import org.apache.maven.continuum.project.ContinuumProjectState;
@@ -34,13 +37,13 @@
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
 import org.codehaus.plexus.util.StringUtils;
-import org.codehaus.plexus.util.cli.CommandLineException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.io.File;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
@@ -52,8 +55,8 @@
 public abstract class AbstractBuildExecutor
     implements ContinuumBuildExecutor, Initializable
 {
-    protected Logger log = LoggerFactory.getLogger( getClass() );
-    
+    protected final Logger log = LoggerFactory.getLogger( getClass() );
+
     private static final String SUDO_EXECUTABLE = "sudo";
 
     private static final String CHROOT_EXECUTABLE = "chroot";
@@ -96,7 +99,7 @@
     //
     // ----------------------------------------------------------------------
 
-    private String id;
+    private final String id;
 
     private boolean resolveExecutable;
 
@@ -155,7 +158,7 @@
             if ( StringUtils.isEmpty( defaultExecutable ) )
             {
                 log.warn( "The default executable for build executor '" + id + "' is not set. " +
-                    "This will cause a problem unless the project has a executable configured." );
+                              "This will cause a problem unless the project has a executable configured." );
             }
             else
             {
@@ -169,7 +172,7 @@
                 else
                 {
                     log.info( "Resolved the executable '" + defaultExecutable + "' to " + "'" +
-                        resolvedExecutable.getAbsolutePath() + "'." );
+                                  resolvedExecutable.getAbsolutePath() + "'." );
                 }
             }
         }
@@ -185,8 +188,8 @@
      * @param defaultExecutable
      * @return The executable path
      */
-    protected String findExecutable( Project project, String executable, String defaultExecutable,
-                                     boolean resolveExecutable, File workingDirectory )
+    protected String findExecutable( String executable, String defaultExecutable, boolean resolveExecutable,
+                                     File workingDirectory )
     {
         // ----------------------------------------------------------------------
         // If we're not searching the path for the executable, prefix the
@@ -240,14 +243,15 @@
     }
 
     protected ContinuumBuildExecutionResult executeShellCommand( Project project, String executable, String arguments,
-                                                                 File output, Map<String, String> environments )
+                                                                 File output, Map<String, String> environments,
+                                                                 List<Project> projectsWithCommonScmRoot,
+                                                                 String projectScmRootUrl )
         throws ContinuumBuildExecutorException
     {
 
-        File workingDirectory = getWorkingDirectory( project );
+        File workingDirectory = getWorkingDirectory( project, projectScmRootUrl, projectsWithCommonScmRoot );
 
-        String actualExecutable =
-            findExecutable( project, executable, defaultExecutable, resolveExecutable, workingDirectory );
+        String actualExecutable = findExecutable( executable, defaultExecutable, resolveExecutable, workingDirectory );
 
         // ----------------------------------------------------------------------
         // Execute the build
@@ -284,7 +288,7 @@
 
             return new ContinuumBuildExecutionResult( output, result.getExitCode() );
         }
-        catch ( CommandLineException e )
+        catch ( Exception e )
         {
             if ( e.getCause() instanceof InterruptedException )
             {
@@ -297,11 +301,6 @@
                         "is not in your path.", e );
             }
         }
-        catch ( Exception e )
-        {
-            throw new ContinuumBuildExecutorException( "Error while executing shell command. " +
-                "The most common error is that '" + executable + "' " + "is not in your path.", e );
-        }
     }
 
     private String getRelativePath( File chrootDir, File workingDirectory, String groupId )
@@ -336,7 +335,8 @@
         return jdk.getVarValue();
     }
 
-    public void backupTestFiles( Project project, int buildId )
+    public void backupTestFiles( Project project, int buildId, String projectScmRootUrl,
+                                 List<Project> projectsWithCommonScmRoot )
     {
         //Nothing to do, by default
     }
@@ -397,10 +397,46 @@
         return relPath + File.separator + buildFile;
     }
 
+    protected boolean isDescriptionUpdated( BuildDefinition buildDefinition, ScmResult scmResult, Project project )
+    {
+        boolean update = true;
+        if ( buildDefinition != null && scmResult != null )
+        {
+            int policy = buildDefinition.getUpdatePolicy();
+            if ( BuildDefinitionUpdatePolicyConstants.UPDATE_DESCRIPTION_NEVER == policy )
+            {
+                update = false;
+            }
+            else if ( BuildDefinitionUpdatePolicyConstants.UPDATE_DESCRIPTION_ONLY_FOR_NEW_POM == policy )
+            {
+                update = pomUpdated( buildDefinition.getBuildFile(), scmResult, project );
+            }
+        }
+        return update;
+    }
+
+    private boolean pomUpdated( String buildFile, ScmResult scmResult, Project project )
+    {
+        String filename = project.getScmUrl() + "/" + buildFile;
+        for ( Iterator changeIt = scmResult.getChanges().listIterator(); changeIt.hasNext(); )
+        {
+            ChangeSet change = (ChangeSet) changeIt.next();
+            for ( Iterator fileIt = change.getFiles().listIterator(); fileIt.hasNext(); )
+            {
+                ChangeFile changeFile = (ChangeFile) fileIt.next();
+                if ( filename.endsWith( changeFile.getName() ) )
+                {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
     public boolean isBuilding( Project project )
     {
-        return project.getState() == ContinuumProjectState.BUILDING ||
-            getShellCommandHelper().isRunning( project.getId() );
+        return project.getState() == ContinuumProjectState.BUILDING || getShellCommandHelper().isRunning(
+            project.getId() );
     }
 
     public void killProcess( Project project )
@@ -408,16 +444,19 @@
         getShellCommandHelper().killProcess( project.getId() );
     }
 
-    public List<Artifact> getDeployableArtifacts( Project project, File workingDirectory, BuildDefinition buildDefinition )
+    public List<Artifact> getDeployableArtifacts( Project project, File workingDirectory,
+                                                  BuildDefinition buildDefinition )
         throws ContinuumBuildExecutorException
     {
         // Not supported by this builder
-        return Collections.EMPTY_LIST;
+        return Collections.emptyList();
     }
 
-    public File getWorkingDirectory( Project project )
+    public File getWorkingDirectory( Project project, String projectScmRootUrl,
+                                     List<Project> projectsWithCommonScmRoot )
     {
-        return getWorkingDirectoryService().getWorkingDirectory( project );
+        return getWorkingDirectoryService().getWorkingDirectory( project, projectScmRootUrl,
+                                                                 projectsWithCommonScmRoot );
     }
 
     public InstallationService getInstallationService()
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/execution/ant/AntBuildExecutor.java b/continuum-core/src/main/java/org/apache/maven/continuum/execution/ant/AntBuildExecutor.java
index 3c1abfc..4d61b6c 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/execution/ant/AntBuildExecutor.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/execution/ant/AntBuildExecutor.java
@@ -27,6 +27,7 @@
 import org.apache.maven.continuum.installation.InstallationService;
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.scm.ScmResult;
 import org.apache.maven.continuum.model.system.Installation;
 import org.apache.maven.continuum.model.system.Profile;
 import org.codehaus.plexus.util.StringUtils;
@@ -35,6 +36,7 @@
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 
@@ -69,11 +71,12 @@
     // ContinuumBuilder Implementation
     // ----------------------------------------------------------------------
 
-    public ContinuumBuildExecutionResult build( Project project, BuildDefinition buildDefinition, File buildOutput )
+    public ContinuumBuildExecutionResult build( Project project, BuildDefinition buildDefinition, File buildOutput,
+                                                List<Project> projectsWithCommonScmRoot, String projectScmRootUrl )
         throws ContinuumBuildExecutorException
     {
-        String executable = getInstallationService().getExecutorConfigurator( InstallationService.ANT_TYPE )
-            .getExecutable();
+        String executable = getInstallationService().getExecutorConfigurator(
+            InstallationService.ANT_TYPE ).getExecutable();
 
         StringBuffer arguments = new StringBuffer();
 
@@ -104,7 +107,7 @@
             setResolveExecutable( false );
         }
 
-        return executeShellCommand( project, executable, arguments.toString(), buildOutput, environments );
+        return executeShellCommand( project, executable, arguments.toString(), buildOutput, environments, null, null );
     }
 
     protected Map<String, String> getEnvironments( BuildDefinition buildDefinition )
@@ -130,7 +133,8 @@
 
     }
 
-    public void updateProjectFromCheckOut( File workingDirectory, Project p, BuildDefinition buildDefinition )
+    public void updateProjectFromCheckOut( File workingDirectory, Project p, BuildDefinition buildDefinition,
+                                           ScmResult scmResult )
         throws ContinuumBuildExecutorException
     {
     }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/execution/manager/BuildExecutorNotFoundException.java b/continuum-core/src/main/java/org/apache/maven/continuum/execution/manager/BuildExecutorNotFoundException.java
index d5cb571..5a95124 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/execution/manager/BuildExecutorNotFoundException.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/execution/manager/BuildExecutorNotFoundException.java
@@ -26,9 +26,9 @@
 public class BuildExecutorNotFoundException
     extends Exception
 {
-	private static final long serialVersionUID = 2709593430202284107L;
+    private static final long serialVersionUID = 2709593430202284107L;
 
-	public BuildExecutorNotFoundException( String message )
+    public BuildExecutorNotFoundException( String message )
     {
         super( message );
     }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/execution/manager/DefaultBuildExecutorManager.java b/continuum-core/src/main/java/org/apache/maven/continuum/execution/manager/DefaultBuildExecutorManager.java
index a66d6dc..8025ff3 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/execution/manager/DefaultBuildExecutorManager.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/execution/manager/DefaultBuildExecutorManager.java
@@ -26,7 +26,6 @@
 import org.slf4j.LoggerFactory;
 
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.Map;
 
 /**
@@ -38,12 +37,12 @@
 public class DefaultBuildExecutorManager
     implements BuildExecutorManager, Initializable
 {
-    private Logger log = LoggerFactory.getLogger( DefaultBuildExecutorManager.class );
+    private static final Logger log = LoggerFactory.getLogger( DefaultBuildExecutorManager.class );
 
     /**
      * @plexus.requirement role="org.apache.maven.continuum.execution.ContinuumBuildExecutor"
      */
-    private Map executors;
+    private Map<String, ContinuumBuildExecutor> executors;
 
     // ----------------------------------------------------------------------
     // Component Lifecycle
@@ -53,7 +52,7 @@
     {
         if ( executors == null )
         {
-            executors = new HashMap();
+            executors = new HashMap<String, ContinuumBuildExecutor>();
         }
 
         if ( executors.size() == 0 )
@@ -64,9 +63,9 @@
         {
             log.info( "Build executors:" );
 
-            for ( Iterator it = executors.keySet().iterator(); it.hasNext(); )
+            for ( String key : executors.keySet() )
             {
-                log.info( "  " + it.next().toString() );
+                log.info( "  " + key );
             }
         }
     }
@@ -78,7 +77,7 @@
     public ContinuumBuildExecutor getBuildExecutor( String builderType )
         throws ContinuumException
     {
-        ContinuumBuildExecutor executor = (ContinuumBuildExecutor) executors.get( builderType );
+        ContinuumBuildExecutor executor = executors.get( builderType );
 
         if ( executor == null )
         {
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m1/DefaultMavenOneMetadataHelper.java b/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m1/DefaultMavenOneMetadataHelper.java
index bb47a41..2953440 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m1/DefaultMavenOneMetadataHelper.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m1/DefaultMavenOneMetadataHelper.java
@@ -49,22 +49,23 @@
 public class DefaultMavenOneMetadataHelper
     implements MavenOneMetadataHelper
 {
-    private Logger log = LoggerFactory.getLogger( DefaultMavenOneMetadataHelper.class );
+    private static final Logger log = LoggerFactory.getLogger( DefaultMavenOneMetadataHelper.class );
 
     // ----------------------------------------------------------------------
     // MavenOneMetadataHelper Implementation
     // ----------------------------------------------------------------------
 
     /**
-     * @deprecated Use {@link #mapMetadata(ContinuumProjectBuildingResult,File,Project)} instead
+     * @deprecated Use {@link #mapMetadata(ContinuumProjectBuildingResult, File, Project)} instead
      */
     public void mapMetadata( File metadata, Project project )
         throws MavenOneMetadataHelperException
     {
-        mapMetadata( new ContinuumProjectBuildingResult(), metadata, project );
+        mapMetadata( new ContinuumProjectBuildingResult(), metadata, project, true );
     }
 
-    public void mapMetadata( ContinuumProjectBuildingResult result, File metadata, Project project )
+    public void mapMetadata( ContinuumProjectBuildingResult result, File metadata, Project project,
+                             boolean updateDefinition )
         throws MavenOneMetadataHelperException
     {
         Xpp3Dom mavenProject;
@@ -349,9 +350,12 @@
 
         project.setArtifactId( artifactId );
 
-        project.setVersion( version );
+        if ( updateDefinition )
+        {
+            project.setVersion( version );
 
-        project.setName( name );
+            project.setName( name );
+        }
 
         if ( StringUtils.isEmpty( shortDescription ) )
         {
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m1/MavenOneBuildExecutor.java b/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m1/MavenOneBuildExecutor.java
index a174ea7..07cd4fd 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m1/MavenOneBuildExecutor.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m1/MavenOneBuildExecutor.java
@@ -28,14 +28,17 @@
 import org.apache.maven.continuum.installation.InstallationService;
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.scm.ScmResult;
 import org.apache.maven.continuum.model.system.Installation;
 import org.apache.maven.continuum.model.system.Profile;
+import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
 import org.codehaus.plexus.util.StringUtils;
 
 import java.io.File;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 
@@ -79,11 +82,12 @@
     // Builder Implementation
     // ----------------------------------------------------------------------
 
-    public ContinuumBuildExecutionResult build( Project project, BuildDefinition buildDefinition, File buildOutput )
+    public ContinuumBuildExecutionResult build( Project project, BuildDefinition buildDefinition, File buildOutput,
+                                                List<Project> projectsWithCommonScmRoot, String projectScmRootUrl )
         throws ContinuumBuildExecutorException
     {
-        String executable = getInstallationService().getExecutorConfigurator( InstallationService.MAVEN1_TYPE )
-            .getExecutable();
+        String executable = getInstallationService().getExecutorConfigurator(
+            InstallationService.MAVEN1_TYPE ).getExecutable();
 
         StringBuffer arguments = new StringBuffer();
 
@@ -108,9 +112,10 @@
         LocalRepository repository = project.getProjectGroup().getLocalRepository();
         if ( repository != null )
         {
-            arguments.append( "\"-Dmaven.repo.local=" ).append( StringUtils.clean(repository.getLocation() ) ).append( "\" " );
+            arguments.append( "\"-Dmaven.repo.local=" ).append( StringUtils.clean( repository.getLocation() ) ).append(
+                "\" " );
         }
-        
+
         arguments.append( StringUtils.clean( buildDefinition.getGoals() ) );
 
         Map<String, String> environments = getEnvironments( buildDefinition );
@@ -121,7 +126,7 @@
             setResolveExecutable( false );
         }
 
-        return executeShellCommand( project, executable, arguments.toString(), buildOutput, environments );
+        return executeShellCommand( project, executable, arguments.toString(), buildOutput, environments, null, null );
     }
 
     protected Map<String, String> getEnvironments( BuildDefinition buildDefinition )
@@ -147,7 +152,8 @@
 
     }
 
-    public void updateProjectFromCheckOut( File workingDirectory, Project project, BuildDefinition buildDefinition )
+    public void updateProjectFromCheckOut( File workingDirectory, Project project, BuildDefinition buildDefinition,
+                                           ScmResult scmResult )
         throws ContinuumBuildExecutorException
     {
         File projectXmlFile = null;
@@ -174,7 +180,8 @@
 
         try
         {
-            metadataHelper.mapMetadata( projectXmlFile, project );
+            boolean update = isDescriptionUpdated( buildDefinition, scmResult, project );
+            metadataHelper.mapMetadata( new ContinuumProjectBuildingResult(), projectXmlFile, project, update );
         }
         catch ( MavenOneMetadataHelperException e )
         {
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m1/MavenOneMetadataHelper.java b/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m1/MavenOneMetadataHelper.java
index 16b034a..a66ee82 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m1/MavenOneMetadataHelper.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m1/MavenOneMetadataHelper.java
@@ -33,7 +33,7 @@
     String ROLE = MavenOneMetadataHelper.class.getName();
 
     /**
-     * @deprecated Use {@link #mapMetadata(ContinuumProjectBuildingResult,File,Project)} instead
+     * @deprecated Use {@link #mapMetadata(ContinuumProjectBuildingResult, File, Project)} instead
      */
     void mapMetadata( File metadata, Project project )
         throws MavenOneMetadataHelperException;
@@ -45,6 +45,6 @@
      * @throws MavenOneMetadataHelperException
      *
      */
-    void mapMetadata( ContinuumProjectBuildingResult result, File metadata, Project project )
+    void mapMetadata( ContinuumProjectBuildingResult result, File metadata, Project project, boolean updateDefinition )
         throws MavenOneMetadataHelperException;
 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m1/MavenOneMetadataHelperException.java b/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m1/MavenOneMetadataHelperException.java
index 5f9b8b1..2edd8f4 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m1/MavenOneMetadataHelperException.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m1/MavenOneMetadataHelperException.java
@@ -26,9 +26,9 @@
 public class MavenOneMetadataHelperException
     extends Exception
 {
-	private static final long serialVersionUID = -5868938464601717160L;
+    private static final long serialVersionUID = -5868938464601717160L;
 
-	public MavenOneMetadataHelperException( String message )
+    public MavenOneMetadataHelperException( String message )
     {
         super( message );
     }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m2/DefaultMavenBuilderHelper.java b/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m2/DefaultMavenBuilderHelper.java
index 311c9fd..2b54b6c 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m2/DefaultMavenBuilderHelper.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m2/DefaultMavenBuilderHelper.java
@@ -72,7 +72,6 @@
 import java.io.IOException;
 import java.io.StringWriter;
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
 
 /**
@@ -84,7 +83,7 @@
 public class DefaultMavenBuilderHelper
     implements MavenBuilderHelper, Contextualizable, Initializable
 {
-    private Logger log = LoggerFactory.getLogger( DefaultMavenBuilderHelper.class );
+    private static final Logger log = LoggerFactory.getLogger( DefaultMavenBuilderHelper.class );
 
     /**
      * @plexus.requirement
@@ -114,12 +113,13 @@
     private PlexusContainer container;
 
     private LocalRepository repository;
-    
+
     // ----------------------------------------------------------------------
     // MavenBuilderHelper Implementation
     // ----------------------------------------------------------------------
 
-    public void mapMetadataToProject( ContinuumProjectBuildingResult result, File metadata, Project continuumProject )
+    public void mapMetadataToProject( ContinuumProjectBuildingResult result, File metadata, Project continuumProject,
+                                      boolean update )
     {
         MavenProject mavenProject = getMavenProject( result, metadata );
 
@@ -130,11 +130,11 @@
             return;
         }
 
-        mapMavenProjectToContinuumProject( result, mavenProject, continuumProject, false );
+        mapMavenProjectToContinuumProject( result, mavenProject, continuumProject, update );
     }
 
     public void mapMavenProjectToContinuumProject( ContinuumProjectBuildingResult result, MavenProject mavenProject,
-                                                   Project continuumProject, boolean groupPom )
+                                                   Project continuumProject, boolean update )
     {
         if ( mavenProject == null )
         {
@@ -142,11 +142,26 @@
             return;
         }
 
-        // ----------------------------------------------------------------------
-        // Name
-        // ----------------------------------------------------------------------
+        if ( update )
+        {
+            // ----------------------------------------------------------------------
+            // Name
+            // ----------------------------------------------------------------------
 
-        continuumProject.setName( getProjectName( mavenProject ) );
+            continuumProject.setName( getProjectName( mavenProject ) );
+
+            // ----------------------------------------------------------------------
+            // Version
+            // ----------------------------------------------------------------------
+
+            continuumProject.setVersion( getVersion( mavenProject ) );
+
+            // ----------------------------------------------------------------------
+            // Description
+            // ----------------------------------------------------------------------
+
+            continuumProject.setDescription( mavenProject.getDescription() );
+        }
 
         // ----------------------------------------------------------------------
         // SCM Url
@@ -166,12 +181,6 @@
         }
 
         // ----------------------------------------------------------------------
-        // Version
-        // ----------------------------------------------------------------------
-
-        continuumProject.setVersion( getVersion( mavenProject ) );
-
-        // ----------------------------------------------------------------------
         // GroupId
         // ----------------------------------------------------------------------
 
@@ -216,7 +225,7 @@
         {
             List<ProjectDeveloper> developers = new ArrayList<ProjectDeveloper>();
 
-            for ( Developer d : (List<Developer>)mavenProject.getDevelopers() )
+            for ( Developer d : (List<Developer>) mavenProject.getDevelopers() )
             {
                 ProjectDeveloper cd = new ProjectDeveloper();
 
@@ -257,7 +266,7 @@
 
         List<ProjectDependency> dependencies = new ArrayList<ProjectDependency>();
 
-        for ( Dependency dependency : (List<Dependency>)mavenProject.getDependencies() )
+        for ( Dependency dependency : (List<Dependency>) mavenProject.getDependencies() )
         {
             ProjectDependency cd = new ProjectDependency();
 
@@ -270,7 +279,7 @@
             dependencies.add( cd );
         }
 
-        for ( Plugin dependency : (List<Plugin>)mavenProject.getBuildPlugins() )
+        for ( Plugin dependency : (List<Plugin>) mavenProject.getBuildPlugins() )
         {
             ProjectDependency cd = new ProjectDependency();
 
@@ -283,7 +292,7 @@
             dependencies.add( cd );
         }
 
-        for ( ReportPlugin dependency : (List<ReportPlugin>)mavenProject.getReportPlugins() )
+        for ( ReportPlugin dependency : (List<ReportPlugin>) mavenProject.getReportPlugins() )
         {
             ProjectDependency cd = new ProjectDependency();
 
@@ -296,7 +305,7 @@
             dependencies.add( cd );
         }
 
-        for ( Extension dependency : (List<Extension>)mavenProject.getBuildExtensions() )
+        for ( Extension dependency : (List<Extension>) mavenProject.getBuildExtensions() )
         {
             ProjectDependency cd = new ProjectDependency();
 
@@ -352,7 +361,7 @@
             }
         }
 
-        List<ProjectNotifier> notifiers = getNotifiers( result, mavenProject, continuumProject );
+        List<ProjectNotifier> notifiers = getNotifiers( result, mavenProject );
         if ( notifiers != null )
         {
             continuumProject.setNotifiers( notifiers );
@@ -382,7 +391,7 @@
 
             ProfileManager profileManager = new DefaultProfileManager( container, settings );
 
-            project = projectBuilder.build( file, getLocalRepository(), profileManager, false );
+            project = projectBuilder.build( file, getLocalRepository(), profileManager, true );
 
             if ( log.isDebugEnabled() )
             {
@@ -413,9 +422,8 @@
 
                 if ( validationResult != null && validationResult.getMessageCount() > 0 )
                 {
-                    for ( Iterator<String> i = validationResult.getMessages().iterator(); i.hasNext(); )
+                    for ( String valmsg : (List<String>) validationResult.getMessages() )
                     {
-                        String valmsg = i.next();
                         result.addError( ContinuumProjectBuildingResult.ERROR_VALIDATION, valmsg );
                         messages.append( valmsg );
                         messages.append( "\n" );
@@ -425,8 +433,7 @@
 
             if ( cause instanceof ArtifactNotFoundException )
             {
-                result.addError( ContinuumProjectBuildingResult.ERROR_ARTIFACT_NOT_FOUND,
-                                 ( (ArtifactNotFoundException) cause ).toString() );
+                result.addError( ContinuumProjectBuildingResult.ERROR_ARTIFACT_NOT_FOUND, ( cause ).toString() );
                 return null;
             }
 
@@ -434,8 +441,6 @@
 
             String msg = "Cannot build maven project from " + file + " (" + e.getMessage() + ").\n" + messages;
 
-            file.delete();
-
             log.error( msg );
 
             return null;
@@ -447,8 +452,6 @@
 
             String msg = "Cannot build maven project from " + file + " (" + e.getMessage() + ").";
 
-            file.delete();
-
             log.error( msg );
 
             return null;
@@ -476,8 +479,8 @@
         {
             result.addError( ContinuumProjectBuildingResult.ERROR_MISSING_SCM_CONNECTION, getProjectName( project ) );
 
-            log.error(
-                "Missing 'connection' element in the 'scm' element in the " + getProjectName( project ) + " POM." );
+            log.error( "Missing 'connection' element in the 'scm' element in the " + getProjectName( project ) +
+                           " POM." );
 
             return null;
         }
@@ -512,14 +515,13 @@
         return project.getScm().getConnection();
     }
 
-    private List<ProjectNotifier> getNotifiers( ContinuumProjectBuildingResult result, MavenProject mavenProject,
-                               Project continuumProject )
+    private List<ProjectNotifier> getNotifiers( ContinuumProjectBuildingResult result, MavenProject mavenProject )
     {
         List<ProjectNotifier> notifiers = new ArrayList<ProjectNotifier>();
 
         if ( mavenProject.getCiManagement() != null && mavenProject.getCiManagement().getNotifiers() != null )
         {
-            for ( Notifier projectNotifier : (List<Notifier>)mavenProject.getCiManagement().getNotifiers() )
+            for ( Notifier projectNotifier : (List<Notifier>) mavenProject.getCiManagement().getNotifiers() )
             {
                 ProjectNotifier notifier = new ProjectNotifier();
 
@@ -596,11 +598,9 @@
 
         if ( repository != null )
         {
-            return artifactRepositoryFactory.createArtifactRepository( repository.getName(), 
-                                                                       "file://" + repository.getLocation(), 
-                                                                       repositoryLayout,
-                                                                       null, 
-                                                                       null );
+            return artifactRepositoryFactory.createArtifactRepository( repository.getName(),
+                                                                       "file://" + repository.getLocation(),
+                                                                       repositoryLayout, null, null );
         }
         else if ( !( StringUtils.isEmpty( settings.getLocalRepository() ) ) )
         {
@@ -692,8 +692,8 @@
 
             for ( Profile profile : profiles )
             {
-                message.append( "\n - " ).append( profile.getId() ).append( " (source: " )
-                    .append( profile.getSource() ).append( ")" );
+                message.append( "\n - " ).append( profile.getId() ).append( " (source: " ).append(
+                    profile.getSource() ).append( ")" );
             }
 
         }
@@ -730,10 +730,8 @@
                                        proxy.getPassword(), proxy.getNonProxyHosts() );
             }
 
-            for ( Iterator<Server> i = settings.getServers().iterator(); i.hasNext(); )
+            for ( Server server : (List<Server>) settings.getServers() )
             {
-                Server server = i.next();
-
                 wagonManager.addAuthenticationInfo( server.getId(), server.getUsername(), server.getPassword(),
                                                     server.getPrivateKey(), server.getPassphrase() );
 
@@ -746,10 +744,8 @@
                 }
             }
 
-            for ( Iterator<Mirror> i = settings.getMirrors().iterator(); i.hasNext(); )
+            for ( Mirror mirror : (List<Mirror>) settings.getMirrors() )
             {
-                Mirror mirror = i.next();
-
                 wagonManager.addMirror( mirror.getId(), mirror.getMirrorOf(), mirror.getUrl() );
             }
         }
@@ -783,7 +779,7 @@
             throw new InitializationException( "Can't initialize '" + getClass().getName() + "'", e );
         }
     }
-    
+
     public void setLocalRepository( LocalRepository repository )
     {
         this.repository = repository;
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m2/MavenBuilderHelper.java b/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m2/MavenBuilderHelper.java
index 456155a..8ec1a96 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m2/MavenBuilderHelper.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m2/MavenBuilderHelper.java
@@ -35,7 +35,8 @@
 {
     String ROLE = MavenBuilderHelper.class.getName();
 
-    void mapMetadataToProject( ContinuumProjectBuildingResult result, File metadata, Project project );
+    void mapMetadataToProject( ContinuumProjectBuildingResult result, File metadata, Project project,
+                               boolean updateDefinition );
 
     MavenProject getMavenProject( ContinuumProjectBuildingResult result, File file );
 
@@ -46,10 +47,10 @@
      * @param groupPom         map this project as if it is being used to initialize a project group
      */
     void mapMavenProjectToContinuumProject( ContinuumProjectBuildingResult result, MavenProject mavenProject,
-                                            Project continuumProject, boolean groupPom );
+                                            Project continuumProject, boolean updateDefinition );
 
     ArtifactRepository getLocalRepository()
         throws SettingsConfigurationException;
-    
+
     void setLocalRepository( LocalRepository repository );
 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m2/MavenTwoBuildExecutor.java b/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m2/MavenTwoBuildExecutor.java
index 3597bc3..6b16bc9 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m2/MavenTwoBuildExecutor.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m2/MavenTwoBuildExecutor.java
@@ -19,16 +19,6 @@
  * under the License.
  */
 
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
 import org.apache.continuum.model.repository.LocalRepository;
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.artifact.metadata.ArtifactMetadata;
@@ -44,6 +34,7 @@
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.scm.ChangeFile;
 import org.apache.maven.continuum.model.scm.ChangeSet;
+import org.apache.maven.continuum.model.scm.ScmResult;
 import org.apache.maven.continuum.model.system.Installation;
 import org.apache.maven.continuum.model.system.Profile;
 import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
@@ -54,6 +45,16 @@
 import org.codehaus.plexus.util.FileUtils;
 import org.codehaus.plexus.util.StringUtils;
 
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
 /**
  * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
  * @version $Id$
@@ -132,11 +133,12 @@
     // ContinuumBuilder Implementation
     // ----------------------------------------------------------------------
 
-    public ContinuumBuildExecutionResult build( Project project, BuildDefinition buildDefinition, File buildOutput )
+    public ContinuumBuildExecutionResult build( Project project, BuildDefinition buildDefinition, File buildOutput,
+                                                List<Project> projectsWithCommonScmRoot, String projectScmRootUrl )
         throws ContinuumBuildExecutorException
     {
-        String executable = getInstallationService().getExecutorConfigurator( InstallationService.MAVEN2_TYPE )
-            .getExecutable();
+        String executable = getInstallationService().getExecutorConfigurator(
+            InstallationService.MAVEN2_TYPE ).getExecutable();
 
         StringBuffer arguments = new StringBuffer();
 
@@ -161,11 +163,12 @@
         LocalRepository repository = project.getProjectGroup().getLocalRepository();
         if ( repository != null )
         {
-            arguments.append( "\"-Dmaven.repo.local=" ).append( StringUtils.clean( repository.getLocation() ) ).append( "\" " );
+            arguments.append( "\"-Dmaven.repo.local=" ).append( StringUtils.clean( repository.getLocation() ) ).append(
+                "\" " );
         }
-        
+
         arguments.append( StringUtils.clean( buildDefinition.getGoals() ) );
-        
+
         Map<String, String> environments = getEnvironments( buildDefinition );
         String m2Home = environments.get( getInstallationService().getEnvVar( InstallationService.MAVEN2_TYPE ) );
         if ( StringUtils.isNotEmpty( m2Home ) )
@@ -174,10 +177,11 @@
             setResolveExecutable( false );
         }
 
-        return executeShellCommand( project, executable, arguments.toString(), buildOutput, environments );
+        return executeShellCommand( project, executable, arguments.toString(), buildOutput, environments, null, null );
     }
 
-    public void updateProjectFromCheckOut( File workingDirectory, Project project, BuildDefinition buildDefinition )
+    public void updateProjectFromCheckOut( File workingDirectory, Project project, BuildDefinition buildDefinition,
+                                           ScmResult scmResult )
         throws ContinuumBuildExecutorException
     {
         File f = getPomFile( getBuildFileForProject( project, buildDefinition ), workingDirectory );
@@ -186,10 +190,9 @@
         {
             throw new ContinuumBuildExecutorException( "Could not find Maven project descriptor." );
         }
-
         ContinuumProjectBuildingResult result = new ContinuumProjectBuildingResult();
-
-        builderHelper.mapMetadataToProject( result, f, project );
+        boolean update = isDescriptionUpdated( buildDefinition, scmResult, project );
+        builderHelper.mapMetadataToProject( result, f, project, update );
 
         if ( result.hasErrors() )
         {
@@ -218,7 +221,7 @@
 
     @Override
     public List<Artifact> getDeployableArtifacts( Project continuumProject, File workingDirectory,
-                                        BuildDefinition buildDefinition )
+                                                  BuildDefinition buildDefinition )
         throws ContinuumBuildExecutorException
     {
         MavenProject project = getMavenProject( continuumProject, workingDirectory, buildDefinition );
@@ -335,7 +338,8 @@
     }
 
     @Override
-    public void backupTestFiles( Project project, int buildId )
+    public void backupTestFiles( Project project, int buildId, String projectScmRootUrl,
+                                 List<Project> projectsWithCommonScmRoot )
     {
         File backupDirectory = null;
         try
@@ -350,7 +354,8 @@
         {
             log.info( "error on surefire backup directory creation skip backup " + e.getMessage(), e );
         }
-        backupTestFiles( getWorkingDirectory( project ), backupDirectory );
+        backupTestFiles( getWorkingDirectory( project, projectScmRootUrl, projectsWithCommonScmRoot ),
+                         backupDirectory );
     }
 
     private void backupTestFiles( File workingDir, File backupDirectory )
@@ -394,11 +399,11 @@
     {
         //Check if it's a recursive build
         boolean isRecursive = false;
-        if (StringUtils.isNotEmpty( buildDefinition.getArguments() ) )
-            {
-            isRecursive =  buildDefinition.getArguments().indexOf( "-N" ) < 0 &&
-                buildDefinition.getArguments().indexOf( "--non-recursive" ) < 0 ;
-            }
+        if ( StringUtils.isNotEmpty( buildDefinition.getArguments() ) )
+        {
+            isRecursive = buildDefinition.getArguments().indexOf( "-N" ) < 0 && buildDefinition.getArguments().indexOf(
+                "--non-recursive" ) < 0;
+        }
         if ( isRecursive && changes != null && !changes.isEmpty() )
         {
             if ( log.isInfoEnabled() )
@@ -410,14 +415,7 @@
 
         MavenProject project = getMavenProject( continuumProject, workingDirectory, buildDefinition );
 
-        //CONTINUUM-1815: additional check for projects recently released
-        if ( !continuumProject.getVersion().equals( project.getVersion() ) )
-        {
-            log.info( "Found changes in project's version ( maybe project was recently released ), building" );
-            return true;
-        }
-        
-        if ( changes.isEmpty() )
+        if ( changes == null || changes.isEmpty() )
         {
             if ( log.isInfoEnabled() )
             {
@@ -425,7 +423,7 @@
             }
             return false;
         }
-        
+
         //check if changes are only in sub-modules or not
         List<String> modules = project.getModules();
 
@@ -452,12 +450,12 @@
                     if ( log.isDebugEnabled() )
                     {
                         log.debug( "changeFile.name " + file.getName() + " removed because in a module" );
-                    }                    
+                    }
                     files.remove( file );
                     found = true;
                     break;
                 }
-                if (log.isDebugEnabled())
+                if ( log.isDebugEnabled() )
                 {
                     log.debug( "no remving file " + file.getName() + " not in module " + module );
                 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m2/SettingsConfigurationException.java b/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m2/SettingsConfigurationException.java
index 01b60de..e7e1e71 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m2/SettingsConfigurationException.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m2/SettingsConfigurationException.java
@@ -45,7 +45,7 @@
     public SettingsConfigurationException( String message, Throwable cause, int lineNumber, int columnNumber )
     {
         super( message + ( lineNumber > 0 ? "\n  Line:   " + lineNumber : "" ) +
-            ( columnNumber > 0 ? "\n  Column: " + columnNumber : "" ), cause );
+                   ( columnNumber > 0 ? "\n  Column: " + columnNumber : "" ), cause );
         this.lineNumber = lineNumber;
         this.columnNumber = columnNumber;
     }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/execution/shell/ShellBuildExecutor.java b/continuum-core/src/main/java/org/apache/maven/continuum/execution/shell/ShellBuildExecutor.java
index 08fcd5e..40c6c29 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/execution/shell/ShellBuildExecutor.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/execution/shell/ShellBuildExecutor.java
@@ -27,6 +27,7 @@
 import org.apache.maven.continuum.installation.InstallationService;
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.scm.ScmResult;
 import org.apache.maven.continuum.model.system.Installation;
 import org.apache.maven.continuum.model.system.Profile;
 import org.codehaus.plexus.util.StringUtils;
@@ -34,6 +35,7 @@
 import java.io.File;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -65,15 +67,16 @@
     // ContinuumBuilder implementation
     // ----------------------------------------------------------------------
 
-    public synchronized ContinuumBuildExecutionResult build( Project project, BuildDefinition buildDefinition,
-                                                             File buildOutput )
+    public ContinuumBuildExecutionResult build( Project project, BuildDefinition buildDefinition,
+                                                             File buildOutput, List<Project> projectsWithCommonScmRoot,
+                                                             String projectScmRootUrl )
         throws ContinuumBuildExecutorException
     {
         // TODO: this should be validated earlier?
         String executable = getBuildFileForProject( project, buildDefinition );
 
-        return executeShellCommand( project, executable, buildDefinition.getArguments(), buildOutput,
-                                    getEnvironments( buildDefinition ) );
+        return executeShellCommand( project, executable, buildDefinition.getArguments(), buildOutput, getEnvironments(
+            buildDefinition ), null, null );
     }
 
     protected Map<String, String> getEnvironments( BuildDefinition buildDefinition )
@@ -99,7 +102,8 @@
 
     }
 
-    public void updateProjectFromCheckOut( File workingDirectory, Project project, BuildDefinition buildDefinition )
+    public void updateProjectFromCheckOut( File workingDirectory, Project project, BuildDefinition buildDefinition,
+                                           ScmResult scmResult )
         throws ContinuumBuildExecutorException
     {
     }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/initialization/DefaultContinuumInitializer.java b/continuum-core/src/main/java/org/apache/maven/continuum/initialization/DefaultContinuumInitializer.java
index 2dac7a3..cf29c35 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/initialization/DefaultContinuumInitializer.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/initialization/DefaultContinuumInitializer.java
@@ -25,9 +25,9 @@
 import org.apache.continuum.dao.SystemConfigurationDao;
 import org.apache.continuum.model.repository.LocalRepository;
 import org.apache.continuum.model.repository.RepositoryPurgeConfiguration;
-import org.apache.maven.continuum.Continuum;
 import org.apache.maven.continuum.builddefinition.BuildDefinitionService;
 import org.apache.maven.continuum.builddefinition.BuildDefinitionServiceException;
+import org.apache.maven.continuum.model.project.BuildDefinitionTemplate;
 import org.apache.maven.continuum.model.project.ProjectGroup;
 import org.apache.maven.continuum.model.system.SystemConfiguration;
 import org.apache.maven.continuum.store.ContinuumObjectNotFoundException;
@@ -40,6 +40,7 @@
 import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
+import java.util.Collection;
 
 /**
  * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
@@ -51,7 +52,7 @@
 public class DefaultContinuumInitializer
     implements ContinuumInitializer
 {
-    private Logger log = LoggerFactory.getLogger( DefaultContinuumInitializer.class );
+    private static final Logger log = LoggerFactory.getLogger( DefaultContinuumInitializer.class );
 
     // ----------------------------------------------------------------------
     //  Requirements
@@ -144,30 +145,34 @@
         ProjectGroup group;
         try
         {
-            group = projectGroupDao.getProjectGroupByGroupId( Continuum.DEFAULT_PROJECT_GROUP_GROUP_ID );
+            group = projectGroupDao.getProjectGroupByGroupId( DEFAULT_PROJECT_GROUP_GROUP_ID );
             log.info( "Default Project Group exists" );
         }
         catch ( ContinuumObjectNotFoundException e )
         {
+            Collection<ProjectGroup> pgs = projectGroupDao.getAllProjectGroups();
+            if ( pgs != null && pgs.isEmpty() )
+            {
+                log.info( "create Default Project Group" );
 
-            log.info( "create Default Project Group" );
+                group = new ProjectGroup();
 
-            group = new ProjectGroup();
+                group.setName( "Default Project Group" );
 
-            group.setName( "Default Project Group" );
+                group.setGroupId( DEFAULT_PROJECT_GROUP_GROUP_ID );
 
-            group.setGroupId( Continuum.DEFAULT_PROJECT_GROUP_GROUP_ID );
+                group.setDescription( "Contains all projects that do not have a group of their own" );
 
-            group.setDescription( "Contains all projects that do not have a group of their own" );
+                LocalRepository localRepository = localRepositoryDao.getLocalRepositoryByName( "DEFAULT" );
 
-            LocalRepository localRepository = localRepositoryDao.getLocalRepositoryByName( "DEFAULT" );
+                group.setLocalRepository( localRepository );
 
-            group.setLocalRepository( localRepository );
+                group = projectGroupDao.addProjectGroup( group );
 
-            group.getBuildDefinitions().addAll(
-                buildDefinitionService.getDefaultMavenTwoBuildDefinitionTemplate().getBuildDefinitions() );
+                BuildDefinitionTemplate bdt = buildDefinitionService.getDefaultMavenTwoBuildDefinitionTemplate();
 
-            group = projectGroupDao.addProjectGroup( group );
+                buildDefinitionService.addBuildDefinitionTemplateToProjectGroup( group.getId(), bdt );
+            }
         }
     }
 
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/notification/DefaultContinuumNotificationDispatcher.java b/continuum-core/src/main/java/org/apache/maven/continuum/notification/DefaultContinuumNotificationDispatcher.java
index c1952ed..17bca74 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/notification/DefaultContinuumNotificationDispatcher.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/notification/DefaultContinuumNotificationDispatcher.java
@@ -46,7 +46,7 @@
 public class DefaultContinuumNotificationDispatcher
     implements ContinuumNotificationDispatcher
 {
-    private Logger log = LoggerFactory.getLogger( getClass() );
+    private static final Logger log = LoggerFactory.getLogger( DefaultContinuumNotificationDispatcher.class );
 
     /**
      * @plexus.requirement
@@ -109,8 +109,6 @@
     private void sendNotification( String messageId, Project project, BuildDefinition buildDefinition,
                                    BuildResult buildResult )
     {
-        //Map context = new HashMap();
-
         // ----------------------------------------------------------------------
         // The objects are reread from the store to make sure they're getting the "final"
         // state of the objects. Ideally this should be done on a per notifier basis or the
@@ -126,14 +124,14 @@
             //  - scm results are used to detect if scm failed
             project = projectDao.getProjectWithAllDetails( project.getId() );
 
-            ProjectGroup projectGroup =
-                projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId( project.getProjectGroup().getId() );
+            ProjectGroup projectGroup = projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId(
+                project.getProjectGroup().getId() );
 
             Map<String, List<ProjectNotifier>> notifiersMap = new HashMap<String, List<ProjectNotifier>>();
-            
+
             getProjectNotifiers( project, notifiersMap );
             getProjectGroupNotifiers( projectGroup, notifiersMap );
-            
+
             for ( String notifierType : notifiersMap.keySet() )
             {
                 MessageContext context = new MessageContext();
@@ -161,12 +159,12 @@
     {
         try
         {
-            ProjectGroup group =
-                projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId( projectScmRoot.getProjectGroup().getId() );
-            
+            ProjectGroup group = projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId(
+                projectScmRoot.getProjectGroup().getId() );
+
             Map<String, List<ProjectNotifier>> notifiersMap = new HashMap<String, List<ProjectNotifier>>();
             getProjectGroupNotifiers( group, notifiersMap );
-            
+
             for ( String notifierType : notifiersMap.keySet() )
             {
                 MessageContext context = new MessageContext();
@@ -200,7 +198,7 @@
             log.error( "Error while trying to use the " + notifierType + " notifier.", e );
         }
     }
-    
+
     private void getProjectNotifiers( Project project, Map<String, List<ProjectNotifier>> notifiersMap )
     {
         if ( project.getNotifiers() != null )
@@ -226,8 +224,8 @@
             }
         }
     }
-    
-    private void getProjectGroupNotifiers( ProjectGroup projectGroup, Map<String, List<ProjectNotifier>>  notifiersMap )
+
+    private void getProjectGroupNotifiers( ProjectGroup projectGroup, Map<String, List<ProjectNotifier>> notifiersMap )
     {
         // perform the project group level notifications
         if ( projectGroup.getNotifiers() != null )
@@ -243,7 +241,7 @@
                 if ( !projectNotifier.isEnabled() )
                 {
                     log.info( projectNotifier.getType() + " projectNotifier (id=" + projectNotifier.getId() +
-                        ") is disabled." );
+                                  ") is disabled." );
 
                     continue;
                 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/notification/console/ConsoleNotifier.java b/continuum-core/src/main/java/org/apache/maven/continuum/notification/console/ConsoleNotifier.java
index 229c4f9..e28faae 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/notification/console/ConsoleNotifier.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/notification/console/ConsoleNotifier.java
@@ -26,7 +26,6 @@
 import org.apache.maven.continuum.notification.ContinuumNotificationDispatcher;
 import org.apache.maven.continuum.notification.MessageContext;
 import org.apache.maven.continuum.notification.NotificationException;
-import org.apache.maven.continuum.project.ContinuumProjectState;
 import org.codehaus.plexus.util.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -40,7 +39,7 @@
 public class ConsoleNotifier
     extends AbstractContinuumNotifier
 {
-    private Logger log = LoggerFactory.getLogger( getClass() );
+    private static final Logger log = LoggerFactory.getLogger( ConsoleNotifier.class );
 
     // ----------------------------------------------------------------------
     // Notifier Implementation
@@ -142,11 +141,6 @@
         }
     }
 
-    private void prepareBuildStarted( ProjectScmRoot projectScmRoot )
-    {
-        out( projectScmRoot, "Prepare build started." );
-    }
-
     private void prepareBuildComplete( ProjectScmRoot projectScmRoot )
     {
         if ( StringUtils.isEmpty( projectScmRoot.getError() ) )
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/notification/mail/FormatterTool.java b/continuum-core/src/main/java/org/apache/maven/continuum/notification/mail/FormatterTool.java
index 50988a7..d0f673b 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/notification/mail/FormatterTool.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/notification/mail/FormatterTool.java
@@ -30,9 +30,9 @@
  */
 public class FormatterTool
 {
-    private String timestampFormatString;
+    private final String timestampFormatString;
 
-    private ThreadLocal timestampFormat = new ThreadLocal();
+    private final ThreadLocal<SimpleDateFormat> timestampFormat = new ThreadLocal<SimpleDateFormat>();
 
     public FormatterTool( String timestampFormatString )
     {
@@ -127,9 +127,9 @@
     //
     // ----------------------------------------------------------------------
 
-    private SimpleDateFormat getSimpleDateFormat( ThreadLocal threadLocal, String format )
+    private SimpleDateFormat getSimpleDateFormat( ThreadLocal<SimpleDateFormat> threadLocal, String format )
     {
-        SimpleDateFormat dateFormat = (SimpleDateFormat) threadLocal.get();
+        SimpleDateFormat dateFormat = threadLocal.get();
 
         if ( dateFormat == null )
         {
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/notification/mail/MailContinuumNotifier.java b/continuum-core/src/main/java/org/apache/maven/continuum/notification/mail/MailContinuumNotifier.java
index 6a61953..efc1ef9 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/notification/mail/MailContinuumNotifier.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/notification/mail/MailContinuumNotifier.java
@@ -54,12 +54,6 @@
 import org.slf4j.LoggerFactory;
 import org.springframework.mail.javamail.JavaMailSender;
 
-import javax.mail.Address;
-import javax.mail.Message;
-import javax.mail.MessagingException;
-import javax.mail.internet.AddressException;
-import javax.mail.internet.InternetAddress;
-import javax.mail.internet.MimeMessage;
 import java.io.StringWriter;
 import java.io.UnsupportedEncodingException;
 import java.net.InetAddress;
@@ -68,8 +62,15 @@
 import java.util.Arrays;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.internet.AddressException;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeMessage;
 
 /**
  * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
@@ -79,7 +80,7 @@
     extends AbstractContinuumNotifier
     implements Initializable
 {
-    private Logger log = LoggerFactory.getLogger( getClass() );
+    private static final Logger log = LoggerFactory.getLogger( MailContinuumNotifier.class );
 
     // ----------------------------------------------------------------------
     // Requirements
@@ -113,6 +114,7 @@
     // ----------------------------------------------------------------------
     // Configuration
     // ----------------------------------------------------------------------
+
     /**
      * @plexus.configuration
      */
@@ -136,11 +138,6 @@
     /**
      * @plexus.configuration
      */
-    private boolean includeBuildResult = true;
-
-    /**
-     * @plexus.configuration
-     */
     private boolean includeBuildSummary = true;
 
     /**
@@ -151,7 +148,7 @@
     /**
      * @plexus.configuration
      */
-    private boolean includeOutput = false;
+    private boolean includeBuildOutput = false;
 
     /**
      * Customizable mail subject.  Use any combination of literal text, project or build attributes.
@@ -163,7 +160,15 @@
      *
      * @plexus.configuration
      */
-    private String subjectFormat = "[continuum] BUILD ${state}: ${project.groupId} ${project.name}";
+    private String buildSubjectFormat = "[continuum] BUILD ${state}: ${project.groupId} ${project.name}";
+
+    /**
+     * Customizable mail subject
+     *
+     * @plexus.configuration
+     */
+    private String prepareBuildSubjectFormat =
+        "[continuum] PREPARE BUILD ${state]: ${projectScmRoot.projectGroup.name}";
 
     // ----------------------------------------------------------------------
     //
@@ -247,18 +252,28 @@
         Project project = context.getProject();
         List<ProjectNotifier> notifiers = context.getNotifiers();
         BuildResult build = context.getBuildResult();
-        String buildOutput = getBuildOutput( project, build );
+
+        if ( build != null )
+        {
+            log.error( "br state=" + build.getState() );
+        }
+
+        if ( project != null )
+        {
+            log.error( "project state=" + project.getState() );
+        }
+
         BuildDefinition buildDefinition = context.getBuildDefinition();
         ProjectScmRoot projectScmRoot = context.getProjectScmRoot();
-        
-        boolean isPrepareBuildComplete =
-            messageId.equals( ContinuumNotificationDispatcher.MESSAGE_ID_PREPARE_BUILD_COMPLETE );
-        
+
+        boolean isPrepareBuildComplete = messageId.equals(
+            ContinuumNotificationDispatcher.MESSAGE_ID_PREPARE_BUILD_COMPLETE );
+
         if ( projectScmRoot == null && isPrepareBuildComplete )
         {
             return;
         }
-        
+
         // ----------------------------------------------------------------------
         // If there wasn't any building done, don't notify
         // ----------------------------------------------------------------------
@@ -274,7 +289,7 @@
 
         if ( messageId.equals( ContinuumNotificationDispatcher.MESSAGE_ID_BUILD_COMPLETE ) )
         {
-            buildComplete( project, notifiers, build, buildOutput, messageId, context, buildDefinition );
+            buildComplete( project, notifiers, build, messageId, context, buildDefinition );
         }
         else if ( isPrepareBuildComplete )
         {
@@ -282,8 +297,8 @@
         }
     }
 
-    private void buildComplete( Project project, List<ProjectNotifier> notifiers, BuildResult build, String buildOutput,
-                                String messageId, MessageContext context, BuildDefinition buildDefinition )
+    private void buildComplete( Project project, List<ProjectNotifier> notifiers, BuildResult build, String messageId,
+                                MessageContext context, BuildDefinition buildDefinition )
         throws NotificationException
     {
         BuildResult previousBuild = getPreviousBuild( project, buildDefinition, build );
@@ -300,12 +315,12 @@
                 notifiersList.add( notifier );
             }
         }
-        buildComplete( project, notifiersList, build, previousBuild, buildOutput, messageId, context, buildDefinition );
+        buildComplete( project, notifiersList, build, previousBuild, messageId, context, buildDefinition );
     }
 
     private void buildComplete( Project project, List<ProjectNotifier> notifiers, BuildResult build,
-                                BuildResult previousBuild, String buildOutput, String messageId,
-                                MessageContext messageContext, BuildDefinition buildDefinition )
+                                BuildResult previousBuild, String messageId, MessageContext messageContext,
+                                BuildDefinition buildDefinition )
         throws NotificationException
     {
         // ----------------------------------------------------------------------
@@ -326,25 +341,26 @@
 
             context.put( "includeTestSummary", includeTestSummary );
 
-            context.put( "includeOutput", includeOutput );
+            context.put( "includeOutput", includeBuildOutput );
 
-            if ( includeBuildResult )
+            if ( includeBuildOutput )
             {
-                context.put( "buildOutput", buildOutput );
+                context.put( "buildOutput", getBuildOutput( project, build ) );
             }
 
             if ( includeBuildSummary )
             {
                 context.put( "build", build );
 
-                ReportTestResult reportTestResult =
-                    reportTestSuiteGenerator.generateReportTestResult( build.getId(), project.getId() );
+                ReportTestResult reportTestResult = reportTestSuiteGenerator.generateReportTestResult( build.getId(),
+                                                                                                       project.getId() );
 
                 context.put( "testResult", reportTestResult );
 
                 context.put( "project", project );
 
-                context.put( "changesSinceLastUpdate", continuum.getChangesSinceLastUpdate( project.getId() ) );
+                context.put( "changesSinceLastSuccess", continuum.getChangesSinceLastSuccess( project.getId(),
+                                                                                              build.getId() ) );
 
                 context.put( "previousBuild", previousBuild );
 
@@ -369,8 +385,8 @@
 
                 context.put( "osName", osName );
 
-                context.put( "javaVersion",
-                             System.getProperty( "java.version" ) + "(" + System.getProperty( "java.vendor" ) + ")" );
+                context.put( "javaVersion", System.getProperty( "java.version" ) + "(" + System.getProperty(
+                    "java.vendor" ) + ")" );
 
                 // TODO only in case of a java project ?
                 context.put( "javaHomeInformations", getJavaHomeInformations( buildDefinition ) );
@@ -422,8 +438,8 @@
         sendMessage( project, notifiers, subject, content, messageContext );
     }
 
-    private void prepareBuildComplete( ProjectScmRoot projectScmRoot, List<ProjectNotifier> notifiers, 
-                                       String messageId, MessageContext messageContext )
+    private void prepareBuildComplete( ProjectScmRoot projectScmRoot, List<ProjectNotifier> notifiers, String messageId,
+                                       MessageContext messageContext )
         throws NotificationException
     {
         // ----------------------------------------------------------------------
@@ -432,7 +448,7 @@
 
         String packageName = getClass().getPackage().getName().replace( '.', '/' );
 
-        String templateName = packageName + "/templates/"  + messageId + ".vm";
+        String templateName = packageName + "/templates/" + messageId + ".vm";
 
         StringWriter writer = new StringWriter();
 
@@ -441,18 +457,16 @@
         try
         {
             VelocityContext context = new VelocityContext();
-            
+
             // ----------------------------------------------------------------------
             // Data objects
             // ----------------------------------------------------------------------
 
-            context.put( "reportUrl", getReportUrl( projectScmRoot.getProjectGroup(), 
-                                                    projectScmRoot, configurationService ) );
-
-            context.put( "projectGroup", projectScmRoot.getProjectGroup() );
+            context.put( "reportUrl", getReportUrl( projectScmRoot.getProjectGroup(), projectScmRoot,
+                                                    configurationService ) );
 
             context.put( "projectScmRoot", projectScmRoot );
-            
+
             // TODO put other profile env var could be a security if they provide passwords ?
 
             // ----------------------------------------------------------------------
@@ -473,7 +487,7 @@
         {
             throw new NotificationException( "Error while generating mail contents.", e );
         }
-        
+
         // ----------------------------------------------------------------------
         // Send the mail
         // ----------------------------------------------------------------------
@@ -490,7 +504,7 @@
 
         sendMessage( projectScmRoot, notifiers, subject, content, messageContext );
     }
-    
+
     // ----------------------------------------------------------------------
     //
     // ----------------------------------------------------------------------
@@ -500,14 +514,14 @@
     {
         if ( buildDefinition == null )
         {
-            return continuum.getInstallationService().getDefaultJdkInformations();
+            return continuum.getInstallationService().getDefaultJavaVersionInfo();
         }
         Profile profile = buildDefinition.getProfile();
         if ( profile == null )
         {
-            return continuum.getInstallationService().getDefaultJdkInformations();
+            return continuum.getInstallationService().getDefaultJavaVersionInfo();
         }
-        return continuum.getInstallationService().getJdkInformations( profile.getJdk() );
+        return continuum.getInstallationService().getJavaVersionInfo( profile.getJdk() );
     }
 
     private List<String> getBuilderVersion( BuildDefinition buildDefinition, Project project )
@@ -533,18 +547,18 @@
             // depends on ExecutorId
             if ( MavenTwoBuildExecutor.ID.equals( project.getExecutorId() ) )
             {
-                executorConfigurator = continuum.getInstallationService()
-                    .getExecutorConfigurator( InstallationService.MAVEN2_TYPE );
+                executorConfigurator = continuum.getInstallationService().getExecutorConfigurator(
+                    InstallationService.MAVEN2_TYPE );
             }
             else if ( MavenOneBuildExecutor.ID.equals( project.getExecutorId() ) )
             {
-                executorConfigurator = continuum.getInstallationService()
-                    .getExecutorConfigurator( InstallationService.MAVEN1_TYPE );
+                executorConfigurator = continuum.getInstallationService().getExecutorConfigurator(
+                    InstallationService.MAVEN1_TYPE );
             }
             else if ( AntBuildExecutor.ID.equals( project.getExecutorId() ) )
             {
-                executorConfigurator = continuum.getInstallationService()
-                    .getExecutorConfigurator( InstallationService.ANT_TYPE );
+                executorConfigurator = continuum.getInstallationService().getExecutorConfigurator(
+                    InstallationService.ANT_TYPE );
             }
             else
             {
@@ -552,8 +566,8 @@
             }
         }
 
-        return continuum.getInstallationService().getExecutorConfiguratorVersion( builder == null ? null : builder
-            .getVarValue(), executorConfigurator, profile );
+        return continuum.getInstallationService().getExecutorVersionInfo(
+            builder == null ? null : builder.getVarValue(), executorConfigurator, profile );
     }
 
     private String generateSubject( Project project, BuildResult build )
@@ -568,25 +582,25 @@
 
         StringWriter writer = new StringWriter();
 
-        boolean velocityResults = velocity.getEngine().evaluate( context, writer, "subjectPattern", subjectFormat );
+        boolean velocityRes = velocity.getEngine().evaluate( context, writer, "subjectPattern", buildSubjectFormat );
 
         return writer.toString();
     }
-    
+
     private String generateSubject( ProjectScmRoot projectScmRoot )
         throws Exception
     {
         String state = getState( projectScmRoot );
-        subjectFormat = "[continuum] PREPARE BUILD ${state}: ${projectScmRoot.scmRootAddress}";
-        
+
         VelocityContext context = new VelocityContext();
         context.put( "projectScmRoot", projectScmRoot );
         context.put( "state", state );
-    
+
         StringWriter writer = new StringWriter();
-    
-        boolean velocityResults = velocity.getEngine().evaluate( context, writer, "subjectPattern", subjectFormat );
-    
+
+        boolean velocityResults = velocity.getEngine().evaluate( context, writer, "subjectPattern",
+                                                                 prepareBuildSubjectFormat );
+
         return writer.toString();
     }
 
@@ -618,7 +632,7 @@
             return "ERROR: Unknown build state " + state;
         }
     }
-    
+
     private String getState( ProjectScmRoot projectScmRoot )
     {
         int state = projectScmRoot.getState();
@@ -633,13 +647,14 @@
         }
         else
         {
-            log.warn( "Unknown prepare build state " + state + " for SCM Root URL " + projectScmRoot.getScmRootAddress() +
-                      " in projectGroup " + projectScmRoot.getProjectGroup().getId() );
+            log.warn(
+                "Unknown prepare build state " + state + " for SCM Root URL " + projectScmRoot.getScmRootAddress() +
+                    " in projectGroup " + projectScmRoot.getProjectGroup().getId() );
 
             return "ERROR: Unknown build state " + state;
         }
     }
-    
+
     private void sendMessage( Project project, List<ProjectNotifier> notifiers, String subject, String content,
                               MessageContext context )
         throws NotificationException
@@ -658,9 +673,8 @@
 
         if ( fromMailbox == null )
         {
-            log
-                .warn( project.getName() +
-                    ": Project is missing nag email and global from mailbox is missing, not sending mail." );
+            log.warn( project.getName() +
+                          ": Project is missing nag email and global from mailbox is missing, not sending mail." );
 
             return;
         }
@@ -690,6 +704,7 @@
 
             if ( StringUtils.isEmpty( toOverride ) )
             {
+                Set<String> listRecipents = new HashSet<String>();
                 for ( ProjectNotifier notifier : notifiers )
                 {
                     Map<String, String> conf = notifier.getConfiguration();
@@ -702,21 +717,50 @@
                             String[] addresses = StringUtils.split( addressField, "," );
                             for ( String address : addresses )
                             {
-                                // TODO: set a proper name
-                                InternetAddress to = new InternetAddress( address.trim() );
+                                if ( !listRecipents.contains( address.trim() ) )
+                                {
+                                    // [CONTINUUM-2281] Dont repeat addesss in recipents.
+                                    // TODO: set a proper name
+                                    InternetAddress to = new InternetAddress( address.trim() );
 
-                                log.info( "Recipient: To '" + to + "'." );
-                                message.addRecipient( Message.RecipientType.TO, to );
+                                    log.info( "Recipient: To '" + to + "'." );
+                                    message.addRecipient( Message.RecipientType.TO, to );
+                                    listRecipents.add( address.trim() );
+                                }
                             }
-                            
+
                         }
 
-                        String committerField = (String) notifier.getConfiguration().get( COMMITTER_FIELD );
-                        if ( StringUtils.isNotEmpty( committerField ) && context.getBuildResult() != null )
+                        if ( context.getBuildResult() != null )
                         {
-                            if ( Boolean.parseBoolean( committerField ) )
+                            String committerField = (String) notifier.getConfiguration().get( COMMITTER_FIELD );
+                            String developerField = (String) notifier.getConfiguration().get( DEVELOPER_FIELD );
+                            // Developers constains committers.
+                            if ( StringUtils.isNotEmpty( developerField ) && Boolean.parseBoolean( developerField ) )
                             {
-                                ScmResult scmResult = context.getProject().getScmResult();
+                                List<ProjectDeveloper> developers = project.getDevelopers();
+                                if ( developers == null || developers.isEmpty() )
+                                {
+                                    log.warn(
+                                        "No developers have been configured...notifcation email will not be sent" );
+                                    return;
+                                }
+                                Map<String, String> developerToEmailMap = mapDevelopersToRecipients( developers );
+                                for ( String email : developerToEmailMap.values() )
+                                {
+                                    if ( !listRecipents.contains( email.trim() ) )
+                                    {
+                                        InternetAddress to = new InternetAddress( email.trim() );
+                                        log.info( "Recipient: To '" + to + "'." );
+                                        message.addRecipient( Message.RecipientType.TO, to );
+                                        listRecipents.add( email.trim() );
+                                    }
+                                }
+                            }
+                            else if ( StringUtils.isNotEmpty( committerField ) && Boolean.parseBoolean(
+                                committerField ) )
+                            {
+                                ScmResult scmResult = context.getBuildResult().getScmResult();
                                 if ( scmResult != null && scmResult.getChanges() != null &&
                                     !scmResult.getChanges().isEmpty() )
                                 {
@@ -724,7 +768,7 @@
                                     if ( developers == null || developers.isEmpty() )
                                     {
                                         log.warn( "No developers have been configured...notifcation email " +
-                                            "will not be sent" );
+                                                      "will not be sent" );
                                         return;
                                     }
 
@@ -741,16 +785,19 @@
                                             if ( StringUtils.isEmpty( email ) )
                                             {
                                                 //TODO: Add a default domain so mail address won't be required
-                                                log.warn( "no email address is defined in developers list for '" +
-                                                    scmId + "' scm id." );
+                                                log.warn(
+                                                    "no email address is defined in developers list for '" + scmId +
+                                                        "' scm id." );
                                             }
-                                            else
+                                            else if ( !listRecipents.contains( email.trim() ) )
                                             {
+                                                // [CONTINUUM-2281] Dont repeat addesss in recipents.)
                                                 // TODO: set a proper name
                                                 InternetAddress to = new InternetAddress( email.trim() );
                                                 log.info( "Recipient: To '" + to + "'." );
 
                                                 message.addRecipient( Message.RecipientType.TO, to );
+                                                listRecipents.add( email.trim() );
                                             }
                                         }
                                     }
@@ -772,7 +819,7 @@
 
             message.setSentDate( new Date() );
 
-            if ( message.getAllRecipients() != null && ( (Address[]) message.getAllRecipients() ).length > 0 )
+            if ( message.getAllRecipients() != null && ( message.getAllRecipients() ).length > 0 )
             {
                 javaMailSender.send( message );
             }
@@ -791,12 +838,12 @@
         }
     }
 
-    private void sendMessage( ProjectScmRoot projectScmRoot, List<ProjectNotifier> notifiers, 
-                              String subject, String content, MessageContext context )
+    private void sendMessage( ProjectScmRoot projectScmRoot, List<ProjectNotifier> notifiers, String subject,
+                              String content, MessageContext context )
         throws NotificationException
     {
         ProjectGroup projectGroup = projectScmRoot.getProjectGroup();
-        
+
         if ( notifiers.size() == 0 )
         {
             // This is a useful message for the users when debugging why they don't
@@ -811,15 +858,14 @@
 
         if ( fromMailbox == null )
         {
-            log
-                .warn( projectGroup.getName() +
-                    ": ProjectGroup is missing nag email and global from mailbox is missing, not sending mail." );
+            log.warn( projectGroup.getName() +
+                          ": ProjectGroup is missing nag email and global from mailbox is missing, not sending mail." );
 
             return;
         }
 
         MimeMessage message = javaMailSender.createMimeMessage();
-        
+
         try
         {
             message.setSubject( subject );
@@ -833,7 +879,7 @@
             message.setFrom( from );
 
             log.info( "Sending message: From '" + from + "'." );
-            
+
             if ( StringUtils.isEmpty( toOverride ) )
             {
                 for ( ProjectNotifier notifier : notifiers )
@@ -842,7 +888,7 @@
                     {
                         continue;
                     }
-                    
+
                     Map<String, String> conf = notifier.getConfiguration();
                     if ( conf != null )
                     {
@@ -876,7 +922,7 @@
 
             message.setSentDate( new Date() );
 
-            if ( message.getAllRecipients() != null && ( (Address[]) message.getAllRecipients() ).length > 0 )
+            if ( message.getAllRecipients() != null && ( message.getAllRecipients() ).length > 0 )
             {
                 javaMailSender.send( message );
             }
@@ -934,7 +980,7 @@
             return FALLBACK_FROM_MAILBOX;
         }
         // olamy : CONTINUUM-860 if address contains commas we use only the first one
-        if ( address.contains( "," ) )
+        if ( address != null && address.contains( "," ) )
         {
             String[] addresses = StringUtils.split( address, "," );
             return addresses[0];
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/DefaultNotifierManager.java b/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/DefaultNotifierManager.java
index f46f88a..1961053 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/DefaultNotifierManager.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/DefaultNotifierManager.java
@@ -1,5 +1,24 @@
 package org.apache.maven.continuum.notification.manager;
 
+/*
+ * 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 org.apache.maven.continuum.notification.Notifier;
 
 import java.util.Map;
@@ -18,12 +37,12 @@
         return notifiers.get( notifierId );
     }
 
-    public Map getNotifiers()
+    public Map<String, Notifier> getNotifiers()
     {
         return notifiers;
     }
 
-    public void setNotifiers( Map notifiers )
+    public void setNotifiers( Map<String, Notifier> notifiers )
     {
         this.notifiers = notifiers;
     }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/NotifierManager.java b/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/NotifierManager.java
index 6db186f..b833eae 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/NotifierManager.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/NotifierManager.java
@@ -27,5 +27,5 @@
  */
 public interface NotifierManager
 {
-    Notifier getNotifier(String notifierId);
+    Notifier getNotifier( String notifierId );
 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/spring/NotifierFactoryBean.java b/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/spring/NotifierFactoryBean.java
index 7e099e2..3623616 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/spring/NotifierFactoryBean.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/spring/NotifierFactoryBean.java
@@ -39,7 +39,7 @@
 public class NotifierFactoryBean
     implements FactoryBean, ApplicationContextAware
 {
-    private Logger log = LoggerFactory.getLogger( getClass() );
+    private static final Logger log = LoggerFactory.getLogger( NotifierFactoryBean.class );
 
     private ApplicationContext applicationContext;
 
@@ -48,8 +48,8 @@
     {
         Map<String, Notifier> notifiers = new HashMap<String, Notifier>();
 
-        Map<String, Notifier> beans =
-            BeanFactoryUtils.beansOfTypeIncludingAncestors( applicationContext, Notifier.class );
+        Map<String, Notifier> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors( applicationContext,
+                                                                                      Notifier.class );
 
         for ( Notifier notifier : beans.values() )
         {
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/project/builder/AbstractContinuumProjectBuilder.java b/continuum-core/src/main/java/org/apache/maven/continuum/project/builder/AbstractContinuumProjectBuilder.java
index 6076c2b..969a479 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/project/builder/AbstractContinuumProjectBuilder.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/project/builder/AbstractContinuumProjectBuilder.java
@@ -21,25 +21,28 @@
 
 import org.apache.commons.io.IOUtils;
 import org.apache.http.HttpException;
+import org.apache.http.HttpHost;
 import org.apache.http.HttpResponse;
 import org.apache.http.HttpVersion;
 import org.apache.http.auth.AuthScope;
 import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.AuthCache;
 import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.protocol.ClientContext;
 import org.apache.http.conn.ClientConnectionManager;
-import org.apache.http.conn.ConnectTimeoutException;
 import org.apache.http.conn.params.ConnManagerPNames;
 import org.apache.http.conn.params.ConnPerRouteBean;
 import org.apache.http.conn.scheme.PlainSocketFactory;
 import org.apache.http.conn.scheme.Scheme;
 import org.apache.http.conn.scheme.SchemeRegistry;
-import org.apache.http.conn.scheme.SocketFactory;
-import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.impl.auth.BasicScheme;
+import org.apache.http.impl.client.BasicAuthCache;
 import org.apache.http.impl.client.DefaultHttpClient;
 import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
 import org.apache.http.params.BasicHttpParams;
 import org.apache.http.params.HttpParams;
 import org.apache.http.params.HttpProtocolParams;
+import org.apache.http.protocol.BasicHttpContext;
 import org.apache.http.util.EntityUtils;
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
@@ -54,9 +57,7 @@
 import java.io.FileWriter;
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.InetAddress;
 import java.net.MalformedURLException;
-import java.net.Socket;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
@@ -72,9 +73,11 @@
 {
     private static final String TMP_DIR = System.getProperty( "java.io.tmpdir" );
 
-    protected Logger log = LoggerFactory.getLogger( AbstractContinuumProjectBuilder.class );
+    protected final Logger log = LoggerFactory.getLogger( getClass() );
 
-    private DefaultHttpClient httpClient;
+    private HttpParams params;
+
+    private ClientConnectionManager cm;
 
     public void initialize()
         throws InitializationException
@@ -85,21 +88,21 @@
         // https scheme
         schemeRegistry.register( new Scheme( "https", new EasySSLSocketFactory(), 443 ) );
 
-        HttpParams params = new BasicHttpParams();
+        params = new BasicHttpParams();
         // TODO put this values to a configuration way ???
-        params.setParameter( ConnManagerPNames.MAX_TOTAL_CONNECTIONS, new Integer( 30 ) );
+        params.setParameter( ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 30 );
         params.setParameter( ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, new ConnPerRouteBean( 30 ) );
         HttpProtocolParams.setVersion( params, HttpVersion.HTTP_1_1 );
 
-        ClientConnectionManager cm = new ThreadSafeClientConnManager( params, schemeRegistry );
-
-        httpClient = new DefaultHttpClient( cm, params );
+        cm = new ThreadSafeClientConnManager( params, schemeRegistry );
     }
 
     protected File createMetadataFile( URL metadata, String username, String password,
                                        ContinuumProjectBuildingResult result )
         throws IOException, URISyntaxException, HttpException
     {
+        DefaultHttpClient httpClient = new DefaultHttpClient( cm, params );
+
         String url = metadata.toExternalForm();
         if ( metadata.getProtocol().startsWith( "http" ) )
         {
@@ -107,39 +110,61 @@
         }
         log.info( "Downloading " + url );
 
-        InputStream is = null;
+        InputStream is;
 
         if ( metadata.getProtocol().startsWith( "http" ) )
         {
             URI uri = metadata.toURI();
             HttpGet httpGet = new HttpGet( uri );
 
+            httpClient.getCredentialsProvider().clear();
+
             // basic auth
             if ( username != null && password != null )
             {
-                httpClient.getCredentialsProvider()
-                    .setCredentials( new AuthScope( uri.getHost(), uri.getPort() ),
-                                     new UsernamePasswordCredentials( username, password ) );
+                httpClient.getCredentialsProvider().setCredentials( new AuthScope( uri.getHost(), uri.getPort() ),
+                                                                    new UsernamePasswordCredentials( username,
+                                                                                                     password ) );
             }
 
+            // basic auth
             HttpResponse httpResponse = httpClient.execute( httpGet );
 
-            // basic auth 
+            // CONTINUUM-2627
+            if ( httpResponse.getStatusLine().getStatusCode() != 200 )
+            {
+                log.debug( "Initial attempt did not return a 200 status code. Trying pre-emptive authentication.." );
+
+                HttpHost targetHost = new HttpHost( uri.getHost(), uri.getPort(), uri.getScheme() );
+
+                // Create AuthCache instance
+                AuthCache authCache = new BasicAuthCache();
+                // Generate BASIC scheme object and add it to the local auth cache
+                BasicScheme basicAuth = new BasicScheme();
+                authCache.put( targetHost, basicAuth );
+
+                // Add AuthCache to the execution context
+                BasicHttpContext localcontext = new BasicHttpContext();
+                localcontext.setAttribute( ClientContext.AUTH_CACHE, authCache );
+
+                httpResponse = httpClient.execute( targetHost, httpGet, localcontext );
+            }
 
             int res = httpResponse.getStatusLine().getStatusCode();
+
             switch ( res )
             {
                 case 200:
                     break;
                 case 401:
-                    log.error( "Error adding project: Unauthorized " + metadata );
+                    log.error( "Error adding project: Unauthorized " + url );
                     result.addError( ContinuumProjectBuildingResult.ERROR_UNAUTHORIZED );
                     return null;
                 default:
                     log.warn( "skip non handled http return code " + res );
             }
-            is = IOUtils.toInputStream( EntityUtils.toString( httpResponse.getEntity(), EntityUtils
-                .getContentCharSet( httpResponse.getEntity() ) ) );
+            is = IOUtils.toInputStream( EntityUtils.toString( httpResponse.getEntity(), EntityUtils.getContentCharSet(
+                httpResponse.getEntity() ) ) );
         }
         else
         {
@@ -180,7 +205,6 @@
 
         File continuumTmpDir = new File( TMP_DIR, "continuum" );
 
-        // FIXME should deleted after has been reading
         File uploadDirectory = new File( continuumTmpDir, baseDirectory );
 
         uploadDirectory.deleteOnExit();
@@ -235,38 +259,45 @@
     protected File createMetadataFile( ContinuumProjectBuildingResult result, URL metadata, String username,
                                        String password )
     {
+        String url = metadata.toExternalForm();
+
+        if ( metadata.getProtocol().startsWith( "http" ) )
+        {
+            url = hidePasswordInUrl( url );
+        }
+
         try
         {
             return createMetadataFile( metadata, username, password, result );
         }
         catch ( FileNotFoundException e )
         {
-            log.info( "URL not found: " + metadata, e );
+            log.info( "URL not found: " + url, e );
             result.addError( ContinuumProjectBuildingResult.ERROR_POM_NOT_FOUND );
         }
         catch ( MalformedURLException e )
         {
-            log.info( "Malformed URL: " + metadata, e );
+            log.info( "Malformed URL: " + url, e );
             result.addError( ContinuumProjectBuildingResult.ERROR_MALFORMED_URL );
         }
         catch ( URISyntaxException e )
         {
-            log.info( "Malformed URL: " + metadata, e );
+            log.info( "Malformed URL: " + url, e );
             result.addError( ContinuumProjectBuildingResult.ERROR_MALFORMED_URL );
         }
         catch ( UnknownHostException e )
         {
-            log.info( "Unknown host: " + metadata, e );
+            log.info( "Unknown host: " + url, e );
             result.addError( ContinuumProjectBuildingResult.ERROR_UNKNOWN_HOST );
         }
         catch ( IOException e )
         {
-            log.warn( "Could not download the URL: " + metadata, e );
+            log.warn( "Could not download the URL: " + url, e );
             result.addError( ContinuumProjectBuildingResult.ERROR_UNKNOWN );
         }
         catch ( HttpException e )
         {
-            log.warn( "Could not download the URL: " + metadata, e );
+            log.warn( "Could not download the URL: " + url, e );
             result.addError( ContinuumProjectBuildingResult.ERROR_UNKNOWN );
         }
         return null;
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/project/builder/EasySSLSocketFactory.java b/continuum-core/src/main/java/org/apache/maven/continuum/project/builder/EasySSLSocketFactory.java
index 9965778..eb30ab8 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/project/builder/EasySSLSocketFactory.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/project/builder/EasySSLSocketFactory.java
@@ -19,16 +19,6 @@
  * under the License.
  */
 
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.net.UnknownHostException;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.TrustManager;
-
 import org.apache.http.conn.ConnectTimeoutException;
 import org.apache.http.conn.scheme.LayeredSocketFactory;
 import org.apache.http.conn.scheme.SocketFactory;
@@ -37,26 +27,36 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.TrustManager;
+
 /**
  * This socket factory will create ssl socket that accepts self signed certificate
+ *
  * @author olamy
- * @since 1.2.3
  * @version $Id$
+ * @since 1.2.3
  */
 public class EasySSLSocketFactory
     implements SocketFactory, LayeredSocketFactory
 {
-
-    private Logger log = LoggerFactory.getLogger( getClass() );
+    private static final Logger log = LoggerFactory.getLogger( EasySSLSocketFactory.class );
 
     private SSLContext sslcontext = null;
 
-    private static SSLContext createEasySSLContext() throws IOException
+    private static SSLContext createEasySSLContext()
+        throws IOException
     {
         try
         {
             SSLContext context = SSLContext.getInstance( "SSL" );
-            context.init( null, new TrustManager[] { new EasyX509TrustManager( null ) }, null );
+            context.init( null, new TrustManager[]{new EasyX509TrustManager( null )}, null );
             return context;
         }
         catch ( Exception e )
@@ -66,7 +66,8 @@
         }
     }
 
-    private SSLContext getSSLContext()  throws IOException
+    private SSLContext getSSLContext()
+        throws IOException
     {
         if ( this.sslcontext == null )
         {
@@ -75,10 +76,11 @@
         return this.sslcontext;
     }
 
-    /** 
+    /**
      * @see org.apache.http.conn.scheme.SocketFactory#connectSocket(java.net.Socket, java.lang.String, int, java.net.InetAddress, int, org.apache.http.params.HttpParams)
      */
-    public Socket connectSocket( Socket sock, String host, int port, InetAddress localAddress, int localPort, HttpParams params )
+    public Socket connectSocket( Socket sock, String host, int port, InetAddress localAddress, int localPort,
+                                 HttpParams params )
         throws IOException, UnknownHostException, ConnectTimeoutException
     {
         int connTimeout = HttpConnectionParams.getConnectionTimeout( params );
@@ -104,20 +106,20 @@
 
     }
 
-    /** 
+    /**
      * @see org.apache.http.conn.scheme.SocketFactory#createSocket()
      */
     public Socket createSocket()
         throws IOException
     {
-        if (log.isDebugEnabled())
+        if ( log.isDebugEnabled() )
         {
             log.debug( "create socket" );
         }
         return getSSLContext().getSocketFactory().createSocket();
     }
 
-    /** 
+    /**
      * @see org.apache.http.conn.scheme.SocketFactory#isSecure(java.net.Socket)
      */
     public boolean isSecure( Socket socket )
@@ -126,16 +128,16 @@
         return true;
     }
 
-    /** 
+    /**
      * @see org.apache.http.conn.scheme.LayeredSocketFactory#createSocket(java.net.Socket, java.lang.String, int, boolean)
      */
     public Socket createSocket( Socket socket, String host, int port, boolean autoClose )
         throws IOException, UnknownHostException
     {
-        if (log.isDebugEnabled())
+        if ( log.isDebugEnabled() )
         {
             log.debug( "create socket host " + host + ", port " + port );
-        }        
+        }
         return getSSLContext().getSocketFactory().createSocket();
     }
 
@@ -144,7 +146,7 @@
     //  Both Object.equals() and Object.hashCode() must be overridden 
     //  for the correct operation of some connection managers
     // -------------------------------------------------------------------
-    
+
     public boolean equals( Object obj )
     {
         return ( ( obj != null ) && obj.getClass().equals( EasySSLSocketFactory.class ) );
@@ -156,6 +158,4 @@
     }
 
 
-
-
 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/project/builder/EasyX509TrustManager.java b/continuum-core/src/main/java/org/apache/maven/continuum/project/builder/EasyX509TrustManager.java
index 9ad17c3..6c088a6 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/project/builder/EasyX509TrustManager.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/project/builder/EasyX509TrustManager.java
@@ -19,29 +19,29 @@
  * under the License.
  */
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import java.security.KeyStore;
 import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
-
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.TrustManagerFactory;
 import javax.net.ssl.X509TrustManager;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 /**
  * @author olamy
- * @since 1.2.3
  * @version $Id$
+ * @since 1.2.3
  */
-public class EasyX509TrustManager implements X509TrustManager
+public class EasyX509TrustManager
+    implements X509TrustManager
 {
-    private X509TrustManager standardTrustManager = null;
+    private static final Logger log = LoggerFactory.getLogger( EasyX509TrustManager.class );
 
-    private Logger log = LoggerFactory.getLogger( getClass() );
+    private X509TrustManager standardTrustManager = null;
 
     /**
      * Constructor for EasyX509TrustManager.
@@ -61,7 +61,7 @@
     }
 
     /**
-     * @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],String authType)
+     * @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[], String authType)
      */
     public void checkClientTrusted( X509Certificate[] certificates, String authType )
         throws CertificateException
@@ -70,7 +70,7 @@
     }
 
     /**
-     * @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],String authType)
+     * @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[], String authType)
      */
     public void checkServerTrusted( X509Certificate[] certificates, String authType )
         throws CertificateException
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/project/builder/manager/DefaultContinuumProjectBuilderManager.java b/continuum-core/src/main/java/org/apache/maven/continuum/project/builder/manager/DefaultContinuumProjectBuilderManager.java
index 368e7ed..21daad9 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/project/builder/manager/DefaultContinuumProjectBuilderManager.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/project/builder/manager/DefaultContinuumProjectBuilderManager.java
@@ -44,7 +44,7 @@
     public ContinuumProjectBuilder getProjectBuilder( String id )
         throws ContinuumProjectBuilderManagerException
     {
-        ContinuumProjectBuilder projectBuilder = (ContinuumProjectBuilder) projectBuilders.get( id );
+        ContinuumProjectBuilder projectBuilder = projectBuilders.get( id );
 
         if ( projectBuilder == null )
         {
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/project/builder/maven/MavenOneContinuumProjectBuilder.java b/continuum-core/src/main/java/org/apache/maven/continuum/project/builder/maven/MavenOneContinuumProjectBuilder.java
index 17c3dcd..b983e16 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/project/builder/maven/MavenOneContinuumProjectBuilder.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/project/builder/maven/MavenOneContinuumProjectBuilder.java
@@ -19,6 +19,7 @@
  * under the License.
  */
 
+import org.apache.continuum.dao.ProjectGroupDao;
 import org.apache.maven.continuum.builddefinition.BuildDefinitionService;
 import org.apache.maven.continuum.builddefinition.BuildDefinitionServiceException;
 import org.apache.maven.continuum.execution.maven.m1.MavenOneBuildExecutor;
@@ -32,11 +33,12 @@
 import org.apache.maven.continuum.project.builder.ContinuumProjectBuilder;
 import org.apache.maven.continuum.project.builder.ContinuumProjectBuilderException;
 import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
+import org.apache.maven.continuum.store.ContinuumStoreException;
 import org.codehaus.plexus.util.StringUtils;
 
 import java.io.File;
 import java.net.URL;
-import java.util.Iterator;
+import java.util.List;
 
 /**
  * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
@@ -60,6 +62,11 @@
      */
     private MavenOneMetadataHelper metadataHelper;
 
+    /**
+     * @plexus.requirement
+     */
+    private ProjectGroupDao projectGroupDao;
+
     // ----------------------------------------------------------------------
     // ProjectCreator Implementation
     // ----------------------------------------------------------------------
@@ -67,17 +74,19 @@
     public ContinuumProjectBuildingResult buildProjectsFromMetadata( URL url, String username, String password )
         throws ContinuumProjectBuilderException
     {
-        return buildProjectsFromMetadata( url, username, password, true );
+        return buildProjectsFromMetadata( url, username, password, true, false );
     }
 
     public ContinuumProjectBuildingResult buildProjectsFromMetadata( URL url, String username, String password,
-                                                                     boolean recursiveProjects )
+                                                                     boolean recursiveProjects,
+                                                                     boolean checkoutInSingleDirectory )
         throws ContinuumProjectBuilderException
     {
         try
         {
-            return buildProjectsFromMetadata( url, username, password, recursiveProjects, buildDefinitionService
-                .getDefaultMavenOneBuildDefinitionTemplate() );
+            return buildProjectsFromMetadata( url, username, password, recursiveProjects,
+                                              buildDefinitionService.getDefaultMavenOneBuildDefinitionTemplate(),
+                                              false );
         }
         catch ( BuildDefinitionServiceException e )
         {
@@ -87,9 +96,40 @@
 
     public ContinuumProjectBuildingResult buildProjectsFromMetadata( URL url, String username, String password,
                                                                      boolean recursiveProjects,
-                                                                     BuildDefinitionTemplate buildDefinitionTemplate )
+                                                                     BuildDefinitionTemplate buildDefinitionTemplate,
+                                                                     boolean checkoutInSingleDirectory )
         throws ContinuumProjectBuilderException
     {
+        return buildProjectsFromMetadata( url, username, password, buildDefinitionTemplate, null );
+    }
+
+    public ContinuumProjectBuildingResult buildProjectsFromMetadata( URL url, String username, String password,
+                                                                     boolean recursiveProjects,
+                                                                     BuildDefinitionTemplate buildDefinitionTemplate,
+                                                                     boolean checkoutInSingleDirectory,
+                                                                     int projectGroupId )
+        throws ContinuumProjectBuilderException
+    {
+        ProjectGroup projectGroup = null;
+        if ( projectGroupId > 0 )
+        {
+            try
+            {
+                projectGroup = projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId( projectGroupId );
+            }
+            catch ( ContinuumStoreException e )
+            {
+                throw new ContinuumProjectBuilderException( e.getMessage(), e );
+            }
+        }
+
+        return buildProjectsFromMetadata( url, username, password, buildDefinitionTemplate, projectGroup );
+    }
+
+    private ContinuumProjectBuildingResult buildProjectsFromMetadata( URL url, String username, String password,
+                                                                      BuildDefinitionTemplate buildDefinitionTemplate,
+                                                                      ProjectGroup projectGroup )
+    {
         ContinuumProjectBuildingResult result = new ContinuumProjectBuildingResult();
 
         File pomFile;
@@ -105,17 +145,17 @@
 
         try
         {
-            metadataHelper.mapMetadata( result, pomFile, project );
+            metadataHelper.mapMetadata( result, pomFile, project, true );
 
             if ( result.hasErrors() )
             {
                 return result;
             }
-            for ( Iterator<BuildDefinition> iterator = buildDefinitionTemplate.getBuildDefinitions().iterator();
-                  iterator
-                      .hasNext(); )
+            for ( BuildDefinition bd : (List<BuildDefinition>) buildDefinitionTemplate.getBuildDefinitions() )
             {
-                project.addBuildDefinition( iterator.next() );
+                BuildDefinition cloneBuildDefinition = buildDefinitionService.cloneBuildDefinition( bd );
+                cloneBuildDefinition.setTemplate( false );
+                project.addBuildDefinition( cloneBuildDefinition );
             }
             result.addProject( project, MavenOneBuildExecutor.ID );
         }
@@ -127,44 +167,47 @@
         }
         finally
         {
-            if ( pomFile != null && pomFile.exists() )
+            if ( pomFile.exists() )
             {
                 pomFile.delete();
             }
-        }        
-
-        ProjectGroup projectGroup = new ProjectGroup();
-
-        // ----------------------------------------------------------------------
-        // Group id
-        // ----------------------------------------------------------------------
-
-        if ( StringUtils.isEmpty( project.getGroupId() ) )
-        {
-            result.addError( ContinuumProjectBuildingResult.ERROR_MISSING_GROUPID );
         }
 
-        projectGroup.setGroupId( project.getGroupId() );
-
-        // ----------------------------------------------------------------------
-        // Name
-        // ----------------------------------------------------------------------
-
-        String name = project.getName();
-
-        if ( StringUtils.isEmpty( name ) )
+        if ( projectGroup == null )
         {
-            name = project.getGroupId();
+            projectGroup = new ProjectGroup();
+
+            // ----------------------------------------------------------------------
+            // Group id
+            // ----------------------------------------------------------------------
+
+            if ( StringUtils.isEmpty( project.getGroupId() ) )
+            {
+                result.addError( ContinuumProjectBuildingResult.ERROR_MISSING_GROUPID );
+            }
+
+            projectGroup.setGroupId( project.getGroupId() );
+
+            // ----------------------------------------------------------------------
+            // Name
+            // ----------------------------------------------------------------------
+
+            String name = project.getName();
+
+            if ( StringUtils.isEmpty( name ) )
+            {
+                name = project.getGroupId();
+            }
+
+            projectGroup.setName( name );
+
+            // ----------------------------------------------------------------------
+            // Description
+            // ----------------------------------------------------------------------
+
+            projectGroup.setDescription( project.getDescription() );
         }
 
-        projectGroup.setName( name );
-
-        // ----------------------------------------------------------------------
-        // Description
-        // ----------------------------------------------------------------------
-
-        projectGroup.setDescription( project.getDescription() );
-
         result.addProjectGroup( projectGroup );
 
         return result;
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/project/builder/maven/MavenTwoContinuumProjectBuilder.java b/continuum-core/src/main/java/org/apache/maven/continuum/project/builder/maven/MavenTwoContinuumProjectBuilder.java
index 89d9364..2aed974 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/project/builder/maven/MavenTwoContinuumProjectBuilder.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/project/builder/maven/MavenTwoContinuumProjectBuilder.java
@@ -19,21 +19,10 @@
  * under the License.
  */
 
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.net.ConnectException;
-import java.net.MalformedURLException;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
 import org.apache.continuum.dao.LocalRepositoryDao;
+import org.apache.continuum.dao.ProjectGroupDao;
 import org.apache.continuum.dao.ScheduleDao;
 import org.apache.continuum.model.repository.LocalRepository;
-import org.apache.http.HttpException;
 import org.apache.maven.continuum.builddefinition.BuildDefinitionService;
 import org.apache.maven.continuum.builddefinition.BuildDefinitionServiceException;
 import org.apache.maven.continuum.configuration.ConfigurationService;
@@ -52,6 +41,12 @@
 import org.apache.maven.project.MavenProject;
 import org.codehaus.plexus.util.StringUtils;
 
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
  * @version $Id$
@@ -90,23 +85,32 @@
      */
     private List<String> excludedPackagingTypes = new ArrayList<String>();
 
+    private Project rootProject;
+
+    /**
+     * @plexus.requirement
+     */
+    private ProjectGroupDao projectGroupDao;
+
     // ----------------------------------------------------------------------
     // AbstractContinuumProjectBuilder Implementation
     // ----------------------------------------------------------------------
     public ContinuumProjectBuildingResult buildProjectsFromMetadata( URL url, String username, String password )
         throws ContinuumProjectBuilderException
     {
-        return buildProjectsFromMetadata( url, username, password, true );
+        return buildProjectsFromMetadata( url, username, password, true, false );
     }
 
     public ContinuumProjectBuildingResult buildProjectsFromMetadata( URL url, String username, String password,
-                                                                     boolean loadRecursiveProjects )
+                                                                     boolean loadRecursiveProjects,
+                                                                     boolean checkoutInSingleDirectory )
         throws ContinuumProjectBuilderException
     {
         try
         {
-            return buildProjectsFromMetadata( url, username, password, loadRecursiveProjects, buildDefinitionService
-                .getDefaultMavenTwoBuildDefinitionTemplate() );
+            return buildProjectsFromMetadata( url, username, password, loadRecursiveProjects,
+                                              buildDefinitionService.getDefaultMavenTwoBuildDefinitionTemplate(),
+                                              checkoutInSingleDirectory );
         }
         catch ( BuildDefinitionServiceException e )
         {
@@ -116,7 +120,18 @@
 
     public ContinuumProjectBuildingResult buildProjectsFromMetadata( URL url, String username, String password,
                                                                      boolean loadRecursiveProjects,
-                                                                     BuildDefinitionTemplate buildDefinitionTemplate )
+                                                                     BuildDefinitionTemplate buildDefinitionTemplate,
+                                                                     boolean checkoutInSingleDirectory )
+        throws ContinuumProjectBuilderException
+    {
+        return buildProjectsFromMetadata( url, username, password, loadRecursiveProjects, buildDefinitionTemplate, checkoutInSingleDirectory, -1 );
+    }
+
+    public ContinuumProjectBuildingResult buildProjectsFromMetadata( URL url, String username, String password,
+                                                                     boolean loadRecursiveProjects,
+                                                                     BuildDefinitionTemplate buildDefinitionTemplate,
+                                                                     boolean checkoutInSingleDirectory,
+                                                                     int projectGroupId )
         throws ContinuumProjectBuilderException
     {
         // ----------------------------------------------------------------------
@@ -127,12 +142,23 @@
 
         try
         {
-            readModules( url, result, true, username, password, null, loadRecursiveProjects, buildDefinitionTemplate );
+            ProjectGroup projectGroup = null;
+            if ( projectGroupId > 0 )
+            {
+                projectGroup = projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId( projectGroupId );
+            }
+
+            readModules( url, result, projectGroup, username, password, null, loadRecursiveProjects, buildDefinitionTemplate,
+                         checkoutInSingleDirectory );
         }
         catch ( BuildDefinitionServiceException e )
         {
             throw new ContinuumProjectBuilderException( e.getMessage(), e );
         }
+        catch ( ContinuumStoreException e )
+        {
+            throw new ContinuumProjectBuilderException( e.getMessage(), e );
+        }
         return result;
     }
 
@@ -140,9 +166,9 @@
     //
     // ----------------------------------------------------------------------
 
-    private void readModules( URL url, ContinuumProjectBuildingResult result, boolean groupPom, String username,
+    private void readModules( URL url, ContinuumProjectBuildingResult result, ProjectGroup projectGroup, String username,
                               String password, String scmUrl, boolean loadRecursiveProjects,
-                              BuildDefinitionTemplate buildDefinitionTemplate )
+                              BuildDefinitionTemplate buildDefinitionTemplate, boolean checkoutInSingleDirectory )
         throws ContinuumProjectBuilderException, BuildDefinitionServiceException
     {
 
@@ -152,13 +178,13 @@
 
         try
         {
-            pomFile = createMetadataFile( url, username, password, result );
-            
+            pomFile = createMetadataFile( result, url, username, password );
+
             if ( result.hasErrors() )
             {
                 return;
             }
-            
+
             mavenProject = builderHelper.getMavenProject( result, pomFile );
 
             if ( result.hasErrors() )
@@ -166,42 +192,6 @@
                 return;
             }
         }
-        catch ( MalformedURLException e )
-        {
-            log.debug( "Error adding project: Malformed URL " + url, e );
-            result.addError( ContinuumProjectBuildingResult.ERROR_MALFORMED_URL );
-            return;
-        }
-        catch ( URISyntaxException e )
-        {
-            log.debug( "Error adding project: Malformed URL " + url, e );
-            result.addError( ContinuumProjectBuildingResult.ERROR_MALFORMED_URL );
-            return;
-        }        
-        catch ( FileNotFoundException e )
-        {
-            log.debug( "Error adding project: File not found " + url, e );
-            result.addError( ContinuumProjectBuildingResult.ERROR_POM_NOT_FOUND );
-            return;
-        }
-        catch ( ConnectException e )
-        {
-            log.debug( "Error adding project: Unable to connect " + url, e );
-            result.addError( ContinuumProjectBuildingResult.ERROR_CONNECT );
-            return;
-        }
-        catch ( IOException e )
-        {
-            log.info( "Error adding project: Unknown error downloading from " + url, e );
-            result.addError( ContinuumProjectBuildingResult.ERROR_UNKNOWN );
-            return;
-        }
-        catch ( HttpException e )
-        {
-            log.info( "Error adding project: Unknown error downloading from " + url, e );
-            result.addError( ContinuumProjectBuildingResult.ERROR_UNKNOWN );
-            return;
-        }        
         finally
         {
             if ( pomFile != null && pomFile.exists() )
@@ -209,59 +199,32 @@
                 pomFile.delete();
             }
         }
-        log.debug( "groupPom " + groupPom );
-        if ( groupPom )
+        log.debug( "projectGroup " + projectGroup );
+
+        if ( projectGroup == null )
         {
-            ProjectGroup projectGroup = buildProjectGroup( mavenProject, result );
+            projectGroup = buildProjectGroup( mavenProject, result );
 
             // project groups have the top lvl build definition which is the default build defintion for the sub
             // projects
             log.debug( "projectGroup != null" + ( projectGroup != null ) );
             if ( projectGroup != null )
             {
-                List<BuildDefinition> buildDefinitions =
-                    getBuildDefinitions( buildDefinitionTemplate, loadRecursiveProjects );
-                boolean defaultSetted = false;
+                List<BuildDefinition> buildDefinitions = getBuildDefinitions( buildDefinitionTemplate,
+                                                                              loadRecursiveProjects,
+                                                                              mavenProject.getBuild().getDefaultGoal() );
                 for ( BuildDefinition buildDefinition : buildDefinitions )
                 {
-                    if ( !defaultSetted && buildDefinition.isDefaultForProject() )
-                    {
-                        buildDefinition.setDefaultForProject( true );
-                        defaultSetted = true;
-                    }
-                    buildDefinition = buildDefinitionService.addBuildDefinition(
-                        buildDefinitionService.cloneBuildDefinition( buildDefinition ) );
-                    //CONTINUUM-1296
-                    String defaultGoal = mavenProject.getBuild().getDefaultGoal();
-                    if ( StringUtils.isNotEmpty( defaultGoal ) )
-                    {
-                        buildDefinition.setGoals( defaultGoal );
-                    }
-                    if ( buildDefinition.getSchedule() == null )
-                    {
-                        try
-                        {
-                            Schedule schedule =
-                                scheduleDao.getScheduleByName( ConfigurationService.DEFAULT_SCHEDULE_NAME );
-
-                            buildDefinition.setSchedule( schedule );
-                        }
-                        catch ( ContinuumStoreException e )
-                        {
-                            log.warn( "Can't get default schedule.", e );
-                        }
-                    }
-                    // jdo complains that Collections.singletonList(bd) is a second class object and fails.
-                    //ArrayList arrayList = new ArrayList();
-
-                    //arrayList.add( buildDefinition );
+                    buildDefinition = persistBuildDefinition( buildDefinition );
 
                     projectGroup.addBuildDefinition( buildDefinition );
-                    // .setBuildDefinitions( arrayList );
                 }
-                result.addProjectGroup( projectGroup );
             }
         }
+        if ( result.getProjectGroups().isEmpty() )
+        {
+            result.addProjectGroup( projectGroup );
+        }
 
         if ( !excludedPackagingTypes.contains( mavenProject.getPackaging() ) )
         {
@@ -281,7 +244,10 @@
                 }
             }
 
-            builderHelper.mapMavenProjectToContinuumProject( result, mavenProject, continuumProject, groupPom );
+            continuumProject.setCheckedOutInSingleDirectory( checkoutInSingleDirectory );
+
+            // New project
+            builderHelper.mapMavenProjectToContinuumProject( result, mavenProject, continuumProject, true );
 
             if ( result.hasErrors() )
             {
@@ -305,7 +271,46 @@
             {
                 continuumProject.setScmTag( mavenProject.getScm().getTag() );
             }
+
+            // CONTINUUM-2563
+            // Don't create if the project has a build definition template assigned to it already
+            if ( !loadRecursiveProjects && buildDefinitionTemplate.equals( getDefaultBuildDefinitionTemplate() ) )
+            {
+                List<BuildDefinition> buildDefinitions = projectGroup.getBuildDefinitions();
+                for ( BuildDefinition buildDefinition : buildDefinitions )
+                {
+                    if ( buildDefinition.isDefaultForProject() )
+                    {
+                        // create a default build definition at the project level
+                        BuildDefinition projectBuildDef = buildDefinitionService.cloneBuildDefinition( buildDefinition );
+                        projectBuildDef.setDefaultForProject( true );
+
+                        String arguments = projectBuildDef.getArguments().replace( "--non-recursive", "" );
+                        arguments = arguments.replace( "-N", "" );
+                        arguments = arguments.trim();
+
+                        // add build definition only if it differs
+                        if ( !projectBuildDef.getArguments().equals( arguments ) )
+                        {
+                            log.info( "Adding default build definition for project '" + continuumProject.getName() +
+                                          "' without '--non-recursive' flag." );
+
+                            projectBuildDef.setArguments( arguments );
+                            continuumProject.addBuildDefinition( projectBuildDef );
+                        }
+
+                        break;
+                    }
+                }
+            }
+
             result.addProject( continuumProject, MavenTwoBuildExecutor.ID );
+
+            if ( checkoutInSingleDirectory && rootProject == null )
+            {
+                rootProject = continuumProject;
+                result.setRootProject( rootProject );
+            }
         }
 
         List<String> modules = mavenProject.getModules();
@@ -342,6 +347,7 @@
 
                     try
                     {
+                        urlString = StringUtils.replace( urlString, '\\', '/' );
                         moduleUrl = new URL( urlString );
                     }
                     catch ( MalformedURLException e )
@@ -351,29 +357,85 @@
                         continue;
                     }
 
-                    String moduleScmUrl;
-                    if ( scmUrl.endsWith( "/" ) )
+                    String moduleScmUrl = "";
+
+                    String modulePath = StringUtils.replace( new String( module ), '\\', '/' );
+
+                    // check if module is relative
+                    if ( modulePath.indexOf( "../" ) != -1 )
                     {
-                        moduleScmUrl = scmUrl + module;
+                        int depth = StringUtils.countMatches( StringUtils.substring( modulePath, 0,
+                                                                                     modulePath.lastIndexOf( '/' ) +
+                                                                                         1 ), "/" );
+
+                        String baseUrl = "";
+                        for ( int j = 1; j <= depth; j++ )
+                        {
+                            scmUrl = StringUtils.chompLast( new String( scmUrl ), "/" );
+                            baseUrl = StringUtils.substring( scmUrl, 0, scmUrl.lastIndexOf( '/' ) );
+                        }
+                        moduleScmUrl = baseUrl + "/" + StringUtils.substring( modulePath, modulePath.lastIndexOf(
+                            "../" ) + 3 );
                     }
                     else
                     {
-                        moduleScmUrl = scmUrl + "/" + module;
+                        scmUrl = StringUtils.chompLast( scmUrl, "/" );
+                        moduleScmUrl = scmUrl + "/" + modulePath;
                     }
                     // we are in recursive loading mode
-                    readModules( moduleUrl, result, false, username, password, moduleScmUrl, true,
-                                 buildDefinitionTemplate );
+                    readModules( moduleUrl, result, projectGroup, username, password, moduleScmUrl, true,
+                                 buildDefinitionTemplate, checkoutInSingleDirectory );
                 }
             }
         }
     }
 
-    private List<BuildDefinition> getBuildDefinitions( BuildDefinitionTemplate template, boolean loadRecursiveProjects )
+    private BuildDefinition persistBuildDefinition( BuildDefinition buildDefinition )
+        throws BuildDefinitionServiceException
+    {
+        buildDefinition = buildDefinitionService.addBuildDefinition( buildDefinition );
+        if ( buildDefinition.getSchedule() == null )
+        {
+            try
+            {
+                Schedule schedule = scheduleDao.getScheduleByName(
+                    ConfigurationService.DEFAULT_SCHEDULE_NAME );
+
+                buildDefinition.setSchedule( schedule );
+            }
+            catch ( ContinuumStoreException e )
+            {
+                log.warn( "Can't get default schedule.", e );
+            }
+        }
+        return buildDefinition;
+    }
+
+    private List<BuildDefinition> getBuildDefinitions( BuildDefinitionTemplate template, boolean loadRecursiveProjects,
+                                                       String defaultGoal )
         throws ContinuumProjectBuilderException, BuildDefinitionServiceException
     {
         List<BuildDefinition> buildDefinitions = new ArrayList<BuildDefinition>();
-        for ( BuildDefinition buildDefinition : (List<BuildDefinition>) template.getBuildDefinitions() )
+        boolean defaultSet = false;
+        for ( BuildDefinition buildDefinition : template.getBuildDefinitions() )
         {
+            buildDefinition = buildDefinitionService.cloneBuildDefinition( buildDefinition );
+
+            if ( !defaultSet && buildDefinition.isDefaultForProject() )
+            {
+                defaultSet = true;
+
+                //CONTINUUM-1296
+                if ( StringUtils.isNotEmpty( defaultGoal ) )
+                {
+                    buildDefinition.setGoals( defaultGoal );
+                }
+            }
+            else
+            {
+                buildDefinition.setDefaultForProject( false );
+            }
+
             // due to CONTINUUM-1207 CONTINUUM-1436 user can do what they want with arguments
             // we must remove if exists --non-recursive or -N
             if ( !loadRecursiveProjects )
@@ -381,12 +443,13 @@
                 if ( StringUtils.isEmpty( buildDefinition.getArguments() ) )
                 {
                     // strange for a mvn build 
-                    log.info( "build definition has empty args" );
+                    log.info( "build definition '" + buildDefinition.getId() + "' has empty args" );
                 }
                 else
                 {
                     String arguments = buildDefinition.getArguments().replace( "--non-recursive", "" );
                     arguments = arguments.replace( "-N", "" );
+                    arguments = arguments.trim();
                     buildDefinition.setArguments( arguments );
                 }
             }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/scheduler/ContinuumBuildJob.java b/continuum-core/src/main/java/org/apache/maven/continuum/scheduler/ContinuumBuildJob.java
index a5a54b5..595b831 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/scheduler/ContinuumBuildJob.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/scheduler/ContinuumBuildJob.java
@@ -22,10 +22,10 @@
 import org.apache.maven.continuum.Continuum;
 import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.model.project.Schedule;
-import org.codehaus.plexus.logging.Logger;
 import org.codehaus.plexus.scheduler.AbstractJob;
 import org.quartz.JobDetail;
 import org.quartz.JobExecutionContext;
+import org.slf4j.Logger;
 
 /**
  * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
@@ -34,6 +34,8 @@
 public class ContinuumBuildJob
     extends AbstractJob
 {
+    public static final String BUILD_GROUP = "BUILD_GROUP";
+
     public void execute( JobExecutionContext context )
     {
         if ( isInterrupted() )
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/scheduler/ContinuumPurgeJob.java b/continuum-core/src/main/java/org/apache/maven/continuum/scheduler/ContinuumPurgeJob.java
index 879f857..720d52b 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/scheduler/ContinuumPurgeJob.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/scheduler/ContinuumPurgeJob.java
@@ -23,10 +23,10 @@
 import org.apache.continuum.purge.ContinuumPurgeManagerException;
 import org.apache.maven.continuum.Continuum;
 import org.apache.maven.continuum.model.project.Schedule;
-import org.codehaus.plexus.logging.Logger;
 import org.codehaus.plexus.scheduler.AbstractJob;
 import org.quartz.JobDetail;
 import org.quartz.JobExecutionContext;
+import org.slf4j.Logger;
 
 /**
  * @author Maria Catherine Tan
@@ -36,6 +36,8 @@
 public class ContinuumPurgeJob
     extends AbstractJob
 {
+    public static final String PURGE_GROUP = "PURGE_GROUP";
+
     public void execute( JobExecutionContext context )
     {
         if ( isInterrupted() )
@@ -62,7 +64,7 @@
         Continuum continuum = (Continuum) jobDetail.getJobDataMap().get( ContinuumSchedulerConstants.CONTINUUM );
 
         ContinuumPurgeManager purgeManager = continuum.getPurgeManager();
-        
+
         Schedule schedule = (Schedule) jobDetail.getJobDataMap().get( ContinuumSchedulerConstants.SCHEDULE );
 
         try
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/scm/queue/CheckOutTaskExecutor.java b/continuum-core/src/main/java/org/apache/maven/continuum/scm/queue/CheckOutTaskExecutor.java
index eba1d14..743fa93 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/scm/queue/CheckOutTaskExecutor.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/scm/queue/CheckOutTaskExecutor.java
@@ -22,6 +22,7 @@
 import org.apache.continuum.dao.ProjectDao;
 import org.apache.continuum.taskqueue.CheckOutTask;
 import org.apache.maven.continuum.core.action.AbstractContinuumAction;
+import org.apache.maven.continuum.core.action.CheckoutProjectContinuumAction;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.store.ContinuumStoreException;
 import org.codehaus.plexus.action.ActionManager;
@@ -38,12 +39,12 @@
  * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
  * @version $Id$
  * @plexus.component role="org.codehaus.plexus.taskqueue.execution.TaskExecutor"
- * role-hint="check-out-project"
+ * role-hint="check-out-project" instantiation-strategy="per-lookup"
  */
 public class CheckOutTaskExecutor
     implements TaskExecutor
 {
-    private Logger log = LoggerFactory.getLogger( CheckOutTaskExecutor.class );
+    private static final Logger log = LoggerFactory.getLogger( CheckOutTaskExecutor.class );
 
     /**
      * @plexus.requirement
@@ -62,6 +63,8 @@
     public void executeTask( Task t )
         throws TaskExecutionException
     {
+        log.info( "Checkout task executor.." );
+
         CheckOutTask task = (CheckOutTask) t;
 
         int projectId = task.getProjectId();
@@ -83,15 +86,20 @@
 
         Map<String, Object> context = new HashMap<String, Object>();
 
-        context.put( AbstractContinuumAction.KEY_PROJECT_ID, new Integer( projectId ) );
+        AbstractContinuumAction.setProjectId( context, projectId );
 
-        context.put( AbstractContinuumAction.KEY_PROJECT, project );
+        AbstractContinuumAction.setProject( context, project );
 
-        context.put( AbstractContinuumAction.KEY_WORKING_DIRECTORY, workingDirectory );
+        AbstractContinuumAction.setWorkingDirectory( context, workingDirectory );
 
-        context.put( AbstractContinuumAction.KEY_SCM_USERNAME, task.getScmUserName() );
+        CheckoutProjectContinuumAction.setScmUsername( context, task.getScmUserName() );
 
-        context.put( AbstractContinuumAction.KEY_SCM_PASSWORD, task.getScmPassword() );
+        CheckoutProjectContinuumAction.setScmPassword( context, task.getScmPassword() );
+
+        AbstractContinuumAction.setProjectScmRootUrl( context, task.getScmRootUrl() );
+
+        AbstractContinuumAction.setListOfProjectsInGroupWithCommonScmRoot( context,
+                                                                           task.getProjectsWithCommonScmRoot() );
 
         try
         {
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/scm/queue/PrepareBuildProjectsTaskExecutor.java b/continuum-core/src/main/java/org/apache/maven/continuum/scm/queue/PrepareBuildProjectsTaskExecutor.java
index f25c09d..c0c3a8e 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/scm/queue/PrepareBuildProjectsTaskExecutor.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/scm/queue/PrepareBuildProjectsTaskExecutor.java
@@ -19,19 +19,22 @@
  * under the License.
  */
 
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
 import org.apache.continuum.dao.BuildDefinitionDao;
+import org.apache.continuum.dao.BuildResultDao;
 import org.apache.continuum.dao.ProjectDao;
+import org.apache.continuum.dao.ProjectGroupDao;
 import org.apache.continuum.dao.ProjectScmRootDao;
 import org.apache.continuum.model.project.ProjectScmRoot;
 import org.apache.continuum.taskqueue.PrepareBuildProjectsTask;
 import org.apache.continuum.utils.ContinuumUtils;
 import org.apache.continuum.utils.ProjectSorter;
+import org.apache.continuum.utils.build.BuildTrigger;
 import org.apache.maven.continuum.core.action.AbstractContinuumAction;
+import org.apache.maven.continuum.core.action.CheckWorkingDirectoryAction;
+import org.apache.maven.continuum.core.action.CheckoutProjectContinuumAction;
+import org.apache.maven.continuum.core.action.UpdateWorkingDirectoryFromScmContinuumAction;
+import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.BuildResult;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.project.ProjectGroup;
 import org.apache.maven.continuum.model.scm.ChangeSet;
@@ -46,10 +49,16 @@
 import org.codehaus.plexus.taskqueue.execution.TaskExecutionException;
 import org.codehaus.plexus.taskqueue.execution.TaskExecutor;
 import org.codehaus.plexus.util.StringUtils;
-import org.codehaus.plexus.util.dag.CycleDetectedException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 /**
  * @author <a href="mailto:ctan@apache.org">Maria Catherine Tan</a>
  * @version $Id$
@@ -59,7 +68,7 @@
 public class PrepareBuildProjectsTaskExecutor
     implements TaskExecutor
 {
-    private Logger log = LoggerFactory.getLogger( PrepareBuildProjectsTaskExecutor.class );
+    private static final Logger log = LoggerFactory.getLogger( PrepareBuildProjectsTaskExecutor.class );
 
     /**
      * @plexus.requirement
@@ -70,17 +79,22 @@
      * @plexus.requirement
      */
     private ProjectDao projectDao;
-    
+
     /**
      * @plexus.requirement
      */
     private BuildDefinitionDao buildDefinitionDao;
-    
+
     /**
      * @plexus.requirement
      */
     private ProjectScmRootDao projectScmRootDao;
-    
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildResultDao buildResultDao;
+
     /**
      * @plexus.requirement
      */
@@ -91,63 +105,104 @@
      */
     private ContinuumNotificationDispatcher notifierDispatcher;
 
+    /**
+     * @plexus.requirement
+     */
+    private ProjectGroupDao projectGroupDao;
+
     public void executeTask( Task task )
         throws TaskExecutionException
     {
         PrepareBuildProjectsTask prepareTask = (PrepareBuildProjectsTask) task;
-        
+
         Map<Integer, Integer> projectsBuildDefinitionsMap = prepareTask.getProjectsBuildDefinitionsMap();
-        int trigger = prepareTask.getTrigger();
+        BuildTrigger buildTrigger = prepareTask.getBuildTrigger();
         Set<Integer> projectsId = projectsBuildDefinitionsMap.keySet();
-        Map context = new HashMap();
+        Map<String, Object> context = new HashMap<String, Object>();
+        Map<Integer, ScmResult> scmResultMap = new HashMap<Integer, ScmResult>();
+        List<Project> projectList = new ArrayList<Project>();
+        int projectGroupId = 0;
 
         try
         {
-            for ( Integer projectId : projectsId )
+            if ( !projectsId.isEmpty() )
             {
-                int buildDefinitionId = projectsBuildDefinitionsMap.get( projectId );
-                
-                log.info( "Initializing prepare build" );
-                context = initializeContext( projectId, buildDefinitionId );
+                int projectId = projectsId.iterator().next();
+                Project project = projectDao.getProject( projectId );
+                ProjectGroup projectGroup = project.getProjectGroup();
+                projectGroupId = projectGroup.getId();
 
-                if ( !checkProjectScmRoot( context ) )
+                List<Project> projects = projectDao.getProjectsWithDependenciesByGroupId( projectGroupId );
+                projectList = ProjectSorter.getSortedProjects( projects, log );
+            }
+
+            Project rootProject = null;
+
+            for ( Project project : projectList )
+            {
+                if ( rootProject == null )
                 {
-                    break;
+                    // first project is the root project.
+                    rootProject = project;
                 }
 
-                log.info( "Starting prepare build of project: " + AbstractContinuumAction.getProject( context ).getName() );
-                startPrepareBuild( context );
+                int projectId = project.getId();
+                int buildDefinitionId;
 
-                try
+                if ( projectsBuildDefinitionsMap.get( projectId ) != null )
                 {
-                    if ( AbstractContinuumAction.getBuildDefinition( context ).isBuildFresh() )
+                    buildDefinitionId = projectsBuildDefinitionsMap.get( projectId );
+
+                    log.info( "Initializing prepare build" );
+                    context = initializeContext( project, buildDefinitionId, prepareTask.getBuildTrigger() );
+
+                    log.info( "Starting prepare build of project: " + AbstractContinuumAction.getProject(
+                        context ).getName() );
+                    startPrepareBuild( context );
+
+                    if ( !checkProjectScmRoot( context ) )
                     {
-                        log.info( "Purging existing working copy" );
-                        cleanWorkingDirectory( context );
+                        break;
                     }
 
-                    // ----------------------------------------------------------------------
-                    // TODO: Centralize the error handling from the SCM related actions.
-                    // ContinuumScmResult should return a ContinuumScmResult from all
-                    // methods, even in a case of failure.
-                    // ----------------------------------------------------------------------
-                    log.info( "Updating working dir" );
-                    updateWorkingDirectory( context );
-
-                    log.info( "Merging SCM results" );
-                    //CONTINUUM-1393
-                    if ( !AbstractContinuumAction.getBuildDefinition( context ).isBuildFresh() )
+                    try
                     {
-                        mergeScmResults( context );
+                        if ( AbstractContinuumAction.getBuildDefinition( context ).isBuildFresh() )
+                        {
+                            log.info( "Purging existing working copy" );
+                            cleanWorkingDirectory( context );
+                        }
+
+                        // ----------------------------------------------------------------------
+                        // TODO: Centralize the error handling from the SCM related actions.
+                        // ContinuumScmResult should return a ContinuumScmResult from all
+                        // methods, even in a case of failure.
+                        // ----------------------------------------------------------------------
+                        log.info( "Updating working dir" );
+                        updateWorkingDirectory( context, rootProject );
+
+                        log.info( "Merging SCM results" );
+                        //CONTINUUM-1393
+                        if ( !AbstractContinuumAction.getBuildDefinition( context ).isBuildFresh() )
+                        {
+                            mergeScmResults( context );
+                        }
                     }
-                }
-                finally
-                {
-                    log.info( "Ending prepare build of project: " + AbstractContinuumAction.getProject( context).getName() );
-                    endProjectPrepareBuild( context );
+                    finally
+                    {
+                        log.info( "Ending prepare build of project: " + AbstractContinuumAction.getProject(
+                            context ).getName() );
+                        scmResultMap.put( AbstractContinuumAction.getProjectId( context ),
+                                          AbstractContinuumAction.getScmResult( context, null ) );
+                        endProjectPrepareBuild( context );
+                    }
                 }
             }
         }
+        catch ( ContinuumStoreException e )
+        {
+            throw new TaskExecutionException( "Failed to prepare build project group: " + projectGroupId, e );
+        }
         finally
         {
             log.info( "Ending prepare build" );
@@ -156,102 +211,175 @@
 
         if ( checkProjectScmRoot( context ) )
         {
-            int projectGroupId = AbstractContinuumAction.getProjectGroupId( context );
-            buildProjects( projectGroupId, projectsBuildDefinitionsMap, trigger );
+            projectGroupId = AbstractContinuumAction.getProjectGroupId( context );
+            buildProjects( projectGroupId, projectList, projectsBuildDefinitionsMap, buildTrigger, scmResultMap );
         }
     }
 
-    private Map initializeContext( int projectId, int buildDefinitionId )
+    private Map<String, Object> initializeContext( Project project, int buildDefinitionId, BuildTrigger buildTrigger )
         throws TaskExecutionException
     {
-        Map context = new HashMap();
+        Map<String, Object> context = new HashMap<String, Object>();
 
         try
         {
-            Project project = projectDao.getProjectWithScmDetails( projectId );
             ProjectGroup projectGroup = project.getProjectGroup();
-            
+
             List<ProjectScmRoot> scmRoots = projectScmRootDao.getProjectScmRootByProjectGroup( projectGroup.getId() );
             String projectScmUrl = project.getScmUrl();
-            
+            String projectScmRootAddress = "";
+
             for ( ProjectScmRoot projectScmRoot : scmRoots )
             {
-                if ( projectScmUrl.contains( projectScmRoot.getScmRootAddress() ) )
+                projectScmRootAddress = projectScmRoot.getScmRootAddress();
+
+                if ( projectScmUrl.startsWith( projectScmRoot.getScmRootAddress() ) )
                 {
-                    context.put( AbstractContinuumAction.KEY_PROJECT_SCM_ROOT, projectScmRoot );
+                    AbstractContinuumAction.setProjectScmRoot( context, projectScmRoot );
+                    AbstractContinuumAction.setProjectScmRootUrl( context, projectScmRootAddress );
                     break;
                 }
             }
 
-            context.put( AbstractContinuumAction.KEY_PROJECT_GROUP_ID, projectGroup.getId() );
-            context.put( AbstractContinuumAction.KEY_PROJECT_ID, projectId );
-            context.put( AbstractContinuumAction.KEY_PROJECT, project );
-    
-            context.put( AbstractContinuumAction.KEY_BUILD_DEFINITION_ID, buildDefinitionId );
-            context.put( AbstractContinuumAction.KEY_BUILD_DEFINITION, buildDefinitionDao.getBuildDefinition( buildDefinitionId ) );
-            
-            context.put( AbstractContinuumAction.KEY_OLD_SCM_RESULT, project.getScmResult() );
+            AbstractContinuumAction.setProjectGroupId( context, projectGroup.getId() );
+            AbstractContinuumAction.setProjectId( context, project.getId() );
+            AbstractContinuumAction.setProject( context, project );
+            AbstractContinuumAction.setBuildTrigger( context, buildTrigger );
+
+            AbstractContinuumAction.setBuildDefinitionId( context, buildDefinitionId );
+            AbstractContinuumAction.setBuildDefinition( context, buildDefinitionDao.getBuildDefinition(
+                buildDefinitionId ) );
+
+            if ( project.isCheckedOutInSingleDirectory() )
+            {
+                List<Project> projectsInGroup = projectGroupDao.getProjectGroupWithProjects(
+                    projectGroup.getId() ).getProjects();
+                List<Project> projectsWithCommonScmRoot = new ArrayList<Project>();
+                for ( Project projectInGroup : projectsInGroup )
+                {
+                    if ( projectInGroup.getScmUrl().startsWith( projectScmRootAddress ) )
+                    {
+                        projectsWithCommonScmRoot.add( projectInGroup );
+                    }
+                }
+                AbstractContinuumAction.setListOfProjectsInGroupWithCommonScmRoot( context, projectsWithCommonScmRoot );
+            }
+
+            BuildResult oldBuildResult = buildResultDao.getLatestBuildResultForBuildDefinition( project.getId(),
+                                                                                                buildDefinitionId );
+
+            if ( oldBuildResult != null )
+            {
+                AbstractContinuumAction.setOldScmResult( context, getOldScmResults( project.getId(),
+                                                                                    oldBuildResult.getBuildNumber(),
+                                                                                    oldBuildResult.getEndTime() ) );
+            }
+            else
+            {
+                AbstractContinuumAction.setOldScmResult( context, null );
+            }
         }
         catch ( ContinuumStoreException e )
         {
             throw new TaskExecutionException( "Error initializing pre-build context", e );
         }
-        
+
         return context;
     }
-    
-    private void cleanWorkingDirectory( Map context )
+
+    private void cleanWorkingDirectory( Map<String, Object> context )
         throws TaskExecutionException
     {
         performAction( "clean-working-directory", context );
     }
-    
-    private void updateWorkingDirectory( Map context )
+
+    private void updateWorkingDirectory( Map<String, Object> context, Project rootProject )
         throws TaskExecutionException
     {
         performAction( "check-working-directory", context );
-    
-        boolean workingDirectoryExists =
-            AbstractContinuumAction.getBoolean( context, AbstractContinuumAction.KEY_WORKING_DIRECTORY_EXISTS );
-    
+
+        boolean workingDirectoryExists = CheckWorkingDirectoryAction.isWorkingDirectoryExists( context );
+
         ScmResult scmResult;
-    
+
         if ( workingDirectoryExists )
         {
             performAction( "update-working-directory-from-scm", context );
-    
-            scmResult = AbstractContinuumAction.getUpdateScmResult( context, null );
+
+            scmResult = UpdateWorkingDirectoryFromScmContinuumAction.getUpdateScmResult( context, null );
         }
         else
         {
             Project project = AbstractContinuumAction.getProject( context );
-    
-            context.put( AbstractContinuumAction.KEY_WORKING_DIRECTORY,
-                               workingDirectoryService.getWorkingDirectory( project ).getAbsolutePath() );
-    
+
+            AbstractContinuumAction.setWorkingDirectory( context, workingDirectoryService.getWorkingDirectory(
+                project ).getAbsolutePath() );
+
+            List<Project> projectsWithCommonScmRoot = AbstractContinuumAction.getListOfProjectsInGroupWithCommonScmRoot(
+                context );
+            String projectScmRootUrl = AbstractContinuumAction.getProjectScmRootUrl( context, project.getScmUrl() );
+            String workingDir = null;
+
+            if ( rootProject.getId() == project.getId() )
+            {
+                workingDir = workingDirectoryService.getWorkingDirectory( project, false ).getAbsolutePath();
+
+                if ( project.isCheckedOutInSingleDirectory() )
+                {
+                    File parentDir = new File( workingDir );
+
+                    while ( !isRootDirectory( parentDir.getAbsolutePath(), project ) )
+                    {
+                        parentDir = parentDir.getParentFile();
+                    }
+
+                    if ( !parentDir.exists() )
+                    {
+                        workingDir = parentDir.getAbsolutePath();
+                    }
+                }
+            }
+
+            if ( workingDir == null || new File( workingDir ).exists() )
+            {
+                workingDir = workingDirectoryService.getWorkingDirectory( project, projectScmRootUrl,
+                                                                          projectsWithCommonScmRoot ).getAbsolutePath();
+            }
+
+            AbstractContinuumAction.setWorkingDirectory( context, workingDir );
+
+            if ( rootProject.getId() != project.getId() || ( rootProject.getId() == project.getId() && !isRootDirectory(
+                workingDir, rootProject ) ) )
+            {
+                AbstractContinuumAction.setRootDirectory( context, false );
+            }
+
             performAction( "checkout-project", context );
-    
-            scmResult = AbstractContinuumAction.getCheckoutResult( context, null );
+
+            scmResult = CheckoutProjectContinuumAction.getCheckoutScmResult( context, null );
         }
-    
-        context.put( AbstractContinuumAction.KEY_SCM_RESULT, scmResult );
+
+        // [CONTINUUM-2207] when returned scmResult is null, this causes a problem when building the project 
+        if ( scmResult == null )
+        {
+            log.debug( "Returned ScmResult is null when updating the working directory" );
+            scmResult = new ScmResult();
+        }
+
+        AbstractContinuumAction.setScmResult( context, scmResult );
     }
-    
-    private boolean checkProjectScmRoot( Map context )
+
+    private boolean checkProjectScmRoot( Map<String, Object> context )
         throws TaskExecutionException
     {
         ProjectScmRoot projectScmRoot = AbstractContinuumAction.getProjectScmRoot( context );
-        
+
         // check state of scm root
-        if ( projectScmRoot.getState() == ContinuumProjectState.ERROR )
-        {
-            return false;
-        }
-        
-        return true;
+        return projectScmRoot.getState() != ContinuumProjectState.ERROR;
+
     }
-    
-    private void startPrepareBuild( Map context )
+
+    private void startPrepareBuild( Map<String, Object> context )
         throws TaskExecutionException
     {
         ProjectScmRoot projectScmRoot = AbstractContinuumAction.getProjectScmRoot( context );
@@ -269,17 +397,17 @@
             }
         }
     }
-    
-    private void endPrepareBuild( Map context )
+
+    private void endPrepareBuild( Map<String, Object> context )
         throws TaskExecutionException
     {
         ProjectScmRoot projectScmRoot = AbstractContinuumAction.getProjectScmRoot( context );
-        
+
         if ( projectScmRoot.getState() != ContinuumProjectState.ERROR )
         {
             projectScmRoot.setState( ContinuumProjectState.UPDATED );
             projectScmRoot.setError( null );
-            
+
             try
             {
                 projectScmRootDao.updateProjectScmRoot( projectScmRoot );
@@ -292,51 +420,77 @@
 
         notifierDispatcher.prepareBuildComplete( projectScmRoot );
     }
-    
+
     /**
-     *  @param context
+     * @param context
      * @throws TaskExecutionException
      */
-    private void endProjectPrepareBuild( Map context )
+    private void endProjectPrepareBuild( Map<String, Object> context )
         throws TaskExecutionException
     {
         ScmResult scmResult = AbstractContinuumAction.getScmResult( context, null );
-        Project project = AbstractContinuumAction.getProject( context );
-        
+
         if ( scmResult == null || !scmResult.isSuccess() )
         {
             String error = convertScmResultToError( scmResult );
-            
+
             updateProjectScmRoot( context, error );
         }
-        
-        try
-        {
-            project.setScmResult( scmResult );
-
-            projectDao.updateProject( project );
-        }
-        catch ( ContinuumStoreException e )
-        {
-            throw new TaskExecutionException( "Error storing the project", e );
-        }
     }
-    
+
+    private ScmResult getOldScmResults( int projectId, long startId, long fromDate )
+        throws ContinuumStoreException
+    {
+        List<BuildResult> results = buildResultDao.getBuildResultsForProjectFromId( projectId, startId );
+
+        ScmResult res = new ScmResult();
+
+        if ( results != null && results.size() > 0 )
+        {
+            for ( BuildResult result : results )
+            {
+                ScmResult scmResult = result.getScmResult();
+
+                if ( scmResult != null )
+                {
+                    List<ChangeSet> changes = scmResult.getChanges();
+
+                    if ( changes != null )
+                    {
+                        for ( ChangeSet changeSet : changes )
+                        {
+                            if ( changeSet.getDate() < fromDate )
+                            {
+                                continue;
+                            }
+                            if ( !res.getChanges().contains( changeSet ) )
+                            {
+                                res.addChange( changeSet );
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return res;
+    }
+
     /**
      * Merges scm results so we'll have all changes since last execution of current build definition
      *
      * @param context The build context
      */
-    private void mergeScmResults( Map context )
+    private void mergeScmResults( Map<String, Object> context )
     {
-        ScmResult oldScmResult = AbstractContinuumAction.getOldScmResult( context, null );
+        ScmResult oldScmResult = AbstractContinuumAction.getOldScmResult( context );
         ScmResult newScmResult = AbstractContinuumAction.getScmResult( context, null );
 
         if ( oldScmResult != null )
         {
             if ( newScmResult == null )
             {
-                context.put( AbstractContinuumAction.KEY_SCM_RESULT, oldScmResult );
+                AbstractContinuumAction.setScmResult( context, oldScmResult );
             }
             else
             {
@@ -356,11 +510,11 @@
             }
         }
     }
-    
-    private void performAction( String actionName, Map context )
+
+    private void performAction( String actionName, Map<String, Object> context )
         throws TaskExecutionException
     {
-        TaskExecutionException exception = null;
+        TaskExecutionException exception;
 
         try
         {
@@ -376,18 +530,18 @@
         {
             exception = new TaskExecutionException( "Error executing action '" + actionName + "'", e );
         }
-        
+
         ScmResult result = new ScmResult();
-        
+
         result.setSuccess( false );
-        
+
         result.setException( ContinuumUtils.throwableToString( exception ) );
-        
-        context.put( AbstractContinuumAction.KEY_SCM_RESULT, result );
-        
+
+        AbstractContinuumAction.setScmResult( context, result );
+
         throw exception;
     }
-    
+
     private String convertScmResultToError( ScmResult result )
     {
         String error = "";
@@ -429,20 +583,20 @@
 
         return error;
     }
-    
-    private void updateProjectScmRoot( Map context, String error )
+
+    private void updateProjectScmRoot( Map<String, Object> context, String error )
         throws TaskExecutionException
     {
         ProjectScmRoot projectScmRoot = AbstractContinuumAction.getProjectScmRoot( context );
-        
+
         try
         {
             projectScmRoot.setState( ContinuumProjectState.ERROR );
             projectScmRoot.setError( error );
 
             projectScmRootDao.updateProjectScmRoot( projectScmRoot );
-            
-            context.put( AbstractContinuumAction.KEY_PROJECT_SCM_ROOT, projectScmRoot );
+
+            AbstractContinuumAction.setProjectScmRoot( context, projectScmRoot );
         }
         catch ( ContinuumStoreException e )
         {
@@ -450,69 +604,63 @@
         }
     }
 
-    private void buildProjects( int projectGroupId, Map<Integer, Integer> projectsAndBuildDefinitionsMap, int trigger )
+    private void buildProjects( int projectGroupId, List<Project> projectList,
+                                Map<Integer, Integer> projectsAndBuildDefinitionsMap, BuildTrigger buildTrigger,
+                                Map<Integer, ScmResult> scmResultMap )
         throws TaskExecutionException
     {
-        List<Project> projects = projectDao.getProjectsWithDependenciesByGroupId( projectGroupId );
-        List<Project> projectList;
-        
-        try
-        {
-            projectList = ProjectSorter.getSortedProjects( projects, log );
-        }
-        catch ( CycleDetectedException e )
-        {
-            projectList = projectDao.getAllProjectsByName();
-        }
+        List<Project> projectsToBeBuilt = new ArrayList<Project>();
+        Map<Integer, BuildDefinition> projectsBuildDefinitionsMap = new HashMap<Integer, BuildDefinition>();
 
         for ( Project project : projectList )
         {
-            boolean shouldBuild = false;
-            int buildDefinitionId = 0;
-            
+            int buildDefinitionId;
+
             if ( projectsAndBuildDefinitionsMap.get( project.getId() ) != null )
             {
                 buildDefinitionId = projectsAndBuildDefinitionsMap.get( project.getId() );
-                shouldBuild = true;
-            }
-            else if ( project.getState() == ContinuumProjectState.CHECKEDOUT || project.getState() == ContinuumProjectState.NEW ) //check if no build result yet for project
-            {
+
                 try
                 {
-                    //get default build definition for project
-                    buildDefinitionId = buildDefinitionDao.getDefaultBuildDefinition( project.getId() ).getId();
+                    BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
+                    projectsBuildDefinitionsMap.put( project.getId(), buildDefinition );
+                    projectsToBeBuilt.add( project );
                 }
                 catch ( ContinuumStoreException e )
                 {
                     log.error( "Error while creating build object", e );
                     throw new TaskExecutionException( "Error while creating build object", e );
                 }
-                shouldBuild = true;
-            }
-
-            if ( shouldBuild )
-            {
-                try
-                {
-                    Map context = new HashMap();
-                    context.put( AbstractContinuumAction.KEY_PROJECT, project );
-                    context.put( AbstractContinuumAction.KEY_BUILD_DEFINITION_ID, buildDefinitionId );
-                    context.put( AbstractContinuumAction.KEY_TRIGGER, trigger );
-                    
-                    log.info( "Performing action create-build-project-task" );
-                    actionManager.lookup( "create-build-project-task" ).execute( context );
-                }
-                catch ( ActionNotFoundException e )
-                {
-                   log.error( "Error looking up action 'build-project'" );
-                   throw new TaskExecutionException( "Error looking up action 'build-project'", e );
-                }
-                catch ( Exception e )
-                {
-                    log.error( e.getMessage(), e );
-                    throw new TaskExecutionException( "Error executing action 'build-project'", e );
-                }
             }
         }
+
+        try
+        {
+            Map<String, Object> context = new HashMap<String, Object>();
+            AbstractContinuumAction.setListOfProjects( context, projectsToBeBuilt );
+            AbstractContinuumAction.setProjectsBuildDefinitionsMap( context, projectsBuildDefinitionsMap );
+            AbstractContinuumAction.setBuildTrigger( context, buildTrigger );
+            AbstractContinuumAction.setScmResultMap( context, scmResultMap );
+            AbstractContinuumAction.setProjectGroupId( context, projectGroupId );
+
+            log.info( "Performing action create-build-project-task" );
+            actionManager.lookup( "create-build-project-task" ).execute( context );
+        }
+        catch ( ActionNotFoundException e )
+        {
+            log.error( "Error looking up action 'build-project'" );
+            throw new TaskExecutionException( "Error looking up action 'build-project'", e );
+        }
+        catch ( Exception e )
+        {
+            log.error( e.getMessage(), e );
+            throw new TaskExecutionException( "Error executing action 'build-project'", e );
+        }
+    }
+
+    private boolean isRootDirectory( String workingDir, Project rootProject )
+    {
+        return workingDir.endsWith( Integer.toString( rootProject.getId() ) + System.getProperty(
+            "line.separator" ) ) || workingDir.endsWith( Integer.toString( rootProject.getId() ) );
     }
 }
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/utils/ProjectSorter.java b/continuum-core/src/main/java/org/apache/maven/continuum/utils/ProjectSorter.java
deleted file mode 100644
index ec86c09..0000000
--- a/continuum-core/src/main/java/org/apache/maven/continuum/utils/ProjectSorter.java
+++ /dev/null
@@ -1,159 +0,0 @@
-package org.apache.maven.continuum.utils;
-
-/*
- * 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 org.apache.maven.continuum.model.project.Project;
-import org.apache.maven.continuum.model.project.ProjectDependency;
-import org.codehaus.plexus.util.dag.CycleDetectedException;
-import org.codehaus.plexus.util.dag.DAG;
-import org.codehaus.plexus.util.dag.TopologicalSorter;
-import org.slf4j.Logger;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Sort projects by dependencies.
- *
- * @author <a href="mailto:brett@apache.org">Brett Porter</a>
- * @version $Id$
- */
-public class ProjectSorter
-{
-    private ProjectSorter()
-    {
-        // no touchy...
-    }
-
-    /**
-     * Sort a list of projects.
-     * <ul>
-     * <li>collect all the vertices for the projects that we want to build.</li>
-     * <li>iterate through the deps of each project and if that dep is within
-     * the set of projects we want to build then add an edge, otherwise throw
-     * the edge away because that dependency is not within the set of projects
-     * we are trying to build. we assume a closed set.</li>
-     * <li>do a topo sort on the graph that remains.</li>
-     * </ul>
-     */
-    public static List<Project> getSortedProjects( Collection<Project> projects, Logger logger )
-        throws CycleDetectedException
-    {
-        DAG dag = new DAG();
-
-        Map<String, Project> projectMap = new HashMap<String, Project>();
-
-        for ( Project project : projects )
-        {
-            String id = getProjectId( project );
-
-            if ( dag.getVertex( id ) != null )
-            {
-                logger.warn( "Project '" + id + "' is duplicated in the reactor" );
-            }
-
-            dag.addVertex( id );
-
-            projectMap.put( id, project );
-        }
-
-        for ( Project project : projects )
-        {
-            String id = getProjectId( project );
-
-            // Dependencies
-            for ( Object o : project.getDependencies() )
-            {
-                ProjectDependency dependency = (ProjectDependency) o;
-
-                String dependencyId = getDependencyId( dependency );
-
-                if ( dag.getVertex( dependencyId ) != null )
-                {
-                    dag.addEdge( id, dependencyId );
-                }
-            }
-
-            // Parent
-            ProjectDependency parent = project.getParent();
-
-            if ( parent != null )
-            {
-                String parentId = getDependencyId( parent );
-
-                if ( dag.getVertex( parentId ) != null )
-                {
-                    // Parent is added as an edge, but must not cause a cycle - so we remove any other edges it has in conflict
-                    if ( dag.hasEdge( parentId, id ) )
-                    {
-                        dag.removeEdge( parentId, id );
-                    }
-                    dag.addEdge( id, parentId );
-                }
-            }
-        }
-
-        List<Project> sortedProjects = new ArrayList<Project>();
-
-        for ( Object o : TopologicalSorter.sort( dag ) )
-        {
-            String id = (String) o;
-
-            sortedProjects.add( projectMap.get( id ) );
-        }
-
-        return sortedProjects;
-    }
-
-    private static String getProjectId( Project project )
-    {
-        String groupId;
-
-        String artifactId;
-
-        if ( project.getGroupId() == null )
-        {
-            groupId = project.getName();
-        }
-        else
-        {
-            groupId = project.getGroupId();
-        }
-
-        if ( project.getArtifactId() == null )
-        {
-            artifactId = project.getName();
-        }
-        else
-        {
-            artifactId = project.getArtifactId();
-        }
-
-        return groupId + ":" + artifactId + ":" + project.getVersion();
-    }
-
-    private static String getDependencyId( ProjectDependency project )
-    {
-        return project.getGroupId() + ":" + project.getArtifactId() + ":" + project.getVersion();
-    }
-}
diff --git a/continuum-core/src/main/resources/META-INF/plexus/components-fragment.xml b/continuum-core/src/main/resources/META-INF/plexus/components-fragment.xml
new file mode 100644
index 0000000..cbcf305
--- /dev/null
+++ b/continuum-core/src/main/resources/META-INF/plexus/components-fragment.xml
@@ -0,0 +1,167 @@
+<!--
+  ~ 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.
+  -->
+
+<component-set>
+  <components>
+
+    <!--
+    |
+    | Build Project Task Queue
+    |
+    |-->
+
+    <component>
+      <role>org.codehaus.plexus.taskqueue.TaskQueue</role>
+      <role-hint>build-project</role-hint>
+      <implementation>org.codehaus.plexus.taskqueue.DefaultTaskQueue</implementation>
+      <instantiation-strategy>per-lookup</instantiation-strategy>
+      <lifecycle-handler>plexus-configurable</lifecycle-handler>
+      <configuration>
+        <task-entry-evaluators>
+        </task-entry-evaluators>
+        <task-exit-evaluators>
+        </task-exit-evaluators>
+        <task-viability-evaluators>
+          <task-viability-evaluator>build-project</task-viability-evaluator>
+        </task-viability-evaluators>
+      </configuration>
+    </component>
+
+    <component>
+      <role>org.codehaus.plexus.taskqueue.TaskViabilityEvaluator</role>
+      <role-hint>build-project</role-hint>
+      <instantiation-strategy>per-lookup</instantiation-strategy>
+      <implementation>
+        org.apache.maven.continuum.buildqueue.evaluator.BuildProjectTaskViabilityEvaluator
+      </implementation>
+      <configuration>
+        <required-buildInterval>1000</required-buildInterval>
+      </configuration>
+    </component>
+
+    <component>
+      <role>org.codehaus.plexus.taskqueue.execution.TaskExecutor</role>
+      <role-hint>build-project</role-hint>
+      <instantiation-strategy>per-lookup</instantiation-strategy>
+      <implementation>org.apache.maven.continuum.buildcontroller.BuildProjectTaskExecutor</implementation>
+      <requirements>
+        <requirement>
+          <role>org.apache.maven.continuum.buildcontroller.BuildController</role>
+        </requirement>
+        <!-- 
+        <requirement>
+          <role>org.apache.continuum.taskqueue.manager.TaskQueueManager</role>
+        </requirement>
+         -->
+      </requirements>
+    </component>
+
+    <component>
+      <role>org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor</role>
+      <role-hint>build-project</role-hint>
+      <instantiation-strategy>per-lookup</instantiation-strategy>
+      <implementation>org.apache.continuum.taskqueueexecutor.ParallelBuildsThreadedTaskQueueExecutor</implementation>
+      <requirements>
+        <requirement>
+          <role>org.codehaus.plexus.taskqueue.execution.TaskExecutor</role>
+          <role-hint>build-project</role-hint>
+        </requirement>
+        <requirement>
+          <role>org.codehaus.plexus.taskqueue.TaskQueue</role>
+          <role-hint>build-project</role-hint>
+        </requirement>
+      </requirements>
+      <configuration>
+        <name>build-project</name>
+      </configuration>
+    </component>
+
+    <!--
+     |
+     | Check Out Task Queue
+     |
+     |-->
+
+    <component>
+      <role>org.codehaus.plexus.taskqueue.TaskQueue</role>
+      <role-hint>check-out-project</role-hint>
+      <implementation>org.codehaus.plexus.taskqueue.DefaultTaskQueue</implementation>
+      <lifecycle-handler>plexus-configurable</lifecycle-handler>
+      <instantiation-strategy>per-lookup</instantiation-strategy>
+    </component>
+
+
+    <component>
+      <role>org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor</role>
+      <role-hint>check-out-project</role-hint>
+      <implementation>org.apache.continuum.taskqueueexecutor.ParallelBuildsThreadedTaskQueueExecutor</implementation>
+      <instantiation-strategy>per-lookup</instantiation-strategy>
+      <requirements>
+        <requirement>
+          <role>org.codehaus.plexus.taskqueue.execution.TaskExecutor</role>
+          <role-hint>check-out-project</role-hint>
+        </requirement>
+        <requirement>
+          <role>org.codehaus.plexus.taskqueue.TaskQueue</role>
+          <role-hint>check-out-project</role-hint>
+        </requirement>
+      </requirements>
+      <configuration>
+        <name>check-out-project</name>
+      </configuration>
+    </component>
+
+
+    <!--
+     |
+     | Prepare Build Project Task Queue
+     |
+     |-->
+
+    <component>
+      <role>org.codehaus.plexus.taskqueue.TaskQueue</role>
+      <role-hint>prepare-build-project</role-hint>
+      <implementation>org.codehaus.plexus.taskqueue.DefaultTaskQueue</implementation>
+      <lifecycle-handler>plexus-configurable</lifecycle-handler>
+      <instantiation-strategy>per-lookup</instantiation-strategy>
+    </component>
+
+    <component>
+      <role>org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor</role>
+      <role-hint>prepare-build-project</role-hint>
+      <implementation>org.apache.continuum.taskqueueexecutor.ParallelBuildsThreadedTaskQueueExecutor</implementation>
+      <instantiation-strategy>per-lookup</instantiation-strategy>
+      <requirements>
+        <requirement>
+          <role>org.codehaus.plexus.taskqueue.execution.TaskExecutor</role>
+          <role-hint>prepare-build-project</role-hint>
+        </requirement>
+        <requirement>
+          <role>org.codehaus.plexus.taskqueue.TaskQueue</role>
+          <role-hint>prepare-build-project</role-hint>
+        </requirement>
+      </requirements>
+      <configuration>
+        <name>prepare-build-project</name>
+      </configuration>
+    </component>
+
+
+  </components>
+</component-set>
diff --git a/continuum-core/src/main/resources/META-INF/plexus/components.xml b/continuum-core/src/main/resources/META-INF/plexus/components.xml
deleted file mode 100644
index 581d8a9..0000000
--- a/continuum-core/src/main/resources/META-INF/plexus/components.xml
+++ /dev/null
@@ -1,159 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<component-set>
-  <components>
-
-    <!--
-     |
-     | Build Project Task Queue
-     |
-     |-->
-
-    <component>
-      <role>org.codehaus.plexus.taskqueue.TaskQueue</role>
-      <role-hint>build-project</role-hint>
-      <implementation>org.codehaus.plexus.taskqueue.DefaultTaskQueue</implementation>
-      <lifecycle-handler>plexus-configurable</lifecycle-handler>
-      <configuration>
-        <task-entry-evaluators>
-        </task-entry-evaluators>
-        <task-exit-evaluators>
-        </task-exit-evaluators>
-        <task-viability-evaluators>
-          <task-viability-evaluator>build-project</task-viability-evaluator>
-        </task-viability-evaluators>
-      </configuration>
-    </component>
-
-    <component>
-      <role>org.codehaus.plexus.taskqueue.TaskViabilityEvaluator</role>
-      <role-hint>build-project</role-hint>
-      <implementation>
-        org.apache.maven.continuum.buildqueue.evaluator.BuildProjectTaskViabilityEvaluator</implementation>
-      <configuration>
-        <required-buildInterval>1000</required-buildInterval>
-      </configuration>
-    </component>
-
-    <component>
-      <role>org.codehaus.plexus.taskqueue.execution.TaskExecutor</role>
-      <role-hint>build-project</role-hint>
-      <implementation>org.apache.maven.continuum.buildcontroller.BuildProjectTaskExecutor</implementation>
-      <requirements>
-        <requirement>
-          <role>org.apache.maven.continuum.buildcontroller.BuildController</role>
-        </requirement>
-        <requirement>
-          <role>org.apache.continuum.taskqueue.manager.TaskQueueManager</role>
-        </requirement>
-      </requirements>
-    </component>
-
-    <component>
-      <role>org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor</role>
-      <role-hint>build-project</role-hint>
-      <implementation>org.codehaus.plexus.taskqueue.execution.ThreadedTaskQueueExecutor</implementation>
-      <instantiation-strategy>singleton</instantiation-strategy>
-      <requirements>
-        <requirement>
-          <role>org.codehaus.plexus.taskqueue.execution.TaskExecutor</role>
-          <role-hint>build-project</role-hint>
-        </requirement>
-        <requirement>
-          <role>org.codehaus.plexus.taskqueue.TaskQueue</role>
-          <role-hint>build-project</role-hint>
-        </requirement>
-      </requirements>
-      <configuration>
-        <name>build-project</name>
-      </configuration>
-    </component>
-
-    <!--
-     |
-     | Check Out Task Queue
-     |
-     |-->
-
-    <component>
-      <role>org.codehaus.plexus.taskqueue.TaskQueue</role>
-      <role-hint>check-out-project</role-hint>
-      <implementation>org.codehaus.plexus.taskqueue.DefaultTaskQueue</implementation>
-      <lifecycle-handler>plexus-configurable</lifecycle-handler>
-    </component>
-
-
-    <component>
-      <role>org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor</role>
-      <role-hint>check-out-project</role-hint>
-      <implementation>org.codehaus.plexus.taskqueue.execution.ThreadedTaskQueueExecutor</implementation>
-      <instantiation-strategy>singleton</instantiation-strategy>
-      <requirements>
-        <requirement>
-          <role>org.codehaus.plexus.taskqueue.execution.TaskExecutor</role>
-          <role-hint>check-out-project</role-hint>
-        </requirement>
-        <requirement>
-          <role>org.codehaus.plexus.taskqueue.TaskQueue</role>
-          <role-hint>check-out-project</role-hint>
-        </requirement>
-      </requirements>
-      <configuration>
-        <name>check-out-project</name>
-      </configuration>
-    </component>
-
-
-    <!--
-     |
-     | Prepare Build Project Task Queue
-     |
-     |-->
-     
-    <component>
-      <role>org.codehaus.plexus.taskqueue.TaskQueue</role>
-      <role-hint>prepare-build-project</role-hint>
-      <implementation>org.codehaus.plexus.taskqueue.DefaultTaskQueue</implementation>
-      <lifecycle-handler>plexus-configurable</lifecycle-handler>
-    </component>
-    
-    <component>
-      <role>org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor</role>
-      <role-hint>prepare-build-project</role-hint>
-      <implementation>org.codehaus.plexus.taskqueue.execution.ThreadedTaskQueueExecutor</implementation>
-      <instantiation-strategy>singleton</instantiation-strategy>
-      <requirements>
-        <requirement>
-          <role>org.codehaus.plexus.taskqueue.execution.TaskExecutor</role>
-          <role-hint>prepare-build-project</role-hint>
-        </requirement>
-        <requirement>
-          <role>org.codehaus.plexus.taskqueue.TaskQueue</role>
-          <role-hint>prepare-build-project</role-hint>
-        </requirement>
-      </requirements>
-      <configuration>
-        <name>prepare-build-project</name>
-      </configuration>
-    </component>
-    
-    
-  </components>
-</component-set>
diff --git a/continuum-core/src/main/resources/META-INF/spring-context.xml b/continuum-core/src/main/resources/META-INF/spring-context.xml
index d893c68..01cc186 100644
--- a/continuum-core/src/main/resources/META-INF/spring-context.xml
+++ b/continuum-core/src/main/resources/META-INF/spring-context.xml
@@ -1,36 +1,67 @@
 <?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
 <beans xmlns="http://www.springframework.org/schema/beans"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xmlns:aop="http://www.springframework.org/schema/aop"
-	xmlns:util="http://www.springframework.org/schema/util"
-	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
-		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
-		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd">
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
 
   <bean name="continuumBuildExecutor#maven2"
-         class="org.apache.maven.continuum.execution.maven.m2.MavenTwoBuildExecutor" autowire="byName">
+        class="org.apache.maven.continuum.execution.maven.m2.MavenTwoBuildExecutor" autowire="byName">
     <property name="defaultExecutable" value="mvn"/>
     <property name="builderHelper" ref="mavenBuilderHelper"/>
     <property name="projectHelper" ref="mavenProjectHelper"/>
   </bean>
   <bean name="continuumBuildExecutor#maven-1"
-         class="org.apache.maven.continuum.execution.maven.m1.MavenOneBuildExecutor" autowire="byName">
+        class="org.apache.maven.continuum.execution.maven.m1.MavenOneBuildExecutor" autowire="byName">
     <property name="defaultExecutable" value="maven"/>
     <property name="metadataHelper" ref="mavenOneMetadataHelper"/>
   </bean>
   <bean name="continuumBuildExecutor#ant"
-         class="org.apache.maven.continuum.execution.ant.AntBuildExecutor" autowire="byName">
+        class="org.apache.maven.continuum.execution.ant.AntBuildExecutor" autowire="byName">
     <property name="defaultExecutable" value="ant"/>
   </bean>
   <bean name="continuumBuildExecutor#shell"
-         class="org.apache.maven.continuum.execution.shell.ShellBuildExecutor" autowire="byName">
+        class="org.apache.maven.continuum.execution.shell.ShellBuildExecutor" autowire="byName">
   </bean>
 
   <bean id="notifierManager"
-    class="org.apache.maven.continuum.notification.manager.DefaultNotifierManager">
+        class="org.apache.maven.continuum.notification.manager.DefaultNotifierManager">
     <property name="notifiers">
       <bean class="org.apache.maven.continuum.notification.manager.spring.NotifierFactoryBean"/>
     </property>
   </bean>
 
+  <bean name="buildsManager#parallel"
+        class="org.apache.continuum.buildmanager.ParallelBuildsManager" autowire="byName"/>
+
+  <bean name="overallBuildQueue"
+        class="org.apache.continuum.taskqueue.DefaultOverallBuildQueue" scope="prototype" autowire="byName">
+    <property name="buildTaskQueueExecutor" ref="taskQueueExecutor#build-project"/>
+    <property name="checkoutTaskQueueExecutor" ref="taskQueueExecutor#check-out-project"/>
+    <property name="prepareBuildTaskQueueExecutor" ref="taskQueueExecutor#prepare-build-project"/>
+  </bean>
+
+  <!-- jobs -->
+  <bean name="continuumBuildJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
+    <property name="targetObject" ref="continuumWorker"/>
+    <property name="targetMethod" value="work"/>
+    <property name="concurrent" value="false"/>
+  </bean>
 </beans>
diff --git a/continuum-core/src/main/resources/org/apache/maven/continuum/notification/mail/templates/PrepareBuildComplete.vm b/continuum-core/src/main/resources/org/apache/maven/continuum/notification/mail/templates/PrepareBuildComplete.vm
index 68779d3..aca1877 100644
--- a/continuum-core/src/main/resources/org/apache/maven/continuum/notification/mail/templates/PrepareBuildComplete.vm
+++ b/continuum-core/src/main/resources/org/apache/maven/continuum/notification/mail/templates/PrepareBuildComplete.vm
@@ -15,7 +15,7 @@
  *#
 Online report : $reportUrl
 
-  Project Group: $projectGroup.name
+  Project Group: $projectScmRoot.projectGroup.name
   SCM Root URL: $projectScmRoot.scmRootAddress
   
 #if ($projectScmRoot.state == 4)
diff --git a/continuum-core/src/test-poms/pom.xml b/continuum-core/src/test-poms/pom.xml
index 1b91b14..f0fe4d4 100755
--- a/continuum-core/src/test-poms/pom.xml
+++ b/continuum-core/src/test-poms/pom.xml
@@ -23,6 +23,7 @@
   <artifactId>continuum-project2</artifactId>
   <packaging>jar</packaging>
   <name>Continuum Test Project 2</name>
+  <description>This is a sample pom for test purposes</description>
   <version>1.0</version>
   
   <scm>
diff --git a/continuum-core/src/test-projects/flat-multi-module/.cvsignore b/continuum-core/src/test-projects/flat-multi-module/.cvsignore
new file mode 100644
index 0000000..cce9515
--- /dev/null
+++ b/continuum-core/src/test-projects/flat-multi-module/.cvsignore
@@ -0,0 +1,8 @@
+target
+*~
+*.log
+.classpath
+.project
+*.ipr
+*.iws
+*.iml
diff --git a/continuum-core/src/test-projects/flat-multi-module/module-a/pom.xml b/continuum-core/src/test-projects/flat-multi-module/module-a/pom.xml
new file mode 100644
index 0000000..d604ab8
--- /dev/null
+++ b/continuum-core/src/test-projects/flat-multi-module/module-a/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<!--
+  ~ 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.
+  -->
+<project>
+  <parent>
+    <artifactId>parent-project</artifactId>
+    <groupId>org.apache.continuum</groupId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.continuum</groupId>
+  <artifactId>module-a</artifactId>
+  <name>module-a</name>
+  <version>1.0-SNAPSHOT</version>
+  <url>http://maven.apache.org</url>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.1</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/continuum-core/src/test-projects/flat-multi-module/module-a/src/main/java/org/apache/continuum/module/a/App.java b/continuum-core/src/test-projects/flat-multi-module/module-a/src/main/java/org/apache/continuum/module/a/App.java
new file mode 100644
index 0000000..de2c49d
--- /dev/null
+++ b/continuum-core/src/test-projects/flat-multi-module/module-a/src/main/java/org/apache/continuum/module/a/App.java
@@ -0,0 +1,32 @@
+package org.apache.continuum.module.a;
+
+/*
+ * 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.
+ */
+
+/**
+ * Hello world!
+ *
+ */
+public class App 
+{
+    public static void main( String[] args )
+    {
+        System.out.println( "Hello World!" );
+    }
+}
diff --git a/continuum-core/src/test-projects/flat-multi-module/module-a/src/test/java/org/apache/continuum/module/a/AppTest.java b/continuum-core/src/test-projects/flat-multi-module/module-a/src/test/java/org/apache/continuum/module/a/AppTest.java
new file mode 100644
index 0000000..876714b
--- /dev/null
+++ b/continuum-core/src/test-projects/flat-multi-module/module-a/src/test/java/org/apache/continuum/module/a/AppTest.java
@@ -0,0 +1,57 @@
+package org.apache.continuum.module.a;
+
+/*
+ * 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 junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Unit test for simple App.
+ */
+public class AppTest 
+    extends TestCase
+{
+    /**
+     * Create the test case
+     *
+     * @param testName name of the test case
+     */
+    public AppTest( String testName )
+    {
+        super( testName );
+    }
+
+    /**
+     * @return the suite of tests being tested
+     */
+    public static Test suite()
+    {
+        return new TestSuite( AppTest.class );
+    }
+
+    /**
+     * Rigourous Test :-)
+     */
+    public void testApp()
+    {
+        assertTrue( true );
+    }
+}
diff --git a/continuum-core/src/test-projects/flat-multi-module/module-b/pom.xml b/continuum-core/src/test-projects/flat-multi-module/module-b/pom.xml
new file mode 100644
index 0000000..95ff9e5
--- /dev/null
+++ b/continuum-core/src/test-projects/flat-multi-module/module-b/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<!--
+  ~ 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.
+  -->
+<project>
+  <parent>
+    <artifactId>parent-project</artifactId>
+    <groupId>org.apache.continuum</groupId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.continuum</groupId>
+  <artifactId>module-b</artifactId>
+  <name>module-b</name>
+  <version>1.0-SNAPSHOT</version>
+  <url>http://maven.apache.org</url>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.1</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
\ No newline at end of file
diff --git a/continuum-core/src/test-projects/flat-multi-module/module-b/src/main/java/org/apache/continuum/module/b/App.java b/continuum-core/src/test-projects/flat-multi-module/module-b/src/main/java/org/apache/continuum/module/b/App.java
new file mode 100644
index 0000000..4a35254
--- /dev/null
+++ b/continuum-core/src/test-projects/flat-multi-module/module-b/src/main/java/org/apache/continuum/module/b/App.java
@@ -0,0 +1,32 @@
+package org.apache.continuum.module.b;
+
+/*
+ * 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.
+ */
+
+/**
+ * Hello world!
+ *
+ */
+public class App 
+{
+    public static void main( String[] args )
+    {
+        System.out.println( "Hello World!" );
+    }
+}
diff --git a/continuum-core/src/test-projects/flat-multi-module/module-b/src/test/java/org/apache/continuum/module/b/AppTest.java b/continuum-core/src/test-projects/flat-multi-module/module-b/src/test/java/org/apache/continuum/module/b/AppTest.java
new file mode 100644
index 0000000..0e8d12f
--- /dev/null
+++ b/continuum-core/src/test-projects/flat-multi-module/module-b/src/test/java/org/apache/continuum/module/b/AppTest.java
@@ -0,0 +1,57 @@
+package org.apache.continuum.module.b;
+
+/*
+ * 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 junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Unit test for simple App.
+ */
+public class AppTest 
+    extends TestCase
+{
+    /**
+     * Create the test case
+     *
+     * @param testName name of the test case
+     */
+    public AppTest( String testName )
+    {
+        super( testName );
+    }
+
+    /**
+     * @return the suite of tests being tested
+     */
+    public static Test suite()
+    {
+        return new TestSuite( AppTest.class );
+    }
+
+    /**
+     * Rigourous Test :-)
+     */
+    public void testApp()
+    {
+        assertTrue( true );
+    }
+}
diff --git a/continuum-core/src/test-projects/flat-multi-module/module-c/module-d/pom.xml b/continuum-core/src/test-projects/flat-multi-module/module-c/module-d/pom.xml
new file mode 100644
index 0000000..7129ba2
--- /dev/null
+++ b/continuum-core/src/test-projects/flat-multi-module/module-c/module-d/pom.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0"?>
+<!--
+  ~ 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.
+  -->
+<project>
+  <parent>
+    <artifactId>parent-project</artifactId>
+    <groupId>org.apache.continuum</groupId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.continuum</groupId>
+  <artifactId>module-d</artifactId>
+  <name>module-d</name>
+  <version>1.0-SNAPSHOT</version>
+  <url>http://maven.apache.org</url>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.1</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>module-a</artifactId>
+      <version>1.0-SNAPSHOT</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/continuum-core/src/test-projects/flat-multi-module/module-c/module-d/src/main/java/org/apache/continuum/module/d/App.java b/continuum-core/src/test-projects/flat-multi-module/module-c/module-d/src/main/java/org/apache/continuum/module/d/App.java
new file mode 100644
index 0000000..952ee35
--- /dev/null
+++ b/continuum-core/src/test-projects/flat-multi-module/module-c/module-d/src/main/java/org/apache/continuum/module/d/App.java
@@ -0,0 +1,32 @@
+package org.apache.continuum.module.d;
+
+/*
+ * 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.
+ */
+
+/**
+ * Hello world!
+ *
+ */
+public class App 
+{
+    public static void main( String[] args )
+    {
+        System.out.println( "Hello World!" );
+    }
+}
diff --git a/continuum-core/src/test-projects/flat-multi-module/module-c/module-d/src/test/java/org/apache/continuum/module/d/AppTest.java b/continuum-core/src/test-projects/flat-multi-module/module-c/module-d/src/test/java/org/apache/continuum/module/d/AppTest.java
new file mode 100644
index 0000000..876714b
--- /dev/null
+++ b/continuum-core/src/test-projects/flat-multi-module/module-c/module-d/src/test/java/org/apache/continuum/module/d/AppTest.java
@@ -0,0 +1,57 @@
+package org.apache.continuum.module.a;
+
+/*
+ * 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 junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Unit test for simple App.
+ */
+public class AppTest 
+    extends TestCase
+{
+    /**
+     * Create the test case
+     *
+     * @param testName name of the test case
+     */
+    public AppTest( String testName )
+    {
+        super( testName );
+    }
+
+    /**
+     * @return the suite of tests being tested
+     */
+    public static Test suite()
+    {
+        return new TestSuite( AppTest.class );
+    }
+
+    /**
+     * Rigourous Test :-)
+     */
+    public void testApp()
+    {
+        assertTrue( true );
+    }
+}
diff --git a/continuum-core/src/test-projects/flat-multi-module/parent-project/pom.xml b/continuum-core/src/test-projects/flat-multi-module/parent-project/pom.xml
new file mode 100644
index 0000000..cbf52d6
--- /dev/null
+++ b/continuum-core/src/test-projects/flat-multi-module/parent-project/pom.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.continuum</groupId>
+  <artifactId>parent-project</artifactId>
+  <packaging>pom</packaging>
+  <version>1.0-SNAPSHOT</version>
+  <name>parent-project</name>
+  <url>http://maven.apache.org</url>
+  <scm>
+    <connection>scm:local:src/test-projects:flat-multi-module/parent-project</connection>
+    <url>http://cvs.plexus.codehaus.org/plexus-components/native/continuum/src/test-projects/flat-multi-module/parent-project</url>
+  </scm>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.1</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+  <modules>
+    <module>../module-a</module>
+    <module>../module-b</module>
+    <module>../module-c/module-d</module>
+  </modules>
+</project>
\ No newline at end of file
diff --git a/continuum-core/src/test-projects/multi-module/module-A/pom.xml b/continuum-core/src/test-projects/multi-module/module-A/pom.xml
new file mode 100644
index 0000000..58d607c
--- /dev/null
+++ b/continuum-core/src/test-projects/multi-module/module-A/pom.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0"?><project>
+<!--
+  ~ 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.
+  -->
+  <parent>
+    <artifactId>multi-module-parent</artifactId>
+    <groupId>org.apache.continuum</groupId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.continuum</groupId>
+  <artifactId>module-A</artifactId>
+  <name>module-A</name>
+  <version>1.0-SNAPSHOT</version>
+  <url>http://maven.apache.org</url>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.1</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/continuum-core/src/test-projects/multi-module/module-A/src/main/java/org/apache/continuum/module/a/App.java b/continuum-core/src/test-projects/multi-module/module-A/src/main/java/org/apache/continuum/module/a/App.java
new file mode 100644
index 0000000..de2c49d
--- /dev/null
+++ b/continuum-core/src/test-projects/multi-module/module-A/src/main/java/org/apache/continuum/module/a/App.java
@@ -0,0 +1,32 @@
+package org.apache.continuum.module.a;
+
+/*
+ * 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.
+ */
+
+/**
+ * Hello world!
+ *
+ */
+public class App 
+{
+    public static void main( String[] args )
+    {
+        System.out.println( "Hello World!" );
+    }
+}
diff --git a/continuum-core/src/test-projects/multi-module/module-A/test/java/org/apache/continuum/module/a/AppTest.java b/continuum-core/src/test-projects/multi-module/module-A/test/java/org/apache/continuum/module/a/AppTest.java
new file mode 100644
index 0000000..876714b
--- /dev/null
+++ b/continuum-core/src/test-projects/multi-module/module-A/test/java/org/apache/continuum/module/a/AppTest.java
@@ -0,0 +1,57 @@
+package org.apache.continuum.module.a;
+
+/*
+ * 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 junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Unit test for simple App.
+ */
+public class AppTest 
+    extends TestCase
+{
+    /**
+     * Create the test case
+     *
+     * @param testName name of the test case
+     */
+    public AppTest( String testName )
+    {
+        super( testName );
+    }
+
+    /**
+     * @return the suite of tests being tested
+     */
+    public static Test suite()
+    {
+        return new TestSuite( AppTest.class );
+    }
+
+    /**
+     * Rigourous Test :-)
+     */
+    public void testApp()
+    {
+        assertTrue( true );
+    }
+}
diff --git a/continuum-core/src/test-projects/multi-module/module-B/pom.xml b/continuum-core/src/test-projects/multi-module/module-B/pom.xml
new file mode 100644
index 0000000..aca86b7
--- /dev/null
+++ b/continuum-core/src/test-projects/multi-module/module-B/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0"?><project>
+<!--
+  ~ 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.
+  -->
+
+  <parent>
+    <artifactId>multi-module-parent</artifactId>
+    <groupId>org.apache.continuum</groupId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.continuum</groupId>
+  <artifactId>module-B</artifactId>
+  <name>module-B</name>
+  <version>1.0-SNAPSHOT</version>
+  <url>http://maven.apache.org</url>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.1</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/continuum-core/src/test-projects/multi-module/module-B/src/main/java/org/apache/continuum/module/b/App.java b/continuum-core/src/test-projects/multi-module/module-B/src/main/java/org/apache/continuum/module/b/App.java
new file mode 100644
index 0000000..4a35254
--- /dev/null
+++ b/continuum-core/src/test-projects/multi-module/module-B/src/main/java/org/apache/continuum/module/b/App.java
@@ -0,0 +1,32 @@
+package org.apache.continuum.module.b;
+
+/*
+ * 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.
+ */
+
+/**
+ * Hello world!
+ *
+ */
+public class App 
+{
+    public static void main( String[] args )
+    {
+        System.out.println( "Hello World!" );
+    }
+}
diff --git a/continuum-core/src/test-projects/multi-module/module-B/src/test/java/org/apache/continuum/module/b/AppTest.java b/continuum-core/src/test-projects/multi-module/module-B/src/test/java/org/apache/continuum/module/b/AppTest.java
new file mode 100644
index 0000000..0e8d12f
--- /dev/null
+++ b/continuum-core/src/test-projects/multi-module/module-B/src/test/java/org/apache/continuum/module/b/AppTest.java
@@ -0,0 +1,57 @@
+package org.apache.continuum.module.b;
+
+/*
+ * 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 junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Unit test for simple App.
+ */
+public class AppTest 
+    extends TestCase
+{
+    /**
+     * Create the test case
+     *
+     * @param testName name of the test case
+     */
+    public AppTest( String testName )
+    {
+        super( testName );
+    }
+
+    /**
+     * @return the suite of tests being tested
+     */
+    public static Test suite()
+    {
+        return new TestSuite( AppTest.class );
+    }
+
+    /**
+     * Rigourous Test :-)
+     */
+    public void testApp()
+    {
+        assertTrue( true );
+    }
+}
diff --git a/continuum-core/src/test-projects/multi-module/module-C/module-D/pom.xml b/continuum-core/src/test-projects/multi-module/module-C/module-D/pom.xml
new file mode 100644
index 0000000..d9b73e6
--- /dev/null
+++ b/continuum-core/src/test-projects/multi-module/module-C/module-D/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<!--
+  ~ 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.
+  -->
+<project>
+  <parent>
+    <artifactId>multi-module-parent</artifactId>
+    <groupId>org.apache.continuum</groupId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.continuum</groupId>
+  <artifactId>module-D</artifactId>
+  <name>module-D</name>
+  <version>1.0-SNAPSHOT</version>
+  <url>http://maven.apache.org</url>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.1</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/continuum-core/src/test-projects/multi-module/module-C/module-D/src/main/java/org/apache/continuum/module/c/App.java b/continuum-core/src/test-projects/multi-module/module-C/module-D/src/main/java/org/apache/continuum/module/c/App.java
new file mode 100644
index 0000000..bbf5ad5
--- /dev/null
+++ b/continuum-core/src/test-projects/multi-module/module-C/module-D/src/main/java/org/apache/continuum/module/c/App.java
@@ -0,0 +1,32 @@
+package org.apache.continuum.module.c;
+
+/*
+ * 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.
+ */
+
+/**
+ * Hello world!
+ *
+ */
+public class App 
+{
+    public static void main( String[] args )
+    {
+        System.out.println( "Hello World!" );
+    }
+}
diff --git a/continuum-core/src/test-projects/multi-module/module-C/module-D/src/test/java/org/apache/continuum/module/b/AppTest.java b/continuum-core/src/test-projects/multi-module/module-C/module-D/src/test/java/org/apache/continuum/module/b/AppTest.java
new file mode 100644
index 0000000..0e8d12f
--- /dev/null
+++ b/continuum-core/src/test-projects/multi-module/module-C/module-D/src/test/java/org/apache/continuum/module/b/AppTest.java
@@ -0,0 +1,57 @@
+package org.apache.continuum.module.b;
+
+/*
+ * 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 junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Unit test for simple App.
+ */
+public class AppTest 
+    extends TestCase
+{
+    /**
+     * Create the test case
+     *
+     * @param testName name of the test case
+     */
+    public AppTest( String testName )
+    {
+        super( testName );
+    }
+
+    /**
+     * @return the suite of tests being tested
+     */
+    public static Test suite()
+    {
+        return new TestSuite( AppTest.class );
+    }
+
+    /**
+     * Rigourous Test :-)
+     */
+    public void testApp()
+    {
+        assertTrue( true );
+    }
+}
diff --git a/continuum-core/src/test-projects/multi-module/pom.xml b/continuum-core/src/test-projects/multi-module/pom.xml
new file mode 100644
index 0000000..14238d4
--- /dev/null
+++ b/continuum-core/src/test-projects/multi-module/pom.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.continuum</groupId>
+  <artifactId>multi-module-parent</artifactId>
+  <packaging>pom</packaging>
+  <version>1.0-SNAPSHOT</version>
+  <name>multi-module-parent</name>
+  <url>http://maven.apache.org</url>
+  <scm>
+    <connection>scm:local:src/test-projects:multi-module</connection>
+    <url>http://cvs.plexus.codehaus.org/plexus-components/native/continuum/src/test-projects/multi-module</url>
+  </scm>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.1</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+  <modules>
+    <module>module-A</module>
+    <module>module-B</module>
+    <module>module-C/module-D</module>
+  </modules>
+</project>
diff --git a/continuum-core/src/test/java/org/apache/continuum/AbstractAddProjectTest.java b/continuum-core/src/test/java/org/apache/continuum/AbstractAddProjectTest.java
new file mode 100644
index 0000000..4d249da
--- /dev/null
+++ b/continuum-core/src/test/java/org/apache/continuum/AbstractAddProjectTest.java
@@ -0,0 +1,58 @@
+package org.apache.continuum;
+
+/*
+ * 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 org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.continuum.AbstractContinuumTest;
+import org.apache.maven.continuum.execution.maven.m2.MavenBuilderHelper;
+import org.apache.maven.continuum.execution.maven.m2.SettingsConfigurationException;
+import org.codehaus.plexus.util.FileUtils;
+
+import java.io.File;
+import java.io.IOException;
+
+public abstract class AbstractAddProjectTest
+    extends AbstractContinuumTest
+{
+    private static void mkdirs( File directory )
+        throws IOException
+    {
+        if ( !directory.exists() && !directory.mkdirs() )
+        {
+            throw new IOException( "Unable to create repository " + directory );
+        }
+    }
+
+    protected void createLocalRepository()
+        throws IOException, SettingsConfigurationException
+    {
+        MavenBuilderHelper helper = (MavenBuilderHelper) lookup( MavenBuilderHelper.class );
+        ArtifactRepository repo = helper.getLocalRepository();
+
+        File localRepo = new File( repo.getBasedir() );
+        mkdirs( localRepo );
+
+        File artifact = new File( localRepo,
+                                  "org/apache/maven/continuum/continuum-parent/1.0.3/continuum-parent-1.0.3.pom" );
+        mkdirs( artifact.getParentFile() );
+
+        FileUtils.copyFile( getTestFile( "src/test/resources/projects/continuum/pom.xml" ), artifact );
+    }
+}
diff --git a/continuum-core/src/test/java/org/apache/continuum/builder/distributed/manager/DefaultDistributedBuildManagerTest.java b/continuum-core/src/test/java/org/apache/continuum/builder/distributed/manager/DefaultDistributedBuildManagerTest.java
new file mode 100644
index 0000000..58d58ac
--- /dev/null
+++ b/continuum-core/src/test/java/org/apache/continuum/builder/distributed/manager/DefaultDistributedBuildManagerTest.java
@@ -0,0 +1,711 @@
+package org.apache.continuum.builder.distributed.manager;
+
+/*
+ * 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 org.apache.continuum.builder.distributed.executor.ThreadedDistributedBuildTaskQueueExecutor;
+import org.apache.continuum.builder.distributed.stubs.DefaultDistributedBuildManagerStub;
+import org.apache.continuum.configuration.BuildAgentConfiguration;
+import org.apache.continuum.configuration.BuildAgentGroupConfiguration;
+import org.apache.continuum.dao.BuildDefinitionDao;
+import org.apache.continuum.dao.BuildResultDao;
+import org.apache.continuum.dao.ProjectDao;
+import org.apache.continuum.dao.ProjectScmRootDao;
+import org.apache.continuum.model.project.ProjectRunSummary;
+import org.apache.continuum.model.project.ProjectScmRoot;
+import org.apache.continuum.taskqueue.BuildProjectTask;
+import org.apache.continuum.taskqueue.OverallDistributedBuildQueue;
+import org.apache.continuum.taskqueue.PrepareBuildProjectsTask;
+import org.apache.continuum.utils.build.BuildTrigger;
+import org.apache.maven.continuum.configuration.ConfigurationService;
+import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.BuildResult;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.project.ProjectGroup;
+import org.apache.maven.continuum.model.system.Profile;
+import org.apache.maven.continuum.project.ContinuumProjectState;
+import org.codehaus.plexus.spring.PlexusInSpringTestCase;
+import org.codehaus.plexus.taskqueue.Task;
+import org.codehaus.plexus.taskqueue.TaskQueue;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.integration.junit3.JUnit3Mockery;
+import org.jmock.lib.legacy.ClassImposteriser;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class DefaultDistributedBuildManagerTest
+    extends PlexusInSpringTestCase
+{
+    private final String TEST_BUILD_AGENT1 = "http://sampleagent";
+
+    private final String TEST_BUILD_AGENT2 = "http://testagent";
+
+    private final String TEST_BUILD_AGENT_GROUP1 = "buildAgentGroup1";
+
+    private DefaultDistributedBuildManager distributedBuildManager;
+
+    private DefaultDistributedBuildManager distributedBuildManagerStub = new DefaultDistributedBuildManagerStub();
+
+    private Mockery context;
+
+    private OverallDistributedBuildQueue overallDistributedBuildQueue1;
+
+    private OverallDistributedBuildQueue overallDistributedBuildQueue2;
+
+    private BuildDefinitionDao buildDefinitionDao;
+
+    private BuildResultDao buildResultDao;
+
+    private ProjectDao projectDao;
+
+    private ProjectScmRootDao projectScmRootDao;
+
+    private ConfigurationService configurationService;
+
+    private List<BuildAgentConfiguration> buildAgents;
+
+    private BuildAgentConfiguration buildAgent1;
+
+    private BuildAgentConfiguration buildAgent2;
+
+    private ThreadedDistributedBuildTaskQueueExecutor distributedBuildTaskQueueExecutor;
+
+    private TaskQueue distributedBuildQueue;
+
+    private Project project;
+
+    private Project project2;
+
+    private ProjectGroup projectGroup;
+
+    private BuildDefinition buildDefinition;
+
+    private BuildAgentGroupConfiguration buildAgentGroup;
+
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        context = new JUnit3Mockery();
+        context.setImposteriser( ClassImposteriser.INSTANCE );
+
+        distributedBuildManager = (DefaultDistributedBuildManager) lookup( DistributedBuildManager.class );
+
+        buildDefinitionDao = context.mock( BuildDefinitionDao.class );
+        distributedBuildManager.setBuildDefinitionDao( buildDefinitionDao );
+        distributedBuildManagerStub.setBuildDefinitionDao( buildDefinitionDao );
+
+        buildResultDao = context.mock( BuildResultDao.class );
+        distributedBuildManager.setBuildResultDao( buildResultDao );
+        distributedBuildManagerStub.setBuildResultDao( buildResultDao );
+
+        projectDao = context.mock( ProjectDao.class );
+        distributedBuildManager.setProjectDao( projectDao );
+        distributedBuildManagerStub.setProjectDao( projectDao );
+
+        projectScmRootDao = context.mock( ProjectScmRootDao.class );
+        distributedBuildManager.setProjectScmRootDao( projectScmRootDao );
+        distributedBuildManagerStub.setProjectScmRootDao( projectScmRootDao );
+
+        distributedBuildManagerStub.setContainer( getContainer() );
+
+        configurationService = context.mock( ConfigurationService.class );
+
+        distributedBuildManager.setConfigurationService( configurationService );
+        distributedBuildManagerStub.setConfigurationService( configurationService );
+
+        distributedBuildTaskQueueExecutor = (ThreadedDistributedBuildTaskQueueExecutor) context.mock(
+            ThreadedDistributedBuildTaskQueueExecutor.class, "distributed-build-project" );
+
+        distributedBuildQueue = context.mock( TaskQueue.class, "distributed-build-queue" );
+
+        overallDistributedBuildQueue1 = context.mock( OverallDistributedBuildQueue.class, TEST_BUILD_AGENT1 );
+        overallDistributedBuildQueue2 = context.mock( OverallDistributedBuildQueue.class, TEST_BUILD_AGENT2 );
+
+        init();
+    }
+
+    private void init()
+    {
+        buildAgent1 = new BuildAgentConfiguration();
+        buildAgent1.setEnabled( true );
+        buildAgent1.setUrl( TEST_BUILD_AGENT1 );
+
+        buildAgent2 = new BuildAgentConfiguration();
+        buildAgent2.setEnabled( true );
+        buildAgent2.setUrl( TEST_BUILD_AGENT2 );
+
+        List<BuildAgentConfiguration> buildAgents = new ArrayList<BuildAgentConfiguration>();
+        buildAgents.add( buildAgent1 );
+        buildAgents.add( buildAgent2 );
+
+        setUpBuildAgentGroup( buildAgents );
+        setupBuildDefinition();
+
+        projectGroup = new ProjectGroup();
+        projectGroup.setId( 1 );
+        projectGroup.setGroupId( "group" );
+
+        project = new Project();
+        project.setId( 1 );
+        project.setGroupId( "groupId" );
+        project.setArtifactId( "artifactId" );
+        project.setVersion( "1.0" );
+        project.setProjectGroup( projectGroup );
+
+        project2 = new Project();
+        project2.setId( 2 );
+        project2.setGroupId( "groupId" );
+        project2.setArtifactId( "artifactId" );
+        project2.setVersion( "1.0" );
+        project2.setProjectGroup( projectGroup );
+    }
+
+    public void testViewQueuesAfterBuildAgentIsLost()
+        throws Exception
+    {
+        distributedBuildManager.setOverallDistributedBuildQueues( getMockOverallDistributedBuildQueues( 1 ) );
+
+        recordViewQueuesAfterBuildAgentIsLost();
+
+        Map<String, List<PrepareBuildProjectsTask>> prepareBuildQueues =
+            distributedBuildManager.getProjectsInPrepareBuildQueue();
+        Map<String, List<BuildProjectTask>> buildQueues = distributedBuildManager.getProjectsInBuildQueue();
+        Map<String, PrepareBuildProjectsTask> currentPrepareBuild =
+            distributedBuildManager.getProjectsCurrentlyPreparingBuild();
+        Map<String, BuildProjectTask> currentBuild = distributedBuildManager.getProjectsCurrentlyBuilding();
+
+        assertEquals( prepareBuildQueues.size(), 0 );
+        assertEquals( buildQueues.size(), 0 );
+        assertEquals( currentPrepareBuild.size(), 0 );
+        assertEquals( currentBuild.size(), 0 );
+
+        context.assertIsSatisfied();
+    }
+
+    public void testDisableBuildAgentWhenUnavailableToPing()
+        throws Exception
+    {
+        distributedBuildManager.setOverallDistributedBuildQueues( getMockOverallDistributedBuildQueues( 1 ) );
+
+        recordDisableOfBuildAgent();
+
+        distributedBuildManager.isAgentAvailable( TEST_BUILD_AGENT1 );
+
+        context.assertIsSatisfied();
+    }
+
+    public void testViewQueuesWhen2BuildAgentsAreLost()
+        throws Exception
+    {
+        distributedBuildManager.setOverallDistributedBuildQueues( getMockOverallDistributedBuildQueues( 2 ) );
+
+        recordViewQueuesAfter2BuildAgentsAreLost();
+
+        Map<String, List<PrepareBuildProjectsTask>> prepareBuildQueues =
+            distributedBuildManager.getProjectsInPrepareBuildQueue();
+        Map<String, List<BuildProjectTask>> buildQueues = distributedBuildManager.getProjectsInBuildQueue();
+        Map<String, PrepareBuildProjectsTask> currentPrepareBuild =
+            distributedBuildManager.getProjectsCurrentlyPreparingBuild();
+        Map<String, BuildProjectTask> currentBuild = distributedBuildManager.getProjectsCurrentlyBuilding();
+
+        assertEquals( prepareBuildQueues.size(), 0 );
+        assertEquals( buildQueues.size(), 0 );
+        assertEquals( currentPrepareBuild.size(), 0 );
+        assertEquals( currentBuild.size(), 0 );
+
+        context.assertIsSatisfied();
+    }
+
+    public void testBuildProjectWithBuildAgentGroupWithNoCurrentBuilds()
+        throws Exception
+    {
+        distributedBuildManagerStub.setOverallDistributedBuildQueues( getMockOverallDistributedBuildQueues( 2 ) );
+
+        Map<Integer, Integer> projectsBuildDefinitionsMap = new HashMap<Integer, Integer>();
+        projectsBuildDefinitionsMap.put( 1, 1 );
+        projectsBuildDefinitionsMap.put( 2, 1 );
+
+        BuildTrigger buildTrigger = new BuildTrigger( 1 );
+
+        recordBuildOfProjectWithBuildAgentGroupWithNoCurrentBuilds();
+
+        List<ProjectScmRoot> scmRoots = new ArrayList<ProjectScmRoot>();
+        ProjectScmRoot scmRoot = new ProjectScmRoot();
+        scmRoot.setId( 1 );
+        scmRoot.setProjectGroup( projectGroup );
+        scmRoot.setScmRootAddress( "scmRootAddress1" );
+        scmRoots.add( scmRoot );
+
+        scmRoot = new ProjectScmRoot();
+        scmRoot.setId( 2 );
+        scmRoot.setProjectGroup( projectGroup );
+        scmRoot.setScmRootAddress( "scmRootAddress2" );
+        scmRoots.add( scmRoot );
+
+        distributedBuildManagerStub.prepareBuildProjects( projectsBuildDefinitionsMap, buildTrigger, 1, "sample",
+                                                          "scmRootAddress1", 1, scmRoots );
+
+        context.assertIsSatisfied();
+    }
+
+    public void testBuildProjectWithBuildAgentGroupWithCurrentBuild()
+        throws Exception
+    {
+        distributedBuildManagerStub.setOverallDistributedBuildQueues( getMockOverallDistributedBuildQueues( 2 ) );
+
+        Map<Integer, Integer> projectsBuildDefinitionsMap = new HashMap<Integer, Integer>();
+        projectsBuildDefinitionsMap.put( 1, 1 );
+
+        BuildTrigger buildTrigger = new BuildTrigger( 1 );
+
+        recordBuildOfProjectWithBuildAgentGroupWithCurrentBuild();
+
+        List<ProjectScmRoot> scmRoots = new ArrayList<ProjectScmRoot>();
+        ProjectScmRoot scmRoot = new ProjectScmRoot();
+        scmRoot.setId( 2 );
+        scmRoot.setProjectGroup( projectGroup );
+        scmRoot.setScmRootAddress( "scmRootAddress2" );
+        scmRoots.add( scmRoot );
+
+        scmRoot = new ProjectScmRoot();
+        scmRoot.setId( 1 );
+        scmRoot.setProjectGroup( projectGroup );
+        scmRoot.setScmRootAddress( "scmRootAddress1" );
+        scmRoots.add( scmRoot );
+
+        distributedBuildManagerStub.prepareBuildProjects( projectsBuildDefinitionsMap, buildTrigger, 1, "sample",
+                                                          "scmRootAddress1", 1, scmRoots );
+
+        context.assertIsSatisfied();
+    }
+
+    // CONTINUUM-2494
+    public void testBuildProjectWithTheSecondBuildAgentAttachedToTheBuildAgentGroup()
+        throws Exception
+    {
+        distributedBuildManagerStub.setOverallDistributedBuildQueues( getMockOverallDistributedBuildQueues( 2 ) );
+
+        List<BuildAgentConfiguration> buildAgents = new ArrayList<BuildAgentConfiguration>();
+        buildAgents.add( buildAgent2 );
+
+        setUpBuildAgentGroup( buildAgents );
+        setupBuildDefinition();
+
+        Map<Integer, Integer> projectsBuildDefinitionsMap = new HashMap<Integer, Integer>();
+        projectsBuildDefinitionsMap.put( 1, 1 );
+
+        BuildTrigger buildTrigger = new BuildTrigger( 1 );
+
+        recordBuildProjectWithTheSecondBuildAgentAttachedToTheBuildAgentGroup();
+
+        List<ProjectScmRoot> scmRoots = new ArrayList<ProjectScmRoot>();
+        ProjectScmRoot scmRoot = new ProjectScmRoot();
+        scmRoot.setId( 1 );
+        scmRoot.setProjectGroup( projectGroup );
+        scmRoot.setScmRootAddress( "scmRootAddress1" );
+        scmRoots.add( scmRoot );
+
+        distributedBuildManagerStub.prepareBuildProjects( projectsBuildDefinitionsMap, buildTrigger, 1, "sample",
+                                                          "scmRootAddress", 1, scmRoots );
+    }
+
+    public void testGetBuildAgentPlatform()
+        throws Exception
+    {
+        distributedBuildManager.setOverallDistributedBuildQueues( getMockOverallDistributedBuildQueues( 1 ) );
+        context.checking( new Expectations()
+        {
+            {
+                exactly( 2 ).of( configurationService ).getBuildAgents();
+                will( returnValue( buildAgents ) );
+
+                one( configurationService ).getSharedSecretPassword();
+                will( returnValue( null ) );
+
+                one( configurationService ).updateBuildAgent( buildAgent1 );
+                one( configurationService ).store();
+
+                exactly( 2 ).of( overallDistributedBuildQueue1 ).getDistributedBuildTaskQueueExecutor();
+                will( returnValue( distributedBuildTaskQueueExecutor ) );
+
+                one( distributedBuildTaskQueueExecutor ).getCurrentTask();
+                will( returnValue( null ) );
+
+                one( overallDistributedBuildQueue1 ).getProjectsInQueue();
+                will( returnValue( new ArrayList<PrepareBuildProjectsTask>() ) );
+
+                one( overallDistributedBuildQueue1 ).getDistributedBuildQueue();
+                will( returnValue( distributedBuildQueue ) );
+
+                one( distributedBuildQueue ).removeAll( new ArrayList<PrepareBuildProjectsTask>() );
+
+                one( distributedBuildTaskQueueExecutor ).stop();
+            }
+        } );
+        assertEquals( distributedBuildManager.getBuildAgentPlatform( TEST_BUILD_AGENT1 ), "" );
+        context.assertIsSatisfied();
+    }
+
+    public void testBuildAgentIsAvailable()
+        throws Exception
+    {
+        assertTrue( distributedBuildManagerStub.isAgentAvailable( TEST_BUILD_AGENT1 ) );
+        context.checking( new Expectations()
+        {
+            {
+                never( configurationService ).getBuildAgents();
+                never( configurationService ).updateBuildAgent( buildAgent1 );
+                never( configurationService ).store();
+            }
+        } );
+        context.assertIsSatisfied();
+    }
+
+    public void testCancelBuildStuckUpdate()
+        throws Exception
+    {
+        distributedBuildManagerStub.setCurrentRuns( getCurrentRuns() );
+
+        recordOfStuckScm();
+
+        distributedBuildManagerStub.cancelBuild( 1 );
+    }
+
+    public void testCancelBuildStuckBuild()
+        throws Exception
+    {
+        distributedBuildManagerStub.setCurrentRuns( getCurrentRuns() );
+
+        recordOfStuckBuild();
+
+        distributedBuildManagerStub.cancelBuild( 1 );
+    }
+
+    private void recordOfStuckBuild()
+        throws Exception
+    {
+        context.checking( new Expectations()
+        {
+            {
+                exactly( 4 ).of( configurationService ).getBuildAgents();
+                will( returnValue( buildAgents ) );
+
+                exactly( 2 ).of( projectScmRootDao ).getProjectScmRoot( 1 );
+                will( returnValue( getScmRoot( ContinuumProjectState.OK ) ) );
+
+                Project proj1 = getProject( 1, ContinuumProjectState.BUILDING );
+                one( projectDao ).getProject( 1 );
+                will( returnValue( proj1 ) );
+
+                one( buildDefinitionDao ).getBuildDefinition( 1 );
+                will( returnValue( new BuildDefinition() ) );
+
+                one( buildResultDao ).addBuildResult( with( any( Project.class ) ), with( any( BuildResult.class ) ) );
+                one( projectDao ).updateProject( proj1 );
+
+                one( projectDao ).getProject( 2 );
+                will( returnValue( getProject( 2, ContinuumProjectState.OK ) ) );
+            }
+        } );
+    }
+
+    private void recordOfStuckScm()
+        throws Exception
+    {
+        context.checking( new Expectations()
+        {
+            {
+                exactly( 4 ).of( configurationService ).getBuildAgents();
+                will( returnValue( buildAgents ) );
+
+                ProjectScmRoot scmRootUpdating = getScmRoot( ContinuumProjectState.UPDATING );
+                one( projectScmRootDao ).getProjectScmRoot( 1 );
+                will( returnValue( scmRootUpdating ) );
+
+                one( projectScmRootDao ).updateProjectScmRoot( scmRootUpdating );
+
+                one( projectScmRootDao ).getProjectScmRoot( 1 );
+                will( returnValue( getScmRoot( ContinuumProjectState.ERROR ) ) );
+            }
+        } );
+    }
+
+    private List<ProjectRunSummary> getCurrentRuns()
+    {
+        List<ProjectRunSummary> runs = new ArrayList<ProjectRunSummary>();
+
+        ProjectRunSummary run1 = new ProjectRunSummary();
+        run1.setProjectId( 1 );
+        run1.setBuildDefinitionId( 1 );
+        run1.setProjectGroupId( 1 );
+        run1.setProjectScmRootId( 1 );
+        run1.setTrigger( 1 );
+        run1.setTriggeredBy( "user" );
+        run1.setBuildAgentUrl( "http://localhost:8181/continuum-buildagent/xmlrpc" );
+        runs.add( run1 );
+
+        ProjectRunSummary run2 = new ProjectRunSummary();
+        run2.setProjectId( 2 );
+        run2.setBuildDefinitionId( 2 );
+        run2.setProjectGroupId( 1 );
+        run2.setProjectScmRootId( 1 );
+        run2.setTrigger( 1 );
+        run2.setTriggeredBy( "user" );
+        run2.setBuildAgentUrl( "http://localhost:8181/continuum-buildagent/xmlrpc" );
+        runs.add( run2 );
+
+        return runs;
+    }
+
+    private ProjectScmRoot getScmRoot( int state )
+    {
+        ProjectScmRoot scmRoot = new ProjectScmRoot();
+        scmRoot.setState( state );
+        return scmRoot;
+    }
+
+    private Project getProject( int projectId, int state )
+    {
+        Project project = new Project();
+        project.setId( projectId );
+        project.setState( state );
+        return project;
+    }
+
+    private Map<String, OverallDistributedBuildQueue> getMockOverallDistributedBuildQueues( int size )
+    {
+        Map<String, OverallDistributedBuildQueue> overallDistributedBuildQueues = Collections.synchronizedMap(
+            new LinkedHashMap<String, OverallDistributedBuildQueue>() );
+
+        buildAgents = new ArrayList<BuildAgentConfiguration>();
+        buildAgents.add( buildAgent1 );
+
+        overallDistributedBuildQueues.put( TEST_BUILD_AGENT1, overallDistributedBuildQueue1 );
+
+        if ( size == 2 )
+        {
+            buildAgents.add( buildAgent2 );
+            overallDistributedBuildQueues.put( TEST_BUILD_AGENT2, overallDistributedBuildQueue2 );
+        }
+
+        return overallDistributedBuildQueues;
+    }
+
+    private void setUpBuildAgentGroup( List<BuildAgentConfiguration> buildAgents )
+    {
+        buildAgentGroup = new BuildAgentGroupConfiguration();
+        buildAgentGroup.setName( TEST_BUILD_AGENT_GROUP1 );
+        buildAgentGroup.setBuildAgents( buildAgents );
+    }
+
+    private void setupBuildDefinition()
+    {
+        Profile buildEnv1 = new Profile();
+        buildEnv1.setBuildAgentGroup( TEST_BUILD_AGENT_GROUP1 );
+
+        buildDefinition = new BuildDefinition();
+        buildDefinition.setId( 1 );
+        buildDefinition.setProfile( buildEnv1 );
+    }
+
+    private void recordDisableOfBuildAgent()
+        throws Exception
+    {
+        context.checking( new Expectations()
+        {
+            {
+                one( configurationService ).getBuildAgents();
+                will( returnValue( buildAgents ) );
+
+                one( configurationService ).getSharedSecretPassword();
+                will( returnValue( null ) );
+
+                one( configurationService ).updateBuildAgent( buildAgent1 );
+                one( configurationService ).store();
+            }
+        } );
+    }
+
+    private void recordViewQueuesAfterBuildAgentIsLost()
+        throws Exception
+    {
+        context.checking( new Expectations()
+        {
+            {
+                exactly( 5 ).of( configurationService ).getBuildAgents();
+                will( returnValue( buildAgents ) );
+
+                one( configurationService ).getSharedSecretPassword();
+                will( returnValue( null ) );
+
+                one( configurationService ).updateBuildAgent( buildAgent1 );
+                one( configurationService ).store();
+
+                exactly( 2 ).of( overallDistributedBuildQueue1 ).getDistributedBuildTaskQueueExecutor();
+                will( returnValue( distributedBuildTaskQueueExecutor ) );
+
+                one( distributedBuildTaskQueueExecutor ).getCurrentTask();
+                will( returnValue( null ) );
+
+                one( overallDistributedBuildQueue1 ).getProjectsInQueue();
+                will( returnValue( new ArrayList<PrepareBuildProjectsTask>() ) );
+
+                one( overallDistributedBuildQueue1 ).getDistributedBuildQueue();
+                will( returnValue( distributedBuildQueue ) );
+
+                one( distributedBuildQueue ).removeAll( new ArrayList<PrepareBuildProjectsTask>() );
+
+                one( distributedBuildTaskQueueExecutor ).stop();
+            }
+        } );
+    }
+
+    private void recordViewQueuesAfter2BuildAgentsAreLost()
+        throws Exception
+    {
+        context.checking( new Expectations()
+        {
+            {
+                exactly( 6 ).of( configurationService ).getBuildAgents();
+                will( returnValue( buildAgents ) );
+
+                exactly( 2 ).of( configurationService ).getSharedSecretPassword();
+                will( returnValue( null ) );
+
+                one( configurationService ).updateBuildAgent( buildAgent1 );
+                one( configurationService ).updateBuildAgent( buildAgent2 );
+                exactly( 2 ).of( configurationService ).store();
+
+                exactly( 2 ).of( overallDistributedBuildQueue1 ).getDistributedBuildTaskQueueExecutor();
+                will( returnValue( distributedBuildTaskQueueExecutor ) );
+
+                exactly( 2 ).of( overallDistributedBuildQueue2 ).getDistributedBuildTaskQueueExecutor();
+                will( returnValue( distributedBuildTaskQueueExecutor ) );
+
+                exactly( 2 ).of( distributedBuildTaskQueueExecutor ).getCurrentTask();
+                will( returnValue( null ) );
+
+                one( overallDistributedBuildQueue1 ).getProjectsInQueue();
+                will( returnValue( new ArrayList<PrepareBuildProjectsTask>() ) );
+
+                one( overallDistributedBuildQueue2 ).getProjectsInQueue();
+                will( returnValue( new ArrayList<PrepareBuildProjectsTask>() ) );
+
+                one( overallDistributedBuildQueue1 ).getDistributedBuildQueue();
+                will( returnValue( distributedBuildQueue ) );
+
+                one( overallDistributedBuildQueue2 ).getDistributedBuildQueue();
+                will( returnValue( distributedBuildQueue ) );
+
+                exactly( 2 ).of( distributedBuildQueue ).removeAll( new ArrayList<PrepareBuildProjectsTask>() );
+
+                exactly( 2 ).of( distributedBuildTaskQueueExecutor ).stop();
+            }
+        } );
+    }
+
+    private void recordBuildOfProjectWithBuildAgentGroupWithNoCurrentBuilds()
+        throws Exception
+    {
+        context.checking( new Expectations()
+        {
+            {
+                exactly( 3 ).of( projectDao ).getProjectWithDependencies( 1 );
+                will( returnValue( project ) );
+
+                exactly( 3 ).of( projectDao ).getProjectWithDependencies( 2 );
+                will( returnValue( project2 ) );
+
+                exactly( 3 ).of( buildDefinitionDao ).getBuildDefinition( 1 );
+                will( returnValue( buildDefinition ) );
+
+                exactly( 3 ).of( configurationService ).getBuildAgentGroup( TEST_BUILD_AGENT_GROUP1 );
+                will( returnValue( buildAgentGroup ) );
+
+                one( configurationService ).getBuildAgents();
+                will( returnValue( buildAgents ) );
+
+                one( overallDistributedBuildQueue1 ).getBuildAgentUrl();
+
+                one( overallDistributedBuildQueue1 ).addToDistributedBuildQueue( with( any( Task.class ) ) );
+            }
+        } );
+    }
+
+    private void recordBuildOfProjectWithBuildAgentGroupWithCurrentBuild()
+        throws Exception
+    {
+        context.checking( new Expectations()
+        {
+            {
+                one( overallDistributedBuildQueue1 ).getProjectsInQueue();
+
+                one( overallDistributedBuildQueue1 ).getDistributedBuildTaskQueueExecutor();
+                will( returnValue( distributedBuildTaskQueueExecutor ) );
+
+                one( distributedBuildTaskQueueExecutor ).getCurrentTask();
+                will( returnValue( null ) );
+
+                one( projectDao ).getProjectsInGroup( 1 );
+                will( returnValue( new ArrayList<Project>() ) );
+
+                one( configurationService ).getBuildAgents();
+                will( returnValue( buildAgents ) );
+
+                one( overallDistributedBuildQueue1 ).getBuildAgentUrl();
+
+                one( overallDistributedBuildQueue1 ).addToDistributedBuildQueue( with( any( Task.class ) ) );
+            }
+        } );
+    }
+
+    private void recordBuildProjectWithTheSecondBuildAgentAttachedToTheBuildAgentGroup()
+        throws Exception
+    {
+        context.checking( new Expectations()
+        {
+            {
+                exactly( 3 ).of( projectDao ).getProjectWithDependencies( 1 );
+                will( returnValue( project ) );
+
+                exactly( 3 ).of( buildDefinitionDao ).getBuildDefinition( 1 );
+                will( returnValue( buildDefinition ) );
+
+                exactly( 3 ).of( configurationService ).getBuildAgentGroup( TEST_BUILD_AGENT_GROUP1 );
+                will( returnValue( buildAgentGroup ) );
+
+                one( configurationService ).getBuildAgents();
+                will( returnValue( buildAgents ) );
+
+                one( overallDistributedBuildQueue2 ).getBuildAgentUrl();
+
+                one( overallDistributedBuildQueue2 ).addToDistributedBuildQueue( with( any( Task.class ) ) );
+            }
+        } );
+    }
+}
\ No newline at end of file
diff --git a/continuum-core/src/test/java/org/apache/continuum/builder/distributed/stubs/DefaultDistributedBuildManagerStub.java b/continuum-core/src/test/java/org/apache/continuum/builder/distributed/stubs/DefaultDistributedBuildManagerStub.java
new file mode 100644
index 0000000..01dbb92
--- /dev/null
+++ b/continuum-core/src/test/java/org/apache/continuum/builder/distributed/stubs/DefaultDistributedBuildManagerStub.java
@@ -0,0 +1,33 @@
+package org.apache.continuum.builder.distributed.stubs;
+
+/*
+ * 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 org.apache.continuum.builder.distributed.manager.DefaultDistributedBuildManager;
+import org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportService;
+
+public class DefaultDistributedBuildManagerStub
+    extends DefaultDistributedBuildManager
+{
+    @Override
+    public SlaveBuildAgentTransportService createSlaveBuildAgentTransportClientConnection( String buildAgentUrl )
+    {
+        return new SlaveBuildAgentTransportClientStub();
+    }
+}
diff --git a/continuum-core/src/test/java/org/apache/continuum/builder/distributed/stubs/SlaveBuildAgentTransportClientStub.java b/continuum-core/src/test/java/org/apache/continuum/builder/distributed/stubs/SlaveBuildAgentTransportClientStub.java
new file mode 100644
index 0000000..fdcdd18
--- /dev/null
+++ b/continuum-core/src/test/java/org/apache/continuum/builder/distributed/stubs/SlaveBuildAgentTransportClientStub.java
@@ -0,0 +1,304 @@
+package org.apache.continuum.builder.distributed.stubs;
+
+/*
+ * 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 org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+public class SlaveBuildAgentTransportClientStub
+    implements SlaveBuildAgentTransportService
+{
+    public Boolean buildProjects( List<Map<String, Object>> projectsBuildContext )
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Boolean cancelBuild()
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public String generateWorkingCopyContent( int projectId, String directory, String baseUrl, String imagesBaseUrl )
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public List<Map<String, String>> getAvailableInstallations()
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Map<String, Object> getBuildResult( int projectId )
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Integer getBuildSizeOfAgent()
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    public Map getListener( String releaseId )
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public String getPreparedReleaseName( String releaseId )
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Map<String, Object> getProjectCurrentlyBuilding()
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Map<String, Object> getProjectCurrentlyPreparingBuild()
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Map<String, Object> getProjectFile( int projectId, String directory, String filename )
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public List<Map<String, Object>> getProjectsInBuildQueue()
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public List<Map<String, Object>> getProjectsInPrepareBuildQueue()
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Map getReleasePluginParameters( int projectId, String pomFilename )
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Map<String, Object> getReleaseResult( String releaseId )
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Boolean isProjectCurrentlyBuilding( int projectId, int buildDefinitionId )
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Boolean isProjectGroupInQueue( int projectGroupId )
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Boolean isProjectScmRootInQueue( int projectScmRootId, List<Integer> projectIds )
+    {
+        return true;
+    }
+
+    public Boolean isProjectInBuildQueue( int projectId, int buildDefinitionId )
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Boolean ping()
+        throws Exception
+    {
+        return true;
+    }
+
+    public List<Map<String, String>> processProject( int projectId, String pomFilename, boolean autoVersionSubmodules )
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public String releaseCleanup( String releaseId )
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Boolean releasePerform( String releaseId, String goals, String arguments, boolean useReleaseProfile,
+                                   Map repository, String username )
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public String releasePerformFromScm( String goals, String arguments, boolean useReleaseProfile, Map repository,
+                                         String scmUrl, String scmUsername, String scmPassword, String scmTag,
+                                         String scmTagBase, Map environments, String username )
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public String releasePrepare( Map project, Properties properties, Map releaseVersion, Map developmentVersion,
+                                  Map environments, String username )
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Boolean releaseRollback( String releaseId, int projectId )
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Boolean removeFromBuildQueue( int projectId, int buildDefinitionId )
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Boolean removeFromBuildQueue( List<String> hashCodes )
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Boolean removeFromPrepareBuildQueue( int projectGroupId, int scmRootId )
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Boolean removeFromPrepareBuildQueue( List<String> hashCodes )
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Boolean removeListener( String releaseId )
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public List<Map<String, Object>> getProjectsAndBuildDefinitionsCurrentlyPreparingBuild()
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public List<Map<String, Object>> getProjectsAndBuildDefinitionsInPrepareBuildQueue()
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Boolean isProjectGroupInPrepareBuildQueue( int projectGroupId )
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Boolean isProjectGroupCurrentlyPreparingBuild( int projectGroupId )
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public String getBuildAgentPlatform()
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Boolean isProjectCurrentlyPreparingBuild( int projectId, int buildDefinitionId )
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Boolean isProjectInPrepareBuildQueue( int projectId, int buildDefinitionId )
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public void executeDirectoryPurge( String directoryType, int daysOlder, int retentionCount, boolean deleteAll )
+        throws Exception
+    {
+        // TODO Auto-generated method stub
+
+    }
+
+}
diff --git a/continuum-core/src/test/java/org/apache/continuum/builder/distributed/work/DefaultContinuumWorkerTest.java b/continuum-core/src/test/java/org/apache/continuum/builder/distributed/work/DefaultContinuumWorkerTest.java
new file mode 100644
index 0000000..587d8b7
--- /dev/null
+++ b/continuum-core/src/test/java/org/apache/continuum/builder/distributed/work/DefaultContinuumWorkerTest.java
@@ -0,0 +1,208 @@
+package org.apache.continuum.builder.distributed.work;
+
+/*
+ * 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 org.apache.continuum.builder.distributed.manager.DistributedBuildManager;
+import org.apache.continuum.dao.BuildDefinitionDao;
+import org.apache.continuum.dao.BuildResultDao;
+import org.apache.continuum.dao.ProjectDao;
+import org.apache.continuum.dao.ProjectScmRootDao;
+import org.apache.continuum.model.project.ProjectRunSummary;
+import org.apache.continuum.model.project.ProjectScmRoot;
+import org.apache.maven.continuum.configuration.ConfigurationService;
+import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.BuildResult;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.project.ContinuumProjectState;
+import org.codehaus.plexus.spring.PlexusInSpringTestCase;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.integration.junit3.JUnit3Mockery;
+import org.jmock.lib.legacy.ClassImposteriser;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class DefaultContinuumWorkerTest
+    extends PlexusInSpringTestCase
+{
+    private Mockery context;
+
+    private ProjectDao projectDao;
+
+    private ProjectScmRootDao projectScmRootDao;
+
+    private BuildDefinitionDao buildDefinitionDao;
+
+    private BuildResultDao buildResultDao;
+
+    private DistributedBuildManager distributedBuildManager;
+
+    private ConfigurationService configurationService;
+
+    private DefaultContinuumWorker worker;
+
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+        context = new JUnit3Mockery();
+        context.setImposteriser( ClassImposteriser.INSTANCE );
+
+        projectDao = context.mock( ProjectDao.class );
+        projectScmRootDao = context.mock( ProjectScmRootDao.class );
+        buildDefinitionDao = context.mock( BuildDefinitionDao.class );
+        buildResultDao = context.mock( BuildResultDao.class );
+        configurationService = context.mock( ConfigurationService.class );
+        distributedBuildManager = context.mock( DistributedBuildManager.class );
+
+        worker = (DefaultContinuumWorker) lookup( ContinuumWorker.class );
+        worker.setBuildDefinitionDao( buildDefinitionDao );
+        worker.setBuildResultDao( buildResultDao );
+        worker.setProjectDao( projectDao );
+        worker.setProjectScmRootDao( projectScmRootDao );
+        worker.setConfigurationService( configurationService );
+        worker.setDistributedBuildManager( distributedBuildManager );
+    }
+
+    public void testWorkerWithStuckBuild()
+        throws Exception
+    {
+        recordOfStuckBuild();
+
+        worker.work();
+
+        context.assertIsSatisfied();
+    }
+
+    public void testWorkerWithStuckScm()
+        throws Exception
+    {
+        recordOfStuckScm();
+
+        worker.work();
+
+        context.assertIsSatisfied();
+    }
+
+    private void recordOfStuckBuild()
+        throws Exception
+    {
+        context.checking( new Expectations()
+        {
+            {
+                one( configurationService ).isDistributedBuildEnabled();
+                will( returnValue( true ) );
+
+                exactly( 2 ).of( distributedBuildManager ).getCurrentRuns();
+                will( returnValue( getCurrentRuns() ) );
+
+                exactly( 2 ).of( projectScmRootDao ).getProjectScmRoot( 1 );
+                will( returnValue( getScmRoot( ContinuumProjectState.OK ) ) );
+
+                Project proj1 = getProject( 1, ContinuumProjectState.BUILDING );
+                one( projectDao ).getProject( 1 );
+                will( returnValue( proj1 ) );
+
+                one( distributedBuildManager ).isProjectCurrentlyBuilding( 1, 1 );
+                will( returnValue( false ) );
+
+                one( buildDefinitionDao ).getBuildDefinition( 1 );
+                will( returnValue( new BuildDefinition() ) );
+
+                one( buildResultDao ).addBuildResult( with( any( Project.class ) ), with( any( BuildResult.class ) ) );
+                one( projectDao ).updateProject( proj1 );
+
+                one( projectDao ).getProject( 2 );
+                will( returnValue( getProject( 2, ContinuumProjectState.OK ) ) );
+            }
+        } );
+    }
+
+    private void recordOfStuckScm()
+        throws Exception
+    {
+        context.checking( new Expectations()
+        {
+            {
+                one( configurationService ).isDistributedBuildEnabled();
+                will( returnValue( true ) );
+
+                exactly( 2 ).of( distributedBuildManager ).getCurrentRuns();
+                will( returnValue( getCurrentRuns() ) );
+
+                ProjectScmRoot scmRootUpdating = getScmRoot( ContinuumProjectState.UPDATING );
+                one( projectScmRootDao ).getProjectScmRoot( 1 );
+                will( returnValue( scmRootUpdating ) );
+
+                one( distributedBuildManager ).isProjectCurrentlyPreparingBuild( 1, 1 );
+                will( returnValue( false ) );
+
+                one( projectScmRootDao ).updateProjectScmRoot( scmRootUpdating );
+
+                one( projectScmRootDao ).getProjectScmRoot( 1 );
+                will( returnValue( getScmRoot( ContinuumProjectState.ERROR ) ) );
+            }
+        } );
+    }
+
+    private List<ProjectRunSummary> getCurrentRuns()
+    {
+        List<ProjectRunSummary> runs = new ArrayList<ProjectRunSummary>();
+
+        ProjectRunSummary run1 = new ProjectRunSummary();
+        run1.setProjectId( 1 );
+        run1.setBuildDefinitionId( 1 );
+        run1.setProjectGroupId( 1 );
+        run1.setProjectScmRootId( 1 );
+        run1.setTrigger( 1 );
+        run1.setTriggeredBy( "user" );
+        run1.setBuildAgentUrl( "http://localhost:8181/continuum-buildagent/xmlrpc" );
+        runs.add( run1 );
+
+        ProjectRunSummary run2 = new ProjectRunSummary();
+        run2.setProjectId( 2 );
+        run2.setBuildDefinitionId( 2 );
+        run2.setProjectGroupId( 1 );
+        run2.setProjectScmRootId( 1 );
+        run2.setTrigger( 1 );
+        run2.setTriggeredBy( "user" );
+        run2.setBuildAgentUrl( "http://localhost:8181/continuum-buildagent/xmlrpc" );
+        runs.add( run2 );
+
+        return runs;
+    }
+
+    private ProjectScmRoot getScmRoot( int state )
+    {
+        ProjectScmRoot scmRoot = new ProjectScmRoot();
+        scmRoot.setState( state );
+        return scmRoot;
+    }
+
+    private Project getProject( int projectId, int state )
+    {
+        Project project = new Project();
+        project.setId( projectId );
+        project.setState( state );
+        return project;
+    }
+}
diff --git a/continuum-core/src/test/java/org/apache/continuum/buildmanager/ParallelBuildsManagerTest.java b/continuum-core/src/test/java/org/apache/continuum/buildmanager/ParallelBuildsManagerTest.java
new file mode 100644
index 0000000..638027c
--- /dev/null
+++ b/continuum-core/src/test/java/org/apache/continuum/buildmanager/ParallelBuildsManagerTest.java
@@ -0,0 +1,1177 @@
+package org.apache.continuum.buildmanager;
+
+/*
+ * 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 org.apache.continuum.buildqueue.BuildQueueService;
+import org.apache.continuum.dao.BuildDefinitionDao;
+import org.apache.continuum.dao.ProjectDao;
+import org.apache.continuum.taskqueue.BuildProjectTask;
+import org.apache.continuum.taskqueue.CheckOutTask;
+import org.apache.continuum.taskqueue.OverallBuildQueue;
+import org.apache.continuum.taskqueue.PrepareBuildProjectsTask;
+import org.apache.continuum.taskqueueexecutor.ParallelBuildsThreadedTaskQueueExecutor;
+import org.apache.continuum.utils.build.BuildTrigger;
+import org.apache.maven.continuum.configuration.ConfigurationService;
+import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.BuildQueue;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.project.Schedule;
+import org.apache.maven.continuum.store.ContinuumStoreException;
+import org.codehaus.plexus.spring.PlexusInSpringTestCase;
+import org.codehaus.plexus.taskqueue.Task;
+import org.codehaus.plexus.taskqueue.TaskQueue;
+import org.codehaus.plexus.taskqueue.TaskQueueException;
+import org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.integration.junit3.JUnit3Mockery;
+import org.jmock.lib.legacy.ClassImposteriser;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * ParallelBuildsManagerTest
+ *
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ */
+public class ParallelBuildsManagerTest
+    extends PlexusInSpringTestCase
+{
+    private ParallelBuildsManager buildsManager;
+
+    private Mockery context;
+
+    private BuildDefinitionDao buildDefinitionDao;
+
+    private ProjectDao projectDao;
+
+    private ConfigurationService configurationService;
+
+    private OverallBuildQueue overallBuildQueue;
+
+    private TaskQueue buildQueue;
+
+    private TaskQueue checkoutQueue;
+
+    private TaskQueue prepareBuildQueue;
+
+    private List<Project> projects;
+
+    private TaskQueueExecutor buildTaskQueueExecutor;
+
+    private TaskQueueExecutor checkoutTaskQueueExecutor;
+
+    private TaskQueueExecutor prepareBuildTaskQueueExecutor;
+
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        buildsManager = (ParallelBuildsManager) lookup( BuildsManager.class, "parallel" );
+
+        context = new JUnit3Mockery();
+        context.setImposteriser( ClassImposteriser.INSTANCE );
+
+        buildDefinitionDao = context.mock( BuildDefinitionDao.class );
+
+        buildsManager.setBuildDefinitionDao( buildDefinitionDao );
+
+        configurationService = context.mock( ConfigurationService.class );
+
+        buildsManager.setConfigurationService( configurationService );
+
+        BuildQueueService buildQueueService = context.mock( BuildQueueService.class );
+
+        buildsManager.setBuildQueueService( buildQueueService );
+
+        buildQueue = context.mock( TaskQueue.class, "build-queue" );
+
+        checkoutQueue = context.mock( TaskQueue.class, "checkout-queue" );
+
+        prepareBuildQueue = context.mock( TaskQueue.class, "prepare-build-queue" );
+
+        projectDao = context.mock( ProjectDao.class );
+
+        buildsManager.setProjectDao( projectDao );
+
+        buildTaskQueueExecutor = context.mock( TaskQueueExecutor.class, "build-task-queue" );
+
+        checkoutTaskQueueExecutor = context.mock( TaskQueueExecutor.class, "checkout-task-queue" );
+
+        prepareBuildTaskQueueExecutor = context.mock( TaskQueueExecutor.class, "prepare-build-task-queue" );
+    }
+
+    @Override
+    public void tearDown()
+        throws Exception
+    {
+        super.tearDown();
+
+        buildsManager = null;
+    }
+
+    private List<BuildQueue> getBuildQueues( int start, int end )
+    {
+        List<BuildQueue> buildQueues = new ArrayList<BuildQueue>();
+        for ( int i = start; i <= end; i++ )
+        {
+            BuildQueue buildQueue = new BuildQueue();
+            buildQueue.setId( i );
+            if ( i == 1 )
+            {
+                buildQueue.setName( ConfigurationService.DEFAULT_BUILD_QUEUE_NAME );
+            }
+            else
+            {
+                buildQueue.setName( "BUILD_QUEUE_" + String.valueOf( i ) );
+            }
+            buildQueues.add( buildQueue );
+        }
+
+        return buildQueues;
+    }
+
+    private Schedule getSchedule( int id, int start, int end )
+    {
+        Schedule schedule = new Schedule();
+        schedule.setId( id );
+        schedule.setName( "DEFAULT_SCHEDULE" );
+        schedule.setCronExpression( "0 0 * * * ?" );
+        schedule.setDelay( 100 );
+        schedule.setMaxJobExecutionTime( 10000 );
+        schedule.setBuildQueues( getBuildQueues( start, end ) );
+
+        return schedule;
+    }
+
+    public void setupMockOverallBuildQueues()
+        throws Exception
+    {
+        Map<Integer, OverallBuildQueue> overallBuildQueues = Collections.synchronizedMap(
+            new HashMap<Integer, OverallBuildQueue>() );
+        overallBuildQueue = context.mock( OverallBuildQueue.class );
+        for ( int i = 1; i <= 5; i++ )
+        {
+            overallBuildQueues.put( i, overallBuildQueue );
+        }
+
+        buildsManager.setOverallBuildQueues( overallBuildQueues );
+    }
+
+    // build project recordings
+    private void recordStartOfBuildProjectSequence()
+        throws TaskQueueException, ContinuumStoreException
+    {
+        context.checking( new Expectations()
+        {
+            {
+                exactly( 5 ).of( overallBuildQueue ).isInBuildQueue( with( any( int.class ) ) );
+                will( returnValue( false ) );
+
+                exactly( 5 ).of( buildTaskQueueExecutor ).getCurrentTask();
+                will( returnValue( null ) );
+
+                one( projectDao ).getProjectsInGroup( with( any( int.class ) ) );
+                will( returnValue( projects ) );
+
+                one( configurationService ).getNumberOfBuildsInParallel();
+                will( returnValue( 2 ) );
+
+                exactly( 2 ).of( overallBuildQueue ).getBuildQueue();
+                will( returnValue( buildQueue ) );
+
+                exactly( 7 ).of( overallBuildQueue ).getBuildTaskQueueExecutor();
+                will( returnValue( buildTaskQueueExecutor ) );
+            }
+        } );
+    }
+
+    private void recordBuildProjectBuildQueuesAreEmpty()
+        throws TaskQueueException, ContinuumStoreException
+    {
+        // shouldn't only the build queues attached to the schedule be checked?
+        recordStartOfBuildProjectSequence();
+
+        final List<Task> tasks = new ArrayList<Task>();
+        context.checking( new Expectations()
+        {
+            {
+                exactly( 2 ).of( buildQueue ).getQueueSnapshot();
+                will( returnValue( tasks ) );
+
+                exactly( 2 ).of( buildTaskQueueExecutor ).getCurrentTask();
+                will( returnValue( null ) );
+
+                one( overallBuildQueue ).getName();
+                will( returnValue( "BUILD_QUEUE_2" ) );
+            }
+        } );
+
+        recordAddToBuildQueue();
+    }
+
+    private void recordAddToBuildQueue()
+        throws TaskQueueException
+    {
+        context.checking( new Expectations()
+        {
+            {
+                one( overallBuildQueue ).addToBuildQueue( with( any( BuildProjectTask.class ) ) );
+            }
+        } );
+    }
+
+    // checkout project recordings
+    private void recordStartOfCheckoutProjectSequence()
+        throws TaskQueueException
+    {
+        context.checking( new Expectations()
+        {
+            {
+                exactly( 5 ).of( overallBuildQueue ).isInCheckoutQueue( with( any( int.class ) ) );
+                will( returnValue( false ) );
+
+                one( configurationService ).getNumberOfBuildsInParallel();
+                will( returnValue( 2 ) );
+
+                exactly( 2 ).of( overallBuildQueue ).getCheckoutQueue();
+                will( returnValue( checkoutQueue ) );
+
+                exactly( 2 ).of( overallBuildQueue ).getCheckoutTaskQueueExecutor();
+                will( returnValue( checkoutTaskQueueExecutor ) );
+            }
+        } );
+
+    }
+
+    private void recordCheckoutProjectBuildQueuesAreEmpty()
+        throws TaskQueueException
+    {
+        recordStartOfCheckoutProjectSequence();
+
+        final List<Task> tasks = new ArrayList<Task>();
+        context.checking( new Expectations()
+        {
+            {
+                exactly( 2 ).of( checkoutQueue ).getQueueSnapshot();
+                will( returnValue( tasks ) );
+
+                exactly( 2 ).of( checkoutTaskQueueExecutor ).getCurrentTask();
+                will( returnValue( null ) );
+
+                one( overallBuildQueue ).getName();
+                will( returnValue( "BUILD_QUEUE_2" ) );
+            }
+        } );
+
+        recordAddToCheckoutQueue();
+    }
+
+    private void recordAddToCheckoutQueue()
+        throws TaskQueueException
+    {
+        context.checking( new Expectations()
+        {
+            {
+                one( overallBuildQueue ).addToCheckoutQueue( with( any( CheckOutTask.class ) ) );
+            }
+        } );
+    }
+
+    // prepare build project recordings
+    private void recordStartOfPrepareBuildProjectSequence()
+        throws TaskQueueException, ContinuumStoreException
+    {
+        final BuildDefinition buildDef = new BuildDefinition();
+        buildDef.setId( 1 );
+        buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
+
+        context.checking( new Expectations()
+        {
+            {
+                exactly( 5 ).of( overallBuildQueue ).isInPrepareBuildQueue( with( any( int.class ) ), with( any(
+                    int.class ) ) );
+                will( returnValue( false ) );
+
+                one( buildDefinitionDao ).getBuildDefinition( 1 );
+                will( returnValue( buildDef ) );
+
+                one( configurationService ).getNumberOfBuildsInParallel();
+                will( returnValue( 2 ) );
+
+                exactly( 2 ).of( overallBuildQueue ).getPrepareBuildQueue();
+                will( returnValue( prepareBuildQueue ) );
+
+                exactly( 2 ).of( overallBuildQueue ).getPrepareBuildTaskQueueExecutor();
+                will( returnValue( prepareBuildTaskQueueExecutor ) );
+            }
+        } );
+    }
+
+    private void recordPrepareBuildProjectPrepareBuildQueuesAreEmpty()
+        throws TaskQueueException, ContinuumStoreException
+    {
+        recordStartOfPrepareBuildProjectSequence();
+
+        final List<Task> tasks = new ArrayList<Task>();
+        context.checking( new Expectations()
+        {
+            {
+                exactly( 2 ).of( prepareBuildQueue ).getQueueSnapshot();
+                will( returnValue( tasks ) );
+
+                exactly( 2 ).of( prepareBuildTaskQueueExecutor ).getCurrentTask();
+                will( returnValue( null ) );
+
+                one( overallBuildQueue ).getName();
+                will( returnValue( "BUILD_QUEUE_2" ) );
+            }
+        } );
+
+        recordAddToPrepareBuildQueue();
+    }
+
+    private void recordAddToPrepareBuildQueue()
+        throws TaskQueueException
+    {
+        context.checking( new Expectations()
+        {
+            {
+                one( overallBuildQueue ).addToPrepareBuildQueue( with( any( PrepareBuildProjectsTask.class ) ) );
+            }
+        } );
+    }
+
+    // start of test cases..
+
+    public void testContainer()
+        throws Exception
+    {
+        buildsManager.setContainer( getContainer() );
+
+        buildsManager.isProjectInAnyCurrentBuild( 1 );
+
+        assertTrue( true );
+    }
+
+    public void testBuildProjectNoProjectQueuedInAnyOverallBuildQueues()
+        throws Exception
+    {
+        setupMockOverallBuildQueues();
+
+        BuildDefinition buildDef = new BuildDefinition();
+        buildDef.setId( 1 );
+        buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
+
+        recordBuildProjectBuildQueuesAreEmpty();
+
+        buildsManager.buildProject( 1, buildDef, "continuum-project-test-1", new BuildTrigger( 1, "test-user" ), null,
+                                    1 );
+
+        context.assertIsSatisfied();
+    }
+
+    public void testBuildProjectProjectsAreAlreadyQueuedInOverallBuildQueues()
+        throws Exception
+    {
+        setupMockOverallBuildQueues();
+
+        BuildDefinition buildDef = new BuildDefinition();
+        buildDef.setId( 1 );
+        buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
+
+        recordBuildProjectBuildQueuesAreEmpty();
+
+        buildsManager.buildProject( 1, buildDef, "continuum-project-test-1", new BuildTrigger( 1, "test-user" ), null,
+                                    1 );
+        context.assertIsSatisfied();
+
+        //queue second project - 1st queue is not empty, 2nd queue is empty 
+        recordStartOfBuildProjectSequence();
+
+        // the first build queue already has a task queued
+        final List<Task> tasks = new ArrayList<Task>();
+        final List<Task> tasksOfFirstBuildQueue = new ArrayList<Task>();
+        tasksOfFirstBuildQueue.add( new BuildProjectTask( 2, 1, new BuildTrigger( 1, "test-user" ),
+                                                          "continuum-project-test-2", buildDef.getDescription(), null,
+                                                          2 ) );
+        context.checking( new Expectations()
+        {
+            {
+                one( buildQueue ).getQueueSnapshot();
+                will( returnValue( tasksOfFirstBuildQueue ) );
+
+                // the second build queue has no tasks queued, so it should return 0
+                one( buildQueue ).getQueueSnapshot();
+                will( returnValue( tasks ) );
+
+                exactly( 2 ).of( buildTaskQueueExecutor ).getCurrentTask();
+                will( returnValue( null ) );
+
+                one( overallBuildQueue ).getName();
+                will( returnValue( "BUILD_QUEUE_3" ) );
+            }
+        } );
+
+        recordAddToBuildQueue();
+
+        buildsManager.buildProject( 2, buildDef, "continuum-project-test-2", new BuildTrigger( 1, "test-user" ), null,
+                                    2 );
+        context.assertIsSatisfied();
+
+        // queue third project - both queues have 1 task queued each
+        recordStartOfBuildProjectSequence();
+
+        // both queues have 1 task each        
+        context.checking( new Expectations()
+        {
+            {
+                exactly( 2 ).of( buildQueue ).getQueueSnapshot();
+                will( returnValue( tasksOfFirstBuildQueue ) );
+
+                exactly( 2 ).of( buildTaskQueueExecutor ).getCurrentTask();
+                will( returnValue( null ) );
+
+                one( overallBuildQueue ).getName();
+                will( returnValue( "BUILD_QUEUE_2" ) );
+            }
+        } );
+
+        recordAddToBuildQueue();
+
+        buildsManager.buildProject( 3, buildDef, "continuum-project-test-3", new BuildTrigger( 1, "test-user" ), null,
+                                    3 );
+        context.assertIsSatisfied();
+    }
+
+    public void testRemoveProjectFromBuildQueue()
+        throws Exception
+    {
+        setupMockOverallBuildQueues();
+
+        context.checking( new Expectations()
+        {
+            {
+                one( overallBuildQueue ).isInBuildQueue( 1 );
+                will( returnValue( true ) );
+
+                one( overallBuildQueue ).removeProjectFromBuildQueue( 1 );
+            }
+        } );
+
+        buildsManager.removeProjectFromBuildQueue( 1 );
+        context.assertIsSatisfied();
+    }
+
+    public void testRemoveProjectsFromBuildQueue()
+        throws Exception
+    {
+        setupMockOverallBuildQueues();
+        int[] projectIds = new int[]{1, 2, 3};
+
+        context.checking( new Expectations()
+        {
+            {
+                exactly( 3 ).of( overallBuildQueue ).isInBuildQueue( with( any( int.class ) ) );
+                will( returnValue( true ) );
+
+                exactly( 3 ).of( overallBuildQueue ).removeProjectFromBuildQueue( with( any( int.class ) ) );
+            }
+        } );
+
+        buildsManager.removeProjectsFromBuildQueue( projectIds );
+        context.assertIsSatisfied();
+    }
+
+    public void testCheckoutProjectSingle()
+        throws Exception
+    {
+        setupMockOverallBuildQueues();
+
+        BuildDefinition buildDef = new BuildDefinition();
+        buildDef.setId( 1 );
+        buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
+
+        recordCheckoutProjectBuildQueuesAreEmpty();
+
+        buildsManager.checkoutProject( 1, "continuum-project-test-1", new File( getBasedir(),
+                                                                                "/target/test-working-dir/1" ), null,
+                                       "dummy", "dummypass", buildDef, null );
+        context.assertIsSatisfied();
+    }
+
+    public void testCheckoutProjectMultiple()
+        throws Exception
+    {
+        setupMockOverallBuildQueues();
+
+        BuildDefinition buildDef = new BuildDefinition();
+        buildDef.setId( 1 );
+        buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
+
+        recordCheckoutProjectBuildQueuesAreEmpty();
+
+        buildsManager.checkoutProject( 1, "continuum-project-test-1", new File( getBasedir(),
+                                                                                "/target/test-working-dir/1" ), null,
+                                       "dummy", "dummypass", buildDef, null );
+        context.assertIsSatisfied();
+
+        // queue second project - 1st queue has 1 task while 2nd queue is empty; project should be queued in
+        //      2nd queue
+        recordStartOfCheckoutProjectSequence();
+
+        final List<Task> tasks = new ArrayList<Task>();
+
+        final List<Task> tasksInFirstCheckoutQueue = new ArrayList<Task>();
+        tasksInFirstCheckoutQueue.add( new CheckOutTask( 1, new File( getBasedir(), "/target/test-working-dir/1" ),
+                                                         "continuum-project-test-1", "dummy", "dummypass", null,
+                                                         null ) );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( checkoutQueue ).getQueueSnapshot();
+                will( returnValue( tasksInFirstCheckoutQueue ) );
+
+                one( checkoutQueue ).getQueueSnapshot();
+                will( returnValue( tasks ) );
+
+                exactly( 2 ).of( checkoutTaskQueueExecutor ).getCurrentTask();
+                will( returnValue( null ) );
+
+                one( overallBuildQueue ).getName();
+                will( returnValue( "BUILD_QUEUE_3" ) );
+            }
+        } );
+
+        recordAddToCheckoutQueue();
+
+        buildsManager.checkoutProject( 2, "continuum-project-test-2", new File( getBasedir(),
+                                                                                "/target/test-working-dir/1" ), null,
+                                       "dummy", "dummypass", buildDef, null );
+        context.assertIsSatisfied();
+
+        // queue third project - both queues have 1 task queued each; third project should be queued in 1st queue
+        recordStartOfCheckoutProjectSequence();
+
+        context.checking( new Expectations()
+        {
+            {
+                exactly( 2 ).of( checkoutQueue ).getQueueSnapshot();
+                will( returnValue( tasksInFirstCheckoutQueue ) );
+
+                exactly( 2 ).of( checkoutTaskQueueExecutor ).getCurrentTask();
+                will( returnValue( null ) );
+
+                one( overallBuildQueue ).getName();
+                will( returnValue( "BUILD_QUEUE_2" ) );
+            }
+        } );
+
+        recordAddToCheckoutQueue();
+
+        buildsManager.checkoutProject( 3, "continuum-project-test-3", new File( getBasedir(),
+                                                                                "/target/test-working-dir/1" ), null,
+                                       "dummy", "dummypass", buildDef, null );
+        context.assertIsSatisfied();
+    }
+
+    public void testRemoveProjectFromCheckoutQueue()
+        throws Exception
+    {
+        setupMockOverallBuildQueues();
+
+        context.checking( new Expectations()
+        {
+            {
+                one( overallBuildQueue ).isInCheckoutQueue( 1 );
+                will( returnValue( true ) );
+
+                one( overallBuildQueue ).removeProjectFromCheckoutQueue( 1 );
+            }
+        } );
+
+        buildsManager.removeProjectFromCheckoutQueue( 1 );
+        context.assertIsSatisfied();
+    }
+
+    public void testRemoveProjectsFromCheckoutQueue()
+        throws Exception
+    {
+        setupMockOverallBuildQueues();
+
+        context.checking( new Expectations()
+        {
+            {
+                exactly( 3 ).of( overallBuildQueue ).isInCheckoutQueue( with( any( int.class ) ) );
+                will( returnValue( true ) );
+
+                exactly( 3 ).of( overallBuildQueue ).removeProjectFromCheckoutQueue( with( any( int.class ) ) );
+            }
+        } );
+
+        int[] projectIds = new int[]{1, 2, 3};
+
+        buildsManager.removeProjectsFromCheckoutQueue( projectIds );
+        context.assertIsSatisfied();
+    }
+
+    public void testRemoveProjectFromCheckoutQueueProjectNotFound()
+        throws Exception
+    {
+        setupMockOverallBuildQueues();
+
+        // shouldn't only the project's build queues be checked instead of all the overall build queues?
+        context.checking( new Expectations()
+        {
+            {
+                exactly( 5 ).of( overallBuildQueue ).isInCheckoutQueue( 1 );
+                will( returnValue( false ) );
+            }
+        } );
+
+        buildsManager.removeProjectFromCheckoutQueue( 1 );
+        context.assertIsSatisfied();
+    }
+
+    public void testRemoveDefaultOverallBuildQueue()
+        throws Exception
+    {
+        setupMockOverallBuildQueues();
+
+        try
+        {
+            context.checking( new Expectations()
+            {
+                {
+                    one( overallBuildQueue ).getName();
+                    will( returnValue( ConfigurationService.DEFAULT_BUILD_QUEUE_NAME ) );
+                }
+            } );
+
+            buildsManager.removeOverallBuildQueue( 1 );
+            context.assertIsSatisfied();
+            fail( "An exception should have been thrown." );
+        }
+        catch ( BuildManagerException e )
+        {
+            assertEquals( "Cannot remove default build queue.", e.getMessage() );
+        }
+    }
+
+    public void testRemoveOverallBuildQueueNoTasksCurrentlyExecuting()
+        throws Exception
+    {
+        // queued tasks (both checkout & build tasks) must be transferred to the other queues!
+        setupMockOverallBuildQueues();
+
+        final BuildDefinition buildDef = new BuildDefinition();
+        buildDef.setId( 1 );
+        buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
+
+        final TaskQueueExecutor buildQueueExecutor = context.mock( TaskQueueExecutor.class, "build-queue-executor" );
+        final TaskQueueExecutor checkoutQueueExecutor = context.mock( TaskQueueExecutor.class,
+                                                                      "checkout-queue-executor" );
+        final TaskQueueExecutor prepareBuildQueueExecutor = context.mock( TaskQueueExecutor.class,
+                                                                          "prepare-build-queue-executor" );
+
+        final List<Task> buildTasks = new ArrayList<Task>();
+        buildTasks.add( new BuildProjectTask( 2, 1, new BuildTrigger( 1, "test-user" ), "continuum-project-test-2",
+                                              "BUILD_DEF", null, 2 ) );
+
+        final List<CheckOutTask> checkoutTasks = new ArrayList<CheckOutTask>();
+        checkoutTasks.add( new CheckOutTask( 2, new File( getBasedir(), "/target/test-working-dir/1" ),
+                                             "continuum-project-test-2", "dummy", "dummypass", null, null ) );
+
+        final List<Task> prepareBuildTasks = new ArrayList<Task>();
+        final Map<Integer, Integer> map = new HashMap<Integer, Integer>();
+        map.put( 1, 1 );
+        prepareBuildTasks.add( new PrepareBuildProjectsTask( map, new BuildTrigger( 1, "test-user" ), 1,
+                                                             "Project Group A", "http://scm.root.address", 2 ) );
+
+        final ParallelBuildsThreadedTaskQueueExecutor buildTaskQueueExecutor = context.mock(
+            ParallelBuildsThreadedTaskQueueExecutor.class, "parallel-build-task-executor" );
+        final ParallelBuildsThreadedTaskQueueExecutor checkoutTaskQueueExecutor = context.mock(
+            ParallelBuildsThreadedTaskQueueExecutor.class, "parallel-checkout-task-executor" );
+        final ParallelBuildsThreadedTaskQueueExecutor prepareBuildTaskQueueExecutor = context.mock(
+            ParallelBuildsThreadedTaskQueueExecutor.class, "parallel-prepare-build-task-executor" );
+
+        final List<Task> tasks = new ArrayList<Task>();
+
+        context.checking( new Expectations()
+        {
+            {
+                one( overallBuildQueue ).getName();
+                will( returnValue( "BUILD_QUEUE_5" ) );
+
+                // check if there is any build task currently being executed
+                one( overallBuildQueue ).getBuildTaskQueueExecutor();
+                will( returnValue( buildQueueExecutor ) );
+                one( buildQueueExecutor ).getCurrentTask();
+                will( returnValue( null ) );
+                //will( returnValue( buildTask ) );
+
+                // check if there is any checkout task currently being executed
+                one( overallBuildQueue ).getCheckoutTaskQueueExecutor();
+                will( returnValue( checkoutQueueExecutor ) );
+                one( checkoutQueueExecutor ).getCurrentTask();
+                will( returnValue( null ) );
+                //will( returnValue( checkoutTask ) );
+
+                // check if there is any prepare build task currently being executed
+                one( overallBuildQueue ).getPrepareBuildTaskQueueExecutor();
+                will( returnValue( prepareBuildQueueExecutor ) );
+                one( prepareBuildQueueExecutor ).getCurrentTask();
+                will( returnValue( null ) );
+
+                // get all queued build tasks & remove them
+                one( overallBuildQueue ).getProjectsInBuildQueue();
+                will( returnValue( buildTasks ) );
+                one( overallBuildQueue ).getBuildQueue();
+                will( returnValue( buildQueue ) );
+                one( buildQueue ).removeAll( buildTasks );
+
+                // get all queued checkout tasks & remove them
+                one( overallBuildQueue ).getProjectsInCheckoutQueue();
+                will( returnValue( checkoutTasks ) );
+                one( overallBuildQueue ).getCheckoutQueue();
+                will( returnValue( checkoutQueue ) );
+                one( checkoutQueue ).removeAll( checkoutTasks );
+
+                // get all queued prepare build tasks & remove them
+                one( overallBuildQueue ).getProjectsInPrepareBuildQueue();
+                will( returnValue( prepareBuildTasks ) );
+                one( overallBuildQueue ).getPrepareBuildQueue();
+                will( returnValue( prepareBuildQueue ) );
+                one( prepareBuildQueue ).removeAll( prepareBuildTasks );
+
+                // stop the build & checkout task queue executors
+                one( overallBuildQueue ).getBuildTaskQueueExecutor();
+                will( returnValue( buildTaskQueueExecutor ) );
+                one( overallBuildQueue ).getCheckoutTaskQueueExecutor();
+                will( returnValue( checkoutTaskQueueExecutor ) );
+                one( overallBuildQueue ).getPrepareBuildTaskQueueExecutor();
+                will( returnValue( prepareBuildTaskQueueExecutor ) );
+
+                one( buildTaskQueueExecutor ).stop();
+                one( checkoutTaskQueueExecutor ).stop();
+                one( prepareBuildTaskQueueExecutor ).stop();
+
+                // TODO: test scenario when there are no longer build queues configured aside from the one removed?
+                //      - the behaviour should be that the default build queue will be used!
+
+                // re-queue projects in the build queue of the deleted overall build queue
+                one( buildDefinitionDao ).getBuildDefinition( 1 );
+                will( returnValue( buildDef ) );
+
+                // queue to other build queue
+                exactly( 4 ).of( overallBuildQueue ).isInBuildQueue( with( any( int.class ) ) );
+                will( returnValue( false ) );
+
+                exactly( 4 ).of( buildQueueExecutor ).getCurrentTask();
+                will( returnValue( null ) );
+
+                one( projectDao ).getProjectsInGroup( with( any( int.class ) ) );
+                will( returnValue( projects ) );
+
+                one( configurationService ).getNumberOfBuildsInParallel();
+                will( returnValue( 2 ) );
+
+                exactly( 2 ).of( overallBuildQueue ).getBuildQueue();
+                will( returnValue( buildQueue ) );
+
+                exactly( 6 ).of( overallBuildQueue ).getBuildTaskQueueExecutor();
+                will( returnValue( buildQueueExecutor ) );
+
+                exactly( 2 ).of( buildQueue ).getQueueSnapshot();
+                will( returnValue( tasks ) );
+
+                exactly( 2 ).of( buildQueueExecutor ).getCurrentTask();
+                will( returnValue( null ) );
+
+                one( overallBuildQueue ).getName();
+                will( returnValue( "BUILD_QUEUE_2" ) );
+
+                recordAddToBuildQueue();
+
+                // re-queue projects in the checkout queue of the deleted overall build queue
+                one( buildDefinitionDao ).getDefaultBuildDefinition( 2 );
+                will( returnValue( buildDef ) );
+
+                // queue to other checkout queues
+                exactly( 4 ).of( overallBuildQueue ).isInCheckoutQueue( with( any( int.class ) ) );
+                will( returnValue( false ) );
+
+                one( configurationService ).getNumberOfBuildsInParallel();
+                will( returnValue( 2 ) );
+
+                exactly( 2 ).of( overallBuildQueue ).getCheckoutQueue();
+                will( returnValue( checkoutQueue ) );
+
+                exactly( 2 ).of( overallBuildQueue ).getCheckoutTaskQueueExecutor();
+                will( returnValue( checkoutQueueExecutor ) );
+
+                exactly( 2 ).of( checkoutQueue ).getQueueSnapshot();
+                will( returnValue( tasks ) );
+
+                exactly( 2 ).of( checkoutQueueExecutor ).getCurrentTask();
+                will( returnValue( null ) );
+
+                one( overallBuildQueue ).getName();
+                will( returnValue( "BUILD_QUEUE_2" ) );
+
+                recordAddToCheckoutQueue();
+
+                // re-queue projects in the prepare build queue of the deleted overall build queue
+                exactly( 4 ).of( overallBuildQueue ).isInPrepareBuildQueue( with( any( int.class ) ), with( any(
+                    int.class ) ) );
+                will( returnValue( false ) );
+
+                one( buildDefinitionDao ).getBuildDefinition( 1 );
+                will( returnValue( buildDef ) );
+
+                one( configurationService ).getNumberOfBuildsInParallel();
+                will( returnValue( 2 ) );
+
+                exactly( 2 ).of( overallBuildQueue ).getPrepareBuildQueue();
+                will( returnValue( prepareBuildQueue ) );
+
+                exactly( 2 ).of( overallBuildQueue ).getPrepareBuildTaskQueueExecutor();
+                will( returnValue( prepareBuildQueueExecutor ) );
+
+                exactly( 2 ).of( prepareBuildQueue ).getQueueSnapshot();
+                will( returnValue( tasks ) );
+
+                exactly( 2 ).of( prepareBuildQueueExecutor ).getCurrentTask();
+                will( returnValue( null ) );
+
+                one( overallBuildQueue ).getName();
+                will( returnValue( "BUILD_QUEUE_2" ) );
+
+                recordAddToPrepareBuildQueue();
+            }
+        } );
+
+        buildsManager.removeOverallBuildQueue( 5 );
+        context.assertIsSatisfied();
+
+        Map<Integer, OverallBuildQueue> overallBuildQueues = buildsManager.getOverallBuildQueues();
+        assertNull( overallBuildQueues.get( 5 ) );
+    }
+
+    public void testRemoveOverallBuildQueueTasksCurrentlyExecuting()
+        throws Exception
+    {
+        setupMockOverallBuildQueues();
+
+        final BuildDefinition buildDef = new BuildDefinition();
+        buildDef.setId( 1 );
+        buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
+
+        final TaskQueueExecutor buildQueueExecutor = context.mock( TaskQueueExecutor.class, "build-queue-executor" );
+        final Task buildTask = new BuildProjectTask( 1, 1, new BuildTrigger( 1, "test-user" ),
+                                                     "continuum-project-test-1", "BUILD_DEF", null, 1 );
+
+        final List<BuildProjectTask> buildTasks = new ArrayList<BuildProjectTask>();
+        buildTasks.add( new BuildProjectTask( 2, 1, new BuildTrigger( 1, "test-user" ), "continuum-project-test-2",
+                                              "BUILD_DEF", null, 2 ) );
+
+        final List<CheckOutTask> checkoutTasks = new ArrayList<CheckOutTask>();
+        checkoutTasks.add( new CheckOutTask( 2, new File( getBasedir(), "/target/test-working-dir/1" ),
+                                             "continuum-project-test-2", "dummy", "dummypass", null, null ) );
+
+        try
+        {
+            context.checking( new Expectations()
+            {
+                {
+                    one( overallBuildQueue ).getName();
+                    will( returnValue( "BUILD_QUEUE_5" ) );
+
+                    // check if there is any build task currently being executed
+                    one( overallBuildQueue ).getBuildTaskQueueExecutor();
+                    will( returnValue( buildQueueExecutor ) );
+                    one( buildQueueExecutor ).getCurrentTask();
+                    will( returnValue( buildTask ) );
+                }
+            } );
+
+            buildsManager.removeOverallBuildQueue( 5 );
+            context.assertIsSatisfied();
+            fail( "An exception should have been thrown." );
+        }
+        catch ( BuildManagerException e )
+        {
+            assertEquals( "Cannot remove build queue. A task is currently executing.", e.getMessage() );
+        }
+    }
+
+    public void testNoBuildQueuesConfigured()
+        throws Exception
+    {
+        overallBuildQueue = context.mock( OverallBuildQueue.class );
+
+        Map<Integer, OverallBuildQueue> overallBuildQueues = Collections.synchronizedMap(
+            new HashMap<Integer, OverallBuildQueue>() );
+        overallBuildQueues.put( 1, overallBuildQueue );
+
+        buildsManager.setOverallBuildQueues( overallBuildQueues );
+
+        Schedule schedule = new Schedule();
+        schedule.setId( 1 );
+        schedule.setName( "DEFAULT_SCHEDULE" );
+        schedule.setCronExpression( "0 0 * * * ?" );
+        schedule.setDelay( 100 );
+        schedule.setMaxJobExecutionTime( 10000 );
+
+        BuildDefinition buildDef = new BuildDefinition();
+        buildDef.setId( 1 );
+        buildDef.setSchedule( schedule );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( overallBuildQueue ).isInBuildQueue( with( any( int.class ) ) );
+                will( returnValue( false ) );
+
+                one( overallBuildQueue ).getBuildTaskQueueExecutor();
+                will( returnValue( buildTaskQueueExecutor ) );
+
+                one( buildTaskQueueExecutor ).getCurrentTask();
+                will( returnValue( null ) );
+
+                one( projectDao ).getProjectsInGroup( with( any( int.class ) ) );
+                will( returnValue( projects ) );
+
+                one( configurationService ).getNumberOfBuildsInParallel();
+                will( returnValue( 2 ) );
+
+                exactly( 2 ).of( overallBuildQueue ).getName();
+                will( returnValue( ConfigurationService.DEFAULT_BUILD_QUEUE_NAME ) );
+
+                one( overallBuildQueue ).addToBuildQueue( with( any( BuildProjectTask.class ) ) );
+            }
+        } );
+
+        buildsManager.buildProject( 1, buildDef, "continuum-project-test-1", new BuildTrigger( 1, "test-user" ), null,
+                                    1 );
+        context.assertIsSatisfied();
+    }
+
+    public void testGetProjectsInBuildQueue()
+        throws Exception
+    {
+        setupMockOverallBuildQueues();
+
+        final List<Task> tasks = new ArrayList<Task>();
+        tasks.add( new BuildProjectTask( 2, 1, new BuildTrigger( 1, "test-user" ), "continuum-project-test-2",
+                                         "BUILD_DEF", null, 2 ) );
+
+        context.checking( new Expectations()
+        {
+            {
+                exactly( 5 ).of( overallBuildQueue ).getName();
+                will( returnValue( "BUILD_QUEUE" ) );
+
+                exactly( 5 ).of( overallBuildQueue ).getProjectsInBuildQueue();
+                will( returnValue( tasks ) );
+            }
+        } );
+
+        buildsManager.getProjectsInBuildQueues();
+        context.assertIsSatisfied();
+    }
+
+    public void testGetProjectsInCheckoutQueue()
+        throws Exception
+    {
+        setupMockOverallBuildQueues();
+
+        final List<Task> tasks = new ArrayList<Task>();
+        tasks.add( new CheckOutTask( 2, new File( getBasedir(), "/target/test-working-dir/1" ),
+                                     "continuum-project-test-2", "dummy", "dummypass", null, null ) );
+
+        context.checking( new Expectations()
+        {
+            {
+                exactly( 5 ).of( overallBuildQueue ).getName();
+                will( returnValue( "BUILD_QUEUE" ) );
+
+                exactly( 5 ).of( overallBuildQueue ).getProjectsInCheckoutQueue();
+                will( returnValue( tasks ) );
+            }
+        } );
+
+        buildsManager.getProjectsInCheckoutQueues();
+        context.assertIsSatisfied();
+    }
+
+    // prepare build queue
+    public void testPrepareBuildProjectNoProjectQueuedInAnyOverallBuildQueues()
+        throws Exception
+    {
+        setupMockOverallBuildQueues();
+
+        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
+        map.put( 1, 1 );
+
+        recordPrepareBuildProjectPrepareBuildQueuesAreEmpty();
+
+        buildsManager.prepareBuildProjects( map, new BuildTrigger( 1, "test-user" ), 1, "Project Group A",
+                                            "http://scm.root.address", 1 );
+        context.assertIsSatisfied();
+    }
+
+    public void testPrepareBuildProjectsAlreadyQueued()
+        throws Exception
+    {
+        setupMockOverallBuildQueues();
+
+        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
+        map.put( 1, 1 );
+
+        //queue second project - 1st queue is not empty, 2nd queue is empty 
+        recordStartOfPrepareBuildProjectSequence();
+
+        // the first prepare build queue already has a task queued
+        final List<Task> tasks = new ArrayList<Task>();
+        final List<Task> tasksOfFirstPrepareBuildQueue = new ArrayList<Task>();
+        tasksOfFirstPrepareBuildQueue.add( new PrepareBuildProjectsTask( new HashMap<Integer, Integer>(),
+                                                                         new BuildTrigger( 1, "test-user" ), 1,
+                                                                         "Project Group B", "http://scm.root.address2",
+                                                                         2 ) );
+        context.checking( new Expectations()
+        {
+            {
+                one( prepareBuildQueue ).getQueueSnapshot();
+                will( returnValue( tasksOfFirstPrepareBuildQueue ) );
+
+                // the second prepare build queue has no tasks queued, so it should return 0
+                one( prepareBuildQueue ).getQueueSnapshot();
+                will( returnValue( tasks ) );
+
+                exactly( 2 ).of( prepareBuildTaskQueueExecutor ).getCurrentTask();
+                will( returnValue( null ) );
+
+                one( overallBuildQueue ).getName();
+                will( returnValue( "BUILD_QUEUE_3" ) );
+            }
+        } );
+
+        recordAddToPrepareBuildQueue();
+
+        buildsManager.prepareBuildProjects( map, new BuildTrigger( 1, "test-user" ), 1, "Project Group A",
+                                            "http://scm.root.address", 1 );
+        context.assertIsSatisfied();
+
+        // queue third project - both queues have 1 task queued each
+        recordStartOfPrepareBuildProjectSequence();
+
+        // both queues have 1 task each        
+        context.checking( new Expectations()
+        {
+            {
+                exactly( 2 ).of( prepareBuildQueue ).getQueueSnapshot();
+                will( returnValue( tasksOfFirstPrepareBuildQueue ) );
+
+                exactly( 2 ).of( prepareBuildTaskQueueExecutor ).getCurrentTask();
+                will( returnValue( null ) );
+
+                one( overallBuildQueue ).getName();
+                will( returnValue( "BUILD_QUEUE_2" ) );
+            }
+        } );
+
+        recordAddToPrepareBuildQueue();
+
+        buildsManager.prepareBuildProjects( map, new BuildTrigger( 1, "test-user" ), 1, "Project Group A",
+                                            "http://scm.root.address", 1 );
+        context.assertIsSatisfied();
+    }
+
+    public void testGetProjectsInPrepareBuildQueue()
+        throws Exception
+    {
+        setupMockOverallBuildQueues();
+
+        final List<Task> tasks = new ArrayList<Task>();
+        tasks.add( new PrepareBuildProjectsTask( new HashMap<Integer, Integer>(), new BuildTrigger( 1, "test-user" ), 1,
+                                                 "Project Group A", "http://scm.root.address", 2 ) );
+
+        context.checking( new Expectations()
+        {
+            {
+                exactly( 5 ).of( overallBuildQueue ).getName();
+                will( returnValue( "PREPARE_BUILD_QUEUE" ) );
+
+                exactly( 5 ).of( overallBuildQueue ).getProjectsInPrepareBuildQueue();
+                will( returnValue( tasks ) );
+            }
+        } );
+
+        buildsManager.getProjectsInPrepareBuildQueue();
+        context.assertIsSatisfied();
+    }
+
+    public void testRemoveProjectFromPrepareBuildQueue()
+        throws Exception
+    {
+        setupMockOverallBuildQueues();
+        context.checking( new Expectations()
+        {
+            {
+                exactly( 5 ).of( overallBuildQueue ).isInPrepareBuildQueue( 1, 2 );
+                will( returnValue( true ) );
+
+                one( overallBuildQueue ).removeProjectFromPrepareBuildQueue( 1, 2 );
+            }
+        } );
+
+        buildsManager.removeProjectFromPrepareBuildQueue( 1, 2 );
+        context.assertIsSatisfied();
+    }
+
+    /*
+    public void testNumOfAllowedParallelBuildsIsLessThanConfiguredBuildQueues()
+        throws Exception
+    {
+    
+    }
+    
+    public void testPrepareBuildProjects()
+        throws Exception
+    {
+    
+    }
+    
+    public void testRemoveProjectFromPrepareBuildQueue()
+        throws Exception
+    {
+
+    }
+    */
+}
diff --git a/continuum-core/src/test/java/org/apache/continuum/notification/mail/MockJavaMailSender.java b/continuum-core/src/test/java/org/apache/continuum/notification/mail/MockJavaMailSender.java
index cfd0f94..ba9838b 100755
--- a/continuum-core/src/test/java/org/apache/continuum/notification/mail/MockJavaMailSender.java
+++ b/continuum-core/src/test/java/org/apache/continuum/notification/mail/MockJavaMailSender.java
@@ -19,33 +19,31 @@
  * under the License.
  */
 
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.mail.internet.MimeMessage;
-
 import org.springframework.mail.MailException;
 import org.springframework.mail.javamail.JavaMailSender;
 import org.springframework.mail.javamail.JavaMailSenderImpl;
 
+import java.util.ArrayList;
+import java.util.List;
+import javax.mail.internet.MimeMessage;
+
 /**
  * @author <a href="mailto:olamy@apache.org">olamy</a>
- * @since 26 sept. 2008
  * @version $Id$
+ * @since 26 sept. 2008
  */
 public class MockJavaMailSender
     extends JavaMailSenderImpl
     implements JavaMailSender
 {
+    private final List<MimeMessage> receivedEmails = new ArrayList<MimeMessage>();
 
-    List<MimeMessage> receivedEmails = new ArrayList<MimeMessage>();
-    
     /**
-     * 
+     *
      */
     public MockJavaMailSender()
     {
-       
+
     }
 
     @Override
@@ -54,7 +52,7 @@
     {
         receivedEmails.add( mimeMessage );
     }
-    
+
     public List<MimeMessage> getReceivedEmails()
     {
         return receivedEmails;
diff --git a/continuum-core/src/test/java/org/apache/continuum/purge/DefaultContinuumPurgeManagerTest.java b/continuum-core/src/test/java/org/apache/continuum/purge/DefaultContinuumPurgeManagerTest.java
index 96d2dca..2071125 100644
--- a/continuum-core/src/test/java/org/apache/continuum/purge/DefaultContinuumPurgeManagerTest.java
+++ b/continuum-core/src/test/java/org/apache/continuum/purge/DefaultContinuumPurgeManagerTest.java
@@ -20,9 +20,11 @@
  */
 
 import org.apache.continuum.dao.DirectoryPurgeConfigurationDao;
+import org.apache.continuum.dao.DistributedDirectoryPurgeConfigurationDao;
 import org.apache.continuum.dao.LocalRepositoryDao;
 import org.apache.continuum.dao.RepositoryPurgeConfigurationDao;
 import org.apache.continuum.model.repository.DirectoryPurgeConfiguration;
+import org.apache.continuum.model.repository.DistributedDirectoryPurgeConfiguration;
 import org.apache.continuum.model.repository.LocalRepository;
 import org.apache.continuum.model.repository.RepositoryPurgeConfiguration;
 import org.apache.continuum.purge.task.PurgeTask;
@@ -43,6 +45,8 @@
 
     private DirectoryPurgeConfigurationDao directoryPurgeConfigurationDao;
 
+    private DistributedDirectoryPurgeConfigurationDao distributedDirectoryPurgeConfigurationDao;
+
     private RepositoryPurgeConfigurationDao repositoryPurgeConfigurationDao;
 
     private ContinuumPurgeManager purgeManager;
@@ -53,6 +57,8 @@
 
     private DirectoryPurgeConfiguration dirPurge;
 
+    private DistributedDirectoryPurgeConfiguration distDirPurge;
+
     private TaskQueueManager taskQueueManager;
 
     @Override
@@ -63,11 +69,14 @@
 
         localRepositoryDao = (LocalRepositoryDao) lookup( LocalRepositoryDao.class.getName() );
 
-        directoryPurgeConfigurationDao =
-            (DirectoryPurgeConfigurationDao) lookup( DirectoryPurgeConfigurationDao.class.getName() );
+        directoryPurgeConfigurationDao = (DirectoryPurgeConfigurationDao) lookup(
+            DirectoryPurgeConfigurationDao.class.getName() );
 
-        repositoryPurgeConfigurationDao =
-            (RepositoryPurgeConfigurationDao) lookup( RepositoryPurgeConfigurationDao.class.getName() );
+        repositoryPurgeConfigurationDao = (RepositoryPurgeConfigurationDao) lookup(
+            RepositoryPurgeConfigurationDao.class.getName() );
+
+        distributedDirectoryPurgeConfigurationDao = (DistributedDirectoryPurgeConfigurationDao) lookup(
+            DistributedDirectoryPurgeConfigurationDao.class.getName() );
 
         purgeManager = (ContinuumPurgeManager) lookup( ContinuumPurgeManager.ROLE );
 
@@ -122,9 +131,11 @@
     {
         purgeManager.purgeRepository( repoPurge );
         purgeManager.purgeDirectory( dirPurge );
+        purgeManager.purgeDistributedDirectory( distDirPurge );
 
         assertNextBuildIs( repoPurge.getId() );
         assertNextBuildIs( dirPurge.getId() );
+        assertNextBuildIs( distDirPurge.getId() );
         assertNextBuildIsNull();
 
         purgeManager.purgeRepository( repoPurge );
@@ -158,6 +169,12 @@
         dirPurge.setDirectoryType( "releases" );
         dirPurge.setLocation( getTestFile( "target/working-directory" ).getAbsolutePath() );
         dirPurge = directoryPurgeConfigurationDao.addDirectoryPurgeConfiguration( dirPurge );
+
+        distDirPurge = new DistributedDirectoryPurgeConfiguration();
+        distDirPurge.setDirectoryType( "releases" );
+        distDirPurge.setBuildAgentUrl( "http://localhost:8186/continuum-buildagent/xmlrpc" );
+        distDirPurge = distributedDirectoryPurgeConfigurationDao.addDistributedDirectoryPurgeConfiguration(
+            distDirPurge );
     }
 
     private void assertNextBuildIs( int expectedPurgeConfigId )
@@ -181,7 +198,7 @@
         if ( task != null )
         {
             fail( "Got a non-null purge task returned. Purge Config id: " +
-                ( (PurgeTask) task ).getPurgeConfigurationId() );
+                      ( (PurgeTask) task ).getPurgeConfigurationId() );
         }
     }
 }
\ No newline at end of file
diff --git a/continuum-core/src/test/java/org/apache/continuum/release/distributed/manager/DefaultDistributedReleaseManagerTest.java b/continuum-core/src/test/java/org/apache/continuum/release/distributed/manager/DefaultDistributedReleaseManagerTest.java
new file mode 100644
index 0000000..95a21f9
--- /dev/null
+++ b/continuum-core/src/test/java/org/apache/continuum/release/distributed/manager/DefaultDistributedReleaseManagerTest.java
@@ -0,0 +1,102 @@
+package org.apache.continuum.release.distributed.manager;
+
+/*
+ * 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 org.apache.continuum.dao.BuildResultDao;
+import org.apache.maven.continuum.model.project.BuildResult;
+import org.codehaus.plexus.spring.PlexusInSpringTestCase;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.integration.junit3.JUnit3Mockery;
+import org.jmock.lib.legacy.ClassImposteriser;
+
+/**
+ * DefaultDistributedReleaseManagerTest
+ */
+public class DefaultDistributedReleaseManagerTest
+    extends PlexusInSpringTestCase
+{
+    private DefaultDistributedReleaseManager distributedReleaseManager;
+
+    private BuildResultDao buildResultDao;
+
+    private BuildResult buildResult;
+
+    private Mockery context;
+
+    @Override
+    protected void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        context = new JUnit3Mockery();
+        context.setImposteriser( ClassImposteriser.INSTANCE );
+
+        distributedReleaseManager = new DefaultDistributedReleaseManager();
+
+        buildResultDao = context.mock( BuildResultDao.class );
+        distributedReleaseManager.setBuildResultDao( buildResultDao );
+    }
+
+    public void testGetDefaultBuildagent()
+        throws Exception
+    {
+        String defaultBuildagentUrl = "http://localhost:8181/continuum-buildagent/xmlrpc";
+
+        buildResult = new BuildResult();
+        buildResult.setBuildUrl( defaultBuildagentUrl );
+
+        contextBuildResultDaoExpectations();
+
+        String returnedBuildagent = distributedReleaseManager.getDefaultBuildagent( 0 );
+
+        assertNotNull( returnedBuildagent );
+        assertEquals( returnedBuildagent, defaultBuildagentUrl );
+
+        context.assertIsSatisfied();
+    }
+
+    public void testGetDefaultBuildagentNullBuildResult()
+        throws Exception
+    {
+        buildResult = null;
+
+        contextBuildResultDaoExpectations();
+
+        String returnedBuildagent = distributedReleaseManager.getDefaultBuildagent( 0 );
+
+        assertNull( returnedBuildagent );
+
+        context.assertIsSatisfied();
+    }
+
+    private void contextBuildResultDaoExpectations()
+        throws Exception
+    {
+        context.checking( new Expectations()
+        {
+            {
+                one( buildResultDao ).getLatestBuildResultForProject( 0 );
+                will( returnValue( buildResult ) );
+            }
+        } );
+    }
+}
diff --git a/continuum-core/src/test/java/org/apache/continuum/repository/DefaultRepositoryServiceTest.java b/continuum-core/src/test/java/org/apache/continuum/repository/DefaultRepositoryServiceTest.java
index 1402ddd..24f9754 100644
--- a/continuum-core/src/test/java/org/apache/continuum/repository/DefaultRepositoryServiceTest.java
+++ b/continuum-core/src/test/java/org/apache/continuum/repository/DefaultRepositoryServiceTest.java
@@ -47,8 +47,8 @@
     {
         super.setUp();
 
-        repositoryPurgeConfigurationDao =
-            (RepositoryPurgeConfigurationDao) lookup( RepositoryPurgeConfigurationDao.class.getName() );
+        repositoryPurgeConfigurationDao = (RepositoryPurgeConfigurationDao) lookup(
+            RepositoryPurgeConfigurationDao.class.getName() );
 
         repositoryService = (RepositoryService) lookup( RepositoryService.ROLE );
 
@@ -91,6 +91,14 @@
         assertEquals( "check # repositories", 1, repositories.size() );
         assertTrue( "check if repository was added", repositories.contains( repository ) );
 
+        LocalRepository repo = repositoryService.getLocalRepositoryByName( "DefaultRepo" );
+        assertNotNull( repo );
+        assertEquals( "check if repository name is the same", repository.getName(), repo.getName() );
+
+        repo = repositoryService.getLocalRepositoryByLocation( repository.getLocation() );
+        assertNotNull( repo );
+        assertEquals( "check if repository location is the same", repository.getLocation(), repo.getLocation() );
+
         ProjectGroup retrievedGroup = getDefaultProjectGroup();
         assertNotNull( retrievedGroup.getLocalRepository() );
         assertEquals( "check if repository is the same", repository, retrievedGroup.getLocalRepository() );
diff --git a/continuum-core/src/test/java/org/apache/continuum/taskqueue/DefaultOverallBuildQueueTest.java b/continuum-core/src/test/java/org/apache/continuum/taskqueue/DefaultOverallBuildQueueTest.java
new file mode 100644
index 0000000..6cbce6b
--- /dev/null
+++ b/continuum-core/src/test/java/org/apache/continuum/taskqueue/DefaultOverallBuildQueueTest.java
@@ -0,0 +1,619 @@
+package org.apache.continuum.taskqueue;
+
+/*
+ * 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 org.apache.continuum.dao.BuildDefinitionDao;
+import org.apache.continuum.taskqueueexecutor.ParallelBuildsThreadedTaskQueueExecutor;
+import org.apache.continuum.utils.build.BuildTrigger;
+import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.codehaus.plexus.spring.PlexusInSpringTestCase;
+import org.codehaus.plexus.taskqueue.Task;
+import org.codehaus.plexus.taskqueue.TaskQueue;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.integration.junit3.JUnit3Mockery;
+import org.jmock.lib.legacy.ClassImposteriser;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * DefaultOverallBuildQueueTest
+ *
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ */
+public class DefaultOverallBuildQueueTest
+    extends PlexusInSpringTestCase
+{
+    private DefaultOverallBuildQueue overallQueue;
+
+    private Mockery context;
+
+    private BuildDefinitionDao buildDefinitionDao;
+
+    private ParallelBuildsThreadedTaskQueueExecutor buildTaskQueueExecutor;
+
+    private ParallelBuildsThreadedTaskQueueExecutor checkoutTaskQueueExecutor;
+
+    private ParallelBuildsThreadedTaskQueueExecutor prepareBuildTaskQueueExecutor;
+
+    @Override
+    protected void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        overallQueue = new DefaultOverallBuildQueue();
+
+        context = new JUnit3Mockery();
+
+        buildDefinitionDao = context.mock( BuildDefinitionDao.class );
+        context.setImposteriser( ClassImposteriser.INSTANCE );
+
+        buildTaskQueueExecutor = context.mock( ParallelBuildsThreadedTaskQueueExecutor.class, "build-queue-executor" );
+
+        checkoutTaskQueueExecutor = context.mock( ParallelBuildsThreadedTaskQueueExecutor.class,
+                                                  "checkout-queue-executor" );
+
+        prepareBuildTaskQueueExecutor = context.mock( ParallelBuildsThreadedTaskQueueExecutor.class,
+                                                      "prepare-build-queue-executor" );
+
+        overallQueue.setBuildDefinitionDao( buildDefinitionDao );
+
+        overallQueue.setBuildTaskQueueExecutor( buildTaskQueueExecutor );
+
+        overallQueue.setCheckoutTaskQueueExecutor( checkoutTaskQueueExecutor );
+
+        overallQueue.setPrepareBuildTaskQueueExecutor( prepareBuildTaskQueueExecutor );
+    }
+
+    // checkout queue
+
+    public void testAddToCheckoutQueue()
+        throws Exception
+    {
+        final CheckOutTask checkoutTask = new CheckOutTask( 1, new File( getBasedir(), "/target/test-working-dir/1" ),
+                                                            "continuum-project-test-1", "dummy", "dummypass", null,
+                                                            null );
+        final TaskQueue checkoutQueue = context.mock( TaskQueue.class, "checkout-queue" );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( checkoutTaskQueueExecutor ).getQueue();
+                will( returnValue( checkoutQueue ) );
+
+                one( checkoutQueue ).put( checkoutTask );
+            }
+        } );
+
+        overallQueue.addToCheckoutQueue( checkoutTask );
+        context.assertIsSatisfied();
+    }
+
+    public void testGetProjectsInCheckoutQueue()
+        throws Exception
+    {
+        final TaskQueue checkoutQueue = context.mock( TaskQueue.class, "checkout-queue" );
+        final List<Task> tasks = new ArrayList<Task>();
+        tasks.add( new CheckOutTask( 1, new File( getBasedir(), "/target/test-working-dir/1" ),
+                                     "continuum-project-test-1", "dummy", "dummypass", null, null ) );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( checkoutTaskQueueExecutor ).getQueue();
+                will( returnValue( checkoutQueue ) );
+
+                one( checkoutQueue ).getQueueSnapshot();
+                will( returnValue( tasks ) );
+            }
+        } );
+
+        List<CheckOutTask> returnedTasks = overallQueue.getProjectsInCheckoutQueue();
+        context.assertIsSatisfied();
+
+        assertNotNull( returnedTasks );
+        assertEquals( 1, returnedTasks.size() );
+    }
+
+    public void testIsInCheckoutQueue()
+        throws Exception
+    {
+        final TaskQueue checkoutQueue = context.mock( TaskQueue.class, "checkout-queue" );
+        final List<Task> tasks = new ArrayList<Task>();
+        tasks.add( new CheckOutTask( 1, new File( getBasedir(), "/target/test-working-dir/1" ),
+                                     "continuum-project-test-1", "dummy", "dummypass", null, null ) );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( checkoutTaskQueueExecutor ).getQueue();
+                will( returnValue( checkoutQueue ) );
+
+                one( checkoutQueue ).getQueueSnapshot();
+                will( returnValue( tasks ) );
+            }
+        } );
+
+        assertTrue( overallQueue.isInCheckoutQueue( 1 ) );
+        context.assertIsSatisfied();
+    }
+
+    public void testRemoveProjectFromCheckoutQueue()
+        throws Exception
+    {
+        final Task checkoutTask = new CheckOutTask( 1, new File( getBasedir(), "/target/test-working-dir/1" ),
+                                                    "continuum-project-test-1", "dummy", "dummypass", null, null );
+        final TaskQueue checkoutQueue = context.mock( TaskQueue.class, "checkout-queue" );
+        final List<Task> tasks = new ArrayList<Task>();
+        tasks.add( checkoutTask );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( checkoutTaskQueueExecutor ).getQueue();
+                will( returnValue( checkoutQueue ) );
+
+                one( checkoutQueue ).getQueueSnapshot();
+                will( returnValue( tasks ) );
+
+                one( checkoutTaskQueueExecutor ).getQueue();
+                will( returnValue( checkoutQueue ) );
+
+                one( checkoutQueue ).remove( checkoutTask );
+            }
+        } );
+
+        overallQueue.removeProjectFromCheckoutQueue( 1 );
+        context.assertIsSatisfied();
+    }
+
+    // build queue
+
+    public void testAddToBuildQueue()
+        throws Exception
+    {
+        final BuildProjectTask buildTask = new BuildProjectTask( 2, 1, new BuildTrigger( 1, "test-user" ),
+                                                                 "continuum-project-test-2", "BUILD_DEF", null, 2 );
+        final TaskQueue buildQueue = context.mock( TaskQueue.class, "build-queue" );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( buildTaskQueueExecutor ).getQueue();
+                will( returnValue( buildQueue ) );
+
+                one( buildQueue ).put( buildTask );
+            }
+        } );
+
+        overallQueue.addToBuildQueue( buildTask );
+        context.assertIsSatisfied();
+    }
+
+    public void testGetProjectsFromBuildQueue()
+        throws Exception
+    {
+        final TaskQueue buildQueue = context.mock( TaskQueue.class, "build-queue" );
+        final List<Task> tasks = new ArrayList<Task>();
+        tasks.add( new BuildProjectTask( 2, 1, new BuildTrigger( 1, "test-user" ), "continuum-project-test-2",
+                                         "BUILD_DEF", null, 2 ) );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( buildTaskQueueExecutor ).getQueue();
+                will( returnValue( buildQueue ) );
+
+                one( buildQueue ).getQueueSnapshot();
+                will( returnValue( tasks ) );
+            }
+        } );
+
+        List<BuildProjectTask> returnedTasks = overallQueue.getProjectsInBuildQueue();
+        context.assertIsSatisfied();
+
+        assertNotNull( returnedTasks );
+        assertEquals( 1, returnedTasks.size() );
+    }
+
+    public void testIsInBuildQueue()
+        throws Exception
+    {
+        final TaskQueue buildQueue = context.mock( TaskQueue.class, "build-queue" );
+        final List<Task> tasks = new ArrayList<Task>();
+        tasks.add( new BuildProjectTask( 2, 1, new BuildTrigger( 1, "test-user" ), "continuum-project-test-2",
+                                         "BUILD_DEF", null, 2 ) );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( buildTaskQueueExecutor ).getQueue();
+                will( returnValue( buildQueue ) );
+
+                one( buildQueue ).getQueueSnapshot();
+                will( returnValue( tasks ) );
+            }
+        } );
+
+        assertTrue( overallQueue.isInBuildQueue( 2 ) );
+        context.assertIsSatisfied();
+    }
+
+    public void testCancelBuildTask()
+        throws Exception
+    {
+        final Task buildTask = new BuildProjectTask( 2, 1, new BuildTrigger( 1, "test-user" ),
+                                                     "continuum-project-test-2", "BUILD_DEF", null, 2 );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( buildTaskQueueExecutor ).getCurrentTask();
+                will( returnValue( buildTask ) );
+
+                one( buildTaskQueueExecutor ).cancelTask( buildTask );
+            }
+        } );
+
+        overallQueue.cancelBuildTask( 2 );
+        context.assertIsSatisfied();
+    }
+
+    public void testCancelCurrentBuild()
+        throws Exception
+    {
+        final Task buildTask = new BuildProjectTask( 2, 1, new BuildTrigger( 1, "test-user" ),
+                                                     "continuum-project-test-2", "BUILD_DEF", null, 2 );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( buildTaskQueueExecutor ).getCurrentTask();
+                will( returnValue( buildTask ) );
+
+                one( buildTaskQueueExecutor ).cancelTask( buildTask );
+            }
+        } );
+
+        overallQueue.cancelCurrentBuild();
+        context.assertIsSatisfied();
+    }
+
+    public void testRemoveProjectFromBuildQueueWithGivenBuildDefinition()
+        throws Exception
+    {
+        final BuildDefinition buildDef = new BuildDefinition();
+        buildDef.setId( 1 );
+        buildDef.setDescription( "Test build definition" );
+
+        final TaskQueue buildQueue = context.mock( TaskQueue.class, "build-queue" );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( buildDefinitionDao ).getBuildDefinition( 1 );
+                will( returnValue( buildDef ) );
+
+                one( buildTaskQueueExecutor ).getQueue();
+                will( returnValue( buildQueue ) );
+
+                one( buildQueue ).remove( with( any( Task.class ) ) );
+            }
+        } );
+
+        overallQueue.removeProjectFromBuildQueue( 1, 1, new BuildTrigger( 1, "test-user" ), "continuum-project-test-1",
+                                                  1 );
+        context.assertIsSatisfied();
+    }
+
+    public void testRemoveProjectFromBuildQueue()
+        throws Exception
+    {
+        final Task buildTask = new BuildProjectTask( 1, 1, new BuildTrigger( 1, "test-user" ),
+                                                     "continuum-project-test-2", "BUILD_DEF", null, 1 );
+
+        final TaskQueue buildQueue = context.mock( TaskQueue.class, "build-queue" );
+        final List<Task> tasks = new ArrayList<Task>();
+        tasks.add( buildTask );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( buildTaskQueueExecutor ).getQueue();
+                will( returnValue( buildQueue ) );
+
+                one( buildQueue ).getQueueSnapshot();
+                will( returnValue( tasks ) );
+
+                one( buildTaskQueueExecutor ).getQueue();
+                will( returnValue( buildQueue ) );
+
+                one( buildQueue ).remove( buildTask );
+            }
+        } );
+
+        overallQueue.removeProjectFromBuildQueue( 1 );
+        context.assertIsSatisfied();
+    }
+
+    // prepare build queue
+
+    public void testAddToPrepareBuildQueue()
+        throws Exception
+    {
+        final PrepareBuildProjectsTask prepareBuildTask = new PrepareBuildProjectsTask( new HashMap<Integer, Integer>(),
+                                                                                        new BuildTrigger( 1,
+                                                                                                          "test-user" ),
+                                                                                        1, "Project Group A",
+                                                                                        "http://scmRootAddress", 1 );
+        final TaskQueue prepareBuildQueue = context.mock( TaskQueue.class, "prepare-build-queue" );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( prepareBuildTaskQueueExecutor ).getQueue();
+                will( returnValue( prepareBuildQueue ) );
+
+                one( prepareBuildQueue ).put( prepareBuildTask );
+            }
+        } );
+
+        overallQueue.addToPrepareBuildQueue( prepareBuildTask );
+        context.assertIsSatisfied();
+    }
+
+    public void testCancelCurrentPrepareBuild()
+        throws Exception
+    {
+        final Task prepareBuildTask = new PrepareBuildProjectsTask( new HashMap<Integer, Integer>(), new BuildTrigger(
+            1, "test-user" ), 1, "Project Group A", "http://scm.root.address", 1 );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( prepareBuildTaskQueueExecutor ).getCurrentTask();
+                will( returnValue( prepareBuildTask ) );
+
+                one( prepareBuildTaskQueueExecutor ).cancelTask( prepareBuildTask );
+            }
+        } );
+
+        overallQueue.cancelCurrentPrepareBuild();
+        context.assertIsSatisfied();
+    }
+
+    public void testCancelPrepareBuildTaskByProject()
+        throws Exception
+    {
+        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
+        map.put( 1, 1 );
+
+        final Task prepareBuildTask = new PrepareBuildProjectsTask( map, new BuildTrigger( 1, "test-user" ), 1,
+                                                                    "Project Group A", "http://scm.root.address", 1 );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( prepareBuildTaskQueueExecutor ).getCurrentTask();
+                will( returnValue( prepareBuildTask ) );
+
+                one( prepareBuildTaskQueueExecutor ).cancelTask( prepareBuildTask );
+            }
+        } );
+
+        overallQueue.cancelPrepareBuildTask( 1 );
+        context.assertIsSatisfied();
+    }
+
+    public void testCancelPrepareBuildTaskByProjectGroup()
+        throws Exception
+    {
+        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
+        map.put( 1, 1 );
+
+        final Task prepareBuildTask = new PrepareBuildProjectsTask( map, new BuildTrigger( 1, "test-user" ), 1,
+                                                                    "Project Group A", "http://scm.root.address", 2 );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( prepareBuildTaskQueueExecutor ).getCurrentTask();
+                will( returnValue( prepareBuildTask ) );
+
+                one( prepareBuildTaskQueueExecutor ).cancelTask( prepareBuildTask );
+            }
+        } );
+
+        overallQueue.cancelPrepareBuildTask( 1, 2 );
+        context.assertIsSatisfied();
+    }
+
+    public void testGetProjectsFromPrepareBuildQueue()
+        throws Exception
+    {
+        final TaskQueue prepareBuildQueue = context.mock( TaskQueue.class, "prepare-build-queue" );
+        final List<Task> tasks = new ArrayList<Task>();
+        tasks.add( new PrepareBuildProjectsTask( new HashMap<Integer, Integer>(), new BuildTrigger( 1, "test-user" ), 2,
+                                                 "Project Group A", "http://scm.root.address", 2 ) );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( prepareBuildTaskQueueExecutor ).getQueue();
+                will( returnValue( prepareBuildQueue ) );
+
+                one( prepareBuildQueue ).getQueueSnapshot();
+                will( returnValue( tasks ) );
+            }
+        } );
+
+        List<PrepareBuildProjectsTask> returnedTasks = overallQueue.getProjectsInPrepareBuildQueue();
+        context.assertIsSatisfied();
+
+        assertNotNull( returnedTasks );
+        assertEquals( 1, returnedTasks.size() );
+    }
+
+    public void testIsInPrepareBuildQueueByProject()
+        throws Exception
+    {
+        final TaskQueue prepareBuildQueue = context.mock( TaskQueue.class, "prepare-build-queue" );
+
+        final Map<Integer, Integer> map = new HashMap<Integer, Integer>();
+        map.put( 2, 1 );
+
+        final List<Task> tasks = new ArrayList<Task>();
+        tasks.add( new PrepareBuildProjectsTask( map, new BuildTrigger( 1, "test-user" ), 1, "Project Group A",
+                                                 "http://scm.root.address", 2 ) );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( prepareBuildTaskQueueExecutor ).getQueue();
+                will( returnValue( prepareBuildQueue ) );
+
+                one( prepareBuildQueue ).getQueueSnapshot();
+                will( returnValue( tasks ) );
+            }
+        } );
+
+        assertTrue( overallQueue.isInPrepareBuildQueue( 2 ) );
+        context.assertIsSatisfied();
+    }
+
+    public void testIsInPrepareBuildQueueByProjectGroupAndScmRootId()
+        throws Exception
+    {
+        final TaskQueue prepareBuildQueue = context.mock( TaskQueue.class, "prepare-build-queue" );
+
+        final Map<Integer, Integer> map = new HashMap<Integer, Integer>();
+        map.put( 2, 1 );
+
+        final List<Task> tasks = new ArrayList<Task>();
+        tasks.add( new PrepareBuildProjectsTask( map, new BuildTrigger( 1, "test-user" ), 1, "Project Group A",
+                                                 "http://scm.root.address", 2 ) );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( prepareBuildTaskQueueExecutor ).getQueue();
+                will( returnValue( prepareBuildQueue ) );
+
+                one( prepareBuildQueue ).getQueueSnapshot();
+                will( returnValue( tasks ) );
+            }
+        } );
+
+        assertTrue( overallQueue.isInPrepareBuildQueue( 1, 2 ) );
+        context.assertIsSatisfied();
+    }
+
+    public void testIsInPrepareBuildQueueByProjectGroupAndScmRootAddress()
+        throws Exception
+    {
+        final TaskQueue prepareBuildQueue = context.mock( TaskQueue.class, "prepare-build-queue" );
+
+        final Map<Integer, Integer> map = new HashMap<Integer, Integer>();
+        map.put( 2, 1 );
+
+        final List<Task> tasks = new ArrayList<Task>();
+        tasks.add( new PrepareBuildProjectsTask( map, new BuildTrigger( 1, "test-user" ), 1, "Project Group A",
+                                                 "http://scm.root.address", 2 ) );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( prepareBuildTaskQueueExecutor ).getQueue();
+                will( returnValue( prepareBuildQueue ) );
+
+                one( prepareBuildQueue ).getQueueSnapshot();
+                will( returnValue( tasks ) );
+            }
+        } );
+
+        assertTrue( overallQueue.isInPrepareBuildQueue( 1, "http://scm.root.address" ) );
+        context.assertIsSatisfied();
+    }
+
+    public void testRemoveProjectsFromPrepareBuildQueueByProjectGroupAndScmRootId()
+        throws Exception
+    {
+        final Task prepareBuildTask = new PrepareBuildProjectsTask( new HashMap<Integer, Integer>(), new BuildTrigger(
+            1, "test-user" ), 1, "Project Group A", "http://scm.root.address", 1 );
+
+        final TaskQueue prepareBuildQueue = context.mock( TaskQueue.class, "prepare-build-queue" );
+        final List<Task> tasks = new ArrayList<Task>();
+        tasks.add( prepareBuildTask );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( prepareBuildTaskQueueExecutor ).getQueue();
+                will( returnValue( prepareBuildQueue ) );
+
+                one( prepareBuildQueue ).getQueueSnapshot();
+                will( returnValue( tasks ) );
+
+                one( prepareBuildTaskQueueExecutor ).getQueue();
+                will( returnValue( prepareBuildQueue ) );
+
+                one( prepareBuildQueue ).remove( prepareBuildTask );
+            }
+        } );
+
+        overallQueue.removeProjectFromPrepareBuildQueue( 1, 1 );
+        context.assertIsSatisfied();
+    }
+
+    public void testRemoveProjectsFromPrepareBuildQueueByProjectGroupAndScmRootAddress()
+        throws Exception
+    {
+        final Task prepareBuildTask = new PrepareBuildProjectsTask( new HashMap<Integer, Integer>(), new BuildTrigger(
+            1, "test-user" ), 1, "Project Group A", "http://scm.root.address", 1 );
+
+        final TaskQueue prepareBuildQueue = context.mock( TaskQueue.class, "prepare-build-queue" );
+        final List<Task> tasks = new ArrayList<Task>();
+        tasks.add( prepareBuildTask );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( prepareBuildTaskQueueExecutor ).getQueue();
+                will( returnValue( prepareBuildQueue ) );
+
+                one( prepareBuildQueue ).getQueueSnapshot();
+                will( returnValue( tasks ) );
+
+                one( prepareBuildTaskQueueExecutor ).getQueue();
+                will( returnValue( prepareBuildQueue ) );
+
+                one( prepareBuildQueue ).remove( prepareBuildTask );
+            }
+        } );
+
+        overallQueue.removeProjectFromPrepareBuildQueue( 1, "http://scm.root.address" );
+        context.assertIsSatisfied();
+    }
+}
diff --git a/continuum-core/src/test/java/org/apache/maven/continuum/AddMaven2ProjectTest.java b/continuum-core/src/test/java/org/apache/maven/continuum/AddMaven2ProjectTest.java
index 2ba5dda..aaa591d 100755
--- a/continuum-core/src/test/java/org/apache/maven/continuum/AddMaven2ProjectTest.java
+++ b/continuum-core/src/test/java/org/apache/maven/continuum/AddMaven2ProjectTest.java
@@ -1,7 +1,6 @@
 package org.apache.maven.continuum;
 
-import java.io.File;
-
+import org.apache.continuum.AbstractAddProjectTest;
 import org.apache.maven.continuum.builddefinition.BuildDefinitionService;
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.BuildDefinitionTemplate;
@@ -11,6 +10,9 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.File;
+import java.util.Collections;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -29,20 +31,22 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 /**
  * @author olamy
- * @since 
  * @version $Id$
  */
 public class AddMaven2ProjectTest
-    extends AbstractContinuumTest
+    extends AbstractAddProjectTest
 {
-    protected Logger log = LoggerFactory.getLogger( getClass() );
+    protected final Logger log = LoggerFactory.getLogger( getClass() );
 
     protected BuildDefinitionTemplate bdt;
 
     protected BuildDefinition bd;
-    
+
+    protected BuildDefinitionService bds;
+
     @Override
     protected void setUp()
         throws Exception
@@ -53,22 +57,22 @@
         bd.setBuildFile( "pom.xml" );
         bd.setDescription( "my foo" );
         bd.setTemplate( true );
-        BuildDefinitionService bds = (BuildDefinitionService) lookup( BuildDefinitionService.class.getName(), "default" );
+        bds = (BuildDefinitionService) lookup( BuildDefinitionService.class.getName(),
+                                                                      "default" );
         bd = bds.addBuildDefinition( bd );
-        
-        
+
         assertEquals( 5, bds.getAllBuildDefinitions().size() );
 
         bdt = new BuildDefinitionTemplate();
         bdt.setName( "bdt foo" );
-        
+
         bdt = bds.addBuildDefinitionTemplate( bdt );
-        
-        bdt = bds.addBuildDefinitionInTemplate( bdt, bd, false );        
-    }    
-    
-    
-    
+
+        bdt = bds.addBuildDefinitionInTemplate( bdt, bd, false );
+
+        createLocalRepository();
+    }
+
     public void testAddProjectToExistingGroupWithBuildDefTemplate()
         throws Exception
     {
@@ -82,30 +86,29 @@
         pg = getContinuum().getProjectGroupWithBuildDetails( pg.getId() );
         // group created with the m2 default build def 
         assertEquals( 1, pg.getBuildDefinitions().size() );
-        
+        assertEquals( "clean install", pg.getBuildDefinitions().get( 0 ).getGoals() );
 
         File rootPom = getTestFile( "src/test/resources/projects/continuum/continuum-core/pom.xml" );
 
         assertTrue( rootPom.exists() );
         //String url = getTestFile( "src/test-projects/project1/pom.xml" ).toURL().toExternalForm();
         ContinuumProjectBuildingResult result = getContinuum().addMavenTwoProject(
-                                                                                   rootPom.toURI().toURL()
-                                                                                       .toExternalForm(), pg.getId(),
-                                                                                   true, false, false, bdt.getId() );
+            rootPom.toURI().toURL().toExternalForm(), pg.getId(), true, false, false, bdt.getId(), false );
         assertNotNull( result );
 
+        assertEquals( Collections.emptyList(), result.getErrors() );
+
         assertEquals( 1, result.getProjects().size() );
 
         Project project = result.getProjects().get( 0 );
         project = getContinuum().getProjectWithBuildDetails( project.getId() );
         assertNotNull( project );
-        pg = getContinuum().getProjectGroupWithBuildDetails( pg.getId() );
         log.info( "project buildDef list size : " + project.getBuildDefinitions().size() );
-        // project with the build def coming from template
         assertEquals( 1, project.getBuildDefinitions().size() );
-        assertEquals( "clean deploy", ( (BuildDefinition) project.getBuildDefinitions().get( 0 ) ).getGoals() );
+        // project with the build def coming from template
+        assertEquals( "clean deploy", project.getBuildDefinitions().get( 0 ).getGoals() );
     }
-    
+
     public void testAddProjectWithGroupCreationWithBuildDefTemplate()
         throws Exception
     {
@@ -116,11 +119,11 @@
         assertTrue( rootPom.exists() );
 
         ContinuumProjectBuildingResult result = getContinuum().addMavenTwoProject(
-                                                                                   rootPom.toURI().toURL()
-                                                                                       .toExternalForm(), -1, true,
-                                                                                   false, true, bdt.getId() );
+            rootPom.toURI().toURL().toExternalForm(), -1, true, false, true, bdt.getId(), false );
         assertNotNull( result );
 
+        assertEquals( Collections.emptyList(), result.getErrors() );
+
         assertEquals( 1, result.getProjects().size() );
         Project project = result.getProjects().get( 0 );
         assertNotNull( project );
@@ -128,7 +131,7 @@
         log.info( "project buildDef list size : " + project.getBuildDefinitions().size() );
         // build def only at the group level du to group creation 
         assertEquals( 0, project.getBuildDefinitions().size() );
-        
+
         log.info( "all pg size " + getContinuum().getAllProjectGroups().size() );
         ProjectGroup pg = result.getProjectGroups().get( 0 );
 
@@ -139,9 +142,9 @@
         log.info( " pg builddefs size " + pg.getBuildDefinitions().size() );
         log.info( "pg bd goals " + ( (BuildDefinition) pg.getBuildDefinitions().get( 0 ) ).getGoals() );
         assertEquals( "clean deploy", ( (BuildDefinition) pg.getBuildDefinitions().get( 0 ) ).getGoals() );
-        
-    }    
-    
+
+    }
+
     public void testAddProjectWithGroupCreationDefaultBuildDef()
         throws Exception
     {
@@ -152,22 +155,22 @@
         assertTrue( rootPom.exists() );
 
         ContinuumProjectBuildingResult result = getContinuum().addMavenTwoProject(
-                                                                                   rootPom.toURI().toURL()
-                                                                                       .toExternalForm(), -1, true,
-                                                                                   false, true, -1 );
+            rootPom.toURI().toURL().toExternalForm(), -1, true, false, true, -1, false );
         assertNotNull( result );
 
+        assertEquals( Collections.emptyList(), result.getErrors() );
+
         assertEquals( 1, result.getProjects().size() );
 
         Project project = result.getProjects().get( 0 );
         assertNotNull( project );
-        
+
         assertNotNull( project );
         project = getContinuum().getProjectWithBuildDetails( project.getId() );
         log.info( "project buildDef list size : " + project.getBuildDefinitions().size() );
         // only build def at group level
         assertEquals( 0, project.getBuildDefinitions().size() );
-        
+
         log.info( "all pg size " + getContinuum().getAllProjectGroups().size() );
         ProjectGroup pg = result.getProjectGroups().get( 0 );
 
@@ -176,51 +179,88 @@
 
         pg = getContinuum().getProjectGroupWithBuildDetails( pg.getId() );
 
-        log.info( " pg groupId " + pg.getGroupId() );
         //@ group level the db from template must be used
-        log.info( " mg builddefs size " + pg.getBuildDefinitions().size() );
-        log.info( "pg bd goals " + ( (BuildDefinition) pg.getBuildDefinitions().get( 0 ) ).getGoals() );
-        assertEquals( "clean install", ( (BuildDefinition) pg.getBuildDefinitions().get( 0 ) ).getGoals() );
+        assertEquals( "clean install", pg.getBuildDefinitions().get( 0 ).getGoals() );
 
-    }       
+    }
 
     public void testAddProjectToExistingGroupDefaultBuildDef()
         throws Exception
     {
-
         ProjectGroup pg = new ProjectGroup();
-        pg.setName( "foo" );
+        String groupId = "foo";
+        pg.setName( groupId );
+        pg.setGroupId( groupId );
         pg.setDescription( "foo pg" );
         getContinuum().addProjectGroup( pg );
-        pg = getContinuum().getAllProjectGroups().get( 1 );
-        assertEquals( 2, getContinuum().getAllProjectGroups().size() );
+        pg = getContinuum().getProjectGroupByGroupIdWithBuildDetails( groupId );
+
+        assertEquals( 1, pg.getBuildDefinitions().size() );
+        BuildDefinition buildDefinition = pg.getBuildDefinitions().get( 0 );
+        assertEquals( "clean install", buildDefinition.getGoals() );
+        assertEquals( "--batch-mode --non-recursive", buildDefinition.getArguments() );
 
         File rootPom = getTestFile( "src/test/resources/projects/continuum/continuum-core/pom.xml" );
 
         assertTrue( rootPom.exists() );
         //String url = getTestFile( "src/test-projects/project1/pom.xml" ).toURL().toExternalForm();
         ContinuumProjectBuildingResult result = getContinuum().addMavenTwoProject(
-                                                                                   rootPom.toURI().toURL()
-                                                                                       .toExternalForm(), pg.getId(),
-                                                                                   true, false, false, -1 );
+            rootPom.toURI().toURL().toExternalForm(), pg.getId(), true, false, false, -1, false );
         assertNotNull( result );
 
+        assertEquals( Collections.emptyList(), result.getErrors() );
+
         assertEquals( 1, result.getProjects().size() );
 
         Project project = result.getProjects().get( 0 );
         project = getContinuum().getProjectWithBuildDetails( project.getId() );
         assertNotNull( project );
-        pg = getContinuum().getProjectGroupWithBuildDetails( pg.getId() );
-        log.info( "project buildDef list size : " + project.getBuildDefinitions().size() );
-        assertEquals( 0, project.getBuildDefinitions().size() );
-        pg = result.getProjectGroups().get( 0 );
+        assertEquals( 1, project.getBuildDefinitions().size() );
 
-        pg = getContinuum().getProjectGroupWithBuildDetails( pg.getId() );
-        
-        assertEquals( "clean install", ( (BuildDefinition) pg.getBuildDefinitions().get( 0 ) ).getGoals() );
+        buildDefinition = project.getBuildDefinitions().get( 0 );
+        assertEquals( "clean install", buildDefinition.getGoals() );
+        assertEquals( "--batch-mode", buildDefinition.getArguments() );
     }
-    
-    
+
+    public void testAddProjectToExistingGroupMatchingBuildDef()
+        throws Exception
+    {
+        ProjectGroup pg = new ProjectGroup();
+        String groupId = "testAddProjectToExistingGroupMatchingBuildDef";
+        pg.setName( groupId );
+        pg.setGroupId( groupId );
+        pg.setDescription( "foo pg" );
+        getContinuum().addProjectGroup( pg );
+        pg = getContinuum().getProjectGroupByGroupIdWithBuildDetails( groupId );
+
+        assertEquals( 1, pg.getBuildDefinitions().size() );
+        BuildDefinition buildDefinition = pg.getBuildDefinitions().get( 0 );
+        buildDefinition.setArguments( "--batch-mode" );
+        bds.updateBuildDefinition( buildDefinition );
+
+        pg = getContinuum().getProjectGroupByGroupIdWithBuildDetails( groupId );
+        buildDefinition = pg.getBuildDefinitions().get( 0 );
+        assertEquals( "clean install", buildDefinition.getGoals() );
+        assertEquals( "--batch-mode", buildDefinition.getArguments() );
+
+        File rootPom = getTestFile( "src/test/resources/projects/continuum/continuum-core/pom.xml" );
+
+        assertTrue( rootPom.exists() );
+        //String url = getTestFile( "src/test-projects/project1/pom.xml" ).toURL().toExternalForm();
+        ContinuumProjectBuildingResult result = getContinuum().addMavenTwoProject(
+            rootPom.toURI().toURL().toExternalForm(), pg.getId(), true, false, false, -1, false );
+        assertNotNull( result );
+
+        assertEquals( Collections.emptyList(), result.getErrors() );
+
+        assertEquals( 1, result.getProjects().size() );
+
+        Project project = result.getProjects().get( 0 );
+        project = getContinuum().getProjectWithBuildDetails( project.getId() );
+        assertNotNull( project );
+        assertEquals( 0, project.getBuildDefinitions().size() );
+    }
+
     private Continuum getContinuum()
         throws Exception
     {
@@ -237,7 +277,7 @@
     protected String getSpringConfigLocation()
     {
         return "applicationContextSlf4jPlexusLogger.xml";
-    }    
-    
-    
+    }
+
+
 }
diff --git a/continuum-core/src/test/java/org/apache/maven/continuum/AddProjectTest.java b/continuum-core/src/test/java/org/apache/maven/continuum/AddProjectTest.java
index 830156e..c755b44 100755
--- a/continuum-core/src/test/java/org/apache/maven/continuum/AddProjectTest.java
+++ b/continuum-core/src/test/java/org/apache/maven/continuum/AddProjectTest.java
@@ -1,3 +1,5 @@
+package org.apache.maven.continuum;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,34 +18,88 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.continuum;
 
+import org.apache.continuum.AbstractAddProjectTest;
+import org.apache.maven.continuum.builddefinition.BuildDefinitionService;
+import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
 import org.apache.maven.continuum.project.builder.maven.MavenTwoContinuumProjectBuilder;
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.DefaultHandler;
+import org.eclipse.jetty.server.handler.HandlerList;
+import org.eclipse.jetty.server.handler.ResourceHandler;
+
+import java.util.Collections;
 
 /**
  * @author <a href="mailto:olamy@apache.org">olamy</a>
- * @since 12 juin 2008
  * @version $Id$
+ * @since 12 juin 2008
  */
 public class AddProjectTest
-    extends AbstractContinuumTest
+    extends AbstractAddProjectTest
 {
+    static final String SCM_USERNAME = "test";
+
+    static final String SCM_PASSWORD = ";password";
+
+    private Server server;
+
+    private String scmUrl;
+
+    @Override
+    protected void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        createLocalRepository();
+
+        server = startJettyServer();
+        int port = server.getConnectors()[0].getLocalPort();
+        scmUrl = "http://test:;password@localhost:" + port + "/projects/continuum/continuum-core/pom.xml";
+    }
+
+    @Override
+    protected void tearDown()
+        throws Exception
+    {
+        super.tearDown();
+        server.stop();
+    }
+
+    private Server startJettyServer()
+        throws Exception
+    {
+        Server server = new Server( 0 );
+        ResourceHandler handler = new ResourceHandler();
+        handler.setResourceBase( getTestFile( "src/test/resources" ).getAbsolutePath() );
+        HandlerList handlers = new HandlerList();
+        handlers.setHandlers( new Handler[]{ handler, new DefaultHandler() } );
+        server.setHandler( handlers );
+        server.start();
+        return server;
+    }
+
     public void testScmUserNamePasswordNotStoring()
         throws Exception
     {
-        String metadataUrl = "http://test:;password@svn.apache.org/repos/asf/continuum/tags/continuum-1.1/continuum-api/pom.xml";
         DefaultContinuum continuum = (DefaultContinuum) lookup( Continuum.ROLE );
-        
-        ContinuumProjectBuildingResult result = continuum
-            .executeAddProjectsFromMetadataActivity( metadataUrl, MavenTwoContinuumProjectBuilder.ID,
-                                                     getDefaultProjectGroup().getId(), false, true, false, -1, false );
+
+        ContinuumProjectBuildingResult result = continuum.executeAddProjectsFromMetadataActivity( scmUrl,
+                                                                                                  MavenTwoContinuumProjectBuilder.ID,
+                                                                                                  getDefaultProjectGroup().getId(),
+                                                                                                  false, true, false,
+                                                                                                  -1, false, false );
+        assertEquals( Collections.emptyList(), result.getErrors() );
+
         assertEquals( 1, result.getProjects().size() );
-        
+
         // read the project from store
-        Project project = continuum.getProject( result.getProjects().get( 0 ).getId());
-        assertNull(  project.getScmUsername() );
+        Project project = continuum.getProject( result.getProjects().get( 0 ).getId() );
+        assertNull( project.getScmUsername() );
         assertNull( project.getScmPassword() );
         assertTrue( project.isScmUseCache() );
     }
@@ -51,18 +107,74 @@
     public void testScmUserNamePasswordStoring()
         throws Exception
     {
-        String metadataUrl = "http://test:;password@svn.apache.org/repos/asf/continuum/tags/continuum-1.1/continuum-api/pom.xml";
         DefaultContinuum continuum = (DefaultContinuum) lookup( Continuum.ROLE );
 
-        ContinuumProjectBuildingResult result = continuum
-            .executeAddProjectsFromMetadataActivity( metadataUrl, MavenTwoContinuumProjectBuilder.ID,
-                                                     getDefaultProjectGroup().getId(), false, false, false, -1, false );
+        ContinuumProjectBuildingResult result = continuum.executeAddProjectsFromMetadataActivity( scmUrl,
+                                                                                                  MavenTwoContinuumProjectBuilder.ID,
+                                                                                                  getDefaultProjectGroup().getId(),
+                                                                                                  false, false, false,
+                                                                                                  -1, false, false );
+        assertEquals( Collections.emptyList(), result.getErrors() );
+
         assertEquals( 1, result.getProjects().size() );
 
         // read the project from store
         Project project = continuum.getProject( result.getProjects().get( 0 ).getId() );
-        assertEquals( "test", project.getScmUsername() );
-        assertEquals( ";password", project.getScmPassword() );
+        assertEquals( SCM_USERNAME, project.getScmUsername() );
+        assertEquals( SCM_PASSWORD, project.getScmPassword() );
         assertFalse( project.isScmUseCache() );
-    }    
+    }
+
+    public void testAntProjectScmUserNamePasswordNotStoring()
+        throws Exception
+    {
+        DefaultContinuum continuum = (DefaultContinuum) lookup( Continuum.ROLE );
+
+        Project project = new Project();
+        project.setName( "Sample Ant Project" );
+        project.setVersion( "1.0" );
+        project.setScmUsername( SCM_USERNAME );
+        project.setScmPassword( SCM_PASSWORD );
+        project.setScmUrl( this.scmUrl );
+        project.setScmUseCache( true );
+
+        BuildDefinitionService bdService = (BuildDefinitionService) lookup( BuildDefinitionService.class.getName() );
+
+        int projectId = continuum.addProject( project, ContinuumBuildExecutorConstants.ANT_BUILD_EXECUTOR,
+                                              getDefaultProjectGroup().getId(),
+                                              bdService.getDefaultAntBuildDefinitionTemplate().getId() );
+
+        // read the project from store
+        Project retrievedProject = continuum.getProject( projectId );
+        assertNull( retrievedProject.getScmUsername() );
+        assertNull( retrievedProject.getScmPassword() );
+        assertTrue( retrievedProject.isScmUseCache() );
+    }
+
+    public void testAntProjectScmUserNamePasswordStoring()
+        throws Exception
+    {
+        DefaultContinuum continuum = (DefaultContinuum) lookup( Continuum.ROLE );
+
+        Project project = new Project();
+        project.setName( "Sample Ant Project" );
+        project.setVersion( "1.0" );
+        project.setScmUsername( SCM_USERNAME );
+        project.setScmPassword( SCM_PASSWORD );
+        project.setScmUrl( scmUrl );
+        project.setScmUseCache( false );
+
+        BuildDefinitionService bdService = (BuildDefinitionService) lookup( BuildDefinitionService.class.getName() );
+
+        int projectId = continuum.addProject( project, ContinuumBuildExecutorConstants.ANT_BUILD_EXECUTOR,
+                                              getDefaultProjectGroup().getId(),
+                                              bdService.getDefaultAntBuildDefinitionTemplate().getId() );
+
+        // read the project from store
+        Project retrievedProject = continuum.getProject( projectId );
+        assertEquals( SCM_USERNAME, retrievedProject.getScmUsername() );
+        assertEquals( SCM_PASSWORD, retrievedProject.getScmPassword() );
+        assertFalse( retrievedProject.isScmUseCache() );
+    }
+
 }
diff --git a/continuum-core/src/test/java/org/apache/maven/continuum/AddProjectToCheckoutQueueStub.java b/continuum-core/src/test/java/org/apache/maven/continuum/AddProjectToCheckoutQueueStub.java
new file mode 100644
index 0000000..b2a1767
--- /dev/null
+++ b/continuum-core/src/test/java/org/apache/maven/continuum/AddProjectToCheckoutQueueStub.java
@@ -0,0 +1,46 @@
+package org.apache.maven.continuum;
+
+/*
+ * 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 junit.framework.Assert;
+import org.apache.maven.continuum.core.action.AbstractContinuumAction;
+import org.apache.maven.continuum.core.action.CheckoutProjectContinuumAction;
+
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ */
+public class AddProjectToCheckoutQueueStub
+    extends AbstractContinuumAction
+{
+    @SuppressWarnings( "unchecked" )
+    public void execute( Map context )
+        throws Exception
+    {
+        getLogger().info( "Executing add-project-to-checkout-queue (stub for testing) action." );
+
+        // check if scm credentials were set in context (CONTINUUM-2466)
+        Assert.assertEquals( AddProjectTest.SCM_USERNAME, CheckoutProjectContinuumAction.getScmUsername( context,
+                                                                                                         null ) );
+        Assert.assertEquals( AddProjectTest.SCM_PASSWORD, CheckoutProjectContinuumAction.getScmPassword( context,
+                                                                                                         null ) );
+    }
+}
diff --git a/continuum-core/src/test/java/org/apache/maven/continuum/DefaultContinuumTest.java b/continuum-core/src/test/java/org/apache/maven/continuum/DefaultContinuumTest.java
index ea72e72..8dcfc4b 100644
--- a/continuum-core/src/test/java/org/apache/maven/continuum/DefaultContinuumTest.java
+++ b/continuum-core/src/test/java/org/apache/maven/continuum/DefaultContinuumTest.java
@@ -19,31 +19,39 @@
  * under the License.
  */
 
-import java.io.File;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
+import org.apache.continuum.buildmanager.BuildsManager;
+import org.apache.continuum.dao.BuildResultDao;
+import org.apache.continuum.dao.ProjectDao;
 import org.apache.continuum.model.release.ContinuumReleaseResult;
 import org.apache.continuum.model.repository.LocalRepository;
+import org.apache.continuum.release.config.ContinuumReleaseDescriptor;
 import org.apache.continuum.repository.RepositoryService;
 import org.apache.continuum.taskqueue.manager.TaskQueueManager;
+import org.apache.continuum.utils.build.BuildTrigger;
 import org.apache.maven.continuum.builddefinition.BuildDefinitionService;
 import org.apache.maven.continuum.configuration.ConfigurationService;
 import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
+import org.apache.maven.continuum.initialization.ContinuumInitializer;
 import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.BuildResult;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.project.ProjectGroup;
 import org.apache.maven.continuum.model.project.ProjectNotifier;
 import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
-import org.apache.maven.continuum.utils.ContinuumUrlValidator;
-import org.codehaus.plexus.taskqueue.TaskQueue;
-import org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor;
+import org.apache.maven.shared.release.ReleaseResult;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.integration.junit3.JUnit3Mockery;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 /**
  * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
  * @version $Id$
@@ -51,26 +59,35 @@
 public class DefaultContinuumTest
     extends AbstractContinuumTest
 {
-    protected Logger log = LoggerFactory.getLogger( getClass() );
-    
+    private static final Logger log = LoggerFactory.getLogger( DefaultContinuumTest.class );
+
+    private Mockery context;
+
+    private TaskQueueManager taskQueueManager;
+
+    private ProjectDao projectDao;
+
+    private BuildResultDao buildResultDao;
+
+    @Override
+    protected void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        context = new JUnit3Mockery();
+
+        taskQueueManager = context.mock( TaskQueueManager.class );
+
+        projectDao = context.mock( ProjectDao.class );
+    }
+
     public void testContinuumConfiguration()
         throws Exception
     {
         lookup( Continuum.ROLE );
     }
 
-    public void testLookups()
-        throws Exception
-    {
-        lookup( TaskQueue.ROLE, "build-project" );
-
-        lookup( TaskQueue.ROLE, "check-out-project" );
-
-        lookup( TaskQueueExecutor.ROLE, "build-project" );
-
-        lookup( TaskQueueExecutor.ROLE, "check-out-project" );
-    }
-
     public void testAddMavenTwoProjectSet()
         throws Exception
     {
@@ -83,20 +100,13 @@
         File rootPom = getTestFile( "src/test/resources/projects/continuum/continuum-notifiers/pom.xml" );
 
         assertTrue( rootPom.exists() );
-        
-        ContinuumUrlValidator validator = (ContinuumUrlValidator) lookup( ContinuumUrlValidator.class, "continuumUrl" );
-        
-        String fileUrl = rootPom.toURL().toExternalForm();
-        
-        //assertTrue( validator.validate( fileUrl ) );
-        
-        ContinuumProjectBuildingResult result = continuum.addMavenTwoProject( rootPom.toURI().toURL()
-                                                                              .toExternalForm(), -1, true,
-                                                                              false, true, -1 );
+
+        ContinuumProjectBuildingResult result = continuum.addMavenTwoProject( rootPom.toURI().toURL().toExternalForm(),
+                                                                              -1, true, false, true, -1, false );
 
         assertNotNull( result );
 
-        assertEquals( "result.warnings.size", 0, result.getWarnings().size() );
+        assertEquals( "result.warnings.size" + result.getErrors(), 0, result.getErrors().size() );
 
         assertEquals( "result.projects.size", 3, result.getProjects().size() );
 
@@ -104,34 +114,119 @@
 
         log.info( "number of projects: " + getProjectDao().getAllProjectsByName().size() );
 
-        log.info(
-            "number of project groups: " + getProjectGroupDao().getAllProjectGroupsWithProjects().size() );
+        log.info( "number of project groups: " + getProjectGroupDao().getAllProjectGroupsWithProjects().size() );
 
         assertEquals( "Total project count", projectCount + 3, getProjectDao().getAllProjectsByName().size() );
 
         assertEquals( "Total project group count.", projectGroupCount + 1,
                       getProjectGroupDao().getAllProjectGroupsWithProjects().size() );
 
-        Map projects = new HashMap();
+        Map<String, Project> projects = new HashMap<String, Project>();
 
-        for ( Iterator i = getProjectDao().getAllProjectsByName().iterator(); i.hasNext(); )
+        for ( Project project : getProjectDao().getAllProjectsByName() )
         {
-            Project project = (Project) i.next();
-
             projects.put( project.getName(), project );
 
             // validate project in project group
-            assertTrue( "project not in project group",
-                        getProjectGroupDao().getProjectGroupByProjectId( project.getId() ) != null );
+            assertTrue( "project not in project group", getProjectGroupDao().getProjectGroupByProjectId(
+                project.getId() ) != null );
         }
 
         assertTrue( "no irc notifier", projects.containsKey( "Continuum IRC Notifier" ) );
 
         assertTrue( "no jabber notifier", projects.containsKey( "Continuum Jabber Notifier" ) );
 
-
     }
 
+/* test failing intermittently, possibly due to the dodgy for loop
+    // handle flat multi-module projects
+    public void testAddMavenTwoProjectSetInSingleDirectory()
+        throws Exception
+    {   
+        Continuum continuum = (Continuum) lookup( Continuum.ROLE );
+        
+        String url = getTestFile( "src/test-projects/flat-multi-module/parent-project/pom.xml" ).toURL().toExternalForm();
+
+        ContinuumProjectBuildingResult result = continuum.addMavenTwoProject( url, -1, true, false, true, -1, true );
+ 
+        assertNotNull( result );
+
+        List<Project> projects = result.getProjects();
+
+        assertEquals( 4, projects.size() );     
+        
+        Project rootProject = result.getRootProject();
+        
+        assertNotNull( rootProject );
+        
+        Map<String, Project> projectsMap = new HashMap<String, Project>();
+
+        int projectGroupId = 0;
+
+        for ( Project project : getProjectDao().getAllProjectsByName() )
+        {
+            projectsMap.put( project.getName(), project );
+
+            ProjectGroup projectGroup = getProjectGroupDao().getProjectGroupByProjectId( project.getId() );
+            projectGroupId = projectGroup.getId();
+
+            // validate project in project group
+            assertTrue( "project not in project group", projectGroup != null );
+        }
+
+        // sometimes projects don't get added to checkout queue
+        continuum.buildProjectGroup( projectGroupId, new org.apache.continuum.utils.build.BuildTrigger( 1, "user" ) );
+
+        assertTrue( "no module-a", projectsMap.containsKey( "module-a" ) );
+        
+        assertTrue( "no module-b", projectsMap.containsKey( "module-b" ) );
+
+        assertTrue( "no module-d", projectsMap.containsKey( "module-d" ) );
+
+        // check if the modules were checked out in the same directory as the parent
+        ConfigurationService configurationService = ( ConfigurationService ) lookup( "configurationService" );
+        
+        File workingDir = configurationService.getWorkingDirectory();
+        
+        Project parentProject = getProjectDao().getProjectByName( "parent-project" );
+        
+        File checkoutDir = new File( workingDir, String.valueOf( parentProject.getId() ) );
+
+        for( long delay = 0; delay <= 999999999; delay++ )
+        {
+            // wait while the project has been checked out/build
+        }
+        
+        assertTrue( "checkout directory of project 'parent-project' does not exist." , new File( checkoutDir, "parent-project" ).exists() );
+        
+        assertFalse( "module-a should not have been checked out as a separate project.",
+                    new File( workingDir, String.valueOf( getProjectDao().getProjectByName( "module-a" ).getId() ) ).exists() );
+        
+        assertFalse( "module-b should not have been checked out as a separate project.",
+                    new File( workingDir, String.valueOf( getProjectDao().getProjectByName( "module-b" ).getId() ) ).exists() );
+
+        assertFalse( "module-d should not have been checked out as a separate project.",
+                     new File( workingDir, String.valueOf( getProjectDao().getProjectByName( "module-d" ).getId() ) ).exists() );
+
+        assertTrue( "module-a was not checked out in the same directory as it's parent.", new File( checkoutDir, "module-a" ).exists() );
+        
+        assertTrue( "module-b was not checked out in the same directory as it's parent.", new File( checkoutDir, "module-b" ).exists() );
+
+        assertTrue( "module-d was not checked out in the same directory as it's parent.", new File( checkoutDir, "module-c/module-d" ).exists() );
+
+        // assert project state
+        // commented out this test case as it sometimes fails because the actual checkout hasn't finished yet so
+        //    the state hasn't been updated yet
+        //assertEquals( "state of 'parent-project' should have been updated.", ContinuumProjectState.CHECKEDOUT, parentProject.getState() );
+        //
+        //assertEquals( "state of 'module-a' should have been updated.", ContinuumProjectState.CHECKEDOUT,
+        //            getProjectDao().getProjectByName( "module-a" ).getState() );
+        //
+        //assertEquals( "state of 'module-b' should have been updated.", ContinuumProjectState.CHECKEDOUT,
+        //            getProjectDao().getProjectByName( "module-b" ).getState() );
+    }
+*/
+
     public void testUpdateMavenTwoProject()
         throws Exception
     {
@@ -147,13 +242,13 @@
 
         assertNotNull( result );
 
-        List projects = result.getProjects();
+        List<Project> projects = result.getProjects();
 
         assertEquals( 1, projects.size() );
 
         assertEquals( Project.class, projects.get( 0 ).getClass() );
 
-        Project project = (Project) projects.get( 0 );
+        Project project = projects.get( 0 );
 
         // reattach
         project = continuum.getProject( project.getId() );
@@ -165,6 +260,48 @@
         project = continuum.getProject( project.getId() );
     }
 
+    public void testRemoveMavenTwoProject()
+        throws Exception
+    {
+        Continuum continuum = (Continuum) lookup( Continuum.ROLE );
+
+        Project project = makeStubProject( "test-project" );
+
+        ProjectGroup defaultGroup = getDefaultProjectGroup();
+
+        defaultGroup.addProject( project );
+
+        getProjectGroupDao().updateProjectGroup( defaultGroup );
+
+        project = getProjectDao().getProjectByName( "test-project" );
+
+        assertNotNull( project );
+
+        BuildResult buildResult = new BuildResult();
+
+        getBuildResultDao().addBuildResult( project, buildResult );
+
+        Collection<BuildResult> brs = continuum.getBuildResultsForProject( project.getId() );
+
+        assertEquals( "Build result of project was not added", 1, brs.size() );
+
+        // delete project
+        continuum.removeProject( project.getId() );
+
+        try
+        {
+            continuum.getProject( project.getId() );
+
+            fail( "Project was not removed" );
+        }
+        catch ( ContinuumException expected )
+        {
+            brs = continuum.getBuildResultsForProject( project.getId() );
+
+            assertEquals( "Build result of project was not removed", 0, brs.size() );
+        }
+    }
+
     public void testBuildDefinitions()
         throws Exception
     {
@@ -176,13 +313,13 @@
 
         assertNotNull( result );
 
-        List projects = result.getProjects();
+        List<Project> projects = result.getProjects();
 
         assertEquals( 1, projects.size() );
 
         assertEquals( Project.class, projects.get( 0 ).getClass() );
 
-        Project project = (Project) projects.get( 0 );
+        Project project = projects.get( 0 );
 
         // reattach
         project = continuum.getProject( project.getId() );
@@ -191,13 +328,13 @@
 
         projectGroup = getProjectGroupDao().getProjectGroupWithBuildDetailsByProjectGroupId( projectGroup.getId() );
 
-        List buildDefs = projectGroup.getBuildDefinitions();
+        List<BuildDefinition> buildDefs = projectGroup.getBuildDefinitions();
 
         assertTrue( "missing project group build definition", !buildDefs.isEmpty() );
 
         assertTrue( "more then one project group build definition on add project", buildDefs.size() == 1 );
 
-        BuildDefinition pgbd = (BuildDefinition) buildDefs.get( 0 );
+        BuildDefinition pgbd = buildDefs.get( 0 );
 
         pgbd.setGoals( "foo" );
 
@@ -209,9 +346,6 @@
 
         assertTrue( "project group build definition is not default", pgbd.isDefaultForProject() );
 
-        assertTrue( "project group build definition not default for project",
-                    continuum.getDefaultBuildDefinition( project.getId() ).getId() == pgbd.getId() );
-
         BuildDefinition nbd = new BuildDefinition();
         nbd.setGoals( "clean" );
         nbd.setArguments( "" );
@@ -220,8 +354,8 @@
 
         continuum.addBuildDefinitionToProject( project.getId(), nbd );
 
-        assertTrue( "project lvl build definition not default for project",
-                    continuum.getDefaultBuildDefinition( project.getId() ).getId() == nbd.getId() );
+        assertTrue( "project lvl build definition not default for project", continuum.getDefaultBuildDefinition(
+            project.getId() ).getId() == nbd.getId() );
 
         continuum.removeBuildDefinitionFromProject( project.getId(), nbd.getId() );
 
@@ -241,15 +375,13 @@
 
     /**
      * todo add another project group to test
-     *
-     * @throws Exception
      */
     public void testProjectGroups()
         throws Exception
     {
         Continuum continuum = (Continuum) lookup( Continuum.ROLE );
 
-        Collection projectGroupList = continuum.getAllProjectGroupsWithProjects();
+        Collection projectGroupList = continuum.getAllProjectGroups();
 
         int projectGroupsBefore = projectGroupList.size();
 
@@ -263,11 +395,11 @@
 
         assertEquals( 1, result.getProjectGroups().size() );
 
-        ProjectGroup projectGroup = (ProjectGroup) result.getProjectGroups().get( 0 );
+        ProjectGroup projectGroup = result.getProjectGroups().get( 0 );
 
         assertEquals( "plexus", projectGroup.getGroupId() );
 
-        projectGroupList = continuum.getAllProjectGroupsWithProjects();
+        projectGroupList = continuum.getAllProjectGroups();
 
         assertEquals( "Project group missing, should have " + ( projectGroupsBefore + 1 ) + " project groups",
                       projectGroupsBefore + 1, projectGroupList.size() );
@@ -276,24 +408,38 @@
 
         assertNotNull( projectGroup );
 
+        BuildsManager buildsManager = continuum.getBuildsManager();
+
+        List<Project> projects = continuum.getProjectGroupWithProjects( projectGroup.getId() ).getProjects();
+        int[] projectIds = new int[projects.size()];
+
+        int idx = 0;
+        for ( Project project : projects )
+        {
+            projectIds[idx] = project.getId();
+            idx++;
+        }
+
+        while ( buildsManager.isAnyProjectCurrentlyBeingCheckedOut( projectIds ) )
+        {
+        }
+
         continuum.removeProjectGroup( projectGroup.getId() );
 
-        projectGroupList = continuum.getAllProjectGroupsWithProjects();
+        projectGroupList = continuum.getAllProjectGroups();
 
         assertEquals( "Remove project group failed", projectGroupsBefore, projectGroupList.size() );
     }
 
     /**
      * test the logic for notifiers
-     *
-     * @throws Exception
      */
     public void testProjectAndGroupNotifiers()
         throws Exception
     {
         Continuum continuum = (Continuum) lookup( Continuum.ROLE );
 
-        Collection projectGroupList = continuum.getAllProjectGroupsWithProjects();
+        Collection projectGroupList = continuum.getAllProjectGroups();
 
         int projectGroupsBefore = projectGroupList.size();
 
@@ -307,13 +453,12 @@
 
         assertEquals( 1, result.getProjectGroups().size() );
 
-        ProjectGroup projectGroup = (ProjectGroup) result.getProjectGroups().get( 0 );
+        ProjectGroup projectGroup = result.getProjectGroups().get( 0 );
 
         continuum.addGroupNotifier( projectGroup.getId(), new ProjectNotifier() );
 
-        for ( Iterator i = projectGroup.getProjects().iterator(); i.hasNext(); )
+        for ( Project p : (List<Project>) projectGroup.getProjects() )
         {
-            Project p = (Project) i.next();
             continuum.addNotifier( p.getId(), new ProjectNotifier() );
         }
 
@@ -321,9 +466,8 @@
 
         assertEquals( 1, projectGroup.getNotifiers().size() );
 
-        for ( Iterator i = projectGroup.getProjects().iterator(); i.hasNext(); )
+        for ( Project p : (List<Project>) projectGroup.getProjects() )
         {
-            Project p = (Project) i.next();
             assertEquals( 2, p.getNotifiers().size() );
         }
     }
@@ -343,8 +487,8 @@
             //expected, check for twice wrapped exception
             if ( e.getCause() != null )
             {
-                assertFalse( exceptionName + " is wrapped in " + exceptionName, e.getCause().getClass()
-                    .equals( ContinuumException.class ) );
+                assertFalse( exceptionName + " is wrapped in " + exceptionName, e.getCause().getClass().equals(
+                    ContinuumException.class ) );
             }
         }
     }
@@ -354,7 +498,7 @@
     {
         Continuum continuum = (Continuum) lookup( Continuum.ROLE );
 
-        TaskQueueManager taskQueueManager = (TaskQueueManager) lookup( TaskQueueManager.ROLE );
+        BuildsManager parallelBuildsManager = continuum.getBuildsManager();
 
         String url = getTestFile( "src/test-projects/project1/pom.xml" ).toURL().toExternalForm();
 
@@ -362,30 +506,76 @@
 
         assertNotNull( result );
 
-        List projects = result.getProjects();
+        List<Project> projects = result.getProjects();
 
         assertEquals( 1, projects.size() );
 
         assertEquals( Project.class, projects.get( 0 ).getClass() );
 
-        Project project = (Project) projects.get( 0 );
+        Project project = projects.get( 0 );
 
-        assertTrue( "project missing from the checkout queue",
-                    taskQueueManager.removeProjectFromCheckoutQueue( project.getId() ) );
+        parallelBuildsManager.removeProjectFromCheckoutQueue( project.getId() );
 
-        assertFalse( "project still exist on the checkout queue",
-                     taskQueueManager.removeProjectFromCheckoutQueue( project.getId() ) );
+        assertFalse( "project still exist on the checkout queue", parallelBuildsManager.isInAnyCheckoutQueue(
+            project.getId() ) );
     }
 
+    /*public void testCreationOfProjectScmRootDuringInitialization()
+    throws Exception
+{
+    DefaultContinuum continuum = (DefaultContinuum) getContinuum();
+
+    ProjectGroup defaultProjectGroup =
+        continuum.getProjectGroupByGroupId( ContinuumInitializer.DEFAULT_PROJECT_GROUP_GROUP_ID );
+
+    ProjectScmRoot scmRoot = new ProjectScmRoot();
+    scmRoot.setProjectGroup( defaultProjectGroup );
+    scmRoot.setScmRootAddress( "http://temp.company.com/svn/trunk" );
+    getProjectScmRootDao().addProjectScmRoot( scmRoot );
+
+    defaultProjectGroup = continuum.getProjectGroupWithProjects( defaultProjectGroup.getId() );
+    assertEquals( 0, defaultProjectGroup.getProjects().size() );
+
+    Project project = new Project();
+    project.setGroupId( "project1" );
+    project.setArtifactId( "project1" );
+    project.setVersion( "1.0-SNAPSHOT" );
+    project.setScmUrl( "http://temp.company.com/svn/trunk/project1" );
+    defaultProjectGroup.addProject( project );
+
+    project = new Project();
+    project.setGroupId( "project2" );
+    project.setArtifactId( "project2" );
+    project.setVersion( "1.0-SNAPSHOT" );
+    project.setScmUrl( "http://temp.company.com/svn/trunk/project2" );
+    defaultProjectGroup.addProject( project );
+
+    project = new Project();
+    project.setGroupId( "project3" );
+    project.setArtifactId( "project3" );
+    project.setVersion( "1.0-SNAPSHOT" );
+    project.setScmUrl( "http://temp.company.com/svn/trunk/project3" );
+    defaultProjectGroup.addProject( project );
+
+    getProjectGroupDao().updateProjectGroup( defaultProjectGroup );
+
+    continuum.initialize();
+
+    List<ProjectScmRoot> scmRoots = continuum.getProjectScmRootByProjectGroup( defaultProjectGroup.getId() );
+    assertEquals( "#scmRoots in the group", 1, scmRoots.size() );
+}    */
+
     public void testAddAntProjectWithdefaultBuildDef()
         throws Exception
     {
         Continuum continuum = getContinuum();
 
         Project project = new Project();
-        int projectId = continuum.addProject( project, ContinuumBuildExecutorConstants.ANT_BUILD_EXECUTOR );
-        ProjectGroup defaultProjectGroup = continuum
-            .getProjectGroupByGroupId( Continuum.DEFAULT_PROJECT_GROUP_GROUP_ID );
+        project.setScmUrl( "scmUrl" );
+        ProjectGroup defaultProjectGroup = continuum.getProjectGroupByGroupId(
+            ContinuumInitializer.DEFAULT_PROJECT_GROUP_GROUP_ID );
+        int projectId = continuum.addProject( project, ContinuumBuildExecutorConstants.ANT_BUILD_EXECUTOR,
+                                              defaultProjectGroup.getId() );
         assertEquals( 1, continuum.getProjectGroupWithProjects( defaultProjectGroup.getId() ).getProjects().size() );
         project = continuum.getProjectWithAllDetails( projectId );
         assertNotNull( project );
@@ -394,8 +584,8 @@
         assertEquals( 4, service.getAllBuildDefinitionTemplate().size() );
         assertEquals( 5, service.getAllBuildDefinitions().size() );
 
-        BuildDefinition buildDef = (BuildDefinition) service.getDefaultAntBuildDefinitionTemplate()
-            .getBuildDefinitions().get( 0 );
+        BuildDefinition buildDef =
+            (BuildDefinition) service.getDefaultAntBuildDefinitionTemplate().getBuildDefinitions().get( 0 );
         buildDef = service.cloneBuildDefinition( buildDef );
         buildDef.setTemplate( false );
         continuum.addBuildDefinitionToProject( project.getId(), buildDef );
@@ -410,24 +600,23 @@
     {
         Continuum continuum = getContinuum();
         RepositoryService service = (RepositoryService) lookup( RepositoryService.ROLE );
-        
+
         LocalRepository repository = new LocalRepository();
         repository.setName( "defaultRepo" );
         repository.setLocation( getTestFile( "target/default-repository" ).getAbsolutePath() );
         repository = service.addLocalRepository( repository );
-        
+
         ProjectGroup group = new ProjectGroup();
         group.setGroupId( "testGroup" );
         group.setName( "testGroup" );
         group.setLocalRepository( repository );
         continuum.addProjectGroup( group );
-        
-        ProjectGroup retrievedDefaultProjectGroup = continuum
-        .getProjectGroupByGroupId( "testGroup" );
+
+        ProjectGroup retrievedDefaultProjectGroup = continuum.getProjectGroupByGroupId( "testGroup" );
         assertNotNull( retrievedDefaultProjectGroup.getLocalRepository() );
-        
+
         continuum.removeProjectGroup( retrievedDefaultProjectGroup.getId() );
-        
+
         try
         {
             continuum.getProjectGroupByGroupId( "testGroup" );
@@ -437,7 +626,7 @@
         {
             // should fail. do nothing.
         }
-        
+
         LocalRepository retrievedRepository = service.getLocalRepository( repository.getId() );
         assertNotNull( retrievedRepository );
         assertEquals( repository, retrievedRepository );
@@ -448,41 +637,136 @@
     {
         Continuum continuum = getContinuum();
 
-        ProjectGroup defaultProjectGroup = continuum.getProjectGroupByGroupId( Continuum.DEFAULT_PROJECT_GROUP_GROUP_ID );
-
+        Project project = makeStubProject( "test-project" );
+        ProjectGroup defaultGroup = getDefaultProjectGroup();
+        defaultGroup.addProject( project );
+        getProjectGroupDao().updateProjectGroup( defaultGroup );
+        project = getProjectDao().getProjectByName( "test-project" );
+        assertNotNull( project );
         assertEquals( 0, continuum.getAllContinuumReleaseResults().size() );
 
-        ContinuumReleaseResult releaseResult = new ContinuumReleaseResult();
-        releaseResult.setStartTime( System.currentTimeMillis() );
+        ReleaseResult result = new ReleaseResult();
+        result.setStartTime( System.currentTimeMillis() );
+        result.setEndTime( System.currentTimeMillis() );
+        result.setResultCode( 200 );
+        result.appendOutput( "Error in release" );
 
-        File logFile = continuum.getConfiguration().getReleaseOutputFile( defaultProjectGroup.getId(), 
-                                                                          "releases-" + releaseResult.getStartTime() );
-        logFile.mkdirs();
+        ContinuumReleaseDescriptor descriptor = new ContinuumReleaseDescriptor();
+        descriptor.setPreparationGoals( "clean" );
+        descriptor.setReleaseBy( "admin" );
 
-        assertTrue( logFile.exists() );
+        continuum.getReleaseManager().getReleaseResults().put( "test-release-id", result );
+        continuum.getReleaseManager().getPreparedReleases().put( "test-release-id", descriptor );
 
-        releaseResult.setResultCode( 0 );
-        releaseResult.setEndTime( System.currentTimeMillis() );
-        releaseResult.setProjectGroup( defaultProjectGroup );
+        ContinuumReleaseResult releaseResult = continuum.addContinuumReleaseResult( project.getId(), "test-release-id",
+                                                                                    "prepare" );
 
         releaseResult = continuum.addContinuumReleaseResult( releaseResult );
 
-        List<ContinuumReleaseResult> releaseResults = continuum.getContinuumReleaseResultsByProjectGroup( defaultProjectGroup.getId() );
+        List<ContinuumReleaseResult> releaseResults = continuum.getContinuumReleaseResultsByProjectGroup(
+            defaultGroup.getId() );
         assertEquals( 1, releaseResults.size() );
         assertEquals( releaseResult, releaseResults.get( 0 ) );
 
         continuum.removeContinuumReleaseResult( releaseResult.getId() );
-        assertEquals( 0 , continuum.getAllContinuumReleaseResults().size() );
-        assertFalse( logFile.exists() );
-        assertEquals( defaultProjectGroup, continuum.getProjectGroupByGroupId( Continuum.DEFAULT_PROJECT_GROUP_GROUP_ID ) );
-        
+        assertEquals( 0, continuum.getAllContinuumReleaseResults().size() );
+        assertEquals( defaultGroup, continuum.getProjectGroupByGroupId(
+            ContinuumInitializer.DEFAULT_PROJECT_GROUP_GROUP_ID ) );
     }
-    
+
+    public void testBuildProjectWhileProjectIsInReleaseStage()
+        throws Exception
+    {
+        DefaultContinuum continuum = (DefaultContinuum) getContinuum();
+
+        continuum.setTaskQueueManager( taskQueueManager );
+
+        continuum.setProjectDao( projectDao );
+
+        final Project project = new Project();
+        project.setId( 1 );
+        project.setName( "Continuum Core" );
+        project.setGroupId( "org.apache.continuum" );
+        project.setArtifactId( "continuum-core" );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( projectDao ).getProject( 1 );
+                will( returnValue( project ) );
+
+                one( taskQueueManager ).isProjectInReleaseStage( "org.apache.continuum:continuum-core" );
+                will( returnValue( true ) );
+            }
+        } );
+
+        try
+        {
+            continuum.buildProject( 1, "test-user" );
+            fail( "An exception should have been thrown." );
+        }
+        catch ( ContinuumException e )
+        {
+            assertEquals( "Project (id=1) is currently in release stage.", e.getMessage() );
+        }
+    }
+
+    public void testBuildProjectGroupWhileAtLeastOneProjectIsInReleaseStage()
+        throws Exception
+    {
+        DefaultContinuum continuum = (DefaultContinuum) getContinuum();
+
+        continuum.setTaskQueueManager( taskQueueManager );
+
+        continuum.setProjectDao( projectDao );
+
+        final List<Project> projects = new ArrayList<Project>();
+
+        Project project = new Project();
+        project.setId( 1 );
+        project.setName( "Continuum Core" );
+        project.setGroupId( "org.apache.continuum" );
+        project.setArtifactId( "continuum-core" );
+        projects.add( project );
+
+        project = new Project();
+        project.setId( 2 );
+        project.setName( "Continuum API" );
+        project.setGroupId( "org.apache.continuum" );
+        project.setArtifactId( "continuum-api" );
+        projects.add( project );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( projectDao ).getProjectsInGroup( 1 );
+                will( returnValue( projects ) );
+
+                one( taskQueueManager ).isProjectInReleaseStage( "org.apache.continuum:continuum-core" );
+                will( returnValue( true ) );
+            }
+        } );
+
+        try
+        {
+            continuum.buildProjectGroup( 1, new BuildTrigger( 1, "test-user" ) );
+            fail( "An exception should have been thrown." );
+        }
+        catch ( ContinuumException e )
+        {
+            assertEquals( "Cannot build project group. Project (id=1) in group is currently in release stage.",
+                          e.getMessage() );
+        }
+    }
+
     private Continuum getContinuum()
         throws Exception
     {
         return (Continuum) lookup( Continuum.ROLE );
     }
 
-
+    private BuildResultDao getBuildResultDao()
+    {
+        return (BuildResultDao) lookup( BuildResultDao.class.getName() );
+    }
 }
diff --git a/continuum-core/src/test/java/org/apache/maven/continuum/buildcontroller/BuildProjectTaskExecutorTest.java b/continuum-core/src/test/java/org/apache/maven/continuum/buildcontroller/BuildProjectTaskExecutorTest.java
index 732cee6..ae14655 100644
--- a/continuum-core/src/test/java/org/apache/maven/continuum/buildcontroller/BuildProjectTaskExecutorTest.java
+++ b/continuum-core/src/test/java/org/apache/maven/continuum/buildcontroller/BuildProjectTaskExecutorTest.java
@@ -20,6 +20,7 @@
  */
 
 import org.apache.continuum.taskqueue.BuildProjectTask;
+import org.apache.continuum.utils.build.BuildTrigger;
 import org.apache.maven.continuum.AbstractContinuumTest;
 import org.apache.maven.continuum.core.action.AbstractContinuumAction;
 import org.apache.maven.continuum.model.project.BuildDefinition;
@@ -61,8 +62,8 @@
         {
             super.setUp();
 
-            projectBuilder =
-                (ContinuumProjectBuilder) lookup( ContinuumProjectBuilder.ROLE, MavenTwoContinuumProjectBuilder.ID );
+            projectBuilder = (ContinuumProjectBuilder) lookup( ContinuumProjectBuilder.ROLE,
+                                                               MavenTwoContinuumProjectBuilder.ID );
 
             buildQueue = (TaskQueue) lookup( TaskQueue.ROLE, "build-project" );
 
@@ -187,7 +188,7 @@
 
         System.err.println( "Waiting for task to start" );
 
-        Task curTask = null;
+        Task curTask;
 
         // Sleep at most 10 seconds for the task to start
         for ( int i = 0; i < 1000; i++ )
@@ -225,11 +226,11 @@
 
         projectGroup.addBuildDefinition( buildDefinition );
 
-        Map pgContext = new HashMap();
+        Map<String, Object> pgContext = new HashMap<String, Object>();
 
-        pgContext.put( AbstractContinuumAction.KEY_WORKING_DIRECTORY, project.getWorkingDirectory() );
+        AbstractContinuumAction.setWorkingDirectory( pgContext, project.getWorkingDirectory() );
 
-        pgContext.put( AbstractContinuumAction.KEY_UNVALIDATED_PROJECT_GROUP, projectGroup );
+        AbstractContinuumAction.setUnvalidatedProjectGroup( pgContext, projectGroup );
 
         actionManager.lookup( "validate-project-group" ).execute( pgContext );
 
@@ -245,8 +246,10 @@
 
         // projectGroup = continuumStore.addProjectGroup( projectGroup );
 
-        BuildProjectTask task = new BuildProjectTask( project.getId(), buildDefinition.getId(), 0, project.getName(),
-                                                      buildDefinition.getDescription() );
+        BuildProjectTask task = new BuildProjectTask( project.getId(), buildDefinition.getId(), new BuildTrigger( 0,
+                                                                                                                  "" ),
+                                                      project.getName(), buildDefinition.getDescription(), null,
+                                                      projectGroupId );
 
         task.setMaxExecutionTime( maxRunTime );
 
@@ -269,7 +272,7 @@
 
         assertEquals( "#Projectgroups", 1, result.getProjectGroups().size() );
 
-        ProjectGroup pg = (ProjectGroup) result.getProjectGroups().get( 0 );
+        ProjectGroup pg = result.getProjectGroups().get( 0 );
 
         // If the next part fails, remove this code! Then result.getProjects
         // might be empty, and result.projectgroups[0].getProjects contains
@@ -277,7 +280,7 @@
 
         assertEquals( "#Projects in result", 1, result.getProjects().size() );
 
-        Project p = (Project) result.getProjects().get( 0 );
+        Project p = result.getProjects().get( 0 );
 
         pg.addProject( p );
 
diff --git a/continuum-core/src/test/java/org/apache/maven/continuum/buildcontroller/DefaultBuildControllerTest.java b/continuum-core/src/test/java/org/apache/maven/continuum/buildcontroller/DefaultBuildControllerTest.java
index 5883586..17a79b3 100644
--- a/continuum-core/src/test/java/org/apache/maven/continuum/buildcontroller/DefaultBuildControllerTest.java
+++ b/continuum-core/src/test/java/org/apache/maven/continuum/buildcontroller/DefaultBuildControllerTest.java
@@ -21,27 +21,35 @@
 
 import org.apache.continuum.dao.BuildDefinitionDao;
 import org.apache.continuum.dao.BuildResultDao;
+import org.apache.continuum.model.project.ProjectScmRoot;
+import org.apache.continuum.utils.build.BuildTrigger;
 import org.apache.maven.continuum.AbstractContinuumTest;
+import org.apache.maven.continuum.core.action.AbstractContinuumAction;
 import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.BuildResult;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.project.ProjectDependency;
+import org.apache.maven.continuum.model.project.Schedule;
 import org.apache.maven.continuum.model.scm.ScmResult;
 import org.apache.maven.continuum.project.ContinuumProjectState;
 
 import java.io.BufferedWriter;
 import java.io.File;
 import java.io.FileWriter;
-import java.io.IOException;
 import java.util.Calendar;
 import java.util.List;
+import java.util.Map;
 
 public class DefaultBuildControllerTest
     extends AbstractContinuumTest
 {
     private DefaultBuildController controller;
 
+    private static String FORCED_BUILD_USER = "TestUsername";
+
+    private static String SCHEDULE_NAME = "TEST_SCHEDULE";
+
     int projectId1;
 
     int projectId2;
@@ -99,7 +107,7 @@
         projectId2 = addProject( project2 ).getId();
         buildDefinitionId2 = buildDefinitionDao.getDefaultBuildDefinition( projectId2 ).getId();
         createPomFile( getProjectDao().getProjectWithAllDetails( projectId2 ) );
-        
+
         controller = (DefaultBuildController) lookup( BuildController.ROLE );
     }
 
@@ -117,27 +125,44 @@
     private BuildDefinition createBuildDefinition()
     {
         BuildDefinition builddef = new BuildDefinition();
+        Schedule schedule = new Schedule();
+        schedule.setName( SCHEDULE_NAME );
+        builddef.setSchedule( schedule );
         builddef.setBuildFile( "pom.xml" );
         builddef.setGoals( "clean" );
         builddef.setDefaultForProject( true );
         return builddef;
     }
 
-    private BuildContext getContext()
+    private BuildContext getScheduledBuildContext()
         throws Exception
     {
-        return controller.initializeBuildContext( projectId2, buildDefinitionId2,
-                                                  ContinuumProjectState.TRIGGER_SCHEDULED );
+        return controller.initializeBuildContext( projectId2, buildDefinitionId2, new BuildTrigger(
+            ContinuumProjectState.TRIGGER_SCHEDULED ), new ScmResult() );
+    }
+
+    private BuildContext getForcedBuildContext()
+        throws Exception
+    {
+        return controller.initializeBuildContext( projectId2, buildDefinitionId2, new BuildTrigger(
+            ContinuumProjectState.TRIGGER_FORCED, FORCED_BUILD_USER ), new ScmResult() );
     }
 
     private BuildContext getContext( int hourOfLastExecution )
         throws Exception
     {
-        BuildContext context = getContext();
+        BuildContext context = getScheduledBuildContext();
         BuildResult oldBuildResult = new BuildResult();
         oldBuildResult.setEndTime( Calendar.getInstance().getTimeInMillis() + ( hourOfLastExecution * 3600000 ) );
         context.setOldBuildResult( oldBuildResult );
         context.setScmResult( new ScmResult() );
+
+        Map<String, Object> actionContext = context.getActionContext();
+        ProjectScmRoot projectScmRoot = new ProjectScmRoot();
+        projectScmRoot.setId( 1 );
+        projectScmRoot.setScmRootAddress( "scm:local:src/test-projects:flat-multi-module" );
+        AbstractContinuumAction.setProjectScmRoot( actionContext, projectScmRoot );
+
         return context;
     }
 
@@ -161,7 +186,7 @@
         p2.setState( ContinuumProjectState.NEW );
         getProjectDao().updateProject( p2 );
 
-        BuildContext context = getContext();
+        BuildContext context = getScheduledBuildContext();
         controller.checkProjectDependencies( context );
         assertEquals( 0, context.getModifiedDependencies().size() );
         assertTrue( controller.shouldBuild( context ) );
@@ -170,7 +195,7 @@
     public void testWithNewBuildDefinition()
         throws Exception
     {
-        BuildContext context = getContext();
+        BuildContext context = getScheduledBuildContext();
         assertNull( context.getOldBuildResult() );
         assertTrue( controller.shouldBuild( context ) );
     }
@@ -184,19 +209,56 @@
         assertTrue( controller.shouldBuild( context ) );
     }
 
+    public void testWithNullScmResult()
+        throws Exception
+    {
+        BuildContext context = getContext( +1 );
+        context.setScmResult( null );
+        controller.checkProjectDependencies( context );
+        assertEquals( 0, context.getModifiedDependencies().size() );
+        assertFalse( controller.shouldBuild( context ) );
+    }
+
+    public void testForcedBuildTriggeredByField()
+        throws Exception
+    {
+        BuildContext context = getForcedBuildContext();
+        assertEquals( FORCED_BUILD_USER, context.getBuildTrigger().getTriggeredBy() );
+    }
+
+    public void testScheduledBuildTriggeredByField()
+        throws Exception
+    {
+        BuildContext context = getScheduledBuildContext();
+        assertEquals( SCHEDULE_NAME, context.getBuildTrigger().getTriggeredBy() );
+    }
+
+    public void testScheduledBuildTriggeredByField_UsernameProvided()
+        throws Exception
+    {
+        BuildTrigger buildTrigger = new BuildTrigger( ContinuumProjectState.TRIGGER_SCHEDULED, "test-user" );
+
+        BuildContext context = controller.initializeBuildContext( projectId2, buildDefinitionId2, buildTrigger,
+                                                                  new ScmResult() );
+
+        String contextTriggeredBy = context.getBuildTrigger().getTriggeredBy();
+        assertFalse( "test-user".equals( contextTriggeredBy ) );
+        assertEquals( SCHEDULE_NAME, contextTriggeredBy );
+    }
+
     private File getWorkingDirectory()
         throws Exception
     {
         File workingDirectory = getTestFile( "target/working-directory" );
-        
+
         if ( !workingDirectory.exists() )
         {
             workingDirectory.mkdir();
         }
-        
+
         return workingDirectory;
     }
-    
+
     private File getWorkingDirectory( Project project )
         throws Exception
     {
@@ -210,23 +272,23 @@
 
         return projectDir;
     }
-    
+
     private void createPomFile( Project project )
         throws Exception
     {
         File pomFile = new File( getWorkingDirectory( project ), "pom.xml" );
-        
+
         BufferedWriter out = new BufferedWriter( new FileWriter( pomFile ) );
         out.write( "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" " +
-        		   "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
-        		   "xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n" );
+                       "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
+                       "xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n" );
         out.write( "<modelVersion>4.0.0</modelVersion>\n" );
         out.write( "<groupId>" + project.getGroupId() + "</groupId>\n" );
         out.write( "<artifactId>" + project.getArtifactId() + "</artifactId>\n" );
         out.write( "<version>" + project.getVersion() + "</version>\n" );
         out.write( "<scm>\n" );
-        out.write( "<connection>" + "scm:local|" + getWorkingDirectory().getAbsolutePath() + 
-                   "|" + project.getId() + "</connection>\n" );
+        out.write( "<connection>" + "scm:local|" + getWorkingDirectory().getAbsolutePath() +
+                       "|" + project.getId() + "</connection>\n" );
         out.write( "</scm>" );
 
         if ( project.getDependencies().size() > 0 )
@@ -248,7 +310,7 @@
 
         out.write( "</project>" );
         out.close();
-        
+
         System.out.println( "pom file created" );
     }
 }
diff --git a/continuum-core/src/test/java/org/apache/maven/continuum/builddefinition/DefaultBuildDefinitionServiceTest.java b/continuum-core/src/test/java/org/apache/maven/continuum/builddefinition/DefaultBuildDefinitionServiceTest.java
index 20b757f..86001ae 100755
--- a/continuum-core/src/test/java/org/apache/maven/continuum/builddefinition/DefaultBuildDefinitionServiceTest.java
+++ b/continuum-core/src/test/java/org/apache/maven/continuum/builddefinition/DefaultBuildDefinitionServiceTest.java
@@ -1,3 +1,5 @@
+package org.apache.maven.continuum.builddefinition;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,15 +18,15 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.continuum.builddefinition;
 
-import org.apache.log4j.Logger;
+import org.apache.continuum.dao.DaoUtils;
 import org.apache.maven.continuum.AbstractContinuumTest;
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.BuildDefinitionTemplate;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.project.ProjectGroup;
-import org.apache.continuum.dao.DaoUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.List;
 
@@ -36,14 +38,10 @@
 public class DefaultBuildDefinitionServiceTest
     extends AbstractContinuumTest
 {
-    private Logger logger = Logger.getLogger( getClass() );
-
-    private ProjectGroup projectGroup;
+    private static final Logger logger = LoggerFactory.getLogger( DefaultBuildDefinitionServiceTest.class );
 
     private Project project;
 
-    private BuildDefinition buildDefinition;
-
     private BuildDefinitionTemplate buildDefinitionTemplate;
 
     protected void setUp()
@@ -53,7 +51,7 @@
         DaoUtils daoUtils = (DaoUtils) lookup( DaoUtils.class.getName() );
         daoUtils.eraseDatabase();
 
-        projectGroup = new ProjectGroup();
+        ProjectGroup projectGroup = new ProjectGroup();
         projectGroup.setName( "test" );
         projectGroup = getProjectGroupDao().addProjectGroup( projectGroup );
 
@@ -64,7 +62,7 @@
         projectGroup.addProject( project );
         getProjectGroupDao().updateProjectGroup( projectGroup );
 
-        buildDefinition = new BuildDefinition();
+        BuildDefinition buildDefinition = new BuildDefinition();
         buildDefinition.setTemplate( true );
         buildDefinition.setArguments( "-N" );
         buildDefinition.setGoals( "clean test-compile" );
@@ -75,8 +73,8 @@
         buildDefinitionTemplate = new BuildDefinitionTemplate();
         buildDefinitionTemplate.setName( "test" );
         buildDefinitionTemplate = getBuildDefinitionService().addBuildDefinitionTemplate( buildDefinitionTemplate );
-        buildDefinitionTemplate =
-            getBuildDefinitionService().addBuildDefinitionInTemplate( buildDefinitionTemplate, buildDefinition, false );
+        buildDefinitionTemplate = getBuildDefinitionService().addBuildDefinitionInTemplate( buildDefinitionTemplate,
+                                                                                            buildDefinition, false );
 
 
     }
@@ -125,13 +123,15 @@
     public void testGetDefaultBuildDef()
         throws Exception
     {
-        BuildDefinition bd = (BuildDefinition) getBuildDefinitionService().getDefaultAntBuildDefinitionTemplate()
-            .getBuildDefinitions().get( 0 );
+        BuildDefinition bd =
+            (BuildDefinition) getBuildDefinitionService().getDefaultAntBuildDefinitionTemplate().getBuildDefinitions().get(
+                0 );
         assertNotNull( bd );
         assertEquals( "build.xml", bd.getBuildFile() );
 
-        bd = (BuildDefinition) getBuildDefinitionService().getDefaultMavenTwoBuildDefinitionTemplate()
-            .getBuildDefinitions().get( 0 );
+        bd =
+            (BuildDefinition) getBuildDefinitionService().getDefaultMavenTwoBuildDefinitionTemplate().getBuildDefinitions().get(
+                0 );
         BuildDefinitionService buildDefinitionService = (BuildDefinitionService) lookup( BuildDefinitionService.class );
 
         assertEquals( 5, buildDefinitionService.getAllBuildDefinitionTemplate().size() );
@@ -145,17 +145,21 @@
         throws Exception
     {
         BuildDefinitionTemplate template = new BuildDefinitionTemplate();
-        template.setName( "test" );
+        template.setName( "testTemplate" );
 
         template = getBuildDefinitionService().addBuildDefinitionTemplate( template );
         template = getBuildDefinitionService().getBuildDefinitionTemplate( template.getId() );
         assertNotNull( template );
-        assertEquals( "test", template.getName() );
+        assertEquals( "testTemplate", template.getName() );
         List<BuildDefinition> all = getBuildDefinitionService().getAllBuildDefinitions();
         assertEquals( 5, all.size() );
-        BuildDefinition bd = (BuildDefinition) getBuildDefinitionService().getDefaultMavenTwoBuildDefinitionTemplate()
-            .getBuildDefinitions().get( 0 );
+        BuildDefinition bd =
+            (BuildDefinition) getBuildDefinitionService().getDefaultMavenTwoBuildDefinitionTemplate().getBuildDefinitions().get(
+                0 );
         template = getBuildDefinitionService().addBuildDefinitionInTemplate( template, bd, false );
+
+        assertEquals( true, getBuildDefinitionService().isBuildDefinitionInUse( bd ) );
+
         assertEquals( 1, template.getBuildDefinitions().size() );
         all = getBuildDefinitionService().getAllBuildDefinitions();
         assertEquals( 5, all.size() );
@@ -168,4 +172,28 @@
         assertEquals( 5, all.size() );
 
     }
+
+    public void testAddDuplicateBuildDefinitionTemplate()
+        throws Exception
+    {
+        BuildDefinitionTemplate template = new BuildDefinitionTemplate();
+        template.setName( "test" );
+
+        template = getBuildDefinitionService().addBuildDefinitionTemplate( template );
+        assertNull( template );
+    }
+
+    public void testUnusedBuildDefinition()
+        throws Exception
+    {
+        BuildDefinition unused = new BuildDefinition();
+
+        unused.setTemplate( true );
+        unused.setArguments( "-N" );
+        unused.setGoals( "clean test-compile" );
+        unused.setBuildFile( "pom.xml" );
+        unused.setDescription( "desc template" );
+
+        assertFalse( getBuildDefinitionService().isBuildDefinitionInUse( unused ) );
+    }
 }
diff --git a/continuum-core/src/test/java/org/apache/maven/continuum/buildqueue/BuildQueueTest.java b/continuum-core/src/test/java/org/apache/maven/continuum/buildqueue/BuildQueueTest.java
index d5f798f..1c456c8 100644
--- a/continuum-core/src/test/java/org/apache/maven/continuum/buildqueue/BuildQueueTest.java
+++ b/continuum-core/src/test/java/org/apache/maven/continuum/buildqueue/BuildQueueTest.java
@@ -20,8 +20,10 @@
  */
 
 import org.apache.continuum.taskqueue.BuildProjectTask;
+import org.apache.continuum.utils.build.BuildTrigger;
 import org.apache.maven.continuum.AbstractContinuumTest;
 import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.project.ProjectGroup;
 import org.apache.maven.continuum.project.ContinuumProjectState;
 import org.codehaus.plexus.taskqueue.Task;
 import org.codehaus.plexus.taskqueue.TaskQueue;
@@ -131,7 +133,9 @@
     private void buildProject( int projectId, int trigger )
         throws Exception
     {
-        buildQueue.put( new BuildProjectTask( projectId, 0, trigger, null, null ) );
+        ProjectGroup group = getDefaultProjectGroup();
+        buildQueue.put( new BuildProjectTask( projectId, 0, new BuildTrigger( trigger, "" ), null, null, null,
+                                              group.getId() ) );
     }
 
     private void assertNextBuildIs( int expectedProjectId )
diff --git a/continuum-core/src/test/java/org/apache/maven/continuum/core/action/CleanWorkingDirectoryActionTest.java b/continuum-core/src/test/java/org/apache/maven/continuum/core/action/CleanWorkingDirectoryActionTest.java
new file mode 100644
index 0000000..488eae9
--- /dev/null
+++ b/continuum-core/src/test/java/org/apache/maven/continuum/core/action/CleanWorkingDirectoryActionTest.java
@@ -0,0 +1,249 @@
+package org.apache.maven.continuum.core.action;
+
+/*
+ * 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 junit.framework.TestCase;
+import org.apache.commons.io.IOUtils;
+import org.apache.continuum.dao.ProjectDao;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.utils.WorkingDirectoryService;
+import org.codehaus.plexus.util.FileUtils;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.integration.junit3.JUnit3Mockery;
+import org.jmock.lib.legacy.ClassImposteriser;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+
+/**
+ * Tests that the cleanup action works properly. This is a non-portable test, and needs a special setup to run.
+ * Specifically:
+ * * OOME test requires a small heap (-Xmx2m -Xms2m)
+ * * Link traversal tests require a system with "/bin/ln"
+ *
+ * @see org.apache.maven.continuum.core.action.CleanWorkingDirectoryAction
+ */
+public class CleanWorkingDirectoryActionTest
+    extends TestCase
+{
+
+    public static final String FILE_PREFIX = "cwdat";
+
+    private CleanWorkingDirectoryAction action;
+
+    private WorkingDirectoryService mockWorkingDirectoryService;
+
+    private ProjectDao mockProjectDao;
+
+    private Mockery context;
+
+    /**
+     * Builds and returns a directory levels deep with the specified number of directories and files at each level.
+     *
+     * @param root   optional root of the tree, a temporary directory will be created otherwise.
+     * @param levels the depth of directories to build
+     * @param files  the number of files to create in each directory
+     * @param dirs   the number of directories to include in each directory
+     * @return the location of the root of the tree, should be root if it was specified
+     * @throws IOException
+     */
+    private File createFileTree( File root, int levels, int files, int dirs )
+        throws IOException
+    {
+        // Create a root path if one isn't specified
+        root = root == null ? FileUtils.createTempFile( FILE_PREFIX, "", null ) : root;
+
+        // Create the directory at that path
+        if ( !root.mkdir() )
+        {
+            throw new IOException( "Failed to create directory " + root );
+        }
+
+        // Create the files for this directory
+        for ( int i = 0; i < files; i++ )
+        {
+            File newFile = FileUtils.createTempFile( FILE_PREFIX, "", root );
+            FileUtils.fileWrite( newFile.getAbsolutePath(), "" );
+        }
+
+        // Create the directories
+        if ( levels > 1 )
+        {
+            for ( int i = 0; i < dirs; i++ )
+            {
+
+                File newDir = FileUtils.createTempFile( FILE_PREFIX, "", root );
+                createFileTree( newDir, levels - 1, files, dirs );
+            }
+        }
+        return root;
+    }
+
+    public void setUp()
+        throws NoSuchFieldException, IllegalAccessException
+    {
+
+        context = new JUnit3Mockery();
+        context.setImposteriser( ClassImposteriser.INSTANCE );
+
+        // Create mocks
+        mockWorkingDirectoryService = context.mock( WorkingDirectoryService.class );
+        mockProjectDao = context.mock( ProjectDao.class );
+
+        action = new CleanWorkingDirectoryAction();
+
+        // Get the private fields and make them accessible
+        Field wdsField = action.getClass().getDeclaredField( "workingDirectoryService" );
+        Field pdField = action.getClass().getDeclaredField( "projectDao" );
+        for ( Field f : new Field[] { wdsField, pdField } )
+        {
+            f.setAccessible( true );
+        }
+
+        // Inject the mocks as dependencies
+        wdsField.set( action, mockWorkingDirectoryService );
+        pdField.set( action, mockProjectDao );
+    }
+
+    /**
+     * Tests that deleting large directories doesn't result in an OutOfMemoryError.
+     * Reported as CONTINUUM-2199.
+     *
+     * @throws Exception
+     */
+    public void testOutOfMemory()
+        throws Exception
+    {
+        final File deepTree = createFileTree( null, 10, 10, 2 );
+        context.checking( new Expectations()
+        {
+            {
+                Project p = new Project();
+                one( mockProjectDao ).getProject( 0 );
+                will( returnValue( p ) );
+
+                one( mockWorkingDirectoryService ).getWorkingDirectory( p, null, new ArrayList<Project>() );
+                will( returnValue( deepTree ) );
+            }
+        } );
+        action.execute( new HashMap() );
+        assertFalse( String.format( "%s should not exist after deletion", deepTree.getPath() ), deepTree.exists() );
+    }
+
+    private int numFiles( File f )
+    {
+        return f.listFiles().length;
+    }
+
+    /**
+     * Tests that cleanup doesn't traverse across symlinks.
+     */
+    public void testSymlinkTraversal()
+        throws Exception
+    {
+        int size = 10;
+
+        final File tree1 = createFileTree( null, 1, 10, 0 );
+        assertEquals( String.format( "%s should contain %s files", tree1, size ), size, numFiles( tree1 ) );
+
+        final File tree2 = createFileTree( null, 1, 10, 0 );
+        assertEquals( String.format( "%s should contain %s files", tree2, size ), size, numFiles( tree2 ) );
+
+        final File symlink = new File( tree1, "tree2soft" );
+
+        // Create a symbolic link to second tree in first tree
+        String[] symlinkCommand = { "/bin/ln", "-s", tree2.getPath(), symlink.getPath() };
+        Process p1 = Runtime.getRuntime().exec( symlinkCommand );
+
+        if ( p1.waitFor() != 0 )
+        {
+            System.err.println( "Failed to run command " + Arrays.toString( symlinkCommand ) );
+            IOUtils.copy( p1.getInputStream(), System.err );
+        }
+        assertTrue( String.format( "Symbolic link %s should have been created", symlink ), symlink.exists() );
+        assertEquals( size + 1, numFiles( tree1 ) );
+
+        context.checking( new Expectations()
+        {
+            {
+                Project p = new Project();
+                one( mockProjectDao ).getProject( 0 );
+                will( returnValue( p ) );
+
+                one( mockWorkingDirectoryService ).getWorkingDirectory( p, null, new ArrayList<Project>() );
+                will( returnValue( tree1 ) );
+            }
+        } );
+        action.execute( new HashMap() );
+        assertFalse( String.format( "%s should not exist after deletion", tree1.getPath() ), tree1.exists() );
+        assertTrue( String.format( "%s should exist after deletion", tree2 ), tree2.exists() );
+        assertEquals( String.format( "%s should have %s files", tree2, size ), size, numFiles( tree2 ) );
+    }
+
+    /**
+     * Tests that cleanup doesn't traverse across hard links.
+     */
+    public void testHardlinkTraversal()
+        throws Exception
+    {
+        int size = 10;
+
+        final File tree1 = createFileTree( null, 1, 10, 0 );
+        assertEquals( String.format( "%s should contain %s files", tree1, size ), size, numFiles( tree1 ) );
+
+        final File tree2 = createFileTree( null, 1, 10, 0 );
+        assertEquals( String.format( "%s should contain %s files", tree2, size ), size, numFiles( tree2 ) );
+
+        final File hardlink = new File( tree1, "tree2hard" );
+
+        File hardLinkedFile = new File( tree2, tree2.list()[0] ); // Hardlinks can't be to directories
+        String[] hardlinkCommand = { "/bin/ln", hardLinkedFile.getPath(), hardlink.getPath() };
+        Process p2 = Runtime.getRuntime().exec( hardlinkCommand );
+
+        if ( p2.waitFor() != 0 )
+        {
+            System.err.println( "Failed to run command " + Arrays.toString( hardlinkCommand ) );
+            IOUtils.copy( p2.getInputStream(), System.err );
+        }
+        assertTrue( String.format( "Hard link %s should have been created", hardlink ), hardlink.exists() );
+        assertEquals( size + 1, numFiles( tree1 ) );
+
+        context.checking( new Expectations()
+        {
+            {
+                Project p = new Project();
+                one( mockProjectDao ).getProject( 0 );
+                will( returnValue( p ) );
+
+                one( mockWorkingDirectoryService ).getWorkingDirectory( p, null, new ArrayList<Project>() );
+                will( returnValue( tree1 ) );
+            }
+        } );
+        action.execute( new HashMap() );
+        assertFalse( String.format( "%s should not exist after deletion", tree1.getPath() ), tree1.exists() );
+        assertTrue( String.format( "%s should exist after deletion", tree2 ), tree2.exists() );
+        assertEquals( String.format( "%s should have %s files", tree2, size ), size, numFiles( tree2 ) );
+    }
+}
diff --git a/continuum-core/src/test/java/org/apache/maven/continuum/core/action/CreateProjectsFromMetadataTest.java b/continuum-core/src/test/java/org/apache/maven/continuum/core/action/CreateProjectsFromMetadataTest.java
index fca9cd6..77c8581 100644
--- a/continuum-core/src/test/java/org/apache/maven/continuum/core/action/CreateProjectsFromMetadataTest.java
+++ b/continuum-core/src/test/java/org/apache/maven/continuum/core/action/CreateProjectsFromMetadataTest.java
@@ -19,12 +19,10 @@
  * under the License.
  */
 
-import java.util.HashMap;
-import java.util.Map;
-
 import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.BuildDefinitionTemplate;
+import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.project.builder.ContinuumProjectBuilder;
 import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
 import org.apache.maven.continuum.project.builder.manager.ContinuumProjectBuilderManager;
@@ -33,39 +31,54 @@
 import org.apache.maven.settings.Settings;
 import org.codehaus.plexus.logging.Logger;
 import org.codehaus.plexus.logging.console.ConsoleLogger;
+import org.codehaus.plexus.spring.PlexusInSpringTestCase;
 import org.jmock.Mock;
 import org.jmock.MockObjectTestCase;
 
+import java.util.HashMap;
+import java.util.Map;
+
 public class CreateProjectsFromMetadataTest
     extends MockObjectTestCase
 {
 
     private CreateProjectsFromMetadataAction action;
 
-    private Mock projectBuilderManagerMock, projectBuilder, mavenSettingsBuilderMock;
+    private ContinuumProjectBuildingResult result;
 
     protected void setUp()
         throws Exception
     {
+        result = new ContinuumProjectBuildingResult();
         action = new CreateProjectsFromMetadataAction();
         action.enableLogging( new ConsoleLogger( Logger.LEVEL_DEBUG, "" ) );
-        projectBuilderManagerMock = mock( ContinuumProjectBuilderManager.class );
-        mavenSettingsBuilderMock = mock( MavenSettingsBuilder.class );
+
+        recordBuildProjectFromHttp();
+    }
+
+    private void recordBuildProjectFromHttp()
+        throws Exception
+    {
+        result = new ContinuumProjectBuildingResult();
+        Mock projectBuilderManagerMock = mock( ContinuumProjectBuilderManager.class );
+
         action.setProjectBuilderManager( (ContinuumProjectBuilderManager) projectBuilderManagerMock.proxy() );
-        action.setMavenSettingsBuilder( (MavenSettingsBuilder) mavenSettingsBuilderMock.proxy() );
         action.setUrlValidator( new ContinuumUrlValidator() );
-        projectBuilder = mock( ContinuumProjectBuilder.class );
 
-        projectBuilderManagerMock.expects( once() ).method( "getProjectBuilder" )
-            .will( returnValue( projectBuilder.proxy() ) );
-        projectBuilder.expects( once() ).method( "buildProjectsFromMetadata" )
-            .will( returnValue( new ContinuumProjectBuildingResult() ) );
+        Mock projectBuilder = mock( ContinuumProjectBuilder.class );
 
-        projectBuilder.expects( once() ).method( "getDefaultBuildDefinitionTemplate" )
-            .will( returnValue( getDefaultBuildDefinitionTemplate() ) );
+        projectBuilderManagerMock.expects( once() ).method( "getProjectBuilder" ).will( returnValue(
+            projectBuilder.proxy() ) );
+        projectBuilder.expects( once() ).method( "buildProjectsFromMetadata" ).will( returnValue( result ) );
+        projectBuilder.expects( once() ).method( "getDefaultBuildDefinitionTemplate" ).will( returnValue(
+            getDefaultBuildDefinitionTemplate() ) );
+    }
 
+    private void invokeBuildSettings()
+    {
+        Mock mavenSettingsBuilderMock = mock( MavenSettingsBuilder.class );
+        action.setMavenSettingsBuilder( (MavenSettingsBuilder) mavenSettingsBuilderMock.proxy() );
         mavenSettingsBuilderMock.expects( once() ).method( "buildSettings" ).will( returnValue( new Settings() ) );
-        
     }
 
     private BuildDefinitionTemplate getDefaultBuildDefinitionTemplate()
@@ -87,43 +100,156 @@
         bdt.addBuildDefinition( bd );
         return bdt;
     }
-    
-    @SuppressWarnings("unchecked")
+
+    @SuppressWarnings( "unchecked" )
     public void testExecuteWithNonRecursiveMode()
         throws Exception
     {
-        Map context = new HashMap();
-        context.put( CreateProjectsFromMetadataAction.KEY_URL,
-                     "http://svn.apache.org/repos/asf/maven/continuum/trunk/pom.xml" );
-        context.put( CreateProjectsFromMetadataAction.KEY_PROJECT_BUILDER_ID, "id" );
-        context.put( CreateProjectsFromMetadataAction.KEY_LOAD_RECURSIVE_PROJECTS, new Boolean( true ) );
+        invokeBuildSettings();
 
-        
+        Map<String, Object> context = new HashMap<String, Object>();
+        CreateProjectsFromMetadataAction.setUrl( context,
+                                                 "http://svn.apache.org/repos/asf/maven/continuum/trunk/pom.xml" );
+        CreateProjectsFromMetadataAction.setProjectBuilderId( context, "id" );
+        CreateProjectsFromMetadataAction.setLoadRecursiveProject( context, true );
+        context.put( CreateProjectsFromMetadataAction.KEY_CHECKOUT_PROJECTS_IN_SINGLE_DIRECTORY, false );
+
         action.execute( context );
 
-        ContinuumProjectBuildingResult result = (ContinuumProjectBuildingResult) context
-            .get( CreateProjectsFromMetadataAction.KEY_PROJECT_BUILDING_RESULT );
+        ContinuumProjectBuildingResult result = CreateProjectsFromMetadataAction.getProjectBuildingResult( context );
 
-        assertFalse( "Should not have errors but had " + result.getErrorsAsString() +
-            " (this test requires internet access)", result.hasErrors() );
+        assertFalse(
+            "Should not have errors but had " + result.getErrorsAsString() + " (this test requires internet access)",
+            result.hasErrors() );
     }
 
     public void testExecuteWithRecursiveMode()
         throws Exception
     {
-        Map context = new HashMap();
-        context.put( CreateProjectsFromMetadataAction.KEY_URL,
-                     "http://svn.apache.org/repos/asf/maven/archiva/trunk/pom.xml" );
-        context.put( CreateProjectsFromMetadataAction.KEY_PROJECT_BUILDER_ID, "id" );
-        context.put( CreateProjectsFromMetadataAction.KEY_LOAD_RECURSIVE_PROJECTS, new Boolean( false ) );
+        invokeBuildSettings();
+
+        Map<String, Object> context = new HashMap<String, Object>();
+        CreateProjectsFromMetadataAction.setUrl( context,
+                                                 "http://svn.apache.org/repos/asf/maven/archiva/trunk/pom.xml" );
+        CreateProjectsFromMetadataAction.setProjectBuilderId( context, "id" );
+        CreateProjectsFromMetadataAction.setLoadRecursiveProject( context, false );
+        context.put( CreateProjectsFromMetadataAction.KEY_CHECKOUT_PROJECTS_IN_SINGLE_DIRECTORY, false );
 
         action.execute( context );
 
-        ContinuumProjectBuildingResult result = (ContinuumProjectBuildingResult) context
-            .get( CreateProjectsFromMetadataAction.KEY_PROJECT_BUILDING_RESULT );
+        ContinuumProjectBuildingResult result = CreateProjectsFromMetadataAction.getProjectBuildingResult( context );
 
-        assertFalse( "Should not have errors but had " + result.getErrorsAsString() +
-            " (this test requires internet access)", result.hasErrors() );
+        assertFalse(
+            "Should not have errors but had " + result.getErrorsAsString() + " (this test requires internet access)",
+            result.hasErrors() );
     }
 
+
+    public void testExecuteWithCheckoutProjectsInSingleDirectory()
+        throws Exception
+    {
+        Project project = new Project();
+        project.setGroupId( "org.apache.continuum" );
+        project.setArtifactId( "parent-project" );
+        project.setVersion( "1.0-SNAPSHOT" );
+        project.setId( 6 );
+        project.setName( "parent-project" );
+        project.setScmUrl( "scm:local:src/test-projects:flat-multi-module/parent-project" );
+
+        this.result.addProject( project );
+
+        project = new Project();
+        project.setGroupId( "org.apache.continuum" );
+        project.setArtifactId( "module-a" );
+        project.setVersion( "1.0-SNAPSHOT" );
+        project.setId( 7 );
+        project.setName( "module-a" );
+        project.setScmUrl( "scm:local:src/test-projects:flat-multi-module/module-a" );
+
+        this.result.addProject( project );
+
+        project = new Project();
+        project.setGroupId( "org.apache.continuum" );
+        project.setArtifactId( "module-b" );
+        project.setVersion( "1.0-SNAPSHOT" );
+        project.setId( 8 );
+        project.setName( "module-b" );
+        project.setScmUrl( "scm:local:src/test-projects:flat-multi-module/module-b" );
+
+        this.result.addProject( project );
+
+        // assert using scm url set in root!
+        Map<String, Object> context = new HashMap<String, Object>();
+        CreateProjectsFromMetadataAction.setUrl( context, "file://" + PlexusInSpringTestCase.getBasedir() +
+            "/src/test-projects/flat-multi-module/parent-project/pom.xml" );
+        CreateProjectsFromMetadataAction.setProjectBuilderId( context, "id" );
+        CreateProjectsFromMetadataAction.setLoadRecursiveProject( context, true );
+        context.put( CreateProjectsFromMetadataAction.KEY_CHECKOUT_PROJECTS_IN_SINGLE_DIRECTORY, true );
+
+        action.execute( context );
+
+        ContinuumProjectBuildingResult result = CreateProjectsFromMetadataAction.getProjectBuildingResult( context );
+
+        assertFalse(
+            "Should not have errors but had " + result.getErrorsAsString() + " (this test requires internet access)",
+            result.hasErrors() );
+        assertEquals( "Incorrect SCM Root Url for flat multi-module project.",
+                      "scm:local:src/test-projects:flat-multi-module/", AbstractContinuumAction.getProjectScmRootUrl(
+            context, "" ) );
+    }
+
+    public void testExecuteFlatMultiModuleProjectThatStartsWithTheSameLetter()
+        throws Exception
+    {
+        invokeBuildSettings();
+
+        Project project = new Project();
+        project.setGroupId( "com.example.flat" );
+        project.setArtifactId( "flat-parent" );
+        project.setVersion( "1.0-SNAPSHOT" );
+        project.setId( 6 );
+        project.setName( "Flat Example" );
+        project.setScmUrl( "scm:svn:http://svn.apache.org/repos/asf/continuum/sandbox/flat-example/flat-parent" );
+
+        this.result.addProject( project );
+
+        project = new Project();
+        project.setGroupId( "com.example.flat" );
+        project.setArtifactId( "flat-core" );
+        project.setVersion( "1.0-SNAPSHOT" );
+        project.setId( 7 );
+        project.setName( "flat-core" );
+        project.setScmUrl( "scm:svn:http://svn.apache.org/repos/asf/continuum/sandbox/flat-example/flat-core" );
+
+        this.result.addProject( project );
+
+        project = new Project();
+        project.setGroupId( "com.example.flat" );
+        project.setArtifactId( "flat-webapp" );
+        project.setVersion( "1.0-SNAPSHOT" );
+        project.setId( 8 );
+        project.setName( "flat-webapp Maven Webapp" );
+        project.setScmUrl( "scm:svn:http://svn.apache.org/repos/asf/continuum/sandbox/flat-example/flat-webapp" );
+
+        this.result.addProject( project );
+
+        Map<String, Object> context = new HashMap<String, Object>();
+        CreateProjectsFromMetadataAction.setUrl( context,
+                                                 "http://svn.apache.org/repos/asf/continuum/sandbox/flat-example/flat-parent/pom.xml" );
+        CreateProjectsFromMetadataAction.setProjectBuilderId( context, "id" );
+        CreateProjectsFromMetadataAction.setLoadRecursiveProject( context, true );
+        context.put( CreateProjectsFromMetadataAction.KEY_CHECKOUT_PROJECTS_IN_SINGLE_DIRECTORY, false );
+
+        action.execute( context );
+
+        ContinuumProjectBuildingResult result = CreateProjectsFromMetadataAction.getProjectBuildingResult( context );
+
+        assertFalse(
+            "Should not have errors but had " + result.getErrorsAsString() + " (this test requires internet access)",
+            result.hasErrors() );
+
+        assertEquals( "Wrong scm root url created",
+                      "scm:svn:http://svn.apache.org/repos/asf/continuum/sandbox/flat-example/",
+                      AbstractContinuumAction.getProjectScmRootUrl( context, null ) );
+    }
 }
diff --git a/continuum-core/src/test/java/org/apache/maven/continuum/execution/ContinuumBuildExecutorTest.java b/continuum-core/src/test/java/org/apache/maven/continuum/execution/ContinuumBuildExecutorTest.java
index 3feaf5b..3fca7e2 100644
--- a/continuum-core/src/test/java/org/apache/maven/continuum/execution/ContinuumBuildExecutorTest.java
+++ b/continuum-core/src/test/java/org/apache/maven/continuum/execution/ContinuumBuildExecutorTest.java
@@ -19,12 +19,7 @@
  * under the License.
  */
 
-import java.io.File;
-import java.util.HashMap;
-import java.util.Map;
-
 import junit.framework.TestCase;
-
 import org.apache.continuum.utils.shell.ExecutionResult;
 import org.apache.continuum.utils.shell.ShellCommandHelper;
 import org.apache.maven.continuum.configuration.ConfigurationService;
@@ -32,18 +27,22 @@
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.project.ProjectGroup;
+import org.apache.maven.continuum.model.scm.ScmResult;
 import org.apache.maven.continuum.utils.ChrootJailWorkingDirectoryService;
-import org.codehaus.plexus.logging.Logger;
-import org.codehaus.plexus.logging.console.ConsoleLogger;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 
+import java.io.File;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 public class ContinuumBuildExecutorTest
     extends TestCase
 {
-    protected AbstractBuildExecutor executor = new BuildExecutorStub();
+    protected final AbstractBuildExecutor executor = new BuildExecutorStub();
 
-    private Mockery context = new Mockery();
+    private final Mockery context = new Mockery();
 
     private String toSystemPath( String path )
     {
@@ -88,8 +87,9 @@
         projectGroup.setGroupId( project.getGroupId() );
         project.setProjectGroup( projectGroup );
 
-        assertEquals( toSystemPath( chrootJailFile.getPath() + "/" + project.getGroupId() + workingDirectory.getPath() +
-            "/" + project.getId() ), directoryService.getWorkingDirectory( project ).getPath() );
+        assertEquals( toSystemPath(
+            chrootJailFile.getPath() + "/" + project.getGroupId() + workingDirectory.getPath() + "/" +
+                project.getId() ), directoryService.getWorkingDirectory( project ).getPath() );
 
         String executable = "mvn";
         final String arguments = "-o clean install";
@@ -105,13 +105,13 @@
         context.checking( new Expectations()
         {
             {
-                one( helper ).executeShellCommand( chrootJailFile, "sudo", toSystemPath( cmd ), output,
-                                                   project.getId(), environments );
+                one( helper ).executeShellCommand( chrootJailFile, "sudo", toSystemPath( cmd ), output, project.getId(),
+                                                   environments );
                 will( returnValue( result ) );
             }
         } );
 
-        executor.executeShellCommand( project, executable, arguments, output, environments );
+        executor.executeShellCommand( project, executable, arguments, output, environments, null, null );
 
         context.assertIsSatisfied();
     }
@@ -125,8 +125,8 @@
             super( "stub", true );
         }
 
-        protected String findExecutable( Project project, String executable, String defaultExecutable,
-                                         boolean resolveExecutable, File workingDirectory )
+        protected String findExecutable( String executable, String defaultExecutable, boolean resolveExecutable,
+                                         File workingDirectory )
         {
             return executable;
         }
@@ -138,14 +138,16 @@
             return null;
         }
 
-        public ContinuumBuildExecutionResult build( Project project, BuildDefinition buildDefinition, File buildOutput )
+        public ContinuumBuildExecutionResult build( Project project, BuildDefinition buildDefinition, File buildOutput,
+                                                    List<Project> projectsWithCommonScmRoot, String projectScmRootUrl )
             throws ContinuumBuildExecutorException
         {
             // TODO Auto-generated method stub
             return null;
         }
 
-        public void updateProjectFromCheckOut( File workingDirectory, Project project, BuildDefinition buildDefinition )
+        public void updateProjectFromCheckOut( File workingDirectory, Project project, BuildDefinition buildDefinition,
+                                               ScmResult scmResult )
             throws ContinuumBuildExecutorException
         {
             // TODO Auto-generated method stub
diff --git a/continuum-core/src/test/java/org/apache/maven/continuum/execution/manager/DefaultBuildExecutorManagerTest.java b/continuum-core/src/test/java/org/apache/maven/continuum/execution/manager/DefaultBuildExecutorManagerTest.java
index 157b5c7..f8eba94 100644
--- a/continuum-core/src/test/java/org/apache/maven/continuum/execution/manager/DefaultBuildExecutorManagerTest.java
+++ b/continuum-core/src/test/java/org/apache/maven/continuum/execution/manager/DefaultBuildExecutorManagerTest.java
@@ -46,8 +46,8 @@
     public void testMavenTwoBuildExecutorDependencyInjection()
         throws Exception
     {
-        MavenTwoBuildExecutor executor =
-            (MavenTwoBuildExecutor) builderManager.getBuildExecutor( MavenTwoBuildExecutor.ID );
+        MavenTwoBuildExecutor executor = (MavenTwoBuildExecutor) builderManager.getBuildExecutor(
+            MavenTwoBuildExecutor.ID );
 
         assertCommonFields( executor );
         assertNotNull( executor.getBuilderHelper() );
@@ -58,8 +58,8 @@
     public void testMavenOneBuildExecutorDependencyInjection()
         throws Exception
     {
-        MavenOneBuildExecutor executor =
-            (MavenOneBuildExecutor) builderManager.getBuildExecutor( MavenOneBuildExecutor.ID );
+        MavenOneBuildExecutor executor = (MavenOneBuildExecutor) builderManager.getBuildExecutor(
+            MavenOneBuildExecutor.ID );
 
         assertCommonFields( executor );
         assertNotNull( executor.getMetadataHelper() );
diff --git a/continuum-core/src/test/java/org/apache/maven/continuum/execution/maven/m1/MavenOneBuildExecutorTest.java b/continuum-core/src/test/java/org/apache/maven/continuum/execution/maven/m1/MavenOneBuildExecutorTest.java
index b5a5c27..c2b19cf 100644
--- a/continuum-core/src/test/java/org/apache/maven/continuum/execution/maven/m1/MavenOneBuildExecutorTest.java
+++ b/continuum-core/src/test/java/org/apache/maven/continuum/execution/maven/m1/MavenOneBuildExecutorTest.java
@@ -94,7 +94,7 @@
 
         notifier.setFrom( ProjectNotifier.FROM_USER );
 
-        List notifiers = new ArrayList();
+        List<ProjectNotifier> notifiers = new ArrayList<ProjectNotifier>();
 
         notifiers.add( notifier );
 
@@ -106,7 +106,7 @@
         //
         // ----------------------------------------------------------------------
 
-        executor.updateProjectFromCheckOut( checkOut, project, null );
+        executor.updateProjectFromCheckOut( checkOut, project, null, null );
 
         // ----------------------------------------------------------------------
         //
@@ -151,7 +151,7 @@
         //
         // ----------------------------------------------------------------------
 
-        executor.updateProjectFromCheckOut( checkOut, project, null );
+        executor.updateProjectFromCheckOut( checkOut, project, null, null );
 
         // ----------------------------------------------------------------------
         //
@@ -171,7 +171,7 @@
         // Updating a new time to prevent duplicated notifiers
         // ----------------------------------------------------------------------
 
-        executor.updateProjectFromCheckOut( checkOut, project, null );
+        executor.updateProjectFromCheckOut( checkOut, project, null, null );
 
         // ----------------------------------------------------------------------
         //
@@ -214,7 +214,7 @@
 
         notifier.setFrom( ProjectNotifier.FROM_USER );
 
-        List notifiers = new ArrayList();
+        List<ProjectNotifier> notifiers = new ArrayList<ProjectNotifier>();
 
         notifiers.add( notifier );
 
@@ -226,7 +226,7 @@
         //
         // ----------------------------------------------------------------------
 
-        executor.updateProjectFromCheckOut( checkOut, project, null );
+        executor.updateProjectFromCheckOut( checkOut, project, null, null );
 
         // ----------------------------------------------------------------------
         //
@@ -250,7 +250,7 @@
         // Updating a new time to prevent duplicated notifiers
         // ----------------------------------------------------------------------
 
-        executor.updateProjectFromCheckOut( checkOut, project, null );
+        executor.updateProjectFromCheckOut( checkOut, project, null, null );
 
         // ----------------------------------------------------------------------
         //
@@ -296,7 +296,7 @@
 
         notifier.setFrom( ProjectNotifier.FROM_USER );
 
-        List notifiers = new ArrayList();
+        List<ProjectNotifier> notifiers = new ArrayList<ProjectNotifier>();
 
         notifiers.add( notifier );
 
@@ -308,7 +308,7 @@
         //
         // ----------------------------------------------------------------------
 
-        executor.updateProjectFromCheckOut( checkOut, project, null );
+        executor.updateProjectFromCheckOut( checkOut, project, null, null );
 
         // ----------------------------------------------------------------------
         //
@@ -328,7 +328,7 @@
         // Updating a new time to prevent duplicated notifiers
         // ----------------------------------------------------------------------
 
-        executor.updateProjectFromCheckOut( checkOut, project, null );
+        executor.updateProjectFromCheckOut( checkOut, project, null, null );
 
         // ----------------------------------------------------------------------
         //
diff --git a/continuum-core/src/test/java/org/apache/maven/continuum/execution/maven/m2/MavenTwoBuildExecutorTest.java b/continuum-core/src/test/java/org/apache/maven/continuum/execution/maven/m2/MavenTwoBuildExecutorTest.java
index 6b4b8b3..e60b25b 100755
--- a/continuum-core/src/test/java/org/apache/maven/continuum/execution/maven/m2/MavenTwoBuildExecutorTest.java
+++ b/continuum-core/src/test/java/org/apache/maven/continuum/execution/maven/m2/MavenTwoBuildExecutorTest.java
@@ -19,10 +19,6 @@
  * under the License.
  */
 
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
 import org.apache.maven.continuum.AbstractContinuumTest;
 import org.apache.maven.continuum.execution.ContinuumBuildExecutor;
 import org.apache.maven.continuum.model.project.BuildDefinition;
@@ -30,16 +26,20 @@
 import org.apache.maven.continuum.model.scm.ChangeFile;
 import org.apache.maven.continuum.model.scm.ChangeSet;
 
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * @author olamy
- * @since 1.2.3
  * @version $Id$
+ * @since 1.2.3
  */
 public class MavenTwoBuildExecutorTest
     extends AbstractContinuumTest
 {
-       
-    
+
+
     @Override
     protected String getSpringConfigLocation()
     {
@@ -52,15 +52,16 @@
         MavenTwoBuildExecutor executor = (MavenTwoBuildExecutor) lookup( ContinuumBuildExecutor.class, "maven2" );
         BuildDefinition buildDefinition = new BuildDefinition();
         buildDefinition.setArguments( "-N" );
-        Project continuumProject = new Project(){
+        Project continuumProject = new Project()
+        {
             {
                 setVersion( "1.0.3" );
             }
         };
-        assertFalse( executor.shouldBuild( new ArrayList<ChangeSet>(), continuumProject, new File( "target/test-classes/projects/continuum" ),
-                                           buildDefinition ) );
+        assertFalse( executor.shouldBuild( new ArrayList<ChangeSet>(), continuumProject, new File(
+            "target/test-classes/projects/continuum" ), buildDefinition ) );
     }
-    
+
     public void testShouldNotBuildNonRecursiveChangeInAModule()
         throws Exception
     {
@@ -74,7 +75,7 @@
             }
         };
         final ChangeFile changeFile = new ChangeFile();
-        changeFile.setName( "continuum-notifiers/pom.xml");
+        changeFile.setName( "continuum-notifiers/pom.xml" );
         ChangeSet changeSet = new ChangeSet()
         {
             {
@@ -83,10 +84,10 @@
         };
         List<ChangeSet> changeSets = new ArrayList<ChangeSet>();
         changeSets.add( changeSet );
-        assertFalse( executor.shouldBuild(changeSets , continuumProject,
-                                           new File( "target/test-classes/projects/continuum" ), buildDefinition ) );
-    }    
-    
+        assertFalse( executor.shouldBuild( changeSets, continuumProject, new File(
+            "target/test-classes/projects/continuum" ), buildDefinition ) );
+    }
+
     public void testShouldBuildRecursiveChangeInAModule()
         throws Exception
     {
@@ -109,7 +110,7 @@
         };
         List<ChangeSet> changeSets = new ArrayList<ChangeSet>();
         changeSets.add( changeSet );
-        assertTrue( executor.shouldBuild( changeSets, continuumProject,
-                                          new File( "target/test-classes/projects/continuum" ), buildDefinition ) );
-    }       
+        assertTrue( executor.shouldBuild( changeSets, continuumProject, new File(
+            "target/test-classes/projects/continuum" ), buildDefinition ) );
+    }
 }
diff --git a/continuum-core/src/test/java/org/apache/maven/continuum/execution/maven/m2/TestMavenBuilderHelper.java b/continuum-core/src/test/java/org/apache/maven/continuum/execution/maven/m2/TestMavenBuilderHelper.java
index 6b009b4..25e1bb4 100755
--- a/continuum-core/src/test/java/org/apache/maven/continuum/execution/maven/m2/TestMavenBuilderHelper.java
+++ b/continuum-core/src/test/java/org/apache/maven/continuum/execution/maven/m2/TestMavenBuilderHelper.java
@@ -1,3 +1,5 @@
+package org.apache.maven.continuum.execution.maven.m2;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,9 +18,6 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.continuum.execution.maven.m2;
-
-import java.io.File;
 
 import org.apache.maven.continuum.AbstractContinuumTest;
 import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
@@ -27,16 +26,17 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.File;
+
 /**
  * @author <a href="mailto:olamy@apache.org">olamy</a>
- * @since 6 juin 2008
  * @version $Id$
+ * @since 6 juin 2008
  */
 public class TestMavenBuilderHelper
     extends AbstractContinuumTest
 {
-    
-    private Logger log = LoggerFactory.getLogger( getClass() );
+    private static final Logger log = LoggerFactory.getLogger( TestMavenBuilderHelper.class );
 
     public void testgetMavenProject()
         throws Exception
@@ -49,11 +49,12 @@
 
         assertEquals( "plexus", project.getGroupId() );
         assertEquals( "continuum-project2", project.getArtifactId() );
+        assertEquals( "This is a sample pom for test purposes", project.getDescription() );
         assertNotNull( project.getScm() );
         assertTrue( project.getDependencies().isEmpty() );
         assertTrue( result.getErrors().isEmpty() );
     }
-    
+
     public void testgetMavenProjectMissingDeps()
         throws Exception
     {
@@ -67,7 +68,5 @@
         log.info( "errorAsString " + errorsAsString );
         assertTrue( errorsAsString.contains( "ghd:non-exists:pom:2.6.267676-beta-754-alpha-95" ) );
         log.info( "errors " + result.getErrors() );
-
-    }    
-    
+    }
 }
diff --git a/continuum-core/src/test/java/org/apache/maven/continuum/initialization/DefaultContinuumInitializerTest.java b/continuum-core/src/test/java/org/apache/maven/continuum/initialization/DefaultContinuumInitializerTest.java
index 53ad029..5b8741b 100644
--- a/continuum-core/src/test/java/org/apache/maven/continuum/initialization/DefaultContinuumInitializerTest.java
+++ b/continuum-core/src/test/java/org/apache/maven/continuum/initialization/DefaultContinuumInitializerTest.java
@@ -38,8 +38,8 @@
         super.setUp();
         DaoUtils daoUtils = (DaoUtils) lookup( DaoUtils.class.getName() );
         daoUtils.eraseDatabase();
-        ContinuumInitializer continuumInitializer =
-            (ContinuumInitializer) lookup( ContinuumInitializer.ROLE, "default" );
+        ContinuumInitializer continuumInitializer = (ContinuumInitializer) lookup( ContinuumInitializer.ROLE,
+                                                                                   "default" );
         continuumInitializer.initialize();
     }
 
diff --git a/continuum-core/src/test/java/org/apache/maven/continuum/notification/ContinuumNotificationDispatcherTest.java b/continuum-core/src/test/java/org/apache/maven/continuum/notification/ContinuumNotificationDispatcherTest.java
index ee99c04..a36aeb7 100644
--- a/continuum-core/src/test/java/org/apache/maven/continuum/notification/ContinuumNotificationDispatcherTest.java
+++ b/continuum-core/src/test/java/org/apache/maven/continuum/notification/ContinuumNotificationDispatcherTest.java
@@ -45,8 +45,8 @@
     public void testNotificationDispatcher()
         throws Exception
     {
-        ContinuumNotificationDispatcher notificationDispatcher =
-            (ContinuumNotificationDispatcher) lookup( ContinuumNotificationDispatcher.ROLE );
+        ContinuumNotificationDispatcher notificationDispatcher = (ContinuumNotificationDispatcher) lookup(
+            ContinuumNotificationDispatcher.ROLE );
 
         Project project = addProject( "Notification Dispatcher Test Project" );
 
diff --git a/continuum-core/src/test/java/org/apache/maven/continuum/notification/mail/MailContinuumNotifierTest.java b/continuum-core/src/test/java/org/apache/maven/continuum/notification/mail/MailContinuumNotifierTest.java
index d8a2608..373c38f 100644
--- a/continuum-core/src/test/java/org/apache/maven/continuum/notification/mail/MailContinuumNotifierTest.java
+++ b/continuum-core/src/test/java/org/apache/maven/continuum/notification/mail/MailContinuumNotifierTest.java
@@ -19,18 +19,11 @@
  * under the License.
  */
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.mail.Address;
-import javax.mail.internet.InternetAddress;
-import javax.mail.internet.MimeMessage;
-import javax.mail.internet.MimeMessage.RecipientType;
-
+import org.apache.continuum.dao.BuildDefinitionDao;
+import org.apache.continuum.dao.BuildResultDao;
 import org.apache.continuum.notification.mail.MockJavaMailSender;
 import org.apache.maven.continuum.AbstractContinuumTest;
+import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.BuildResult;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.project.ProjectGroup;
@@ -43,6 +36,15 @@
 import org.slf4j.LoggerFactory;
 import org.springframework.mail.javamail.JavaMailSender;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.mail.Address;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMessage.RecipientType;
+
 /**
  * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
  * @version $Id$
@@ -50,9 +52,8 @@
 public class MailContinuumNotifierTest
     extends AbstractContinuumTest
 {
-    
-    protected Logger logger = LoggerFactory.getLogger( getClass() );
-    
+    protected static final Logger logger = LoggerFactory.getLogger( MailContinuumNotifierTest.class );
+
     public void testSuccessfulBuild()
         throws Exception
     {
@@ -62,15 +63,46 @@
 
         ProjectGroup group = createStubProjectGroup( "foo.bar", "" );
 
+        BuildResultDao brDao = (BuildResultDao) lookup( BuildResultDao.class );
         Project project = addProject( "Test Project", group );
+        BuildResult br = makeBuild( ContinuumProjectState.FAILED );
+        brDao.addBuildResult( project, br );
+
+        br = makeBuild( ContinuumProjectState.OK );
+        brDao.addBuildResult( project, br );
+
+        br = makeBuild( ContinuumProjectState.FAILED );
+        brDao.addBuildResult( project, br );
 
         BuildResult build = makeBuild( ContinuumProjectState.OK );
+        assertEquals( ContinuumProjectState.OK, build.getState() );
 
-        MimeMessage mailMessage = sendNotificationAndGetMessage( project, build, "lots out build output", toOverride );
+        project.setState( build.getState() );
+        getProjectDao().updateProject( project );
+
+        BuildDefinition buildDef = new BuildDefinition();
+        buildDef.setType( "maven2" );
+        buildDef.setBuildFile( "pom.xml" );
+        buildDef.setGoals( "clean install" );
+        buildDef.setArguments( "" );
+        BuildDefinitionDao buildDefDao = (BuildDefinitionDao) lookup( BuildDefinitionDao.class );
+        buildDef = buildDefDao.addBuildDefinition( buildDef );
+        build.setBuildDefinition( buildDef );
+        assertEquals( ContinuumProjectState.OK, build.getState() );
+
+        brDao.addBuildResult( project, build );
+        build = brDao.getLatestBuildResultForProjectWithDetails( project.getId() );
+        assertEquals( ContinuumProjectState.OK, build.getState() );
+
+        MimeMessage mailMessage = sendNotificationAndGetMessage( project, build, buildDef, "lots out build output",
+                                                                 toOverride );
 
         assertEquals( "[continuum] BUILD SUCCESSFUL: foo.bar Test Project", mailMessage.getSubject() );
 
-        dumpContent( mailMessage, "recipient@host.com" );
+        String mailContent = dumpContent( mailMessage, "recipient@host.com" );
+
+        //CONTINUUM-1946
+        assertTrue( mailContent.indexOf( "Goals: clean install" ) > 0 );
     }
 
     public void testFailedBuild()
@@ -82,7 +114,7 @@
 
         BuildResult build = makeBuild( ContinuumProjectState.FAILED );
 
-        MimeMessage mailMessage = sendNotificationAndGetMessage( project, build, "output", null );
+        MimeMessage mailMessage = sendNotificationAndGetMessage( project, build, null, "output", null );
 
         assertEquals( "[continuum] BUILD FAILURE: foo.bar Test Project", mailMessage.getSubject() );
 
@@ -100,47 +132,49 @@
 
         build.setError( "Big long error message" );
 
-        MimeMessage mailMessage = sendNotificationAndGetMessage( project, build, "lots of stack traces", null );
+        MimeMessage mailMessage = sendNotificationAndGetMessage( project, build, null, "lots of stack traces", null );
 
         assertEquals( "[continuum] BUILD ERROR: foo.bar Test Project", mailMessage.getSubject() );
 
         dumpContent( mailMessage );
     }
 
-    private void dumpContent( MimeMessage mailMessage )
+    private String dumpContent( MimeMessage mailMessage )
         throws Exception
     {
-        dumpContent( mailMessage, null );
+        return dumpContent( mailMessage, null );
     }
 
-    private void dumpContent( MimeMessage mailMessage, String toOverride )
+    private String dumpContent( MimeMessage mailMessage, String toOverride )
         throws Exception
     {
-        Address[] tos  = mailMessage.getRecipients( RecipientType.TO );
+        Address[] tos = mailMessage.getRecipients( RecipientType.TO );
         if ( toOverride != null )
         {
-            assertEquals( toOverride, ( (InternetAddress) tos[ 0 ] ).getAddress() );
+            assertEquals( toOverride, ( (InternetAddress) tos[0] ).getAddress() );
         }
         else
         {
-            assertEquals( "foo@bar", ( (InternetAddress) tos[ 0 ] ).getAddress() );
+            assertEquals( "foo@bar", ( (InternetAddress) tos[0] ).getAddress() );
         }
-        assertTrue( "The template isn't loaded correctly.",
-                    ((String)mailMessage.getContent()).indexOf( "#shellBuildResult()" ) < 0 );
-        assertTrue( "The template isn't loaded correctly.",
-                    ((String)mailMessage.getContent()).indexOf( "Build statistics" ) > 0 );
+        assertTrue( "The template isn't loaded correctly.", ( (String) mailMessage.getContent() ).indexOf(
+            "#shellBuildResult()" ) < 0 );
+        assertTrue( "The template isn't loaded correctly.", ( (String) mailMessage.getContent() ).indexOf(
+            "Build statistics" ) > 0 );
 
-        if ( true )
-        {
-            logger.info( ((String)mailMessage.getContent()) );
-        }
+        String mailContent = (String) mailMessage.getContent();
+
+        logger.info( mailContent );
+
+        return mailContent;
     }
 
     // ----------------------------------------------------------------------
     //
     // ----------------------------------------------------------------------
 
-    private MimeMessage sendNotificationAndGetMessage( Project project, BuildResult build, String buildOutput, String toOverride )
+    private MimeMessage sendNotificationAndGetMessage( Project project, BuildResult build, BuildDefinition buildDef,
+                                                       String buildOutput, String toOverride )
         throws Exception
     {
         MessageContext context = new MessageContext();
@@ -149,6 +183,8 @@
 
         context.setBuildResult( build );
 
+        context.setBuildDefinition( buildDef );
+
         ProjectNotifier projectNotifier = new ProjectNotifier();
         projectNotifier.setType( "mail" );
         Map<String, String> config = new HashMap<String, String>();
@@ -182,21 +218,21 @@
 
         List<MimeMessage> mails = mailSender.getReceivedEmails();
 
-        MimeMessage mailMessage = (MimeMessage) mails.get( 0 );
+        MimeMessage mailMessage = mails.get( 0 );
 
         // ----------------------------------------------------------------------
         //
         // ----------------------------------------------------------------------
 
-        assertEquals( "continuum@localhost", ((InternetAddress) mailMessage.getFrom()[0]).getAddress() );
+        assertEquals( "continuum@localhost", ( (InternetAddress) mailMessage.getFrom()[0] ).getAddress() );
 
-        assertEquals( "Continuum", ((InternetAddress) mailMessage.getFrom()[0]).getPersonal() );
+        assertEquals( "Continuum", ( (InternetAddress) mailMessage.getFrom()[0] ).getPersonal() );
 
-        Address[] tos  = mailMessage.getRecipients( RecipientType.TO );
+        Address[] tos = mailMessage.getRecipients( RecipientType.TO );
 
         assertEquals( 1, tos.length );
 
-        assertEquals(toOverride == null ? "foo@bar" : toOverride, ( (InternetAddress) tos[0] ).getAddress() );
+        assertEquals( toOverride == null ? "foo@bar" : toOverride, ( (InternetAddress) tos[0] ).getAddress() );
 
         return mailMessage;
     }
@@ -205,8 +241,6 @@
     {
         BuildResult build = new BuildResult();
 
-        build.setId( 17 );
-
         build.setStartTime( System.currentTimeMillis() );
 
         build.setEndTime( System.currentTimeMillis() + 1234567 );
diff --git a/continuum-core/src/test/java/org/apache/maven/continuum/project/builder/AbstractContinuumProjectBuilderTest.java b/continuum-core/src/test/java/org/apache/maven/continuum/project/builder/AbstractContinuumProjectBuilderTest.java
index eb56cef..2c815f5 100644
--- a/continuum-core/src/test/java/org/apache/maven/continuum/project/builder/AbstractContinuumProjectBuilderTest.java
+++ b/continuum-core/src/test/java/org/apache/maven/continuum/project/builder/AbstractContinuumProjectBuilderTest.java
@@ -19,13 +19,10 @@
  * under the License.
  */
 
-import java.net.URL;
-
 import junit.framework.TestCase;
-
 import org.apache.maven.continuum.model.project.BuildDefinitionTemplate;
-import org.codehaus.plexus.logging.Logger;
-import org.codehaus.plexus.logging.console.ConsoleLogger;
+
+import java.net.URL;
 
 /**
  * Test for {@link AbstractContinuumProjectBuilder}
@@ -44,7 +41,6 @@
     {
         super.setUp();
         builder = new ContinuumProjectBuilder();
-        //builder.enableLogging( new ConsoleLogger( Logger.LEVEL_DEBUG, "" ) );
     }
 
     /**
@@ -72,7 +68,8 @@
         }
 
         public ContinuumProjectBuildingResult buildProjectsFromMetadata( URL url, String username, String password,
-                                                                         boolean recursiveProjects )
+                                                                         boolean recursiveProjects,
+                                                                         boolean checkoutInSingleDirectory )
             throws ContinuumProjectBuilderException
         {
             return null;
@@ -80,13 +77,24 @@
 
         public ContinuumProjectBuildingResult buildProjectsFromMetadata( URL url, String username, String password,
                                                                          boolean recursiveProjects,
-                                                                         BuildDefinitionTemplate buildDefinitionTemplate )
+                                                                         BuildDefinitionTemplate buildDefinitionTemplate,
+                                                                         boolean checkoutInSingleDirectory )
             throws ContinuumProjectBuilderException
         {
             return null;
         }
 
-        public BuildDefinitionTemplate  getDefaultBuildDefinitionTemplate()
+        public ContinuumProjectBuildingResult buildProjectsFromMetadata( URL url, String username, String password,
+                                                                         boolean recursiveProjects,
+                                                                         BuildDefinitionTemplate buildDefinitionTemplate,
+                                                                         boolean checkoutInSingleDirectory,
+                                                                         int projectGroupId )
+            throws ContinuumProjectBuilderException
+        {
+            return null;
+        }
+
+        public BuildDefinitionTemplate getDefaultBuildDefinitionTemplate()
             throws ContinuumProjectBuilderException
         {
             return null;
diff --git a/continuum-core/src/test/java/org/apache/maven/continuum/project/builder/maven/MavenOneContinuumProjectBuilderTest.java b/continuum-core/src/test/java/org/apache/maven/continuum/project/builder/maven/MavenOneContinuumProjectBuilderTest.java
index 191e474..038c1b4 100644
--- a/continuum-core/src/test/java/org/apache/maven/continuum/project/builder/maven/MavenOneContinuumProjectBuilderTest.java
+++ b/continuum-core/src/test/java/org/apache/maven/continuum/project/builder/maven/MavenOneContinuumProjectBuilderTest.java
@@ -29,8 +29,6 @@
 import org.apache.maven.continuum.project.builder.ContinuumProjectBuilder;
 import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
 
-import java.util.Iterator;
-
 /**
  * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
  * @version $Id$
@@ -41,10 +39,9 @@
     public void testBuildingAProjectFromMetadataWithACompleteMaven1Pom()
         throws Exception
     {
-        ContinuumProjectBuilder projectBuilder =
-            (ContinuumProjectBuilder) lookup( ContinuumProjectBuilder.ROLE, MavenOneContinuumProjectBuilder.ID );
+        ContinuumProjectBuilder projectBuilder = (ContinuumProjectBuilder) lookup( ContinuumProjectBuilder.ROLE,
+                                                                                   MavenOneContinuumProjectBuilder.ID );
 
-        
         BuildDefinition bd = new BuildDefinition();
 
         bd.setDefaultForProject( true );
@@ -54,26 +51,24 @@
         bd.setBuildFile( "project.xml" );
 
         bd.setType( ContinuumBuildExecutorConstants.MAVEN_ONE_BUILD_EXECUTOR );
-        
+
         bd.setTemplate( true );
-        
+
         BuildDefinitionService service = (BuildDefinitionService) lookup( BuildDefinitionService.class );
-        
+
         BuildDefinitionTemplate bdt = new BuildDefinitionTemplate();
         bdt.setName( "maven1" );
         bd = service.addBuildDefinition( bd );
         bdt = service.addBuildDefinitionTemplate( bdt );
         bdt = service.addBuildDefinitionInTemplate( bdt, bd, false );
-        
-        ContinuumProjectBuildingResult result = projectBuilder
-            .buildProjectsFromMetadata( getTestFile( "src/test/resources/projects/maven-1.pom.xml" ).toURL(), null,
-                                        null, false, bdt );
 
+        ContinuumProjectBuildingResult result = projectBuilder.buildProjectsFromMetadata( getTestFile(
+            "src/test/resources/projects/maven-1.pom.xml" ).toURL(), null, null, false, bdt, false );
 
         assertOnResult( result );
-        
+
     }
-    
+
     public void testBuildingAProjectFromMetadataWithACompleteMaven1PomWithDefaultBuildDef()
         throws Exception
     {
@@ -82,37 +77,38 @@
 
         BuildDefinitionService service = (BuildDefinitionService) lookup( BuildDefinitionService.class );
 
-        ContinuumProjectBuildingResult result = projectBuilder
-            .buildProjectsFromMetadata( getTestFile( "src/test/resources/projects/maven-1.pom.xml" ).toURL(), null,
-                                        null, false, service.getDefaultMavenOneBuildDefinitionTemplate() );
+        ContinuumProjectBuildingResult result = projectBuilder.buildProjectsFromMetadata( getTestFile(
+            "src/test/resources/projects/maven-1.pom.xml" ).toURL(), null, null, false,
+                                                                                          service.getDefaultMavenOneBuildDefinitionTemplate(),
+                                                                                          false );
 
         assertOnResult( result );
 
-    }    
-    
+    }
+
     protected void assertOnResult( ContinuumProjectBuildingResult result )
     {
-        assertNotNull( result.getWarnings() );
+        assertNotNull( result.getErrors() );
 
         assertNotNull( result.getProjects() );
 
-        for ( Iterator it = result.getWarnings().iterator(); it.hasNext(); )
+        for ( String error : result.getErrors() )
         {
-            String s = (String) it.next();
-
-            System.err.println( s );
+            System.err.println( error );
         }
 
-        assertEquals( "result.warning.length", 0, result.getWarnings().size() );
+        assertEquals( "result.warning.length", 0, result.getErrors().size() );
 
         assertEquals( "result.projects.length", 1, result.getProjects().size() );
 
-        Project project = (Project) result.getProjects().get( 0 );
+        Project project = result.getProjects().get( 0 );
 
         assertNotNull( project );
 
         assertEquals( "Maven", project.getName() );
 
+        assertEquals( "Java Project Management Tools", project.getDescription() );
+
         assertEquals( "scm:svn:http://svn.apache.org/repos/asf:maven/maven-1/core/trunk/", project.getScmUrl() );
 
         ProjectNotifier notifier = (ProjectNotifier) project.getNotifiers().get( 0 );
diff --git a/continuum-core/src/test/java/org/apache/maven/continuum/project/builder/maven/MavenTwoContinuumProjectBuilderTest.java b/continuum-core/src/test/java/org/apache/maven/continuum/project/builder/maven/MavenTwoContinuumProjectBuilderTest.java
index c51f398..62c714e 100644
--- a/continuum-core/src/test/java/org/apache/maven/continuum/project/builder/maven/MavenTwoContinuumProjectBuilderTest.java
+++ b/continuum-core/src/test/java/org/apache/maven/continuum/project/builder/maven/MavenTwoContinuumProjectBuilderTest.java
@@ -19,7 +19,6 @@
  * under the License.
  */
 
-import org.apache.log4j.Logger;
 import org.apache.maven.continuum.AbstractContinuumTest;
 import org.apache.maven.continuum.builddefinition.BuildDefinitionService;
 import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
@@ -32,11 +31,13 @@
 import org.apache.maven.continuum.project.builder.ContinuumProjectBuilder;
 import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
 import org.codehaus.plexus.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.io.File;
 import java.net.URL;
 import java.util.HashMap;
-import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -46,27 +47,13 @@
 public class MavenTwoContinuumProjectBuilderTest
     extends AbstractContinuumTest
 {
-
-    private Logger logger = Logger.getLogger( getClass() );
-
-    /*
-    protected String getConfigurationName( String subname )
-        throws Exception
-    {
-        return super.getConfigurationName( subname );
-    }
-    */
-
-    protected String getCustomConfigurationName()
-    {
-        return "plexus.xml";
-    }
+    private static final Logger logger = LoggerFactory.getLogger( MavenTwoContinuumProjectBuilderTest.class );
 
     public void testGetEmailAddressWhenTypeIsSetToEmail()
         throws Exception
     {
-        ContinuumProjectBuilder projectBuilder =
-            (ContinuumProjectBuilder) lookup( ContinuumProjectBuilder.ROLE, MavenTwoContinuumProjectBuilder.ID );
+        ContinuumProjectBuilder projectBuilder = (ContinuumProjectBuilder) lookup( ContinuumProjectBuilder.ROLE,
+                                                                                   MavenTwoContinuumProjectBuilder.ID );
 
         File pom = getTestFile( "src/test/repository/maven-builder-helper-1.xml" );
 
@@ -80,7 +67,7 @@
 
         assertEquals( 1, result.getProjects().size() );
 
-        Project project = (Project) result.getProjects().get( 0 );
+        Project project = result.getProjects().get( 0 );
 
         assertNotNull( project );
 
@@ -94,7 +81,7 @@
 
         assertEquals( "foo@bar", notifier.getConfiguration().get( "address" ) );
 
-        ProjectGroup pg = (ProjectGroup) result.getProjectGroups().get( 0 );
+        ProjectGroup pg = result.getProjectGroups().get( 0 );
 
         assertNotNull( pg );
 
@@ -106,8 +93,8 @@
     public void testGetEmailAddressWhenTypeIsntSet()
         throws Exception
     {
-        ContinuumProjectBuilder projectBuilder =
-            (ContinuumProjectBuilder) lookup( ContinuumProjectBuilder.ROLE, MavenTwoContinuumProjectBuilder.ID );
+        ContinuumProjectBuilder projectBuilder = (ContinuumProjectBuilder) lookup( ContinuumProjectBuilder.ROLE,
+                                                                                   MavenTwoContinuumProjectBuilder.ID );
 
         File pom = getTestFile( "src/test/repository/maven-builder-helper-2.xml" );
 
@@ -121,7 +108,7 @@
 
         assertEquals( 1, result.getProjects().size() );
 
-        Project project = (Project) result.getProjects().get( 0 );
+        Project project = result.getProjects().get( 0 );
 
         assertNotNull( project );
 
@@ -135,7 +122,7 @@
 
         assertEquals( "foo@bar", notifier.getConfiguration().get( "address" ) );
 
-        ProjectGroup pg = (ProjectGroup) result.getProjectGroups().get( 0 );
+        ProjectGroup pg = result.getProjectGroups().get( 0 );
 
         assertNotNull( pg );
 
@@ -147,8 +134,8 @@
     public void testGetScmUrlWithParams()
         throws Exception
     {
-        ContinuumProjectBuilder projectBuilder =
-            (ContinuumProjectBuilder) lookup( ContinuumProjectBuilder.ROLE, MavenTwoContinuumProjectBuilder.ID );
+        ContinuumProjectBuilder projectBuilder = (ContinuumProjectBuilder) lookup( ContinuumProjectBuilder.ROLE,
+                                                                                   MavenTwoContinuumProjectBuilder.ID );
 
         File pom = getTestFile( "src/test/repository/maven-builder-helper-3.xml" );
 
@@ -162,7 +149,7 @@
 
         assertEquals( 1, result.getProjects().size() );
 
-        ProjectGroup pg = (ProjectGroup) result.getProjectGroups().get( 0 );
+        ProjectGroup pg = result.getProjectGroups().get( 0 );
 
         assertNotNull( pg );
 
@@ -170,7 +157,7 @@
 
         String scmUrl = "scm:cvs:ext:${user.name}@company.org:/home/company/cvs:project/foo";
 
-        Project project = (Project) result.getProjects().get( 0 );
+        Project project = result.getProjects().get( 0 );
 
         scmUrl = StringUtils.replace( scmUrl, "${user.name}", username );
 
@@ -180,8 +167,8 @@
     public void testCreateProjectsWithModules()
         throws Exception
     {
-        ContinuumProjectBuilder projectBuilder =
-            (ContinuumProjectBuilder) lookup( ContinuumProjectBuilder.ROLE, MavenTwoContinuumProjectBuilder.ID );
+        ContinuumProjectBuilder projectBuilder = (ContinuumProjectBuilder) lookup( ContinuumProjectBuilder.ROLE,
+                                                                                   MavenTwoContinuumProjectBuilder.ID );
 
         URL url = getClass().getClassLoader().getResource( "projects/continuum/pom.xml" );
 
@@ -197,7 +184,7 @@
 
         assertEquals( 1, result.getErrors().size() );
 
-        assertEquals( ContinuumProjectBuildingResult.ERROR_POM_NOT_FOUND, result.getErrors().get( 0 ).toString() );
+        assertEquals( ContinuumProjectBuildingResult.ERROR_POM_NOT_FOUND, result.getErrors().get( 0 ) );
 
         // ----------------------------------------------------------------------
         // Assert the project group built
@@ -207,7 +194,7 @@
 
         assertEquals( 1, result.getProjectGroups().size() );
 
-        ProjectGroup projectGroup = (ProjectGroup) result.getProjectGroups().iterator().next();
+        ProjectGroup projectGroup = result.getProjectGroups().iterator().next();
 
         assertEquals( "projectGroup.groupId", "org.apache.maven.continuum", projectGroup.getGroupId() );
 
@@ -225,14 +212,14 @@
 
         assertEquals( 9, result.getProjects().size() );
 
-        Map projects = new HashMap();
+        Map<String, Project> projects = new HashMap<String, Project>();
 
-        for ( Iterator it = result.getProjects().iterator(); it.hasNext(); )
+        for ( Project project : result.getProjects() )
         {
-            Project project = (Project) it.next();
-
             assertNotNull( project.getName() );
 
+            assertNotNull( project.getDescription() );
+
             projects.put( project.getName(), project );
         }
 
@@ -248,11 +235,11 @@
         assertMavenTwoProject( "Continuum IRC Notifier", projects );
         assertMavenTwoProject( "Continuum Jabber Notifier", projects );
 
-        assertEquals( "continuum-parent-notifiers",
-                      ( (Project) projects.get( "Continuum IRC Notifier" ) ).getParent().getArtifactId() );
+        assertEquals( "continuum-parent-notifiers", ( projects.get(
+            "Continuum IRC Notifier" ) ).getParent().getArtifactId() );
 
-        assertEquals( "continuum-parent-notifiers",
-                      ( (Project) projects.get( "Continuum Jabber Notifier" ) ).getParent().getArtifactId() );
+        assertEquals( "continuum-parent-notifiers", ( projects.get(
+            "Continuum Jabber Notifier" ) ).getParent().getArtifactId() );
 
         assertDependency( "Continuum Model", "Continuum Web", projects );
     }
@@ -260,8 +247,8 @@
     public void testCreateProjectsWithModuleswithParentPomIsntPomXml()
         throws Exception
     {
-        ContinuumProjectBuilder projectBuilder =
-            (ContinuumProjectBuilder) lookup( ContinuumProjectBuilder.ROLE, MavenTwoContinuumProjectBuilder.ID );
+        ContinuumProjectBuilder projectBuilder = (ContinuumProjectBuilder) lookup( ContinuumProjectBuilder.ROLE,
+                                                                                   MavenTwoContinuumProjectBuilder.ID );
 
         URL url = getClass().getClassLoader().getResource( "projects/continuum/pom_ci.xml" );
 
@@ -277,7 +264,7 @@
 
         assertEquals( 1, result.getErrors().size() );
 
-        assertEquals( ContinuumProjectBuildingResult.ERROR_POM_NOT_FOUND, result.getErrors().get( 0 ).toString() );
+        assertEquals( ContinuumProjectBuildingResult.ERROR_POM_NOT_FOUND, result.getErrors().get( 0 ) );
 
         // ----------------------------------------------------------------------
         // Assert the project group built
@@ -287,7 +274,7 @@
 
         assertEquals( 1, result.getProjectGroups().size() );
 
-        ProjectGroup projectGroup = (ProjectGroup) result.getProjectGroups().iterator().next();
+        ProjectGroup projectGroup = result.getProjectGroups().iterator().next();
 
         assertEquals( "projectGroup.groupId", "org.apache.maven.continuum", projectGroup.getGroupId() );
 
@@ -305,12 +292,10 @@
 
         assertEquals( 9, result.getProjects().size() );
 
-        Map projects = new HashMap();
+        Map<String, Project> projects = new HashMap<String, Project>();
 
-        for ( Iterator it = result.getProjects().iterator(); it.hasNext(); )
+        for ( Project project : result.getProjects() )
         {
-            Project project = (Project) it.next();
-
             assertNotNull( project.getName() );
 
             projects.put( project.getName(), project );
@@ -328,11 +313,11 @@
         assertMavenTwoProject( "Continuum IRC Notifier", projects );
         assertMavenTwoProject( "Continuum Jabber Notifier", projects );
 
-        assertEquals( "continuum-parent-notifiers",
-                      ( (Project) projects.get( "Continuum IRC Notifier" ) ).getParent().getArtifactId() );
+        assertEquals( "continuum-parent-notifiers", ( projects.get(
+            "Continuum IRC Notifier" ) ).getParent().getArtifactId() );
 
-        assertEquals( "continuum-parent-notifiers",
-                      ( (Project) projects.get( "Continuum Jabber Notifier" ) ).getParent().getArtifactId() );
+        assertEquals( "continuum-parent-notifiers", ( projects.get(
+            "Continuum Jabber Notifier" ) ).getParent().getArtifactId() );
 
         assertDependency( "Continuum Model", "Continuum Web", projects );
     }
@@ -341,8 +326,8 @@
         throws Exception
     {
 
-        ContinuumProjectBuilder projectBuilder =
-            (ContinuumProjectBuilder) lookup( ContinuumProjectBuilder.ROLE, MavenTwoContinuumProjectBuilder.ID );
+        ContinuumProjectBuilder projectBuilder = (ContinuumProjectBuilder) lookup( ContinuumProjectBuilder.ROLE,
+                                                                                   MavenTwoContinuumProjectBuilder.ID );
 
         URL url = getClass().getClassLoader().getResource( "projects/continuum/continuum-core/pom.xml" );
 
@@ -374,7 +359,8 @@
 
         ContinuumProjectBuildingResult result;
 
-        result = projectBuilder.buildProjectsFromMetadata( url, null, null, false, bdt );
+        result = projectBuilder.buildProjectsFromMetadata( url, null, null, false, bdt, false );
+        assertFalse( result.hasErrors() );
 
         assertEquals( 5, service.getAllBuildDefinitionTemplate().size() );
 
@@ -390,7 +376,7 @@
 
         assertEquals( 1, result.getProjectGroups().size() );
 
-        ProjectGroup projectGroup = (ProjectGroup) result.getProjectGroups().get( 0 );
+        ProjectGroup projectGroup = result.getProjectGroups().get( 0 );
 
         assertEquals( "projectGroup.groupId", "org.apache.maven.continuum", projectGroup.getGroupId() );
 
@@ -405,11 +391,119 @@
         assertEquals( 0, projectGroup.getProjects().size() );
     }
 
-    private void assertDependency( String dep, String proj, Map projects )
+    public void testCreateProjectWithFlatStructure()
+        throws Exception
     {
-        Project p = (Project) projects.get( proj );
+        ContinuumProjectBuilder projectBuilder = (ContinuumProjectBuilder) lookup( ContinuumProjectBuilder.ROLE,
+                                                                                   MavenTwoContinuumProjectBuilder.ID );
 
-        Project dependency = (Project) projects.get( dep );
+        URL url = getTestFile( "/src/test-projects/flat-multi-module/parent-project/pom.xml" ).toURL();
+
+        ContinuumProjectBuildingResult result = projectBuilder.buildProjectsFromMetadata( url, null, null, true, true );
+
+        Project rootProject = result.getRootProject();
+        assertEquals( "Incorrect root project", "parent-project", rootProject.getArtifactId() );
+
+        List<Project> projects = result.getProjects();
+        for ( Project project : projects )
+        {
+            if ( project.getName().equals( "parent-project" ) )
+            {
+                assertEquals( "Incorrect scm url for parent-project",
+                              "scm:local:src/test-projects:flat-multi-module/parent-project", project.getScmUrl() );
+            }
+            else if ( project.getName().equals( "module-a" ) )
+            {
+                assertEquals( "Incorrect scm url for parent-project",
+                              "scm:local:src/test-projects:flat-multi-module/module-a", project.getScmUrl() );
+            }
+            else if ( project.getName().equals( "module-b" ) )
+            {
+                assertEquals( "Incorrect scm url for parent-project",
+                              "scm:local:src/test-projects:flat-multi-module/module-b", project.getScmUrl() );
+            }
+            else if ( project.getName().equals( "module-d" ) )
+            {
+                assertEquals( "Incorrect scm url for module-d",
+                              "scm:local:src/test-projects:flat-multi-module/module-c/module-d", project.getScmUrl() );
+            }
+            else
+            {
+                fail( "Unknown project: " + project.getName() );
+            }
+        }
+    }
+
+    // CONTINUUM-2563
+    public void testCreateMultiModuleProjectLoadRecursiveProjectsIsFalse()
+        throws Exception
+    {
+        ContinuumProjectBuilder projectBuilder = (ContinuumProjectBuilder) lookup( ContinuumProjectBuilder.ROLE,
+                                                                                   MavenTwoContinuumProjectBuilder.ID );
+
+        URL url = getClass().getClassLoader().getResource( "projects/continuum/pom.xml" );
+
+        ContinuumProjectBuildingResult result = projectBuilder.buildProjectsFromMetadata( url, null, null, false,
+                                                                                          false );
+
+        assertNotNull( result );
+
+        // ----------------------------------------------------------------------
+        // Assert the project group built
+        // ----------------------------------------------------------------------
+
+        assertNotNull( result.getProjectGroups() );
+
+        assertEquals( 1, result.getProjectGroups().size() );
+
+        ProjectGroup projectGroup = result.getProjectGroups().iterator().next();
+
+        assertEquals( "projectGroup.groupId", "org.apache.maven.continuum", projectGroup.getGroupId() );
+
+        assertEquals( "projectGroup.name", "Continuum Parent Project", projectGroup.getName() );
+
+        assertEquals( "projectGroup.description", "Continuum Project Description", projectGroup.getDescription() );
+
+        // ----------------------------------------------------------------------
+        // Assert the projects built
+        // ----------------------------------------------------------------------
+
+        assertNotNull( result.getProjects() );
+
+        assertEquals( 1, result.getProjects().size() );
+
+        Map<String, Project> projects = new HashMap<String, Project>();
+
+        Project project = result.getProjects().iterator().next();
+        assertNotNull( project.getName() );
+        assertNotNull( project.getDescription() );
+        projects.put( project.getName(), project );
+
+        assertMavenTwoProject( "Continuum Parent Project", projects );
+
+        // assert the default project build definition
+        List<BuildDefinition> buildDefs = project.getBuildDefinitions();
+        assertEquals( 0, buildDefs.size() );
+
+        // assert the default project build definition
+        buildDefs = projectGroup.getBuildDefinitions();
+        assertEquals( 1, buildDefs.size() );
+        for ( BuildDefinition buildDef : buildDefs )
+        {
+            if ( buildDef.isDefaultForProject() )
+            {
+                assertEquals( "--batch-mode", buildDef.getArguments() );
+                assertEquals( "clean install", buildDef.getGoals() );
+                assertEquals( "pom.xml", buildDef.getBuildFile() );
+            }
+        }
+    }
+
+    private void assertDependency( String dep, String proj, Map<String, Project> projects )
+    {
+        Project p = projects.get( proj );
+
+        Project dependency = projects.get( dep );
 
         assertNotNull( p );
 
@@ -417,10 +511,8 @@
 
         assertNotNull( p.getDependencies() );
 
-        for ( Iterator i = p.getDependencies().iterator(); i.hasNext(); )
+        for ( ProjectDependency pd : (List<ProjectDependency>) p.getDependencies() )
         {
-            ProjectDependency pd = (ProjectDependency) i.next();
-
             if ( pd.getArtifactId().equals( dependency.getArtifactId() ) &&
                 pd.getGroupId().equals( dependency.getGroupId() ) && pd.getVersion().equals( dependency.getVersion() ) )
             {
@@ -435,12 +527,12 @@
     //
     // ----------------------------------------------------------------------
 
-    private Project getProject( String name, Map projects )
+    private Project getProject( String name, Map<String, Project> projects )
     {
-        return (Project) projects.get( name );
+        return projects.get( name );
     }
 
-    private void assertMavenTwoProject( String name, Map projects )
+    private void assertMavenTwoProject( String name, Map<String, Project> projects )
     {
         Project project = getProject( name, projects );
 
@@ -453,7 +545,7 @@
         assertTrue( project.getScmUrl().startsWith( scmUrl ) );
     }
 
-    private void assertScmUrl( String name, Map projects, String scmUrl )
+    private void assertScmUrl( String name, Map<String, Project> projects, String scmUrl )
     {
         assertMavenTwoProject( name, projects );
 
diff --git a/continuum-core/src/test/java/org/apache/maven/continuum/scm/queue/PrepareBuildProjectsTaskExecutorTest.java b/continuum-core/src/test/java/org/apache/maven/continuum/scm/queue/PrepareBuildProjectsTaskExecutorTest.java
new file mode 100644
index 0000000..62a75e7
--- /dev/null
+++ b/continuum-core/src/test/java/org/apache/maven/continuum/scm/queue/PrepareBuildProjectsTaskExecutorTest.java
@@ -0,0 +1,626 @@
+package org.apache.maven.continuum.scm.queue;
+
+/*
+ * 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 org.apache.continuum.buildmanager.BuildsManager;
+import org.apache.continuum.buildmanager.ParallelBuildsManager;
+import org.apache.continuum.dao.ProjectScmRootDao;
+import org.apache.continuum.model.project.ProjectScmRoot;
+import org.apache.continuum.taskqueue.BuildProjectTask;
+import org.apache.continuum.taskqueue.PrepareBuildProjectsTask;
+import org.apache.maven.continuum.AbstractContinuumTest;
+import org.apache.maven.continuum.configuration.ConfigurationService;
+import org.apache.maven.continuum.core.action.AbstractContinuumAction;
+import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.project.ProjectGroup;
+import org.apache.maven.continuum.project.ContinuumProjectState;
+import org.apache.maven.continuum.project.builder.ContinuumProjectBuilder;
+import org.apache.maven.continuum.project.builder.ContinuumProjectBuilderException;
+import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
+import org.apache.maven.continuum.project.builder.maven.MavenTwoContinuumProjectBuilder;
+import org.codehaus.plexus.action.ActionManager;
+import org.codehaus.plexus.util.StringUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class PrepareBuildProjectsTaskExecutorTest
+    extends AbstractContinuumTest
+{
+    private ContinuumProjectBuilder projectBuilder;
+
+    private ActionManager actionManager;
+
+    private ProjectScmRootDao projectScmRootDao;
+
+    private ConfigurationService configurationService;
+
+    private BuildsManager buildsManager;
+
+    @Override
+    protected void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        projectBuilder = (ContinuumProjectBuilder) lookup( ContinuumProjectBuilder.ROLE,
+                                                           MavenTwoContinuumProjectBuilder.ID );
+
+        projectScmRootDao = (ProjectScmRootDao) lookup( ProjectScmRootDao.class.getName() );
+
+        actionManager = (ActionManager) lookup( ActionManager.ROLE );
+
+        configurationService = (ConfigurationService) lookup( "configurationService" );
+
+        buildsManager = (ParallelBuildsManager) lookup( BuildsManager.class, "parallel" );
+    }
+
+    public void testCheckoutPrepareBuildMultiModuleProject()
+        throws Exception
+    {
+        PrepareBuildProjectsTask task = createTask( "src/test-projects/multi-module/pom.xml", false, false );
+
+        List<Project> projects = getProjectDao().getProjectsInGroup( task.getProjectGroupId() );
+
+        assertEquals( "failed to add all projects", 4, projects.size() );
+
+        Project rootProject = getProjectDao().getProjectByName( "multi-module-parent" );
+        Project moduleA = getProjectDao().getProjectByName( "module-A" );
+        Project moduleB = getProjectDao().getProjectByName( "module-B" );
+        Project moduleD = getProjectDao().getProjectByName( "module-D" );
+
+        buildsManager.prepareBuildProjects( task.getProjectsBuildDefinitionsMap(), task.getBuildTrigger(),
+                                            task.getProjectGroupId(), task.getProjectGroupName(),
+                                            task.getScmRootAddress(), task.getProjectScmRootId() );
+
+        // wait while task finishes prepare build
+        waitForPrepareBuildToFinish( task.getProjectGroupId(), task.getProjectScmRootId() );
+
+        ProjectScmRoot scmRoot = projectScmRootDao.getProjectScmRoot( task.getProjectScmRootId() );
+        assertEquals( "Failed to update multi-module project", ContinuumProjectState.UPDATED, scmRoot.getState() );
+
+        File workingDir = configurationService.getWorkingDirectory();
+
+        assertTrue( "checkout directory of project 'multi-module-parent' does not exist.", new File( workingDir,
+                                                                                                     Integer.toString(
+                                                                                                         rootProject.getId() ) ).exists() );
+
+        assertTrue( "checkout directory of project 'module-A' does not exist.", new File( workingDir, Integer.toString(
+            moduleA.getId() ) ).exists() );
+
+        assertTrue( "checkout directory of project 'module-B' does not exist.", new File( workingDir, Integer.toString(
+            moduleB.getId() ) ).exists() );
+
+        assertTrue( "checkout directory of project 'module-D' does not exist.", new File( workingDir, Integer.toString(
+            moduleD.getId() ) ).exists() );
+
+        assertTrue( "failed to checkout project 'multi-module-parent'", new File( workingDir, Integer.toString(
+            rootProject.getId() ) ).list().length > 0 );
+
+        assertTrue( "failed to checkout project 'module-A'", new File( workingDir, Integer.toString(
+            moduleA.getId() ) ).list().length > 0 );
+
+        assertTrue( "failed to checkout project 'module-B'", new File( workingDir, Integer.toString(
+            moduleB.getId() ) ).list().length > 0 );
+
+        assertTrue( "failed to checkout project 'module-D'", new File( workingDir, Integer.toString(
+            moduleD.getId() ) ).list().length > 0 );
+
+        // wait while task finished build
+        waitForBuildToFinish();
+    }
+
+    public void testCheckoutPrepareBuildMultiModuleProjectFreshBuild()
+        throws Exception
+    {
+        PrepareBuildProjectsTask task = createTask( "src/test-projects/multi-module/pom.xml", false, true );
+
+        List<Project> projects = getProjectDao().getProjectsInGroup( task.getProjectGroupId() );
+
+        assertEquals( "failed to add all projects", 4, projects.size() );
+
+        Project rootProject = getProjectDao().getProjectByName( "multi-module-parent" );
+        Project moduleA = getProjectDao().getProjectByName( "module-A" );
+        Project moduleB = getProjectDao().getProjectByName( "module-B" );
+        Project moduleD = getProjectDao().getProjectByName( "module-D" );
+
+        buildsManager.prepareBuildProjects( task.getProjectsBuildDefinitionsMap(), task.getBuildTrigger(),
+                                            task.getProjectGroupId(), task.getProjectGroupName(),
+                                            task.getScmRootAddress(), task.getProjectScmRootId() );
+
+        // wait while task finishes prepare build
+        waitForPrepareBuildToFinish( task.getProjectGroupId(), task.getProjectScmRootId() );
+
+        ProjectScmRoot scmRoot = projectScmRootDao.getProjectScmRoot( task.getProjectScmRootId() );
+        assertEquals( "Failed to update multi-module project", ContinuumProjectState.UPDATED, scmRoot.getState() );
+
+        File workingDir = configurationService.getWorkingDirectory();
+
+        assertTrue( "checkout directory of project 'multi-module-parent' does not exist.", new File( workingDir,
+                                                                                                     Integer.toString(
+                                                                                                         rootProject.getId() ) ).exists() );
+
+        assertTrue( "checkout directory of project 'module-A' does not exist.", new File( workingDir, Integer.toString(
+            moduleA.getId() ) ).exists() );
+
+        assertTrue( "checkout directory of project 'module-B' does not exist.", new File( workingDir, Integer.toString(
+            moduleB.getId() ) ).exists() );
+
+        assertTrue( "checkout directory of project 'module-D' does not exist.", new File( workingDir, Integer.toString(
+            moduleD.getId() ) ).exists() );
+
+        assertTrue( "failed to checkout project 'multi-module-parent'", new File( workingDir, Integer.toString(
+            rootProject.getId() ) ).list().length > 0 );
+
+        assertTrue( "failed to checkout project 'module-A'", new File( workingDir, Integer.toString(
+            moduleA.getId() ) ).list().length > 0 );
+
+        assertTrue( "failed to checkout project 'module-B'", new File( workingDir, Integer.toString(
+            moduleB.getId() ) ).list().length > 0 );
+
+        assertTrue( "failed to checkout project 'module-D'", new File( workingDir, Integer.toString(
+            moduleD.getId() ) ).list().length > 0 );
+
+        // wait while task finished build
+        waitForBuildToFinish();
+    }
+
+    public void testCheckoutPrepareBuildSingleCheckedoutMultiModuleProject()
+        throws Exception
+    {
+        PrepareBuildProjectsTask task = createTask( "src/test-projects/multi-module/pom.xml", true, false );
+
+        List<Project> projects = getProjectDao().getProjectsInGroup( task.getProjectGroupId() );
+
+        assertEquals( "failed to add all projects", 4, projects.size() );
+
+        Project rootProject = getProjectDao().getProjectByName( "multi-module-parent" );
+
+        buildsManager.prepareBuildProjects( task.getProjectsBuildDefinitionsMap(), task.getBuildTrigger(),
+                                            task.getProjectGroupId(), task.getProjectGroupName(),
+                                            task.getScmRootAddress(), task.getProjectScmRootId() );
+
+        // wait while task finishes prepare build
+        waitForPrepareBuildToFinish( task.getProjectGroupId(), task.getProjectScmRootId() );
+
+        ProjectScmRoot scmRoot = projectScmRootDao.getProjectScmRoot( task.getProjectScmRootId() );
+        assertEquals( "Failed to update multi-module project", ContinuumProjectState.UPDATED, scmRoot.getState() );
+
+        File checkedOutDir = new File( configurationService.getWorkingDirectory(), Integer.toString(
+            rootProject.getId() ) );
+
+        assertTrue( "checkout directory of project 'multi-module-parent' does not exist.", checkedOutDir.exists() );
+
+        assertTrue( "module-A was not checked out in the same directory as it's parent.", new File( checkedOutDir,
+                                                                                                    "module-A" ).exists() );
+
+        assertTrue( "module-B was not checked out in the same directory as it's parent.", new File( checkedOutDir,
+                                                                                                    "module-B" ).exists() );
+
+        assertTrue( "module-D was not checked out in the same directory as it's parent.", new File( checkedOutDir,
+                                                                                                    "module-C/module-D" ).exists() );
+
+        assertTrue( "failed to checkout project 'multi-module-parent'", checkedOutDir.list().length > 0 );
+
+        assertTrue( "failed to checkout project 'module-A'", new File( checkedOutDir, "module-A" ).list().length > 0 );
+
+        assertTrue( "failed to checkout project 'module-B'", new File( checkedOutDir, "module-B" ).list().length > 0 );
+
+        assertTrue( "failed to checkout project 'module-D'", new File( checkedOutDir,
+                                                                       "module-C/module-D" ).list().length > 0 );
+
+        // wait while task finishes build
+        waitForBuildToFinish();
+    }
+
+    public void testCheckoutPrepareBuildSingleCheckedoutMultiModuleProjectFreshBuild()
+        throws Exception
+    {
+        PrepareBuildProjectsTask task = createTask( "src/test-projects/multi-module/pom.xml", true, true );
+
+        List<Project> projects = getProjectDao().getProjectsInGroup( task.getProjectGroupId() );
+
+        assertEquals( "failed to add all projects", 4, projects.size() );
+
+        Project rootProject = getProjectDao().getProjectByName( "multi-module-parent" );
+
+        buildsManager.prepareBuildProjects( task.getProjectsBuildDefinitionsMap(), task.getBuildTrigger(),
+                                            task.getProjectGroupId(), task.getProjectGroupName(),
+                                            task.getScmRootAddress(), task.getProjectScmRootId() );
+
+        // wait while task finishes prepare build
+        waitForPrepareBuildToFinish( task.getProjectGroupId(), task.getProjectScmRootId() );
+
+        ProjectScmRoot scmRoot = projectScmRootDao.getProjectScmRoot( task.getProjectScmRootId() );
+        assertEquals( "Failed to update multi-module project", ContinuumProjectState.UPDATED, scmRoot.getState() );
+
+        File checkedOutDir = new File( configurationService.getWorkingDirectory(), Integer.toString(
+            rootProject.getId() ) );
+
+        assertTrue( "checkout directory of project 'multi-module-parent' does not exist.", checkedOutDir.exists() );
+
+        assertTrue( "module-A was not checked out in the same directory as it's parent.", new File( checkedOutDir,
+                                                                                                    "module-A" ).exists() );
+
+        assertTrue( "module-B was not checked out in the same directory as it's parent.", new File( checkedOutDir,
+                                                                                                    "module-B" ).exists() );
+
+        assertTrue( "module-D was not checked out in the same directory as it's parent.", new File( checkedOutDir,
+                                                                                                    "module-C/module-D" ).exists() );
+
+        assertTrue( "failed to checkout project 'multi-module-parent'", checkedOutDir.list().length > 0 );
+
+        assertTrue( "failed to checkout project 'module-A'", new File( checkedOutDir, "module-A" ).list().length > 0 );
+
+        assertTrue( "failed to checkout project 'module-B'", new File( checkedOutDir, "module-B" ).list().length > 0 );
+
+        assertTrue( "failed to checkout project 'module-D'", new File( checkedOutDir,
+                                                                       "module-C/module-D" ).list().length > 0 );
+
+        // wait while task finishes build
+        waitForBuildToFinish();
+    }
+
+    public void testCheckoutPrepareBuildSingleCheckoutFlatMultiModuleProject()
+        throws Exception
+    {
+        PrepareBuildProjectsTask task = createTask( "src/test-projects/flat-multi-module/parent-project/pom.xml", true,
+                                                    false );
+
+        List<Project> projects = getProjectDao().getProjectsInGroup( task.getProjectGroupId() );
+
+        assertEquals( "failed to add all projects", 4, projects.size() );
+
+        Project rootProject = getProjectDao().getProjectByName( "parent-project" );
+
+        buildsManager.prepareBuildProjects( task.getProjectsBuildDefinitionsMap(), task.getBuildTrigger(),
+                                            task.getProjectGroupId(), task.getProjectGroupName(),
+                                            task.getScmRootAddress(), task.getProjectScmRootId() );
+
+        // wait while task finishes prepare build
+        waitForPrepareBuildToFinish( task.getProjectGroupId(), task.getProjectScmRootId() );
+
+        ProjectScmRoot scmRoot = projectScmRootDao.getProjectScmRoot( task.getProjectScmRootId() );
+        assertEquals( "Failed to update multi-module project", ContinuumProjectState.UPDATED, scmRoot.getState() );
+
+        File checkedOutDir = new File( configurationService.getWorkingDirectory(), Integer.toString(
+            rootProject.getId() ) );
+
+        assertTrue( "checkout directory of project 'parent-project' does not exist.", new File( checkedOutDir,
+                                                                                                "parent-project" ).exists() );
+
+        assertTrue( "module-a was not checked out in the same directory as it's parent.", new File( checkedOutDir,
+                                                                                                    "module-a" ).exists() );
+
+        assertTrue( "module-b was not checked out in the same directory as it's parent.", new File( checkedOutDir,
+                                                                                                    "module-b" ).exists() );
+
+        assertTrue( "module-d was not checked out in the same directory as it's parent.", new File( checkedOutDir,
+                                                                                                    "module-c/module-d" ).exists() );
+
+        assertTrue( "failed to checkout parent-project", new File( checkedOutDir, "parent-project" ).list().length >
+            0 );
+
+        assertTrue( "failed to checkout module-a", new File( checkedOutDir, "module-a" ).list().length > 0 );
+
+        assertTrue( "failed to checkout module-b", new File( checkedOutDir, "module-b" ).list().length > 0 );
+
+        assertTrue( "failed to checkout module-d", new File( checkedOutDir, "module-c/module-d" ).list().length > 0 );
+
+        // wait while task finishes build
+        waitForPrepareBuildToFinish( task.getProjectGroupId(), task.getProjectScmRootId() );
+    }
+
+    public void testCheckoutPrepareBuildSingleCheckoutFlatMultiModuleProjectBuildFresh()
+        throws Exception
+    {
+        PrepareBuildProjectsTask task = createTask( "src/test-projects/flat-multi-module/parent-project/pom.xml", true,
+                                                    true );
+
+        List<Project> projects = getProjectDao().getProjectsInGroup( task.getProjectGroupId() );
+
+        assertEquals( "failed to add all projects", 4, projects.size() );
+
+        Project rootProject = getProjectDao().getProjectByName( "parent-project" );
+
+        buildsManager.prepareBuildProjects( task.getProjectsBuildDefinitionsMap(), task.getBuildTrigger(),
+                                            task.getProjectGroupId(), task.getProjectGroupName(),
+                                            task.getScmRootAddress(), task.getProjectScmRootId() );
+
+        // wait while task finishes prepare build
+        waitForPrepareBuildToFinish( task.getProjectGroupId(), task.getProjectScmRootId() );
+
+        ProjectScmRoot scmRoot = projectScmRootDao.getProjectScmRoot( task.getProjectScmRootId() );
+        assertEquals( "Failed to update multi-module project", ContinuumProjectState.UPDATED, scmRoot.getState() );
+
+        File checkedOutDir = new File( configurationService.getWorkingDirectory(), Integer.toString(
+            rootProject.getId() ) );
+
+        assertTrue( "checkout directory of project 'parent-project' does not exist.", new File( checkedOutDir,
+                                                                                                "parent-project" ).exists() );
+
+        assertTrue( "module-a was not checked out in the same directory as it's parent.", new File( checkedOutDir,
+                                                                                                    "module-a" ).exists() );
+
+        assertTrue( "module-b was not checked out in the same directory as it's parent.", new File( checkedOutDir,
+                                                                                                    "module-b" ).exists() );
+
+        assertTrue( "module-d was not checked out in the same directory as it's parent.", new File( checkedOutDir,
+                                                                                                    "module-c/module-d" ).exists() );
+
+        assertTrue( "failed to checkout parent-project", new File( checkedOutDir, "parent-project" ).list().length >
+            0 );
+
+        assertTrue( "failed to checkout module-a", new File( checkedOutDir, "module-a" ).list().length > 0 );
+
+        assertTrue( "failed to checkout module-b", new File( checkedOutDir, "module-b" ).list().length > 0 );
+
+        assertTrue( "failed to checkout module-d", new File( checkedOutDir, "module-c/module-d" ).list().length > 0 );
+
+        // wait while task finishes build
+        waitForBuildToFinish();
+    }
+
+    public void testCheckoutPrepareBuildSingleCheckoutFlatMultiModuleProjectBuildFreshAfterRemovingWorkingCopy()
+        throws Exception
+    {
+        PrepareBuildProjectsTask task = createTask( "src/test-projects/flat-multi-module/parent-project/pom.xml", true,
+                                                    true );
+
+        List<Project> projects = getProjectDao().getProjectsInGroup( task.getProjectGroupId() );
+
+        assertEquals( "failed to add all projects", 4, projects.size() );
+
+        Project rootProject = getProjectDao().getProjectByName( "parent-project" );
+
+        File rootProjectDir = new File( configurationService.getWorkingDirectory(), Integer.toString(
+            rootProject.getId() ) );
+        rootProjectDir = new File( rootProjectDir, "parent-project" );
+
+        rootProject.setWorkingDirectory( rootProjectDir.getAbsolutePath() );
+
+        getProjectDao().updateProject( rootProject );
+
+        buildsManager.prepareBuildProjects( task.getProjectsBuildDefinitionsMap(), task.getBuildTrigger(),
+                                            task.getProjectGroupId(), task.getProjectGroupName(),
+                                            task.getScmRootAddress(), task.getProjectScmRootId() );
+
+        // wait while task finishes prepare build
+        waitForPrepareBuildToFinish( task.getProjectGroupId(), task.getProjectScmRootId() );
+
+        ProjectScmRoot scmRoot = projectScmRootDao.getProjectScmRoot( task.getProjectScmRootId() );
+        assertEquals( "Failed to update multi-module project", ContinuumProjectState.UPDATED, scmRoot.getState() );
+
+        File checkedOutDir = new File( configurationService.getWorkingDirectory(), Integer.toString(
+            rootProject.getId() ) );
+
+        assertTrue( "checkout directory of project 'parent-project' does not exist.", new File( checkedOutDir,
+                                                                                                "parent-project" ).exists() );
+
+        assertTrue( "module-a was not checked out in the same directory as it's parent.", new File( checkedOutDir,
+                                                                                                    "module-a" ).exists() );
+
+        assertTrue( "module-b was not checked out in the same directory as it's parent.", new File( checkedOutDir,
+                                                                                                    "module-b" ).exists() );
+
+        assertTrue( "module-d was not checked out in the same directory as it's parent.", new File( checkedOutDir,
+                                                                                                    "module-c/module-d" ).exists() );
+
+        assertTrue( "failed to checkout parent-project", new File( checkedOutDir, "parent-project" ).list().length >
+            0 );
+
+        assertTrue( "failed to checkout module-a", new File( checkedOutDir, "module-a" ).list().length > 0 );
+
+        assertTrue( "failed to checkout module-b", new File( checkedOutDir, "module-b" ).list().length > 0 );
+
+        assertTrue( "failed to checkout module-d", new File( checkedOutDir, "module-c/module-d" ).list().length > 0 );
+
+        // wait while task finishes build
+        waitForBuildToFinish();
+    }
+
+    private PrepareBuildProjectsTask createTask( String pomResource, boolean singleCheckout, boolean buildFresh )
+        throws Exception
+    {
+        ProjectGroup projectGroup = getProjectGroup( pomResource, singleCheckout );
+
+        BuildDefinition buildDefinition = new BuildDefinition();
+        buildDefinition.setId( 0 );
+        buildDefinition.setGoals( "clean" );
+        buildDefinition.setBuildFresh( buildFresh );
+
+        projectGroup.addBuildDefinition( buildDefinition );
+
+        Map<String, Object> pgContext = new HashMap<String, Object>();
+
+        AbstractContinuumAction.setWorkingDirectory( pgContext,
+                                                     configurationService.getWorkingDirectory().getAbsolutePath() );
+
+        AbstractContinuumAction.setUnvalidatedProjectGroup( pgContext, projectGroup );
+
+        actionManager.lookup( "validate-project-group" ).execute( pgContext );
+
+        actionManager.lookup( "store-project-group" ).execute( pgContext );
+
+        int projectGroupId = AbstractContinuumAction.getProjectGroupId( pgContext );
+
+        projectGroup = getProjectGroupDao().getProjectGroupWithBuildDetailsByProjectGroupId( projectGroupId );
+
+        String scmRootUrl = getScmRootUrl( projectGroup );
+
+        assertNotNull( scmRootUrl );
+
+        ProjectScmRoot scmRoot = getProjectScmRoot( projectGroup, scmRootUrl );
+
+        assertNotNull( scmRoot );
+
+        buildDefinition = (BuildDefinition) projectGroup.getBuildDefinitions().get( 0 );
+
+        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
+
+        Project rootProject = null;
+
+        List<Project> projects = (List<Project>) projectGroup.getProjects();
+
+        for ( Project project : projects )
+        {
+            assertFalse( project.getId() == 0 );
+
+            map.put( project.getId(), buildDefinition.getId() );
+
+            if ( rootProject == null || rootProject.getId() > project.getId() )
+            {
+                rootProject = project;
+            }
+        }
+
+        assertEquals( 4, map.size() );
+        PrepareBuildProjectsTask task = new PrepareBuildProjectsTask( map,
+                                                                      new org.apache.continuum.utils.build.BuildTrigger(
+                                                                          1, "user" ), projectGroupId,
+                                                                      projectGroup.getName(),
+                                                                      scmRoot.getScmRootAddress(), scmRoot.getId() );
+
+        return task;
+    }
+
+    private ProjectGroup getProjectGroup( String pomResource, boolean singleCheckout )
+        throws ContinuumProjectBuilderException, IOException
+    {
+        File pom = getTestFile( pomResource );
+
+        assertNotNull( "Can't find project " + pomResource, pom );
+
+        //ContinuumProjectBuildingResult result = projectBuilder.buildProjectsFromMetadata( pom.toURL(), null, null, true );
+        ContinuumProjectBuildingResult result = projectBuilder.buildProjectsFromMetadata( pom.toURL(), null, null, true,
+                                                                                          singleCheckout );
+
+        // some assertions to make sure our expectations match. This is NOT
+        // meant as a unit test for the projectbuilder!
+
+        assertNotNull( "Project list not null", result.getProjects() );
+
+        assertEquals( "#Projectgroups", 1, result.getProjectGroups().size() );
+
+        ProjectGroup pg = result.getProjectGroups().get( 0 );
+
+        if ( !result.getProjects().isEmpty() )
+        {
+            for ( Project p : result.getProjects() )
+            {
+                pg.addProject( p );
+            }
+        }
+
+        return pg;
+    }
+
+    private ProjectScmRoot getProjectScmRoot( ProjectGroup pg, String url )
+        throws Exception
+    {
+        if ( StringUtils.isEmpty( url ) )
+        {
+            return null;
+        }
+
+        ProjectScmRoot scmRoot = projectScmRootDao.getProjectScmRootByProjectGroupAndScmRootAddress( pg.getId(), url );
+
+        if ( scmRoot != null )
+        {
+            return scmRoot;
+        }
+
+        ProjectScmRoot projectScmRoot = new ProjectScmRoot();
+
+        projectScmRoot.setProjectGroup( pg );
+
+        projectScmRoot.setScmRootAddress( url );
+
+        //projectScmRoot.setState( ContinuumProjectState.ERROR );
+
+        return projectScmRootDao.addProjectScmRoot( projectScmRoot );
+    }
+
+    private String getScmRootUrl( ProjectGroup pg )
+    {
+        String scmRootUrl = null;
+
+        for ( Project project : (List<Project>) pg.getProjects() )
+        {
+            String scmUrl = project.getScmUrl();
+
+            scmRootUrl = getCommonPath( scmUrl, scmRootUrl );
+        }
+
+        return scmRootUrl;
+    }
+
+    private String getCommonPath( String path1, String path2 )
+    {
+        if ( path2 == null || path2.equals( "" ) )
+        {
+            return path1;
+        }
+        else
+        {
+            int indexDiff = StringUtils.differenceAt( path1, path2 );
+            return path1.substring( 0, indexDiff );
+        }
+    }
+
+    private void waitForPrepareBuildToFinish( int projectGroupId, int scmRootId )
+        throws Exception
+    {
+        while ( buildsManager.isInPrepareBuildQueue( projectGroupId, scmRootId ) ||
+            buildsManager.isProjectGroupCurrentlyPreparingBuild( projectGroupId, scmRootId ) )
+        {
+            Thread.sleep( 10 );
+        }
+    }
+
+    private void waitForBuildToFinish()
+        throws Exception
+    {
+        while ( buildsManager.isBuildInProgress() || isAnyProjectInBuildQueue() )
+        {
+            Thread.sleep( 10 );
+        }
+    }
+
+    private boolean isAnyProjectInBuildQueue()
+        throws Exception
+    {
+        Map<String, List<BuildProjectTask>> buildTasks = buildsManager.getProjectsInBuildQueues();
+
+        for ( String queue : buildTasks.keySet() )
+        {
+            if ( !buildTasks.get( queue ).isEmpty() )
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+}
diff --git a/continuum-core/src/test/resources/applicationContextSlf4jPlexusLogger.xml b/continuum-core/src/test/resources/applicationContextSlf4jPlexusLogger.xml
deleted file mode 100755
index b5bf893..0000000
--- a/continuum-core/src/test/resources/applicationContextSlf4jPlexusLogger.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!--
-  ~ 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.
-  -->
-
-<beans xmlns="http://www.springframework.org/schema/beans"
-       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xsi:schemaLocation="http://www.springframework.org/schema/beans
-           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
-
-  <bean id="loggerManager" class="org.codehaus.plexus.logging.slf4j.Slf4jLoggerManager"
-    init-method="initialize"/>
-  
-</beans>
diff --git a/continuum-core/src/test/resources/log4j.xml b/continuum-core/src/test/resources/log4j.xml
deleted file mode 100644
index bbc5fda..0000000
--- a/continuum-core/src/test/resources/log4j.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
-
-<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
-
-  <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
-    <layout class="org.apache.log4j.PatternLayout">
-      <param name="ConversionPattern" value="%d %-5p %c %x - %m%n"/>
-    </layout>
-  </appender>
-
-  <!-- quiet spring loading :-) -->
-  <logger name="org.springframework">
-    <level value="ERROR"/>
-  </logger>
-  <logger name="org.codehaus.plexus">
-    <level value="ERROR"/>
-  </logger>
-  
-  <logger name="org.apache.commons">
-    <level value="ERROR"/>
-  </logger>  
-  
-  <logger name="org.apache.maven.continuum.execution.maven.m2">
-    <level value="debug" />
-  </logger>
-
-  <!-- JPOX -->
-  <logger name="JPOX">
-    <level value="WARN"/>
-  </logger>
-  <logger name="JPOX.RDBMS">
-    <level value="ERROR"/>
-  </logger>
-
-  <root>
-    <level value="INFO"/>
-    <appender-ref ref="CONSOLE"/>
-  </root>
-
-</log4j:configuration>
\ No newline at end of file
diff --git a/continuum-core/src/test/resources/org/apache/maven/continuum/AddProjectTest.xml b/continuum-core/src/test/resources/org/apache/maven/continuum/AddProjectTest.xml
index 18f0152..3c7b069 100644
--- a/continuum-core/src/test/resources/org/apache/maven/continuum/AddProjectTest.xml
+++ b/continuum-core/src/test/resources/org/apache/maven/continuum/AddProjectTest.xml
@@ -24,5 +24,10 @@
       <role-hint>continuumUrl</role-hint>
       <implementation>org.apache.maven.continuum.utils.ContinuumUrlValidator</implementation>
     </component>
+    <component>
+      <role>org.codehaus.plexus.action.Action</role>
+      <role-hint>add-project-to-checkout-queue</role-hint>
+      <implementation>org.apache.maven.continuum.AddProjectToCheckoutQueueStub</implementation>
+    </component>
   </components>
 </plexus>
diff --git a/continuum-core/src/test/resources/org/apache/maven/continuum/DefaultContinuumTest.xml b/continuum-core/src/test/resources/org/apache/maven/continuum/DefaultContinuumTest.xml
index 477520b..c986668 100644
--- a/continuum-core/src/test/resources/org/apache/maven/continuum/DefaultContinuumTest.xml
+++ b/continuum-core/src/test/resources/org/apache/maven/continuum/DefaultContinuumTest.xml
@@ -70,7 +70,9 @@
       <role>org.codehaus.plexus.redback.role.processor.RoleModelProcessor</role>
       <role-hint>default</role-hint>
       <implementation>org.codehaus.plexus.redback.role.processor.DefaultRoleModelProcessor</implementation>
-      <description>DefaultRoleModelProcessor: inserts the components of the model that can be populated into the rbac manager</description>
+      <description>DefaultRoleModelProcessor: inserts the components of the model that can be populated into the rbac
+        manager
+      </description>
       <requirements>
         <requirement>
           <role>org.codehaus.plexus.redback.rbac.RBACManager</role>
@@ -95,7 +97,8 @@
       <role>org.codehaus.plexus.redback.role.template.RoleTemplateProcessor</role>
       <role-hint>default</role-hint>
       <implementation>org.codehaus.plexus.redback.role.template.DefaultRoleTemplateProcessor</implementation>
-      <description>DefaultRoleTemplateProcessor: inserts the components of a template into the rbac manager</description>
+      <description>DefaultRoleTemplateProcessor: inserts the components of a template into the rbac manager
+      </description>
       <requirements>
         <requirement>
           <role>org.codehaus.plexus.redback.rbac.RBACManager</role>
@@ -110,7 +113,7 @@
       <implementation>org.codehaus.plexus.redback.role.DefaultRoleManager</implementation>
       <instantiation-strategy>singleton</instantiation-strategy>
       <description>RoleProfileManager:</description>
-      <requirements>        
+      <requirements>
         <requirement>
           <role>org.codehaus.plexus.redback.role.validator.RoleModelValidator</role>
           <role-hint>default</role-hint>
diff --git a/continuum-core/src/test/resources/org/apache/maven/continuum/notification/ContinuumNotificationDispatcherTest.xml b/continuum-core/src/test/resources/org/apache/maven/continuum/notification/ContinuumNotificationDispatcherTest.xml
index e652092..20f7e94 100644
--- a/continuum-core/src/test/resources/org/apache/maven/continuum/notification/ContinuumNotificationDispatcherTest.xml
+++ b/continuum-core/src/test/resources/org/apache/maven/continuum/notification/ContinuumNotificationDispatcherTest.xml
@@ -19,12 +19,12 @@
 
 <plexus>
   <components>
-   
+
     <component>
       <role>org.springframework.mail.javamail.JavaMailSender</role>
       <implementation>org.apache.continuum.notification.mail.MockJavaMailSender</implementation>
       <role-hint>continuum</role-hint>
-    </component>    
+    </component>
 
     <component>
       <role>org.apache.maven.continuum.notification.Notifier</role>
@@ -59,7 +59,7 @@
         <fromMailbox>continuum@localhost</fromMailbox>
         <fromName>Continuum</fromName>
         <timestampFormat>EEE, d MMM yyyy HH:mm:ss Z</timestampFormat>
-        <includeBuildResult>true</includeBuildResult>
+        <includeBuildOutput>true</includeBuildOutput>
         <toOverride>nobody@localhost</toOverride>
       </configuration>
     </component>
diff --git a/continuum-core/src/test/resources/org/apache/maven/continuum/notification/mail/MailContinuumNotifierTest.xml b/continuum-core/src/test/resources/org/apache/maven/continuum/notification/mail/MailContinuumNotifierTest.xml
index 2538d6e..31209f4 100644
--- a/continuum-core/src/test/resources/org/apache/maven/continuum/notification/mail/MailContinuumNotifierTest.xml
+++ b/continuum-core/src/test/resources/org/apache/maven/continuum/notification/mail/MailContinuumNotifierTest.xml
@@ -55,13 +55,13 @@
           <role>org.apache.maven.continuum.reports.surefire.ReportTestSuiteGenerator</role>
           <field-name>reportTestSuiteGenerator</field-name>
           <role-hint>default</role-hint>
-        </requirement>         
+        </requirement>
       </requirements>
       <configuration>
         <fromMailbox>continuum@localhost</fromMailbox>
         <fromName>Continuum</fromName>
         <timestampFormat>EEE, d MMM yyyy HH:mm:ss Z</timestampFormat>
-        <includeBuildResult>true</includeBuildResult>
+        <includeBuildOutput>true</includeBuildOutput>
       </configuration>
     </component>
 
diff --git a/continuum-core/src/test/resources/plexus.xml b/continuum-core/src/test/resources/plexus.xml
deleted file mode 100755
index 4c70ff6..0000000
--- a/continuum-core/src/test/resources/plexus.xml
+++ /dev/null
@@ -1,115 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!--
-  ~ 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.
-  -->
-<plexus>
-  <components>
-
-    <!--
-     | Logger manager
-     -->
-    <component>
-      <role>org.codehaus.plexus.logging.LoggerManager</role>
-      <implementation>org.codehaus.plexus.logging.log4j.Log4JLoggerManager</implementation>
-      <lifecycle-handler>basic</lifecycle-handler>
-
-      <configuration>
-        <threshold>INFO</threshold>
-        <default-appender>console</default-appender>
-
-        <appenders>
-          <appender>
-            <id>console</id>
-            <type>org.apache.log4j.ConsoleAppender</type>
-            <conversion-pattern>%d [%t] %-5p %c - %m%n</conversion-pattern>
-          </appender>
-        </appenders>
-
-        <levels>
-          <!-- Help identify bugs during testing -->
-          <level>
-            <hierarchy>org.apache.maven.continuum</hierarchy>
-            <level>DEBUG</level>
-          </level>
-          <level>
-            <hierarchy>org.apache.maven</hierarchy>
-            <level>INFO</level>
-          </level>
-          <level>
-            <hierarchy>org.apache.maven.continuum.project.builder.maven.MavenTwoContinuumProjectBuilder:maven-two-builder</hierarchy>
-            <level>DEBUG</level>
-          </level>          
-          <level>
-            <hierarchy>org.codehaus.plexus.redback</hierarchy>
-            <level>INFO</level>
-          </level>
-          <!-- squelch noisy objects (for now) -->
-          <level>
-            <hierarchy>org.codehaus.plexus.mailsender.MailSender</hierarchy>
-            <level>INFO</level>
-          </level>
-          <level>
-            <hierarchy>org.quartz</hierarchy>
-            <level>INFO</level>
-          </level>
-          <level>
-            <hierarchy>org.apache.jasper</hierarchy>
-            <level>INFO</level>
-          </level>
-          <level>
-            <hierarchy>com.opensymphony.xwork</hierarchy>
-            <level>INFO</level>
-          </level>
-          <level>
-            <!-- CONTINUUM-1228 -->
-            <hierarchy>com.opensymphony.xwork2.util.OgnlUtil</hierarchy>
-            <level>ERROR</level>
-          </level>
-          <level>
-            <hierarchy>org.codehaus.plexus.PlexusContainer</hierarchy>
-            <level>INFO</level>
-          </level>
-          <level>
-            <hierarchy>JPOX</hierarchy>
-            <level>WARN</level>
-          </level>
-          <level>
-            <hierarchy>JPOX.MetaData</hierarchy>
-            <level>ERROR</level>
-          </level>
-          <level>
-            <hierarchy>JPOX.RDBMS.SQL</hierarchy>
-            <level>ERROR</level>
-          </level>
-          <level>
-            <hierarchy>SQL</hierarchy>
-            <level>ERROR</level>
-          </level>
-          <level>
-            <hierarchy>freemarker</hierarchy>
-            <level>WARN</level>
-          </level>
-          <level>
-            <hierarchy>org.codehaus.plexus.component.manager.ClassicSingletonComponentManager</hierarchy>
-            <level>ERROR</level>
-          </level>
-        </levels>
-      </configuration>
-    </component>    
-  </components>
-</plexus>
\ No newline at end of file
diff --git a/continuum-data-management/continuum-legacy/pom.xml b/continuum-data-management/continuum-legacy/pom.xml
index 649b2d5..babeca5 100644
--- a/continuum-data-management/continuum-legacy/pom.xml
+++ b/continuum-data-management/continuum-legacy/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <artifactId>continuum-data-management</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>continuum-legacy</artifactId>
@@ -36,42 +36,24 @@
           <execution>
             <id>modello-continuum-metadata</id>
             <goals>
-              <goal>jpox-metadata-class</goal>
               <goal>java</goal>
               <goal>stax-reader</goal>
               <goal>stax-writer</goal>
             </goals>
           </execution>
-          <execution>
-            <id>jpox-jdo-mapping</id>
-            <goals>
-              <goal>jpox-jdo-mapping</goal>
-            </goals>
-            <configuration>
-              <outputDirectory>${basedir}/target/classes/META-INF</outputDirectory>
-            </configuration>
-          </execution>
-          <execution>
-            <id>jpox-jdo-mapping-replication</id>
-            <goals>
-              <goal>jpox-jdo-mapping</goal>
-            </goals>
-            <configuration>
-              <outputDirectory>${basedir}/target/classes/META-INF</outputDirectory>
-              <replicationParameters>true</replicationParameters>
-            </configuration>
-          </execution>
         </executions>
         <configuration>
           <version>1.0.9</version>
           <packageWithVersion>true</packageWithVersion>
-          <model>src/main/mdo/continuum.xml</model>
+          <models>
+            <model>src/main/mdo/continuum.xml</model>
+          </models>
+          <useJava5>true</useJava5>
         </configuration>
       </plugin>
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>jpox-maven-plugin</artifactId>
-        <version>1.1.6</version>
         <executions>
           <execution>
             <goals>
@@ -84,31 +66,10 @@
         <artifactId>maven-antrun-plugin</artifactId>
         <executions>
           <execution>
-            <id>hack-sources</id>
-            <phase>process-sources</phase>
-            <configuration>
-              <tasks>
-                <!-- Workaround for MODELLO-89 -->
-                <replace file="target/generated-sources/modello/org/apache/maven/continuum/model/project/v1_0_9/ContinuumModelloMetadata.java" token="project;" value="project.v1_0_9;" />
-              </tasks>
-            </configuration>
-            <goals>
-              <goal>run</goal>
-            </goals>
-          </execution>
-          <execution>
             <id>hack-resources</id>
             <phase>process-classes</phase>
             <configuration>
               <tasks>
-                <!-- Workaround for MODELLO-91 -->
-                <replace dir="target/classes/META-INF" token="name=&quot;notifiertype&quot;" value="name=&quot;type&quot;" />
-                <replace dir="target/classes/META-INF" token="name=&quot;resultstate&quot;" value="name=&quot;state&quot;" />
-                <replace dir="target/classes/META-INF" token="name=&quot;resulttrigger&quot;" value="name=&quot;trigger&quot;" />
-                <replace dir="target/classes/META-INF" token="name=&quot;projectstate&quot;" value="name=&quot;state&quot;" />
-                <replace dir="target/classes/META-INF" token="name=&quot;changecomment&quot;" value="name=&quot;comment&quot;" />
-                <replace dir="target/classes/META-INF" token="name=&quot;changedate&quot;" value="name=&quot;date&quot;" />
-                <replace dir="target/classes/META-INF" token="name=&quot;scheduledelay&quot;" value="name=&quot;delay&quot;" />
                 <move file="target/classes/META-INF/package.jdorepl" tofile="target/classes/META-INF/package.jdorepl109" />
                 <move file="target/classes/META-INF/package.jdo" tofile="target/classes/META-INF/package.jdo109" />
                 <delete file="target/classes/package.jdo" />
@@ -119,6 +80,40 @@
               <goal>run</goal>
             </goals>
           </execution>
+          <execution>
+            <id>copy-resources</id>
+            <!-- Need to perform the workaround for MODELLO-91 first -->
+            <phase>process-classes</phase>
+            <configuration>
+              <tasks>
+                <copy file="target/classes/META-INF/package.jdorepl109" todir="target/classes" />
+                <copy file="target/classes/META-INF/package.jdo109" todir="target/classes" />
+              </tasks>
+            </configuration>
+            <goals>
+              <goal>run</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>com.google.code.maven-replacer-plugin</groupId>
+        <artifactId>replacer</artifactId>
+        <executions>
+          <execution>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>replace</goal>
+            </goals>
+            <configuration>
+              <basedir>${basedir}</basedir>
+              <includes>
+                <include>target/generated-sources/**</include>
+              </includes>
+              <token>Generated by Modello.*</token>
+              <value>Generated by Modello</value>
+            </configuration>
+          </execution>
         </executions>
       </plugin>
     </plugins>
@@ -127,13 +122,6 @@
     <dependency>
       <groupId>net.java.dev.stax-utils</groupId>
       <artifactId>stax-utils</artifactId>
-      <version>20060502</version>
-      <exclusions>
-        <exclusion>
-          <groupId>com.bea.xml</groupId>
-          <artifactId>jsr173-ri</artifactId>
-        </exclusion>
-      </exclusions>
     </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
@@ -142,7 +130,6 @@
     <dependency>
       <groupId>stax</groupId>
       <artifactId>stax-api</artifactId>
-      <version>1.0.1</version>
     </dependency>
   </dependencies>
 </project>
diff --git a/continuum-data-management/continuum-legacy/src/main/java/org/apache/maven/continuum/model/project/v1_0_9/ContinuumModelloMetadata.java b/continuum-data-management/continuum-legacy/src/main/java/org/apache/maven/continuum/model/project/v1_0_9/ContinuumModelloMetadata.java
new file mode 100644
index 0000000..3f75506
--- /dev/null
+++ b/continuum-data-management/continuum-legacy/src/main/java/org/apache/maven/continuum/model/project/v1_0_9/ContinuumModelloMetadata.java
@@ -0,0 +1,35 @@
+package org.apache.maven.continuum.model.project.v1_0_9;
+
+/*
+ * 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.
+ */
+
+public class ContinuumModelloMetadata
+{
+    private String modelVersion;
+
+    public String getModelVersion()
+    {
+        return modelVersion;
+    }
+
+    public void setModelVersion( String modelVersion )
+    {
+        this.modelVersion = modelVersion;
+    }
+}
diff --git a/continuum-data-management/continuum-legacy/src/main/mdo/continuum.xml b/continuum-data-management/continuum-legacy/src/main/mdo/continuum.xml
index f6eba0a..4bc2b68 100644
--- a/continuum-data-management/continuum-legacy/src/main/mdo/continuum.xml
+++ b/continuum-data-management/continuum-legacy/src/main/mdo/continuum.xml
@@ -504,6 +504,11 @@
           <version>1.0.9</version>
           <type>int</type>
         </field>
+        <field>
+          <name>username</name>
+          <version>1.0.9+</version>
+          <type>String</type>
+        </field>
         <field jpox.column="resultstate">
           <name>state</name>
           <version>1.1.0+</version>
@@ -895,7 +900,7 @@
           <name>type</name>
           <version>1.1.0+</version>
           <type>String</type>
-          <description>type of the buid defintion</description>          
+          <description>type of the buid defintion</description>
         </field>
         <field>
           <name>schedule</name>
@@ -934,7 +939,7 @@
           <description>
             true if this buildDefinition is a template
           </description>
-        </field>        
+        </field>
       </fields>
     </class>
     <class>
@@ -967,8 +972,8 @@
           <name>type</name>
           <version>1.1.0+</version>
           <type>String</type>
-          <description>type of the buid BuildDefinitionTemplate use for default</description>          
-        </field>                                
+          <description>type of the buid BuildDefinitionTemplate use for default</description>
+        </field>
         <field xml.reference="true" stash.part="true" jpox.fetch-groups="build-template-build-definitions">
           <name>buildDefinitions</name>
           <version>1.1.0+</version>
@@ -1245,8 +1250,8 @@
       </fields>
       <codeSegments>
         <codeSegment>
-           <version>1.1.0+</version>
-           <code><![CDATA[
+          <version>1.1.0+</version>
+          <code><![CDATA[
     public final static int NEW = 1;
     public final static int OK = 2;
     public final static int FAILED = 3;
diff --git a/continuum-data-management/continuum-legacy/src/main/resources/META-INF/package.jdo b/continuum-data-management/continuum-legacy/src/main/resources/META-INF/package.jdo
new file mode 100644
index 0000000..4d059fc
--- /dev/null
+++ b/continuum-data-management/continuum-legacy/src/main/resources/META-INF/package.jdo
@@ -0,0 +1,306 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ 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.
+  -->
+<!DOCTYPE jdo PUBLIC
+  "-//Sun Microsystems, Inc.//DTD Java Data Objects Metadata 2.0//EN"
+  "http://java.sun.com/dtd/jdo_2_0.dtd">
+
+<jdo>
+  <package name="org.apache.maven.continuum.model.project.v1_0_9">
+    <class name="ProjectGroup" detachable="true" table="ProjectGroup" identity-type="application" objectid-class="javax.jdo.identity.IntIdentity">
+      <field name="id" null-value="exception" primary-key="true" value-strategy="native"/>
+      <field name="groupId"/>
+      <field name="name"/>
+      <field name="description">
+        <column length="8192"/>
+      </field>
+      <field name="projects" mapped-by="projectGroup">
+        <collection element-type="Project" dependent-element="true"/>
+      </field>
+      <field name="notifiers">
+        <collection element-type="ProjectNotifier" dependent-element="true"/>
+        <join/>
+      </field>
+      <field name="buildDefinitions">
+        <collection element-type="BuildDefinition" dependent-element="true"/>
+        <join/>
+      </field>
+      <fetch-group name="ProjectGroup_detail">
+        <field name="projects"/>
+        <field name="notifiers"/>
+        <field name="buildDefinitions"/>
+      </fetch-group>
+      <fetch-group name="project-build-details">
+        <field name="projects"/>
+        <field name="notifiers"/>
+        <field name="buildDefinitions"/>
+      </fetch-group>
+      <fetch-group name="projectgroup-projects">
+        <field name="projects"/>
+      </fetch-group>
+    </class>
+    <class name="Project" detachable="true" table="Project" identity-type="application" objectid-class="javax.jdo.identity.IntIdentity">
+      <field name="id" null-value="exception" primary-key="true" value-strategy="native"/>
+      <field name="groupId"/>
+      <field name="artifactId"/>
+      <field name="executorId"/>
+      <field name="name"/>
+      <field name="description">
+        <column length="8192"/>
+      </field>
+      <field name="url">
+        <column length="256"/>
+      </field>
+      <field name="scmUrl">
+        <column length="256"/>
+      </field>
+      <field name="scmTag"/>
+      <field name="scmUsername"/>
+      <field name="scmPassword"/>
+      <field name="version"/>
+      <field name="state">
+        <column name="state"/>
+      </field>
+      <field name="oldState"/>
+      <field name="latestBuildId"/>
+      <field name="buildNumber"/>
+      <field name="workingDirectory">
+        <column length="256"/>
+      </field>
+      <field name="buildResults" mapped-by="project">
+        <collection element-type="BuildResult" dependent-element="true"/>
+      </field>
+      <field name="checkoutResult" dependent="true"/>
+      <field name="developers">
+        <collection element-type="ProjectDeveloper" dependent-element="true"/>
+      </field>
+      <field name="parent" dependent="true"/>
+      <field name="dependencies">
+        <collection element-type="ProjectDependency" dependent-element="true"/>
+      </field>
+      <field name="projectGroup" null-value="exception" default-fetch-group="true"/>
+      <field name="notifiers">
+        <collection element-type="ProjectNotifier" dependent-element="true"/>
+        <join/>
+      </field>
+      <field name="buildDefinitions">
+        <collection element-type="BuildDefinition" dependent-element="true"/>
+        <join/>
+      </field>
+      <fetch-group name="Project_detail">
+        <field name="buildResults"/>
+        <field name="checkoutResult"/>
+        <field name="developers"/>
+        <field name="parent"/>
+        <field name="dependencies"/>
+        <field name="notifiers"/>
+        <field name="buildDefinitions"/>
+      </fetch-group>
+      <fetch-group name="project-all-details">
+        <field name="developers"/>
+        <field name="parent"/>
+        <field name="dependencies"/>
+        <field name="notifiers"/>
+        <field name="buildDefinitions"/>
+      </fetch-group>
+      <fetch-group name="project-build-details">
+        <field name="notifiers"/>
+        <field name="buildDefinitions"/>
+      </fetch-group>
+      <fetch-group name="project-with-builds">
+        <field name="buildResults"/>
+      </fetch-group>
+      <fetch-group name="project-dependencies">
+        <field name="parent"/>
+        <field name="dependencies"/>
+      </fetch-group>
+      <fetch-group name="project-with-checkout-result">
+        <field name="checkoutResult"/>
+      </fetch-group>
+    </class>
+    <class name="ProjectNotifier" detachable="true" table="ProjectNotifier" identity-type="application" objectid-class="javax.jdo.identity.IntIdentity">
+      <field name="id" null-value="exception" primary-key="true" value-strategy="native"/>
+      <field name="type">
+        <column name="type"/>
+      </field>
+      <field name="from">
+        <column name="notifierorigin"/>
+      </field>
+      <field name="enabled"/>
+      <field name="recipientType"/>
+      <field name="sendOnSuccess"/>
+      <field name="sendOnFailure"/>
+      <field name="sendOnError"/>
+      <field name="sendOnWarning"/>
+      <field name="configuration" default-fetch-group="true">
+        <map key-type="java.lang.String" value-type="java.lang.String" dependent-key="true" dependent-value="true"/>
+        <join/>
+      </field>
+    </class>
+    <class name="ProjectDeveloper" detachable="true" table="ProjectDeveloper">
+      <field name="scmId"/>
+      <field name="name"/>
+      <field name="email"/>
+      <field name="continuumId"/>
+    </class>
+    <class name="ProjectDependency" detachable="true" table="ProjectDependency">
+      <field name="groupId"/>
+      <field name="artifactId"/>
+      <field name="version"/>
+    </class>
+    <class name="BuildResult" detachable="true" table="BuildResult" identity-type="application" objectid-class="javax.jdo.identity.IntIdentity">
+      <field name="project" default-fetch-group="true"/>
+      <field name="id" primary-key="true" value-strategy="native"/>
+      <field name="buildNumber"/>
+      <field name="state">
+        <column name="state"/>
+      </field>
+      <field name="trigger">
+        <column name="trigger"/>
+      </field>
+      <field name="startTime"/>
+      <field name="endTime"/>
+      <field name="error">
+        <column length="8192"/>
+      </field>
+      <field name="success"/>
+      <field name="exitCode"/>
+      <field name="scmResult" dependent="true"/>
+      <field name="testResult" dependent="true"/>
+      <fetch-group name="BuildResult_detail">
+        <field name="scmResult"/>
+        <field name="testResult"/>
+      </fetch-group>
+      <fetch-group name="build-result-with-details">
+        <field name="scmResult"/>
+        <field name="testResult"/>
+      </fetch-group>
+    </class>
+    <class name="BuildDefinition" detachable="true" table="BuildDefinition" identity-type="application" objectid-class="javax.jdo.identity.IntIdentity">
+      <field name="id" null-value="exception" primary-key="true" value-strategy="native"/>
+      <field name="defaultForProject"/>
+      <field name="goals"/>
+      <field name="arguments"/>
+      <field name="buildFile"/>
+      <field name="schedule" default-fetch-group="true"/>
+      <field name="latestBuildId" null-value="default">
+        <column default-value="0"/>
+      </field>
+    </class>
+    <class name="Schedule" detachable="true" table="Schedule" identity-type="application" objectid-class="javax.jdo.identity.IntIdentity">
+      <field name="id" primary-key="true" value-strategy="native"/>
+      <field name="active"/>
+      <field name="name"/>
+      <field name="description"/>
+      <field name="delay">
+        <column name="delay"/>
+      </field>
+      <field name="maxJobExecutionTime"/>
+      <field name="cronExpression"/>
+    </class>
+    <class name="ContinuumModelloMetadata" detachable="true">
+      <field name="modelVersion" null-value="default">
+        <column default-value="1.0.9"/>
+      </field>
+    </class>
+  </package>
+  <package name="org.apache.maven.continuum.model.scm.v1_0_9">
+    <class name="ScmResult" detachable="true" table="ScmResult">
+      <field name="success"/>
+      <field name="commandLine">
+        <column length="1024"/>
+      </field>
+      <field name="providerMessage">
+        <column length="1024"/>
+      </field>
+      <field name="commandOutput">
+        <column length="1024"/>
+      </field>
+      <field name="exception">
+        <column name="exceptionstring" length="8192"/>
+      </field>
+      <field name="changes" default-fetch-group="true">
+        <collection element-type="ChangeSet" dependent-element="true"/>
+      </field>
+    </class>
+    <class name="ChangeSet" detachable="true" table="ChangeSet">
+      <field name="author"/>
+      <field name="comment">
+        <column name="comment" length="8192"/>
+      </field>
+      <field name="date">
+        <column name="date"/>
+      </field>
+      <field name="files" default-fetch-group="true">
+        <collection element-type="ChangeFile" dependent-element="true"/>
+      </field>
+    </class>
+    <class name="ChangeFile" detachable="true" table="ChangeFile">
+      <field name="name"/>
+      <field name="revision"/>
+      <field name="status"/>
+    </class>
+    <class name="TestResult" detachable="true" table="TestResult">
+      <field name="testCount"/>
+      <field name="failureCount"/>
+      <field name="totalTime"/>
+      <field name="suiteResults" default-fetch-group="true">
+        <collection element-type="SuiteResult" dependent-element="true"/>
+      </field>
+    </class>
+    <class name="SuiteResult" detachable="true" table="SuiteResult">
+      <field name="name"/>
+      <field name="testCount"/>
+      <field name="failureCount"/>
+      <field name="totalTime"/>
+      <field name="failures" default-fetch-group="true">
+        <collection element-type="TestCaseFailure" dependent-element="true"/>
+      </field>
+    </class>
+    <class name="TestCaseFailure" detachable="true" table="TestCaseFailure">
+      <field name="name"/>
+      <field name="exception">
+        <column name="exceptionstring" length="8192"/>
+      </field>
+    </class>
+  </package>
+  <package name="org.apache.maven.continuum.model.system.v1_0_9">
+    <class name="SystemConfiguration" detachable="true" table="SystemConfiguration">
+      <field name="guestAccountEnabled"/>
+      <field name="defaultScheduleDescription"/>
+      <field name="defaultScheduleCronExpression"/>
+      <field name="workingDirectory"/>
+      <field name="buildOutputDirectory"/>
+      <field name="deploymentRepositoryDirectory"/>
+      <field name="baseUrl"/>
+      <field name="initialized"/>
+    </class>
+    <class name="NotificationAddress" detachable="true" table="NotificationAddress">
+      <field name="type">
+        <column name="type"/>
+      </field>
+      <field name="address"/>
+      <field name="configuration" default-fetch-group="true">
+        <map key-type="java.lang.String" value-type="java.lang.String" dependent-key="true" dependent-value="true"/>
+        <join/>
+      </field>
+    </class>
+  </package>
+</jdo>
diff --git a/continuum-data-management/continuum-legacy/src/main/resources/META-INF/package.jdorepl b/continuum-data-management/continuum-legacy/src/main/resources/META-INF/package.jdorepl
new file mode 100644
index 0000000..b24ac8d
--- /dev/null
+++ b/continuum-data-management/continuum-legacy/src/main/resources/META-INF/package.jdorepl
@@ -0,0 +1,306 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ 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.
+  -->
+<!DOCTYPE jdo PUBLIC
+  "-//Sun Microsystems, Inc.//DTD Java Data Objects Metadata 2.0//EN"
+  "http://java.sun.com/dtd/jdo_2_0.dtd">
+
+<jdo>
+  <package name="org.apache.maven.continuum.model.project.v1_0_9">
+    <class name="ProjectGroup" detachable="true" table="ProjectGroup" identity-type="application">
+      <field name="id" null-value="exception" primary-key="true"/>
+      <field name="groupId"/>
+      <field name="name"/>
+      <field name="description">
+        <column length="8192"/>
+      </field>
+      <field name="projects" mapped-by="projectGroup">
+        <collection element-type="Project" dependent-element="true"/>
+      </field>
+      <field name="notifiers">
+        <collection element-type="ProjectNotifier" dependent-element="true"/>
+        <join/>
+      </field>
+      <field name="buildDefinitions">
+        <collection element-type="BuildDefinition" dependent-element="true"/>
+        <join/>
+      </field>
+      <fetch-group name="ProjectGroup_detail">
+        <field name="projects"/>
+        <field name="notifiers"/>
+        <field name="buildDefinitions"/>
+      </fetch-group>
+      <fetch-group name="project-build-details">
+        <field name="projects"/>
+        <field name="notifiers"/>
+        <field name="buildDefinitions"/>
+      </fetch-group>
+      <fetch-group name="projectgroup-projects">
+        <field name="projects"/>
+      </fetch-group>
+    </class>
+    <class name="Project" detachable="true" table="Project" identity-type="application">
+      <field name="id" null-value="exception" primary-key="true"/>
+      <field name="groupId"/>
+      <field name="artifactId"/>
+      <field name="executorId"/>
+      <field name="name"/>
+      <field name="description">
+        <column length="8192"/>
+      </field>
+      <field name="url">
+        <column length="256"/>
+      </field>
+      <field name="scmUrl">
+        <column length="256"/>
+      </field>
+      <field name="scmTag"/>
+      <field name="scmUsername"/>
+      <field name="scmPassword"/>
+      <field name="version"/>
+      <field name="state">
+        <column name="state"/>
+      </field>
+      <field name="oldState"/>
+      <field name="latestBuildId"/>
+      <field name="buildNumber"/>
+      <field name="workingDirectory">
+        <column length="256"/>
+      </field>
+      <field name="buildResults" mapped-by="project">
+        <collection element-type="BuildResult" dependent-element="true"/>
+      </field>
+      <field name="checkoutResult" dependent="true"/>
+      <field name="developers">
+        <collection element-type="ProjectDeveloper" dependent-element="true"/>
+      </field>
+      <field name="parent" dependent="true"/>
+      <field name="dependencies">
+        <collection element-type="ProjectDependency" dependent-element="true"/>
+      </field>
+      <field name="projectGroup" null-value="exception" default-fetch-group="true"/>
+      <field name="notifiers">
+        <collection element-type="ProjectNotifier" dependent-element="true"/>
+        <join/>
+      </field>
+      <field name="buildDefinitions">
+        <collection element-type="BuildDefinition" dependent-element="true"/>
+        <join/>
+      </field>
+      <fetch-group name="Project_detail">
+        <field name="buildResults"/>
+        <field name="checkoutResult"/>
+        <field name="developers"/>
+        <field name="parent"/>
+        <field name="dependencies"/>
+        <field name="notifiers"/>
+        <field name="buildDefinitions"/>
+      </fetch-group>
+      <fetch-group name="project-all-details">
+        <field name="developers"/>
+        <field name="parent"/>
+        <field name="dependencies"/>
+        <field name="notifiers"/>
+        <field name="buildDefinitions"/>
+      </fetch-group>
+      <fetch-group name="project-build-details">
+        <field name="notifiers"/>
+        <field name="buildDefinitions"/>
+      </fetch-group>
+      <fetch-group name="project-with-builds">
+        <field name="buildResults"/>
+      </fetch-group>
+      <fetch-group name="project-dependencies">
+        <field name="parent"/>
+        <field name="dependencies"/>
+      </fetch-group>
+      <fetch-group name="project-with-checkout-result">
+        <field name="checkoutResult"/>
+      </fetch-group>
+    </class>
+    <class name="ProjectNotifier" detachable="true" table="ProjectNotifier" identity-type="application">
+      <field name="id" null-value="exception" primary-key="true"/>
+      <field name="type">
+        <column name="type"/>
+      </field>
+      <field name="from">
+        <column name="notifierorigin"/>
+      </field>
+      <field name="enabled"/>
+      <field name="recipientType"/>
+      <field name="sendOnSuccess"/>
+      <field name="sendOnFailure"/>
+      <field name="sendOnError"/>
+      <field name="sendOnWarning"/>
+      <field name="configuration" default-fetch-group="true">
+        <map key-type="java.lang.String" value-type="java.lang.String" dependent-key="true" dependent-value="true"/>
+        <join/>
+      </field>
+    </class>
+    <class name="ProjectDeveloper" detachable="true" table="ProjectDeveloper">
+      <field name="scmId"/>
+      <field name="name"/>
+      <field name="email"/>
+      <field name="continuumId"/>
+    </class>
+    <class name="ProjectDependency" detachable="true" table="ProjectDependency">
+      <field name="groupId"/>
+      <field name="artifactId"/>
+      <field name="version"/>
+    </class>
+    <class name="BuildResult" detachable="true" table="BuildResult" identity-type="application">
+      <field name="project" default-fetch-group="true"/>
+      <field name="id" primary-key="true"/>
+      <field name="buildNumber"/>
+      <field name="state">
+        <column name="state"/>
+      </field>
+      <field name="trigger">
+        <column name="trigger"/>
+      </field>
+      <field name="startTime"/>
+      <field name="endTime"/>
+      <field name="error">
+        <column length="8192"/>
+      </field>
+      <field name="success"/>
+      <field name="exitCode"/>
+      <field name="scmResult" dependent="true"/>
+      <field name="testResult" dependent="true"/>
+      <fetch-group name="BuildResult_detail">
+        <field name="scmResult"/>
+        <field name="testResult"/>
+      </fetch-group>
+      <fetch-group name="build-result-with-details">
+        <field name="scmResult"/>
+        <field name="testResult"/>
+      </fetch-group>
+    </class>
+    <class name="BuildDefinition" detachable="true" table="BuildDefinition" identity-type="application">
+      <field name="id" null-value="exception" primary-key="true"/>
+      <field name="defaultForProject"/>
+      <field name="goals"/>
+      <field name="arguments"/>
+      <field name="buildFile"/>
+      <field name="schedule" default-fetch-group="true"/>
+      <field name="latestBuildId" null-value="default">
+        <column default-value="0"/>
+      </field>
+    </class>
+    <class name="Schedule" detachable="true" table="Schedule" identity-type="application">
+      <field name="id" primary-key="true"/>
+      <field name="active"/>
+      <field name="name"/>
+      <field name="description"/>
+      <field name="delay">
+        <column name="delay"/>
+      </field>
+      <field name="maxJobExecutionTime"/>
+      <field name="cronExpression"/>
+    </class>
+    <class name="ContinuumModelloMetadata" detachable="true">
+      <field name="modelVersion" null-value="default">
+        <column default-value="1.0.9"/>
+      </field>
+    </class>
+  </package>
+  <package name="org.apache.maven.continuum.model.scm.v1_0_9">
+    <class name="ScmResult" detachable="true" table="ScmResult">
+      <field name="success"/>
+      <field name="commandLine">
+        <column length="1024"/>
+      </field>
+      <field name="providerMessage">
+        <column length="1024"/>
+      </field>
+      <field name="commandOutput">
+        <column length="1024"/>
+      </field>
+      <field name="exception">
+        <column name="exceptionstring" length="8192"/>
+      </field>
+      <field name="changes" default-fetch-group="true">
+        <collection element-type="ChangeSet" dependent-element="true"/>
+      </field>
+    </class>
+    <class name="ChangeSet" detachable="true" table="ChangeSet">
+      <field name="author"/>
+      <field name="comment">
+        <column name="comment" length="8192"/>
+      </field>
+      <field name="date">
+        <column name="date"/>
+      </field>
+      <field name="files" default-fetch-group="true">
+        <collection element-type="ChangeFile" dependent-element="true"/>
+      </field>
+    </class>
+    <class name="ChangeFile" detachable="true" table="ChangeFile">
+      <field name="name"/>
+      <field name="revision"/>
+      <field name="status"/>
+    </class>
+    <class name="TestResult" detachable="true" table="TestResult">
+      <field name="testCount"/>
+      <field name="failureCount"/>
+      <field name="totalTime"/>
+      <field name="suiteResults" default-fetch-group="true">
+        <collection element-type="SuiteResult" dependent-element="true"/>
+      </field>
+    </class>
+    <class name="SuiteResult" detachable="true" table="SuiteResult">
+      <field name="name"/>
+      <field name="testCount"/>
+      <field name="failureCount"/>
+      <field name="totalTime"/>
+      <field name="failures" default-fetch-group="true">
+        <collection element-type="TestCaseFailure" dependent-element="true"/>
+      </field>
+    </class>
+    <class name="TestCaseFailure" detachable="true" table="TestCaseFailure">
+      <field name="name"/>
+      <field name="exception">
+        <column name="exceptionstring" length="8192"/>
+      </field>
+    </class>
+  </package>
+  <package name="org.apache.maven.continuum.model.system.v1_0_9">
+    <class name="SystemConfiguration" detachable="true" table="SystemConfiguration">
+      <field name="guestAccountEnabled"/>
+      <field name="defaultScheduleDescription"/>
+      <field name="defaultScheduleCronExpression"/>
+      <field name="workingDirectory"/>
+      <field name="buildOutputDirectory"/>
+      <field name="deploymentRepositoryDirectory"/>
+      <field name="baseUrl"/>
+      <field name="initialized"/>
+    </class>
+    <class name="NotificationAddress" detachable="true" table="NotificationAddress">
+      <field name="type">
+        <column name="type"/>
+      </field>
+      <field name="address"/>
+      <field name="configuration" default-fetch-group="true">
+        <map key-type="java.lang.String" value-type="java.lang.String" dependent-key="true" dependent-value="true"/>
+        <join/>
+      </field>
+    </class>
+  </package>
+</jdo>
diff --git a/continuum-data-management/data-management-api/pom.xml b/continuum-data-management/data-management-api/pom.xml
index 7dcaaf8..c77a782 100644
--- a/continuum-data-management/data-management-api/pom.xml
+++ b/continuum-data-management/data-management-api/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <artifactId>continuum-data-management</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>data-management-api</artifactId>
diff --git a/continuum-data-management/data-management-api/src/main/java/org/apache/maven/continuum/management/DataManagementException.java b/continuum-data-management/data-management-api/src/main/java/org/apache/maven/continuum/management/DataManagementException.java
index 87d2aa1..48fa6c3 100644
--- a/continuum-data-management/data-management-api/src/main/java/org/apache/maven/continuum/management/DataManagementException.java
+++ b/continuum-data-management/data-management-api/src/main/java/org/apache/maven/continuum/management/DataManagementException.java
@@ -21,6 +21,7 @@
 
 /**
  * Exception wrapper for application errors that can't be recovered from.
+ *
  * @version $Id$
  */
 public class DataManagementException
diff --git a/continuum-data-management/data-management-api/src/main/java/org/apache/maven/continuum/management/DataManagementTool.java b/continuum-data-management/data-management-api/src/main/java/org/apache/maven/continuum/management/DataManagementTool.java
index 6f3b8b2..b9e7d79 100644
--- a/continuum-data-management/data-management-api/src/main/java/org/apache/maven/continuum/management/DataManagementTool.java
+++ b/continuum-data-management/data-management-api/src/main/java/org/apache/maven/continuum/management/DataManagementTool.java
@@ -24,6 +24,7 @@
 
 /**
  * Delegate to the correct data management tool.
+ *
  * @version $Id$
  */
 public interface DataManagementTool
@@ -42,10 +43,11 @@
      * Restore the database.
      *
      * @param backupDirectory the directory where the backup to restore from resides
+     * @param strict
      * @throws java.io.IOException     if there is a problem reading the backup file
      * @throws DataManagementException if there is a problem parsing the backup file
      */
-    void restoreDatabase( File backupDirectory )
+    void restoreDatabase( File backupDirectory, boolean strict )
         throws IOException, DataManagementException;
 
     /**
diff --git a/continuum-data-management/data-management-api/src/main/java/org/apache/maven/continuum/management/DatabaseFactoryConfigurator.java b/continuum-data-management/data-management-api/src/main/java/org/apache/maven/continuum/management/DatabaseFactoryConfigurator.java
index 2f499e1..3a2c5a8 100644
--- a/continuum-data-management/data-management-api/src/main/java/org/apache/maven/continuum/management/DatabaseFactoryConfigurator.java
+++ b/continuum-data-management/data-management-api/src/main/java/org/apache/maven/continuum/management/DatabaseFactoryConfigurator.java
@@ -20,7 +20,6 @@
  */
 
 /**
- * 
  * @version $Id$
  */
 public interface DatabaseFactoryConfigurator
diff --git a/continuum-data-management/data-management-api/src/main/java/org/apache/maven/continuum/management/DatabaseParams.java b/continuum-data-management/data-management-api/src/main/java/org/apache/maven/continuum/management/DatabaseParams.java
index 98d0e04..191b014 100644
--- a/continuum-data-management/data-management-api/src/main/java/org/apache/maven/continuum/management/DatabaseParams.java
+++ b/continuum-data-management/data-management-api/src/main/java/org/apache/maven/continuum/management/DatabaseParams.java
@@ -23,6 +23,7 @@
 
 /**
  * Bean for storing database parameters.
+ *
  * @version $Id$
  */
 public class DatabaseParams
diff --git a/continuum-data-management/data-management-cli/pom.xml b/continuum-data-management/data-management-cli/pom.xml
index 771e8b8..548cb47 100644
--- a/continuum-data-management/data-management-cli/pom.xml
+++ b/continuum-data-management/data-management-cli/pom.xml
@@ -22,116 +22,144 @@
   <parent>
     <artifactId>continuum-data-management</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>data-management-cli</artifactId>
   <name>Continuum :: Data Management :: CLI</name>
   <dependencies>
     <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-container-default</artifactId>
-      <version>1.0-alpha-20</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven</groupId>
-      <artifactId>maven-project</artifactId>
-    </dependency>
-    <dependency>
       <groupId>org.apache.continuum</groupId>
       <artifactId>data-management-api</artifactId>
     </dependency>
     <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>data-management-jdo</artifactId>
-      <!-- Ensures correct build order -->
-      <scope>provided</scope>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-artifact</artifactId>
     </dependency>
+    <!-- start - order matters, requires maven 2.0.9+ -->
     <dependency>
       <groupId>org.apache.continuum</groupId>
-      <artifactId>data-management-redback-jdo</artifactId>
-      <!-- Ensures correct build order -->
-      <scope>provided</scope>
+      <artifactId>continuum-artifact-manager</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-artifact-manager</artifactId>
+    </dependency>
+    <!-- end - order matters -->
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-settings</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-project</artifactId>
+      <scope>runtime</scope>
     </dependency>
     <dependency>
       <groupId>com.google.code.cli-parser</groupId>
       <artifactId>cli</artifactId>
-      <version>7</version>
     </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-jdo2</artifactId>
+      <artifactId>plexus-utils</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-component-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-slf4j-logging</artifactId>
+      <scope>runtime</scope>
     </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-log4j12</artifactId>
-    </dependency>      
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>jcl-over-slf4j</artifactId>
+      <scope>runtime</scope>
+    </dependency>
     <dependency>
       <groupId>log4j</groupId>
       <artifactId>log4j</artifactId>
     </dependency>
-
+    <dependency>
+      <groupId>org.apache.maven.wagon</groupId>
+      <artifactId>wagon-provider-api</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.apache.maven.wagon</groupId>
       <artifactId>wagon-http-lightweight</artifactId>
       <scope>runtime</scope>
     </dependency>
     <dependency>
-      <groupId>stax</groupId>
-      <artifactId>stax</artifactId>
-      <version>1.1.1-dev</version>
-      <scope>runtime</scope>
-      <exclusions>
-        <exclusion>
-          <groupId>xmlbeans</groupId>
-          <artifactId>xmlbeans-jsr173-api</artifactId>
-        </exclusion>
-      </exclusions>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>plexus-spring</artifactId>
     </dependency>
     <dependency>
-      <groupId>stax</groupId>
-      <artifactId>stax-api</artifactId>
-      <version>1.0.1</version>
-      <scope>runtime</scope>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-context</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-beans</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
     </dependency>
   </dependencies>
   <build>
     <plugins>
-      <!-- TODO: shade it instead, not currently working with this
-        <plugin>
-          <artifactId>shade-maven-plugin</artifactId>
-          <groupId>org.codehaus.mojo</groupId>
-          <version>1.0-alpha-7</version>
-          <executions>
-            <execution>
-              <goals>
-                <goal>shade</goal>
-              </goals>
-            </execution>
-          </executions>
-        </plugin>
-      -->
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-assembly-plugin</artifactId>
-        <version>2.1</version>
-        <configuration>
-          <descriptor>src/assembly/app.xml</descriptor>
-          <archive>
-            <manifest>
-              <mainClass>org.apache.continuum.management.DataManagementCli</mainClass>
-            </manifest>
-          </archive>
-        </configuration>
+        <artifactId>maven-shade-plugin</artifactId>
         <executions>
           <execution>
             <phase>package</phase>
             <goals>
-              <goal>single</goal>
+              <goal>shade</goal>
             </goals>
+            <configuration>
+              <shadedArtifactAttached>true</shadedArtifactAttached>
+              <shadedClassifierName>app</shadedClassifierName>
+              <transformers>
+                <transformer implementation="org.apache.maven.plugins.shade.resource.ComponentsXmlResourceTransformer" />
+                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                  <resource>META-INF/spring.handlers</resource>
+                </transformer>
+                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                  <resource>META-INF/spring.schemas</resource>
+                </transformer>
+              </transformers>
+              <artifactSet>
+                <excludes>
+                  <exclude>xml-apis:xml-apis</exclude>
+                </excludes>
+              </artifactSet>
+            </configuration>
           </execution>
         </executions>
       </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <version>2.1</version>
+        <configuration>
+          <archive>
+            <manifest>
+              <mainClass>org.apache.maven.continuum.management.DataManagementCli</mainClass>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
     </plugins>
   </build>
 </project>
diff --git a/continuum-data-management/data-management-cli/src/main/java/org/apache/maven/continuum/management/DataManagementCli.java b/continuum-data-management/data-management-cli/src/main/java/org/apache/maven/continuum/management/DataManagementCli.java
index 0739124..421493e 100644
--- a/continuum-data-management/data-management-cli/src/main/java/org/apache/maven/continuum/management/DataManagementCli.java
+++ b/continuum-data-management/data-management-cli/src/main/java/org/apache/maven/continuum/management/DataManagementCli.java
@@ -36,8 +36,11 @@
 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
 import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
 import org.apache.maven.artifact.resolver.ArtifactResolver;
+import org.apache.maven.artifact.resolver.DebugResolutionListener;
+import org.apache.maven.artifact.resolver.ResolutionListener;
 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
 import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter;
+import org.apache.maven.continuum.management.util.PlexusFileSystemXmlApplicationContext;
 import org.apache.maven.settings.MavenSettingsBuilder;
 import org.apache.maven.settings.Mirror;
 import org.apache.maven.settings.Profile;
@@ -46,12 +49,12 @@
 import org.apache.maven.settings.Server;
 import org.apache.maven.settings.Settings;
 import org.apache.maven.wagon.repository.RepositoryPermissions;
-import org.codehaus.plexus.DefaultPlexusContainer;
 import org.codehaus.plexus.PlexusContainer;
 import org.codehaus.plexus.PlexusContainerException;
-import org.codehaus.plexus.classworlds.realm.ClassRealm;
 import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+import org.codehaus.plexus.spring.PlexusClassPathXmlApplicationContext;
+import org.codehaus.plexus.spring.PlexusContainerAdapter;
 import org.codehaus.plexus.util.xml.Xpp3Dom;
 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
 
@@ -70,12 +73,21 @@
 /**
  * An application for performing database upgrades from old Continuum and Redback versions. A suitable tool until it
  * is natively incorporated into Continuum itself.
+ *
  * @version $Id$
  */
 public class DataManagementCli
 {
     private static final Logger LOGGER = Logger.getLogger( DataManagementCli.class );
 
+    private static final String JAR_FILE_PREFIX = "jar:file:";
+
+    private static final String FILE_PREFIX = "file:";
+
+    private static final String SPRING_CONTEXT_LOC = "!/**/META-INF/spring-context.xml";
+
+    private static final String PLEXUS_XML_LOC = "!/**/META-INF/plexus/components.xml";
+
     public static void main( String[] args )
         throws Exception
     {
@@ -162,26 +174,37 @@
         else
         {
             Logger.getRootLogger().setLevel( Level.INFO );
+            Logger.getLogger( "JPOX" ).setLevel( Level.WARN );
+        }
+
+        if ( command.settings != null && !command.settings.isFile() )
+        {
+            System.err.println( command.settings + " not exists or is not a file." );
+            Args.usage( command );
+            return;
         }
 
         if ( command.buildsJdbcUrl != null )
         {
             LOGGER.info( "Processing Continuum database..." );
             processDatabase( databaseType, databaseFormat, mode, command.buildsJdbcUrl, command.directory,
-                             databaseFormat.getContinuumToolRoleHint(), "data-management-jdo", "continuum" );
+                             command.settings, databaseFormat.getContinuumToolRoleHint(), "data-management-jdo",
+                             "continuum", command.strict );
         }
 
         if ( command.usersJdbcUrl != null )
         {
             LOGGER.info( "Processing Redback database..." );
             processDatabase( databaseType, databaseFormat, mode, command.usersJdbcUrl, command.directory,
-                             databaseFormat.getRedbackToolRoleHint(), "data-management-redback-jdo", "redback" );
+                             command.settings, databaseFormat.getRedbackToolRoleHint(), "data-management-redback-jdo",
+                             "redback", command.strict );
         }
     }
 
     private static void processDatabase( SupportedDatabase databaseType, DatabaseFormat databaseFormat,
-                                         OperationMode mode, String jdbcUrl, File directory, String toolRoleHint,
-                                         String managementArtifactId, String configRoleHint )
+                                         OperationMode mode, String jdbcUrl, File directory, File setting,
+                                         String toolRoleHint, String managementArtifactId, String configRoleHint,
+                                         boolean strict )
         throws PlexusContainerException, ComponentLookupException, ComponentLifecycleException,
         ArtifactNotFoundException, ArtifactResolutionException, IOException
     {
@@ -190,22 +213,29 @@
         DatabaseParams params = new DatabaseParams( databaseType.defaultParams );
         params.setUrl( jdbcUrl );
 
-        DefaultPlexusContainer container = new DefaultPlexusContainer();
+        PlexusClassPathXmlApplicationContext classPathApplicationContext = new PlexusClassPathXmlApplicationContext(
+            new String[]{"classpath*:/META-INF/spring-context.xml", "classpath*:/META-INF/plexus/components.xml",
+                "classpath*:/META-INF/plexus/plexus.xml"} );
 
-        initializeWagon( container );
+        PlexusContainerAdapter container = new PlexusContainerAdapter();
+        container.setApplicationContext( classPathApplicationContext );
+
+        initializeWagon( container, setting );
 
         List<Artifact> artifacts = new ArrayList<Artifact>();
-        artifacts.addAll(
-            downloadArtifact( container, params.getGroupId(), params.getArtifactId(), params.getVersion() ) );
-        artifacts.addAll(
-            downloadArtifact( container, "org.apache.maven.continuum", managementArtifactId, applicationVersion ) );
-        artifacts.addAll( downloadArtifact( container, "jpox", "jpox", databaseFormat.getJpoxVersion() ) );
+        artifacts.addAll( downloadArtifact( container, params.getGroupId(), params.getArtifactId(), params.getVersion(),
+                                            setting ) );
+        artifacts.addAll( downloadArtifact( container, "org.apache.continuum", managementArtifactId, applicationVersion,
+                                            setting ) );
+        artifacts.addAll( downloadArtifact( container, "jpox", "jpox", databaseFormat.getJpoxVersion(), setting ) );
 
-        List<File> jars = new ArrayList<File>();
+        List<String> jars = new ArrayList<String>();
 
         // Little hack to make it work more nicely in the IDE
         List<String> exclusions = new ArrayList<String>();
         URLClassLoader cp = (URLClassLoader) DataManagementCli.class.getClassLoader();
+        List<URL> jarUrls = new ArrayList<URL>();
+
         for ( URL url : cp.getURLs() )
         {
             String urlEF = url.toExternalForm();
@@ -218,17 +248,22 @@
                     !"continuum-legacy".equals( id ) && !"continuum-model".equals( id ) &&
                     !"redback-legacy".equals( id ) )
                 {
-                    exclusions.add( "org.apache.maven.continuum:" + id );
-                    jars.add( new File( url.getPath() ) );
+                    LOGGER.debug( "[IDE Help] Adding '" + id + "' as an exclusion and using one from classpath" );
+                    exclusions.add( "org.apache.continuum:" + id );
+                    jars.add( url.getPath() );
+                    jarUrls.add( url );
                 }
             }
 
             // Sometimes finds its way into the IDE. Make sure it is loaded in the extra classloader too
             if ( urlEF.contains( "jpox-enhancer" ) )
             {
-                jars.add( new File( url.getPath() ) );
+                LOGGER.debug( "[IDE Help] Adding 'jpox-enhancer' as an exclusion and using one from classpath" );
+                jars.add( url.getPath() );
+                jarUrls.add( url );
             }
         }
+
         ArtifactFilter filter = new ExcludesArtifactFilter( exclusions );
 
         for ( Artifact a : artifacts )
@@ -237,28 +272,36 @@
             {
                 if ( a.getVersion().equals( databaseFormat.getJpoxVersion() ) )
                 {
-                    jars.add( a.getFile() );
+                    LOGGER.debug( "Adding artifact: " + a.getFile() );
+                    jars.add( JAR_FILE_PREFIX + a.getFile().getAbsolutePath() + SPRING_CONTEXT_LOC );
+                    jars.add( JAR_FILE_PREFIX + a.getFile().getAbsolutePath() + PLEXUS_XML_LOC );
+                    jarUrls.add( new URL( FILE_PREFIX + a.getFile().getAbsolutePath() ) );
                 }
             }
             else if ( filter.include( a ) )
             {
-                jars.add( a.getFile() );
+                LOGGER.debug( "Adding artifact: " + a.getFile() );
+                jars.add( JAR_FILE_PREFIX + a.getFile().getAbsolutePath() + SPRING_CONTEXT_LOC );
+                jars.add( JAR_FILE_PREFIX + a.getFile().getAbsolutePath() + PLEXUS_XML_LOC );
+                jarUrls.add( new URL( FILE_PREFIX + a.getFile().getAbsolutePath() ) );
             }
         }
 
-        ClassRealm realm = container.createComponentRealm( "app", jars );
+        URLClassLoader newClassLoader = new URLClassLoader( (URL[]) jarUrls.toArray( new URL[jarUrls.size()] ), cp );
+        Thread.currentThread().setContextClassLoader( newClassLoader );
+        classPathApplicationContext.setClassLoader( newClassLoader );
 
-        ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
-        Thread.currentThread().setContextClassLoader( realm );
-
-        ClassRealm oldRealm = container.setLookupRealm( realm );
+        PlexusFileSystemXmlApplicationContext fileSystemApplicationContext = new PlexusFileSystemXmlApplicationContext(
+            (String[]) jars.toArray( new String[jars.size()] ), classPathApplicationContext );
+        fileSystemApplicationContext.setClassLoader( newClassLoader );
+        container.setApplicationContext( fileSystemApplicationContext );
 
         DatabaseFactoryConfigurator configurator = (DatabaseFactoryConfigurator) container.lookup(
-            DatabaseFactoryConfigurator.class.getName(), configRoleHint, realm );
+            DatabaseFactoryConfigurator.class.getName(), configRoleHint );
         configurator.configure( params );
 
-        DataManagementTool manager =
-            (DataManagementTool) container.lookup( DataManagementTool.class.getName(), toolRoleHint, realm );
+        DataManagementTool manager = (DataManagementTool) container.lookup( DataManagementTool.class.getName(),
+                                                                            toolRoleHint );
 
         if ( mode == OperationMode.EXPORT )
         {
@@ -267,19 +310,16 @@
         else if ( mode == OperationMode.IMPORT )
         {
             manager.eraseDatabase();
-            manager.restoreDatabase( directory );
+            manager.restoreDatabase( directory, strict );
         }
-
-        container.setLookupRealm( oldRealm );
-        Thread.currentThread().setContextClassLoader( oldLoader );
     }
 
-    private static void initializeWagon( DefaultPlexusContainer container )
+    private static void initializeWagon( PlexusContainerAdapter container, File setting )
         throws ComponentLookupException, ComponentLifecycleException, IOException
     {
         WagonManager wagonManager = (WagonManager) container.lookup( WagonManager.ROLE );
 
-        Settings settings = getSettings( container );
+        Settings settings = getSettings( container, setting );
 
         try
         {
@@ -335,47 +375,49 @@
     }
 
     private static Collection<Artifact> downloadArtifact( PlexusContainer container, String groupId, String artifactId,
-                                                          String version )
+                                                          String version, File setting )
         throws ComponentLookupException, ArtifactNotFoundException, ArtifactResolutionException, IOException
     {
-        ArtifactRepositoryFactory factory =
-            (ArtifactRepositoryFactory) container.lookup( ArtifactRepositoryFactory.ROLE );
+        ArtifactRepositoryFactory factory = (ArtifactRepositoryFactory) container.lookup(
+            ArtifactRepositoryFactory.ROLE );
 
-        DefaultRepositoryLayout layout =
-            (DefaultRepositoryLayout) container.lookup( ArtifactRepositoryLayout.ROLE, "default" );
+        DefaultRepositoryLayout layout = (DefaultRepositoryLayout) container.lookup( ArtifactRepositoryLayout.ROLE,
+                                                                                     "default" );
 
-        ArtifactRepository localRepository =
-            factory.createArtifactRepository( "local", getLocalRepositoryURL( container ), layout, null, null );
+        ArtifactRepository localRepository = factory.createArtifactRepository( "local", getLocalRepositoryURL(
+            container, setting ), layout, null, null );
 
         List<ArtifactRepository> remoteRepositories = new ArrayList<ArtifactRepository>();
-        remoteRepositories.add(
-            factory.createArtifactRepository( "central", "http://repo1.maven.org/maven2", layout, null, null ) );
+        remoteRepositories.add( factory.createArtifactRepository( "central", "http://repo1.maven.org/maven2", layout,
+                                                                  null, null ) );
         //Load extra repositories from active profile
-        
-        Settings settings = getSettings( container );
+
+        Settings settings = getSettings( container, setting );
         List<String> profileIds = settings.getActiveProfiles();
-        List<Profile> profiles = settings.getProfiles();
         Map<String, Profile> profilesAsMap = settings.getProfilesAsMap();
         if ( profileIds != null && !profileIds.isEmpty() )
         {
             for ( String profileId : profileIds )
             {
                 Profile profile = profilesAsMap.get( profileId );
-                List<Repository> repos = profile.getRepositories();
-                if ( repos != null && !repos.isEmpty() )
+                if ( profile != null )
                 {
-                    for ( Repository repo : repos )
+                    List<Repository> repos = profile.getRepositories();
+                    if ( repos != null && !repos.isEmpty() )
                     {
-                        remoteRepositories.add( factory.createArtifactRepository( repo.getId(), repo
-                            .getUrl(), layout, null, null ) );
+                        for ( Repository repo : repos )
+                        {
+                            remoteRepositories.add( factory.createArtifactRepository( repo.getId(), repo.getUrl(),
+                                                                                      layout, null, null ) );
+                        }
                     }
                 }
             }
         }
-        
+
         ArtifactFactory artifactFactory = (ArtifactFactory) container.lookup( ArtifactFactory.ROLE );
-        Artifact artifact =
-            artifactFactory.createArtifact( groupId, artifactId, version, Artifact.SCOPE_RUNTIME, "jar" );
+        Artifact artifact = artifactFactory.createArtifact( groupId, artifactId, version, Artifact.SCOPE_RUNTIME,
+                                                            "jar" );
         Artifact dummyArtifact = artifactFactory.createProjectArtifact( "dummy", "dummy", "1.0" );
 
         if ( artifact.isSnapshot() )
@@ -388,46 +430,71 @@
         ArtifactResolver resolver = (ArtifactResolver) container.lookup( ArtifactResolver.ROLE );
 
         List<String> exclusions = new ArrayList<String>();
-        exclusions.add( "org.apache.maven.continuum:data-management-api" );
+        exclusions.add( "org.apache.continuum:data-management-api" );
         exclusions.add( "org.codehaus.plexus:plexus-component-api" );
         exclusions.add( "org.codehaus.plexus:plexus-container-default" );
-        exclusions.add( "stax:stax-api" );
+        exclusions.add( "org.slf4j:slf4j-api" );
         exclusions.add( "log4j:log4j" );
 
         ArtifactFilter filter = new ExcludesArtifactFilter( exclusions );
 
-        ArtifactMetadataSource source =
-            (ArtifactMetadataSource) container.lookup( ArtifactMetadataSource.ROLE, "maven" );
+        List<? extends ResolutionListener> listeners;
+        if ( LOGGER.isDebugEnabled() )
+        {
+            listeners = Collections.singletonList( new DebugResolutionListener( container.getLogger() ) );
+        }
+        else
+        {
+            listeners = Collections.emptyList();
+        }
+
+        ArtifactMetadataSource source = (ArtifactMetadataSource) container.lookup( ArtifactMetadataSource.ROLE,
+                                                                                   "maven" );
         ArtifactResolutionResult result = resolver.resolveTransitively( Collections.singleton( artifact ),
-                                                                        dummyArtifact, localRepository,
-                                                                        remoteRepositories, source, filter );
+                                                                        dummyArtifact, Collections.emptyMap(),
+                                                                        localRepository, remoteRepositories, source,
+                                                                        filter, listeners );
 
         return result.getArtifacts();
     }
 
-    private static String getLocalRepositoryURL( PlexusContainer container )
+    private static String getLocalRepositoryURL( PlexusContainer container, File setting )
         throws ComponentLookupException, IOException
     {
+        String repositoryPath;
         File settingsFile = new File( System.getProperty( "user.home" ), ".m2/settings.xml" );
-        if ( !settingsFile.exists() )
+        if ( setting != null )
         {
-            return new File( System.getProperty( "user.home" ), ".m2/repository" ).toURL().toString();
+            Settings settings = getSettings( container, setting );
+            repositoryPath = new File( settings.getLocalRepository() ).toURL().toString();
+        }
+        else if ( !settingsFile.exists() )
+        {
+            repositoryPath = new File( System.getProperty( "user.home" ), ".m2/repository" ).toURL().toString();
         }
         else
         {
-            Settings settings = getSettings( container );
-            return new File( settings.getLocalRepository() ).toURL().toString();
+            Settings settings = getSettings( container, null );
+            repositoryPath = new File( settings.getLocalRepository() ).toURL().toString();
         }
+        return repositoryPath;
     }
 
-    private static Settings getSettings( PlexusContainer container )
+    private static Settings getSettings( PlexusContainer container, File setting )
         throws ComponentLookupException, IOException
     {
-        MavenSettingsBuilder mavenSettingsBuilder =
-            (MavenSettingsBuilder) container.lookup( MavenSettingsBuilder.class.getName() );
+        MavenSettingsBuilder mavenSettingsBuilder = (MavenSettingsBuilder) container.lookup(
+            MavenSettingsBuilder.class.getName() );
         try
         {
-            return mavenSettingsBuilder.buildSettings( false );
+            if ( setting != null )
+            {
+                return mavenSettingsBuilder.buildSettings( setting, false );
+            }
+            else
+            {
+                return mavenSettingsBuilder.buildSettings( false );
+            }
         }
         catch ( XmlPullParserException e )
         {
@@ -441,32 +508,32 @@
     {
         Properties properties = new Properties();
         properties.load( DataManagementCli.class.getResourceAsStream(
-            "/META-INF/maven/org.apache.maven.continuum/data-management-api/pom.properties" ) );
+            "/META-INF/maven/org.apache.continuum/data-management-api/pom.properties" ) );
         return properties.getProperty( "version" );
     }
 
     private static class Commands
     {
 
-        @Argument(description = "Display help information", value = "help", alias = "h")
+        @Argument( description = "Display help information", value = "help", alias = "h" )
         private boolean help;
 
-        @Argument(description = "Display version information", value = "version", alias = "v")
+        @Argument( description = "Display version information", value = "version", alias = "v" )
         private boolean version;
 
         @Argument(
             description = "The JDBC URL for the Continuum database that contains the data to convert, or to import the data into",
-            value = "buildsJdbcUrl")
+            value = "buildsJdbcUrl" )
         private String buildsJdbcUrl;
 
         @Argument(
             description = "The JDBC URL for the Redback database that contains the data to convert, or to import the data into",
-            value = "usersJdbcUrl")
+            value = "usersJdbcUrl" )
         private String usersJdbcUrl;
 
         // TODO: ability to use the enum directly would be nice
         @Argument(
-            description = "Format of the database. Valid values are CONTINUUM_103, CONTINUUM_109, CONTINUUM_11. Default is CONTINUUM_11.")
+            description = "Format of the database. Valid values are CONTINUUM_103, CONTINUUM_109, CONTINUUM_11. Default is CONTINUUM_11." )
         private String databaseFormat = DatabaseFormat.CONTINUUM_11.toString();
 
 /* TODO: not yet supported
@@ -477,48 +544,55 @@
 
         @Argument(
             description = "The directory to export the data to, or import the data from. Default is 'backups' in the current working directory.",
-            value = "directory")
+            value = "directory" )
         private File directory = new File( "backups" );
 
         @Argument(
             description = "Mode of operation. Valid values are IMPORT and EXPORT. Default is EXPORT.",
-            value = "mode")
+            value = "mode" )
         private String mode = OperationMode.EXPORT.toString();
 
         @Argument(
             description = "Whether to overwrite the designated directory if it already exists in export mode. Default is false.",
-            value = "overwrite")
+            value = "overwrite" )
         private boolean overwrite;
 
         @Argument(
             description = "The type of database to use. Currently supported values are DERBY_10_1. The default value is DERBY_10_1.",
-            value = "databaseType")
+            value = "databaseType" )
         private String databaseType = SupportedDatabase.DERBY_10_1.toString();
 
-        @Argument(description = "JDBC driver class", value = "driverClass", required = false)
+        @Argument( description = "JDBC driver class", value = "driverClass", required = false )
         private String driverClass;
 
-        @Argument(description = "JDBC driver groupId", value = "groupId", required = false)
+        @Argument( description = "JDBC driver groupId", value = "groupId", required = false )
         private String groupId;
 
-        @Argument(description = "JDBC driver artifactId", value = "artifactId", required = false)
+        @Argument( description = "JDBC driver artifactId", value = "artifactId", required = false )
         private String artifactId;
 
-        @Argument(description = "Artifact version of the JDBC driver class",
-                  value = "artifactVersion",
-                  required = false)
+        @Argument( description = "Artifact version of the JDBC driver class",
+                   value = "artifactVersion",
+                   required = false )
         private String artifactVersion;
 
-        @Argument(description = "Username", value = "username", required = false)
+        @Argument( description = "Username", value = "username", required = false )
         private String username;
 
-        @Argument(description = "Password", value = "password", required = false)
+        @Argument( description = "Password", value = "password", required = false )
         private String password;
 
         @Argument(
             description = "Turn on debugging information. Default is off.",
-            value = "debug")
+            value = "debug" )
         private boolean debug;
+
+        @Argument( description = "Alternate path for the user settings file", value = "settings", required = false,
+                   alias = "s" )
+        private File settings;
+
+        @Argument( description = "Run on strict mode. Default is false.", value = "strict" )
+        private boolean strict;
     }
 
     private enum OperationMode
diff --git a/continuum-data-management/data-management-cli/src/main/java/org/apache/maven/continuum/management/DatabaseFormat.java b/continuum-data-management/data-management-cli/src/main/java/org/apache/maven/continuum/management/DatabaseFormat.java
index 6e9a113..3b23275 100644
--- a/continuum-data-management/data-management-cli/src/main/java/org/apache/maven/continuum/management/DatabaseFormat.java
+++ b/continuum-data-management/data-management-cli/src/main/java/org/apache/maven/continuum/management/DatabaseFormat.java
@@ -21,6 +21,7 @@
 
 /**
  * Enumeration of known database formats.
+ *
  * @version $Id$
  */
 public enum DatabaseFormat
diff --git a/continuum-data-management/data-management-cli/src/main/java/org/apache/maven/continuum/management/util/PlexusApplicationContextDelegate.java b/continuum-data-management/data-management-cli/src/main/java/org/apache/maven/continuum/management/util/PlexusApplicationContextDelegate.java
new file mode 100644
index 0000000..c36480b
--- /dev/null
+++ b/continuum-data-management/data-management-cli/src/main/java/org/apache/maven/continuum/management/util/PlexusApplicationContextDelegate.java
@@ -0,0 +1,101 @@
+package org.apache.maven.continuum.management.util;
+
+/*
+ * 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 org.codehaus.plexus.spring.PlexusBeanDefinitionDocumentReader;
+import org.codehaus.plexus.spring.PlexusConfigurationPropertyEditor;
+import org.codehaus.plexus.spring.PlexusContainerAdapter;
+import org.codehaus.plexus.spring.PlexusLifecycleBeanPostProcessor;
+import org.codehaus.plexus.spring.editors.CollectionPropertyEditor;
+import org.codehaus.plexus.spring.editors.MapPropertyEditor;
+import org.codehaus.plexus.spring.editors.PropertiesPropertyEditor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.context.ApplicationContext;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class PlexusApplicationContextDelegate
+{
+    /**
+     * Logger used by this class.
+     */
+    protected Logger logger = LoggerFactory.getLogger( getClass() );
+
+    private PlexusLifecycleBeanPostProcessor lifecycleBeanPostProcessor;
+
+    /**
+     * @see org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(org.springframework.beans.factory.xml.XmlBeanDefinitionReader)
+     */
+    protected void loadBeanDefinitions( XmlBeanDefinitionReader reader )
+        throws BeansException, IOException
+    {
+        logger.info( "Registering Plexus to Spring XML translation" );
+        reader.setDocumentReaderClass( PlexusBeanDefinitionDocumentReader.class );
+    }
+
+    /**
+     * @see org.springframework.context.support.AbstractApplicationContext#postProcessBeanFactory(org.springframework.beans.factory.config.ConfigurableListableBeanFactory)
+     */
+    protected void postProcessBeanFactory( ConfigurableListableBeanFactory beanFactory, ApplicationContext context )
+    {
+        // Register a PlexusContainerAdapter bean to allow context lookups using plexus API
+        PlexusContainerAdapter plexus = new PlexusContainerAdapter();
+        plexus.setApplicationContext( context );
+        beanFactory.registerSingleton( "plexusContainer", plexus );
+
+        // Register a beanPostProcessor to handle plexus interface-based lifecycle management
+        lifecycleBeanPostProcessor = new PlexusLifecycleBeanPostProcessor();
+        lifecycleBeanPostProcessor.setBeanFactory( context );
+        beanFactory.addBeanPostProcessor( lifecycleBeanPostProcessor );
+
+        // Register a PropertyEditor to support plexus XML <configuration> set as CDATA in
+        // a spring context XML file.
+        beanFactory.addPropertyEditorRegistrar( new PlexusConfigurationPropertyEditor() );
+        beanFactory.addPropertyEditorRegistrar( new PropertiesPropertyEditor() );
+        beanFactory.addPropertyEditorRegistrar( new CollectionPropertyEditor( List.class, ArrayList.class ) );
+        beanFactory.addPropertyEditorRegistrar( new CollectionPropertyEditor( Set.class, HashSet.class ) );
+        beanFactory.addPropertyEditorRegistrar( new MapPropertyEditor( Map.class, HashMap.class ) );
+    }
+
+    /**
+     * @see org.springframework.context.support.AbstractApplicationContext#doClose()
+     */
+    protected void doClose()
+    {
+        try
+        {
+            lifecycleBeanPostProcessor.destroy();
+        }
+        catch ( Throwable ex )
+        {
+            logger.error( "Exception thrown from PlexusLifecycleBeanPostProcessor handling ContextClosedEvent", ex );
+        }
+    }
+}
\ No newline at end of file
diff --git a/continuum-data-management/data-management-cli/src/main/java/org/apache/maven/continuum/management/util/PlexusFileSystemXmlApplicationContext.java b/continuum-data-management/data-management-cli/src/main/java/org/apache/maven/continuum/management/util/PlexusFileSystemXmlApplicationContext.java
new file mode 100644
index 0000000..cf3cf8f
--- /dev/null
+++ b/continuum-data-management/data-management-cli/src/main/java/org/apache/maven/continuum/management/util/PlexusFileSystemXmlApplicationContext.java
@@ -0,0 +1,120 @@
+package org.apache.maven.continuum.management.util;
+
+/*
+ * 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 org.codehaus.plexus.spring.PlexusXmlBeanDefinitionReader;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.xml.ResourceEntityResolver;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.FileSystemXmlApplicationContext;
+
+import java.io.IOException;
+
+public class PlexusFileSystemXmlApplicationContext
+    extends FileSystemXmlApplicationContext
+{
+    private static PlexusApplicationContextDelegate delegate = new PlexusApplicationContextDelegate();
+
+    public PlexusFileSystemXmlApplicationContext( String configLocation )
+    {
+        super( configLocation );
+    }
+
+    public PlexusFileSystemXmlApplicationContext( String[] configLocations )
+    {
+        super( configLocations );
+    }
+
+    public PlexusFileSystemXmlApplicationContext( String[] configLocations, ApplicationContext parent )
+    {
+        super( configLocations, parent );
+    }
+
+    public PlexusFileSystemXmlApplicationContext( String[] configLocations, boolean refresh )
+    {
+        super( configLocations, refresh );
+    }
+
+    public PlexusFileSystemXmlApplicationContext( String[] configLocations, boolean refresh, ApplicationContext parent )
+    {
+        super( configLocations, refresh, parent );
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @see org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(org.springframework.beans.factory.xml.XmlBeanDefinitionReader)
+     */
+    protected void loadBeanDefinitions( XmlBeanDefinitionReader reader )
+        throws BeansException, IOException
+    {
+        delegate.loadBeanDefinitions( reader );
+        super.loadBeanDefinitions( reader );
+    }
+
+    /**
+     * Copied from {@link AbstractXmlApplicationContext}
+     * Loads the bean definitions via an XmlBeanDefinitionReader.
+     *
+     * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
+     * @see #initBeanDefinitionReader
+     * @see #loadBeanDefinitions
+     */
+    protected void loadBeanDefinitions( DefaultListableBeanFactory beanFactory )
+        throws IOException
+    {
+        // Create a new XmlBeanDefinitionReader for the given BeanFactory.
+        XmlBeanDefinitionReader beanDefinitionReader = new PlexusXmlBeanDefinitionReader( beanFactory );
+
+        // Configure the bean definition reader with this context's
+        // resource loading environment.
+        beanDefinitionReader.setResourceLoader( this );
+        beanDefinitionReader.setEntityResolver( new ResourceEntityResolver( this ) );
+
+        // Allow a subclass to provide custom initialization of the reader,
+        // then proceed with actually loading the bean definitions.
+        initBeanDefinitionReader( beanDefinitionReader );
+        loadBeanDefinitions( beanDefinitionReader );
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @see org.springframework.context.support.AbstractApplicationContext#postProcessBeanFactory(org.springframework.beans.factory.config.ConfigurableListableBeanFactory)
+     */
+    protected void postProcessBeanFactory( ConfigurableListableBeanFactory beanFactory )
+    {
+        delegate.postProcessBeanFactory( beanFactory, this );
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @see org.springframework.context.support.AbstractApplicationContext#doClose()
+     */
+    protected void doClose()
+    {
+        delegate.doClose();
+        super.doClose();
+    }
+}
\ No newline at end of file
diff --git a/continuum-data-management/data-management-cli/src/main/resources/META-INF/plexus/plexus.xml b/continuum-data-management/data-management-cli/src/main/resources/META-INF/plexus/plexus.xml
index c4a981a..6c25b09 100644
--- a/continuum-data-management/data-management-cli/src/main/resources/META-INF/plexus/plexus.xml
+++ b/continuum-data-management/data-management-cli/src/main/resources/META-INF/plexus/plexus.xml
@@ -16,10 +16,17 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
   -->
-  <!-- $Id$ -->
+
+<!-- $Id$ -->
 <plexus>
   <components>
     <component>
+      <role>org.codehaus.plexus.logging.LoggerManager</role>
+      <implementation>org.codehaus.plexus.logging.slf4j.Slf4jLoggerManager</implementation>
+      <lifecycle-handler>basic</lifecycle-handler>
+    </component>
+
+    <component>
       <role>org.codehaus.plexus.jdo.JdoFactory</role>
       <role-hint>continuum</role-hint>
       <implementation>org.codehaus.plexus.jdo.DefaultConfigurableJdoFactory</implementation>
@@ -76,5 +83,62 @@
       </configuration>
     </component>
 
+    <component>
+      <role>org.codehaus.plexus.jdo.JdoFactory</role>
+      <role-hint>users</role-hint>
+      <implementation>org.codehaus.plexus.jdo.DefaultConfigurableJdoFactory</implementation>
+      <configuration>
+        <!-- Database Configuration -->
+        <!--
+              <driverName>org.hsqldb.jdbcDriver</driverName>
+              <url>jdbc:hsqldb:mem:database</url>
+              <userName>sa</userName>
+              <password></password>
+        -->
+        <persistenceManagerFactoryClass>org.jpox.PersistenceManagerFactoryImpl</persistenceManagerFactoryClass>
+
+        <otherProperties>
+          <property>
+            <name>org.jpox.autoCreateSchema</name>
+            <value>true</value>
+          </property>
+          <property>
+            <name>org.jpox.validateTables</name>
+            <value>false</value>
+          </property>
+          <property>
+            <name>org.jpox.validateConstraints</name>
+            <value>false</value>
+          </property>
+          <property>
+            <name>org.jpox.validateColumns</name>
+            <value>false</value>
+          </property>
+          <property>
+            <name>org.jpox.autoStartMechanism</name>
+            <value>None</value>
+          </property>
+          <property>
+            <name>org.jpox.transactionIsolation</name>
+            <value>READ_UNCOMMITTED</value>
+          </property>
+          <property>
+            <name>org.jpox.poid.transactionIsolation</name>
+            <value>READ_UNCOMMITTED</value>
+          </property>
+          <property>
+            <name>org.jpox.rdbms.dateTimezone</name>
+            <value>JDK_DEFAULT_TIMEZONE</value>
+          </property>
+          <!--
+                    <property>
+                      <name>org.jpox.identifier.case</name>
+                      <value>PreserveCase</value>
+                    </property>
+          -->
+        </otherProperties>
+      </configuration>
+    </component>
+
   </components>
 </plexus>
diff --git a/continuum-data-management/data-management-jdo/pom.xml b/continuum-data-management/data-management-jdo/pom.xml
index a0f98cd..8277229 100644
--- a/continuum-data-management/data-management-jdo/pom.xml
+++ b/continuum-data-management/data-management-jdo/pom.xml
@@ -22,18 +22,40 @@
   <parent>
     <artifactId>continuum-data-management</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>data-management-jdo</artifactId>
   <name>Continuum :: Data Management :: JDO</name>
   <dependencies>
     <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-simple</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
       <groupId>org.apache.continuum</groupId>
       <artifactId>data-management-api</artifactId>
     </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-utils</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>javax.jdo</groupId>
+      <artifactId>jdo2-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>plexus-spring</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-jdo2</artifactId>
     </dependency>
     <dependency>
@@ -50,6 +72,15 @@
     </dependency>
     <dependency>
       <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-commons</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>stax</groupId>
+      <artifactId>stax-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
       <artifactId>continuum-store</artifactId>
       <scope>runtime</scope>
     </dependency>
@@ -74,43 +105,24 @@
       </exclusions>
     </dependency>
     <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-simple</artifactId>
-      <version>1.5.0</version>
-      <scope>runtime</scope>
-    </dependency>
-    <dependency>
-      <groupId>hsqldb</groupId>
+      <groupId>org.hsqldb</groupId>
       <artifactId>hsqldb</artifactId>
+      <version>2.3.2</version>
       <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>stax</groupId>
       <artifactId>stax</artifactId>
-      <version>1.1.1-dev</version>
-      <scope>test</scope>
-      <exclusions>
-        <exclusion>
-          <groupId>xmlbeans</groupId>
-          <artifactId>xmlbeans-jsr173-api</artifactId>
-        </exclusion>
-      </exclusions>
+      <scope>runtime</scope>
     </dependency>
     <dependency>
       <groupId>xmlunit</groupId>
       <artifactId>xmlunit</artifactId>
-      <version>1.0</version>
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>jdom</groupId>
+      <groupId>org.jdom</groupId>
       <artifactId>jdom</artifactId>
-      <version>1.0</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-log4j12</artifactId>
       <scope>test</scope>
     </dependency>
   </dependencies>
diff --git a/continuum-data-management/data-management-jdo/src/main/java/org/apache/maven/continuum/management/JdoDataManagementTool.java b/continuum-data-management/data-management-jdo/src/main/java/org/apache/maven/continuum/management/JdoDataManagementTool.java
index c06969c..109f63f 100644
--- a/continuum-data-management/data-management-jdo/src/main/java/org/apache/maven/continuum/management/JdoDataManagementTool.java
+++ b/continuum-data-management/data-management-jdo/src/main/java/org/apache/maven/continuum/management/JdoDataManagementTool.java
@@ -1,7 +1,31 @@
 package org.apache.maven.continuum.management;
 
+/*
+ * 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 org.apache.continuum.dao.BuildDefinitionDao;
+import org.apache.continuum.dao.BuildDefinitionTemplateDao;
+import org.apache.continuum.dao.BuildQueueDao;
+import org.apache.continuum.dao.ContinuumReleaseResultDao;
 import org.apache.continuum.dao.DaoUtils;
 import org.apache.continuum.dao.DirectoryPurgeConfigurationDao;
+import org.apache.continuum.dao.DistributedDirectoryPurgeConfigurationDao;
 import org.apache.continuum.dao.InstallationDao;
 import org.apache.continuum.dao.LocalRepositoryDao;
 import org.apache.continuum.dao.ProfileDao;
@@ -10,8 +34,14 @@
 import org.apache.continuum.dao.RepositoryPurgeConfigurationDao;
 import org.apache.continuum.dao.ScheduleDao;
 import org.apache.continuum.dao.SystemConfigurationDao;
+import org.apache.continuum.model.project.ProjectScmRoot;
+import org.apache.continuum.model.release.ContinuumReleaseResult;
+import org.apache.continuum.model.repository.DirectoryPurgeConfiguration;
 import org.apache.continuum.model.repository.LocalRepository;
+import org.apache.continuum.utils.ProjectSorter;
 import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.BuildDefinitionTemplate;
+import org.apache.maven.continuum.model.project.BuildQueue;
 import org.apache.maven.continuum.model.project.ContinuumDatabase;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.project.ProjectGroup;
@@ -24,10 +54,9 @@
 import org.codehaus.plexus.jdo.ConfigurableJdoFactory;
 import org.codehaus.plexus.jdo.PlexusJdoUtils;
 import org.codehaus.plexus.util.IOUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-import javax.jdo.JDOHelper;
-import javax.jdo.PersistenceManagerFactory;
-import javax.xml.stream.XMLStreamException;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.FileReader;
@@ -43,15 +72,22 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
+import java.util.Set;
+import javax.jdo.JDOHelper;
+import javax.jdo.PersistenceManagerFactory;
+import javax.xml.stream.XMLStreamException;
 
 /**
  * JDO implementation the database management tool API.
+ *
  * @version $Id$
  * @plexus.component role="org.apache.maven.continuum.management.DataManagementTool" role-hint="continuum-jdo"
  */
 public class JdoDataManagementTool
     implements DataManagementTool
 {
+    private Logger log = LoggerFactory.getLogger( JdoDataManagementTool.class );
+
     /**
      * @plexus.requirement
      */
@@ -75,6 +111,11 @@
     /**
      * @plexus.requirement
      */
+    private DistributedDirectoryPurgeConfigurationDao distributedDirectoryPurgeConfigurationDao;
+
+    /**
+     * @plexus.requirement
+     */
     private InstallationDao installationDao;
 
     /**
@@ -102,6 +143,26 @@
      */
     private ProjectScmRootDao projectScmRootDao;
 
+    /**
+     * @plexus.requirement
+     */
+    private BuildDefinitionTemplateDao buildDefinitionTemplateDao;
+
+    /**
+     * @plexus.requirement
+     */
+    private ContinuumReleaseResultDao releaseResultDao;
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildQueueDao buildQueueDao;
+
+    /**
+     * @plexus.requirement
+     */
+    private BuildDefinitionDao buildDefinitionDao;
+
     protected static final String BUILDS_XML = "builds.xml";
 
     /**
@@ -128,6 +189,12 @@
         try
         {
             database.setInstallations( installationDao.getAllInstallations() );
+
+            database.setBuildDefinitionTemplates( buildDefinitionTemplateDao.getAllBuildDefinitionTemplate() );
+
+            database.setBuildQueues( buildQueueDao.getAllBuildQueues() );
+
+            database.setBuildDefinitions( buildDefinitionDao.getAllTemplates() );
         }
         catch ( ContinuumStoreException e )
         {
@@ -135,13 +202,14 @@
         }
         database.setSchedules( scheduleDao.getAllSchedulesByName() );
         database.setProfiles( profileDao.getAllProfilesByName() );
-
         database.setLocalRepositories( localRepositoryDao.getAllLocalRepositories() );
         database.setRepositoryPurgeConfigurations(
             repositoryPurgeConfigurationDao.getAllRepositoryPurgeConfigurations() );
         database.setDirectoryPurgeConfigurations( directoryPurgeConfigurationDao.getAllDirectoryPurgeConfigurations() );
-
+        database.setDistributedDirectoryPurgeConfigurations(
+            distributedDirectoryPurgeConfigurationDao.getAllDistributedDirectoryPurgeConfigurations() );
         database.setProjectScmRoots( projectScmRootDao.getAllProjectScmRoots() );
+        database.setContinuumReleaseResults( releaseResultDao.getAllContinuumReleaseResults() );
 
         ContinuumStaxWriter writer = new ContinuumStaxWriter();
 
@@ -171,7 +239,7 @@
         daoUtils.eraseDatabase();
     }
 
-    public void restoreDatabase( File backupDirectory )
+    public void restoreDatabase( File backupDirectory, boolean strict )
         throws IOException
     {
         ContinuumStaxReader reader = new ContinuumStaxReader();
@@ -181,7 +249,7 @@
         ContinuumDatabase database;
         try
         {
-            database = reader.read( fileReader );
+            database = reader.read( fileReader, strict );
         }
         catch ( XMLStreamException e )
         {
@@ -201,10 +269,18 @@
 
         PlexusJdoUtils.addObject( pmf.getPersistenceManager(), database.getSystemConfiguration() );
 
+        Map<Integer, BuildQueue> buildQueues = new HashMap<Integer, BuildQueue>();
+        for ( BuildQueue buildQueue : (List<BuildQueue>) database.getBuildQueues() )
+        {
+            buildQueue = (BuildQueue) PlexusJdoUtils.addObject( pmf.getPersistenceManager(), buildQueue );
+            buildQueues.put( buildQueue.getId(), buildQueue );
+        }
+
         Map<Integer, Schedule> schedules = new HashMap<Integer, Schedule>();
         for ( Iterator i = database.getSchedules().iterator(); i.hasNext(); )
         {
             Schedule schedule = (Schedule) i.next();
+            schedule.setBuildQueues( getBuildQueuesBySchedule( buildQueues, schedule ) );
 
             schedule = (Schedule) PlexusJdoUtils.addObject( pmf.getPersistenceManager(), schedule );
             schedules.put( Integer.valueOf( schedule.getId() ), schedule );
@@ -233,16 +309,42 @@
             {
                 profile.setBuilder( installations.get( profile.getBuilder().getInstallationId() ) );
             }
-
+            List environmentVariables = new ArrayList();
+            for ( Iterator envIt = profile.getEnvironmentVariables().listIterator(); envIt.hasNext(); )
+            {
+                Installation installation = (Installation) envIt.next();
+                environmentVariables.add( installations.get( installation.getInstallationId() ) );
+                envIt.remove();
+            }
+            profile.setEnvironmentVariables( environmentVariables );
             profile = (Profile) PlexusJdoUtils.addObject( pmf.getPersistenceManager(), profile );
             profiles.put( Integer.valueOf( profile.getId() ), profile );
         }
 
+        Map<Integer, BuildDefinition> buildDefinitions = new HashMap<Integer, BuildDefinition>();
+        for ( BuildDefinition buildDefinition : (List<BuildDefinition>) database.getBuildDefinitions() )
+        {
+            if ( buildDefinition.getSchedule() != null )
+            {
+                buildDefinition.setSchedule( schedules.get( Integer.valueOf(
+                    buildDefinition.getSchedule().getId() ) ) );
+            }
+
+            if ( buildDefinition.getProfile() != null )
+            {
+                buildDefinition.setProfile( profiles.get( Integer.valueOf( buildDefinition.getProfile().getId() ) ) );
+            }
+
+            buildDefinition = (BuildDefinition) PlexusJdoUtils.addObject( pmf.getPersistenceManager(),
+                                                                          buildDefinition );
+            buildDefinitions.put( Integer.valueOf( buildDefinition.getId() ), buildDefinition );
+        }
+
         Map<Integer, LocalRepository> localRepositories = new HashMap<Integer, LocalRepository>();
         for ( LocalRepository localRepository : (List<LocalRepository>) database.getLocalRepositories() )
         {
-            localRepository =
-                (LocalRepository) PlexusJdoUtils.addObject( pmf.getPersistenceManager(), localRepository );
+            localRepository = (LocalRepository) PlexusJdoUtils.addObject( pmf.getPersistenceManager(),
+                                                                          localRepository );
             localRepositories.put( Integer.valueOf( localRepository.getId() ), localRepository );
         }
 
@@ -252,43 +354,190 @@
             ProjectGroup projectGroup = (ProjectGroup) i.next();
 
             // first, we must map up any schedules, etc.
-            processBuildDefinitions( projectGroup.getBuildDefinitions(), schedules, profiles, localRepositories );
+            projectGroup.setBuildDefinitions( processBuildDefinitions( projectGroup.getBuildDefinitions(), schedules,
+                                                                       profiles, buildDefinitions ) );
 
             for ( Iterator j = projectGroup.getProjects().iterator(); j.hasNext(); )
             {
                 Project project = (Project) j.next();
 
-                processBuildDefinitions( project.getBuildDefinitions(), schedules, profiles, localRepositories );
+                project.setBuildDefinitions( processBuildDefinitions( project.getBuildDefinitions(), schedules,
+                                                                      profiles, buildDefinitions ) );
             }
-            
+
             if ( projectGroup.getLocalRepository() != null )
             {
-                projectGroup.setLocalRepository( localRepositories.get( 
-                                                 Integer.valueOf( projectGroup.getLocalRepository().getId() ) ) );
+                projectGroup.setLocalRepository( localRepositories.get( Integer.valueOf(
+                    projectGroup.getLocalRepository().getId() ) ) );
             }
 
             projectGroup = (ProjectGroup) PlexusJdoUtils.addObject( pmf.getPersistenceManager(), projectGroup );
             projectGroups.put( Integer.valueOf( projectGroup.getId() ), projectGroup );
         }
-    }
 
-    private static void processBuildDefinitions( List buildDefinitions, Map<Integer, Schedule> schedules,
-                                                 Map<Integer, Profile> profiles,
-                                                 Map<Integer, LocalRepository> localRepositories )
-    {
-        for ( Iterator i = buildDefinitions.iterator(); i.hasNext(); )
+        // create project scm root data (CONTINUUM-2040)
+        Map<Integer, ProjectScmRoot> projectScmRoots = new HashMap<Integer, ProjectScmRoot>();
+        Set<Integer> keys = projectGroups.keySet();
+        int id = 1;
+        for ( Integer key : keys )
         {
-            BuildDefinition def = (BuildDefinition) i.next();
-
-            if ( def.getSchedule() != null )
+            ProjectGroup projectGroup = projectGroups.get( key );
+            String url = " ";
+            List<Project> projects = ProjectSorter.getSortedProjects( getProjectsByGroupIdWithDependencies( pmf,
+                                                                                                            projectGroup.getId() ),
+                                                                      log );
+            for ( Iterator j = projects.iterator(); j.hasNext(); )
             {
-                def.setSchedule( schedules.get( Integer.valueOf( def.getSchedule().getId() ) ) );
-            }
+                Project project = (Project) j.next();
+                if ( !project.getScmUrl().trim().startsWith( url ) )
+                {
+                    url = project.getScmUrl();
+                    ProjectScmRoot projectScmRoot = new ProjectScmRoot();
+                    projectScmRoot.setId( id );
+                    projectScmRoot.setProjectGroup( projectGroup );
+                    projectScmRoot.setScmRootAddress( url );
+                    projectScmRoot.setState( project.getState() );
 
-            if ( def.getProfile() != null )
-            {
-                def.setProfile( profiles.get( Integer.valueOf( def.getProfile().getId() ) ) );
+                    projectScmRoot = (ProjectScmRoot) PlexusJdoUtils.addObject( pmf.getPersistenceManager(),
+                                                                                projectScmRoot );
+                    projectScmRoots.put( Integer.valueOf( projectScmRoot.getId() ), projectScmRoot );
+                    id++;
+                }
             }
         }
+
+        /*
+        for ( RepositoryPurgeConfiguration repoPurge : (List<RepositoryPurgeConfiguration>) database.getRepositoryPurgeConfigurations() )
+        {
+            repoPurge.setRepository( localRepositories.get(
+                                     Integer.valueOf( repoPurge.getRepository().getId() ) ) );
+
+            if ( repoPurge.getSchedule() != null )
+            {
+                repoPurge.setSchedule( schedules.get(
+                                       Integer.valueOf( repoPurge.getSchedule().getId() ) ) );
+            }
+
+            repoPurge = (RepositoryPurgeConfiguration) PlexusJdoUtils.addObject( pmf.getPersistenceManager(), repoPurge );
+        }*/
+
+        for ( DirectoryPurgeConfiguration dirPurge : (List<DirectoryPurgeConfiguration>) database.getDirectoryPurgeConfigurations() )
+        {
+            if ( dirPurge.getSchedule() != null )
+            {
+                dirPurge.setSchedule( schedules.get( Integer.valueOf( dirPurge.getSchedule().getId() ) ) );
+            }
+
+            dirPurge = (DirectoryPurgeConfiguration) PlexusJdoUtils.addObject( pmf.getPersistenceManager(), dirPurge );
+        }
+
+        for ( ContinuumReleaseResult releaseResult : (List<ContinuumReleaseResult>) database.getContinuumReleaseResults() )
+        {
+            releaseResult.setProjectGroup( projectGroups.get( Integer.valueOf(
+                releaseResult.getProjectGroup().getId() ) ) );
+
+            ProjectGroup group = releaseResult.getProjectGroup();
+
+            for ( Project project : (List<Project>) group.getProjects() )
+            {
+                if ( project.getId() == releaseResult.getProject().getId() )
+                {
+                    try
+                    {
+                        Project proj = (Project) PlexusJdoUtils.getObjectById( pmf.getPersistenceManager(),
+                                                                               Project.class, project.getId(), null );
+                        releaseResult.setProject( proj );
+                    }
+                    catch ( Exception e )
+                    {
+                        throw new DataManagementException( e );
+                    }
+                }
+            }
+
+            releaseResult = (ContinuumReleaseResult) PlexusJdoUtils.addObject( pmf.getPersistenceManager(),
+                                                                               releaseResult );
+        }
+
+        for ( BuildDefinitionTemplate template : (List<BuildDefinitionTemplate>) database.getBuildDefinitionTemplates() )
+        {
+            template.setBuildDefinitions( processBuildDefinitions( template.getBuildDefinitions(), buildDefinitions ) );
+
+            template = (BuildDefinitionTemplate) PlexusJdoUtils.addObject( pmf.getPersistenceManager(), template );
+        }
+    }
+
+    private List<Project> getProjectsByGroupIdWithDependencies( PersistenceManagerFactory pmf, int projectGroupId )
+    {
+        List<Project> allProjects = PlexusJdoUtils.getAllObjectsDetached( pmf.getPersistenceManager(), Project.class,
+                                                                          "name ascending", "project-dependencies" );
+        List<Project> groupProjects = new ArrayList<Project>();
+
+        for ( Project project : allProjects )
+        {
+            if ( project.getProjectGroup().getId() == projectGroupId )
+            {
+                groupProjects.add( project );
+            }
+        }
+
+        return groupProjects;
+    }
+
+    private List<BuildDefinition> processBuildDefinitions( List<BuildDefinition> buildDefinitions,
+                                                           Map<Integer, Schedule> schedules,
+                                                           Map<Integer, Profile> profiles,
+                                                           Map<Integer, BuildDefinition> buildDefs )
+    {
+        List<BuildDefinition> buildDefsList = new ArrayList<BuildDefinition>();
+
+        for ( BuildDefinition def : buildDefinitions )
+        {
+            if ( buildDefs.get( Integer.valueOf( def.getId() ) ) != null )
+            {
+                buildDefsList.add( buildDefs.get( Integer.valueOf( def.getId() ) ) );
+            }
+            else
+            {
+                if ( def.getSchedule() != null )
+                {
+                    def.setSchedule( schedules.get( Integer.valueOf( def.getSchedule().getId() ) ) );
+                }
+
+                if ( def.getProfile() != null )
+                {
+                    def.setProfile( profiles.get( Integer.valueOf( def.getProfile().getId() ) ) );
+                }
+
+                buildDefsList.add( def );
+            }
+        }
+
+        return buildDefsList;
+    }
+
+    private List<BuildDefinition> processBuildDefinitions( List<BuildDefinition> buildDefinitions,
+                                                           Map<Integer, BuildDefinition> buildDefs )
+    {
+        List<BuildDefinition> buildDefsList = new ArrayList<BuildDefinition>();
+
+        for ( BuildDefinition buildDefinition : buildDefinitions )
+        {
+            buildDefsList.add( buildDefs.get( Integer.valueOf( buildDefinition.getId() ) ) );
+        }
+
+        return buildDefsList;
+    }
+
+    private List<BuildQueue> getBuildQueuesBySchedule( Map<Integer, BuildQueue> allBuildQueues, Schedule schedule )
+    {
+        List<BuildQueue> buildQueues = new ArrayList<BuildQueue>();
+
+        for ( BuildQueue buildQueue : (List<BuildQueue>) schedule.getBuildQueues() )
+        {
+            buildQueues.add( allBuildQueues.get( Integer.valueOf( buildQueue.getId() ) ) );
+        }
+
+        return buildQueues;
     }
 }
diff --git a/continuum-data-management/data-management-jdo/src/main/java/org/apache/maven/continuum/management/LegacyJdoDataManagementTool.java b/continuum-data-management/data-management-jdo/src/main/java/org/apache/maven/continuum/management/LegacyJdoDataManagementTool.java
index 859f9fe..b120215 100644
--- a/continuum-data-management/data-management-jdo/src/main/java/org/apache/maven/continuum/management/LegacyJdoDataManagementTool.java
+++ b/continuum-data-management/data-management-jdo/src/main/java/org/apache/maven/continuum/management/LegacyJdoDataManagementTool.java
@@ -42,11 +42,6 @@
 import org.codehaus.plexus.jdo.PlexusJdoUtils;
 import org.codehaus.plexus.util.IOUtil;
 
-import javax.jdo.FetchPlan;
-import javax.jdo.JDOHelper;
-import javax.jdo.PersistenceManager;
-import javax.jdo.PersistenceManagerFactory;
-import javax.xml.stream.XMLStreamException;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.FileReader;
@@ -63,9 +58,15 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
+import javax.jdo.FetchPlan;
+import javax.jdo.JDOHelper;
+import javax.jdo.PersistenceManager;
+import javax.jdo.PersistenceManagerFactory;
+import javax.xml.stream.XMLStreamException;
 
 /**
  * JDO implementation the database management tool API.
+ *
  * @version $Id$
  * @plexus.component role="org.apache.maven.continuum.management.DataManagementTool" role-hint="legacy-continuum-jdo"
  */
@@ -157,7 +158,7 @@
         return result;
     }
 
-    @SuppressWarnings({"OverlyCoupledMethod"})
+    @SuppressWarnings( {"OverlyCoupledMethod"} )
     public void eraseDatabase()
     {
         PersistenceManagerFactory pmf = getPersistenceManagerFactory( "jdo109" );
@@ -189,7 +190,7 @@
         return pm;
     }
 
-    public void restoreDatabase( File backupDirectory )
+    public void restoreDatabase( File backupDirectory, boolean strict )
         throws IOException
     {
         ContinuumStaxReader reader = new ContinuumStaxReader();
@@ -199,7 +200,7 @@
         ContinuumDatabase database;
         try
         {
-            database = reader.read( fileReader );
+            database = reader.read( fileReader, strict );
         }
         catch ( XMLStreamException e )
         {
diff --git a/continuum-data-management/data-management-jdo/src/test/java/org/apache/maven/continuum/management/DataManagementToolTest.java b/continuum-data-management/data-management-jdo/src/test/java/org/apache/maven/continuum/management/DataManagementToolTest.java
index 798b657..050fab1 100644
--- a/continuum-data-management/data-management-jdo/src/test/java/org/apache/maven/continuum/management/DataManagementToolTest.java
+++ b/continuum-data-management/data-management-jdo/src/test/java/org/apache/maven/continuum/management/DataManagementToolTest.java
@@ -1,31 +1,24 @@
 package org.apache.maven.continuum.management;
 
 /*
- * 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.
+ * 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.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-
-import javax.xml.stream.XMLStreamException;
-
 import org.apache.maven.continuum.store.AbstractContinuumStoreTestCase;
 import org.apache.maven.continuum.store.ContinuumStoreException;
 import org.codehaus.plexus.util.FileUtils;
@@ -36,6 +29,19 @@
 import org.jdom.output.Format;
 import org.jdom.output.XMLOutputter;
 
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.Statement;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import javax.xml.stream.XMLStreamException;
+
 /**
  * Test the database management tool.
  */
@@ -58,6 +64,24 @@
         targetDirectory = createBackupDirectory();
     }
 
+    public void tearDown()
+        throws Exception
+    {
+        Connection connection = DriverManager.getConnection( "jdbc:hsqldb:mem:." );
+        Statement stmt = connection.createStatement();
+        try
+        {
+            stmt.execute("TRUNCATE SCHEMA PUBLIC RESTART IDENTITY AND COMMIT NO CHECK");
+            connection.commit();
+        }
+        finally
+        {
+            stmt.close();
+            connection.close();
+        }
+        super.tearDown();
+    }
+
 /*
     protected ContinuumStore createStore()
         throws Exception
@@ -77,7 +101,7 @@
     public void testBackupBuilds()
         throws IOException, ContinuumStoreException, XMLStreamException, Exception
     {
-        createBuildDatabase();
+        createBuildDatabase( true );
 
         // test sanity check
         assertBuildDatabase();
@@ -94,31 +118,32 @@
 
         //assertEquals( "Check database content", removeTimestampVariance( sw.toString() ),
         //              removeTimestampVariance( FileUtils.fileRead( backupFile ) ) );        
-        assertXmlSimilar( removeTimestampVariance( sw.toString() ), removeTimestampVariance( FileUtils.fileRead( backupFile ) ));
+        assertXmlSimilar( removeTimestampVariance( sw.toString() ), removeTimestampVariance( FileUtils.fileRead(
+            backupFile ) ) );
     }
 
     public void testEraseBuilds()
         throws Exception
     {
-        createBuildDatabase();
+        createBuildDatabase( false );
 
         dataManagementTool.eraseDatabase();
 
-        assertEmpty();
+        assertEmpty( false );
     }
 
     public void testRestoreBuilds()
         throws Exception
     {
-        createBuildDatabase( false );
+        createBuildDatabase( false, true );
 
-        assertEmpty();
+        assertEmpty( true );
 
         File backupFile = new File( targetDirectory, BUILDS_XML );
 
         IOUtil.copy( getClass().getResourceAsStream( "/expected.xml" ), new FileWriter( backupFile ) );
 
-        dataManagementTool.restoreDatabase( targetDirectory );
+        dataManagementTool.restoreDatabase( targetDirectory, true );
 /*
         // TODO: why is this wrong?
         assertBuildDatabase();
diff --git a/continuum-data-management/data-management-jdo/src/test/resources/expected.xml b/continuum-data-management/data-management-jdo/src/test/resources/expected.xml
index 5e2a8b0..28f9aa3 100644
--- a/continuum-data-management/data-management-jdo/src/test/resources/expected.xml
+++ b/continuum-data-management/data-management-jdo/src/test/resources/expected.xml
@@ -1,4 +1,23 @@
 <?xml version='1.0' encoding='UTF-8'?>
+<!--
+  ~ 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.
+  -->
+
 <continuumDatabase>
   <projectGroups>
     <projectGroup>
@@ -23,10 +42,11 @@
               <project id="1"></project>
               <id>1</id>
               <buildNumber>1</buildNumber>
-              <state>1</state>
+              <username>user</username>
+              <state>2</state>
               <trigger>1</trigger>
-              <startTime>1164693625928</startTime>
-              <endTime>1164693626928</endTime>
+              <startTime>1239794961904</startTime>
+              <endTime>1239794962904</endTime>
               <error>error1</error>
               <success>true</success>
               <exitCode>1</exitCode>
@@ -38,7 +58,7 @@
                   <change>
                     <author>author1.1</author>
                     <comment>comment1.1</comment>
-                    <date>1164693625935</date>
+                    <date>1239794961904</date>
                     <files>
                       <file>
                         <name>name1.1.1</name>
@@ -57,7 +77,7 @@
                   <change>
                     <author>author1.2</author>
                     <comment>comment1.2</comment>
-                    <date>1164693625936</date>
+                    <date>1239794961904</date>
                     <files>
                       <file>
                         <name>name1.2.1</name>
@@ -80,10 +100,11 @@
               <project id="1"></project>
               <id>2</id>
               <buildNumber>2</buildNumber>
-              <state>2</state>
+              <username>schedule</username>
+              <state>3</state>
               <trigger>2</trigger>
-              <startTime>1164693627928</startTime>
-              <endTime>1164693628928</endTime>
+              <startTime>1239794963904</startTime>
+              <endTime>1239794964904</endTime>
               <error>error2</error>
               <exitCode>2</exitCode>
             </buildResult>
@@ -95,7 +116,7 @@
               <change>
                 <author>authorCO1.1</author>
                 <comment>commentCO1.1</comment>
-                <date>1164693625936</date>
+                <date>1239794961904</date>
                 <files>
                   <file>
                     <name>nameCO1.1.1</name>
@@ -114,7 +135,7 @@
               <change>
                 <author>authorCO1.2</author>
                 <comment>commentCO1.2</comment>
-                <date>1164693625936</date>
+                <date>1239794961904</date>
                 <files>
                   <file>
                     <name>nameCO1.2.1</name>
@@ -155,7 +176,7 @@
           <projectGroup id="1"></projectGroup>
           <notifiers>
             <notifier>
-              <id>3</id>
+              <id>1</id>
               <type>type11</type>
               <recipientType>11</recipientType>
               <sendOnSuccess>false</sendOnSuccess>
@@ -167,7 +188,7 @@
           </notifiers>
           <buildDefinitions>
             <buildDefinition>
-              <id>1</id>
+              <id>3</id>
               <goals>goals11</goals>
               <arguments>arguments11</arguments>
               <buildFile>buildFile11</buildFile>
@@ -175,7 +196,7 @@
               <profile id="2"></profile>
             </buildDefinition>
             <buildDefinition>
-              <id>2</id>
+              <id>4</id>
               <goals>goals12</goals>
               <arguments>arguments12</arguments>
               <buildFile>buildFile12</buildFile>
@@ -200,10 +221,11 @@
               <project id="2"></project>
               <id>3</id>
               <buildNumber>3</buildNumber>
-              <state>3</state>
-              <trigger>3</trigger>
-              <startTime>1164693629928</startTime>
-              <endTime>1164693630928</endTime>
+              <username>schedule</username>
+              <state>2</state>
+              <trigger>2</trigger>
+              <startTime>1239794965904</startTime>
+              <endTime>1239794966904</endTime>
               <error>error3</error>
               <success>true</success>
               <exitCode>3</exitCode>
@@ -215,7 +237,7 @@
                   <change>
                     <author>author3.1</author>
                     <comment>comment3.1</comment>
-                    <date>1164693625936</date>
+                    <date>1239794961904</date>
                     <files>
                       <file>
                         <name>name3.1.1</name>
@@ -234,7 +256,7 @@
                   <change>
                     <author>author3.2</author>
                     <comment>comment3.2</comment>
-                    <date>1164693625936</date>
+                    <date>1239794961904</date>
                     <files>
                       <file>
                         <name>name3.2.1</name>
@@ -278,7 +300,7 @@
           <projectGroup id="1"></projectGroup>
           <notifiers>
             <notifier>
-              <id>4</id>
+              <id>2</id>
               <type>type12</type>
               <recipientType>12</recipientType>
               <sendOnFailure>false</sendOnFailure>
@@ -289,7 +311,7 @@
               </configuration>
             </notifier>
             <notifier>
-              <id>5</id>
+              <id>3</id>
               <type>type13</type>
               <recipientType>13</recipientType>
               <sendOnSuccess>false</sendOnSuccess>
@@ -302,7 +324,7 @@
           </notifiers>
           <buildDefinitions>
             <buildDefinition>
-              <id>3</id>
+              <id>5</id>
               <goals>goals13</goals>
               <arguments>arguments13</arguments>
               <buildFile>buildFile13</buildFile>
@@ -310,7 +332,7 @@
               <profile id="1"></profile>
             </buildDefinition>
             <buildDefinition>
-              <id>8</id>
+              <id>6</id>
               <goals>deploy</goals>
             </buildDefinition>
           </buildDefinitions>
@@ -318,7 +340,7 @@
       </projects>
       <notifiers>
         <notifier>
-          <id>1</id>
+          <id>4</id>
           <type>type1</type>
           <recipientType>1</recipientType>
           <sendOnFailure>false</sendOnFailure>
@@ -328,7 +350,7 @@
           </configuration>
         </notifier>
         <notifier>
-          <id>2</id>
+          <id>5</id>
           <type>type2</type>
           <recipientType>2</recipientType>
           <sendOnSuccess>false</sendOnSuccess>
@@ -341,7 +363,7 @@
       </notifiers>
       <buildDefinitions>
         <buildDefinition>
-          <id>4</id>
+          <id>2</id>
           <goals>goals1</goals>
           <arguments>arguments1</arguments>
           <buildFile>buildFile1</buildFile>
@@ -371,7 +393,7 @@
       </notifiers>
       <buildDefinitions>
         <buildDefinition>
-          <id>5</id>
+          <id>7</id>
           <goals>goals2</goals>
           <arguments>arguments2</arguments>
           <buildFile>buildFile2</buildFile>
@@ -379,7 +401,7 @@
           <profile id="1"></profile>
         </buildDefinition>
         <buildDefinition>
-          <id>6</id>
+          <id>8</id>
           <goals>goals3</goals>
           <arguments>arguments3</arguments>
           <buildFile>buildFile3</buildFile>
@@ -387,7 +409,7 @@
           <profile id="2"></profile>
         </buildDefinition>
         <buildDefinition>
-          <id>7</id>
+          <id>9</id>
           <goals>deploy</goals>
         </buildDefinition>
       </buildDefinitions>
@@ -421,11 +443,18 @@
     </installation>
     <installation>
       <type>maven2</type>
-      <varValue>/usr/local/maven-2.0-alpha-3</varValue>    
+      <varValue>/usr/local/maven-2.0-alpha-3</varValue>
       <varName>M2_HOME</varName>
       <name>Maven 2.0 alpha 3</name>
       <installationId>2</installationId>
     </installation>
+    <installation>
+      <type>envvar</type>
+      <varValue>-Xms256m -Xmx256m</varValue>
+      <varName>MAVEN_OPTS</varName>
+      <name>Maven Heap Size</name>
+      <installationId>4</installationId>
+    </installation>
   </installations>
   <schedules>
     <schedule>
@@ -435,6 +464,10 @@
       <description>description1</description>
       <delay>1</delay>
       <cronExpression>cronExpression1</cronExpression>
+      <buildQueues>
+        <buildQueue id="1"></buildQueue>
+        <buildQueue id="2"></buildQueue>
+      </buildQueues>
     </schedule>
     <schedule>
       <id>1</id>
@@ -443,6 +476,10 @@
       <description>description2</description>
       <delay>2</delay>
       <cronExpression>cronExpression2</cronExpression>
+      <buildQueues>
+        <buildQueue id="2"></buildQueue>
+        <buildQueue id="3"></buildQueue>
+      </buildQueues>
     </schedule>
     <schedule>
       <id>3</id>
@@ -482,6 +519,17 @@
       <jdk installationId="1"></jdk>
       <builder installationId="2"></builder>
     </profile>
+    <profile>
+      <id>4</id>
+      <name>name4</name>
+      <description>description4</description>
+      <scmMode>4</scmMode>
+      <jdk installationId="1"></jdk>
+      <builder installationId="2"></builder>
+      <environmentVariables>
+        <environmentVariable installationId="4"></environmentVariable>
+      </environmentVariables>
+    </profile>
   </profiles>
   <localRepositories>
     <localRepository>
@@ -549,4 +597,46 @@
       <projectGroup id="2"></projectGroup>
     </projectScmRoot>
   </projectScmRoots>
+  <continuumReleaseResults>
+    <continuumReleaseResult>
+      <id>1</id>
+      <projectGroup id="2"></projectGroup>
+      <releaseGoal>releaseGoal</releaseGoal>
+    </continuumReleaseResult>
+  </continuumReleaseResults>
+  <buildDefinitionTemplates>
+    <buildDefinitionTemplate>
+      <id>1</id>
+      <name>template2</name>
+      <type>type2</type>
+      <buildDefinitions>
+        <buildDefinition id="1"></buildDefinition>
+      </buildDefinitions>
+    </buildDefinitionTemplate>
+  </buildDefinitionTemplates>
+  <buildQueues>
+    <buildQueue>
+      <id>1</id>
+      <name>build queue 1</name>
+    </buildQueue>
+    <buildQueue>
+      <id>2</id>
+      <name>build queue 2</name>
+    </buildQueue>
+    <buildQueue>
+      <id>3</id>
+      <name>build queue 3</name>
+    </buildQueue>
+  </buildQueues>
+  <buildDefinitions>
+    <buildDefinition>
+      <id>1</id>
+      <goals>goals14</goals>
+      <arguments>arguments14</arguments>
+      <buildFile>buildFile14</buildFile>
+      <schedule id="2"></schedule>
+      <profile id="1"></profile>
+      <template>true</template>
+    </buildDefinition>
+  </buildDefinitions>
 </continuumDatabase>
diff --git a/continuum-data-management/data-management-jdo/src/test/resources/org/apache/maven/continuum/management/DataManagementToolTest.xml b/continuum-data-management/data-management-jdo/src/test/resources/org/apache/maven/continuum/management/DataManagementToolTest.xml
index d8d0064..1a6185c 100644
--- a/continuum-data-management/data-management-jdo/src/test/resources/org/apache/maven/continuum/management/DataManagementToolTest.xml
+++ b/continuum-data-management/data-management-jdo/src/test/resources/org/apache/maven/continuum/management/DataManagementToolTest.xml
@@ -26,7 +26,7 @@
       <configuration>
         <!-- Database Configuration -->
         <driverName>org.hsqldb.jdbcDriver</driverName>
-        <url>jdbc:hsqldb:mem:database</url>
+        <url>jdbc:hsqldb:mem:.</url>
         <userName>sa</userName>
         <password></password>
         <persistenceManagerFactoryClass>org.jpox.PersistenceManagerFactoryImpl</persistenceManagerFactoryClass>
diff --git a/continuum-data-management/data-management-redback-jdo/pom.xml b/continuum-data-management/data-management-redback-jdo/pom.xml
index bc62b04..f6c3a14 100644
--- a/continuum-data-management/data-management-redback-jdo/pom.xml
+++ b/continuum-data-management/data-management-redback-jdo/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <artifactId>continuum-data-management</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>data-management-redback-jdo</artifactId>
@@ -33,10 +33,28 @@
       <artifactId>data-management-api</artifactId>
     </dependency>
     <dependency>
+      <groupId>javax.jdo</groupId>
+      <artifactId>jdo2-api</artifactId>
+    </dependency>
+    <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-jdo2</artifactId>
     </dependency>
     <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-utils</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus.security</groupId>
+      <artifactId>plexus-security-authorization-rbac-model</artifactId>
+      <version>1.0-alpha-5</version>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus.security</groupId>
+      <artifactId>plexus-security-user-management-api</artifactId>
+      <version>1.0-alpha-5</version>
+    </dependency>
+    <dependency>
       <groupId>org.apache.continuum</groupId>
       <artifactId>redback-legacy</artifactId>
     </dependency>
@@ -44,5 +62,21 @@
       <groupId>org.codehaus.redback</groupId>
       <artifactId>redback-data-management</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>redback-rbac-model</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>redback-users-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>redback-keys-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>stax</groupId>
+      <artifactId>stax-api</artifactId>
+    </dependency>
   </dependencies>
 </project>
diff --git a/continuum-data-management/data-management-redback-jdo/src/main/java/org/apache/maven/continuum/management/redback/JdoDataManagementTool.java b/continuum-data-management/data-management-redback-jdo/src/main/java/org/apache/maven/continuum/management/redback/JdoDataManagementTool.java
index 4cec1d1..e03a094 100644
--- a/continuum-data-management/data-management-redback-jdo/src/main/java/org/apache/maven/continuum/management/redback/JdoDataManagementTool.java
+++ b/continuum-data-management/data-management-redback-jdo/src/main/java/org/apache/maven/continuum/management/redback/JdoDataManagementTool.java
@@ -26,12 +26,13 @@
 import org.codehaus.plexus.redback.rbac.RbacManagerException;
 import org.codehaus.plexus.redback.users.UserManager;
 
-import javax.xml.stream.XMLStreamException;
 import java.io.File;
 import java.io.IOException;
+import javax.xml.stream.XMLStreamException;
 
 /**
  * JDO implementation the database management tool API.
+ *
  * @version $Id$
  * @plexus.component role="org.apache.maven.continuum.management.DataManagementTool" role-hint="redback-jdo"
  */
@@ -84,7 +85,7 @@
         toolDelegate.eraseUsersDatabase( userManager );
     }
 
-    public void restoreDatabase( File backupDirectory )
+    public void restoreDatabase( File backupDirectory, boolean strict )
         throws IOException
     {
         try
diff --git a/continuum-data-management/data-management-redback-jdo/src/main/java/org/apache/maven/continuum/management/redback/LegacyJdoDataManagementTool.java b/continuum-data-management/data-management-redback-jdo/src/main/java/org/apache/maven/continuum/management/redback/LegacyJdoDataManagementTool.java
index 4f86c5f..f278b36 100644
--- a/continuum-data-management/data-management-redback-jdo/src/main/java/org/apache/maven/continuum/management/redback/LegacyJdoDataManagementTool.java
+++ b/continuum-data-management/data-management-redback-jdo/src/main/java/org/apache/maven/continuum/management/redback/LegacyJdoDataManagementTool.java
@@ -50,9 +50,6 @@
 import org.codehaus.plexus.util.IOUtil;
 import org.codehaus.plexus.util.StringUtils;
 
-import javax.jdo.JDOHelper;
-import javax.jdo.PersistenceManager;
-import javax.xml.stream.XMLStreamException;
 import java.io.File;
 import java.io.FileReader;
 import java.io.FileWriter;
@@ -62,9 +59,13 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import javax.jdo.JDOHelper;
+import javax.jdo.PersistenceManager;
+import javax.xml.stream.XMLStreamException;
 
 /**
  * JDO implementation the database management tool API.
+ *
  * @version $Id$
  * @plexus.component role="org.apache.maven.continuum.management.DataManagementTool" role-hint="legacy-redback-jdo"
  */
@@ -101,7 +102,7 @@
         }
     }
 
-    public void restoreDatabase( File backupDirectory )
+    public void restoreDatabase( File backupDirectory, boolean strict )
         throws IOException, DataManagementException
     {
         try
@@ -136,8 +137,8 @@
     {
         RbacDatabase database = new RbacDatabase();
         database.setRoles( PlexusJdoUtils.getAllObjectsDetached( getPersistenceManager(), JdoRole.class ) );
-        database.setUserAssignments(
-            PlexusJdoUtils.getAllObjectsDetached( getPersistenceManager(), JdoUserAssignment.class ) );
+        database.setUserAssignments( PlexusJdoUtils.getAllObjectsDetached( getPersistenceManager(),
+                                                                           JdoUserAssignment.class ) );
         database.setPermissions( PlexusJdoUtils.getAllObjectsDetached( getPersistenceManager(), JdoPermission.class ) );
         database.setOperations( PlexusJdoUtils.getAllObjectsDetached( getPersistenceManager(), JdoOperation.class ) );
         database.setResources( PlexusJdoUtils.getAllObjectsDetached( getPersistenceManager(), JdoResource.class ) );
@@ -260,8 +261,8 @@
                     else
                     {
                         RBACObjectAssertions.assertValid( operation );
-                        operation =
-                            (JdoOperation) PlexusJdoUtils.saveObject( getPersistenceManager(), operation, null );
+                        operation = (JdoOperation) PlexusJdoUtils.saveObject( getPersistenceManager(), operation,
+                                                                              null );
                         operations.put( operation.getName(), operation );
                     }
                     permission.setOperation( operation );
@@ -338,13 +339,13 @@
             if ( !( user instanceof JdoUser ) )
             {
                 throw new UserManagerException( "Unable to Add User. User object " + user.getClass().getName() +
-                    " is not an instance of " + JdoUser.class.getName() );
+                                                    " is not an instance of " + JdoUser.class.getName() );
             }
 
             if ( StringUtils.isEmpty( user.getUsername() ) )
             {
-                throw new IllegalStateException(
-                    Messages.getString( "user.manager.cannot.add.user.without.username" ) ); //$NON-NLS-1$
+                throw new IllegalStateException( Messages.getString(
+                    "user.manager.cannot.add.user.without.username" ) ); //$NON-NLS-1$
             }
 
             PlexusJdoUtils.addObject( getPersistenceManager(), user );
diff --git a/continuum-data-management/pom.xml b/continuum-data-management/pom.xml
index d5f176b..c49f36e 100644
--- a/continuum-data-management/pom.xml
+++ b/continuum-data-management/pom.xml
@@ -1,22 +1,23 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
+  ~ 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.
+  -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <prerequisites>
@@ -25,19 +26,20 @@
   <parent>
     <artifactId>continuum</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <packaging>pom</packaging>
   <artifactId>continuum-data-management</artifactId>
   <name>Continuum :: Data Management :: Parent</name>
   <modules>
-    <module>data-management-cli</module>
     <module>data-management-api</module>
     <module>continuum-legacy</module>
     <module>data-management-jdo</module>
     <!-- TODO: move to redback data management -->
     <module>redback-legacy</module>
     <module>data-management-redback-jdo</module>
+    <!-- Must come after the above since we are not using dependencies to control build order -->
+    <module>data-management-cli</module>
   </modules>
   <build>
     <plugins>
diff --git a/continuum-data-management/redback-legacy/pom.xml b/continuum-data-management/redback-legacy/pom.xml
index def2206..b628bc2 100644
--- a/continuum-data-management/redback-legacy/pom.xml
+++ b/continuum-data-management/redback-legacy/pom.xml
@@ -1,8 +1,27 @@
+<!--
+  ~ 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.
+  -->
+
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <artifactId>continuum-data-management</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>redback-legacy</artifactId>
@@ -16,149 +35,79 @@
           <execution>
             <id>modello-rbac</id>
             <goals>
-              <goal>jpox-metadata-class</goal>
               <goal>java</goal>
               <goal>stax-reader</goal>
               <goal>stax-writer</goal>
             </goals>
             <configuration>
-              <model>src/main/mdo/rbac-jdo.mdo</model>
-            </configuration>
-          </execution>
-          <execution>
-            <id>jpox-jdo-mapping-rbac</id>
-            <goals>
-              <goal>jpox-jdo-mapping</goal>
-            </goals>
-            <configuration>
-              <model>src/main/mdo/rbac-jdo.mdo</model>
-              <outputDirectory>
-                ${basedir}/target/classes/org/codehaus/plexus/security/authorization/rbac/jdo
-              </outputDirectory>
-            </configuration>
-          </execution>
-          <execution>
-            <id>jpox-jdo-mapping-rbac-replication</id>
-            <goals>
-              <goal>jpox-jdo-mapping</goal>
-            </goals>
-            <configuration>
-              <model>src/main/mdo/rbac-jdo.mdo</model>
-              <outputDirectory>
-                ${basedir}/target/classes/org/codehaus/plexus/security/authorization/rbac/jdo
-              </outputDirectory>
-              <replicationParameters>true</replicationParameters>
+              <models>
+                <model>src/main/mdo/rbac-jdo.mdo</model>
+              </models>
             </configuration>
           </execution>
           <execution>
             <id>modello-keys</id>
             <goals>
-              <goal>jpox-metadata-class</goal>
               <goal>java</goal>
               <goal>stax-reader</goal>
               <goal>stax-writer</goal>
             </goals>
             <configuration>
-              <model>src/main/mdo/keys-jdo.mdo</model>
-            </configuration>
-          </execution>
-          <execution>
-            <id>jpox-jdo-mapping-keys</id>
-            <goals>
-              <goal>jpox-jdo-mapping</goal>
-            </goals>
-            <configuration>
-              <model>src/main/mdo/keys-jdo.mdo</model>
-              <outputDirectory>
-                ${basedir}/target/classes/org/codehaus/plexus/security/keys/jdo
-              </outputDirectory>
-            </configuration>
-          </execution>
-          <execution>
-            <id>jpox-jdo-mapping-keys-replication</id>
-            <goals>
-              <goal>jpox-jdo-mapping</goal>
-            </goals>
-            <configuration>
-              <model>src/main/mdo/keys-jdo.mdo</model>
-              <outputDirectory>
-                ${basedir}/target/classes/org/codehaus/plexus/security/keys/jdo
-              </outputDirectory>
-              <replicationParameters>true</replicationParameters>
+              <models>
+                <model>src/main/mdo/keys-jdo.mdo</model>
+              </models>
             </configuration>
           </execution>
           <execution>
             <id>modello-users</id>
             <goals>
-              <goal>jpox-metadata-class</goal>
               <goal>java</goal>
               <goal>stax-reader</goal>
               <goal>stax-writer</goal>
             </goals>
             <configuration>
-              <model>src/main/mdo/users-jdo.mdo</model>
-            </configuration>
-          </execution>
-          <execution>
-            <id>jpox-jdo-mapping-users</id>
-            <goals>
-              <goal>jpox-jdo-mapping</goal>
-            </goals>
-            <configuration>
-              <model>src/main/mdo/users-jdo.mdo</model>
-              <outputDirectory>
-                ${basedir}/target/classes/org/codehaus/plexus/security/user/jdo
-              </outputDirectory>
-            </configuration>
-          </execution>
-          <execution>
-            <id>jpox-jdo-mapping-users-replication</id>
-            <goals>
-              <goal>jpox-jdo-mapping</goal>
-            </goals>
-            <configuration>
-              <model>src/main/mdo/users-jdo.mdo</model>
-              <outputDirectory>
-                ${basedir}/target/classes/org/codehaus/plexus/security/user/jdo
-              </outputDirectory>
-              <replicationParameters>true</replicationParameters>
+              <models>
+                <model>src/main/mdo/users-jdo.mdo</model>
+              </models>
             </configuration>
           </execution>
         </executions>
         <configuration>
           <version>0.9.0</version>
           <packageWithVersion>true</packageWithVersion>
+          <!--<useJava5>true</useJava5>-->
         </configuration>
       </plugin>
       <plugin>
+        <groupId>com.google.code.maven-replacer-plugin</groupId>
+        <artifactId>replacer</artifactId>
+        <executions>
+          <execution>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>replace</goal>
+            </goals>
+            <configuration>
+              <basedir>${basedir}</basedir>
+              <includes>
+                <include>target/generated-sources/**</include>
+              </includes>
+              <token>Generated by Modello.*</token>
+              <value>Generated by Modello</value>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
         <artifactId>maven-antrun-plugin</artifactId>
         <executions>
           <execution>
-            <id>hack-sources</id>
-            <phase>generate-sources</phase>
+            <id>copy-resources</id>
+            <phase>process-resources</phase>
             <configuration>
               <tasks>
-                <!-- Workaround for MODELLO-89 -->
-                <replace file="target/generated-sources/modello/org/codehaus/plexus/security/keys/jdo/v0_9_0/PlexusSecurityKeyManagementJdoModelloMetadata.java" token="jdo;" value="jdo.v0_9_0;" />
-                <replace file="target/generated-sources/modello/org/codehaus/plexus/security/authorization/rbac/jdo/v0_9_0/RbacJdoModelModelloMetadata.java" token="jdo;" value="jdo.v0_9_0;" />
-                <replace file="target/generated-sources/modello/org/codehaus/plexus/security/user/jdo/v0_9_0/UserManagementModelloMetadata.java" token="jdo;" value="jdo.v0_9_0;" />
-              </tasks>
-            </configuration>
-            <goals>
-              <goal>run</goal>
-            </goals>
-          </execution>
-          <execution>
-            <id>hack-resources</id>
-            <phase>process-classes</phase>
-            <configuration>
-              <tasks>
-                <!-- Workaround for MODELLO-91 -->
-                <replace dir="target/classes/org/codehaus/plexus/security/user/jdo" token="name=&quot;USER_PASSWORD&quot;" value="name=&quot;PASSWORD&quot;" />
-                <replace dir="target/classes/org/codehaus/plexus/security/authorization/rbac/jdo" token="SECURITY_" value="" />
-                <replace dir="target/classes/org/codehaus/plexus/security/authorization/rbac/jdo" token="name=&quot;RBAC_OPERATION&quot;" value="name=&quot;OPERATION&quot;" />
-                <replace dir="target/classes/org/codehaus/plexus/security/authorization/rbac/jdo" token="name=&quot;RBAC_RESOURCE&quot;" value="name=&quot;RESOURCE&quot;" />
-                <replace dir="target/classes/org/codehaus/plexus/security/authorization/rbac/jdo" token="name=&quot;LAST_UPDATED&quot;" value="name=&quot;TIMESTAMP&quot;" />
+                <copy file="target/classes/org/codehaus/plexus/security/authorization/rbac/jdo/package.jdorepl" todir="target/classes" />
+                <copy file="target/classes/org/codehaus/plexus/security/authorization/rbac/jdo/package.jdo" todir="target/classes" />
               </tasks>
             </configuration>
             <goals>
@@ -170,7 +119,6 @@
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>jpox-maven-plugin</artifactId>
-        <version>1.1.6</version>
         <executions>
           <execution>
             <goals>
@@ -185,18 +133,10 @@
     <dependency>
       <groupId>net.java.dev.stax-utils</groupId>
       <artifactId>stax-utils</artifactId>
-      <version>20060502</version>
-      <exclusions>
-        <exclusion>
-          <groupId>com.bea.xml</groupId>
-          <artifactId>jsr173-ri</artifactId>
-        </exclusion>
-      </exclusions>
     </dependency>
     <dependency>
       <groupId>stax</groupId>
       <artifactId>stax-api</artifactId>
-      <version>1.0.1</version>
     </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
diff --git a/continuum-data-management/redback-legacy/src/main/java/org/codehaus/plexus/security/authorization/rbac/jdo/v0_9_0/RbacJdoModelModelloMetadata.java b/continuum-data-management/redback-legacy/src/main/java/org/codehaus/plexus/security/authorization/rbac/jdo/v0_9_0/RbacJdoModelModelloMetadata.java
new file mode 100644
index 0000000..a427f63
--- /dev/null
+++ b/continuum-data-management/redback-legacy/src/main/java/org/codehaus/plexus/security/authorization/rbac/jdo/v0_9_0/RbacJdoModelModelloMetadata.java
@@ -0,0 +1,35 @@
+package org.codehaus.plexus.security.authorization.rbac.jdo.v0_9_0;
+
+/*
+ * 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.
+ */
+
+public class RbacJdoModelModelloMetadata
+{
+    private String modelVersion;
+
+    public String getModelVersion()
+    {
+        return modelVersion;
+    }
+
+    public void setModelVersion( String modelVersion )
+    {
+        this.modelVersion = modelVersion;
+    }
+}
diff --git a/continuum-data-management/redback-legacy/src/main/java/org/codehaus/plexus/security/keys/jdo/v0_9_0/PlexusSecurityKeyManagementJdoModelloMetadata.java b/continuum-data-management/redback-legacy/src/main/java/org/codehaus/plexus/security/keys/jdo/v0_9_0/PlexusSecurityKeyManagementJdoModelloMetadata.java
new file mode 100644
index 0000000..5d18c97
--- /dev/null
+++ b/continuum-data-management/redback-legacy/src/main/java/org/codehaus/plexus/security/keys/jdo/v0_9_0/PlexusSecurityKeyManagementJdoModelloMetadata.java
@@ -0,0 +1,35 @@
+package org.codehaus.plexus.security.keys.jdo.v0_9_0;
+
+/*
+ * 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.
+ */
+
+public class PlexusSecurityKeyManagementJdoModelloMetadata
+{
+    private String modelVersion;
+
+    public String getModelVersion()
+    {
+        return modelVersion;
+    }
+
+    public void setModelVersion( String modelVersion )
+    {
+        this.modelVersion = modelVersion;
+    }
+}
diff --git a/continuum-data-management/redback-legacy/src/main/java/org/codehaus/plexus/security/user/jdo/v0_9_0/UserManagementModelloMetadata.java b/continuum-data-management/redback-legacy/src/main/java/org/codehaus/plexus/security/user/jdo/v0_9_0/UserManagementModelloMetadata.java
new file mode 100644
index 0000000..109e33b
--- /dev/null
+++ b/continuum-data-management/redback-legacy/src/main/java/org/codehaus/plexus/security/user/jdo/v0_9_0/UserManagementModelloMetadata.java
@@ -0,0 +1,35 @@
+package org.codehaus.plexus.security.user.jdo.v0_9_0;
+
+/*
+ * 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.
+ */
+
+public class UserManagementModelloMetadata
+{
+    private String modelVersion;
+
+    public String getModelVersion()
+    {
+        return modelVersion;
+    }
+
+    public void setModelVersion( String modelVersion )
+    {
+        this.modelVersion = modelVersion;
+    }
+}
diff --git a/continuum-data-management/redback-legacy/src/main/mdo/rbac-jdo.mdo b/continuum-data-management/redback-legacy/src/main/mdo/rbac-jdo.mdo
index 5da3868..a68e399 100644
--- a/continuum-data-management/redback-legacy/src/main/mdo/rbac-jdo.mdo
+++ b/continuum-data-management/redback-legacy/src/main/mdo/rbac-jdo.mdo
@@ -78,7 +78,7 @@
       </fields>
     </class>
 
-    <class jpox.stashable="true" 
+    <class jpox.stashable="true"
            jpox.table="ROLES"
            jpox.not-persisted-fields="modelEncoding">
       <name>JdoRole</name>
@@ -115,16 +115,16 @@
             true if this object is permanent.
           </description>
         </field>
-        <field jpox.persistence-modifier="persistent" 
+        <field jpox.persistence-modifier="persistent"
                jpox.fetch-groups="role-child-detail"
                jpox.join-table="ROLE_CHILDROLE_MAP">
           <name>childRoleNames</name>
           <version>0.9.0</version>
-          <association stash.part="true" 
+          <association stash.part="true"
                        jpox.join="true"
-                       java.init="field" 
+                       java.init="field"
                        jpox.dependent="false"
-                       java.generate-break="false" 
+                       java.generate-break="false"
                        java.generate-create="false"
                        zjava.use-interface="org.codehaus.plexus.security.rbac.Role">
             <type>String</type>
@@ -153,7 +153,7 @@
       </fields>
     </class>
 
-    <class jpox.stashable="true" 
+    <class jpox.stashable="true"
            jpox.table="PERMISSIONS"
            jpox.not-persisted-fields="modelEncoding">
       <name>JdoPermission</name>
@@ -184,7 +184,7 @@
         <field jpox.indexed="true" jpox.column="RBAC_OPERATION">
           <name>operation</name>
           <version>0.9.0</version>
-          <association stash.part="true" 
+          <association stash.part="true"
                        xml.reference="true"
                        java.use-interface="org.codehaus.plexus.security.rbac.Operation"
                        jpox.dependent="false">
@@ -195,7 +195,7 @@
         <field jpox.indexed="true" jpox.column="RBAC_RESOURCE">
           <name>resource</name>
           <version>0.9.0</version>
-          <association stash.part="true" 
+          <association stash.part="true"
                        xml.reference="true"
                        java.use-interface="org.codehaus.plexus.security.rbac.Resource"
                        jpox.dependent="false">
@@ -206,7 +206,7 @@
       </fields>
     </class>
 
-    <class jpox.stashable="true" 
+    <class jpox.stashable="true"
            jpox.table="OPERATIONS"
            jpox.not-persisted-fields="modelEncoding">
       <name>JdoOperation</name>
@@ -245,7 +245,7 @@
       </fields>
     </class>
 
-    <class jpox.stashable="true" 
+    <class jpox.stashable="true"
            jpox.table="RESOURCES"
            jpox.not-persisted-fields="modelEncoding">
       <name>JdoResource</name>
@@ -286,7 +286,7 @@
       </fields>
     </class>
 
-    <class jpox.stashable="true" 
+    <class jpox.stashable="true"
            jpox.table="USER_ASSIGNMENTS"
            jpox.not-persisted-fields="modelEncoding">
       <name>JdoUserAssignment</name>
@@ -317,12 +317,12 @@
           </description>
         </field>
         <field java.adder="false"
-               jpox.persistence-modifier="persistent" 
+               jpox.persistence-modifier="persistent"
                jpox.indexed="false"
                jpox.join-table="USERASSIGNMENT_ROLENAMES">
           <name>roleNames</name>
           <version>0.9.0</version>
-          <association stash.part="true" 
+          <association stash.part="true"
                        jpox.join="true"
                        java.init="field"
                        java.generate-break="false"
diff --git a/continuum-data-management/redback-legacy/src/main/resources/org/codehaus/plexus/security/authorization/rbac/jdo/package.jdo b/continuum-data-management/redback-legacy/src/main/resources/org/codehaus/plexus/security/authorization/rbac/jdo/package.jdo
new file mode 100644
index 0000000..d7b99fd
--- /dev/null
+++ b/continuum-data-management/redback-legacy/src/main/resources/org/codehaus/plexus/security/authorization/rbac/jdo/package.jdo
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ 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.
+  -->
+<!DOCTYPE jdo PUBLIC
+  "-//Sun Microsystems, Inc.//DTD Java Data Objects Metadata 2.0//EN"
+  "http://java.sun.com/dtd/jdo_2_0.dtd">
+
+<jdo>
+  <package name="org.codehaus.plexus.security.authorization.rbac.jdo.v0_9_0">
+    <class name="RbacDatabase" detachable="true" table="RbacDatabase">
+      <field name="roles">
+        <collection element-type="JdoRole" dependent-element="true"/>
+        <join/>
+      </field>
+      <field name="permissions">
+        <collection element-type="JdoPermission" dependent-element="true"/>
+        <join/>
+      </field>
+      <field name="operations">
+        <collection element-type="JdoOperation" dependent-element="true"/>
+        <join/>
+      </field>
+      <field name="resources">
+        <collection element-type="JdoResource" dependent-element="true"/>
+        <join/>
+      </field>
+      <field name="userAssignments">
+        <collection element-type="JdoUserAssignment" dependent-element="true"/>
+        <join/>
+      </field>
+      <fetch-group name="RbacDatabase_detail">
+        <field name="roles"/>
+        <field name="permissions"/>
+        <field name="operations"/>
+        <field name="resources"/>
+        <field name="userAssignments"/>
+      </fetch-group>
+    </class>
+    <class name="JdoRole" detachable="true" table="ROLES" identity-type="application" objectid-class="javax.jdo.identity.StringIdentity">
+      <field name="name" primary-key="true"/>
+      <field name="description"/>
+      <field name="assignable"/>
+      <field name="permanent"/>
+      <field name="childRoleNames" persistence-modifier="persistent" table="ROLE_CHILDROLE_MAP" default-fetch-group="true">
+        <collection element-type="java.lang.String" dependent-element="false"/>
+        <join/>
+      </field>
+      <field name="permissions" table="ROLE_PERMISSION_MAP" default-fetch-group="true">
+        <collection element-type="JdoPermission" dependent-element="false"/>
+        <join/>
+      </field>
+      <fetch-group name="role-child-detail">
+        <field name="childRoleNames"/>
+        <field name="permissions"/>
+      </fetch-group>
+    </class>
+    <class name="JdoPermission" detachable="true" table="PERMISSIONS" identity-type="application" objectid-class="javax.jdo.identity.StringIdentity">
+      <field name="name" primary-key="true"/>
+      <field name="description"/>
+      <field name="permanent"/>
+      <field name="operation" indexed="true" default-fetch-group="true"/>
+      <field name="resource" indexed="true" default-fetch-group="true"/>
+    </class>
+    <class name="JdoOperation" detachable="true" table="OPERATIONS" identity-type="application" objectid-class="javax.jdo.identity.StringIdentity">
+      <field name="name" primary-key="true"/>
+      <field name="description"/>
+      <field name="permanent"/>
+      <field name="resourceRequired"/>
+    </class>
+    <class name="JdoResource" detachable="true" table="RESOURCES" identity-type="application" objectid-class="javax.jdo.identity.StringIdentity">
+      <field name="identifier" primary-key="true"/>
+      <field name="pattern"/>
+      <field name="permanent"/>
+    </class>
+    <class name="JdoUserAssignment" detachable="true" table="USER_ASSIGNMENTS" identity-type="application" objectid-class="javax.jdo.identity.StringIdentity">
+      <field name="principal" primary-key="true"/>
+      <field name="timestamp">
+        <column name="TIMESTAMP"/>
+      </field>
+      <field name="permanent"/>
+      <field name="roleNames" persistence-modifier="persistent" table="USERASSIGNMENT_ROLENAMES" indexed="false" default-fetch-group="true">
+        <collection element-type="java.lang.String" dependent-element="true"/>
+        <join/>
+      </field>
+    </class>
+    <class name="RbacJdoModelModelloMetadata" detachable="true">
+      <field name="modelVersion" null-value="default">
+        <column default-value="0.9.0"/>
+      </field>
+    </class>
+  </package>
+</jdo>
diff --git a/continuum-data-management/redback-legacy/src/main/resources/org/codehaus/plexus/security/authorization/rbac/jdo/package.jdorepl b/continuum-data-management/redback-legacy/src/main/resources/org/codehaus/plexus/security/authorization/rbac/jdo/package.jdorepl
new file mode 100644
index 0000000..0212dca
--- /dev/null
+++ b/continuum-data-management/redback-legacy/src/main/resources/org/codehaus/plexus/security/authorization/rbac/jdo/package.jdorepl
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ 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.
+  -->
+<!DOCTYPE jdo PUBLIC
+  "-//Sun Microsystems, Inc.//DTD Java Data Objects Metadata 2.0//EN"
+  "http://java.sun.com/dtd/jdo_2_0.dtd">
+
+<jdo>
+  <package name="org.codehaus.plexus.security.authorization.rbac.jdo.v0_9_0">
+    <class name="RbacDatabase" detachable="true" table="RbacDatabase">
+      <field name="roles">
+        <collection element-type="JdoRole" dependent-element="true"/>
+        <join/>
+      </field>
+      <field name="permissions">
+        <collection element-type="JdoPermission" dependent-element="true"/>
+        <join/>
+      </field>
+      <field name="operations">
+        <collection element-type="JdoOperation" dependent-element="true"/>
+        <join/>
+      </field>
+      <field name="resources">
+        <collection element-type="JdoResource" dependent-element="true"/>
+        <join/>
+      </field>
+      <field name="userAssignments">
+        <collection element-type="JdoUserAssignment" dependent-element="true"/>
+        <join/>
+      </field>
+      <fetch-group name="RbacDatabase_detail">
+        <field name="roles"/>
+        <field name="permissions"/>
+        <field name="operations"/>
+        <field name="resources"/>
+        <field name="userAssignments"/>
+      </fetch-group>
+    </class>
+    <class name="JdoRole" detachable="true" table="ROLES" identity-type="application">
+      <field name="name" primary-key="true"/>
+      <field name="description"/>
+      <field name="assignable"/>
+      <field name="permanent"/>
+      <field name="childRoleNames" persistence-modifier="persistent" table="ROLE_CHILDROLE_MAP" default-fetch-group="true">
+        <collection element-type="java.lang.String" dependent-element="false"/>
+        <join/>
+      </field>
+      <field name="permissions" table="ROLE_PERMISSION_MAP" default-fetch-group="true">
+        <collection element-type="JdoPermission" dependent-element="false"/>
+        <join/>
+      </field>
+      <fetch-group name="role-child-detail">
+        <field name="childRoleNames"/>
+        <field name="permissions"/>
+      </fetch-group>
+    </class>
+    <class name="JdoPermission" detachable="true" table="PERMISSIONS" identity-type="application">
+      <field name="name" primary-key="true"/>
+      <field name="description"/>
+      <field name="permanent"/>
+      <field name="operation" indexed="true" default-fetch-group="true"/>
+      <field name="resource" indexed="true" default-fetch-group="true"/>
+    </class>
+    <class name="JdoOperation" detachable="true" table="OPERATIONS" identity-type="application">
+      <field name="name" primary-key="true"/>
+      <field name="description"/>
+      <field name="permanent"/>
+      <field name="resourceRequired"/>
+    </class>
+    <class name="JdoResource" detachable="true" table="RESOURCES" identity-type="application">
+      <field name="identifier" primary-key="true"/>
+      <field name="pattern"/>
+      <field name="permanent"/>
+    </class>
+    <class name="JdoUserAssignment" detachable="true" table="USER_ASSIGNMENTS" identity-type="application">
+      <field name="principal" primary-key="true"/>
+      <field name="timestamp">
+        <column name="TIMESTAMP"/>
+      </field>
+      <field name="permanent"/>
+      <field name="roleNames" persistence-modifier="persistent" table="USERASSIGNMENT_ROLENAMES" indexed="false" default-fetch-group="true">
+        <collection element-type="java.lang.String" dependent-element="true"/>
+        <join/>
+      </field>
+    </class>
+    <class name="RbacJdoModelModelloMetadata" detachable="true">
+      <field name="modelVersion" null-value="default">
+        <column default-value="0.9.0"/>
+      </field>
+    </class>
+  </package>
+</jdo>
diff --git a/continuum-data-management/redback-legacy/src/main/resources/org/codehaus/plexus/security/keys/jdo/package.jdo b/continuum-data-management/redback-legacy/src/main/resources/org/codehaus/plexus/security/keys/jdo/package.jdo
new file mode 100644
index 0000000..4f9119a
--- /dev/null
+++ b/continuum-data-management/redback-legacy/src/main/resources/org/codehaus/plexus/security/keys/jdo/package.jdo
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ 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.
+  -->
+<!DOCTYPE jdo PUBLIC
+  "-//Sun Microsystems, Inc.//DTD Java Data Objects Metadata 2.0//EN"
+  "http://java.sun.com/dtd/jdo_2_0.dtd">
+
+<jdo>
+  <package name="org.codehaus.plexus.security.keys.jdo.v0_9_0">
+    <class name="AuthenticationKeyDatabase" detachable="true" table="AuthenticationKeyDatabase">
+      <field name="keys">
+        <collection element-type="JdoAuthenticationKey" dependent-element="true"/>
+        <join/>
+      </field>
+      <fetch-group name="AuthenticationKeyDatabase_detail">
+        <field name="keys"/>
+      </fetch-group>
+    </class>
+    <class name="JdoAuthenticationKey" detachable="true" table="JdoAuthenticationKey" identity-type="application" objectid-class="javax.jdo.identity.StringIdentity">
+      <field name="key" persistence-modifier="persistent" primary-key="true">
+        <column name="AUTHKEY"/>
+      </field>
+      <field name="forPrincipal"/>
+      <field name="purpose"/>
+      <field name="dateCreated"/>
+      <field name="dateExpires"/>
+    </class>
+    <class name="PlexusSecurityKeyManagementJdoModelloMetadata" detachable="true">
+      <field name="modelVersion" null-value="default">
+        <column default-value="0.9.0"/>
+      </field>
+    </class>
+  </package>
+</jdo>
diff --git a/continuum-data-management/redback-legacy/src/main/resources/org/codehaus/plexus/security/keys/jdo/package.jdorepl b/continuum-data-management/redback-legacy/src/main/resources/org/codehaus/plexus/security/keys/jdo/package.jdorepl
new file mode 100644
index 0000000..d4c249d
--- /dev/null
+++ b/continuum-data-management/redback-legacy/src/main/resources/org/codehaus/plexus/security/keys/jdo/package.jdorepl
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ 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.
+  -->
+<!DOCTYPE jdo PUBLIC
+  "-//Sun Microsystems, Inc.//DTD Java Data Objects Metadata 2.0//EN"
+  "http://java.sun.com/dtd/jdo_2_0.dtd">
+
+<jdo>
+  <package name="org.codehaus.plexus.security.keys.jdo.v0_9_0">
+    <class name="AuthenticationKeyDatabase" detachable="true" table="AuthenticationKeyDatabase">
+      <field name="keys">
+        <collection element-type="JdoAuthenticationKey" dependent-element="true"/>
+        <join/>
+      </field>
+      <fetch-group name="AuthenticationKeyDatabase_detail">
+        <field name="keys"/>
+      </fetch-group>
+    </class>
+    <class name="JdoAuthenticationKey" detachable="true" table="JdoAuthenticationKey" identity-type="application">
+      <field name="key" persistence-modifier="persistent" primary-key="true">
+        <column name="AUTHKEY"/>
+      </field>
+      <field name="forPrincipal"/>
+      <field name="purpose"/>
+      <field name="dateCreated"/>
+      <field name="dateExpires"/>
+    </class>
+    <class name="PlexusSecurityKeyManagementJdoModelloMetadata" detachable="true">
+      <field name="modelVersion" null-value="default">
+        <column default-value="0.9.0"/>
+      </field>
+    </class>
+  </package>
+</jdo>
diff --git a/continuum-data-management/redback-legacy/src/main/resources/org/codehaus/plexus/security/user/jdo/package.jdo b/continuum-data-management/redback-legacy/src/main/resources/org/codehaus/plexus/security/user/jdo/package.jdo
new file mode 100644
index 0000000..0a44906
--- /dev/null
+++ b/continuum-data-management/redback-legacy/src/main/resources/org/codehaus/plexus/security/user/jdo/package.jdo
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ 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.
+  -->
+<!DOCTYPE jdo PUBLIC
+  "-//Sun Microsystems, Inc.//DTD Java Data Objects Metadata 2.0//EN"
+  "http://java.sun.com/dtd/jdo_2_0.dtd">
+
+<jdo>
+  <package name="org.codehaus.plexus.security.user.jdo.v0_9_0">
+    <class name="UserDatabase" detachable="true" table="UserDatabase">
+      <field name="users">
+        <collection element-type="JdoUser" dependent-element="true"/>
+        <join/>
+      </field>
+      <fetch-group name="UserDatabase_detail">
+        <field name="users"/>
+      </fetch-group>
+    </class>
+    <class name="JdoUser" detachable="true" table="JdoUser" identity-type="application" objectid-class="javax.jdo.identity.StringIdentity">
+      <field name="username" persistence-modifier="persistent" primary-key="true"/>
+      <field name="password">
+        <column name="PASSWORD"/>
+      </field>
+      <field name="encodedPassword"/>
+      <field name="fullName"/>
+      <field name="email"/>
+      <field name="lastPasswordChange"/>
+      <field name="lastLoginDate"/>
+      <field name="countFailedLoginAttempts"/>
+      <field name="locked"/>
+      <field name="permanent"/>
+      <field name="validated"/>
+      <field name="passwordChangeRequired"/>
+      <field name="previousEncodedPasswords" default-fetch-group="true">
+        <collection element-type="java.lang.String" dependent-element="true"/>
+        <join/>
+      </field>
+      <field name="accountCreationDate"/>
+    </class>
+    <class name="UserManagementModelloMetadata" detachable="true">
+      <field name="modelVersion" null-value="default">
+        <column default-value="0.9.0"/>
+      </field>
+    </class>
+  </package>
+</jdo>
diff --git a/continuum-data-management/redback-legacy/src/main/resources/org/codehaus/plexus/security/user/jdo/package.jdorepl b/continuum-data-management/redback-legacy/src/main/resources/org/codehaus/plexus/security/user/jdo/package.jdorepl
new file mode 100644
index 0000000..7aa29e4
--- /dev/null
+++ b/continuum-data-management/redback-legacy/src/main/resources/org/codehaus/plexus/security/user/jdo/package.jdorepl
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ 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.
+  -->
+<!DOCTYPE jdo PUBLIC
+  "-//Sun Microsystems, Inc.//DTD Java Data Objects Metadata 2.0//EN"
+  "http://java.sun.com/dtd/jdo_2_0.dtd">
+
+<jdo>
+  <package name="org.codehaus.plexus.security.user.jdo.v0_9_0">
+    <class name="UserDatabase" detachable="true" table="UserDatabase">
+      <field name="users">
+        <collection element-type="JdoUser" dependent-element="true"/>
+        <join/>
+      </field>
+      <fetch-group name="UserDatabase_detail">
+        <field name="users"/>
+      </fetch-group>
+    </class>
+    <class name="JdoUser" detachable="true" table="JdoUser" identity-type="application">
+      <field name="username" persistence-modifier="persistent" primary-key="true"/>
+      <field name="password">
+        <column name="PASSWORD"/>
+      </field>
+      <field name="encodedPassword"/>
+      <field name="fullName"/>
+      <field name="email"/>
+      <field name="lastPasswordChange"/>
+      <field name="lastLoginDate"/>
+      <field name="countFailedLoginAttempts"/>
+      <field name="locked"/>
+      <field name="permanent"/>
+      <field name="validated"/>
+      <field name="passwordChangeRequired"/>
+      <field name="previousEncodedPasswords" default-fetch-group="true">
+        <collection element-type="java.lang.String" dependent-element="true"/>
+        <join/>
+      </field>
+      <field name="accountCreationDate"/>
+    </class>
+    <class name="UserManagementModelloMetadata" detachable="true">
+      <field name="modelVersion" null-value="default">
+        <column default-value="0.9.0"/>
+      </field>
+    </class>
+  </package>
+</jdo>
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-api/pom.xml b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-api/pom.xml
deleted file mode 100644
index 0ed72af..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-api/pom.xml
+++ /dev/null
@@ -1,98 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <parent>
-    <groupId>org.apache.continuum</groupId>
-    <artifactId>continuum-buildagent</artifactId>
-    <version>1.3.1-SNAPSHOT</version>
-  </parent>
-
-  <groupId>org.apache.continuum</groupId>
-  <artifactId>continuum-buildagent-api</artifactId>
-  <packaging>jar</packaging>
-  <name>Continuum :: Distributed Build :: Build Agent API</name>
-  
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.codehaus.modello</groupId>
-        <artifactId>modello-maven-plugin</artifactId>
-        <configuration>
-          <models>
-            <model>src/main/mdo/continuum-buildagent.xml</model>
-          </models>
-          <version>1.0.0</version>
-        </configuration>
-        <executions>
-          <execution>
-            <id>continuum-modello</id>
-            <phase>generate-sources</phase>
-            <goals>
-              <goal>java</goal>
-              <goal>xpp3-reader</goal>
-              <goal>xpp3-writer</goal>
-            </goals>
-          </execution>
-          <execution>
-            <id>site-docs</id>
-            <phase>pre-site</phase>
-            <goals>
-              <goal>xdoc</goal>
-              <goal>xsd</goal>
-            </goals>
-          </execution>
-          <execution>
-            <id>generate-xsd</id>
-            <phase>generate-resources</phase>
-            <goals>
-              <goal>xsd</goal>
-            </goals>
-            <configuration>
-              <outputDirectory>${project.build.outputDirectory}/META-INF/continuum/xsd</outputDirectory>
-            </configuration>
-          </execution>                    
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
-  <dependencies>
-    <dependency>
-      <groupId>net.java.dev.stax-utils</groupId>
-      <artifactId>stax-utils</artifactId>
-      <version>20060502</version>
-      <exclusions>
-        <exclusion>
-          <groupId>com.bea.xml</groupId>
-          <artifactId>jsr173-ri</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>stax</groupId>
-      <artifactId>stax-api</artifactId>
-      <version>1.0.1</version>
-    </dependency>
-    <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-utils</artifactId>
-    </dependency>
-  </dependencies>
-</project>
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-api/src/main/java/org/apache/continuum/buildagent/ContinuumBuildAgentService.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-api/src/main/java/org/apache/continuum/buildagent/ContinuumBuildAgentService.java
deleted file mode 100644
index 0d53631..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-api/src/main/java/org/apache/continuum/buildagent/ContinuumBuildAgentService.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.apache.continuum.buildagent;
-
-/*
- * 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.List;
-import java.util.Map;
-
-public interface ContinuumBuildAgentService
-{
-    void buildProjects( List<Map> projectsBuildContext )
-        throws ContinuumBuildAgentException;
-    
-    List<Map> getAvailableInstallations()
-        throws ContinuumBuildAgentException;
-
-    Map getBuildResult( int projectId )
-        throws ContinuumBuildAgentException;
-    
-    int getProjectCurrentlyBuilding()
-        throws ContinuumBuildAgentException;
-    
-    void cancelBuild()
-        throws ContinuumBuildAgentException;
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-api/src/main/mdo/continuum-buildagent.xml b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-api/src/main/mdo/continuum-buildagent.xml
deleted file mode 100644
index 7706aba..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-api/src/main/mdo/continuum-buildagent.xml
+++ /dev/null
@@ -1,87 +0,0 @@
-<!--
-  ~ 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.
-  -->
-<model>
-  <id>continuum-buildagent</id>
-  <name>ContinuumBuildAgentConfigurationModel</name>
-  <description>Continuum Build Agent object model.</description>
-  <defaults>
-    <default>
-      <key>package</key>
-      <value>org.apache.continuum.buildagent.model</value>
-    </default>
-  </defaults>
-
-  <classes>
-    <class rootElement="true" xml.tagName="continuum-buildagent-configuration">
-      <name>ContinuumBuildAgentConfigurationModel</name>
-      <version>1.0.0+</version>
-      <fields>
-        <field>
-          <name>buildOutputDirectory</name>
-          <version>1.0.0+</version>
-          <type>String</type>
-        </field>
-        <field>
-          <name>workingDirectory</name>
-          <version>1.0.0+</version>
-          <type>String</type>
-        </field>
-        <field>
-          <name>continuumServerUrl</name>
-          <version>1.0.0+</version>
-          <type>String</type>
-        </field>
-        <field>
-          <name>installations</name>
-          <version>1.0.0+</version>
-          <association>
-            <type>Installation</type>
-            <multiplicity>*</multiplicity>
-          </association>
-        </field>
-      </fields>
-    </class>
-    <class xml.tagName="buildagent-installation">
-      <name>Installation</name>
-      <version>1.0.0+</version>
-      <fields>
-        <field>
-          <name>type</name>
-          <version>1.0.0+</version>
-          <type>String</type>
-        </field>
-        <field>
-          <name>varValue</name>
-          <version>1.0.0+</version>
-          <type>String</type>
-        </field>
-        <field>
-          <name>varName</name>
-          <version>1.0.0+</version>
-          <type>String</type>
-        </field>   
-        <field>
-          <name>name</name>
-          <version>1.0.0+</version>
-          <type>String</type>
-        </field>                     
-      </fields>
-    </class>
-  </classes>
-</model>
\ No newline at end of file
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/pom.xml b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/pom.xml
deleted file mode 100644
index 8f95abb..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/pom.xml
+++ /dev/null
@@ -1,145 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-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.
---><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <parent>
-    <groupId>org.apache.continuum</groupId>
-    <artifactId>continuum-buildagent</artifactId>
-    <version>1.3.1-SNAPSHOT</version>
-  </parent>
-
-  <groupId>org.apache.continuum</groupId>
-  <artifactId>continuum-buildagent-core</artifactId>
-  <packaging>jar</packaging>
-  <name>Continuum :: Distributed Build :: Build Agent Core</name>
-
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-buildagent-api</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-api</artifactId>
-      <exclusions>
-        <exclusion>
-          <groupId>org.apache.archiva</groupId>
-          <artifactId>archiva-common</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>org.apache.archiva</groupId>
-          <artifactId>archiva-repository-layer</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-scm</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-distributed-build-transport-master-client</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.shared</groupId>
-      <artifactId>file-management</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-utils</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-taskqueue</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-action</artifactId>
-      <version>1.0-alpha-6</version>
-      <exclusions>
-        <exclusion>
-          <groupId>org.codehaus.plexus</groupId>
-          <artifactId>plexus-container-default</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-command-line</artifactId>
-      <version>1.0-alpha-2</version>
-      <exclusions>
-        <exclusion>
-          <groupId>org.codehaus.plexus</groupId>
-          <artifactId>plexus-container-default</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.release</groupId>
-      <artifactId>maven-release-manager</artifactId>
-      <version>1.0-alpha-3</version>
-      <exclusions>
-        <exclusion>
-          <groupId>org.codehaus.plexus</groupId>
-          <artifactId>plexus-container-default</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-api</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>javax.annotation</groupId>
-      <artifactId>jsr250-api</artifactId>
-    </dependency>      
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-log4j12</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-slf4j-logging</artifactId>
-      <scope>test</scope>
-    </dependency>
-  </dependencies>
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.codehaus.plexus</groupId>
-        <artifactId>plexus-maven-plugin</artifactId>
-        <executions>
-          <execution>
-            <id>generate</id>
-            <goals>
-              <goal>descriptor</goal>
-            </goals>
-          </execution>
-          <execution>
-            <id>merge</id>
-            <goals>
-              <goal>merge-descriptors</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-   </build>
-</project>
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/ContinuumBuildAgentServiceImpl.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/ContinuumBuildAgentServiceImpl.java
deleted file mode 100644
index 416832c..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/ContinuumBuildAgentServiceImpl.java
+++ /dev/null
@@ -1,279 +0,0 @@
-package org.apache.continuum.buildagent;
-
-/*
- * 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.io.File;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.lang.StringEscapeUtils;
-import org.apache.continuum.buildagent.buildcontext.BuildContext;
-import org.apache.continuum.buildagent.buildcontext.manager.BuildContextManager;
-import org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
-import org.apache.continuum.buildagent.manager.BuildAgentManager;
-import org.apache.continuum.buildagent.model.Installation;
-import org.apache.continuum.buildagent.taskqueue.manager.BuildAgentTaskQueueManager;
-import org.apache.continuum.buildagent.utils.ContinuumBuildAgentUtil;
-import org.apache.continuum.taskqueue.manager.TaskQueueManagerException;
-import org.apache.maven.continuum.ContinuumException;
-import org.apache.maven.continuum.model.project.BuildResult;
-import org.apache.maven.continuum.project.ContinuumProjectState;
-import org.codehaus.plexus.util.FileUtils;
-import org.codehaus.plexus.util.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * @plexus.component role="org.apache.continuum.buildagent.ContinuumBuildAgentService"
- */
-public class ContinuumBuildAgentServiceImpl
-    implements ContinuumBuildAgentService
-{
-    private Logger log = LoggerFactory.getLogger( this.getClass() );
-
-    /**
-     * @plexus.requirement
-     */
-    private BuildAgentConfigurationService buildAgentConfigurationService;
-
-    /**
-     * @plexus.requirement
-     */
-    private BuildAgentManager buildAgentManager;
-
-    /**
-     * @plexus.requirement
-     */
-    private BuildAgentTaskQueueManager buildAgentTaskQueueManager;
-
-    /**
-     * @plexus.requirement
-     */
-    private BuildContextManager buildContextManager;
-
-    public void buildProjects( List<Map> projectsBuildContext )
-        throws ContinuumBuildAgentException
-    {
-        List<BuildContext> buildContextList = initializeBuildContext( projectsBuildContext );
-
-        try
-        {
-            buildAgentManager.prepareBuildProjects( buildContextList );
-        }
-        catch ( ContinuumException e )
-        {
-            throw new ContinuumBuildAgentException( e.getMessage(), e );
-        }
-    }
-
-    public List<Map> getAvailableInstallations()
-        throws ContinuumBuildAgentException
-    {
-        List<Map> installationsList = new ArrayList<Map>();
-        
-        List<Installation> installations = buildAgentConfigurationService.getAvailableInstallations();
-
-        for ( Installation installation : installations )
-        {
-            Map map = new HashMap();
-            
-            if ( StringUtils.isBlank( installation.getName() ) )
-            {
-                map.put( ContinuumBuildAgentUtil.KEY_INSTALLATION_NAME, "" );
-            }
-            else
-            {
-                map.put( ContinuumBuildAgentUtil.KEY_INSTALLATION_NAME, installation.getName() );
-            }
-
-            if ( StringUtils.isBlank( installation.getType() ) )
-            {
-                map.put( ContinuumBuildAgentUtil.KEY_INSTALLATION_TYPE, "" );
-            }
-            else
-            {
-                map.put( ContinuumBuildAgentUtil.KEY_INSTALLATION_TYPE, installation.getType() );
-            }
-
-            if ( StringUtils.isBlank( installation.getVarName() ) )
-            {
-                map.put( ContinuumBuildAgentUtil.KEY_INSTALLATION_VAR_NAME, "" );
-            }
-            else
-            {
-                map.put( ContinuumBuildAgentUtil.KEY_INSTALLATION_VAR_VALUE, installation.getVarValue() );
-            }
-
-            if ( StringUtils.isBlank( installation.getVarValue() ) )
-            {
-                map.put( ContinuumBuildAgentUtil.KEY_INSTALLATION_VAR_VALUE, "" );
-            }
-            else
-            {
-                map.put( ContinuumBuildAgentUtil.KEY_INSTALLATION_VAR_VALUE, installation.getVarValue() );
-            }
-
-            installationsList.add( map );
-        }
-
-        return installationsList;
-    }
-
-    public Map getBuildResult( int projectId )
-        throws ContinuumBuildAgentException
-    {
-        Map result = new HashMap();
-
-        if ( projectId == getProjectCurrentlyBuilding() )
-        {
-            BuildContext buildContext = buildContextManager.getBuildContext( projectId );
-            
-            result.put( ContinuumBuildAgentUtil.KEY_PROJECT_ID, new Integer( buildContext.getProjectId() ) );
-            result.put( ContinuumBuildAgentUtil.KEY_BUILD_DEFINITION_ID, new Integer( buildContext.getBuildDefinitionId() ) );
-            result.put( ContinuumBuildAgentUtil.KEY_TRIGGER, new Integer( buildContext.getTrigger() ) );
-            
-            BuildResult buildResult = buildContext.getBuildResult();
-
-            if ( buildResult != null )
-            {
-                if ( buildResult.getStartTime() <= 0 )
-                {
-                    result.put( ContinuumBuildAgentUtil.KEY_BUILD_START, new Long( buildContext.getBuildStartTime() ).toString() );
-                }
-                else
-                {
-                    result.put( ContinuumBuildAgentUtil.KEY_BUILD_START, new Long( buildResult.getStartTime() ).toString() );
-                }
-
-                if ( buildResult.getError() == null )
-                {
-                    result.put( ContinuumBuildAgentUtil.KEY_BUILD_ERROR, "" );
-                }
-                else
-                {
-                    result.put( ContinuumBuildAgentUtil.KEY_BUILD_ERROR, buildResult.getError() );
-                }
-
-                result.put( ContinuumBuildAgentUtil.KEY_BUILD_STATE, new Integer( buildResult.getState() ) );
-                result.put( ContinuumBuildAgentUtil.KEY_BUILD_END, new Long( buildResult.getEndTime() ).toString() );
-                result.put( ContinuumBuildAgentUtil.KEY_BUILD_EXIT_CODE, buildResult.getExitCode() );
-            }
-            else
-            {
-                result.put( ContinuumBuildAgentUtil.KEY_BUILD_START, new Long( buildContext.getBuildStartTime() ).toString() );
-                result.put( ContinuumBuildAgentUtil.KEY_BUILD_END, new Long( 0 ).toString() );
-                result.put( ContinuumBuildAgentUtil.KEY_BUILD_STATE, new Integer( ContinuumProjectState.BUILDING ) );
-                result.put( ContinuumBuildAgentUtil.KEY_BUILD_ERROR, "" );
-                result.put( ContinuumBuildAgentUtil.KEY_BUILD_EXIT_CODE, new Integer( 0 ) );
-            }
-            
-            String buildOutput = getBuildOutputText( projectId );
-            if ( buildOutput == null )
-            {
-                result.put( ContinuumBuildAgentUtil.KEY_BUILD_OUTPUT, "" );
-            }
-            else
-            {
-                result.put( ContinuumBuildAgentUtil.KEY_BUILD_OUTPUT, buildOutput );
-            }
-        }
-        return result;
-    }
-
-    public int getProjectCurrentlyBuilding()
-        throws ContinuumBuildAgentException
-    {
-        try
-        {
-            return buildAgentTaskQueueManager.getCurrentProjectInBuilding();
-        }
-        catch ( TaskQueueManagerException e )
-        {
-            throw new ContinuumBuildAgentException( e.getMessage(), e );
-        }
-    }
-
-    public void cancelBuild()
-        throws ContinuumBuildAgentException
-    {
-        try
-        {
-            buildAgentTaskQueueManager.cancelBuild();
-        }
-        catch ( TaskQueueManagerException e )
-        {
-            throw new ContinuumBuildAgentException( e.getMessage(), e );
-        }
-    }
-
-    private List<BuildContext> initializeBuildContext( List<Map> projectsBuildContext )
-    {
-        List<BuildContext> buildContext = new ArrayList<BuildContext>();
-        
-        for ( Map map : projectsBuildContext )
-        {
-            BuildContext context = new BuildContext();
-            context.setProjectId( ContinuumBuildAgentUtil.getProjectId( map ) );
-            context.setBuildDefinitionId( ContinuumBuildAgentUtil.getBuildDefinitionId( map ) );
-            context.setBuildFile( ContinuumBuildAgentUtil.getBuildFile( map ) );
-            context.setExecutorId( ContinuumBuildAgentUtil.getExecutorId( map ) );
-            context.setGoals( ContinuumBuildAgentUtil.getGoals( map ) );
-            context.setArguments( ContinuumBuildAgentUtil.getArguments( map ) );
-            context.setScmUrl( ContinuumBuildAgentUtil.getScmUrl( map ) );
-            context.setScmUsername( ContinuumBuildAgentUtil.getScmUsername( map ) );
-            context.setScmPassword( ContinuumBuildAgentUtil.getScmPassword( map ) );
-            context.setBuildFresh( ContinuumBuildAgentUtil.isBuildFresh( map ) );
-            context.setProjectGroupId( ContinuumBuildAgentUtil.getProjectGroupId( map ) );
-            context.setScmRootAddress( ContinuumBuildAgentUtil.getScmRootAddress( map ) );
-            context.setProjectName( ContinuumBuildAgentUtil.getProjectName( map ) );
-            context.setProjectState( ContinuumBuildAgentUtil.getProjectState( map ) );
-            context.setTrigger( ContinuumBuildAgentUtil.getTrigger( map ) );
-            context.setLocalRepository( ContinuumBuildAgentUtil.getLocalRepository( map ) );
-
-            buildContext.add( context );
-        }
-
-        buildContextManager.setBuildContextList( buildContext );
-
-        return buildContext;
-    }
-
-    private String getBuildOutputText( int projectId )
-    {
-        try
-        {
-            File buildOutputFile = buildAgentConfigurationService.getBuildOutputFile( projectId );
-        
-            if ( buildOutputFile.exists() )
-            {
-                return StringEscapeUtils.escapeHtml( FileUtils.fileRead( buildOutputFile ) );
-            }
-        }
-        catch ( Exception e )
-        {
-            // do not throw exception, just log it
-            log.error( "Error retrieving build output file", e );
-        }
-
-        return null;
-    }
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/CheckWorkingDirectoryAction.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/CheckWorkingDirectoryAction.java
deleted file mode 100644
index 4afc758..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/CheckWorkingDirectoryAction.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package org.apache.continuum.buildagent.action;
-
-/*
- * 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.io.File;
-import java.util.Map;
-
-import org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
-import org.apache.continuum.buildagent.utils.ContinuumBuildAgentUtil;
-import org.apache.maven.continuum.model.project.Project;
-import org.codehaus.plexus.action.AbstractAction;
-
-/**
- * @plexus.component role="org.codehaus.plexus.action.Action" role-hint="check-agent-working-directory"
- */
-public class CheckWorkingDirectoryAction
-    extends AbstractAction
-{
-    /**
-     * @plexus.requirement
-     */
-    BuildAgentConfigurationService buildAgentConfigurationService;
-    
-    public void execute( Map context )
-        throws Exception
-    {
-        Project project = ContinuumBuildAgentUtil.getProject( context );
-
-        File workingDirectory = buildAgentConfigurationService.getWorkingDirectory( project.getId() );
-
-        if ( !workingDirectory.exists() )
-        {
-            context.put( ContinuumBuildAgentUtil.KEY_WORKING_DIRECTORY_EXISTS, Boolean.FALSE );
-
-            return;
-        }
-
-        File[] files = workingDirectory.listFiles();
-
-        context.put( ContinuumBuildAgentUtil.KEY_WORKING_DIRECTORY_EXISTS, Boolean.valueOf( files.length > 0 ) );
-    }
-
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/CheckoutProjectAction.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/CheckoutProjectAction.java
deleted file mode 100644
index 280eec0..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/CheckoutProjectAction.java
+++ /dev/null
@@ -1,226 +0,0 @@
-package org.apache.continuum.buildagent.action;
-
-/*
- * 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.io.File;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
-import org.apache.continuum.buildagent.utils.ContinuumBuildAgentUtil;
-import org.apache.continuum.scm.ContinuumScm;
-import org.apache.continuum.scm.ContinuumScmConfiguration;
-import org.apache.maven.continuum.model.project.BuildDefinition;
-import org.apache.maven.continuum.model.project.Project;
-import org.apache.maven.continuum.model.scm.ScmResult;
-import org.apache.maven.scm.ScmException;
-import org.apache.maven.scm.command.checkout.CheckOutScmResult;
-import org.apache.maven.scm.manager.NoSuchScmProviderException;
-import org.apache.maven.scm.repository.ScmRepositoryException;
-import org.codehaus.plexus.action.AbstractAction;
-
-/**
- * @plexus.component role="org.codehaus.plexus.action.Action" role-hint="checkout-agent-project"
- */
-public class CheckoutProjectAction
-    extends AbstractAction
-{
-    /**
-     * @plexus.requirement
-     */
-    private BuildAgentConfigurationService buildAgentConfigurationService;
-
-    /**
-     * @plexus.requirement
-     */
-    private ContinuumScm scm;
-
-    public void execute( Map context )
-        throws Exception
-    {
-        Project project = ContinuumBuildAgentUtil.getProject( context );
-        BuildDefinition buildDefinition = ContinuumBuildAgentUtil.getBuildDefinition( context );
-
-        File workingDirectory = buildAgentConfigurationService.getWorkingDirectory( project.getId() );
-
-        // ----------------------------------------------------------------------
-        // Check out the project
-        // ----------------------------------------------------------------------
-
-        ScmResult result;
-
-        try
-        {
-            String scmUserName = ContinuumBuildAgentUtil.getString( context, ContinuumBuildAgentUtil.KEY_SCM_USERNAME, "" );
-            String scmPassword = ContinuumBuildAgentUtil.getString( context, ContinuumBuildAgentUtil.KEY_SCM_PASSWORD, "" );
-
-            ContinuumScmConfiguration config =
-                createScmConfiguration( project, workingDirectory, scmUserName, scmPassword );
-
-            String tag = config.getTag();
-            getLogger().info( "Checking out project: '" + project.getName() + "', id: '" + project.getId() + "' " +
-                "to '" + workingDirectory + "'" + ( tag != null ? " with branch/tag " + tag + "." : "." ) );
-
-            CheckOutScmResult checkoutResult = scm.checkout( config );
-            //if ( StringUtils.isNotEmpty( checkoutResult.getRelativePathProjectDirectory() ) )
-            //{
-            //    context.put( AbstractContinuumAction.KEY_PROJECT_RELATIVE_PATH,
-            //                 checkoutResult.getRelativePathProjectDirectory() );
-            //}
-
-            if ( !checkoutResult.isSuccess() )
-            {
-                // TODO: is it more appropriate to return this in the converted result so that it can be presented to
-                // the user?
-                String msg = "Error while checking out the code for project: '" + project.getName() + "', id: '" +
-                    project.getId() + "' to '" + workingDirectory.getAbsolutePath() + "'" +
-                    ( tag != null ? " with branch/tag " + tag + "." : "." );
-                getLogger().warn( msg );
-
-                getLogger().warn( "Command output: " + checkoutResult.getCommandOutput() );
-
-                getLogger().warn( "Provider message: " + checkoutResult.getProviderMessage() );
-            }
-            else
-            {
-                getLogger().info( "Checked out " + checkoutResult.getCheckedOutFiles().size() + " files." );
-            }
-
-            result = convertScmResult( checkoutResult );
-        }
-        catch ( ScmRepositoryException e )
-        {
-            result = new ScmResult();
-
-            result.setSuccess( false );
-
-            result.setProviderMessage( e.getMessage() + ": " + getValidationMessages( e ) );
-
-            getLogger().error( e.getMessage(), e );
-        }
-        catch ( NoSuchScmProviderException e )
-        {
-            // TODO: this is not making it back into a result of any kind - log it at least. Same is probably the case for ScmException
-            result = new ScmResult();
-
-            result.setSuccess( false );
-
-            result.setProviderMessage( e.getMessage() );
-
-            getLogger().error( e.getMessage(), e );
-        }
-        catch ( ScmException e )
-        {
-            result = new ScmResult();
-
-            result.setSuccess( false );
-
-            result.setException( ContinuumBuildAgentUtil.throwableMessagesToString( e ) );
-
-            getLogger().error( e.getMessage(), e );
-        }
-        catch ( Throwable t )
-        {
-            // TODO: do we want this here, or should it be to the logs?
-            // TODO: what throwables do we really get here that we can cope with?
-            result = new ScmResult();
-
-            result.setSuccess( false );
-
-            result.setException( ContinuumBuildAgentUtil.throwableMessagesToString( t ) );
-
-            getLogger().error( t.getMessage(), t );
-        }
-
-        context.put( ContinuumBuildAgentUtil.KEY_CHECKOUT_SCM_RESULT, result );
-    }
-
-    private ContinuumScmConfiguration createScmConfiguration( Project project, File workingDirectory,
-                                                              String scmUserName, String scmPassword )
-    {
-        ContinuumScmConfiguration config = new ContinuumScmConfiguration();
-        config.setUrl( project.getScmUrl() );
-        config.setUsername( scmUserName );
-        config.setPassword( scmPassword );
-        config.setUseCredentialsCache( project.isScmUseCache() );
-        config.setWorkingDirectory( workingDirectory );
-        config.setTag( project.getScmTag() );
-        return config;
-    }
-
-    private ScmResult convertScmResult( CheckOutScmResult scmResult )
-    {
-        ScmResult result = new ScmResult();
-
-        result.setSuccess( scmResult.isSuccess() );
-
-        result.setCommandLine( maskPassword( scmResult.getCommandLine() ) );
-
-        result.setCommandOutput( scmResult.getCommandOutput() );
-
-        result.setProviderMessage( scmResult.getProviderMessage() );
-
-        return result;
-    }
-
-    // TODO: migrate to the SvnCommandLineUtils version (preferably properly encapsulated in the provider)
-    private String maskPassword( String commandLine )
-    {
-        String cmd = commandLine;
-
-        if ( cmd != null && cmd.startsWith( "svn" ) )
-        {
-            String pwdString = "--password";
-
-            if ( cmd.indexOf( pwdString ) > 0 )
-            {
-                int index = cmd.indexOf( pwdString ) + pwdString.length() + 1;
-
-                int nextSpace = cmd.indexOf( " ", index );
-
-                cmd = cmd.substring( 0, index ) + "********" + cmd.substring( nextSpace );
-            }
-        }
-
-        return cmd;
-    }
-
-    private String getValidationMessages( ScmRepositoryException ex )
-    {
-        List<String> messages = ex.getValidationMessages();
-
-        StringBuffer message = new StringBuffer();
-
-        if ( messages != null && !messages.isEmpty() )
-        {
-            for ( Iterator<String> i = messages.iterator(); i.hasNext(); )
-            {
-                message.append( (String) i.next() );
-
-                if ( i.hasNext() )
-                {
-                    message.append( System.getProperty( "line.separator" ) );
-                }
-            }
-        }
-        return message.toString();
-    }
-}
\ No newline at end of file
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/CleanWorkingDirectoryAction.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/CleanWorkingDirectoryAction.java
deleted file mode 100644
index b88efa0..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/CleanWorkingDirectoryAction.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package org.apache.continuum.buildagent.action;
-
-/*
- * 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.io.File;
-import java.util.Map;
-
-import org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
-import org.apache.continuum.buildagent.utils.ContinuumBuildAgentUtil;
-import org.apache.maven.continuum.model.project.Project;
-import org.apache.maven.shared.model.fileset.FileSet;
-import org.apache.maven.shared.model.fileset.util.FileSetManager;
-import org.codehaus.plexus.action.AbstractAction;
-
-/**
- * @plexus.component role="org.codehaus.plexus.action.Action" role-hint="clean-agent-working-directory"
- */
-public class CleanWorkingDirectoryAction
-    extends AbstractAction
-{
-    /**
-     * @plexus.requirement
-     */
-    private BuildAgentConfigurationService buildAgentConfigurationService;
-
-    public void execute( Map context )
-        throws Exception
-    {
-        Project project = ContinuumBuildAgentUtil.getProject( context );
-    
-        File workingDirectory = buildAgentConfigurationService.getWorkingDirectory( project.getId() );
-    
-        if ( workingDirectory.exists() )
-        {
-            FileSetManager fileSetManager = new FileSetManager();
-            FileSet fileSet = new FileSet();
-            fileSet.setDirectory( workingDirectory.getPath() );
-            fileSet.addInclude( "**/**" );
-            // TODO : this with a configuration option somewhere ?
-            fileSet.setFollowSymlinks( false );
-            fileSetManager.delete( fileSet );
-        }
-    }
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/ExecuteBuilderAction.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/ExecuteBuilderAction.java
deleted file mode 100644
index a28051e..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/ExecuteBuilderAction.java
+++ /dev/null
@@ -1,129 +0,0 @@
-package org.apache.continuum.buildagent.action;
-
-/*
- * 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.io.File;
-import java.util.Date;
-import java.util.Map;
-
-import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildCancelledException;
-import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutionResult;
-import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutor;
-import org.apache.continuum.buildagent.build.execution.manager.BuildAgentBuildExecutorManager;
-import org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
-import org.apache.continuum.buildagent.utils.ContinuumBuildAgentUtil;
-import org.apache.maven.continuum.model.project.BuildDefinition;
-import org.apache.maven.continuum.model.project.BuildResult;
-import org.apache.maven.continuum.model.project.Project;
-import org.apache.maven.continuum.project.ContinuumProjectState;
-import org.codehaus.plexus.action.AbstractAction;
-
-/**
- * @plexus.component role="org.codehaus.plexus.action.Action" role-hint="execute-agent-builder"
- */
-public class ExecuteBuilderAction
-    extends AbstractAction
-{
-    /**
-     * @plexus.requirement
-     */
-    private BuildAgentBuildExecutorManager buildAgentBuildExecutorManager;
-
-    /**
-     * @plexus.requirement
-     */
-    private BuildAgentConfigurationService buildAgentConfigurationService;
-
-    public void execute( Map context )
-        throws Exception
-    {
-        // ----------------------------------------------------------------------
-        // Get parameters from the context
-        // ----------------------------------------------------------------------
-        
-        Project project = ContinuumBuildAgentUtil.getProject( context );
-
-        BuildDefinition buildDefinition = ContinuumBuildAgentUtil.getBuildDefinition( context );
-
-        Map<String, String> environments = ContinuumBuildAgentUtil.getEnvironments( context );
-
-        String localRepository = ContinuumBuildAgentUtil.getLocalRepository( context );
-
-        int trigger = ContinuumBuildAgentUtil.getTrigger( context );
-
-        ContinuumAgentBuildExecutor buildExecutor = buildAgentBuildExecutorManager.getBuildExecutor( project.getExecutorId() );
-        
-        // ----------------------------------------------------------------------
-        // Make the buildResult
-        // ----------------------------------------------------------------------
-
-        BuildResult buildResult = new BuildResult();
-
-        buildResult.setStartTime( new Date().getTime() );
-
-        buildResult.setState( ContinuumProjectState.BUILDING );
-
-        buildResult.setTrigger( trigger );
-
-        buildResult.setBuildDefinition( buildDefinition );
-
-        context.put( ContinuumBuildAgentUtil.KEY_BUILD_RESULT, buildResult );
-
-        try
-        {
-            File buildOutputFile = buildAgentConfigurationService.getBuildOutputFile( project.getId() );
-
-            ContinuumAgentBuildExecutionResult result = buildExecutor.build( project, buildDefinition, buildOutputFile,
-                                                                             environments, localRepository );
-
-            buildResult.setState( result.getExitCode() == 0 ? ContinuumProjectState.OK : ContinuumProjectState.FAILED );
-
-            buildResult.setExitCode( result.getExitCode() );
-        }
-        catch ( ContinuumAgentBuildCancelledException e )
-        {
-            getLogger().info( "Cancelled build" );
-            
-            buildResult.setState( ContinuumProjectState.CANCELLED );
-        }
-        catch ( Throwable e )
-        {
-            getLogger().error( "Error running buildResult", e );
-
-            buildResult.setState( ContinuumProjectState.ERROR );
-
-            buildResult.setError( ContinuumBuildAgentUtil.throwableToString( e ) );
-        }
-        finally
-        {
-            buildResult.setEndTime( new Date().getTime() );
-
-            if ( buildResult.getState() != ContinuumProjectState.OK &&
-                 buildResult.getState() != ContinuumProjectState.FAILED &&
-                 buildResult.getState() != ContinuumProjectState.ERROR &&
-                 buildResult.getState() != ContinuumProjectState.CANCELLED )
-            {
-                buildResult.setState( ContinuumProjectState.ERROR );
-            }
-
-            context.put( ContinuumBuildAgentUtil.KEY_BUILD_RESULT, buildResult );
-        }
-    }
-}
\ No newline at end of file
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/UpdateWorkingDirectoryAction.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/UpdateWorkingDirectoryAction.java
deleted file mode 100644
index b575fed..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/action/UpdateWorkingDirectoryAction.java
+++ /dev/null
@@ -1,199 +0,0 @@
-package org.apache.continuum.buildagent.action;
-
-/*
- * 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.io.File;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
-import org.apache.continuum.buildagent.utils.ContinuumBuildAgentUtil;
-import org.apache.continuum.scm.ContinuumScm;
-import org.apache.continuum.scm.ContinuumScmConfiguration;
-import org.apache.maven.continuum.model.project.BuildDefinition;
-import org.apache.maven.continuum.model.project.Project;
-import org.apache.maven.continuum.model.scm.ScmResult;
-import org.apache.maven.scm.ScmException;
-import org.apache.maven.scm.command.update.UpdateScmResult;
-import org.apache.maven.scm.manager.NoSuchScmProviderException;
-import org.apache.maven.scm.repository.ScmRepositoryException;
-import org.codehaus.plexus.action.AbstractAction;
-
-/**
- * @plexus.component role="org.codehaus.plexus.action.Action" role-hint="update-agent-working-directory"
- */
-public class UpdateWorkingDirectoryAction
-    extends AbstractAction
-{
-    /**
-     * @plexus.requirement
-     */
-    private BuildAgentConfigurationService buildAgentConfigurationService;
-
-    /**
-     * @plexus.requirement
-     */
-    private ContinuumScm scm;
-
-    public void execute( Map context )
-        throws Exception
-    {
-        Project project = ContinuumBuildAgentUtil.getProject( context );
-
-        BuildDefinition buildDefinition = ContinuumBuildAgentUtil.getBuildDefinition( context );
-
-        UpdateScmResult scmResult;
-
-        ScmResult result;
-        
-        try
-        {
-            // TODO: not sure why this is different to the context, but it all needs to change
-            File workingDirectory = buildAgentConfigurationService.getWorkingDirectory( project.getId() );
-            ContinuumScmConfiguration config = createScmConfiguration( project, workingDirectory );
-            //config.setLatestUpdateDate( latestUpdateDate );
-            String tag = config.getTag();
-            String msg = project.getName() + "', id: '" + project.getId() + "' to '" +
-                workingDirectory.getAbsolutePath() + "'" + ( tag != null ? " with branch/tag " + tag + "." : "." );
-            getLogger().info( "Updating project: " + msg );
-            scmResult = scm.update( config );
-
-            if ( !scmResult.isSuccess() )
-            {
-                getLogger().warn( "Error while updating the code for project: '" + msg );
-
-                getLogger().warn( "Command output: " + scmResult.getCommandOutput() );
-
-                getLogger().warn( "Provider message: " + scmResult.getProviderMessage() );
-            }
-
-            if ( scmResult.getUpdatedFiles() != null && scmResult.getUpdatedFiles().size() > 0 )
-            {
-                getLogger().info( "Updated " + scmResult.getUpdatedFiles().size() + " files." );
-            }
-
-            result = convertScmResult( scmResult );
-        }
-        catch ( ScmRepositoryException e )
-        {
-            result = new ScmResult();
-
-            result.setSuccess( false );
-
-            result.setProviderMessage( e.getMessage() + ": " + getValidationMessages( e ) );
-            
-            getLogger().error( e.getMessage(), e);
-        }
-        catch ( NoSuchScmProviderException e )
-        {
-            // TODO: this is not making it back into a result of any kind - log it at least. Same is probably the case for ScmException
-            result = new ScmResult();
-
-            result.setSuccess( false );
-
-            result.setProviderMessage( e.getMessage() );
-            
-            getLogger().error( e.getMessage(), e);
-        }
-        catch ( ScmException e )
-        {
-            result = new ScmResult();
-
-            result.setSuccess( false );
-
-            result.setException( ContinuumBuildAgentUtil.throwableMessagesToString( e ) );
-            
-            getLogger().error( e.getMessage(), e);
-        }
-
-        context.put( ContinuumBuildAgentUtil.KEY_UPDATE_SCM_RESULT, result );
-    }
-
-    private ContinuumScmConfiguration createScmConfiguration( Project project, File workingDirectory )
-    {
-        ContinuumScmConfiguration config = new ContinuumScmConfiguration();
-        config.setUrl( project.getScmUrl() );
-        config.setUsername( project.getScmUsername() );
-        config.setPassword( project.getScmPassword() );
-        config.setUseCredentialsCache( project.isScmUseCache() );
-        config.setWorkingDirectory( workingDirectory );
-        config.setTag( project.getScmTag() );
-        return config;
-    }
-
-    private ScmResult convertScmResult( UpdateScmResult scmResult )
-    {
-        ScmResult result = new ScmResult();
-
-        result.setCommandLine( maskPassword( scmResult.getCommandLine() ) );
-
-        result.setSuccess( scmResult.isSuccess() );
-
-        result.setCommandOutput( scmResult.getCommandOutput() );
-
-        result.setProviderMessage( scmResult.getProviderMessage() );
-
-        return result;
-    }
-    
- // TODO: migrate to the SvnCommandLineUtils version (preferably properly encapsulated in the provider)
-    private String maskPassword( String commandLine )
-    {
-        String cmd = commandLine;
-
-        if ( cmd != null && cmd.startsWith( "svn" ) )
-        {
-            String pwdString = "--password";
-
-            if ( cmd.indexOf( pwdString ) > 0 )
-            {
-                int index = cmd.indexOf( pwdString ) + pwdString.length() + 1;
-
-                int nextSpace = cmd.indexOf( " ", index );
-
-                cmd = cmd.substring( 0, index ) + "********" + cmd.substring( nextSpace );
-            }
-        }
-
-        return cmd;
-    }
-    
-    private String getValidationMessages( ScmRepositoryException ex )
-    {
-        List<String> messages = ex.getValidationMessages();
-
-        StringBuffer message = new StringBuffer();
-
-        if ( messages != null && !messages.isEmpty() )
-        {
-            for ( Iterator<String> i = messages.iterator(); i.hasNext(); )
-            {
-                message.append( i.next() );
-
-                if ( i.hasNext() )
-                {
-                    message.append( System.getProperty( "line.separator" ) );
-                }
-            }
-        }
-        return message.toString();
-    }
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/AbstractBuildExecutor.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/AbstractBuildExecutor.java
deleted file mode 100644
index 2e412d7..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/AbstractBuildExecutor.java
+++ /dev/null
@@ -1,337 +0,0 @@
-package org.apache.continuum.buildagent.build.execution;
-
-/*
- * 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.io.File;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
-import org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
-import org.apache.continuum.buildagent.installation.BuildAgentInstallationService;
-import org.apache.continuum.buildagent.utils.shell.ExecutionResult;
-import org.apache.continuum.buildagent.utils.shell.BuildAgentShellCommandHelper;
-import org.apache.maven.artifact.Artifact;
-import org.apache.maven.continuum.model.project.BuildDefinition;
-import org.apache.maven.continuum.model.project.Project;
-import org.apache.maven.continuum.project.ContinuumProjectState;
-import org.codehaus.plexus.commandline.ExecutableResolver;
-import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
-import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
-import org.codehaus.plexus.util.StringUtils;
-import org.codehaus.plexus.util.cli.CommandLineException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public abstract class AbstractBuildExecutor
-    implements ContinuumAgentBuildExecutor, Initializable
-{
-    protected Logger log = LoggerFactory.getLogger( getClass() );
-
-    /**
-     * @plexus.requirement
-     */
-    private BuildAgentShellCommandHelper buildAgentShellCommandHelper;
-
-    /**
-     * @plexus.requirement
-     */
-    private ExecutableResolver executableResolver;
-
-    /**
-     * @plexus.requirement
-     */
-    private BuildAgentConfigurationService buildAgentConfigurationService;
-
-    /**
-     * @plexus.requirement
-     */
-    private BuildAgentInstallationService buildAgentInstallationService;
-
-    /**
-     * @plexus.configuration
-     */
-    private String defaultExecutable;
-
-    // ----------------------------------------------------------------------
-    //
-    // ----------------------------------------------------------------------
-
-    private String id;
-
-    private boolean resolveExecutable;
-
- // ----------------------------------------------------------------------
-    //
-    // ----------------------------------------------------------------------
-
-    protected AbstractBuildExecutor( String id, boolean resolveExecutable )
-    {
-        this.id = id;
-
-        this.resolveExecutable = resolveExecutable;
-    }
-
-    public void setBuildAgentShellCommandHelper( BuildAgentShellCommandHelper buildAgentShellCommandHelper )
-    {
-        this.buildAgentShellCommandHelper = buildAgentShellCommandHelper;
-    }
-
-    public BuildAgentShellCommandHelper getBuildAgentShellCommandHelper()
-    {
-        return buildAgentShellCommandHelper;
-    }
-
-    public void setDefaultExecutable( String defaultExecutable )
-    {
-        this.defaultExecutable = defaultExecutable;
-    }
-
-    public BuildAgentConfigurationService getBuildAgentConfigurationService()
-    {
-        return buildAgentConfigurationService;
-    }
-
-    public void setBuildAgentConfigurationService( BuildAgentConfigurationService buildAgentConfigurationService )
-    {
-        this.buildAgentConfigurationService = buildAgentConfigurationService;
-    }
-
-    public BuildAgentInstallationService getBuildAgentInstallationService()
-    {
-        return buildAgentInstallationService;
-    }
-
-    public void setBuildAgentInstallationService( BuildAgentInstallationService buildAgentInstallationService )
-    {
-        this.buildAgentInstallationService = buildAgentInstallationService;
-    }
-
-    // ----------------------------------------------------------------------
-    // Component Lifecycle
-    // ----------------------------------------------------------------------
-
-    public String getDefaultExecutable()
-    {
-        return defaultExecutable;
-    }
-
-    public void initialize()
-        throws InitializationException
-    {
-        List path = executableResolver.getDefaultPath();
-
-        if ( resolveExecutable )
-        {
-            if ( StringUtils.isEmpty( defaultExecutable ) )
-            {
-                log.warn( "The default executable for build executor '" + id + "' is not set. " +
-                    "This will cause a problem unless the project has a executable configured." );
-            }
-            else
-            {
-                File resolvedExecutable = executableResolver.findExecutable( defaultExecutable, path );
-
-                if ( resolvedExecutable == null )
-                {
-                    log.warn(
-                        "Could not find the executable '" + defaultExecutable + "' in the " + "path '" + path + "'." );
-                }
-                else
-                {
-                    log.info( "Resolved the executable '" + defaultExecutable + "' to " + "'" +
-                        resolvedExecutable.getAbsolutePath() + "'." );
-                }
-            }
-        }
-    }
-
-    // ----------------------------------------------------------------------
-    //
-    // ----------------------------------------------------------------------
-
-    /**
-     * Find the actual executable path to be used
-     *
-     * @param defaultExecutable
-     * @return The executable path
-     */
-    protected String findExecutable( Project project, String executable, String defaultExecutable,
-                                     boolean resolveExecutable, File workingDirectory )
-    {
-        // ----------------------------------------------------------------------
-        // If we're not searching the path for the executable, prefix the
-        // executable with the working directory to make sure the path is
-        // absolute and thus won't be tried resolved by using the PATH
-        // ----------------------------------------------------------------------
-
-        String actualExecutable;
-
-        if ( !resolveExecutable )
-        {
-            actualExecutable = new File( workingDirectory, executable ).getAbsolutePath();
-        }
-        else
-        {
-            List<String> path = executableResolver.getDefaultPath();
-
-            if ( StringUtils.isEmpty( executable ) )
-            {
-                executable = defaultExecutable;
-            }
-
-            File e = executableResolver.findExecutable( executable, path );
-
-            if ( e == null )
-            {
-                log.warn( "Could not find the executable '" + executable + "' in this path: " );
-
-                for ( String element : path )
-                {
-                    log.warn( element );
-                }
-
-                actualExecutable = defaultExecutable;
-            }
-            else
-            {
-                actualExecutable = e.getAbsolutePath();
-            }
-        }
-
-        //sometimes executable isn't found in path but it exit (CONTINUUM-365)
-        File actualExecutableFile = new File( actualExecutable );
-
-        if ( !actualExecutableFile.exists() )
-        {
-            actualExecutable = executable;
-        }
-
-        return actualExecutable;
-    }
-
-    protected ContinuumAgentBuildExecutionResult executeShellCommand( Project project, String executable, String arguments,
-                                                                 File output, Map<String, String> environments )
-        throws ContinuumAgentBuildExecutorException, ContinuumAgentBuildCancelledException
-    {
-
-        File workingDirectory = getWorkingDirectory( project.getId() );
-
-        String actualExecutable =
-            findExecutable( project, executable, defaultExecutable, resolveExecutable, workingDirectory );
-
-        // ----------------------------------------------------------------------
-        // Execute the build
-        // ----------------------------------------------------------------------
-
-        try
-        {
-            ExecutionResult result = getBuildAgentShellCommandHelper().executeShellCommand( workingDirectory, actualExecutable,
-                                                                                  arguments, output, project.getId(),
-                                                                                  environments );
-
-            log.info( "Exit code: " + result.getExitCode() );
-
-            return new ContinuumAgentBuildExecutionResult( output, result.getExitCode() );
-        }
-        catch ( CommandLineException e )
-        {
-            if ( e.getCause() instanceof InterruptedException )
-            {
-                throw new ContinuumAgentBuildCancelledException( "The build was cancelled", e );
-            }
-            else
-            {
-                throw new ContinuumAgentBuildExecutorException(
-                    "Error while executing shell command. The most common error is that '" + executable + "' " +
-                        "is not in your path.", e );
-            }
-        }
-        catch ( Exception e )
-        {
-            throw new ContinuumAgentBuildExecutorException( "Error while executing shell command. " +
-                "The most common error is that '" + executable + "' " + "is not in your path.", e );
-        }
-    }
-
-    protected Properties getContinuumSystemProperties( Project project )
-    {
-        Properties properties = new Properties();
-        properties.setProperty( "continuum.project.group.name", project.getProjectGroup().getName() );
-        properties.setProperty( "continuum.project.lastBuild.state", String.valueOf( project.getOldState() ) );
-        properties.setProperty( "continuum.project.lastBuild.number", String.valueOf( project.getBuildNumber() ) );
-        properties.setProperty( "continuum.project.nextBuild.number", String.valueOf( project.getBuildNumber() + 1 ) );
-        properties.setProperty( "continuum.project.id", String.valueOf( project.getId() ) );
-        properties.setProperty( "continuum.project.name", project.getName() );
-        properties.setProperty( "continuum.project.version", project.getVersion() );
-        return properties;
-    }
-
-    protected String getBuildFileForProject( Project project, BuildDefinition buildDefinition )
-    {
-        String buildFile = StringUtils.clean( buildDefinition.getBuildFile() );
-        
-        return buildFile;
-    }
-
-    public boolean isBuilding( Project project )
-    {
-        return project.getState() == ContinuumProjectState.BUILDING ||
-            getBuildAgentShellCommandHelper().isRunning( project.getId() );
-    }
-
-    public void killProcess( Project project )
-    {
-        getBuildAgentShellCommandHelper().killProcess( project.getId() );
-    }
-
-    public List<Artifact> getDeployableArtifacts( Project project, File workingDirectory, BuildDefinition buildDefinition )
-        throws ContinuumAgentBuildExecutorException
-    {
-        // Not supported by this builder
-        return Collections.EMPTY_LIST;
-    }
-
-    public File getWorkingDirectory( int projectId )
-    {
-        return getBuildAgentConfigurationService().getWorkingDirectory( projectId );
-    }
-
-    public boolean isResolveExecutable()
-    {
-        return resolveExecutable;
-    }
-
-    public void setResolveExecutable( boolean resolveExecutable )
-    {
-        this.resolveExecutable = resolveExecutable;
-    }
-
-    public void setExecutableResolver( ExecutableResolver executableResolver )
-    {
-        this.executableResolver = executableResolver;
-    }
-
-    public ExecutableResolver getExecutableResolver()
-    {
-        return executableResolver;
-    }
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/ContinuumAgentBuildExecutionResult.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/ContinuumAgentBuildExecutionResult.java
deleted file mode 100644
index fdbcab5..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/ContinuumAgentBuildExecutionResult.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package org.apache.continuum.buildagent.build.execution;
-
-/*
- * 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.io.File;
-
-public class ContinuumAgentBuildExecutionResult
-{
-    private File output;
-
-    private int exitCode;
-
-    public ContinuumAgentBuildExecutionResult( File output, int exitCode )
-    {
-        this.output = output;
-
-        this.exitCode = exitCode;
-    }
-
-    public File getOutput()
-    {
-        return output;
-    }
-
-    public int getExitCode()
-    {
-        return exitCode;
-    }
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/ContinuumAgentBuildExecutor.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/ContinuumAgentBuildExecutor.java
deleted file mode 100644
index 0fbcb49..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/ContinuumAgentBuildExecutor.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.apache.continuum.buildagent.build.execution;
-
-/*
- * 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.io.File;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.maven.artifact.Artifact;
-import org.apache.maven.continuum.model.project.BuildDefinition;
-import org.apache.maven.continuum.model.project.Project;
-
-public interface ContinuumAgentBuildExecutor
-{
-    String ROLE = ContinuumAgentBuildExecutor.class.getName();
-
-    ContinuumAgentBuildExecutionResult build( Project project, BuildDefinition buildDefinition, File buildOutput,
-                                              Map<String, String> environments, String localRepository )
-        throws ContinuumAgentBuildExecutorException, ContinuumAgentBuildCancelledException;
-    
-    boolean isBuilding( Project project );
-
-    void killProcess( Project project );
-
-    // TODO: are these part of the builder interface, or a separate project/build definition interface?
-    List<Artifact> getDeployableArtifacts( Project project, File workingDirectory, BuildDefinition buildDefinition )
-        throws ContinuumAgentBuildExecutorException;
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/ant/AntBuildExecutor.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/ant/AntBuildExecutor.java
deleted file mode 100644
index b037f2e..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/ant/AntBuildExecutor.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package org.apache.continuum.buildagent.build.execution.ant;
-
-/*
- * 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.io.File;
-import java.util.Enumeration;
-import java.util.Map;
-import java.util.Properties;
-
-import org.apache.continuum.buildagent.build.execution.AbstractBuildExecutor;
-import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildCancelledException;
-import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutionResult;
-import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutor;
-import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutorException;
-import org.apache.continuum.buildagent.installation.BuildAgentInstallationService;
-import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
-import org.apache.maven.continuum.model.project.BuildDefinition;
-import org.apache.maven.continuum.model.project.Project;
-import org.codehaus.plexus.util.StringUtils;
-
-public class AntBuildExecutor
-    extends AbstractBuildExecutor   
-    implements ContinuumAgentBuildExecutor
-{
-    public static final String CONFIGURATION_EXECUTABLE = "executable";
-
-    public static final String CONFIGURATION_TARGETS = "targets";
-
-    public static final String ID = ContinuumBuildExecutorConstants.ANT_BUILD_EXECUTOR;
-
-    protected AntBuildExecutor()
-    {
-        super( ID, true );
-    }
-
-    public ContinuumAgentBuildExecutionResult build( Project project, BuildDefinition buildDefinition, 
-                                                     File buildOutput, Map<String, String> environments,
-                                                     String localRepository )
-        throws ContinuumAgentBuildExecutorException, ContinuumAgentBuildCancelledException
-    {
-        String executable = getBuildAgentInstallationService().getExecutorConfigurator( BuildAgentInstallationService.ANT_TYPE )
-            .getExecutable();
-
-        StringBuffer arguments = new StringBuffer();
-    
-        String buildFile = getBuildFileForProject( project, buildDefinition );
-    
-        if ( !StringUtils.isEmpty( buildFile ) )
-        {
-            arguments.append( "-f " ).append( buildFile ).append( " " );
-        }
-    
-        arguments.append( StringUtils.clean( buildDefinition.getArguments() ) ).append( " " );
-    
-        Properties props = getContinuumSystemProperties( project );
-        for ( Enumeration itr = props.propertyNames(); itr.hasMoreElements(); )
-        {
-            String name = (String) itr.nextElement();
-            String value = props.getProperty( name );
-            arguments.append( "\"-D" ).append( name ).append( "=" ).append( value ).append( "\" " );
-        }
-
-        arguments.append( StringUtils.clean( buildDefinition.getGoals() ) );
-
-        String antHome = null;
-
-        if ( environments != null )
-        {
-            antHome = environments.get( getBuildAgentInstallationService().getEnvVar( BuildAgentInstallationService.ANT_TYPE ) );
-        }
-
-        if ( StringUtils.isNotEmpty( antHome ) )
-        {
-            executable = antHome + File.separator + "bin" + File.separator + executable;
-            setResolveExecutable( false );
-        }
-
-        return executeShellCommand( project, executable, arguments.toString(), buildOutput, environments );
-    }
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/manager/DefaultBuildAgentBuildExecutorManager.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/manager/DefaultBuildAgentBuildExecutorManager.java
deleted file mode 100644
index 9be397f..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/manager/DefaultBuildAgentBuildExecutorManager.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package org.apache.continuum.buildagent.build.execution.manager;
-
-/*
- * 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.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
-import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutor;
-import org.apache.maven.continuum.ContinuumException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * @plexus.component role="org.apache.continuum.buildagent.build.execution.manager.BuildAgentBuildExecutorManager"
- * role-hint"default"
- */
-public class DefaultBuildAgentBuildExecutorManager
-    implements BuildAgentBuildExecutorManager
-{
-    private Logger log = LoggerFactory.getLogger( this.getClass() );
-
-    /**
-     * @plexus.requirement role="org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutor"
-     */
-    private Map executors;
-
-    // ----------------------------------------------------------------------
-    // Component Lifecycle
-    // ----------------------------------------------------------------------
-
-    public void initialize()
-    {
-        if ( executors == null )
-        {
-            executors = new HashMap();
-        }
-
-        if ( executors.size() == 0 )
-        {
-            log.warn( "No build executors defined." );
-        }
-        else
-        {
-            log.info( "Build executors:" );
-
-            for ( Iterator it = executors.keySet().iterator(); it.hasNext(); )
-            {
-                log.info( "  " + it.next().toString() );
-            }
-        }
-    }
-
-    // ----------------------------------------------------------------------
-    // BuildExecutorManager Implementation
-    // ----------------------------------------------------------------------
-
-    public ContinuumAgentBuildExecutor getBuildExecutor( String builderType )
-        throws ContinuumException
-    {
-        ContinuumAgentBuildExecutor executor = (ContinuumAgentBuildExecutor) executors.get( builderType );
-
-        if ( executor == null )
-        {
-            throw new ContinuumException( "No such executor: '" + builderType + "'." );
-        }
-
-        return executor;
-    }
-
-    public boolean hasBuildExecutor( String executorId )
-    {
-        return executors.containsKey( executorId );
-    }
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m1/MavenOneBuildExecutor.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m1/MavenOneBuildExecutor.java
deleted file mode 100644
index 3a2d2c1..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m1/MavenOneBuildExecutor.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package org.apache.continuum.buildagent.build.execution.maven.m1;
-
-/*
- * 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.io.File;
-import java.util.Enumeration;
-import java.util.Map;
-import java.util.Properties;
-
-import org.apache.continuum.buildagent.build.execution.AbstractBuildExecutor;
-import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildCancelledException;
-import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutionResult;
-import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutor;
-import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutorException;
-import org.apache.continuum.buildagent.installation.BuildAgentInstallationService;
-import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
-import org.apache.maven.continuum.model.project.BuildDefinition;
-import org.apache.maven.continuum.model.project.Project;
-import org.codehaus.plexus.util.StringUtils;
-
-public class MavenOneBuildExecutor
-    extends AbstractBuildExecutor
-    implements ContinuumAgentBuildExecutor
-{
-    public final static String CONFIGURATION_GOALS = "goals";
-
-    public final static String ID = ContinuumBuildExecutorConstants.MAVEN_ONE_BUILD_EXECUTOR;
-
-    public MavenOneBuildExecutor()
-    {
-        super( ID, true );
-    }
-
-    public ContinuumAgentBuildExecutionResult build( Project project, BuildDefinition buildDefinition, 
-                                                     File buildOutput, Map<String, String> environments,
-                                                     String localRepository )
-        throws ContinuumAgentBuildExecutorException, ContinuumAgentBuildCancelledException
-    {
-        String executable = getBuildAgentInstallationService().getExecutorConfigurator( BuildAgentInstallationService.MAVEN1_TYPE )
-        .getExecutable();
-    
-        StringBuffer arguments = new StringBuffer();
-    
-        String buildFile = getBuildFileForProject( project, buildDefinition );
-    
-        if ( !StringUtils.isEmpty( buildFile ) && !"project.xml".equals( buildFile ) )
-        {
-            arguments.append( "-p " ).append( buildFile ).append( " " );
-        }
-    
-        arguments.append( StringUtils.clean( buildDefinition.getArguments() ) ).append( " " );
-    
-        Properties props = getContinuumSystemProperties( project );
-        for ( Enumeration itr = props.propertyNames(); itr.hasMoreElements(); )
-        {
-            String name = (String) itr.nextElement();
-            String value = props.getProperty( name );
-            arguments.append( "\"-D" ).append( name ).append( "=" ).append( value ).append( "\" " );
-        }
-
-        if ( StringUtils.isNotEmpty( localRepository ) )
-        {
-            arguments.append( "\"-Dmaven.repo.local=" ).append( StringUtils.clean( localRepository ) ).append( "\" " );
-        }
-
-        arguments.append( StringUtils.clean( buildDefinition.getGoals() ) );
-
-        String m1Home = null;
-
-        if ( environments != null )
-        {
-            m1Home = environments.get( getBuildAgentInstallationService().getEnvVar( BuildAgentInstallationService.MAVEN1_TYPE ) );
-        }
-
-        if ( StringUtils.isNotEmpty( m1Home ) )
-        {
-            executable = m1Home + File.separator + "bin" + File.separator + executable;
-                setResolveExecutable( false );
-        }
-
-        return executeShellCommand( project, executable, arguments.toString(), buildOutput, environments );
-    }
-
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m2/BuildAgentMavenBuilderHelper.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m2/BuildAgentMavenBuilderHelper.java
deleted file mode 100644
index d9df585..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m2/BuildAgentMavenBuilderHelper.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.apache.continuum.buildagent.build.execution.maven.m2;
-
-/*
- * 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.io.File;
-
-import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
-import org.apache.maven.project.MavenProject;
-
-public interface BuildAgentMavenBuilderHelper
-{
-    String ROLE = BuildAgentMavenBuilderHelper.class.getName();
-
-    MavenProject getMavenProject( ContinuumProjectBuildingResult result, File file );
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m2/DefaultBuildAgentMavenBuilderHelper.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m2/DefaultBuildAgentMavenBuilderHelper.java
deleted file mode 100644
index b8cccd3..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m2/DefaultBuildAgentMavenBuilderHelper.java
+++ /dev/null
@@ -1,417 +0,0 @@
-package org.apache.continuum.buildagent.build.execution.maven.m2;
-
-/*
- * 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.io.File;
-import java.io.IOException;
-import java.io.StringWriter;
-import java.util.Iterator;
-import java.util.List;
-
-import javax.annotation.Resource;
-
-import org.apache.maven.artifact.manager.WagonManager;
-import org.apache.maven.artifact.repository.ArtifactRepository;
-import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
-import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
-import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
-import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
-import org.apache.maven.model.Model;
-import org.apache.maven.model.Profile;
-import org.apache.maven.model.Scm;
-import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
-import org.apache.maven.profiles.DefaultProfileManager;
-import org.apache.maven.profiles.ProfileManager;
-import org.apache.maven.project.InvalidProjectModelException;
-import org.apache.maven.project.MavenProject;
-import org.apache.maven.project.MavenProjectBuilder;
-import org.apache.maven.project.ProjectBuildingException;
-import org.apache.maven.project.validation.ModelValidationResult;
-import org.apache.maven.settings.MavenSettingsBuilder;
-import org.apache.maven.settings.Mirror;
-import org.apache.maven.settings.Proxy;
-import org.apache.maven.settings.Server;
-import org.apache.maven.settings.Settings;
-import org.apache.maven.settings.io.xpp3.SettingsXpp3Writer;
-import org.codehaus.plexus.PlexusConstants;
-import org.codehaus.plexus.PlexusContainer;
-import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
-import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
-import org.codehaus.plexus.context.Context;
-import org.codehaus.plexus.context.ContextException;
-import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
-import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
-import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
-import org.codehaus.plexus.util.StringUtils;
-import org.codehaus.plexus.util.xml.Xpp3Dom;
-import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Service;
-
-/**
- * @author marica
- */
-@Service("buildAgentMavenBuilderHelper")
-public class DefaultBuildAgentMavenBuilderHelper
-    implements BuildAgentMavenBuilderHelper, Contextualizable, Initializable
-{
-    private Logger log = LoggerFactory.getLogger( this.getClass() );
-
-    @Resource
-    private MavenProjectBuilder projectBuilder;
-
-    @Resource
-    private MavenSettingsBuilder mavenSettingsBuilder;
-
-    @Resource
-    private ArtifactRepositoryFactory artifactRepositoryFactory;
-
-    @Resource
-    private ArtifactRepositoryLayout defaultRepositoryLayout;
-
-    private PlexusContainer container;
-    
-    public MavenProject getMavenProject( ContinuumProjectBuildingResult result, File file )
-    {
-        MavenProject project;
-
-        try
-        {
-            //   TODO: This seems like code that is shared with DefaultMaven, so it should be moved to the project
-            //   builder perhaps
-
-            Settings settings = getSettings();
-
-            if ( log.isDebugEnabled() )
-            {
-                writeSettings( settings );
-            }
-
-            ProfileManager profileManager = new DefaultProfileManager( container, settings );
-
-            project = projectBuilder.build( file, getRepository( settings ), profileManager, false );
-
-            if ( log.isDebugEnabled() )
-            {
-                writePom( project );
-                writeActiveProfileStatement( project );
-            }
-
-        }
-        catch ( ProjectBuildingException e )
-        {
-            StringBuffer messages = new StringBuffer();
-
-            Throwable cause = e.getCause();
-
-            if ( cause != null )
-            {
-                while ( ( cause.getCause() != null ) && ( cause instanceof ProjectBuildingException ) )
-                {
-                    cause = cause.getCause();
-                }
-            }
-
-            if ( e instanceof InvalidProjectModelException )
-            {
-                InvalidProjectModelException ex = (InvalidProjectModelException) e;
-
-                ModelValidationResult validationResult = ex.getValidationResult();
-
-                if ( validationResult != null && validationResult.getMessageCount() > 0 )
-                {
-                    for ( Iterator<String> i = validationResult.getMessages().iterator(); i.hasNext(); )
-                    {
-                        String valmsg = i.next();
-                        result.addError( ContinuumProjectBuildingResult.ERROR_VALIDATION, valmsg );
-                        messages.append( valmsg );
-                        messages.append( "\n" );
-                    }
-                }
-            }
-
-            if ( cause instanceof ArtifactNotFoundException )
-            {
-                result.addError( ContinuumProjectBuildingResult.ERROR_ARTIFACT_NOT_FOUND,
-                                 ( (ArtifactNotFoundException) cause ).toString() );
-                return null;
-            }
-
-            result.addError( ContinuumProjectBuildingResult.ERROR_PROJECT_BUILDING, e.getMessage() );
-
-            String msg = "Cannot build maven project from " + file + " (" + e.getMessage() + ").\n" + messages;
-
-            file.delete();
-
-            log.error( msg );
-
-            return null;
-        }
-        // TODO catch all exceptions is bad
-        catch ( Exception e )
-        {
-            result.addError( ContinuumProjectBuildingResult.ERROR_PROJECT_BUILDING, e.getMessage() );
-
-            String msg = "Cannot build maven project from " + file + " (" + e.getMessage() + ").";
-
-            file.delete();
-
-            log.error( msg );
-
-            return null;
-        }
-
-        // ----------------------------------------------------------------------
-        // Validate the MavenProject using some Continuum rules
-        // ----------------------------------------------------------------------
-
-        // SCM connection
-        Scm scm = project.getScm();
-
-        if ( scm == null )
-        {
-            result.addError( ContinuumProjectBuildingResult.ERROR_MISSING_SCM, getProjectName( project ) );
-
-            log.error( "Missing 'scm' element in the " + getProjectName( project ) + " POM." );
-
-            return null;
-        }
-
-        String url = scm.getConnection();
-
-        if ( StringUtils.isEmpty( url ) )
-        {
-            result.addError( ContinuumProjectBuildingResult.ERROR_MISSING_SCM_CONNECTION, getProjectName( project ) );
-
-            log.error(
-                "Missing 'connection' element in the 'scm' element in the " + getProjectName( project ) + " POM." );
-
-            return null;
-        }
-
-        return project;
-    }
-
-    private Settings getSettings()
-        throws SettingsConfigurationException
-    {
-        try
-        {
-            return mavenSettingsBuilder.buildSettings( false );
-        }
-        catch ( IOException e )
-        {
-            throw new SettingsConfigurationException( "Error reading settings file", e );
-        }
-        catch ( XmlPullParserException e )
-        {
-            throw new SettingsConfigurationException( e.getMessage(), e.getDetail(), e.getLineNumber(),
-                                                      e.getColumnNumber() );
-        }
-    }
-
-    private ArtifactRepository getRepository( Settings settings )
-    {
-        return artifactRepositoryFactory.createArtifactRepository( "local", "file://" + settings.getLocalRepository(), 
-                                                                   defaultRepositoryLayout, null, null );
-    }
-    
-    public String getProjectName( MavenProject project )
-    {
-        String name = project.getName();
-
-        if ( StringUtils.isEmpty( name ) )
-        {
-            return project.getId();
-        }
-
-        return name;
-    }
-    
-    private void writeSettings( Settings settings )
-    {
-        StringWriter sWriter = new StringWriter();
-
-        SettingsXpp3Writer settingsWriter = new SettingsXpp3Writer();
-
-        try
-        {
-            settingsWriter.write( sWriter, settings );
-
-            StringBuffer message = new StringBuffer();
-
-            message.append( "\n************************************************************************************" );
-            message.append( "\nEffective Settings" );
-            message.append( "\n************************************************************************************" );
-            message.append( "\n" );
-            message.append( sWriter.toString() );
-            message.append( "\n************************************************************************************" );
-            message.append( "\n\n" );
-
-            log.debug( message.toString() );
-        }
-        catch ( IOException e )
-        {
-            log.warn( "Cannot serialize Settings to XML.", e );
-        }
-    }
-
-    private void writePom( MavenProject project )
-    {
-        StringBuffer message = new StringBuffer();
-
-        Model pom = project.getModel();
-
-        StringWriter sWriter = new StringWriter();
-
-        MavenXpp3Writer pomWriter = new MavenXpp3Writer();
-
-        try
-        {
-            pomWriter.write( sWriter, pom );
-
-            message.append( "\n************************************************************************************" );
-            message.append( "\nEffective POM for project \'" ).append( project.getId() ).append( "\'" );
-            message.append( "\n************************************************************************************" );
-            message.append( "\n" );
-            message.append( sWriter.toString() );
-            message.append( "\n************************************************************************************" );
-            message.append( "\n\n" );
-
-            log.debug( message.toString() );
-        }
-        catch ( IOException e )
-        {
-            log.warn( "Cannot serialize POM to XML.", e );
-        }
-    }
-    
-    private void writeActiveProfileStatement( MavenProject project )
-    {
-        List<Profile> profiles = project.getActiveProfiles();
-
-        StringBuffer message = new StringBuffer();
-
-        message.append( "\n" );
-
-        message.append( "\n************************************************************************************" );
-        message.append( "\nActive Profiles for Project \'" ).append( project.getId() ).append( "\'" );
-        message.append( "\n************************************************************************************" );
-        message.append( "\n" );
-
-        if ( profiles == null || profiles.isEmpty() )
-        {
-            message.append( "There are no active profiles." );
-        }
-        else
-        {
-            message.append( "The following profiles are active:\n" );
-
-            for ( Profile profile : profiles )
-            {
-                message.append( "\n - " ).append( profile.getId() ).append( " (source: " )
-                    .append( profile.getSource() ).append( ")" );
-            }
-
-        }
-
-        message.append( "\n************************************************************************************" );
-        message.append( "\n\n" );
-
-        log.debug( message.toString() );
-    }
-
-    public void contextualize( Context context )
-        throws ContextException
-    {
-        container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
-    }
-
-    public void initialize()
-        throws InitializationException
-    {
-        try
-        {
-            Settings settings = getSettings();
-
-            resolveParameters( settings );
-        }
-        catch ( Exception e )
-        {
-            throw new InitializationException( "Can't initialize '" + getClass().getName() + "'", e );
-        }
-    }
-    
-    /**
-     * @todo [BP] this might not be required if there is a better way to pass
-     * them in. It doesn't feel quite right.
-     * @todo [JC] we should at least provide a mapping of protocol-to-proxy for
-     * the wagons, shouldn't we?
-     */
-    private void resolveParameters( Settings settings )
-        throws ComponentLookupException, ComponentLifecycleException, SettingsConfigurationException
-    {
-        WagonManager wagonManager = (WagonManager) container.lookup( WagonManager.ROLE );
-
-        try
-        {
-            Proxy proxy = settings.getActiveProxy();
-
-            if ( proxy != null )
-            {
-                if ( proxy.getHost() == null )
-                {
-                    throw new SettingsConfigurationException( "Proxy in settings.xml has no host" );
-                }
-
-                wagonManager.addProxy( proxy.getProtocol(), proxy.getHost(), proxy.getPort(), proxy.getUsername(),
-                                       proxy.getPassword(), proxy.getNonProxyHosts() );
-            }
-
-            for ( Iterator<Server> i = settings.getServers().iterator(); i.hasNext(); )
-            {
-                Server server = i.next();
-
-                wagonManager.addAuthenticationInfo( server.getId(), server.getUsername(), server.getPassword(),
-                                                    server.getPrivateKey(), server.getPassphrase() );
-
-                wagonManager.addPermissionInfo( server.getId(), server.getFilePermissions(),
-                                                server.getDirectoryPermissions() );
-
-                if ( server.getConfiguration() != null )
-                {
-                    wagonManager.addConfiguration( server.getId(), (Xpp3Dom) server.getConfiguration() );
-                }
-            }
-
-            for ( Iterator<Mirror> i = settings.getMirrors().iterator(); i.hasNext(); )
-            {
-                Mirror mirror = i.next();
-
-                wagonManager.addMirror( mirror.getId(), mirror.getMirrorOf(), mirror.getUrl() );
-            }
-        }
-        finally
-        {
-            container.release( wagonManager );
-        }
-    }
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m2/MavenTwoBuildExecutor.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m2/MavenTwoBuildExecutor.java
deleted file mode 100644
index 4f6a116..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m2/MavenTwoBuildExecutor.java
+++ /dev/null
@@ -1,276 +0,0 @@
-package org.apache.continuum.buildagent.build.execution.maven.m2;
-
-/*
- * 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.io.File;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
-import javax.annotation.Resource;
-
-import org.apache.continuum.buildagent.build.execution.AbstractBuildExecutor;
-import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildCancelledException;
-import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutionResult;
-import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutor;
-import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutorException;
-import org.apache.continuum.buildagent.installation.BuildAgentInstallationService;
-import org.apache.maven.artifact.Artifact;
-import org.apache.maven.artifact.metadata.ArtifactMetadata;
-import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
-import org.apache.maven.continuum.model.project.BuildDefinition;
-import org.apache.maven.continuum.model.project.Project;
-import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
-import org.apache.maven.project.MavenProject;
-import org.apache.maven.project.MavenProjectHelper;
-import org.apache.maven.project.artifact.ProjectArtifactMetadata;
-import org.codehaus.plexus.util.StringUtils;
-
-public class MavenTwoBuildExecutor
-    extends AbstractBuildExecutor
-    implements ContinuumAgentBuildExecutor
-{
-    public static final String CONFIGURATION_GOALS = "goals";
-
-    public static final String ID = ContinuumBuildExecutorConstants.MAVEN_TWO_BUILD_EXECUTOR;
-
-    @Resource
-    private MavenProjectHelper projectHelper;
-
-    @Resource
-    private BuildAgentMavenBuilderHelper buildAgentMavenBuilderHelper;
-
-    public MavenTwoBuildExecutor()
-    {
-        super( ID, true );
-    }
-
-    public MavenProjectHelper getProjectHelper()
-    {
-        return projectHelper;
-    }
-
-    public void setProjectHelper( MavenProjectHelper projectHelper )
-    {
-        this.projectHelper = projectHelper;
-    }
-
-    public BuildAgentMavenBuilderHelper getBuilderHelper()
-    {
-        return buildAgentMavenBuilderHelper;
-    }
-
-    public void setBuilderHelper( BuildAgentMavenBuilderHelper builderHelper )
-    {
-        this.buildAgentMavenBuilderHelper = builderHelper;
-    }
-
-    public ContinuumAgentBuildExecutionResult build( Project project, BuildDefinition buildDefinition, 
-                                                     File buildOutput, Map<String, String> environments,
-                                                     String localRepository )
-        throws ContinuumAgentBuildExecutorException, ContinuumAgentBuildCancelledException
-    {
-        String executable = getBuildAgentInstallationService().getExecutorConfigurator( BuildAgentInstallationService.MAVEN2_TYPE )
-        .getExecutable();
-
-        StringBuffer arguments = new StringBuffer();
-    
-        String buildFile = getBuildFileForProject( project, buildDefinition );
-    
-        if ( !StringUtils.isEmpty( buildFile ) && !"pom.xml".equals( buildFile ) )
-        {
-            arguments.append( "-f " ).append( buildFile ).append( " " );
-        }
-    
-        arguments.append( StringUtils.clean( buildDefinition.getArguments() ) ).append( " " );
-    
-        /*
-        Properties props = getContinuumSystemProperties( project );
-        for ( Enumeration itr = props.propertyNames(); itr.hasMoreElements(); )
-        {
-            String name = (String) itr.nextElement();
-            String value = props.getProperty( name );
-            arguments.append( "\"-D" ).append( name ).append( "=" ).append( value ).append( "\" " );
-        }
-        */
-
-        if ( StringUtils.isNotEmpty( localRepository ) )
-        {
-            arguments.append( "\"-Dmaven.repo.local=" ).append( StringUtils.clean( localRepository ) ).append( "\" " );
-        }
-
-        arguments.append( StringUtils.clean( buildDefinition.getGoals() ) );
-
-        String m2Home = null;
-
-        if ( environments != null )
-        {
-            m2Home = environments.get( getBuildAgentInstallationService().getEnvVar( BuildAgentInstallationService.MAVEN2_TYPE ) );
-        }
-
-        if ( StringUtils.isNotEmpty( m2Home ) )
-        {
-            executable = m2Home + File.separator + "bin" + File.separator + executable;
-            setResolveExecutable( false );
-        }
-
-        return executeShellCommand( project, executable, arguments.toString(), buildOutput, environments );
-    }
-
-    @Override
-    public List<Artifact> getDeployableArtifacts( Project continuumProject, File workingDirectory,
-                                        BuildDefinition buildDefinition )
-        throws ContinuumAgentBuildExecutorException
-    {
-        MavenProject project = getMavenProject( continuumProject, workingDirectory, buildDefinition );
-
-        // Maven could help us out a lot more here by knowing how to get the deployment artifacts from a project.
-        // TODO: this is currently quite lame
-
-        Artifact artifact = project.getArtifact();
-
-        String projectPackaging = project.getPackaging();
-
-        boolean isPomArtifact = "pom".equals( projectPackaging );
-
-        if ( isPomArtifact )
-        {
-            artifact.setFile( project.getFile() );
-        }
-        else
-        {
-            // Attach pom
-            ArtifactMetadata metadata = new ProjectArtifactMetadata( artifact, project.getFile() );
-
-            artifact.addMetadata( metadata );
-
-            String finalName = project.getBuild().getFinalName();
-
-            String filename = finalName + "." + artifact.getArtifactHandler().getExtension();
-
-            String buildDirectory = project.getBuild().getDirectory();
-
-            File artifactFile = new File( buildDirectory, filename );
-
-            artifact.setFile( artifactFile );
-
-            // sources jar
-            File sourcesFile = new File( buildDirectory, finalName + "-sources.jar" );
-
-            if ( sourcesFile.exists() )
-            {
-                projectHelper.attachArtifact( project, "java-source", "sources", sourcesFile );
-            }
-
-            // tests sources jar
-            File testsSourcesFile = new File( buildDirectory, finalName + "-test-sources.jar" );
-
-            if ( testsSourcesFile.exists() )
-            {
-                projectHelper.attachArtifact( project, "java-source", "test-sources", testsSourcesFile );
-            }
-
-            // javadoc jar
-            File javadocFile = new File( buildDirectory, finalName + "-javadoc.jar" );
-
-            if ( javadocFile.exists() )
-            {
-                projectHelper.attachArtifact( project, "javadoc", "javadoc", javadocFile );
-            }
-
-            // client jar
-            File clientFile = new File( buildDirectory, finalName + "-client.jar" );
-
-            if ( clientFile.exists() )
-            {
-                projectHelper.attachArtifact( project, projectPackaging + "-client", "client", clientFile );
-            }
-
-            // Tests jar
-            File testsFile = new File( buildDirectory, finalName + "-tests.jar" );
-
-            if ( testsFile.exists() )
-            {
-                projectHelper.attachArtifact( project, "jar", "tests", testsFile );
-            }
-        }
-
-        List<Artifact> attachedArtifacts = project.getAttachedArtifacts();
-
-        List<Artifact> artifacts = new ArrayList<Artifact>( attachedArtifacts.size() + 1 );
-
-        if ( artifact.getFile().exists() )
-        {
-            artifacts.add( artifact );
-        }
-
-        for ( Artifact attachedArtifact : attachedArtifacts )
-        {
-            artifacts.add( attachedArtifact );
-        }
-
-        return artifacts;
-    }
-
-    private MavenProject getMavenProject( Project continuumProject, File workingDirectory,
-                                          BuildDefinition buildDefinition )
-        throws ContinuumAgentBuildExecutorException
-    {
-        ContinuumProjectBuildingResult result = new ContinuumProjectBuildingResult();
-
-        File f = getPomFile( getBuildFileForProject( continuumProject, buildDefinition ), workingDirectory );
-
-        if ( !f.exists() )
-        {
-            throw new ContinuumAgentBuildExecutorException( "Could not find Maven project descriptor '" + f + "'." );
-        }
-
-        MavenProject project = buildAgentMavenBuilderHelper.getMavenProject( result, f );
-
-        if ( result.hasErrors() )
-        {
-            throw new ContinuumAgentBuildExecutorException(
-                "Unable to read the Maven project descriptor '" + f + "': " + result.getErrorsAsString() );
-        }
-        return project;
-    }
-
-    private static File getPomFile( String projectBuildFile, File workingDirectory )
-    {
-        File f = null;
-
-        String buildFile = StringUtils.clean( projectBuildFile );
-
-        if ( !StringUtils.isEmpty( buildFile ) )
-        {
-            f = new File( workingDirectory, buildFile );
-        }
-
-        if ( f == null )
-        {
-            f = new File( workingDirectory, "pom.xml" );
-        }
-
-        return f;
-    }
-
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m2/SettingsConfigurationException.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m2/SettingsConfigurationException.java
deleted file mode 100644
index ac52bbf..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/maven/m2/SettingsConfigurationException.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package org.apache.continuum.buildagent.build.execution.maven.m2;
-
-/*
- * 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.
- */
-
-public class SettingsConfigurationException
-    extends Exception
-    {
-    private int lineNumber;
-    
-    private int columnNumber;
-    
-    public SettingsConfigurationException( String message )
-    {
-        super( message );
-    }
-    
-    public SettingsConfigurationException( String message, Throwable cause )
-    {
-        super( message, cause );
-    }
-    
-    public SettingsConfigurationException( String message, Throwable cause, int lineNumber, int columnNumber )
-    {
-        super( message + ( lineNumber > 0 ? "\n  Line:   " + lineNumber : "" ) +
-            ( columnNumber > 0 ? "\n  Column: " + columnNumber : "" ), cause );
-        this.lineNumber = lineNumber;
-        this.columnNumber = columnNumber;
-    }
-    
-    public int getColumnNumber()
-    {
-        return columnNumber;
-    }
-    
-    public int getLineNumber()
-    {
-        return lineNumber;
-    }
-}
\ No newline at end of file
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/shell/ShellBuildExecutor.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/shell/ShellBuildExecutor.java
deleted file mode 100644
index bff1ffd..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/build/execution/shell/ShellBuildExecutor.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package org.apache.continuum.buildagent.build.execution.shell;
-
-/*
- * 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.io.File;
-import java.util.Map;
-
-import org.apache.continuum.buildagent.build.execution.AbstractBuildExecutor;
-import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildCancelledException;
-import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutionResult;
-import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutor;
-import org.apache.continuum.buildagent.build.execution.ContinuumAgentBuildExecutorException;
-import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
-import org.apache.maven.continuum.model.project.BuildDefinition;
-import org.apache.maven.continuum.model.project.Project;
-
-public class ShellBuildExecutor
-    extends AbstractBuildExecutor
-    implements ContinuumAgentBuildExecutor
-{
-    public static final String CONFIGURATION_EXECUTABLE = "executable";
-
-    public static final String ID = ContinuumBuildExecutorConstants.SHELL_BUILD_EXECUTOR;
-
-    public ShellBuildExecutor()
-    {
-        super( ID, false );
-    }
-
-    public ContinuumAgentBuildExecutionResult build( Project project, BuildDefinition buildDefinition, 
-                                                     File buildOutput, Map<String, String> environments,
-                                                     String localRepository )
-        throws ContinuumAgentBuildExecutorException, ContinuumAgentBuildCancelledException
-    {
-        String executable = getBuildFileForProject( project, buildDefinition );
-
-        return executeShellCommand( project, executable, buildDefinition.getArguments(), buildOutput, environments );
-    }
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/buildcontext/BuildContext.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/buildcontext/BuildContext.java
deleted file mode 100644
index 921c359..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/buildcontext/BuildContext.java
+++ /dev/null
@@ -1,268 +0,0 @@
-package org.apache.continuum.buildagent.buildcontext;
-
-/*
- * 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.Map;
-
-import org.apache.maven.continuum.model.project.BuildResult;
-import org.apache.maven.continuum.model.scm.ScmResult;
-
-public class BuildContext
-{
-    private int projectId;
-
-    private String projectName;
-
-    private int projectState;
-
-    private int buildDefinitionId;
-
-    private String buildFile;
-
-    private String goals;
-
-    private String arguments;
-
-    private String executorId;
-
-    private String scmUrl;
-
-    private String scmUsername;
-
-    private String scmPassword;
-
-    private int trigger;
-
-    private boolean buildFresh;
-
-    private int projectGroupId;
-
-    private String scmRootAddress;
-
-    private Map<String, Object> actionContext;
-
-    private ScmResult scmResult;
-
-    private BuildResult buildResult;
-
-    private long buildStartTime;
-
-    private String localRepository;
-
-    public int getProjectGroupId()
-    {
-        return projectGroupId;
-    }
-
-    public void setProjectGroupId( int projectGroupId )
-    {
-        this.projectGroupId = projectGroupId;
-    }
-
-    public String getScmRootAddress()
-    {
-        return scmRootAddress;
-    }
-
-    public void setScmRootAddress( String scmRootAddress )
-    {
-        this.scmRootAddress = scmRootAddress;
-    }
-
-    public int getProjectId()
-    {
-        return projectId;
-    }
-
-    public void setProjectId( int projectId )
-    {
-        this.projectId = projectId;
-    }
-
-    public String getProjectName()
-    {
-        return projectName;
-    }
-
-    public void setProjectName( String projectName )
-    {
-        this.projectName = projectName;
-    }
-
-    public int getProjectState()
-    {
-        return projectState;
-    }
-
-    public void setProjectState( int projectState )
-    {
-        this.projectState = projectState;
-    }
-
-    public int getBuildDefinitionId()
-    {
-        return buildDefinitionId;
-    }
-
-    public void setBuildDefinitionId( int buildDefinitionId )
-    {
-        this.buildDefinitionId = buildDefinitionId;
-    }
-
-    public String getBuildFile()
-    {
-        return buildFile;
-    }
-
-    public void setBuildFile( String buildFile )
-    {
-        this.buildFile = buildFile;
-    }
-
-    public String getGoals()
-    {
-        return goals;
-    }
-
-    public void setGoals( String goals )
-    {
-        this.goals = goals;
-    }
-
-    public String getArguments()
-    {
-        return arguments;
-    }
-
-    public void setArguments( String arguments )
-    {
-        this.arguments = arguments;
-    }
-
-    public String getExecutorId()
-    {
-        return executorId;
-    }
-
-    public void setExecutorId( String executorId )
-    {
-        this.executorId = executorId;
-    }
-
-    public String getScmUrl()
-    {
-        return scmUrl;
-    }
-
-    public void setScmUrl( String scmUrl )
-    {
-        this.scmUrl = scmUrl;
-    }
-
-    public String getScmUsername()
-    {
-        return scmUsername;
-    }
-
-    public void setScmUsername( String scmUsername )
-    {
-        this.scmUsername = scmUsername;
-    }
-
-    public String getScmPassword()
-    {
-        return scmPassword;
-    }
-
-    public void setScmPassword( String scmPassword )
-    {
-        this.scmPassword = scmPassword;
-    }
-
-    public int getTrigger()
-    {
-        return trigger;
-    }
-
-    public void setTrigger( int trigger )
-    {
-        this.trigger = trigger;
-    }
-
-    public boolean isBuildFresh()
-    {
-        return buildFresh;
-    }
-
-    public void setBuildFresh( boolean buildFresh )
-    {
-        this.buildFresh = buildFresh;
-    }
-
-    public Map<String, Object> getActionContext()
-    {
-        return actionContext;
-    }
-
-    public void setActionContext( Map<String, Object> actionContext ) 
-    {
-        this.actionContext = actionContext;
-    }
-
-    public ScmResult getScmResult()
-    {
-        return scmResult;
-    }
-
-    public void setScmResult( ScmResult scmResult )
-    {
-        this.scmResult = scmResult;
-    }
-
-    public BuildResult getBuildResult()
-    {
-        return buildResult;
-    }
-
-    public void setBuildResult( BuildResult buildResult )
-    {
-        this.buildResult = buildResult;
-    }
-
-    public long getBuildStartTime()
-    {
-        return buildStartTime;
-    }
-
-    public void setBuildStartTime( long buildStartTime )
-    {
-        this.buildStartTime = buildStartTime;
-    }
-
-    public String getLocalRepository()
-    {
-        return localRepository;
-    }
-
-    public void setLocalRepository( String localRepository )
-    {
-        this.localRepository = localRepository;
-    }
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/buildcontext/manager/BuildContextManager.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/buildcontext/manager/BuildContextManager.java
deleted file mode 100644
index bb1e166..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/buildcontext/manager/BuildContextManager.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.apache.continuum.buildagent.buildcontext.manager;
-
-/*
- * 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.List;
-
-import org.apache.continuum.buildagent.buildcontext.BuildContext;
-
-/**
- * @author Jan Stevens Ancajas
- */
-public interface BuildContextManager
-{
-    String ROLE = BuildContextManager.class.getName();
-    
-    public void setBuildContextList(List<BuildContext> buildContext);
-    
-    public List<BuildContext> getBuildContextList();
-    
-    public BuildContext getBuildContext(int projectId);
-}
\ No newline at end of file
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/buildcontext/manager/DefaultBuildContextManager.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/buildcontext/manager/DefaultBuildContextManager.java
deleted file mode 100644
index 7342288..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/buildcontext/manager/DefaultBuildContextManager.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.apache.continuum.buildagent.buildcontext.manager;
-
-/*
- * 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.List;
-
-import org.apache.continuum.buildagent.buildcontext.BuildContext;
-import org.springframework.stereotype.Service;
-
-/**
- * @author Jan Steven Ancajas
- */
-@Service("buildContextManager")
-public class DefaultBuildContextManager
-    implements BuildContextManager
-{
-    public List<BuildContext> buildContexts;
-
-    public BuildContext getBuildContext( int projectId )
-    {
-        BuildContext context = null;
-
-        if (buildContexts!= null)
-        {
-            for ( BuildContext item : buildContexts )
-            {
-                if (item.getProjectId() == projectId)
-                {
-                    context = item;
-                    break;
-                }
-            }
-        }
-
-        return context;
-    }
-
-    public List<BuildContext> getBuildContextList()
-    {
-        return buildContexts;
-    }
-
-    public void setBuildContextList( List<BuildContext> buildContexts )
-    {
-        this.buildContexts = buildContexts;
-    }
-}
\ No newline at end of file
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/BuildAgentConfiguration.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/BuildAgentConfiguration.java
deleted file mode 100644
index 7127d52..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/BuildAgentConfiguration.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.apache.continuum.buildagent.configuration;
-
-import java.io.File;
-
-/*
- * 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.
- */
-
-public interface BuildAgentConfiguration
-{
-    String ROLE = BuildAgentConfiguration.class.getName();
-
-    GeneralBuildAgentConfiguration getContinuumBuildAgentConfiguration()
-        throws BuildAgentConfigurationException;
-
-    void setContinuumBuildAgentConfiguration( GeneralBuildAgentConfiguration configuration )
-        throws BuildAgentConfigurationException;
-
-    void save()
-        throws BuildAgentConfigurationException;
-    
-    void save( File file )
-        throws BuildAgentConfigurationException;
-    
-    void reload( )
-        throws BuildAgentConfigurationException;    
-    
-    void reload( File file )
-        throws BuildAgentConfigurationException;
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/BuildAgentConfigurationService.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/BuildAgentConfigurationService.java
deleted file mode 100644
index 21ffcbf..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/BuildAgentConfigurationService.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package org.apache.continuum.buildagent.configuration;
-
-/*
- * 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.io.File;
-import java.util.List;
-
-public interface BuildAgentConfigurationService
-{
-    String ROLE = BuildAgentConfigurationService.class.getName();
-
-    File getBuildOutputDirectory();
-
-    File getBuildOutputDirectory( int projectId );
-
-    File getWorkingDirectory();
-
-    File getWorkingDirectory( int projectId );
-
-    String getContinuumServerUrl();
-
-    String getBuildOutput( int projectId )
-        throws BuildAgentConfigurationException;
-
-    File getBuildOutputFile( int projectId )
-        throws BuildAgentConfigurationException;
-
-    List getAvailableInstallations();
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/DefaultBuildAgentConfiguration.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/DefaultBuildAgentConfiguration.java
deleted file mode 100644
index c8668d5..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/DefaultBuildAgentConfiguration.java
+++ /dev/null
@@ -1,169 +0,0 @@
-package org.apache.continuum.buildagent.configuration;
-
-/*
- * 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.io.File;
-import java.io.FileInputStream;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStreamReader;
-
-import org.apache.continuum.buildagent.model.ContinuumBuildAgentConfigurationModel;
-import org.apache.continuum.buildagent.model.io.xpp3.ContinuumBuildAgentConfigurationModelXpp3Reader;
-import org.apache.continuum.buildagent.model.io.xpp3.ContinuumBuildAgentConfigurationModelXpp3Writer;
-import org.codehaus.plexus.util.StringUtils;
-import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class DefaultBuildAgentConfiguration
-    implements BuildAgentConfiguration
-{
-    private Logger log = LoggerFactory.getLogger( getClass() );
-
-    private File configurationFile;
-
-    private GeneralBuildAgentConfiguration generalBuildAgentConfiguration;
-
-    protected void initialize()
-    {
-        if ( log.isDebugEnabled() )
-        {
-            log.debug( "configurationFile null " + ( configurationFile.getPath() == null ) );
-        }
-        if ( configurationFile != null && configurationFile.exists() )
-        {
-            try
-            {
-                reload( configurationFile );
-            }
-            catch ( BuildAgentConfigurationException e )
-            {
-                // skip this and only log a warn
-                log.warn( " error on loading configuration from file " + configurationFile.getPath() );
-            }
-        }
-        else
-        {
-            log.info( "build agent configuration file does not exists" );
-            this.generalBuildAgentConfiguration = new GeneralBuildAgentConfiguration();
-        }
-    }
-
-    public GeneralBuildAgentConfiguration getContinuumBuildAgentConfiguration()
-        throws BuildAgentConfigurationException
-    {
-        return generalBuildAgentConfiguration;
-    }
-
-    public void reload()
-        throws BuildAgentConfigurationException
-    {
-        this.initialize();
-    }
-
-    public void reload( File file )
-        throws BuildAgentConfigurationException
-    {
-        try
-        {
-            ContinuumBuildAgentConfigurationModelXpp3Reader configurationXpp3Reader = 
-                new ContinuumBuildAgentConfigurationModelXpp3Reader();
-            ContinuumBuildAgentConfigurationModel configuration = configurationXpp3Reader
-                .read( new InputStreamReader( new FileInputStream( file ) ) );
-
-            this.generalBuildAgentConfiguration = new GeneralBuildAgentConfiguration();
-            if ( StringUtils.isNotEmpty( configuration.getBuildOutputDirectory() ) )
-            {
-                this.generalBuildAgentConfiguration.setBuildOutputDirectory( new File( configuration.getBuildOutputDirectory() ) );
-            }
-            if ( StringUtils.isNotEmpty( configuration.getWorkingDirectory() ) )
-            {
-                this.generalBuildAgentConfiguration.setWorkingDirectory( new File( configuration.getWorkingDirectory() ) );
-            }
-            this.generalBuildAgentConfiguration.setContinuumServerUrl( configuration.getContinuumServerUrl() );
-            this.generalBuildAgentConfiguration.setInstallations( configuration.getInstallations() );
-        }
-        catch ( IOException e )
-        {
-            log.error( e.getMessage(), e );
-            throw new BuildAgentConfigurationException( e.getMessage(), e );
-        }
-        catch ( XmlPullParserException e )
-        {
-            log.error( e.getMessage(), e );
-            throw new BuildAgentConfigurationException( e.getMessage(), e );
-        }
-    }
-
-    public void save()
-        throws BuildAgentConfigurationException
-    {
-        if ( !configurationFile.exists() )
-        {
-            configurationFile.getParentFile().mkdir();
-        }
-        save( configurationFile );
-    }
-
-    public void save( File file )
-        throws BuildAgentConfigurationException
-    {
-        try
-        {
-            ContinuumBuildAgentConfigurationModel configurationModel = new ContinuumBuildAgentConfigurationModel();
-            if ( this.generalBuildAgentConfiguration.getBuildOutputDirectory() != null )
-            {
-                configurationModel.setBuildOutputDirectory( this.generalBuildAgentConfiguration.getBuildOutputDirectory().getPath() );
-            }
-            if ( this.generalBuildAgentConfiguration.getWorkingDirectory() != null )
-            {
-                configurationModel.setWorkingDirectory( this.generalBuildAgentConfiguration.getWorkingDirectory().getPath() );
-            }
-            configurationModel.setContinuumServerUrl( this.generalBuildAgentConfiguration.getContinuumServerUrl() );
-            configurationModel.setInstallations( this.generalBuildAgentConfiguration.getInstallations() );
-
-            ContinuumBuildAgentConfigurationModelXpp3Writer writer = new ContinuumBuildAgentConfigurationModelXpp3Writer();
-            FileWriter fileWriter = new FileWriter( file );
-            writer.write( fileWriter, configurationModel );
-        }
-        catch ( IOException e )
-        {
-            log.error( e.getMessage(), e );
-            throw new BuildAgentConfigurationException( e.getMessage(), e );
-        }
-    }
-
-    public void setContinuumBuildAgentConfiguration( GeneralBuildAgentConfiguration buildAgentConfiguration )
-        throws BuildAgentConfigurationException
-    {
-        this.generalBuildAgentConfiguration = buildAgentConfiguration;
-    }
-
-    public File getConfigurationFile()
-    {
-        return configurationFile;
-    }
-
-    public void setConfigurationFile( File configurationFile )
-    {
-        this.configurationFile = configurationFile;
-    }
-}
\ No newline at end of file
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/DefaultBuildAgentConfigurationService.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/DefaultBuildAgentConfigurationService.java
deleted file mode 100644
index 344c53c..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/DefaultBuildAgentConfigurationService.java
+++ /dev/null
@@ -1,122 +0,0 @@
-package org.apache.continuum.buildagent.configuration;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
-
-import javax.annotation.Resource;
-
-import org.codehaus.plexus.util.FileUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class DefaultBuildAgentConfigurationService
-    implements BuildAgentConfigurationService
-{
-    private Logger log = LoggerFactory.getLogger( this.getClass() );
-
-    @Resource
-    private BuildAgentConfiguration buildAgentConfiguration;
-
-    private GeneralBuildAgentConfiguration generalBuildAgentConfiguration;
-
-    public void initialize()
-        throws BuildAgentConfigurationException
-    {
-        loadData();
-    }
-
-    public BuildAgentConfiguration getBuildAgentConfiguration()
-    {
-        return buildAgentConfiguration;
-    }
-
-    public void setBuildAgentConfiguration( BuildAgentConfiguration buildAgentConfiguration )
-    {
-        this.buildAgentConfiguration = buildAgentConfiguration;
-    }
-
-    public File getBuildOutputDirectory()
-    {
-        return generalBuildAgentConfiguration.getBuildOutputDirectory();
-    }
-
-    public File getBuildOutputDirectory( int projectId )
-    {
-        File dir = new File( getBuildOutputDirectory(), Integer.toString( projectId ) );
-
-        try
-        {
-            dir = dir.getCanonicalFile();
-        }
-        catch ( IOException e )
-        {
-        }
-
-        return dir;
-    }
-
-    public File getWorkingDirectory()
-    {
-        return generalBuildAgentConfiguration.getWorkingDirectory();
-    }
-
-    public File getWorkingDirectory( int projectId )
-    {
-        return new File( generalBuildAgentConfiguration.getWorkingDirectory(), Integer.toString( projectId ) );
-    }
-
-    public String getBuildOutput( int projectId )
-        throws BuildAgentConfigurationException
-    {
-        File file = getBuildOutputFile( projectId );
-    
-        try
-        {
-            if ( file.exists() )
-            {
-                return FileUtils.fileRead( file.getAbsolutePath() );
-            }
-            else
-            {
-                return "There are no output for this build.";
-            }
-        }
-        catch ( IOException e )
-        {
-            log.warn( "Error reading build output for project '" + projectId + "'.", e );
-    
-            return null;
-        }
-    }
-
-    public File getBuildOutputFile( int projectId )
-        throws BuildAgentConfigurationException
-    {
-        File dir = getBuildOutputDirectory( projectId );
-
-        if ( !dir.exists() && !dir.mkdirs() )
-        {
-            throw new BuildAgentConfigurationException( 
-                      "Could not make the build output directory: " + "'" + dir.getAbsolutePath() + "'." );
-        }
-
-        return new File( dir, "build.log.txt" );
-    }
-
-    public String getContinuumServerUrl()
-    {
-        return generalBuildAgentConfiguration.getContinuumServerUrl();
-    }
-
-    public List getAvailableInstallations()
-    {
-        return generalBuildAgentConfiguration.getInstallations();
-    }
-
-    private void loadData()
-        throws BuildAgentConfigurationException
-    {
-        generalBuildAgentConfiguration = buildAgentConfiguration.getContinuumBuildAgentConfiguration();
-    }
-}
\ No newline at end of file
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/GeneralBuildAgentConfiguration.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/GeneralBuildAgentConfiguration.java
deleted file mode 100644
index 7b2bf68..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/configuration/GeneralBuildAgentConfiguration.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package org.apache.continuum.buildagent.configuration;
-
-/*
- * 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.io.File;
-import java.util.List;
-
-import org.apache.continuum.buildagent.model.Installation;
-
-public class GeneralBuildAgentConfiguration
-{
-    private File workingDirectory;
-
-    private File buildOutputDirectory;
-
-    private String continuumServerUrl;
-
-    private List<Installation> installations;
-
-    public File getWorkingDirectory()
-    {
-        return workingDirectory;
-    }
-
-    public void setWorkingDirectory( File workingDirectory )
-    {
-        this.workingDirectory = workingDirectory;
-    }
-
-    public File getBuildOutputDirectory()
-    {
-        return buildOutputDirectory;
-    }
-
-    public void setBuildOutputDirectory( File buildOutputDirectory )
-    {
-        this.buildOutputDirectory = buildOutputDirectory;
-    }
-
-    public String getContinuumServerUrl()
-    {
-        return continuumServerUrl;
-    }
-
-    public void setContinuumServerUrl( String continuumServerUrl )
-    {
-        this.continuumServerUrl = continuumServerUrl;
-    }
-
-    public List<Installation> getInstallations()
-    {
-        return installations;
-    }
-
-    public void setInstallations( List<Installation> installations )
-    {
-        this.installations = installations;
-    }
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/installation/DefaultBuildAgentInstallationService.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/installation/DefaultBuildAgentInstallationService.java
deleted file mode 100644
index 6aadbd6..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/installation/DefaultBuildAgentInstallationService.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package org.apache.continuum.buildagent.installation;
-
-/*
- * 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.HashMap;
-import java.util.Map;
-
-import org.apache.maven.continuum.execution.ExecutorConfigurator;
-import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
-import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
-import org.springframework.stereotype.Service;
-
-@Service("buildAgentInstallationService")
-public class DefaultBuildAgentInstallationService
-    implements BuildAgentInstallationService, Initializable
-{
-    private Map<String, ExecutorConfigurator> typesValues;
-
-    public ExecutorConfigurator getExecutorConfigurator( String type )
-    {
-        return this.typesValues.get( type );
-    }
-
-    public void initialize()
-        throws InitializationException
-    {
-        this.typesValues = new HashMap<String, ExecutorConfigurator>();
-        this.typesValues.put( BuildAgentInstallationService.ANT_TYPE,
-                              new ExecutorConfigurator( "ant", "bin", "ANT_HOME", "-version" ) );
-
-        this.typesValues.put( BuildAgentInstallationService.ENVVAR_TYPE, null );
-        this.typesValues.put( BuildAgentInstallationService.JDK_TYPE,
-                              new ExecutorConfigurator( "java", "bin", "JAVA_HOME", "-version" ) );
-        this.typesValues.put( BuildAgentInstallationService.MAVEN1_TYPE,
-                              new ExecutorConfigurator( "maven", "bin", "MAVEN_HOME", "-v" ) );
-        this.typesValues
-            .put( BuildAgentInstallationService.MAVEN2_TYPE, new ExecutorConfigurator( "mvn", "bin", "M2_HOME", "-v" ) );
-    }
-
-    public String getEnvVar( String type )
-    {
-        ExecutorConfigurator executorConfigurator = this.typesValues.get( type );
-        return executorConfigurator == null ? null : executorConfigurator.getEnvVar();
-    }
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/manager/BuildAgentManager.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/manager/BuildAgentManager.java
deleted file mode 100644
index c233067..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/manager/BuildAgentManager.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package org.apache.continuum.buildagent.manager;
-
-/*
- * 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.List;
-import java.util.Map;
-
-import org.apache.continuum.buildagent.buildcontext.BuildContext;
-import org.apache.maven.continuum.ContinuumException;
-
-public interface BuildAgentManager
-{
-    String ROLE = BuildAgentManager.class.getName();
-
-    void prepareBuildProjects( List<BuildContext> buildContextList )
-        throws ContinuumException;
-
-    void returnBuildResult( Map result )
-        throws ContinuumException;
-    
-    void startProjectBuild( int projectId )
-        throws ContinuumException;
-
-    Map<String, String> getEnvironments( int buildDefinitionId, String installationType )
-        throws ContinuumException;
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/manager/DefaultBuildAgentManager.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/manager/DefaultBuildAgentManager.java
deleted file mode 100644
index 98cafcf..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/manager/DefaultBuildAgentManager.java
+++ /dev/null
@@ -1,521 +0,0 @@
-package org.apache.continuum.buildagent.manager;
-
-/*
- * 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.net.MalformedURLException;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.continuum.buildagent.buildcontext.BuildContext;
-import org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
-import org.apache.continuum.buildagent.taskqueue.manager.BuildAgentTaskQueueManager;
-import org.apache.continuum.buildagent.utils.BuildContextToBuildDefinition;
-import org.apache.continuum.buildagent.utils.BuildContextToProject;
-import org.apache.continuum.buildagent.utils.ContinuumBuildAgentUtil;
-import org.apache.continuum.distributed.transport.master.MasterBuildAgentTransportClient;
-import org.apache.continuum.taskqueue.BuildProjectTask;
-import org.apache.continuum.taskqueue.manager.TaskQueueManagerException;
-import org.apache.maven.continuum.ContinuumException;
-import org.apache.maven.continuum.model.project.BuildDefinition;
-import org.apache.maven.continuum.model.project.Project;
-import org.apache.maven.continuum.model.scm.ScmResult;
-import org.apache.maven.continuum.project.ContinuumProjectState;
-import org.codehaus.plexus.action.ActionManager;
-import org.codehaus.plexus.action.ActionNotFoundException;
-import org.codehaus.plexus.taskqueue.TaskQueueException;
-import org.codehaus.plexus.util.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * @plexus.component role="org.apache.continuum.buildagent.manager.BuildAgentManager" role-hint="default"
- */
-public class DefaultBuildAgentManager
-    implements BuildAgentManager
-{
-    private Logger log = LoggerFactory.getLogger( this.getClass() );
-
-    /**
-     * @plexus.requirement
-     */
-    private ActionManager actionManager;
-
-    /**
-     * @plexus.requirement
-     */
-    private BuildAgentConfigurationService buildAgentConfigurationService;
-
-    /**
-     * @plexus.requirement
-     */
-    private BuildAgentTaskQueueManager buildAgentTaskQueueManager;
-
-    public void prepareBuildProjects( List<BuildContext> buildContexts)
-        throws ContinuumException
-    {
-        Map<String, Object> context = null;
-
-        if ( buildContexts != null && buildContexts.size() > 0 )
-        {
-            try
-            {
-                for ( BuildContext buildContext : buildContexts )
-                {
-                    BuildDefinition buildDef = BuildContextToBuildDefinition.getBuildDefinition( buildContext );
-        
-                    log.info( "Check scm root state" );
-                    if ( !checkProjectScmRoot( context ) )
-                    {
-                        break;
-                    }
-                    
-                    log.info( "Starting prepare build" );
-                    startPrepareBuild( buildContext );
-                    
-                    log.info( "Initializing prepare build" );
-                    initializeActionContext( buildContext );
-                    
-                    try
-                    {
-                        if ( buildDef.isBuildFresh() )
-                        {
-                            log.info( "Clean up working directory" );
-                            cleanWorkingDirectory( buildContext );
-                        }
-            
-                        log.info( "Updating working directory" );
-                        updateWorkingDirectory( buildContext );
-                    }
-                    finally
-                    {
-                        endProjectPrepareBuild( buildContext );
-                        context = buildContext.getActionContext();
-                    }
-                }
-            }
-            finally
-            {
-                endPrepareBuild( context );
-            }
-
-            if ( checkProjectScmRoot( context ) )
-            {
-                buildProjects( buildContexts );
-            }
-        }
-    }
-
-    public void startProjectBuild( int projectId )
-        throws ContinuumException
-    {
-        try
-        {
-            MasterBuildAgentTransportClient client = new MasterBuildAgentTransportClient(
-                new URL( buildAgentConfigurationService.getContinuumServerUrl() ) );
-            client.startProjectBuild( projectId );
-        }
-        catch ( MalformedURLException e )
-        {
-            log.error( "Invalid continuum server URL '" + buildAgentConfigurationService.getContinuumServerUrl() + "'" );
-            throw new ContinuumException( "Invalid continuum server URL '" + buildAgentConfigurationService.getContinuumServerUrl() + "'" );
-        }
-        catch ( Exception e )
-        {
-            log.error( "Error starting project build", e );
-            throw new ContinuumException( "Error starting project build", e );
-        }
-    }
-
-    public void returnBuildResult( Map buildResult )
-        throws ContinuumException
-    {
-        try
-        {
-            MasterBuildAgentTransportClient client = new MasterBuildAgentTransportClient(
-                new URL( buildAgentConfigurationService.getContinuumServerUrl() ) );
-            client.returnBuildResult( buildResult );
-        }
-        catch ( MalformedURLException e )
-        {
-            log.error( "Invalid continuum server URL '" + buildAgentConfigurationService.getContinuumServerUrl() + "'" );
-            throw new ContinuumException( "Invalid continuum server URL '" + buildAgentConfigurationService.getContinuumServerUrl() + "'" );
-        }
-        catch ( Exception e )
-        {
-            log.error( "Error while returning build result to the continuum server", e );
-            throw new ContinuumException( e.getMessage(), e );
-        }
-    }
-
-    public Map<String, String> getEnvironments( int buildDefinitionId, String installationType )
-        throws ContinuumException
-    {
-        try
-        {
-            MasterBuildAgentTransportClient client = new MasterBuildAgentTransportClient(
-                new URL( buildAgentConfigurationService.getContinuumServerUrl() ) );
-            return client.getEnvironments( buildDefinitionId, installationType );
-        }
-        catch ( MalformedURLException e )
-        {
-            log.error( "Invalid continuum server URL '" + buildAgentConfigurationService.getContinuumServerUrl() + "'" );
-            throw new ContinuumException( "Invalid continuum server URL '" + buildAgentConfigurationService.getContinuumServerUrl() + "'" );
-        }
-        catch ( Exception e )
-        {
-            log.error( "Error while retrieving environments for build definition " + buildDefinitionId, e );
-            throw new ContinuumException( e.getMessage(), e );
-        }
-    }
-
-    private void startPrepareBuild( BuildContext buildContext )
-        throws ContinuumException
-    {
-        Map<String, Object> actionContext = buildContext.getActionContext();
-        
-        if ( actionContext == null || !( ContinuumBuildAgentUtil.getScmRootState( actionContext ) == ContinuumProjectState.UPDATING ) ) 
-        {
-            Map<String, Object> map = new HashMap<String, Object>();
-            map.put( ContinuumBuildAgentUtil.KEY_PROJECT_GROUP_ID, new Integer( buildContext.getProjectGroupId() ) );
-            map.put( ContinuumBuildAgentUtil.KEY_SCM_ROOT_ADDRESS, buildContext.getScmRootAddress() );
-            
-            try
-            {
-                MasterBuildAgentTransportClient client = new MasterBuildAgentTransportClient(
-                    new URL( buildAgentConfigurationService.getContinuumServerUrl() ) );
-                client.startPrepareBuild( map );
-            }
-            catch ( MalformedURLException e )
-            {
-                log.error( "Invalid continuum server URL '" + buildAgentConfigurationService.getContinuumServerUrl() + "'" );
-                throw new ContinuumException( "Invalid continuum server URL '" + buildAgentConfigurationService.getContinuumServerUrl() + "'", e );
-            }
-            catch ( Exception e )
-            {
-                log.error( "Error starting prepare build", e );
-                throw new ContinuumException( "Error starting prepare build", e );
-            }
-        }
-    }
-
-    private void initializeActionContext( BuildContext buildContext )
-    {
-        Map<String, Object> actionContext = new HashMap<String, Object>();
-
-        actionContext.put( ContinuumBuildAgentUtil.KEY_PROJECT_ID, buildContext.getProjectId() );
-        actionContext.put( ContinuumBuildAgentUtil.KEY_PROJECT, BuildContextToProject.getProject( buildContext ) );
-        actionContext.put( ContinuumBuildAgentUtil.KEY_BUILD_DEFINITION, BuildContextToBuildDefinition.getBuildDefinition( buildContext ) );
-        actionContext.put( ContinuumBuildAgentUtil.KEY_SCM_ROOT_STATE, ContinuumProjectState.UPDATING );
-        actionContext.put( ContinuumBuildAgentUtil.KEY_PROJECT_GROUP_ID, buildContext.getProjectGroupId() );
-        actionContext.put( ContinuumBuildAgentUtil.KEY_SCM_ROOT_ADDRESS, buildContext.getScmRootAddress() );
-        
-        buildContext.setActionContext( actionContext );
-    }
-
-    private boolean checkProjectScmRoot( Map context )
-    {
-        if ( context != null && ContinuumBuildAgentUtil.getScmRootState( context ) == ContinuumProjectState.ERROR )
-        {
-            return false;
-        }
-
-        return true;
-    }
-
-    private void cleanWorkingDirectory( BuildContext buildContext )
-        throws ContinuumException
-    {
-        performAction( "clean-agent-work-directory", buildContext );
-    }
-
-    private void updateWorkingDirectory( BuildContext buildContext )
-        throws ContinuumException
-    {
-        Map<String, Object> actionContext = buildContext.getActionContext();
-
-        performAction( "check-agent-working-directory", buildContext );
-        
-        boolean workingDirectoryExists =
-            ContinuumBuildAgentUtil.getBoolean( actionContext, ContinuumBuildAgentUtil.KEY_WORKING_DIRECTORY_EXISTS );
-    
-        ScmResult scmResult;
-    
-        if ( workingDirectoryExists )
-        {
-            performAction( "update-agent-working-directory", buildContext );
-    
-            scmResult = ContinuumBuildAgentUtil.getUpdateScmResult( actionContext, null );
-        }
-        else
-        {
-            Project project = ContinuumBuildAgentUtil.getProject( actionContext );
-    
-            actionContext.put( ContinuumBuildAgentUtil.KEY_WORKING_DIRECTORY,
-                               buildAgentConfigurationService.getWorkingDirectory( project.getId() ).getAbsolutePath() );
-    
-            performAction( "checkout-agent-project", buildContext );
-    
-            scmResult = ContinuumBuildAgentUtil.getCheckoutScmResult( actionContext, null );
-        }
-    
-        buildContext.setScmResult( scmResult );
-        actionContext.put( ContinuumBuildAgentUtil.KEY_SCM_RESULT, scmResult );
-    }
-
-    private void endProjectPrepareBuild( BuildContext buildContext )
-        throws ContinuumException
-    {
-        Map<String, Object> context = buildContext.getActionContext();
-
-        ScmResult scmResult = ContinuumBuildAgentUtil.getScmResult( context, null );
-        Project project = ContinuumBuildAgentUtil.getProject( context );
-
-        if ( scmResult == null || !scmResult.isSuccess() )
-        {
-            context.put( ContinuumBuildAgentUtil.KEY_SCM_ROOT_STATE, ContinuumProjectState.ERROR );
-        }
-
-        // connect to continuum server (master)
-        try
-        {
-            MasterBuildAgentTransportClient client = new MasterBuildAgentTransportClient(
-                 new URL( buildAgentConfigurationService.getContinuumServerUrl() ) );
-            client.returnScmResult( createScmResult( buildContext ) );
-        }
-        catch ( MalformedURLException e )
-        {
-            throw new ContinuumException( "Invalid Continuum Server URL '" + buildAgentConfigurationService.getContinuumServerUrl() + "'" );
-        }
-        catch ( Exception e )
-        {
-            throw new ContinuumException( "Error while returning scm result to the continuum server", e );
-        }
-    }
-
-    private void endPrepareBuild( Map context )
-        throws ContinuumException
-    {
-        if ( context != null )
-        {
-            Map<String, Object> result = new HashMap<String, Object>();
-            result.put( ContinuumBuildAgentUtil.KEY_PROJECT_GROUP_ID, new Integer( ContinuumBuildAgentUtil.getProjectGroupId( context ) ) );
-            result.put( ContinuumBuildAgentUtil.KEY_SCM_ROOT_ADDRESS, ContinuumBuildAgentUtil.getScmRootAddress( context ) );
-            result.put( ContinuumBuildAgentUtil.KEY_SCM_ROOT_STATE, new Integer( ContinuumBuildAgentUtil.getScmRootState( context ) ) );
-            
-            if ( ContinuumBuildAgentUtil.getScmRootState( context ) == ContinuumProjectState.ERROR )
-            {
-                String error = convertScmResultToError( ContinuumBuildAgentUtil.getScmResult( context, null ) );
-                
-                if ( StringUtils.isEmpty( error ) )
-                {
-                    result.put( ContinuumBuildAgentUtil.KEY_SCM_ERROR, "" );
-                }
-                else
-                {
-                    result.put( ContinuumBuildAgentUtil.KEY_SCM_ERROR, error );
-                }
-            }
-            else
-            {
-                result.put( ContinuumBuildAgentUtil.KEY_SCM_ERROR, "" );
-            }
-    
-            // connect to continuum server (master)
-            try
-            {
-                MasterBuildAgentTransportClient client = new MasterBuildAgentTransportClient(
-                     new URL( buildAgentConfigurationService.getContinuumServerUrl() ) );
-                client.prepareBuildFinished( result );
-            }
-            catch ( MalformedURLException e )
-            {
-                throw new ContinuumException( "Invalid Continuum Server URL '" + buildAgentConfigurationService.getContinuumServerUrl() + "'" );
-            }
-            catch ( Exception e )
-            {
-                throw new ContinuumException( "Error while finishing prepare build", e );
-            }
-        }
-    }
-
-    private Map<String, Object> createScmResult( BuildContext buildContext )
-    {
-        Map<String, Object> result = new HashMap<String, Object>();
-        ScmResult scmResult = buildContext.getScmResult();
-
-        result.put( ContinuumBuildAgentUtil.KEY_PROJECT_ID, new Integer( buildContext.getProjectId() ) );
-        if ( StringUtils.isEmpty( scmResult.getCommandLine() ) )
-        {
-            result.put( ContinuumBuildAgentUtil.KEY_SCM_COMMAND_LINE, "" );
-        }
-        else
-        {
-            result.put( ContinuumBuildAgentUtil.KEY_SCM_COMMAND_LINE, scmResult.getCommandLine() );
-        }
-        if ( StringUtils.isEmpty( scmResult.getCommandOutput() ) )
-        {
-            result.put( ContinuumBuildAgentUtil.KEY_SCM_COMMAND_OUTPUT, "" );
-        }
-        else
-        {
-            result.put( ContinuumBuildAgentUtil.KEY_SCM_COMMAND_OUTPUT, scmResult.getCommandOutput() );
-        }
-        if ( StringUtils.isEmpty( scmResult.getProviderMessage() ) )
-        {
-            result.put( ContinuumBuildAgentUtil.KEY_SCM_PROVIDER_MESSAGE, "" );
-        }
-        else
-        {
-            result.put( ContinuumBuildAgentUtil.KEY_SCM_PROVIDER_MESSAGE, scmResult.getProviderMessage() );
-        }
-        if ( StringUtils.isEmpty( scmResult.getException() ) )
-        {
-            result.put( ContinuumBuildAgentUtil.KEY_SCM_EXCEPTION, "" );
-        }
-        else
-        {
-            result.put( ContinuumBuildAgentUtil.KEY_SCM_EXCEPTION, scmResult.getException() );
-        }
-        result.put( ContinuumBuildAgentUtil.KEY_SCM_SUCCESS, new Boolean( scmResult.isSuccess() ) );
-        
-        return result;
-    }
-
-    private String convertScmResultToError( ScmResult result )
-    {
-        String error = "";
-
-        if ( result == null )
-        {
-            error = "Scm result is null.";
-        }
-        else
-        {
-            if ( result.getCommandLine() != null )
-            {
-                error = "Command line: " + StringUtils.clean( result.getCommandLine() ) +
-                    System.getProperty( "line.separator" );
-            }
-
-            if ( result.getProviderMessage() != null )
-            {
-                error = "Provider message: " + StringUtils.clean( result.getProviderMessage() ) +
-                    System.getProperty( "line.separator" );
-            }
-
-            if ( result.getCommandOutput() != null )
-            {
-                error += "Command output: " + System.getProperty( "line.separator" );
-                error += "-------------------------------------------------------------------------------" +
-                    System.getProperty( "line.separator" );
-                error += StringUtils.clean( result.getCommandOutput() ) + System.getProperty( "line.separator" );
-                error += "-------------------------------------------------------------------------------" +
-                    System.getProperty( "line.separator" );
-            }
-
-            if ( result.getException() != null )
-            {
-                error += "Exception:" + System.getProperty( "line.separator" );
-                error += result.getException();
-            }
-        }
-
-        return error;
-    }
-
-    private void performAction( String actionName, BuildContext buildContext )
-        throws ContinuumException
-    {
-        ContinuumException exception = null;
-    
-        try
-        {
-            log.info( "Performing action " + actionName );
-            actionManager.lookup( actionName ).execute( buildContext.getActionContext() );
-            return;
-        }
-        catch ( ActionNotFoundException e )
-        {
-            exception = new ContinuumException( "Error looking up action '" + actionName + "'", e );
-        }
-        catch ( Exception e )
-        {
-            exception = new ContinuumException( "Error executing action '" + actionName + "'", e );
-        }
-        
-        ScmResult result = new ScmResult();
-        
-        result.setSuccess( false );
-        
-        result.setException( ContinuumBuildAgentUtil.throwableToString( exception ) );
-
-        buildContext.setScmResult( result );
-        buildContext.getActionContext().put( ContinuumBuildAgentUtil.KEY_UPDATE_SCM_RESULT, result );
-        
-        throw exception;
-    }
-    
-    private void buildProjects( List<BuildContext> buildContexts )
-        throws ContinuumException
-    {
-        for ( BuildContext buildContext : buildContexts )
-        {
-            // only build if it's forced build or project state is not OK
-            if ( buildContext.getTrigger() == ContinuumProjectState.TRIGGER_FORCED || 
-                 buildContext.getProjectState() != ContinuumProjectState.OK )
-            {
-                BuildProjectTask buildProjectTask = new BuildProjectTask( buildContext.getProjectId(),
-                                                                          buildContext.getBuildDefinitionId(),
-                                                                          buildContext.getTrigger(),
-                                                                          buildContext.getProjectName(),
-                                                                          "" );
-                try
-                {
-                    buildAgentTaskQueueManager.getBuildQueue().put( buildProjectTask );
-                }
-                catch ( TaskQueueException e )
-                {
-                    log.error( "Error while enqueing build task for project " + buildContext.getProjectId(), e );
-                    throw new ContinuumException( "Error while enqueuing build task for project " + buildContext.getProjectId(), e );
-                }
-            }
-        }
-
-        try
-        {
-            boolean stop = false;
-            while ( !stop )
-            {
-                if ( buildAgentTaskQueueManager.getCurrentProjectInBuilding() <= 0 && 
-                                !buildAgentTaskQueueManager.hasBuildTaskInQueue()  )
-                {
-                    stop = true;
-                }
-            }   
-        }
-        catch ( TaskQueueManagerException e )
-        {
-            throw new ContinuumException( e.getMessage(), e );
-        }
-    }
-
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/taskqueue/execution/BuildProjectTaskExecutor.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/taskqueue/execution/BuildProjectTaskExecutor.java
deleted file mode 100644
index baeaf08..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/taskqueue/execution/BuildProjectTaskExecutor.java
+++ /dev/null
@@ -1,345 +0,0 @@
-package org.apache.continuum.buildagent.taskqueue.execution;
-
-/*
- * 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.io.File;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import javax.annotation.Resource;
-
-import org.apache.commons.lang.StringEscapeUtils;
-import org.apache.continuum.buildagent.buildcontext.BuildContext;
-import org.apache.continuum.buildagent.buildcontext.manager.BuildContextManager;
-import org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
-import org.apache.continuum.buildagent.installation.BuildAgentInstallationService;
-import org.apache.continuum.buildagent.manager.BuildAgentManager;
-import org.apache.continuum.buildagent.utils.BuildContextToBuildDefinition;
-import org.apache.continuum.buildagent.utils.BuildContextToProject;
-import org.apache.continuum.buildagent.utils.ContinuumBuildAgentUtil;
-import org.apache.continuum.taskqueue.BuildProjectTask;
-import org.apache.maven.continuum.ContinuumException;
-import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
-import org.apache.maven.continuum.model.project.BuildResult;
-import org.apache.maven.continuum.project.ContinuumProjectState;
-import org.apache.maven.scm.ScmException;
-import org.apache.maven.scm.repository.ScmRepositoryException;
-import org.codehaus.plexus.action.ActionManager;
-import org.codehaus.plexus.action.ActionNotFoundException;
-import org.codehaus.plexus.taskqueue.Task;
-import org.codehaus.plexus.taskqueue.execution.TaskExecutionException;
-import org.codehaus.plexus.taskqueue.execution.TaskExecutor;
-import org.codehaus.plexus.util.FileUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * @plexus.component role="org.codehaus.plexus.taskqueue.execution.TaskExecutor"
- * role-hint="build-agent"
- */
-public class BuildProjectTaskExecutor
-    implements TaskExecutor
-{
-    private Logger log = LoggerFactory.getLogger( this.getClass() );
-
-    /**
-     * @plexus.requirement
-     */
-    private BuildContextManager buildContextManager;
-
-    /**
-     * @plexus.requirement
-     */
-    private ActionManager actionManager;
-
-    /**
-     * @plexus.requirement
-     */
-    private BuildAgentConfigurationService buildAgentConfigurationService;
-
-    /**
-     * @plexus.requirement
-     */
-    private BuildAgentManager buildAgentManager;
-
-    public void executeTask( Task task )
-        throws TaskExecutionException
-    {
-        BuildProjectTask buildProjectTask = (BuildProjectTask) task;
-
-        int projectId = buildProjectTask.getProjectId();
-
-        log.info( "Initializing build" );
-        BuildContext context = buildContextManager.getBuildContext( projectId );
-        initializeBuildContext( context );
-
-        if ( !checkScmResult( context ) )
-        {
-            log.info( "Error updating from SCM, not building" );
-            return;
-        }
-        
-        log.info( "Starting build of " + context.getProjectName() );
-        startBuild( context );
-
-        try
-        {
-            Map actionContext = context.getActionContext();
-
-            performAction( "execute-agent-builder", context );
-
-            updateBuildResult( context, null );
-        }
-        finally
-        {
-            endBuild( context );
-        }
-    }
-
-    private void initializeBuildContext( BuildContext buildContext )
-        throws TaskExecutionException
-    {
-        Map<String, Object> actionContext = buildContext.getActionContext();
-
-        actionContext.put( ContinuumBuildAgentUtil.KEY_PROJECT_ID, buildContext.getProjectId() );
-        actionContext.put( ContinuumBuildAgentUtil.KEY_PROJECT, BuildContextToProject.getProject( buildContext ) );
-        actionContext.put( ContinuumBuildAgentUtil.KEY_BUILD_DEFINITION, BuildContextToBuildDefinition.getBuildDefinition( buildContext ) );
-        actionContext.put( ContinuumBuildAgentUtil.KEY_TRIGGER, buildContext.getTrigger() );
-        actionContext.put( ContinuumBuildAgentUtil.KEY_ENVIRONMENTS, getEnvironments( buildContext.getBuildDefinitionId(), 
-                                                                                      getInstallationType( buildContext ) ) );
-        actionContext.put( ContinuumBuildAgentUtil.KEY_LOCAL_REPOSITORY, buildContext.getLocalRepository() );
-
-        buildContext.setBuildStartTime( System.currentTimeMillis() );
-    }
-    
-    private boolean checkScmResult( BuildContext buildContext )
-    {
-        if ( buildContext.getScmResult() == null || !buildContext.getScmResult().isSuccess() )
-        {
-            return false;
-        }
-
-        return true;
-    }
-
-    private void startBuild( BuildContext buildContext )
-        throws TaskExecutionException
-    {
-        try
-        {
-            buildAgentManager.startProjectBuild( buildContext.getProjectId() );
-        }
-        catch ( ContinuumException e )
-        {
-            // do not throw exception, just log?
-            log.error( "Failed to start project '" + buildContext.getProjectName() + "'", e );
-            throw new TaskExecutionException( "Failed to start project '" + buildContext.getProjectName() + "'", e );
-        }
-    }
-
-    private void endBuild( BuildContext buildContext )
-        throws TaskExecutionException
-    {
-        // return build result to master
-        BuildResult buildResult = buildContext.getBuildResult();
-
-        Map<String, Object> result = new HashMap<String, Object>();
-        result.put( ContinuumBuildAgentUtil.KEY_PROJECT_ID, new Integer( buildContext.getProjectId() ) );
-        result.put( ContinuumBuildAgentUtil.KEY_BUILD_DEFINITION_ID, new Integer( buildContext.getBuildDefinitionId() ) );
-        result.put( ContinuumBuildAgentUtil.KEY_TRIGGER, new Integer( buildContext.getTrigger() ) );
-        result.put( ContinuumBuildAgentUtil.KEY_BUILD_STATE, new Integer( buildResult.getState() ) );
-        result.put( ContinuumBuildAgentUtil.KEY_BUILD_START, new Long( buildResult.getStartTime() ).toString() );
-        result.put( ContinuumBuildAgentUtil.KEY_BUILD_END, new Long( buildResult.getEndTime() ).toString() );
-        result.put( ContinuumBuildAgentUtil.KEY_BUILD_EXIT_CODE, new Integer( buildResult.getExitCode() ) );
-        
-        String buildOutput = getBuildOutputText( buildContext.getProjectId() );
-        if ( buildOutput == null )
-        {
-            result.put( ContinuumBuildAgentUtil.KEY_BUILD_OUTPUT, "" );
-        }
-        else
-        {
-            result.put( ContinuumBuildAgentUtil.KEY_BUILD_OUTPUT, buildOutput );
-        }
-
-        if ( buildResult.getError() != null )
-        {
-            result.put( ContinuumBuildAgentUtil.KEY_BUILD_ERROR, buildResult.getError() );
-        }
-        else
-        {
-            result.put( ContinuumBuildAgentUtil.KEY_BUILD_ERROR, "" );
-        }
-
-        try
-        {
-            buildAgentManager.returnBuildResult( result );
-        }
-        catch ( ContinuumException e )
-        {
-            log.error( "Failed to return build result for project '" + buildContext.getProjectName() + "'", e );
-            throw new TaskExecutionException( "Failed to return build result for project '" + buildContext.getProjectName() + "'", e );
-        }
-    }
-
-    private void performAction( String actionName, BuildContext context )
-        throws TaskExecutionException
-    {
-        String error = null;
-        TaskExecutionException exception = null;
-    
-        try
-        {
-            log.info( "Performing action " + actionName );
-            actionManager.lookup( actionName ).execute( context.getActionContext() );
-            return;
-        }
-        catch ( ActionNotFoundException e )
-        {
-            error = ContinuumBuildAgentUtil.throwableToString( e );
-            exception = new TaskExecutionException( "Error looking up action '" + actionName + "'", e );
-        }
-        catch ( ScmRepositoryException e )
-        {
-            error = getValidationMessages( e ) + "\n" + ContinuumBuildAgentUtil.throwableToString( e );
-    
-            exception = new TaskExecutionException( "SCM error while executing '" + actionName + "'", e );
-        }
-        catch ( ScmException e )
-        {
-            error = ContinuumBuildAgentUtil.throwableToString( e );
-    
-            exception = new TaskExecutionException( "SCM error while executing '" + actionName + "'", e );
-        }
-        catch ( Exception e )
-        {
-            exception = new TaskExecutionException( "Error executing action '" + actionName + "'", e );
-            error = ContinuumBuildAgentUtil.throwableToString( exception );
-        }
-
-        updateBuildResult( context, error );
-
-        throw exception;
-    }
-
-    private void updateBuildResult( BuildContext context, String error )
-    {
-        context.setBuildResult( ContinuumBuildAgentUtil.getBuildResult( context.getActionContext(), null ) );
-        
-        if ( context.getBuildResult() == null )
-        {
-            BuildResult build = new BuildResult();
-
-            build.setState( ContinuumProjectState.ERROR );
-
-            build.setTrigger( context.getTrigger() );
-
-            build.setStartTime( context.getBuildStartTime() );
-
-            build.setEndTime( System.currentTimeMillis() );
-
-            build.setBuildDefinition( BuildContextToBuildDefinition.getBuildDefinition( context ) );
-
-            if ( error != null )
-            {
-                build.setError( error );
-            }
-
-            context.setBuildResult( build );
-        }
-    }
-
-    private String getValidationMessages( ScmRepositoryException ex )
-    {
-        List<String> messages = ex.getValidationMessages();
-
-        StringBuffer message = new StringBuffer();
-
-        if ( messages != null && !messages.isEmpty() )
-        {
-            for ( Iterator<String> i = messages.iterator(); i.hasNext(); )
-            {
-                message.append( i.next() );
-
-                if ( i.hasNext() )
-                {
-                    message.append( System.getProperty( "line.separator" ) );
-                }
-            }
-        }
-        return message.toString();
-    }
-
-    private String getBuildOutputText( int projectId )
-    {
-        try
-        {
-            File buildOutputFile = buildAgentConfigurationService.getBuildOutputFile( projectId );
-        
-            if ( buildOutputFile.exists() )
-            {
-                return StringEscapeUtils.escapeHtml( FileUtils.fileRead( buildOutputFile ) );
-            }
-        }
-        catch ( Exception e )
-        {
-            // do not throw exception, just log it
-            log.error( "Error retrieving build output file", e );
-        }
-
-        return null;
-    }
-
-    private Map<String, String> getEnvironments( int buildDefinitionId, String installationType )
-        throws TaskExecutionException
-    {
-        try
-        {
-            return buildAgentManager.getEnvironments( buildDefinitionId, installationType );
-        }
-        catch ( ContinuumException e )
-        {
-            log.error( "Error while retrieving environments of build definition: " + buildDefinitionId, e );
-            throw new TaskExecutionException( "Error while retrieving environments of build definition: " + buildDefinitionId, e );
-        }
-    }
-
-    private String getInstallationType( BuildContext buildContext )
-    {
-        String executorId = buildContext.getExecutorId();
-        
-        if ( ContinuumBuildExecutorConstants.MAVEN_TWO_BUILD_EXECUTOR.equals( executorId ) )
-        {
-            return BuildAgentInstallationService.MAVEN2_TYPE;
-        }
-        else if ( ContinuumBuildExecutorConstants.MAVEN_ONE_BUILD_EXECUTOR.equals( executorId ) )
-        {
-            return BuildAgentInstallationService.MAVEN1_TYPE;
-        }
-        else if ( ContinuumBuildExecutorConstants.ANT_BUILD_EXECUTOR.equals( executorId ) )
-        {
-            return BuildAgentInstallationService.ANT_TYPE;
-        }
-
-        return null;
-    }
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/taskqueue/manager/BuildAgentTaskQueueManager.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/taskqueue/manager/BuildAgentTaskQueueManager.java
deleted file mode 100644
index ebcd3e2..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/taskqueue/manager/BuildAgentTaskQueueManager.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.apache.continuum.buildagent.taskqueue.manager;
-
-/*
- * 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 org.apache.continuum.taskqueue.manager.TaskQueueManagerException;
-import org.codehaus.plexus.taskqueue.TaskQueue;
-
-public interface BuildAgentTaskQueueManager
-{
-    String ROLE = BuildAgentTaskQueueManager.class.getName();
-
-    TaskQueue getBuildQueue();
-
-    void cancelBuild()
-        throws TaskQueueManagerException;
-
-    int getCurrentProjectInBuilding()
-        throws TaskQueueManagerException;
-
-    boolean hasBuildTaskInQueue()
-        throws TaskQueueManagerException;
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/taskqueue/manager/DefaultBuildAgentTaskQueueManager.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/taskqueue/manager/DefaultBuildAgentTaskQueueManager.java
deleted file mode 100644
index 4c146f6..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/taskqueue/manager/DefaultBuildAgentTaskQueueManager.java
+++ /dev/null
@@ -1,164 +0,0 @@
-package org.apache.continuum.buildagent.taskqueue.manager;
-
-/*
- * 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.List;
-
-import javax.annotation.Resource;
-
-import org.apache.continuum.taskqueue.BuildProjectTask;
-import org.apache.continuum.taskqueue.manager.TaskQueueManagerException;
-import org.codehaus.plexus.PlexusConstants;
-import org.codehaus.plexus.PlexusContainer;
-import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
-import org.codehaus.plexus.context.Context;
-import org.codehaus.plexus.context.ContextException;
-import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
-import org.codehaus.plexus.taskqueue.Task;
-import org.codehaus.plexus.taskqueue.TaskQueue;
-import org.codehaus.plexus.taskqueue.TaskQueueException;
-import org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Service;
-
-@Service("buildAgentTaskQueueManager")
-public class DefaultBuildAgentTaskQueueManager
-    implements BuildAgentTaskQueueManager, Contextualizable
-{
-    private Logger log = LoggerFactory.getLogger( this.getClass() );
-
-    @Resource
-    private TaskQueue buildAgentBuildQueue;
-
-    private PlexusContainer container;
-
-    public void cancelBuild()
-        throws TaskQueueManagerException
-    {
-        removeProjectsFromBuildQueue();
-        cancelCurrentBuild();
-    }
-
-    public TaskQueue getBuildQueue()
-    {
-        return buildAgentBuildQueue;
-    }
-
-    public int getCurrentProjectInBuilding()
-        throws TaskQueueManagerException
-    {
-        Task task = getBuildTaskQueueExecutor().getCurrentTask();
-        if ( task != null )
-        {
-            if ( task instanceof BuildProjectTask )
-            {
-                return ( (BuildProjectTask) task ).getProjectId();
-            }
-        }
-        return -1;
-    }
-    
-    private void removeProjectsFromBuildQueue()
-        throws TaskQueueManagerException
-    {
-        try
-        {
-            List<BuildProjectTask> queues = buildAgentBuildQueue.getQueueSnapshot();
-        
-            if ( queues != null )
-            {
-                for ( BuildProjectTask task : queues )
-                {
-                    log.info( "remove project '" + task.getProjectName() + "' from build queue" );
-                    buildAgentBuildQueue.remove( task );
-                }
-            }
-            else
-            {
-                log.info( "no build task in queue" );
-            }
-        }
-        catch ( TaskQueueException e )
-        {
-            throw new TaskQueueManagerException( "Error while getting build tasks from queue", e );
-        }
-    }
-
-    private boolean cancelCurrentBuild()
-        throws TaskQueueManagerException
-    {
-        Task task = getBuildTaskQueueExecutor().getCurrentTask();
-        
-        if ( task != null )
-        {
-            if ( task instanceof BuildProjectTask )
-            {
-                log.info( "Cancelling current build task" );
-                return getBuildTaskQueueExecutor().cancelTask( task );
-            }
-            else
-            {
-                log.warn( "Current task not a BuildProjectTask - not cancelling" );
-            }
-        }
-        else
-        {
-            log.warn( "No task running - not cancelling" );
-        }
-        return false;
-    }
-
-    public TaskQueueExecutor getBuildTaskQueueExecutor()
-        throws TaskQueueManagerException
-    {
-        try
-        {
-            return (TaskQueueExecutor) container.lookup( TaskQueueExecutor.class, "build-agent" );
-        }
-        catch ( ComponentLookupException e )
-        {
-            throw new TaskQueueManagerException( e.getMessage(), e );
-        }
-    }
-
-    public boolean hasBuildTaskInQueue()
-        throws TaskQueueManagerException
-    {
-        try
-        {
-            if ( getBuildQueue().getQueueSnapshot() != null && getBuildQueue().getQueueSnapshot().size() > 0 )
-            {
-                return true;
-            }
-        }
-        catch ( TaskQueueException e )
-        {
-            throw new TaskQueueManagerException( e.getMessage(), e );
-        }
-        return false;
-    }
-
-    public void contextualize( Context context )
-        throws ContextException
-    {
-        container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
-    }
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/BuildContextToProject.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/BuildContextToProject.java
deleted file mode 100644
index 4fb4525..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/BuildContextToProject.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package org.apache.continuum.buildagent.utils;
-
-/*
- * 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 org.apache.continuum.buildagent.buildcontext.BuildContext;
-import org.apache.maven.continuum.model.project.Project;
-
-/**
- * @author Jan Stevens Ancajas
- */
-public class BuildContextToProject
-{
-    public static Project getProject( BuildContext buildContext )
-    {
-        Project project = new Project();    
-
-        project.setId( buildContext.getProjectId() );
-
-        project.setName( buildContext.getProjectName() );
-
-        project.setScmUrl( buildContext.getScmUrl() );
-
-        project.setScmUsername( buildContext.getScmUsername() );
-
-        project.setScmPassword( buildContext.getScmPassword() );
-
-        project.setExecutorId( buildContext.getExecutorId() );
-
-        project.setState( buildContext.getProjectState() );
-        
-        return project;
-    }
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/ContinuumBuildAgentUtil.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/ContinuumBuildAgentUtil.java
deleted file mode 100644
index 72a3c98..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/ContinuumBuildAgentUtil.java
+++ /dev/null
@@ -1,350 +0,0 @@
-package org.apache.continuum.buildagent.utils;
-
-/*
- * 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.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.Map;
-
-import org.apache.maven.continuum.model.project.BuildDefinition;
-import org.apache.maven.continuum.model.project.BuildResult;
-import org.apache.maven.continuum.model.project.Project;
-import org.apache.maven.continuum.model.scm.ScmResult;
-
-public class ContinuumBuildAgentUtil
-{
-    public static final String EOL = System.getProperty( "line.separator" );
-
-    public static final String KEY_PROJECT_ID = "project-id";
-
-    public static final String KEY_BUILD_DEFINITION_ID = "builddefinition-id";
-
-    public static final String KEY_TRIGGER = "trigger";
-
-    public static final String KEY_EXECUTOR_ID = "executor-id";
-
-    public static final String KEY_SCM_URL = "scm-url";
-
-    public static final String KEY_SCM_USERNAME = "scm-username";
-
-    public static final String KEY_SCM_PASSWORD = "scm-password";
-
-    public static final String KEY_BUILD_FILE = "build-file";
-
-    public static final String KEY_GOALS = "goals";
-
-    public static final String KEY_ARGUMENTS = "arguments";
-
-    public static final String KEY_BUILD_FRESH = "build-fresh";
-
-    public static final String KEY_BUILD_START = "build-start";
-
-    public static final String KEY_BUILD_END = "build-end";
-
-    public static final String KEY_BUILD_ERROR = "build-error";
-
-    public static final String KEY_BUILD_EXIT_CODE = "build-exit-code";
-
-    public static final String KEY_BUILD_STATE = "build-state";
-
-    public static final String KEY_SCM_STATE = "scm-state";
-
-    public static final String KEY_SCM_COMMAND_OUTPUT = "scm-command-output";
-
-    public static final String KEY_SCM_COMMAND_LINE = "scm-command-line";
-
-    public static final String KEY_SCM_PROVIDER_MESSAGE = "scm-provider-message";
-
-    public static final String KEY_SCM_EXCEPTION = "scm-exception";
-
-    public static final String KEY_PROJECT_GROUP_ID = "project-group-id";
-
-    public static final String KEY_SCM_ROOT_ADDRESS = "scm-root-address";
-
-    public static final String KEY_SCM_ROOT_STATE = "scm-root-state";
-
-    public static final String KEY_CHECKOUT_SCM_RESULT = "checkout-scm-result";
-
-    public static final String KEY_UPDATE_SCM_RESULT = "update-scm-result";
-
-    public static final String KEY_WORKING_DIRECTORY_EXISTS = "working-directory-exists";
-
-    public static final String KEY_PROJECT = "project";
-
-    public static final String KEY_BUILD_DEFINITION = "build-definition";
-
-    public static final String KEY_SCM_RESULT = "scm-result";
-
-    public static final String KEY_WORKING_DIRECTORY = "working-directory";
-
-    public static final String KEY_SCM_SUCCESS = "scm-success";
-
-    public static final String KEY_SCM_ERROR = "scm-error";
-
-    public static final String KEY_BUILD_RESULT = "build-result";
-
-    public static final String KEY_PROJECT_NAME = "project-name";
-
-    public static final String KEY_BUILD_OUTPUT = "build-output";
-
-    public static final String KEY_PROJECT_STATE = "project-state";
-
-    public static final String KEY_INSTALLATION_NAME = "installation-name";
-
-    public static final String KEY_INSTALLATION_TYPE = "installation-type";
-
-    public static final String KEY_INSTALLATION_VAR_NAME = "installation-var-name";
-
-    public static final String KEY_INSTALLATION_VAR_VALUE = "installation-var-value";
-
-    public static final String KEY_ENVIRONMENTS = "environments";
-
-    public static final String KEY_LOCAL_REPOSITORY = "local-repository";
-
-    public static Integer getProjectId( Map context )
-    {
-        return getInteger( context, KEY_PROJECT_ID );
-    }
-
-    public static String getProjectName( Map context )
-    {
-        return getString( context, KEY_PROJECT_NAME );
-    }
-
-    public static Integer getProjectState( Map context )
-    {
-        return getInteger( context, KEY_PROJECT_STATE );
-    }
-
-    public static Integer getBuildDefinitionId( Map context )
-    {
-        return getInteger( context, KEY_BUILD_DEFINITION_ID );
-    }
-
-    public static String getBuildFile( Map context )
-    {
-        return getString( context, KEY_BUILD_FILE );
-    }
-
-    public static String getExecutorId( Map context )
-    {
-        return getString( context, KEY_EXECUTOR_ID );
-    }
-
-    public static String getGoals( Map context )
-    {
-        return getString( context, KEY_GOALS );
-    }
-
-    public static String getArguments( Map context )
-    {
-        return getString( context, KEY_ARGUMENTS );
-    }
-
-    public static String getScmUrl( Map context )
-    {
-        return getString( context, KEY_SCM_URL );
-    }
-
-    public static String getScmUsername( Map context )
-    {
-        return getString( context, KEY_SCM_USERNAME );
-    }
-
-    public static String getScmPassword( Map context )
-    {
-        return getString( context, KEY_SCM_PASSWORD );
-    }
-
-    public static boolean isBuildFresh( Map context )
-    {
-        return getBoolean( context, KEY_BUILD_FRESH );
-    }
-
-    public static int getProjectGroupId( Map context )
-    {
-        return getInteger( context, KEY_PROJECT_GROUP_ID );
-    }
-
-    public static String getScmRootAddress( Map context )
-    {
-        return getString( context, KEY_SCM_ROOT_ADDRESS );
-    }
-
-    public static int getScmRootState( Map context )
-    {
-        return getInteger( context, KEY_SCM_ROOT_STATE );
-    }
-
-    public static Project getProject( Map context )
-    {
-        return (Project) getObject( context, KEY_PROJECT );
-    }
-
-    public static BuildDefinition getBuildDefinition( Map context )
-    {
-        return (BuildDefinition) getObject( context, KEY_BUILD_DEFINITION );
-    }
-
-    public static ScmResult getCheckoutScmResult( Map context, Object defaultValue )
-    {
-        return (ScmResult) getObject( context, KEY_CHECKOUT_SCM_RESULT, defaultValue );
-    }
-
-    public static ScmResult getUpdateScmResult( Map context, Object defaultValue )
-    {
-        return (ScmResult) getObject( context, KEY_UPDATE_SCM_RESULT, defaultValue );
-    }
-
-    public static ScmResult getScmResult( Map context, Object defaultValue )
-    {
-        return (ScmResult) getObject( context, KEY_SCM_RESULT );
-    }
-
-    public static int getTrigger( Map context )
-    {
-        return (Integer) getObject( context, KEY_TRIGGER );
-    }
-
-    public static BuildResult getBuildResult( Map context, Object defaultValue )
-    {
-        return (BuildResult) getObject( context, KEY_BUILD_RESULT );
-    }
-
-    public static Map<String, String> getEnvironments( Map context )
-    {
-        return (Map<String, String>) getObject( context, KEY_ENVIRONMENTS );
-    }
-
-    public static String getLocalRepository( Map context )
-    {
-        return (String) getObject( context, KEY_LOCAL_REPOSITORY );
-    }
-
-    // ----------------------------------------------------------------------
-    //
-    // ----------------------------------------------------------------------
-
-    public static String getString( Map context, String key )
-    {
-        return (String) getObject( context, key );
-    }
-
-    public static String getString( Map context, String key, String defaultValue )
-    {
-        return (String) getObject( context, key, defaultValue );
-    }
-
-    public static boolean getBoolean( Map context, String key )
-    {
-        return ( (Boolean) getObject( context, key ) ).booleanValue();
-    }
-    
-    public static boolean getBoolean( Map context, String key, boolean defaultValue )
-    {
-        return ( (Boolean) getObject( context, key, Boolean.valueOf( defaultValue ) ) ).booleanValue();
-    }    
-
-    public static int getInteger( Map context, String key )
-    {
-        Object obj = getObject( context, key, null );
-        
-        if ( obj == null )
-        {
-            return 0;
-        }
-        else
-        {
-            return ( (Integer) obj ).intValue();
-        }
-    }
-
-    protected static Object getObject( Map context, String key )
-    {
-        if ( !context.containsKey( key ) )
-        {
-            throw new RuntimeException( "Missing key '" + key + "'." );
-        }
-
-        Object value = context.get( key );
-
-        if ( value == null )
-        {
-            throw new RuntimeException( "Missing value for key '" + key + "'." );
-        }
-
-        return value;
-    }
-
-    protected static Object getObject( Map context, String key, Object defaultValue )
-    {
-        Object value = context.get( key );
-
-        if ( value == null )
-        {
-            return defaultValue;
-        }
-
-        return value;
-    }
-
-    public static String throwableToString( Throwable error )
-    {
-        if ( error == null )
-        {
-            return "";
-        }
-
-        StringWriter writer = new StringWriter();
-
-        PrintWriter printer = new PrintWriter( writer );
-
-        error.printStackTrace( printer );
-
-        printer.flush();
-
-        return writer.getBuffer().toString();
-    }
-
-    public static String throwableMessagesToString( Throwable error )
-    {
-        if ( error == null )
-        {
-            return "";
-        }
-
-        StringBuffer buffer = new StringBuffer();
-
-        buffer.append( error.getMessage() );
-
-        error = error.getCause();
-
-        while ( error != null )
-        {
-            buffer.append( EOL );
-
-            buffer.append( error.getMessage() );
-
-            error = error.getCause();
-        }
-
-        return buffer.toString();
-    }
-}
\ No newline at end of file
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/shell/BuildAgentShellCommandHelper.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/shell/BuildAgentShellCommandHelper.java
deleted file mode 100644
index e123470..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/shell/BuildAgentShellCommandHelper.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package org.apache.continuum.buildagent.utils.shell;
-
-/*
- * 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.io.File;
-import java.util.Map;
-
-import org.apache.maven.shared.release.ReleaseResult;
-
-public interface BuildAgentShellCommandHelper
-{
-    String ROLE = BuildAgentShellCommandHelper.class.getName();
-
-    ExecutionResult executeShellCommand( File workingDirectory, String executable, String arguments, File output,
-                                         long idCommand, Map<String, String> environments )
-        throws Exception;
-
-    ExecutionResult executeShellCommand( File workingDirectory, String executable, String[] arguments, File output,
-                                         long idCommand, Map<String, String> environments )
-        throws Exception;
-
-    boolean isRunning( long idCommand );
-
-    void killProcess( long idCommand );
-
-    void executeGoals( File workingDirectory, String goals, boolean interactive, String arguments,
-                       ReleaseResult relResult, Map<String, String> environments )
-        throws Exception;
-
-    void executeGoals( File workingDirectory, String goals, boolean interactive, String[] arguments,
-                       ReleaseResult relResult, Map<String, String> environments )
-        throws Exception;
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/shell/DefaultBuildAgentShellCommandHelper.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/shell/DefaultBuildAgentShellCommandHelper.java
deleted file mode 100644
index 1fdddc2..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/shell/DefaultBuildAgentShellCommandHelper.java
+++ /dev/null
@@ -1,223 +0,0 @@
-package org.apache.continuum.buildagent.utils.shell;
-
-/*
- * 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.io.File;
-import java.io.FileWriter;
-import java.io.Writer;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.Map;
-
-import org.apache.maven.shared.release.ReleaseResult;
-import org.apache.maven.shared.release.exec.MavenExecutorException;
-import org.apache.maven.shared.release.exec.TeeConsumer;
-import org.codehaus.plexus.util.StringUtils;
-import org.codehaus.plexus.util.cli.CommandLineException;
-import org.codehaus.plexus.util.cli.CommandLineUtils;
-import org.codehaus.plexus.util.cli.Commandline;
-import org.codehaus.plexus.util.cli.StreamConsumer;
-import org.codehaus.plexus.util.cli.WriterStreamConsumer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Service;
-
-@Service("buildAgentShellCommandHelper")
-public class DefaultBuildAgentShellCommandHelper
-    implements BuildAgentShellCommandHelper
-{
-    private Logger log = LoggerFactory.getLogger( this.getClass() );
-    
-    // ----------------------------------------------------------------------
-    // ShellCommandHelper Implementation
-    // ----------------------------------------------------------------------
-
-    public ExecutionResult executeShellCommand( File workingDirectory, String executable, String arguments, File output,
-                                                long idCommand, Map<String, String> environments )
-        throws Exception
-    {
-        Commandline cl = new Commandline();
-
-        Commandline.Argument argument = cl.createArgument();
-
-        argument.setLine( arguments );
-
-        return executeShellCommand( workingDirectory, executable, argument.getParts(), output, idCommand,
-                                    environments );
-    }
-
-    /**
-     * Make the command line
-     * 
-     * @param workingDirectory
-     * @param executable
-     * @param arguments
-     * @param idCommand
-     * @param environments
-     * @return
-     * @throws Exception
-     */
-    protected Commandline createCommandline( File workingDirectory, String executable, String[] arguments,
-                                             long idCommand, Map<String, String> environments )
-        throws Exception
-    {
-        Commandline cl = new Commandline();
-
-        cl.setPid( idCommand );
-
-        cl.addEnvironment( "MAVEN_TERMINATE_CMD", "on" );
-
-        if ( environments != null && !environments.isEmpty() )
-        {
-            for ( Iterator<String> iterator = environments.keySet().iterator(); iterator.hasNext(); )
-            {
-                String key = iterator.next();
-                String value = environments.get( key );
-                cl.addEnvironment( key, value );
-            }
-        }
-
-        cl.addSystemEnvironment();
-
-        cl.setExecutable( executable );
-
-        cl.setWorkingDirectory( workingDirectory.getAbsolutePath() );
-
-        if ( arguments != null )
-        {
-            for ( int i = 0; i < arguments.length; i++ )
-            {
-                String argument = arguments[i];
-
-                cl.createArgument().setValue( argument );
-            }
-        }
-
-        return cl;
-    }
-
-    public ExecutionResult executeShellCommand( File workingDirectory, String executable, String[] arguments,
-                                                File output, long idCommand, Map<String, String> environments )
-        throws Exception
-    {
-
-        Commandline cl = createCommandline( workingDirectory, executable, arguments, idCommand, environments );
-
-        log.info( "Executing: " + cl );
-        log.info( "Working directory: " + cl.getWorkingDirectory().getAbsolutePath() );
-        log.debug( "EnvironmentVariables " + Arrays.asList( cl.getEnvironmentVariables() ) );
-
-        // ----------------------------------------------------------------------
-        //
-        // ----------------------------------------------------------------------
-
-        //CommandLineUtils.StringStreamConsumer consumer = new CommandLineUtils.StringStreamConsumer();
-
-        Writer writer = new FileWriter( output );
-
-        StreamConsumer consumer = new WriterStreamConsumer( writer );
-
-        int exitCode = CommandLineUtils.executeCommandLine( cl, consumer, consumer );
-
-        writer.flush();
-
-        writer.close();
-
-        // ----------------------------------------------------------------------
-        //
-        // ----------------------------------------------------------------------
-
-        return new ExecutionResult( exitCode );
-    }
-
-    public boolean isRunning( long idCommand )
-    {
-        return CommandLineUtils.isAlive( idCommand );
-    }
-
-    public void killProcess( long idCommand )
-    {
-        CommandLineUtils.killProcess( idCommand );
-    }
-
-    public void executeGoals( File workingDirectory, String goals, boolean interactive, String arguments,
-                              ReleaseResult relResult, Map<String, String> environments )
-        throws Exception
-    {
-        Commandline cl = new Commandline();
-
-        Commandline.Argument argument = cl.createArgument();
-
-        argument.setLine( arguments );
-
-        executeGoals( workingDirectory, goals, interactive, argument.getParts(), relResult, environments );
-    }
-
-    public void executeGoals( File workingDirectory, String goals, boolean interactive, String[] arguments,
-                              ReleaseResult relResult, Map<String, String> environments )
-        throws Exception
-    {
-        Commandline cl = createCommandline( workingDirectory, "mvn", arguments, -1, environments );
-
-        if ( goals != null )
-        {
-            // accept both space and comma, so the old way still work
-            String[] tokens = StringUtils.split( goals, ", " );
-
-            for ( int i = 0; i < tokens.length; ++i )
-            {
-                cl.createArgument().setValue( tokens[i] );
-            }
-        }
-
-        cl.createArgument().setValue( "--no-plugin-updates" );
-
-        if ( !interactive )
-        {
-            cl.createArgument().setValue( "--batch-mode" );
-        }
-
-        StreamConsumer stdOut = new TeeConsumer( System.out );
-
-        StreamConsumer stdErr = new TeeConsumer( System.err );
-
-        try
-        {
-            relResult.appendInfo( "Executing: " + cl.toString() );
-            log.info( "Executing: " + cl.toString() );
-
-            int result = CommandLineUtils.executeCommandLine( cl, stdOut, stdErr );
-
-            if ( result != 0 )
-            {
-                throw new MavenExecutorException( "Maven execution failed, exit code: \'" + result + "\'", result,
-                                                  stdOut.toString(), stdErr.toString() );
-            }
-        }
-        catch ( CommandLineException e )
-        {
-            throw new MavenExecutorException( "Can't run goal " + goals, stdOut.toString(), stdErr.toString(), e );
-        }
-        finally
-        {
-            relResult.appendOutput( stdOut.toString() );
-        }
-    }
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/shell/ExecutionResult.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/shell/ExecutionResult.java
deleted file mode 100644
index 305aa61..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/java/org/apache/continuum/buildagent/utils/shell/ExecutionResult.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.apache.continuum.buildagent.utils.shell;
-
-/*
- * 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.
- */
-
-public class ExecutionResult
-{
-    private int exitCode;
-
-    public ExecutionResult( int exitCode )
-    {
-        this.exitCode = exitCode;
-    }
-
-    public int getExitCode()
-    {
-        return exitCode;
-    }
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/resources/META-INF/plexus/components.xml b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/resources/META-INF/plexus/components.xml
deleted file mode 100644
index 2cfe73c..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/resources/META-INF/plexus/components.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<component-set>
-  <components>
-    <component>
-      <role>org.codehaus.plexus.taskqueue.TaskQueue</role>
-      <role-hint>build-agent</role-hint>
-      <implementation>org.codehaus.plexus.taskqueue.DefaultTaskQueue</implementation>
-      <lifecycle-handler>plexus-configurable</lifecycle-handler>
-    </component>
-
-    <component>
-      <role>org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor</role>
-      <role-hint>build-agent</role-hint>
-      <implementation>org.codehaus.plexus.taskqueue.execution.ThreadedTaskQueueExecutor</implementation>
-      <instantiation-strategy>singleton</instantiation-strategy>
-      <requirements>
-        <requirement>
-          <role>org.codehaus.plexus.taskqueue.execution.TaskExecutor</role>
-          <role-hint>build-agent</role-hint>
-        </requirement>
-        <requirement>
-          <role>org.codehaus.plexus.taskqueue.TaskQueue</role>
-          <role-hint>build-agent</role-hint>
-        </requirement>
-      </requirements>
-      <configuration>
-        <name>build-agent</name>
-      </configuration>
-    </component>
-  </components>
-</component-set>
\ No newline at end of file
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/resources/META-INF/spring-context.xml b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/resources/META-INF/spring-context.xml
deleted file mode 100644
index b9ac859..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-core/src/main/resources/META-INF/spring-context.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xmlns:aop="http://www.springframework.org/schema/aop"
-	xmlns:util="http://www.springframework.org/schema/util"
-	xmlns:context="http://www.springframework.org/schema/context"
-	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
-		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
-		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd
-		http://www.springframework.org/schema/context 
-        http://www.springframework.org/schema/context/spring-context-2.5.xsd">
-
-  <context:annotation-config />
-  <context:component-scan base-package="org.apache.continuum.buildagent"/>
-
-  <bean name="continuumAgentBuildExecutor#maven2"
-         class="org.apache.continuum.buildagent.build.execution.maven.m2.MavenTwoBuildExecutor" autowire="byName">
-    <property name="defaultExecutable" value="mvn"/>
-    <property name="builderHelper" ref="buildAgentMavenBuilderHelper"/>
-    <property name="projectHelper" ref="mavenProjectHelper"/>
-  </bean>
-  <bean name="continuumAgentBuildExecutor#maven-1"
-         class="org.apache.continuum.buildagent.build.execution.maven.m1.MavenOneBuildExecutor" autowire="byName">
-    <property name="defaultExecutable" value="maven"/>
-  </bean>
-  <bean name="continuumAgentBuildExecutor#ant"
-         class="org.apache.continuum.buildagent.build.execution.ant.AntBuildExecutor" autowire="byName">
-    <property name="defaultExecutable" value="ant"/>
-  </bean>
-  <bean name="continuumAgentBuildExecutor#shell"
-         class="org.apache.continuum.buildagent.build.execution.shell.ShellBuildExecutor" autowire="byName">
-  </bean>
-
-  <bean id="buildAgentConfigurationService" class="org.apache.continuum.buildagent.configuration.DefaultBuildAgentConfigurationService"
-        init-method="initialize"/>
-  
-  <bean id="buildAgentConfiguration" class="org.apache.continuum.buildagent.configuration.DefaultBuildAgentConfiguration"
-     init-method="initialize">
-    <property name="configurationFile" value="file:${CONTINUUM_BUILDAGENT_HOME}/conf/continuum-buildagent.xml" />
-  </bean>
-
-  <bean id="projectHelper" class="org.apache.maven.project.DefaultMavenProjectHelper"/>
-
-  <bean id="projectBuilder" class="org.apache.maven.project.DefaultMavenProjectBuilder"/>
-
-  <bean id="mavenSettingsBuilder" class="org.apache.maven.settings.DefaultMavenSettingsBuilder"/>
-
-  <bean id="artifactRepositoryFactory" class="org.apache.maven.artifact.repository.DefaultArtifactRepositoryFactory"/>
-
-  <bean id="defaultRepositoryLayout" class="org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout"/>
-
-  <bean id="actionManager" class="org.codehaus.plexus.action.DefaultActionManager"/>
-</beans>
-	
\ No newline at end of file
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-jetty/pom.xml b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-jetty/pom.xml
deleted file mode 100644
index 3743d8c..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-jetty/pom.xml
+++ /dev/null
@@ -1,284 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<!--
-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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <parent>
-    <artifactId>continuum-buildagent</artifactId>
-    <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
-  </parent>
-  <artifactId>continuum-buildagent-jetty</artifactId>
-  <packaging>pom</packaging>
-  <name>Apache Continuum Build Agent</name>
-  <dependencies>
-    <dependency>
-      <groupId>org.mortbay.jetty</groupId>
-      <artifactId>jetty</artifactId>
-      <version>${jetty.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.mortbay.jetty</groupId>
-      <artifactId>start</artifactId>
-      <version>${jetty.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-buildagent-webapp</artifactId>
-      <type>war</type>
-    </dependency>
-    <!-- Runtime dependencies that need to be included in the generated binaries -->
-    <dependency>
-      <groupId>org.mortbay.jetty</groupId>
-      <artifactId>jetty-naming</artifactId>
-      <version>${jetty.version}</version>
-      <scope>runtime</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.mortbay.jetty</groupId>
-      <artifactId>servlet-api-2.5</artifactId>
-      <version>${jetty.version}</version>
-      <scope>runtime</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.mortbay.jetty</groupId>
-      <artifactId>jsp-api-2.0</artifactId>
-      <version>${jetty.version}</version>
-      <scope>runtime</scope>
-    </dependency>    
-    <dependency>
-      <groupId>org.mortbay.jetty</groupId>
-      <artifactId>jetty-plus</artifactId>
-      <version>${jetty.version}</version>
-      <scope>runtime</scope>
-    </dependency>
-    <dependency>
-      <groupId>ant</groupId>
-      <artifactId>ant</artifactId>
-      <version>1.6.5</version>
-      <scope>runtime</scope>
-    </dependency>
-    <dependency>
-      <groupId>commons-el</groupId>
-      <artifactId>commons-el</artifactId>
-      <version>1.0</version>
-      <scope>runtime</scope>
-      <exclusions>
-        <exclusion>
-          <groupId>commons-logging</groupId>
-          <artifactId>commons-logging</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>tomcat</groupId>
-      <artifactId>jasper-compiler</artifactId>
-      <version>5.5.15</version>
-      <scope>runtime</scope>
-      <exclusions>
-        <exclusion>
-          <groupId>javax.servlet</groupId>
-          <artifactId>jsp-api</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>    
-    <dependency>
-      <groupId>tomcat</groupId>
-      <artifactId>jasper-runtime</artifactId>
-      <version>5.5.15</version>
-      <scope>runtime</scope>
-      <exclusions>
-        <exclusion>
-          <groupId>javax.servlet</groupId>
-          <artifactId>servlet-api</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>jcl104-over-slf4j</artifactId>
-      <version>1.5.0</version>
-      <scope>runtime</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-simple</artifactId>
-      <version>1.5.0</version>
-      <scope>runtime</scope>
-    </dependency>
-    <dependency>
-      <groupId>tomcat</groupId>
-      <artifactId>jasper-compiler-jdt</artifactId>
-      <version>5.5.15</version>
-      <scope>runtime</scope>
-      <exclusions>
-        <exclusion>
-          <groupId>org.eclipse.jdt</groupId>
-          <artifactId>core</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-  </dependencies>
-  <build>
-    <plugins>
-       <plugin>
-        <groupId>org.codehaus.mojo</groupId>
-        <artifactId>appassembler-maven-plugin</artifactId>
-        <version>1.0-beta-2</version>
-        <configuration>
-          <daemons>
-            <daemon>
-              <id>continuum-buildagent</id>
-              <mainClass>org.mortbay.start.Main</mainClass>
-              <commandLineArguments>
-                <commandLineArgument>conf/jetty.xml</commandLineArgument>
-                <commandLineArgument>conf/jetty-logging.xml</commandLineArgument> 
-              </commandLineArguments>
-              <platforms>
-                <platform>jsw</platform>
-              </platforms>              
-              <generatorConfigurations>
-                <generatorConfiguration>
-                  <generator>jsw</generator>
-                  <configuration>
-                    <property>
-                      <name>wrapper.console.loglevel</name>
-                      <value>INFO</value>
-                    </property>
-                    <property>
-                      <name>wrapper.java.additional.1.stripquotes</name>
-                      <value>TRUE</value>
-                    </property>
-                    <property>
-                      <name>set.default.REPO_DIR</name>
-                      <value>lib</value>
-                    </property>
-                    <property>
-                      <name>wrapper.logfile</name>
-                      <value>%CONTINUUM_BUILDAGENT_BASE%/logs/wrapper.log</value>
-                    </property>
-                    <property>
-                      <name>wrapper.app.parameter.2</name>
-                      <value>%CONTINUUM_BUILDAGENT_BASE%/conf/jetty.xml</value>
-                    </property>
-                    <property>
-                      <name>wrapper.app.parameter.3</name>
-                      <value>%CONTINUUM_BUILDAGENT_BASE%/conf/jetty-logging.xml</value>
-                    </property>
-                    <property>
-                      <name>app.base.envvar</name>
-                      <value>CONTINUUM_BUILDAGENT_BASE</value>
-                    </property>
-                    <property>
-                      <name>wrapper.on_exit.default</name>
-                      <value>RESTART</value>
-                    </property>
-                    <property>
-                      <name>wrapper.on_exit.0</name>
-                      <value>SHUTDOWN</value>
-                    </property>
-                    <property>
-                      <name>wrapper.restart.delay</name>
-                      <value>30</value>
-                    </property>
-                  </configuration>
-                  <includes>
-                    <include>linux-x86-32</include>
-                    <include>linux-x86-64</include>
-                    <include>macosx-x86-universal-32</include>
-                    <include>solaris-x86-32</include>
-                    <include>solaris-sparc-32</include>
-                    <include>solaris-sparc-64</include>
-                    <include>windows-x86-32</include>
-                  </includes>
-                </generatorConfiguration>
-              </generatorConfigurations>
-              <jvmSettings>
-                <systemProperties>
-                  <systemProperty>appserver.home=.</systemProperty>
-                  <systemProperty>CONTINUUM_BUILDAGENT_HOME=%CONTINUUM_BUILDAGENT_BASE%</systemProperty>
-                  <systemProperty>jetty.logs=%CONTINUUM_BUILDAGENT_BASE%/logs</systemProperty>
-                  <systemProperty>java.io.tmpdir=%CONTINUUM_BUILDAGENT_BASE%/tmp</systemProperty>
-                </systemProperties>
-              </jvmSettings> 
-            </daemon>
-          </daemons>          
-          <repoPath>lib</repoPath>
-          <repositoryLayout>flat</repositoryLayout>
-          <assembleDirectory>target/generated-resources/appassembler/jsw/continuum-buildagent</assembleDirectory>
-        </configuration>
-        <executions>
-          <execution>
-            <goals>
-              <goal>generate-daemons</goal>
-              <goal>create-repository</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-assembly-plugin</artifactId>
-        <version>2.1</version>
-        <executions>
-          <execution>
-            <phase>package</phase>
-            <goals>
-              <goal>single</goal>
-            </goals>
-          </execution>
-        </executions>
-        <configuration>
-          <descriptor>src/main/assembly/bin.xml</descriptor>
-          <finalName>apache-continuum-buildagent-${version}</finalName>
-        </configuration>
-      </plugin>
-      <plugin>
-        <artifactId>maven-antrun-plugin</artifactId>
-        <version>1.1</version>
-        <executions>
-          <execution>
-            <id>config</id>
-            <phase>process-resources</phase>
-            <configuration>
-              <tasks>
-                <copy todir="target/generated-resources/appassembler/jsw/continuum-buildagent/conf">
-                  <fileset dir="src/main/conf" />                  
-                </copy>
-                <mkdir dir="target/generated-resources/appassembler/jsw/continuum-buildagent/logs" />      
-              </tasks>
-            </configuration>
-            <goals>
-              <goal>run</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
-  <pluginRepositories>
-    <pluginRepository>
-      <id>codehaus.org</id>
-      <url>http://snapshots.repository.codehaus.org/</url>
-    </pluginRepository>
-  </pluginRepositories>
-  <properties>
-    <jetty.version>6.1.11</jetty.version>
-  </properties>
-</project>
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-jetty/src/main/assembly/bin.xml b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-jetty/src/main/assembly/bin.xml
deleted file mode 100644
index 9247423..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-jetty/src/main/assembly/bin.xml
+++ /dev/null
@@ -1,116 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<assembly>
-  <id>bin</id>
-  <formats>
-    <format>tar.gz</format>
-    <format>zip</format>
-  </formats>
-  <fileSets>
-    <fileSet>      
-      <directory>target/generated-resources/appassembler/jsw/continuum-buildagent/apps</directory>
-      <outputDirectory>apps</outputDirectory>
-    </fileSet>
-    <fileSet>
-      <directory>target/generated-resources/appassembler/jsw/continuum-buildagent/conf</directory>
-      <outputDirectory>conf</outputDirectory>
-    </fileSet>
-    <fileSet>
-      <directory>target/generated-resources/appassembler/jsw/continuum-buildagent/lib</directory>
-      <outputDirectory>lib</outputDirectory>
-      <excludes>
-        <exclude>continuum-*</exclude>
-        <exclude>maven-metadata-appassembler.xml</exclude>
-      </excludes>
-      <fileMode>0755</fileMode>
-    </fileSet> 
-    <fileSet>
-      <directory>target/generated-resources/appassembler/jsw/continuum-buildagent/logs</directory>
-      <outputDirectory>logs</outputDirectory>
-    </fileSet>
-    <fileSet>
-      <directory>target/generated-resources/appassembler/jsw/continuum-buildagent/bin</directory>
-      <outputDirectory>bin</outputDirectory>
-      <includes>   
-         <include>continuum-buildagent</include>           
-      </includes>
-      <fileMode>0755</fileMode>
-      <lineEnding>unix</lineEnding>
-    </fileSet>
-    <fileSet>
-      <directory>target/generated-resources/appassembler/jsw/continuum-buildagent/bin</directory>
-      <outputDirectory>bin</outputDirectory>
-      <includes>   
-         <include>wrapper-linux-x86-32</include>
-         <include>wrapper-linux-x86-64</include>
-         <include>wrapper-macosx-universal-32</include>
-         <include>wrapper-solaris-x86-32</include>
-         <include>wrapper-solaris-sparc-32</include>
-         <include>wrapper-solaris-sparc-64</include>
-      </includes>
-      <fileMode>0755</fileMode>
-    </fileSet>
-    <fileSet>
-      <directory>target/generated-resources/appassembler/jsw/continuum-buildagent/bin</directory>
-      <outputDirectory>bin</outputDirectory>
-      <includes>        
-        <include>continuum-buildagent.bat</include>
-      </includes>
-      <fileMode>0755</fileMode>
-      <lineEnding>dos</lineEnding>
-    </fileSet>
-    <fileSet>
-      <directory>target/generated-resources/appassembler/jsw/continuum-buildagent/bin</directory>
-      <outputDirectory>bin</outputDirectory>
-      <includes>   
-        <include>wrapper-windows-x86-32.exe</include>
-      </includes>
-      <fileMode>0755</fileMode>
-    </fileSet>
-    <fileSet>
-      <directory>target/maven-shared-archive-resources/META-INF/</directory>
-      <outputDirectory>/</outputDirectory>
-      <includes>
-        <include>NOTICE</include>
-      </includes>
-    </fileSet>
-    <fileSet>
-      <directory>src/main/resources/</directory>
-      <outputDirectory>/</outputDirectory>
-      <includes>
-        <include>LICENSE</include>
-      </includes>
-    </fileSet>
-    <fileSet>
-      <directory>src/main/tmp/</directory>
-      <outputDirectory>/tmp</outputDirectory>
-    </fileSet>
-  </fileSets>
-  <dependencySets>
-    <dependencySet>
-      <unpack>true</unpack>
-      <outputDirectory>apps/continuum-buildagent</outputDirectory>
-      <includes>
-        <include>org.apache.continuum:continuum-buildagent-webapp</include>
-      </includes>
-    </dependencySet>
-  </dependencySets>
-</assembly>
-
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/continuum-buildagent.xml b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/continuum-buildagent.xml
deleted file mode 100644
index 743433a..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/continuum-buildagent.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<!--
-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.
--->
-
-<continuum-buildagent-configuration />
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/jetty-logging.xml b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/jetty-logging.xml
deleted file mode 100644
index 379bd13..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/jetty-logging.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
-<!--
-  ~ 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.
-  -->
-
-<!-- =============================================================== -->
-<!-- Configure stderr and stdout to a Jetty rollover log file        -->
-<!-- this configuration file should be used in combination with      -->
-<!-- other configuration files.  e.g.                                -->
-<!--    java -jar start.jar etc/jetty-logging.xml etc/jetty.xml      -->
-<!-- =============================================================== -->
-<Configure id="Server" class="org.mortbay.jetty.Server">
-
-    <New id="ServerLog" class="java.io.PrintStream">
-      <Arg>
-        <New class="org.mortbay.util.RolloverFileOutputStream">
-          <Arg><SystemProperty name="jetty.logs" default="./logs"/>/yyyy_mm_dd.stderrout.log</Arg>
-          <Arg type="boolean">false</Arg>
-          <Arg type="int">90</Arg>
-          <Arg><Call class="java.util.TimeZone" name="getTimeZone"><Arg>GMT</Arg></Call></Arg>
-          <Get id="ServerLogName" name="datedFilename"/>
-        </New>
-      </Arg>
-    </New>
-
-    <Call class="org.mortbay.log.Log" name="info"><Arg>Redirecting stderr/stdout to <Ref id="ServerLogName"/></Arg></Call>
-    <Call class="java.lang.System" name="setErr"><Arg><Ref id="ServerLog"/></Arg></Call>
-    <Call class="java.lang.System" name="setOut"><Arg><Ref id="ServerLog"/></Arg></Call>
-
-</Configure>
-
-
-
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/jetty.xml b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/jetty.xml
deleted file mode 100644
index 57a6163..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/jetty.xml
+++ /dev/null
@@ -1,275 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
-<!--
-  ~ 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.
-  -->
-
-<!-- =============================================================== -->
-<!-- Configure the Jetty Server                                      -->
-<!--                                                                 -->
-<!-- Documentation of this file format can be found at:              -->
-<!-- http://docs.codehaus.org/display/JETTY/jetty.xml                -->
-<!--                                                                 -->
-<!-- =============================================================== -->
-
-
-<Configure id="Server" class="org.mortbay.jetty.Server">
-
-    <!-- =========================================================== -->
-    <!-- Server Thread Pool                                          -->
-    <!-- =========================================================== -->
-    <Set name="ThreadPool">
-      <!-- Default bounded blocking threadpool 
-      -->
-      <New class="org.mortbay.thread.BoundedThreadPool">
-        <Set name="minThreads">10</Set>
-        <Set name="maxThreads">250</Set>
-        <Set name="lowThreads">25</Set>
-      </New>
-
-      <!-- Optional Java 5 bounded threadpool with job queue 
-      <New class="org.mortbay.thread.concurrent.ThreadPool">
-        <Set name="corePoolSize">250</Set>
-        <Set name="maximumPoolSize">250</Set>
-      </New>
-      -->
-    </Set>
-
-
-
-    <!-- =========================================================== -->
-    <!-- Set connectors                                              -->
-    <!-- =========================================================== -->
-    <!-- One of each type!                                           -->
-    <!-- =========================================================== -->
-
-    <!-- Use this connector for many frequently idle connections
-         and for threadless continuations.
-    -->    
-    <!-- START SNIPPET: jetty_port -->    
-    <Call name="addConnector">
-      <Arg>
-          <New class="org.mortbay.jetty.nio.SelectChannelConnector">
-            <Set name="host"><SystemProperty name="jetty.host" /></Set>
-            <Set name="port"><SystemProperty name="jetty.port" default="8181"/></Set>
-            <Set name="maxIdleTime">30000</Set>
-            <Set name="Acceptors">2</Set>
-            <Set name="statsOn">false</Set>
-            <Set name="confidentialPort">8443</Set>
-	    <Set name="lowResourcesConnections">5000</Set>
-	    <Set name="lowResourcesMaxIdleTime">5000</Set>
-          </New>
-      </Arg>
-    </Call>
-    <!-- END SNIPPET: jetty_port -->
-
-    <!-- Use this connector if NIO is not available. 
-    <Call name="addConnector">
-      <Arg>
-          <New class="org.mortbay.jetty.bio.SocketConnector">
-            <Set name="port">8081</Set>
-            <Set name="maxIdleTime">50000</Set>
-            <Set name="lowResourceMaxIdleTime">1500</Set>
-          </New>
-      </Arg>
-    </Call>
-    -->
-
-    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
-    <!-- To add a HTTPS SSL listener                                     -->
-    <!-- see jetty-ssl.xml to add an ssl connector. use                  -->
-    <!-- java -jar start.jar etc/jetty.xml etc/jetty-ssl.xml             -->
-    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
-    
-    <!-- =========================================================== -->
-    <!-- Set up global session ID manager                            -->
-    <!-- =========================================================== -->
-    <!--
-    <Set name="sessionIdManager">
-      <New class="org.mortbay.jetty.servlet.HashSessionIdManager">
-        <Set name="workerName">node1</Set>
-      </New>
-    </Set>
-    -->
-
-    <!-- =========================================================== -->
-    <!-- Set handler Collection Structure                            --> 
-    <!-- =========================================================== -->
-    <Set name="handler">
-      <New id="Handlers" class="org.mortbay.jetty.handler.HandlerCollection">
-        <Set name="handlers">
-         <Array type="org.mortbay.jetty.Handler">
-           <Item>
-             <New id="Contexts" class="org.mortbay.jetty.handler.ContextHandlerCollection"/>
-           </Item>
-           <Item>
-             <New id="DefaultHandler" class="org.mortbay.jetty.handler.DefaultHandler"/>
-           </Item>
-           <Item>
-             <New id="RequestLog" class="org.mortbay.jetty.handler.RequestLogHandler"/>
-           </Item>
-         </Array>
-        </Set>
-      </New>
-    </Set>
-    
-    <!-- =========================================================== -->
-    <!-- Configure the context deployer                              -->
-    <!-- A context deployer will deploy contexts described in        -->
-    <!-- configuration files discovered in a directory.              -->
-    <!-- The configuration directory can be scanned for hot          -->
-    <!-- deployments at the configured scanInterval.                 -->
-    <!--                                                             -->
-    <!-- This deployer is configured to deploy contexts configured   -->
-    <!-- in the $JETTY_HOME/contexts directory                       -->
-    <!--                                                             -->
-    <!-- =========================================================== -->
-    <Call name="addLifeCycle">
-      <Arg>
-        <New class="org.mortbay.jetty.deployer.ContextDeployer">
-          <Set name="contexts"><Ref id="Contexts"/></Set>
-          <Set name="configurationDir"><SystemProperty name="jetty.home" default="."/>/contexts</Set>
-          <Set name="scanInterval">1</Set>
-        </New>
-      </Arg>
-    </Call>
-
-    <!-- =========================================================== -->
-    <!-- Configure the webapp deployer.                              -->
-    <!-- A webapp  deployer will deploy standard webapps discovered  -->
-    <!-- in a directory at startup, without the need for additional  -->
-    <!-- configuration files.    It does not support hot deploy or   -->
-    <!-- non standard contexts (see ContextDeployer above).          -->
-    <!--                                                             -->
-    <!-- This deployer is configured to deploy webapps from the      -->
-    <!-- $JETTY_HOME/webapps directory                               -->
-    <!--                                                             -->
-    <!-- Normally only one type of deployer need be used.            -->
-    <!--                                                             -->
-    <!-- =========================================================== -->
-    <Call name="addLifeCycle">
-      <Arg>
-        <New class="org.mortbay.jetty.deployer.WebAppDeployer">
-          <Set name="contexts"><Ref id="Contexts"/></Set>
-          <Set name="webAppDir"><SystemProperty name="jetty.home" default="."/>/apps</Set>
-	  <Set name="parentLoaderPriority">false</Set>
-	  <Set name="extract">true</Set>
-	  <Set name="allowDuplicates">false</Set>
-          <Set name="defaultsDescriptor"><SystemProperty name="jetty.home" default="."/>/conf/webdefault.xml</Set>
-        </New>
-      </Arg>
-    </Call>
-
-    <!-- =========================================================== -->
-    <!-- Configure Request Log                                       -->
-    <!-- Request logs  may be configured for the entire server here, -->
-    <!-- or they can be configured for a specific web app in a       -->
-    <!-- contexts configuration (see $(jetty.home)/contexts/test.xml -->
-    <!-- for an example).                                            -->
-    <!-- =========================================================== -->
-    <Ref id="RequestLog">
-      <Set name="requestLog">
-        <New id="RequestLogImpl" class="org.mortbay.jetty.NCSARequestLog">
-          <Set name="filename"><SystemProperty name="jetty.logs" default="./logs"/>/yyyy_mm_dd.request.log</Set>
-          <Set name="filenameDateFormat">yyyy_MM_dd</Set>
-          <Set name="retainDays">90</Set>
-          <Set name="append">true</Set>
-          <Set name="extended">true</Set>
-          <Set name="logCookies">false</Set>
-          <Set name="LogTimeZone">GMT</Set>
-        </New>
-      </Set>
-    </Ref>
-
-    <!-- =========================================================== -->
-    <!-- extra options                                               -->
-    <!-- =========================================================== -->
-    <Set name="stopAtShutdown">true</Set>
-    <Set name="sendServerVersion">true</Set>
-    <Set name="sendDateHeader">true</Set>
-    <Set name="gracefulShutdown">1000</Set>
-
-
- 
- <!-- =========================================================== -->
-  <!-- JNDI java:comp/env                                          -->
-  <!-- To use JNDI with Jetty, you will need to tell your          -->
-  <!-- WebAppContext to process the naming related items in        -->
-  <!-- web.xml. For an example of how to do that, see the test     -->
-  <!-- webapp below. More information can be found at              -->
-  <!-- http://docs.codehaus.org/display/JETTY/Jetty+Wiki           -->
-  <!-- =========================================================== -->
-
-
-  <!-- Configuring <resource-ref> and <resource-env-ref>s          -->
-  <!--                                                             -->
-  <!-- The following are examples of setting up a resource that   -->
-  <!-- can be referenced in a web.xml file as a <resource-ref> or  -->
-  <!-- a <resource-env-ref>. The first argument is the name of the -->
-  <!-- resource relative to java:comp/env and must be the SAME as  -->
-  <!-- the <res-ref-name> or <resource-env-ref-name> in web.xml.   -->
-  <!-- The second argument is the construction of the resource     -->
-  <!-- object. Any object at all can be configured.                -->
-
-
-  <!-- These examples set up a javax.sql.DataSource around an      -->
-  <!-- XADataSource that is provided by the Derby relational db.   -->
-  <!-- The DataSource wrapper that is registered in JNDI is        -->
-  <!--  provided by Atomikos, and works with the Atomikos          -->
-  <!-- transaction manager configured further below. To use these  -->
-  <!-- examples, download Atomikos http://www.atomikos.com and     -->
-  <!-- Derby http://db.apache.org/derby                            -->
-
-
-  <!-- Configuring Transactions                                    -->
-  <!--                                                             -->
-  <!-- The following is a example of a setting up a JTA            -->
-  <!-- transaction manager that can be referenced by looking up    -->
-  <!-- java:comp/UserTransaction. Note that this is just an        -->
-  <!-- example and if you uncomment it, you will need to download  -->
-  <!-- the atomikos jar (see http://www.atomikos.com/download.html)-->
-  <!-- You can configure any transaction manager that implements   -->
-  <!-- javax.transaction.UserTransaction.                          -->
-
-
-
-  <!-- =========================================================== -->
-  <!-- Configurations for WebAppContexts                           -->
-  <!-- Sequence of configurations to be applied to a webapp.       -->
-  <!-- =========================================================== -->
-  <Array id="plusConfig" type="java.lang.String">
-    <Item>org.mortbay.jetty.webapp.WebInfConfiguration</Item>
-    <Item>org.mortbay.jetty.plus.webapp.EnvConfiguration</Item>
-    <Item>org.mortbay.jetty.plus.webapp.Configuration</Item>
-    <Item>org.mortbay.jetty.webapp.JettyWebXmlConfiguration</Item>
-    <Item>org.mortbay.jetty.webapp.TagLibConfiguration</Item>
-  </Array>
-
-  <!-- =========================================================== -->
-  <!-- Deploy all webapps in webapps-plus                          -->
-  <!-- =========================================================== -->
-  <Call class="org.mortbay.jetty.webapp.WebAppContext" name="addWebApplications">
-    <Arg><Ref id="Contexts"/></Arg>
-    <Arg>./apps</Arg>
-    <Arg>org/mortbay/jetty/webapp/webdefault.xml</Arg>
-    <Arg><Ref id="plusConfig"/></Arg>
-    <Arg type="boolean">True</Arg>
-    <Arg type="boolean">False</Arg>
-  </Call>
-
-</Configure>
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/shared.xml b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/shared.xml
deleted file mode 100644
index 22850c1..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/shared.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<!--
-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.
--->
-<configuration />
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/webdefault.xml b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/webdefault.xml
deleted file mode 100644
index 5604d03..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-jetty/src/main/conf/webdefault.xml
+++ /dev/null
@@ -1,420 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<!--
-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.
--->
-
-<!-- ===================================================================== -->
-<!-- This file contains the default descriptor for web applications.       -->
-<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
-<!-- The intent of this descriptor is to include jetty specific or common  -->
-<!-- configuration for all webapps.   If a context has a webdefault.xml    -->
-<!-- descriptor, it is applied before the contexts own web.xml file        -->
-<!--                                                                       -->
-<!-- A context may be assigned a default descriptor by:                    -->
-<!--  + Calling WebApplicationContext.setDefaultsDescriptor                -->
-<!--  + Passed an arg to addWebApplications                                -->
-<!--                                                                       -->
-<!-- This file is used both as the resource within the jetty.jar (which is -->
-<!-- used as the default if no explicit defaults descriptor is set) and it -->
-<!-- is copied to the etc directory of the Jetty distro and explicitly     -->
-<!-- by the jetty.xml file.                                                -->
-<!--                                                                       -->
-<!-- ===================================================================== -->
-<web-app 
-   xmlns="http://java.sun.com/xml/ns/javaee" 
-   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
-   metadata-complete="true"
-   version="2.5"> 
-
-  <description>
-    Default web.xml file.  
-    This file is applied to a Web application before it's own WEB_INF/web.xml file
-  </description>
-
-
-  <!-- ==================================================================== -->
-  <!-- Context params to control Session Cookies                            -->
-  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
-  <!-- UNCOMMENT TO ACTIVATE
-  <context-param>
-    <param-name>org.mortbay.jetty.servlet.SessionDomain</param-name>
-    <param-value>127.0.0.1</param-value>
-  </context-param>
-
-  <context-param>
-    <param-name>org.mortbay.jetty.servlet.SessionPath</param-name>
-    <param-value>/</param-value>
-  </context-param>
-
-  <context-param>
-    <param-name>org.mortbay.jetty.servlet.MaxAge</param-name>
-    <param-value>-1</param-value>
-  </context-param>
-  -->
-
-  <context-param>
-    <param-name>org.mortbay.jetty.webapp.NoTLDJarPattern</param-name>
-    <param-value>start.jar|ant-.*\.jar|dojo-.*\.jar|jetty-.*\.jar|jsp-api-.*\.jar|junit-.*\.jar|servlet-api-.*\.jar|dnsns\.jar|rt\.jar|jsse\.jar|tools\.jar|sunpkcs11\.jar|sunjce_provider\.jar|xerces.*\.jar</param-value>
-  </context-param>
-            
-
-
-  <!-- ==================================================================== -->
-  <!-- The default servlet.                                                 -->
-  <!-- This servlet, normally mapped to /, provides the handling for static -->
-  <!-- content, OPTIONS and TRACE methods for the context.                  -->
-  <!-- The following initParameters are supported:                          -->
-  <!--                                                                      -->
-  <!--   acceptRanges     If true, range requests and responses are         -->
-  <!--                    supported                                         -->
-  <!--                                                                      -->
-  <!--   dirAllowed       If true, directory listings are returned if no    -->
-  <!--                    welcome file is found. Else 403 Forbidden.        -->
-  <!--                                                                      -->
-  <!--   redirectWelcome  If true, redirect welcome file requests           -->
-  <!--                    else use request dispatcher forwards              -->
-  <!--                                                                      -->
-  <!--   gzip             If set to true, then static content will be served--> 
-  <!--                    as gzip content encoded if a matching resource is -->
-  <!--                    found ending with ".gz"                           -->
-  <!--                                                                      -->
-  <!--   resoureBase      Can be set to replace the context resource base   -->
-  <!--                                                                      -->
-  <!--   relativeResourceBase                                               -->
-  <!--                    Set with a pathname relative to the base of the   -->
-  <!--                    servlet context root. Useful for only serving     -->
-  <!--                    static content from only specific subdirectories. -->
-  <!--                                                                      -->
-  <!--   useFileMappedBuffer                                                -->
-  <!--                    If set to true (the default), a  memory mapped    -->
-  <!--                    file buffer will be used to serve static content  -->
-  <!--                    when using an NIO connector. Setting this value   -->
-  <!--                    to false means that a direct buffer will be used  -->
-  <!--                    instead. If you are having trouble with Windows   -->
-  <!--                    file locking, set this to false.                  -->
-  <!--                                                                      -->
-  <!--  cacheControl      If set, all static content will have this value   -->
-  <!--                    set as the cache-control header.                  -->
-  <!--                                                                      -->
-  <!--  maxCacheSize      Maximum size of the static resource cache         -->
-  <!--                                                                      -->
-  <!--  maxCachedFileSize Maximum size of any single file in the cache      -->
-  <!--                                                                      -->
-  <!--  maxCachedFiles    Maximum number of files in the cache              -->
-  <!--                                                                      -->
-  <!--  cacheType         "nio", "bio" or "both" to determine the type(s)   -->
-  <!--                    of resource cache. A bio cached buffer may be used-->
-  <!--                    by nio but is not as efficient as a nio buffer.   -->
-  <!--                    An nio cached buffer may not be used by bio.      -->
-  <!--                                                                      -->
-  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
-  <servlet>
-    <servlet-name>default</servlet-name>
-    <servlet-class>org.mortbay.jetty.servlet.DefaultServlet</servlet-class>
-    <init-param>
-      <param-name>acceptRanges</param-name>
-      <param-value>true</param-value>
-    </init-param>
-    <init-param>
-      <param-name>dirAllowed</param-name>
-      <param-value>true</param-value>
-    </init-param>
-    <init-param>
-      <param-name>redirectWelcome</param-name>
-      <param-value>false</param-value>
-    </init-param>
-    <init-param>
-      <param-name>maxCacheSize</param-name>
-      <param-value>256000000</param-value>
-    </init-param>
-    <init-param>
-      <param-name>maxCachedFileSize</param-name>
-      <param-value>10000000</param-value>
-    </init-param>
-    <init-param>
-      <param-name>maxCachedFiles</param-name>
-      <param-value>1000</param-value>
-    </init-param>
-    <init-param>
-      <param-name>cacheType</param-name>
-      <param-value>both</param-value>
-    </init-param>
-    <init-param>
-      <param-name>gzip</param-name>
-      <param-value>true</param-value>
-    </init-param>
-    <init-param>
-      <param-name>useFileMappedBuffer</param-name>
-      <param-value>true</param-value>
-    </init-param>  
-    <!--
-    <init-param>
-      <param-name>cacheControl</param-name>
-      <param-value>max-age=3600,public</param-value>
-    </init-param>
-    -->
-    <load-on-startup>0</load-on-startup>
-  </servlet> 
-
-  <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
-  
-
-  <!-- ==================================================================== -->
-  <!-- JSP Servlet                                                          -->
-  <!-- This is the jasper JSP servlet from the jakarta project              -->
-  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
-  <!-- The JSP page compiler and execution servlet, which is the mechanism  -->
-  <!-- used by Glassfish to support JSP pages.  Traditionally, this servlet -->
-  <!-- is mapped to URL patterh "*.jsp".  This servlet supports the         -->
-  <!-- following initialization parameters (default values are in square    -->
-  <!-- brackets):                                                           -->
-  <!--                                                                      -->
-  <!--   checkInterval       If development is false and reloading is true, -->
-  <!--                       background compiles are enabled. checkInterval -->
-  <!--                       is the time in seconds between checks to see   -->
-  <!--                       if a JSP page needs to be recompiled. [300]    -->
-  <!--                                                                      -->
-  <!--   compiler            Which compiler Ant should use to compile JSP   -->
-  <!--                       pages.  See the Ant documenation for more      -->
-  <!--                       information. [javac]                           -->
-  <!--                                                                      -->
-  <!--   classdebuginfo      Should the class file be compiled with         -->
-  <!--                       debugging information?  [true]                 -->
-  <!--                                                                      -->
-  <!--   classpath           What class path should I use while compiling   -->
-  <!--                       generated servlets?  [Created dynamically      -->
-  <!--                       based on the current web application]          -->
-  <!--                       Set to ? to make the container explicitly set  -->
-  <!--                       this parameter.                                -->
-  <!--                                                                      -->
-  <!--   development         Is Jasper used in development mode (will check -->
-  <!--                       for JSP modification on every access)?  [true] -->
-  <!--                                                                      -->
-  <!--   enablePooling       Determines whether tag handler pooling is      -->
-  <!--                       enabled  [true]                                -->
-  <!--                                                                      -->
-  <!--   fork                Tell Ant to fork compiles of JSP pages so that -->
-  <!--                       a separate JVM is used for JSP page compiles   -->
-  <!--                       from the one Tomcat is running in. [true]      -->
-  <!--                                                                      -->
-  <!--   ieClassId           The class-id value to be sent to Internet      -->
-  <!--                       Explorer when using <jsp:plugin> tags.         -->
-  <!--                       [clsid:8AD9C840-044E-11D1-B3E9-00805F499D93]   -->
-  <!--                                                                      -->
-  <!--   javaEncoding        Java file encoding to use for generating java  -->
-  <!--                       source files. [UTF-8]                          -->
-  <!--                                                                      -->
-  <!--   keepgenerated       Should we keep the generated Java source code  -->
-  <!--                       for each page instead of deleting it? [true]   -->
-  <!--                                                                      -->
-  <!--   logVerbosityLevel   The level of detailed messages to be produced  -->
-  <!--                       by this servlet.  Increasing levels cause the  -->
-  <!--                       generation of more messages.  Valid values are -->
-  <!--                       FATAL, ERROR, WARNING, INFORMATION, and DEBUG. -->
-  <!--                       [WARNING]                                      -->
-  <!--                                                                      -->
-  <!--   mappedfile          Should we generate static content with one     -->
-  <!--                       print statement per input line, to ease        -->
-  <!--                       debugging?  [false]                            -->
-  <!--                                                                      -->
-  <!--                                                                      -->
-  <!--   reloading           Should Jasper check for modified JSPs?  [true] -->
-  <!--                                                                      -->
-  <!--   suppressSmap        Should the generation of SMAP info for JSR45   -->
-  <!--                       debugging be suppressed?  [false]              -->
-  <!--                                                                      -->
-  <!--   dumpSmap            Should the SMAP info for JSR45 debugging be    -->
-  <!--                       dumped to a file? [false]                      -->
-  <!--                       False if suppressSmap is true                  -->
-  <!--                                                                      -->
-  <!--   scratchdir          What scratch directory should we use when      -->
-  <!--                       compiling JSP pages?  [default work directory  -->
-  <!--                       for the current web application]               -->
-  <!--                                                                      -->
-  <!--   tagpoolMaxSize      The maximum tag handler pool size  [5]         -->
-  <!--                                                                      -->
-  <!--   xpoweredBy          Determines whether X-Powered-By response       -->
-  <!--                       header is added by generated servlet  [false]  -->
-  <!--                                                                      -->
-  <!-- If you wish to use Jikes to compile JSP pages:                       -->
-  <!--   Set the init parameter "compiler" to "jikes".  Define              -->
-  <!--   the property "-Dbuild.compiler.emacs=true" when starting Jetty     -->
-  <!--   to cause Jikes to emit error messages in a format compatible with  -->
-  <!--   Jasper.                                                            -->
-  <!--   If you get an error reporting that jikes can't use UTF-8 encoding, -->
-  <!--   try setting the init parameter "javaEncoding" to "ISO-8859-1".     -->
-  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
-  <servlet id="jsp">
-    <servlet-name>jsp</servlet-name>
-    <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
-    <init-param>
-        <param-name>logVerbosityLevel</param-name>
-        <param-value>DEBUG</param-value>
-    </init-param>
-    <init-param>
-        <param-name>fork</param-name>
-        <param-value>false</param-value>
-    </init-param>
-    <init-param>
-        <param-name>xpoweredBy</param-name>
-        <param-value>false</param-value>
-    </init-param>
-    <!--  
-    <init-param>
-        <param-name>classpath</param-name>
-        <param-value>?</param-value>
-    </init-param>
-    -->
-    <load-on-startup>0</load-on-startup>
-  </servlet>
-
-  <servlet-mapping> 
-    <servlet-name>jsp</servlet-name> 
-    <url-pattern>*.jsp</url-pattern> 
-    <url-pattern>*.jspf</url-pattern>
-    <url-pattern>*.jspx</url-pattern>
-    <url-pattern>*.xsp</url-pattern>
-    <url-pattern>*.JSP</url-pattern> 
-    <url-pattern>*.JSPF</url-pattern>
-    <url-pattern>*.JSPX</url-pattern>
-    <url-pattern>*.XSP</url-pattern>
-  </servlet-mapping>
-  
-  <!-- ==================================================================== -->
-  <!-- Dynamic Servlet Invoker.                                             -->
-  <!-- This servlet invokes anonymous servlets that have not been defined   -->
-  <!-- in the web.xml or by other means. The first element of the pathInfo  -->
-  <!-- of a request passed to the envoker is treated as a servlet name for  -->
-  <!-- an existing servlet, or as a class name of a new servlet.            -->
-  <!-- This servlet is normally mapped to /servlet/*                        -->
-  <!-- This servlet support the following initParams:                       -->
-  <!--                                                                      -->
-  <!--  nonContextServlets       If false, the invoker can only load        -->
-  <!--                           servlets from the contexts classloader.    -->
-  <!--                           This is false by default and setting this  -->
-  <!--                           to true may have security implications.    -->
-  <!--                                                                      -->
-  <!--  verbose                  If true, log dynamic loads                 -->
-  <!--                                                                      -->
-  <!--  *                        All other parameters are copied to the     -->
-  <!--                           each dynamic servlet as init parameters    -->
-  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
-  <!-- Uncomment for dynamic invocation
-  <servlet>
-    <servlet-name>invoker</servlet-name>
-    <servlet-class>org.mortbay.jetty.servlet.Invoker</servlet-class>
-    <init-param>
-      <param-name>verbose</param-name>
-      <param-value>false</param-value>
-    </init-param>
-    <init-param>
-      <param-name>nonContextServlets</param-name>
-      <param-value>false</param-value>
-    </init-param>
-    <init-param>
-      <param-name>dynamicParam</param-name>
-      <param-value>anyValue</param-value>
-    </init-param>
-    <load-on-startup>0</load-on-startup>
-  </servlet>
-
-  <servlet-mapping> <servlet-name>invoker</servlet-name> <url-pattern>/servlet/*</url-pattern> </servlet-mapping>
-  -->
-
-
-
-  <!-- ==================================================================== -->
-  <session-config>
-    <session-timeout>30</session-timeout>
-  </session-config>
-
-  <!-- ==================================================================== -->
-  <!-- Default MIME mappings                                                -->
-  <!-- The default MIME mappings are provided by the mime.properties        -->
-  <!-- resource in the org.mortbay.jetty.jar file.  Additional or modified  -->
-  <!-- mappings may be specified here                                       -->
-  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
-  <!-- UNCOMMENT TO ACTIVATE
-  <mime-mapping>
-    <extension>mysuffix</extension>
-    <mime-type>mymime/type</mime-type>
-  </mime-mapping>
-  -->
-
-  <!-- ==================================================================== -->
-  <welcome-file-list>
-    <welcome-file>index.html</welcome-file>
-    <welcome-file>index.htm</welcome-file>
-    <welcome-file>index.jsp</welcome-file>
-  </welcome-file-list>
-
-  <!-- ==================================================================== -->
-  <locale-encoding-mapping-list>
-    <locale-encoding-mapping><locale>ar</locale><encoding>ISO-8859-6</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>be</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>bg</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>ca</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>cs</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>da</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>de</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>el</locale><encoding>ISO-8859-7</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>en</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>es</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>et</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>fi</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>fr</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>hr</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>hu</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>is</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>it</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>iw</locale><encoding>ISO-8859-8</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>ja</locale><encoding>Shift_JIS</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>ko</locale><encoding>EUC-KR</encoding></locale-encoding-mapping>     
-    <locale-encoding-mapping><locale>lt</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>lv</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>mk</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>nl</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>no</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>pl</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>pt</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>ro</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>ru</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>sh</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>sk</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>sl</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>sq</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>sr</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>sv</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>tr</locale><encoding>ISO-8859-9</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>uk</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>zh</locale><encoding>GB2312</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>zh_TW</locale><encoding>Big5</encoding></locale-encoding-mapping>   
-  </locale-encoding-mapping-list>
-  
-  <security-constraint>
-    <web-resource-collection>
-      <web-resource-name>Disable TRACE</web-resource-name>
-      <url-pattern>/</url-pattern>
-      <http-method>TRACE</http-method>
-    </web-resource-collection>
-    <auth-constraint/>
-  </security-constraint>
-  
-</web-app>
-
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-webapp/pom.xml b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-webapp/pom.xml
deleted file mode 100644
index 5fe9a19..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-webapp/pom.xml
+++ /dev/null
@@ -1,106 +0,0 @@
-<?xml version="1.0"?>
-<!--
-    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.
-    -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <parent>
-    <artifactId>continuum-buildagent</artifactId>
-    <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
-  </parent>
-  <modelVersion>4.0.0</modelVersion>
-  <groupId>org.apache.continuum</groupId>
-  <artifactId>continuum-buildagent-webapp</artifactId>
-  <packaging>war</packaging>
-  <name>Continuum :: Distributed Build :: Build Agent: Webapp</name>
-  <url>http://continuum.apache.org</url>
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-distributed-build-transport-slave-server</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-distributed-build-transport-master-client</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-buildagent-core</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.springframework</groupId>
-      <artifactId>spring-web</artifactId>
-      <version>2.5.4</version>
-    </dependency>
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-api</artifactId>
-    </dependency>      
-    <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-slf4j-logging</artifactId>
-      <scope>runtime</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-log4j12</artifactId>
-      <scope>runtime</scope>
-    </dependency>
-    <dependency>
-      <groupId>javax.servlet</groupId>
-      <artifactId>servlet-api</artifactId>
-      <version>2.4</version>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>javax.servlet</groupId>
-      <artifactId>jsp-api</artifactId>
-      <version>2.0</version>
-      <scope>provided</scope>
-    </dependency>
-  </dependencies>
-  
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.mortbay.jetty</groupId>
-        <artifactId>maven-jetty-plugin</artifactId>
-        <version>6.1.11</version>
-        <configuration>
-          <scanIntervalSeconds>10</scanIntervalSeconds>
-          <contextPath>/</contextPath>
-          <stopKey>stopkey</stopKey>
-          <stopPort>9192</stopPort>
-          <jettyEnvXml>${basedir}/src/jetty-env.xml</jettyEnvXml>
-          <connectors>
-            <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
-              <port>9191</port>
-              <maxIdleTime>60000</maxIdleTime>
-            </connector>
-          </connectors>
-          <systemProperties>
-            <systemProperty>
-              <name>CONTINUUM_BUILDAGENT_HOME</name>
-              <value>${project.build.directory}/appserver-base</value>
-            </systemProperty>
-          </systemProperties>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
-</project>
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-webapp/src/jetty-env.xml b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-webapp/src/jetty-env.xml
deleted file mode 100644
index 2513b2c..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-webapp/src/jetty-env.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0"?>
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
-
-<Configure class="org.mortbay.jetty.webapp.WebAppContext" />
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-webapp/src/main/java/org/apache/continuum/web/startup/BuildAgentStartup.java b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-webapp/src/main/java/org/apache/continuum/web/startup/BuildAgentStartup.java
deleted file mode 100644
index 86971ad..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-webapp/src/main/java/org/apache/continuum/web/startup/BuildAgentStartup.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package org.apache.continuum.web.startup;
-
-import javax.servlet.ServletContextEvent;
-import javax.servlet.ServletContextListener;
-
-import org.codehaus.plexus.spring.PlexusToSpringUtils;
-import org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.web.context.WebApplicationContext;
-import org.springframework.web.context.support.WebApplicationContextUtils;
-
-public class BuildAgentStartup
-    implements ServletContextListener
-{
-    private Logger log = LoggerFactory.getLogger( getClass() );
-    
-    /** 
-     * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent)
-     */
-    public void contextDestroyed( ServletContextEvent sce )
-    {
-        // nothing to do here
-
-    }
-    
-    /** 
-     * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent)
-     */
-    public void contextInitialized( ServletContextEvent sce )
-    {
-        log.info( "Initializing Build Agent Task Queue Executor" );
-
-        WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext( sce
-            .getServletContext() );
-        
-        TaskQueueExecutor buildAgent = (TaskQueueExecutor) wac.getBean( PlexusToSpringUtils
-            .buildSpringId( TaskQueueExecutor.class, "build-agent" ) );
-    }
-}
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-webapp/src/main/resources/META-INF/continuum/continuum-configuration.xml b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-webapp/src/main/resources/META-INF/continuum/continuum-configuration.xml
deleted file mode 100644
index 90ca6fc..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-webapp/src/main/resources/META-INF/continuum/continuum-configuration.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0"?>
-
-<!--
-  ~ 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.
-  -->
-
-<configuration>
-  <system/>
-  <jndi prefix="java:comp/env" config-optional="true"/>  
-  <xml fileName="${appserver.base}/conf/continuum-buildagent.xml" config-optional="true"
-       config-forceCreate="true" config-name="org.apache.continuum"/>
-  <xml fileName="${user.home}/.m2/continuum-buildagent.xml" config-optional="true"
-       config-forceCreate="true" config-name="org.apache.continuum.user"/>  
-</configuration>
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-webapp/src/main/resources/META-INF/plexus/application.xml b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-webapp/src/main/resources/META-INF/plexus/application.xml
deleted file mode 100644
index 631a021..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-webapp/src/main/resources/META-INF/plexus/application.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!--
-  ~ 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.
-  -->
-<plexus>
-  <components>
-   
-    <!--
-     | Logger manager
-     -->
-    <component>
-      <role>org.codehaus.plexus.logging.LoggerManager</role>
-      <implementation>org.codehaus.plexus.logging.slf4j.Slf4jLoggerManager</implementation>
-      <lifecycle-handler>basic</lifecycle-handler>
-    </component>
-
-  </components>
-  
-  <lifecycle-handler-manager implementation="org.codehaus.plexus.lifecycle.DefaultLifecycleHandlerManager">
-    <default-lifecycle-handler-id>plexus</default-lifecycle-handler-id>
-    <lifecycle-handlers>
-      <lifecycle-handler implementation="org.codehaus.plexus.personality.plexus.PlexusLifecycleHandler">
-        <id>plexus</id>
-        <name>Plexus Lifecycle Handler</name>
-        <begin-segment>
-          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.LogEnablePhase"/>
-          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.CompositionPhase"/>
-          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.ContextualizePhase"/>
-          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.AutoConfigurePhase"/>
-          <phase implementation="org.codehaus.plexus.registry.RegistryConfigurePhase"/>
-          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.ServiceablePhase"/>
-          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializePhase"/>
-          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.StartPhase"/>
-        </begin-segment>
-        <suspend-segment>
-          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.SuspendPhase"/>
-        </suspend-segment>
-        <resume-segment>
-          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.ResumePhase"/>
-        </resume-segment>
-        <end-segment>
-          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.StopPhase"/>
-          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.DisposePhase"/>
-          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.LogDisablePhase"/>
-        </end-segment>
-      </lifecycle-handler>
-    </lifecycle-handlers>
-  </lifecycle-handler-manager>
-</plexus>
\ No newline at end of file
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-webapp/src/main/resources/applicationContext.xml b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-webapp/src/main/resources/applicationContext.xml
deleted file mode 100644
index 9866804..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-webapp/src/main/resources/applicationContext.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
-       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xsi:schemaLocation="http://www.springframework.org/schema/beans
-           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
-  
-  <bean id="slaveBuildAgentTransportServer" class="org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportServer">
-    <constructor-arg ref="continuumBuildAgentService"/>
-  </bean>
-
-  <bean name="xmlrpcServicesList" class="java.util.ArrayList">
-    <constructor-arg>
-      <list>
-        <ref bean="slaveBuildAgentTransportServer"/>
-      </list>
-    </constructor-arg>
-  </bean>
-  
-</beans>
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-webapp/src/main/resources/log4j.xml b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-webapp/src/main/resources/log4j.xml
deleted file mode 100644
index 375b4cd..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-webapp/src/main/resources/log4j.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
-
-<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
-  <appender name="console" class="org.apache.log4j.ConsoleAppender">
-    <param name="Target" value="System.out"/>
-    <layout class="org.apache.log4j.PatternLayout">
-      <param name="ConversionPattern" value="[%p] %-30c{1} - %m%n"/>
-    </layout>
-  </appender>
-  <logger name="org.apache.continuum.buildagent">
-    <level value="info"/>
-  </logger>
-  <logger name="org.apache.continuum.web">
-    <level value="info"/>
-  </logger>
-  <logger name="org.springframework">
-    <level value="error"/>
-  </logger>
-  <root>
-    <priority value ="info" />
-    <appender-ref ref="console" />
-  </root>
-</log4j:configuration>
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-webapp/src/main/webapp/WEB-INF/web.xml b/continuum-distributed-build/continuum-buildagent/continuum-buildagent-webapp/src/main/webapp/WEB-INF/web.xml
deleted file mode 100644
index d84aca3..0000000
--- a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-webapp/src/main/webapp/WEB-INF/web.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-<!DOCTYPE web-app PUBLIC
- "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
- "http://java.sun.com/dtd/web-app_2_3.dtd" >
-
-<web-app>
-  <display-name>Continuum Distributed Build Transport Tests</display-name>
-  
-  <listener>
-    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
-  </listener>
-  
-  <listener>
-    <!-- TODO: some Spring technique for this? -->
-  	<listener-class>org.apache.continuum.web.startup.BuildAgentStartup</listener-class>
-  </listener>
-  
-  <context-param>
-    <param-name>contextClass</param-name>
-    <param-value>org.codehaus.plexus.spring.PlexusWebApplicationContext</param-value>
-  </context-param>
-  
-  <context-param>
-    <param-name>contextConfigLocation</param-name>
-    <param-value>
-      classpath*:/META-INF/spring-context.xml
-      classpath*:/applicationContext.xml
-      classpath*:/META-INF/plexus/components.xml
-      classpath*:/META-INF/plexus/application.xml
-    </param-value>
-  </context-param>
-  
-  <servlet>
-    <servlet-name>MasterXmlRpcServlet</servlet-name>
-    <servlet-class>
-      com.atlassian.xmlrpc.spring.BinderSpringXmlRpcServlet
-    </servlet-class>
-    <init-param>
-      <param-name>serviceListBeanName</param-name>
-      <param-value>xmlrpcServicesList</param-value>
-    </init-param>
-    <init-param>
-      <param-name>enabledForExtensions</param-name>
-      <param-value>true</param-value>
-    </init-param>
-    <load-on-startup>1</load-on-startup>
-  </servlet>
-  
-  <servlet>
-    <servlet-name>SlaveXmlRpcServlet</servlet-name>
-    <servlet-class>
-      com.atlassian.xmlrpc.spring.BinderSpringXmlRpcServlet
-    </servlet-class>
-    <init-param>
-      <param-name>serviceListBeanName</param-name>
-      <param-value>xmlrpcServicesList</param-value>
-    </init-param>
-    <init-param>
-      <param-name>enabledForExtensions</param-name>
-      <param-value>true</param-value>
-    </init-param>
-    <load-on-startup>1</load-on-startup>
-  </servlet>
-  
-  <servlet-mapping>
-    <servlet-name>MasterXmlRpcServlet</servlet-name>
-    <url-pattern>/master-xmlrpc</url-pattern>
-  </servlet-mapping>
-  
-  <servlet-mapping>
-    <servlet-name>SlaveXmlRpcServlet</servlet-name>
-    <url-pattern>/buildagent-xmlrpc</url-pattern>
-  </servlet-mapping>
-</web-app>
diff --git a/continuum-distributed-build/continuum-buildagent/pom.xml b/continuum-distributed-build/continuum-buildagent/pom.xml
deleted file mode 100644
index 0020d07..0000000
--- a/continuum-distributed-build/continuum-buildagent/pom.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<!--
-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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <parent>
-    <groupId>org.apache.continuum</groupId>
-    <artifactId>continuum-distributed-build</artifactId>
-    <version>1.3.1-SNAPSHOT</version>
-  </parent>
-
-  <groupId>org.apache.continuum</groupId>
-  <artifactId>continuum-buildagent</artifactId>
-  <packaging>pom</packaging>
-  <name>Continuum :: Distributed Build :: Build Agent</name>
-  
-  <modules>
-    <module>continuum-buildagent-api</module>
-    <module>continuum-buildagent-core</module>
-    <module>continuum-buildagent-webapp</module>
-    <module>continuum-buildagent-jetty</module>
-  </modules>
-</project>
diff --git a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-master/continuum-distributed-build-transport-master-api/pom.xml b/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-master/continuum-distributed-build-transport-master-api/pom.xml
deleted file mode 100644
index b3b62d9..0000000
--- a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-master/continuum-distributed-build-transport-master-api/pom.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<!--
-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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <parent>
-    <groupId>org.apache.continuum</groupId>
-    <artifactId>continuum-distributed-build-transport-master</artifactId>
-    <version>1.3.1-SNAPSHOT</version>
-  </parent>
-  <modelVersion>4.0.0</modelVersion>
-  <artifactId>continuum-distributed-build-transport-master-api</artifactId>
-  <name>Continuum :: Distributed Build :: Transport :: Master :: API</name>
-
-  <dependencies>
-    <dependency>
-      <groupId>com.atlassian.xmlrpc</groupId>
-      <artifactId>atlassian-xmlrpc-binder-server-spring</artifactId>
-      <version>0.8.2</version>
-    </dependency>
-  </dependencies>
-</project>
diff --git a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-master/continuum-distributed-build-transport-master-api/src/main/java/org/apache/continuum/distributed/transport/master/MasterBuildAgentTransportService.java b/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-master/continuum-distributed-build-transport-master-api/src/main/java/org/apache/continuum/distributed/transport/master/MasterBuildAgentTransportService.java
deleted file mode 100644
index 9f8638d..0000000
--- a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-master/continuum-distributed-build-transport-master-api/src/main/java/org/apache/continuum/distributed/transport/master/MasterBuildAgentTransportService.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.apache.continuum.distributed.transport.master;
-
-import java.util.Map;
-
-import com.atlassian.xmlrpc.ServiceObject;
-
-/*
- * 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.
- */
-
-/**
- * MasterBuildAgentTransportService
- */
-@ServiceObject( "MasterBuildAgentTransportService" )
-public interface MasterBuildAgentTransportService
-{
-    public Boolean returnBuildResult( Map buildResult ) throws Exception;
-    
-    public Boolean returnScmResult( Map scmResult ) throws Exception;
-
-    public Boolean startProjectBuild( Integer projectId ) throws Exception;
-
-    public Boolean prepareBuildFinished( Map prepareBuildResult ) throws Exception; 
-
-    public Boolean startPrepareBuild( Map prepareBuildResult ) throws Exception;
-
-    public Map<String, String> getEnvironments( Integer buildDefinitionId, String installationType ) throws Exception;
-
-    public Boolean ping() throws Exception;
-}
diff --git a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-master/continuum-distributed-build-transport-master-client/pom.xml b/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-master/continuum-distributed-build-transport-master-client/pom.xml
deleted file mode 100644
index 192550b..0000000
--- a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-master/continuum-distributed-build-transport-master-client/pom.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<!--
-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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <parent>
-    <groupId>org.apache.continuum</groupId>
-    <artifactId>continuum-distributed-build-transport-master</artifactId>
-    <version>1.3.1-SNAPSHOT</version>
-  </parent>
-  <modelVersion>4.0.0</modelVersion>
-  <artifactId>continuum-distributed-build-transport-master-client</artifactId>
-  <name>Continuum :: Distributed Build :: Transport :: Master :: Client</name>
-
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-distributed-build-transport-master-api</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>com.atlassian.xmlrpc</groupId>
-      <artifactId>atlassian-xmlrpc-binder</artifactId>
-      <version>0.8.2</version>
-    </dependency>
-  </dependencies>
-</project>
diff --git a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-master/continuum-distributed-build-transport-master-client/src/main/java/org/apache/continuum/distributed/transport/master/MasterBuildAgentTransportClient.java b/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-master/continuum-distributed-build-transport-master-client/src/main/java/org/apache/continuum/distributed/transport/master/MasterBuildAgentTransportClient.java
deleted file mode 100644
index df9d4d5..0000000
--- a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-master/continuum-distributed-build-transport-master-client/src/main/java/org/apache/continuum/distributed/transport/master/MasterBuildAgentTransportClient.java
+++ /dev/null
@@ -1,197 +0,0 @@
-package org.apache.continuum.distributed.transport.master;
-
-/*
- * 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.net.URL;
-import java.util.Map;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.atlassian.xmlrpc.AuthenticationInfo;
-import com.atlassian.xmlrpc.Binder;
-import com.atlassian.xmlrpc.BindingException;
-import com.atlassian.xmlrpc.DefaultBinder;
-
-/**
- * MasterBuildAgentTransportClient
- */
-public class MasterBuildAgentTransportClient
-    implements MasterBuildAgentTransportService
-{
-    private Logger log = LoggerFactory.getLogger( this.getClass() );
-    
-    MasterBuildAgentTransportService master;
-    
-    public MasterBuildAgentTransportClient( URL serviceUrl )
-        throws Exception
-    {
-        this( serviceUrl, null, null );
-    }
-
-    public MasterBuildAgentTransportClient( URL serviceUrl, String login, String password )
-        throws Exception
-    {
-        Binder binder = new DefaultBinder();
-        AuthenticationInfo authnInfo = new AuthenticationInfo( login, password );
-        
-        try
-        {
-            master = binder.bind( MasterBuildAgentTransportService.class, serviceUrl, authnInfo );
-        }
-        catch ( BindingException e )
-        {
-            log.error( "Can't bind service interface " + MasterBuildAgentTransportService.class.getName() + " to " + serviceUrl.toExternalForm() + " using " + authnInfo.getUsername() + ", " + authnInfo.getPassword(), e );
-            throw new Exception( "Can't bind service interface " + MasterBuildAgentTransportService.class.getName() + " to " + serviceUrl.toExternalForm() + " using " + authnInfo.getUsername() + ", " + authnInfo.getPassword(), e);
-        }
-    }
-
-    public Boolean returnBuildResult( Map buildResult )
-        throws Exception
-    {
-        Boolean result = null;
-        
-        try
-        {
-            result = master.returnBuildResult( buildResult );
-            log.info( "Returning the build result." );
-        }
-        catch ( Exception e )
-        {
-            log.error( "Failed to return the build result.", e );
-            throw new Exception( "Failed to return the build result", e);
-        }
-        
-        return result;
-    }
-
-    public Boolean returnScmResult( Map scmResult )
-        throws Exception
-    {
-        Boolean result = null;
-        
-        try
-        {
-            result = master.returnScmResult( scmResult );
-            log.info( "Returning the scm result." );
-        }
-        catch ( Exception e )
-        {
-            log.error( "Failed to return the SCM result.", e );
-            throw new Exception( "Failed to return the SCM result", e);
-        }
-        
-        return result;
-    }
-    
-    public Boolean ping()
-        throws Exception
-    {
-        Boolean result = null;
-        
-        try
-        {
-            result = master.ping();
-            log.info( "Ping " + ( result.booleanValue() ? "ok" : "failed" ) );
-        }
-        catch ( Exception e )
-        {
-            log.info( "Ping error" );
-            throw new Exception( "Ping error", e );
-        }
-        
-        return result;
-    }
-
-    public Boolean prepareBuildFinished( Map prepareBuildResult )
-        throws Exception
-    {
-        Boolean result = null;
-        
-        try
-        {
-            result = master.prepareBuildFinished( prepareBuildResult );
-            log.info(  "Prepare build finished." );
-        }
-        catch ( Exception e )
-        {
-            log.error( "Failed to finish prepare build" );
-            throw new Exception( "Failed to finish prepare build", e );
-        }
-        
-        return result;
-    }
-
-    public Boolean startProjectBuild( Integer projectId )
-        throws Exception
-    {
-        Boolean result = null;
-        
-        try
-        {
-            result = master.startProjectBuild( projectId );
-            log.info( "Return project currently building" );
-        }
-        catch ( Exception e )
-        {
-            log.error( "Failed to return project currently building", e );
-            throw new Exception( "Failed to return project currently building", e );
-        }
-
-        return result;
-    }
-
-    public Boolean startPrepareBuild( Map prepareBuildResult )
-        throws Exception
-    {
-        Boolean result = null;
-
-        try
-        {
-            result = master.startPrepareBuild( prepareBuildResult );
-            log.info( "Started prepare build" );
-        }
-        catch ( Exception e )
-        {
-            log.error( "Failed to start prepare build", e );
-            throw new Exception( "Failed to start prepare build", e );
-        }
-
-        return result;
-    }
-
-    public Map<String, String> getEnvironments( Integer buildDefinitionId, String installationType )
-        throws Exception
-    {
-        Map<String, String> result = null;
-        try
-        {
-            result = master.getEnvironments( buildDefinitionId, installationType );
-            log.info( "Retrieved environments" );
-        }
-        catch ( Exception e )
-        {
-            log.error( "Failed to retrieve environments", e );
-            throw new Exception( "Failed to retrieve environments", e );
-        }
-
-        return result;
-    }
-}
diff --git a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-master/continuum-distributed-build-transport-master-server/pom.xml b/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-master/continuum-distributed-build-transport-master-server/pom.xml
deleted file mode 100644
index afd8f66..0000000
--- a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-master/continuum-distributed-build-transport-master-server/pom.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<!--
-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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <parent>
-    <groupId>org.apache.continuum</groupId>
-    <artifactId>continuum-distributed-build-transport-master</artifactId>
-    <version>1.3.1-SNAPSHOT</version>
-  </parent>
-  <modelVersion>4.0.0</modelVersion>
-  <artifactId>continuum-distributed-build-transport-master-server</artifactId>
-  <name>Continuum :: Distributed Build :: Transport :: Master :: Server</name>
-
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-distributed-build-transport-master-api</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-api</artifactId>
-      <exclusions>
-        <exclusion>
-          <groupId>org.apache.archiva</groupId>
-          <artifactId>archiva-common</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>org.apache.archiva</groupId>
-          <artifactId>archiva-repository-layer</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-  </dependencies>
-</project>
diff --git a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-master/continuum-distributed-build-transport-master-server/src/main/java/org/apache/continuum/distributed/transport/master/MasterBuildAgentTransportServer.java b/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-master/continuum-distributed-build-transport-master-server/src/main/java/org/apache/continuum/distributed/transport/master/MasterBuildAgentTransportServer.java
deleted file mode 100644
index 3376bc1..0000000
--- a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-master/continuum-distributed-build-transport-master-server/src/main/java/org/apache/continuum/distributed/transport/master/MasterBuildAgentTransportServer.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package org.apache.continuum.distributed.transport.master;
-
-/*
- * 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.Map;
-
-import org.apache.continuum.builder.distributed.manager.DistributedBuildManager;
-import org.apache.continuum.distributed.transport.master.MasterBuildAgentTransportService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * MasterBuildAgentTransportServer
- */
-public class MasterBuildAgentTransportServer
-    implements MasterBuildAgentTransportService
-{
-    private Logger log = LoggerFactory.getLogger( this.getClass() );
-
-    private DistributedBuildManager distributedBuildManager;
-
-    public MasterBuildAgentTransportServer( DistributedBuildManager distributedBuildManager )
-    {
-        this.distributedBuildManager = distributedBuildManager;
-    }
-
-    public Boolean returnBuildResult( Map buildResult )
-        throws Exception
-    {
-        log.info( "Build result returned." );
-        distributedBuildManager.updateBuildResult( buildResult );
-        return Boolean.TRUE;
-    }
-
-    public Boolean returnScmResult( Map scmResult )
-        throws Exception
-    {
-        log.info( "SCM result returned." );
-        distributedBuildManager.updateScmResult( scmResult );
-        return Boolean.TRUE;
-    }
-
-    public Boolean ping()
-        throws Exception
-    {
-        log.info( "Ping ok" );
-        
-        return Boolean.TRUE;
-    }
-
-    public Boolean prepareBuildFinished( Map prepareBuildResult )
-        throws Exception
-    {
-        log.info( "Prepare build finished." );
-        distributedBuildManager.prepareBuildFinished( prepareBuildResult );
-        return Boolean.TRUE;
-    }
-
-    public Boolean startProjectBuild( Integer projectId )
-        throws Exception
-    {
-        log.info( "Start project build." );
-        distributedBuildManager.startProjectBuild( projectId.intValue() );
-        return Boolean.TRUE;
-    }
-
-    public Boolean startPrepareBuild( Map prepareBuildResult )
-        throws Exception
-    {
-        log.info( "Start prepare build." );
-        distributedBuildManager.startPrepareBuild( prepareBuildResult );
-        return Boolean.TRUE;
-    }
-
-    public Map<String, String> getEnvironments( Integer buildDefinitionId, String installationType )
-        throws Exception
-    {
-        log.info( "Retrieving environments" );
-        return distributedBuildManager.getEnvironments( buildDefinitionId, installationType );
-    }
-}
diff --git a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-master/pom.xml b/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-master/pom.xml
deleted file mode 100644
index c20737b..0000000
--- a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-master/pom.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <parent>
-    <artifactId>continuum-distributed-build-transport</artifactId>
-    <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
-  </parent>
-  <modelVersion>4.0.0</modelVersion>
-  <artifactId>continuum-distributed-build-transport-master</artifactId>
-  <name>Continuum :: Distributed Build :: Transport :: Master</name>
-  <packaging>pom</packaging>
-  <modules>
-    <module>continuum-distributed-build-transport-master-api</module>
-    <module>continuum-distributed-build-transport-master-server</module>
-    <module>continuum-distributed-build-transport-master-client</module>
-  </modules>
-</project>
diff --git a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-slave/continuum-distributed-build-transport-slave-api/pom.xml b/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-slave/continuum-distributed-build-transport-slave-api/pom.xml
deleted file mode 100644
index 6e61301..0000000
--- a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-slave/continuum-distributed-build-transport-slave-api/pom.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<!--
-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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <parent>
-    <groupId>org.apache.continuum</groupId>
-    <artifactId>continuum-distributed-build-transport-slave</artifactId>
-    <version>1.3.1-SNAPSHOT</version>
-  </parent>
-  <modelVersion>4.0.0</modelVersion>
-  <artifactId>continuum-distributed-build-transport-slave-api</artifactId>
-  <name>Continuum :: Distributed Build :: Transport :: Slave :: API</name>
-
-  <dependencies>
-    <dependency>
-      <groupId>com.atlassian.xmlrpc</groupId>
-      <artifactId>atlassian-xmlrpc-binder-server-spring</artifactId>
-      <version>0.8.2</version>
-    </dependency>
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-api</artifactId>
-    </dependency>
-  </dependencies>
-</project>
diff --git a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-slave/continuum-distributed-build-transport-slave-api/src/main/java/org/apache/continuum/distributed/transport/slave/SlaveBuildAgentTransportService.java b/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-slave/continuum-distributed-build-transport-slave-api/src/main/java/org/apache/continuum/distributed/transport/slave/SlaveBuildAgentTransportService.java
deleted file mode 100644
index 3f14b19..0000000
--- a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-slave/continuum-distributed-build-transport-slave-api/src/main/java/org/apache/continuum/distributed/transport/slave/SlaveBuildAgentTransportService.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package org.apache.continuum.distributed.transport.slave;
-
-import java.util.List;
-import java.util.Map;
-
-import com.atlassian.xmlrpc.ServiceObject;
-
-/*
- * 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.
- */
-
-/**
- * SlaveBuildAgentTransportService
- */
-@ServiceObject( "SlaveBuildAgentTransportService" )
-public interface SlaveBuildAgentTransportService
-{
-    public Boolean buildProjects( List<Map> projectsBuildContext ) throws Exception;
-    
-    public Map getBuildResult( int projectId ) throws Exception;
-    
-    public Integer getProjectCurrentlyBuilding() throws Exception;
-    
-    public List<Map> getAvailableInstallations() throws Exception;
-    
-    public Boolean ping() throws Exception;
-
-    public Boolean cancelBuild() throws Exception;
-}
diff --git a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-slave/continuum-distributed-build-transport-slave-client/pom.xml b/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-slave/continuum-distributed-build-transport-slave-client/pom.xml
deleted file mode 100644
index 337c1a3..0000000
--- a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-slave/continuum-distributed-build-transport-slave-client/pom.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<!--
-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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <parent>
-    <groupId>org.apache.continuum</groupId>
-    <artifactId>continuum-distributed-build-transport-slave</artifactId>
-    <version>1.3.1-SNAPSHOT</version>
-  </parent>
-  <modelVersion>4.0.0</modelVersion>
-  <artifactId>continuum-distributed-build-transport-slave-client</artifactId>
-  <name>Continuum :: Distributed Build :: Transport :: Slave :: Client</name>
-
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-distributed-build-transport-slave-api</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>com.atlassian.xmlrpc</groupId>
-      <artifactId>atlassian-xmlrpc-binder</artifactId>
-      <version>0.8.2</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-buildagent-api</artifactId>
-    </dependency>
-  </dependencies>
-</project>
diff --git a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-slave/continuum-distributed-build-transport-slave-client/src/main/java/org/apache/continuum/distributed/transport/slave/SlaveBuildAgentTransportClient.java b/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-slave/continuum-distributed-build-transport-slave-client/src/main/java/org/apache/continuum/distributed/transport/slave/SlaveBuildAgentTransportClient.java
deleted file mode 100644
index 06dd68c..0000000
--- a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-slave/continuum-distributed-build-transport-slave-client/src/main/java/org/apache/continuum/distributed/transport/slave/SlaveBuildAgentTransportClient.java
+++ /dev/null
@@ -1,180 +0,0 @@
-package org.apache.continuum.distributed.transport.slave;
-
-/*
- * 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.net.URL;
-import java.util.List;
-import java.util.Map;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.atlassian.xmlrpc.AuthenticationInfo;
-import com.atlassian.xmlrpc.Binder;
-import com.atlassian.xmlrpc.BindingException;
-import com.atlassian.xmlrpc.DefaultBinder;
-
-/**
- * SlaveBuildAgentTransportClient
- */
-public class SlaveBuildAgentTransportClient
-    implements SlaveBuildAgentTransportService
-{
-    private Logger log = LoggerFactory.getLogger( this.getClass() );
-    
-    private SlaveBuildAgentTransportService slave;
-    
-    public SlaveBuildAgentTransportClient( URL serviceUrl )
-        throws Exception
-    {
-        this( serviceUrl, null, null );
-    }
-
-    public SlaveBuildAgentTransportClient( URL serviceUrl, String login, String password )
-        throws Exception
-    {
-        Binder binder = new DefaultBinder();
-        AuthenticationInfo authnInfo = new AuthenticationInfo( login, password );
-        
-        try
-        {
-            slave = binder.bind( SlaveBuildAgentTransportService.class, serviceUrl, authnInfo );
-        }
-        catch ( BindingException e )
-        {
-            log.error( "Can't bind service interface " + SlaveBuildAgentTransportService.class.getName() + " to " + serviceUrl.toExternalForm() + " using " + authnInfo.getUsername() + ", " + authnInfo.getPassword(), e );
-            throw new Exception( "Can't bind service interface " + SlaveBuildAgentTransportService.class.getName() + " to " + serviceUrl.toExternalForm() + " using " + authnInfo.getUsername() + ", " + authnInfo.getPassword(), e);
-        }
-    }
-
-    public Boolean buildProjects( List<Map> projectsBuildContext )
-        throws Exception
-    {
-        Boolean result = null;
-        
-        try
-        {
-            result = slave.buildProjects( projectsBuildContext );
-            log.info( "Building projects." );
-        }
-        catch ( Exception e )
-        {
-            log.error( "Failed to build projects.", e );
-            throw new Exception( "Failed to build projects.", e );
-        }
-        
-        return result;
-    }
-
-    public List<Map> getAvailableInstallations()
-        throws Exception
-    {
-        List<Map> installations = null;
-        
-        try
-        {
-            installations = slave.getAvailableInstallations();
-            log.info( "Available installations: " + installations.size() );
-        }
-        catch ( Exception e )
-        {
-            log.error( "Failed to get available installations.", e );
-            throw new Exception( "Failed to get available installations." , e );
-        }
-        
-        return installations;
-    }
-
-    public Map getBuildResult( int projectId )
-        throws Exception
-    {
-        Map buildResult = null;
-        
-        try
-        {
-            buildResult = slave.getBuildResult( projectId );
-            log.info( "Build result for project " + projectId + " acquired." );
-        }
-        catch ( Exception e )
-        {
-            log.error( "Failed to get build result for project " + projectId, e );
-            throw new Exception( "Failed to get build result for project " + projectId, e );
-        }
-        
-        return buildResult;
-    }
-
-    public Integer getProjectCurrentlyBuilding()
-        throws Exception
-    {
-        Integer projectId = null;
-        
-        try
-        {
-            projectId = slave.getProjectCurrentlyBuilding();
-            log.info( "Currently building project " + projectId );
-        }
-        catch ( Exception e )
-        {
-            log.error( "Failed to get the currently building project", e );
-            throw new Exception( "Failed to get the currently building project", e );
-        }
-        
-        return projectId;
-    }
-
-    public Boolean ping()
-        throws Exception
-    {
-        Boolean result = null;
-        
-        try
-        {
-            result = slave.ping();
-            log.info( "Ping " + ( result.booleanValue() ? "ok" : "failed" ) );
-        }
-        catch ( Exception e )
-        {
-            log.info( "Ping error" );
-            throw new Exception( "Ping error", e );
-        }
-        
-        return result;
-    }
-
-    public Boolean cancelBuild()
-        throws Exception
-    {
-        Boolean result = null;
-
-        try
-        {
-            result = slave.cancelBuild();
-            log.info( "Cancelled build" );
-        }
-        catch ( Exception e )
-        {
-            log.error( "Error cancelling build" );
-            throw new Exception( "Error cancelling build", e );
-        }
-
-        return null;
-    }
-}
diff --git a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-slave/continuum-distributed-build-transport-slave-server/pom.xml b/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-slave/continuum-distributed-build-transport-slave-server/pom.xml
deleted file mode 100644
index bb4f619..0000000
--- a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-slave/continuum-distributed-build-transport-slave-server/pom.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<!--
-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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <parent>
-    <groupId>org.apache.continuum</groupId>
-    <artifactId>continuum-distributed-build-transport-slave</artifactId>
-    <version>1.3.1-SNAPSHOT</version>
-  </parent>
-  <modelVersion>4.0.0</modelVersion>
-  <artifactId>continuum-distributed-build-transport-slave-server</artifactId>
-  <name>Continuum :: Distributed Build :: Transport :: Slave :: Server</name>
-
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-distributed-build-transport-slave-api</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-buildagent-api</artifactId>
-    </dependency>
-  </dependencies>
-</project>
diff --git a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-slave/continuum-distributed-build-transport-slave-server/src/main/java/org/apache/continuum/distributed/transport/slave/SlaveBuildAgentTransportServer.java b/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-slave/continuum-distributed-build-transport-slave-server/src/main/java/org/apache/continuum/distributed/transport/slave/SlaveBuildAgentTransportServer.java
deleted file mode 100644
index 75231dd..0000000
--- a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-slave/continuum-distributed-build-transport-slave-server/src/main/java/org/apache/continuum/distributed/transport/slave/SlaveBuildAgentTransportServer.java
+++ /dev/null
@@ -1,138 +0,0 @@
-package org.apache.continuum.distributed.transport.slave;
-
-/*
- * 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.List;
-import java.util.Map;
-
-import org.apache.continuum.buildagent.ContinuumBuildAgentException;
-import org.apache.continuum.buildagent.ContinuumBuildAgentService;
-import org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * ProxyMasterBuildAgentTransportService
- */
-public class SlaveBuildAgentTransportServer
-    implements SlaveBuildAgentTransportService
-{
-    private Logger log = LoggerFactory.getLogger( this.getClass() );
-
-    private ContinuumBuildAgentService continuumBuildAgentService;
-    
-    public SlaveBuildAgentTransportServer( ContinuumBuildAgentService continuumBuildAgentService )
-    {
-        this.continuumBuildAgentService = continuumBuildAgentService;
-    }
-    
-    public Boolean buildProjects( List<Map> projectsBuildContext )
-        throws Exception
-    {
-        Boolean result = Boolean.FALSE;
-        
-        try
-        {
-            continuumBuildAgentService.buildProjects( projectsBuildContext );
-            result = Boolean.TRUE;
-            
-            log.info( "Building projects." );
-        }
-        catch ( ContinuumBuildAgentException e )
-        {
-            log.error( "Failed to build projects.", e );
-        }
-        
-        return result;
-    }
-
-    public List<Map> getAvailableInstallations()
-        throws Exception
-    {
-        List<Map> installations = null;
-
-        try
-        {
-            installations = continuumBuildAgentService.getAvailableInstallations();
-            log.info( "Available installations: " + installations.size() );
-        }
-        catch ( ContinuumBuildAgentException e )
-        {
-            log.error( "Failed to get available installations.", e );
-        }
-
-        return installations;
-    }
-
-    public Map getBuildResult( int projectId )
-        throws Exception
-    {
-        Map buildResult = null;
-        
-        try
-        {
-            buildResult = continuumBuildAgentService.getBuildResult( projectId );
-            log.info( "Build result for project " + projectId + " acquired." );
-        }
-        catch ( ContinuumBuildAgentException e )
-        {
-            log.error( "Failed to get build result for project " + projectId, e );
-        }
-        
-        return buildResult;
-    }
-
-    public Integer getProjectCurrentlyBuilding()
-        throws Exception
-    {
-        Integer projectId = new Integer( continuumBuildAgentService.getProjectCurrentlyBuilding() );
-        
-        log.info( "Currently building project " + projectId.intValue() );
-        
-        return projectId;
-    }
-
-    public Boolean ping()
-        throws Exception
-    {
-        log.info( "Ping ok" );
-        
-        return Boolean.TRUE;
-    }
-
-    public Boolean cancelBuild()
-        throws Exception
-    {
-        Boolean result = Boolean.FALSE;
-
-        try
-        {
-            continuumBuildAgentService.cancelBuild();
-            result = Boolean.TRUE;
-            log.info( "Cancelled build" );
-        }
-        catch ( ContinuumBuildAgentException e )
-        {
-            log.error( "Failed to cancel build", e );
-        }
-
-        return result;
-    }
-}
diff --git a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-slave/pom.xml b/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-slave/pom.xml
deleted file mode 100644
index 2d3673f..0000000
--- a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-slave/pom.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-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.
---><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <parent>
-    <artifactId>continuum-distributed-build</artifactId>
-    <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
-  </parent>
-  <modelVersion>4.0.0</modelVersion>
-  <artifactId>continuum-distributed-build-transport-slave</artifactId>
-  <name>Continuum :: Distributed Build :: Transport :: Slave</name>
-  <packaging>pom</packaging>
-  <modules>
-    <module>continuum-distributed-build-transport-slave-api</module>
-    <module>continuum-distributed-build-transport-slave-server</module>
-    <module>continuum-distributed-build-transport-slave-client</module>
-  </modules>
-</project>
diff --git a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/pom.xml b/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/pom.xml
deleted file mode 100644
index 971b83b..0000000
--- a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/pom.xml
+++ /dev/null
@@ -1,149 +0,0 @@
-<?xml version="1.0"?>
-<!--
-    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.
-    -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <parent>
-    <artifactId>continuum-distributed-build-transport</artifactId>
-    <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
-  </parent>
-  <modelVersion>4.0.0</modelVersion>
-  <groupId>org.apache.continuum</groupId>
-  <artifactId>continuum-distributed-build-transport-tests</artifactId>
-  <packaging>war</packaging>
-  <name>Continuum :: Distributed Build :: Transport :: Tests</name>
-  <url>http://continuum.apache.org</url>
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-distributed-build-transport-slave-server</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-distributed-build-transport-slave-client</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-distributed-build-transport-master-server</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-distributed-build-transport-master-client</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-buildagent-core</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.springframework</groupId>
-      <artifactId>spring-web</artifactId>
-      <version>2.5.4</version>
-    </dependency>
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-api</artifactId>
-    </dependency>      
-    <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-slf4j-logging</artifactId>
-      <scope>runtime</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-log4j12</artifactId>
-      <scope>runtime</scope>
-    </dependency>
-    <dependency>
-      <groupId>javax.servlet</groupId>
-      <artifactId>servlet-api</artifactId>
-      <version>2.4</version>
-      <scope>provided</scope>
-    </dependency>
-  </dependencies>
-  
-  <build>
-    <testSourceDirectory>src/test/it</testSourceDirectory>
-    <plugins>
-      <plugin>
-        <groupId>org.mortbay.jetty</groupId>
-        <artifactId>maven-jetty-plugin</artifactId>
-        <version>6.1.11</version>
-        <configuration>
-          <scanIntervalSeconds>10</scanIntervalSeconds>
-          <contextPath>/</contextPath>
-          <stopKey>stopkey</stopKey>
-          <stopPort>9192</stopPort>
-          <jettyEnvXml>${basedir}/src/jetty-env.xml</jettyEnvXml>
-          <connectors>
-            <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
-              <port>9191</port>
-              <maxIdleTime>60000</maxIdleTime>
-            </connector>
-          </connectors>
-          <systemProperties>
-            <systemProperty>
-              <name>appserver.base</name>
-              <value>${project.build.directory}/appserver-base</value>
-            </systemProperty>
-          </systemProperties>
-        </configuration>
-        <executions>
-          <execution>
-            <id>start-jetty</id>
-            <phase>pre-integration-test</phase>
-            <goals>
-              <goal>run</goal>
-            </goals>
-            <configuration>
-              <scanIntervalSeconds>0</scanIntervalSeconds>
-              <daemon>true</daemon>
-            </configuration>
-          </execution>
-          <execution>
-            <id>stop-jetty</id>
-            <phase>post-integration-test</phase>
-            <goals>
-              <goal>stop</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-surefire-plugin</artifactId>
-        <version>2.4.3</version>
-        <configuration>
-          <skip>true</skip>
-        </configuration>
-        <executions>
-          <execution>
-            <id>integration-tests</id>
-            <phase>integration-test</phase>
-            <goals>
-              <goal>test</goal>
-            </goals>
-            <configuration>
-              <skip>false</skip>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
-</project>
diff --git a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/jetty-env.xml b/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/jetty-env.xml
deleted file mode 100644
index 2513b2c..0000000
--- a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/jetty-env.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0"?>
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
-
-<Configure class="org.mortbay.jetty.webapp.WebAppContext" />
diff --git a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/main/java/org/apache/continuum/web/startup/BuildAgentStartup.java b/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/main/java/org/apache/continuum/web/startup/BuildAgentStartup.java
deleted file mode 100644
index 86971ad..0000000
--- a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/main/java/org/apache/continuum/web/startup/BuildAgentStartup.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package org.apache.continuum.web.startup;
-
-import javax.servlet.ServletContextEvent;
-import javax.servlet.ServletContextListener;
-
-import org.codehaus.plexus.spring.PlexusToSpringUtils;
-import org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.web.context.WebApplicationContext;
-import org.springframework.web.context.support.WebApplicationContextUtils;
-
-public class BuildAgentStartup
-    implements ServletContextListener
-{
-    private Logger log = LoggerFactory.getLogger( getClass() );
-    
-    /** 
-     * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent)
-     */
-    public void contextDestroyed( ServletContextEvent sce )
-    {
-        // nothing to do here
-
-    }
-    
-    /** 
-     * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent)
-     */
-    public void contextInitialized( ServletContextEvent sce )
-    {
-        log.info( "Initializing Build Agent Task Queue Executor" );
-
-        WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext( sce
-            .getServletContext() );
-        
-        TaskQueueExecutor buildAgent = (TaskQueueExecutor) wac.getBean( PlexusToSpringUtils
-            .buildSpringId( TaskQueueExecutor.class, "build-agent" ) );
-    }
-}
diff --git a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/main/resources/META-INF/continuum/continuum-configuration.xml b/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/main/resources/META-INF/continuum/continuum-configuration.xml
deleted file mode 100644
index 90ca6fc..0000000
--- a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/main/resources/META-INF/continuum/continuum-configuration.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0"?>
-
-<!--
-  ~ 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.
-  -->
-
-<configuration>
-  <system/>
-  <jndi prefix="java:comp/env" config-optional="true"/>  
-  <xml fileName="${appserver.base}/conf/continuum-buildagent.xml" config-optional="true"
-       config-forceCreate="true" config-name="org.apache.continuum"/>
-  <xml fileName="${user.home}/.m2/continuum-buildagent.xml" config-optional="true"
-       config-forceCreate="true" config-name="org.apache.continuum.user"/>  
-</configuration>
diff --git a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/main/resources/META-INF/plexus/application.xml b/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/main/resources/META-INF/plexus/application.xml
deleted file mode 100644
index 631a021..0000000
--- a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/main/resources/META-INF/plexus/application.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!--
-  ~ 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.
-  -->
-<plexus>
-  <components>
-   
-    <!--
-     | Logger manager
-     -->
-    <component>
-      <role>org.codehaus.plexus.logging.LoggerManager</role>
-      <implementation>org.codehaus.plexus.logging.slf4j.Slf4jLoggerManager</implementation>
-      <lifecycle-handler>basic</lifecycle-handler>
-    </component>
-
-  </components>
-  
-  <lifecycle-handler-manager implementation="org.codehaus.plexus.lifecycle.DefaultLifecycleHandlerManager">
-    <default-lifecycle-handler-id>plexus</default-lifecycle-handler-id>
-    <lifecycle-handlers>
-      <lifecycle-handler implementation="org.codehaus.plexus.personality.plexus.PlexusLifecycleHandler">
-        <id>plexus</id>
-        <name>Plexus Lifecycle Handler</name>
-        <begin-segment>
-          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.LogEnablePhase"/>
-          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.CompositionPhase"/>
-          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.ContextualizePhase"/>
-          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.AutoConfigurePhase"/>
-          <phase implementation="org.codehaus.plexus.registry.RegistryConfigurePhase"/>
-          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.ServiceablePhase"/>
-          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializePhase"/>
-          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.StartPhase"/>
-        </begin-segment>
-        <suspend-segment>
-          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.SuspendPhase"/>
-        </suspend-segment>
-        <resume-segment>
-          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.ResumePhase"/>
-        </resume-segment>
-        <end-segment>
-          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.StopPhase"/>
-          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.DisposePhase"/>
-          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.LogDisablePhase"/>
-        </end-segment>
-      </lifecycle-handler>
-    </lifecycle-handlers>
-  </lifecycle-handler-manager>
-</plexus>
\ No newline at end of file
diff --git a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/main/resources/applicationContext.xml b/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/main/resources/applicationContext.xml
deleted file mode 100644
index bb28430..0000000
--- a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/main/resources/applicationContext.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
-       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xsi:schemaLocation="http://www.springframework.org/schema/beans
-           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
-
-  <bean id="masterBuildAgentTransportServer" class="org.apache.continuum.distributed.transport.master.MasterBuildAgentTransportServer"/>
-  
-  <bean id="slaveBuildAgentTransportServer" class="org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportServer">
-    <constructor-arg ref="continuumBuildAgentService"/>
-  </bean>
-
-  <bean name="xmlrpcServicesList" class="java.util.ArrayList">
-    <constructor-arg>
-      <list>
-        <ref bean="slaveBuildAgentTransportServer"/>
-        <ref bean="masterBuildAgentTransportServer"/>
-      </list>
-    </constructor-arg>
-  </bean>
-  
-</beans>
diff --git a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/main/resources/log4j.xml b/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/main/resources/log4j.xml
deleted file mode 100644
index e42a3b8..0000000
--- a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/main/resources/log4j.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
-
-<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
-  <appender name="console" class="org.apache.log4j.ConsoleAppender">
-    <param name="Target" value="System.out"/>
-    <layout class="org.apache.log4j.PatternLayout">
-      <param name="ConversionPattern" value="[%p] %-30c{1} - %m%n"/>
-    </layout>
-  </appender>
-  <logger name="org.apache.continuum.distributed">
-    <level value="info"/>
-  </logger>
-  <logger name="org.apache.continuum.buildagent">
-    <level value="info"/>
-  </logger>
-  <logger name="org.apache.continuum.web">
-    <level value="info"/>
-  </logger>
-  <logger name="org.springframework">
-    <level value="error"/>
-  </logger>
-  <root>
-    <priority value ="info" />
-    <appender-ref ref="console" />
-  </root>
-</log4j:configuration>
diff --git a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/main/webapp/WEB-INF/web.xml b/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/main/webapp/WEB-INF/web.xml
deleted file mode 100644
index bb1697d..0000000
--- a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/main/webapp/WEB-INF/web.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-<!DOCTYPE web-app PUBLIC
- "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
- "http://java.sun.com/dtd/web-app_2_3.dtd" >
-
-<web-app>
-  <display-name>Continuum Distributed Build Transport Tests</display-name>
-  
-  <listener>
-    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
-  </listener>
-  
-  <listener>
-    <!-- TODO: some Spring technique for this? -->
-  	<listener-class>org.apache.continuum.web.startup.BuildAgentStartup</listener-class>
-  </listener>
-  
-  <context-param>
-    <param-name>contextClass</param-name>
-    <param-value>org.codehaus.plexus.spring.PlexusWebApplicationContext</param-value>
-  </context-param>
-  
-  <context-param>
-    <param-name>contextConfigLocation</param-name>
-    <param-value>
-      classpath*:/META-INF/spring-context.xml
-      classpath*:/applicationContext.xml
-      classpath*:/META-INF/plexus/components.xml
-      classpath*:/META-INF/plexus/application.xml
-    </param-value>
-  </context-param>
-  
-  <servlet>
-    <servlet-name>MasterXmlRpcServlet</servlet-name>
-    <servlet-class>
-      com.atlassian.xmlrpc.spring.BinderSpringXmlRpcServlet
-    </servlet-class>
-    <init-param>
-      <param-name>serviceListBeanName</param-name>
-      <param-value>xmlrpcServicesList</param-value>
-    </init-param>
-    <init-param>
-      <param-name>enabledForExtensions</param-name>
-      <param-value>true</param-value>
-    </init-param>
-    <load-on-startup>1</load-on-startup>
-  </servlet>
-  
-  <servlet>
-    <servlet-name>SlaveXmlRpcServlet</servlet-name>
-    <servlet-class>
-      com.atlassian.xmlrpc.spring.BinderSpringXmlRpcServlet
-    </servlet-class>
-    <init-param>
-      <param-name>serviceListBeanName</param-name>
-      <param-value>xmlrpcServicesList</param-value>
-    </init-param>
-    <init-param>
-      <param-name>enabledForExtensions</param-name>
-      <param-value>true</param-value>
-    </init-param>
-    <load-on-startup>1</load-on-startup>
-  </servlet>
-  
-  <servlet-mapping>
-    <servlet-name>MasterXmlRpcServlet</servlet-name>
-    <url-pattern>/master-xmlrpc</url-pattern>
-  </servlet-mapping>
-  
-  <servlet-mapping>
-    <servlet-name>SlaveXmlRpcServlet</servlet-name>
-    <url-pattern>/slave-xmlrpc</url-pattern>
-  </servlet-mapping>
-</web-app>
diff --git a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/main/webapp/index.jsp b/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/main/webapp/index.jsp
deleted file mode 100644
index c38169b..0000000
--- a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/main/webapp/index.jsp
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body>
-<h2>Hello World!</h2>
-</body>
-</html>
diff --git a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/test/it/org/apache/continuum/distributed/transport/tests/MasterBuildAgentTransportServiceTest.java b/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/test/it/org/apache/continuum/distributed/transport/tests/MasterBuildAgentTransportServiceTest.java
deleted file mode 100644
index 2772c84..0000000
--- a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/test/it/org/apache/continuum/distributed/transport/tests/MasterBuildAgentTransportServiceTest.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.apache.continuum.distributed.transport.tests;
-
-/*
- * 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.net.URL;
-import java.util.HashMap;
-
-import junit.framework.TestCase;
-
-import org.apache.continuum.distributed.transport.master.MasterBuildAgentTransportClient;
-import org.apache.continuum.distributed.transport.master.MasterBuildAgentTransportService;
-import org.springframework.beans.factory.BeanFactory;
-import org.springframework.beans.factory.xml.XmlBeanFactory;
-import org.springframework.core.io.ClassPathResource;
-
-/**
- * MasterBuildAgentTransportServiceTest
- */
-public class MasterBuildAgentTransportServiceTest
-    extends TestCase
-{
-    private MasterBuildAgentTransportService masterProxy;
-    
-    private BeanFactory beanFactory = new XmlBeanFactory( new ClassPathResource( "applicationContext.xml" ) );
-    
-    protected void setUp()
-        throws Exception
-    {
-        super.setUp();
-        
-        masterProxy = new MasterBuildAgentTransportClient( new URL( "http://localhost:9191/master-xmlrpc"), null , null );
-    }
-    
-    public void testReturnBuildResult()
-    {
-        try
-        {
-            masterProxy.returnBuildResult( new HashMap() );
-        }
-        catch ( Exception e )
-        {
-            fail( e.getMessage() );
-        }
-    }
-    
-    public void testReturnScmResult()
-    {
-        try
-        {
-            masterProxy.returnScmResult( new HashMap() );
-        }
-        catch ( Exception e )
-        {
-            fail( e.getMessage() );
-        }
-    }
-
-    public void testPing()
-    {
-        try
-        {
-            masterProxy.ping();
-        }
-        catch ( Exception e )
-        {
-            fail( e.getMessage() );
-        }
-    }
-}
diff --git a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/test/it/org/apache/continuum/distributed/transport/tests/SlaveBuildAgentTransportServiceTest.java b/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/test/it/org/apache/continuum/distributed/transport/tests/SlaveBuildAgentTransportServiceTest.java
deleted file mode 100644
index f829a37..0000000
--- a/continuum-distributed-build/continuum-distributed-build-transport/continuum-distributed-build-transport-tests/src/test/it/org/apache/continuum/distributed/transport/tests/SlaveBuildAgentTransportServiceTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package org.apache.continuum.distributed.transport.tests;
-
-/*
- * 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.net.URL;
-import java.util.Collections;
-
-import junit.framework.TestCase;
-
-import org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportClient;
-import org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportService;
-import org.springframework.beans.factory.BeanFactory;
-import org.springframework.beans.factory.xml.XmlBeanFactory;
-import org.springframework.core.io.ClassPathResource;
-
-/**
- * SlaveBuildAgentTransportServiceTest
- */
-public class SlaveBuildAgentTransportServiceTest
-    extends TestCase
-{
-    private SlaveBuildAgentTransportService slaveProxy;
-    
-    private BeanFactory beanFactory = new XmlBeanFactory( new ClassPathResource( "applicationContext.xml" ) );
-    
-    protected void setUp()
-        throws Exception
-    {
-        super.setUp();
-        
-        slaveProxy = new SlaveBuildAgentTransportClient( new URL( "http://localhost:9191/slave-xmlrpc"), null , null );
-    }
-
-    public void testBuildProjects()
-    {
-        try
-        {
-            slaveProxy.buildProjects( Collections.EMPTY_LIST );
-        }
-        catch ( Exception e )
-        {
-            fail( e.getMessage() );
-        }
-    }
-
-    public void testGetAvailableInstallations()
-    {
-        try
-        {
-            slaveProxy.getAvailableInstallations();
-        }
-        catch ( Exception e )
-        {
-            fail( e.getMessage() );
-        }
-    }
-
-    public void testGetBuildResult()
-    {
-        try
-        {
-            slaveProxy.getBuildResult( 0 );
-        }
-        catch ( Exception e )
-        {
-            fail( e.getMessage() );
-        }
-    }
-
-    public void testGetProjectCurrentlyBuilding()
-    {
-        try
-        {
-            slaveProxy.getProjectCurrentlyBuilding();
-        }
-        catch ( Exception e )
-        {
-            fail( e.getMessage() );
-        }
-    }
-
-    public void testPing()
-    {
-        try
-        {
-            slaveProxy.ping();
-        }
-        catch ( Exception e )
-        {
-            fail( e.getMessage() );
-        }
-    }
-}
diff --git a/continuum-distributed-build/continuum-distributed-build-transport/pom.xml b/continuum-distributed-build/continuum-distributed-build-transport/pom.xml
deleted file mode 100644
index 3c1dca9..0000000
--- a/continuum-distributed-build/continuum-distributed-build-transport/pom.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <parent>
-    <artifactId>continuum-distributed-build</artifactId>
-    <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
-  </parent>
-  <modelVersion>4.0.0</modelVersion>
-  <artifactId>continuum-distributed-build-transport</artifactId>
-  <name>Continuum :: Distributed Build :: Transport</name>
-  <packaging>pom</packaging>
-  <modules>
-    <module>continuum-distributed-build-transport-master</module>
-    <module>continuum-distributed-build-transport-slave</module>
-    <!-- <module>continuum-distributed-build-transport-tests</module> -->
-  </modules>
-  <dependencies>
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-api</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-log4j12</artifactId>
-      <version>1.5.0</version>
-    </dependency>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>3.8.1</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>easymock</groupId>
-      <artifactId>easymock</artifactId>
-      <version>1.2_Java1.3</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>easymock</groupId>
-      <artifactId>easymockclassextension</artifactId>
-      <version>1.2</version>
-      <scope>test</scope>
-    </dependency>
-  </dependencies>
-</project>
diff --git a/continuum-distributed-build/pom.xml b/continuum-distributed-build/pom.xml
deleted file mode 100644
index e232937..0000000
--- a/continuum-distributed-build/pom.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<!--
-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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <parent>
-    <groupId>org.apache.continuum</groupId>
-    <artifactId>continuum</artifactId>
-    <version>1.3.1-SNAPSHOT</version>
-  </parent>
-
-  <groupId>org.apache.continuum</groupId>
-  <artifactId>continuum-distributed-build</artifactId>
-  <packaging>pom</packaging>
-  <name>Continuum :: Distributed Build</name>
-  <modules>
-    <module>continuum-buildagent</module>
-    <module>continuum-distributed-build-transport</module>
-  </modules>
-</project>
diff --git a/continuum-distributed/continuum-distributed-commons/pom.xml b/continuum-distributed/continuum-distributed-commons/pom.xml
new file mode 100644
index 0000000..a3e115c
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-commons/pom.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <artifactId>continuum-distributed</artifactId>
+    <groupId>org.apache.continuum</groupId>
+    <version>1.4.3</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>continuum-distributed-commons</artifactId>
+  <name>Continuum :: Distributed Build :: Commons</name>
+  <dependencies>
+    <dependency>
+      <groupId>com.atlassian.xmlrpc</groupId>
+      <artifactId>atlassian-xmlrpc-binder</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.atlassian.xmlrpc</groupId>
+      <artifactId>atlassian-xmlrpc-binder-support</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.xmlrpc</groupId>
+      <artifactId>xmlrpc-client</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-httpclient</groupId>
+      <artifactId>commons-httpclient</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/continuum-distributed/continuum-distributed-commons/src/main/java/org/apache/continuum/distributed/commons/utils/ContinuumDistributedUtil.java b/continuum-distributed/continuum-distributed-commons/src/main/java/org/apache/continuum/distributed/commons/utils/ContinuumDistributedUtil.java
new file mode 100644
index 0000000..627a3bd
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-commons/src/main/java/org/apache/continuum/distributed/commons/utils/ContinuumDistributedUtil.java
@@ -0,0 +1,126 @@
+package org.apache.continuum.distributed.commons.utils;
+
+/*
+ * 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.Map;
+
+/**
+ * ContinuumDistributedUtil
+ */
+public class ContinuumDistributedUtil
+{
+    public static final String KEY_PROJECT_ID = "project-id";
+
+    public static final String KEY_PROJECT_GROUP_ID = "project-group-id";
+
+    public static final String KEY_PROJECT_NAME = "project-name";
+
+    public static final String KEY_ARTIFACT_ID = "artifact-id";
+
+    public static int getProjectId( Map<String, Object> context )
+    {
+        return getInteger( context, KEY_PROJECT_ID );
+    }
+
+    public static int getProjectGroupId( Map<String, Object> context )
+    {
+        return getInteger( context, KEY_PROJECT_GROUP_ID );
+    }
+
+    public static String getArtifactId( Map<String, Object> context )
+    {
+        return getString( context, KEY_ARTIFACT_ID );
+    }
+
+    public static String getProjectName( Map<String, Object> context )
+    {
+        return getString( context, KEY_PROJECT_NAME );
+    }
+
+    public static String getProjectNameAndId( Map<String, Object> context )
+    {
+        StringBuilder result = new StringBuilder();
+
+        if ( getProjectName( context ) != null )
+        {
+            result.append( getProjectName( context ) ).append( " " );
+        }
+        else if ( getArtifactId( context ) != null )
+        {
+            result.append( getArtifactId( context ) ).append( " " );
+        }
+
+        if ( context.containsKey( KEY_PROJECT_ID ) )
+        {
+            result.append( "(projectId=" ).append( getProjectId( context ) ).append( ")" );
+        }
+        else
+        {
+            result.append( "(projectGroupId=" ).append( getProjectGroupId( context ) ).append( ")" );
+        }
+
+        return result.toString();
+    }
+
+    // ----------------------------------------------------------------------
+    //
+    // ----------------------------------------------------------------------
+
+    private static String getString( Map<String, Object> context, String key )
+    {
+        Object obj = getObject( context, key, null );
+
+        if ( obj == null )
+        {
+            return null;
+        }
+        else
+        {
+            return (String) obj;
+        }
+    }
+
+    private static int getInteger( Map<String, Object> context, String key )
+    {
+        Object obj = getObject( context, key, null );
+
+        if ( obj == null )
+        {
+            return 0;
+        }
+        else
+        {
+            return (Integer) obj;
+        }
+    }
+
+    private static Object getObject( Map<String, Object> context, String key, Object defaultValue )
+    {
+        Object value = context.get( key );
+
+        if ( value == null )
+        {
+            return defaultValue;
+        }
+
+        return value;
+    }
+}
+
diff --git a/continuum-distributed/continuum-distributed-commons/src/main/java/org/apache/continuum/distributed/commons/utils/ContinuumXmlRpcBinder.java b/continuum-distributed/continuum-distributed-commons/src/main/java/org/apache/continuum/distributed/commons/utils/ContinuumXmlRpcBinder.java
new file mode 100644
index 0000000..4782b17
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-commons/src/main/java/org/apache/continuum/distributed/commons/utils/ContinuumXmlRpcBinder.java
@@ -0,0 +1,135 @@
+package org.apache.continuum.distributed.commons.utils;
+
+/*
+ * 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 com.atlassian.xmlrpc.Binder;
+import com.atlassian.xmlrpc.BinderTypeFactory;
+import com.atlassian.xmlrpc.BindingException;
+import com.atlassian.xmlrpc.ConnectionInfo;
+import com.atlassian.xmlrpc.ServiceObject;
+import com.atlassian.xmlrpc.XmlRpcClientProvider;
+import com.atlassian.xmlrpc.XmlRpcInvocationHandler;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
+import org.apache.xmlrpc.XmlRpcException;
+import org.apache.xmlrpc.client.XmlRpcClient;
+import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
+import org.apache.xmlrpc.client.XmlRpcCommonsTransportFactory;
+
+import java.lang.reflect.Proxy;
+import java.net.URL;
+import java.util.Vector;
+
+/**
+ * Used to bind the given XML-RPC service to an instance of
+ * the given interface type.
+ *
+ * This implementation uses the Apache XML-RPC client.
+ *
+ * This is derived from ApacheBinder from the atlassian-xmlrpc-binder project. In this version, we customise the
+ * transport used for better connection management. It is thread-safe and should be reused.
+ *
+ * @author <a href="mailto:james@atlassian.com">James William Dumay</a>
+ */
+public class ContinuumXmlRpcBinder
+    implements Binder
+{
+    private final HttpClient httpClient;
+
+    private static ContinuumXmlRpcBinder binder = new ContinuumXmlRpcBinder();
+
+    private ContinuumXmlRpcBinder()
+    {
+        this.httpClient = new HttpClient( new MultiThreadedHttpConnectionManager() );
+    }
+
+    public <T> T bind( Class<T> bindClass, URL url )
+        throws BindingException
+    {
+        return bind( bindClass, url, new ConnectionInfo() );
+    }
+
+    public <T> T bind( Class<T> bindClass, URL url, ConnectionInfo connectionInfo )
+        throws BindingException
+    {
+        if ( !bindClass.isInterface() )
+        {
+            throw new BindingException( "Class " + bindClass.getName() + "is not an interface" );
+        }
+        ServiceObject serviceObject = bindClass.getAnnotation( ServiceObject.class );
+        if ( serviceObject == null )
+        {
+            throw new BindingException( "Could not find ServiceObject annotation on " + bindClass.getName() );
+        }
+        final XmlRpcClient client = getXmlRpcClient( url, connectionInfo );
+
+        XmlRpcInvocationHandler handler = new XmlRpcInvocationHandler( new XmlRpcClientProvider()
+        {
+            public Object execute( String serviceName, String methodName, Vector arguments )
+                throws BindingException
+            {
+                try
+                {
+                    return client.execute( serviceName + "." + methodName, arguments );
+                }
+                catch ( XmlRpcException e )
+                {
+                    throw new BindingException( e );
+                }
+            }
+        } );
+
+        return (T) Proxy.newProxyInstance( getClass().getClassLoader(), new Class[]{bindClass}, handler );
+    }
+
+    private XmlRpcClient getXmlRpcClient( URL url, ConnectionInfo connectionInfo )
+    {
+        XmlRpcClientConfigImpl clientConfig = new XmlRpcClientConfigImpl();
+        clientConfig.setServerURL( url );
+        clientConfig.setEnabledForExceptions( true );
+
+        if ( connectionInfo != null )
+        {
+            clientConfig.setBasicUserName( connectionInfo.getUsername() );
+            clientConfig.setBasicPassword( connectionInfo.getPassword() );
+            clientConfig.setBasicEncoding( connectionInfo.getEncoding() );
+            clientConfig.setGzipCompressing( connectionInfo.isGzip() );
+            clientConfig.setGzipRequesting( connectionInfo.isGzip() );
+            clientConfig.setReplyTimeout( connectionInfo.getTimeout() );
+            clientConfig.setConnectionTimeout( connectionInfo.getTimeout() );
+            clientConfig.setTimeZone( connectionInfo.getTimeZone() );
+        }
+
+        final XmlRpcClient client = new XmlRpcClient();
+        client.setTypeFactory( new BinderTypeFactory( client ) );
+        XmlRpcCommonsTransportFactory factory = new XmlRpcCommonsTransportFactory( client );
+        // Alternative - use simple connection manager, but make sure it closes the connection each time
+        // This would be set here since it would not be thread-safe
+//        factory.setHttpClient( new HttpClient( new SimpleHttpConnectionManager( true ) ) );
+        factory.setHttpClient( httpClient );
+        client.setConfig( clientConfig );
+        return client;
+    }
+
+    public static ContinuumXmlRpcBinder getInstance()
+    {
+        return binder;
+    }
+}
diff --git a/continuum-distributed/continuum-distributed-master/continuum-distributed-master-api/pom.xml b/continuum-distributed/continuum-distributed-master/continuum-distributed-master-api/pom.xml
new file mode 100644
index 0000000..6b049dd
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-master/continuum-distributed-master-api/pom.xml
@@ -0,0 +1,36 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <groupId>org.apache.continuum</groupId>
+    <artifactId>continuum-distributed-master</artifactId>
+    <version>1.4.3</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>continuum-distributed-master-api</artifactId>
+  <name>Continuum :: Distributed Build :: Transport :: Master :: API</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>com.atlassian.xmlrpc</groupId>
+      <artifactId>atlassian-xmlrpc-binder-annotations</artifactId>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/continuum-distributed/continuum-distributed-master/continuum-distributed-master-api/src/main/java/org/apache/continuum/distributed/transport/master/MasterBuildAgentTransportService.java b/continuum-distributed/continuum-distributed-master/continuum-distributed-master-api/src/main/java/org/apache/continuum/distributed/transport/master/MasterBuildAgentTransportService.java
new file mode 100644
index 0000000..d1d1714
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-master/continuum-distributed-master-api/src/main/java/org/apache/continuum/distributed/transport/master/MasterBuildAgentTransportService.java
@@ -0,0 +1,55 @@
+package org.apache.continuum.distributed.transport.master;
+
+/*
+ * 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 com.atlassian.xmlrpc.ServiceObject;
+
+import java.util.Map;
+
+/**
+ * MasterBuildAgentTransportService
+ */
+@ServiceObject( "MasterBuildAgentTransportService" )
+public interface MasterBuildAgentTransportService
+{
+    public Boolean returnBuildResult( Map<String, Object> buildResult, String buildAgentUrl )
+        throws Exception;
+
+    public Boolean startProjectBuild( Integer projectId, String buildAgentUrl )
+        throws Exception;
+
+    public Boolean prepareBuildFinished( Map<String, Object> prepareBuildResult, String buildAgentUrl )
+        throws Exception;
+
+    public Boolean startPrepareBuild( Map<String, Object> prepareBuildResult, String buildAgentUrl )
+        throws Exception;
+
+    public Map<String, String> getEnvironments( Integer buildDefinitionId, String installationType )
+        throws Exception;
+
+    public Boolean updateProject( Map<String, Object> project )
+        throws Exception;
+
+    public Boolean ping()
+        throws Exception;
+
+    public Boolean shouldBuild( Map<String, Object> context, String buildAgentUrl )
+        throws Exception;
+}
diff --git a/continuum-distributed/continuum-distributed-master/continuum-distributed-master-client/pom.xml b/continuum-distributed/continuum-distributed-master/continuum-distributed-master-client/pom.xml
new file mode 100644
index 0000000..27b083d
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-master/continuum-distributed-master-client/pom.xml
@@ -0,0 +1,72 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <groupId>org.apache.continuum</groupId>
+    <artifactId>continuum-distributed-master</artifactId>
+    <version>1.4.3</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>continuum-distributed-master-client</artifactId>
+  <name>Continuum :: Distributed Build :: Transport :: Master :: Client</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-distributed-master-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-distributed-commons</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.atlassian.xmlrpc</groupId>
+      <artifactId>atlassian-xmlrpc-binder</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>exec-maven-plugin</artifactId>
+        <configuration>
+          <executable>java</executable>
+          <arguments>
+            <argument>-Dmyproperty=myvalue</argument>
+            <argument>-classpath</argument>
+            <!-- automatically creates the classpath using all project dependencies, also adding the project build directory -->
+            <classpath />
+            <argument>org.apache.continuum.distributed.transport.slave.SampleBuildAgentClient</argument>
+            <argument>${url}/xmlrpc</argument>
+          </arguments>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <properties>
+    <url>http://localhost:${port}/continuum-buildagent</url>
+    <port>8181</port>
+  </properties>
+</project>
diff --git a/continuum-distributed/continuum-distributed-master/continuum-distributed-master-client/src/main/java/org/apache/continuum/distributed/transport/master/MasterBuildAgentTransportClient.java b/continuum-distributed/continuum-distributed-master/continuum-distributed-master-client/src/main/java/org/apache/continuum/distributed/transport/master/MasterBuildAgentTransportClient.java
new file mode 100644
index 0000000..f40015c
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-master/continuum-distributed-master-client/src/main/java/org/apache/continuum/distributed/transport/master/MasterBuildAgentTransportClient.java
@@ -0,0 +1,247 @@
+package org.apache.continuum.distributed.transport.master;
+
+/*
+ * 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 com.atlassian.xmlrpc.Binder;
+import com.atlassian.xmlrpc.BindingException;
+import com.atlassian.xmlrpc.ConnectionInfo;
+import org.apache.continuum.distributed.commons.utils.ContinuumDistributedUtil;
+import org.apache.continuum.distributed.commons.utils.ContinuumXmlRpcBinder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.URL;
+import java.util.Map;
+import java.util.TimeZone;
+
+/**
+ * MasterBuildAgentTransportClient
+ */
+public class MasterBuildAgentTransportClient
+    implements MasterBuildAgentTransportService
+{
+    private static final Logger log = LoggerFactory.getLogger( MasterBuildAgentTransportClient.class );
+
+    MasterBuildAgentTransportService master;
+
+    private String masterServerUrl;
+
+    public MasterBuildAgentTransportClient( URL serviceUrl )
+        throws Exception
+    {
+        this( serviceUrl, null, null );
+    }
+
+    public MasterBuildAgentTransportClient( URL serviceUrl, String login, String password )
+        throws Exception
+    {
+        Binder binder = ContinuumXmlRpcBinder.getInstance();
+
+        ConnectionInfo connectionInfo = new ConnectionInfo();
+        connectionInfo.setUsername( login );
+        connectionInfo.setPassword( password );
+        connectionInfo.setTimeZone( TimeZone.getDefault() );
+
+        this.masterServerUrl = serviceUrl.toString();
+
+        try
+        {
+            master = binder.bind( MasterBuildAgentTransportService.class, serviceUrl, connectionInfo );
+        }
+        catch ( BindingException e )
+        {
+            log.error( "Can't bind service interface " + MasterBuildAgentTransportService.class.getName() + " to " +
+                           serviceUrl.toExternalForm() + " using " + connectionInfo.getUsername() + ", " +
+                           connectionInfo.getPassword(), e );
+            throw new Exception(
+                "Can't bind service interface " + MasterBuildAgentTransportService.class.getName() + " to " +
+                    serviceUrl.toExternalForm() + " using " + connectionInfo.getUsername() + ", " +
+                    connectionInfo.getPassword(), e );
+        }
+    }
+
+    public Boolean returnBuildResult( Map<String, Object> buildResult, String buildAgentUrl )
+        throws Exception
+    {
+        Boolean result;
+        String projectInfo = ContinuumDistributedUtil.getProjectNameAndId( buildResult );
+
+        try
+        {
+            result = master.returnBuildResult( buildResult, buildAgentUrl );
+            log.info( "Build finished. Returning the build result for project {} to master {}", projectInfo,
+                      masterServerUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error(
+                "Failed to finish the build and return the build result for project " + projectInfo + " to master " +
+                    masterServerUrl, e );
+            throw new Exception(
+                "Failed to finish the build and return the build result for project " + projectInfo + " to master " +
+                    masterServerUrl, e );
+        }
+
+        return result;
+    }
+
+    public Boolean ping()
+        throws Exception
+    {
+        Boolean result;
+
+        try
+        {
+            result = master.ping();
+            log.debug( "Ping Master {} : {}", masterServerUrl, ( result ? "ok" : "failed" ) );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Ping Master " + masterServerUrl + " error", e );
+            throw new Exception( "Ping Master " + masterServerUrl + " error", e );
+        }
+
+        return result;
+    }
+
+    public Boolean prepareBuildFinished( Map<String, Object> prepareBuildResult, String buildAgentUrl )
+        throws Exception
+    {
+        Boolean result;
+        String projectInfo = ContinuumDistributedUtil.getProjectNameAndId( prepareBuildResult );
+
+        try
+        {
+            result = master.prepareBuildFinished( prepareBuildResult, buildAgentUrl );
+            log.info( "Prepare build finished for project '{}'", projectInfo );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to finish prepare build for project {}", projectInfo );
+            throw new Exception( "Failed to finish prepare build for project " + projectInfo + ".", e );
+        }
+
+        return result;
+    }
+
+    public Boolean startProjectBuild( Integer projectId, String buildAgentUrl )
+        throws Exception
+    {
+        Boolean result;
+
+        try
+        {
+            result = master.startProjectBuild( projectId, buildAgentUrl );
+            log.info( "Start project {} build", projectId );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to start build of projectId=" + projectId + " to master " + masterServerUrl, e );
+            throw new Exception( "Failed to start build of projectId=" + projectId + " to master " + masterServerUrl,
+                                 e );
+        }
+
+        return result;
+    }
+
+    public Boolean startPrepareBuild( Map<String, Object> prepareBuildResult, String buildAgentUrl )
+        throws Exception
+    {
+        Boolean result;
+        String projectInfo = ContinuumDistributedUtil.getProjectNameAndId( prepareBuildResult );
+
+        try
+        {
+            result = master.startPrepareBuild( prepareBuildResult, buildAgentUrl );
+            log.info( "Start prepare build for project {}", projectInfo );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to start prepare build for project {}", projectInfo, e );
+            throw new Exception( "Failed to start prepare build for project " + projectInfo, e );
+        }
+
+        return result;
+    }
+
+    public Map<String, String> getEnvironments( Integer buildDefinitionId, String installationType )
+        throws Exception
+    {
+        Map<String, String> result;
+        try
+        {
+            result = master.getEnvironments( buildDefinitionId, installationType );
+            log.debug( "Retrieved environments. buildDefinitionId={}, installationType={} from master {}",
+                       new Object[]{buildDefinitionId, installationType, masterServerUrl} );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to retrieve environments. buildDefinitionId=" + buildDefinitionId +
+                           ", installationType=" + installationType + " from master " + masterServerUrl, e );
+            throw new Exception( "Failed to retrieve environments. buildDefinitionId=" +
+                                     buildDefinitionId + ", installationType=" + installationType + " from master " +
+                                     masterServerUrl, e );
+        }
+
+        return result;
+    }
+
+    public Boolean updateProject( Map<String, Object> project )
+        throws Exception
+    {
+        Boolean result;
+        String projectInfo = ContinuumDistributedUtil.getProjectNameAndId( project );
+
+        try
+        {
+            result = master.updateProject( project );
+            log.debug( "Updating project {} in master {}", projectInfo, masterServerUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to update project " + projectInfo + " in master " + masterServerUrl, e );
+            throw new Exception( "Failed to update project " + projectInfo + " in master " + masterServerUrl, e );
+        }
+
+        return result;
+    }
+
+    public Boolean shouldBuild( Map<String, Object> context, String buildAgentUrl )
+        throws Exception
+    {
+        Boolean result;
+        String projectInfo = ContinuumDistributedUtil.getProjectNameAndId( context );
+
+        try
+        {
+            result = master.shouldBuild( context, buildAgentUrl );
+            log.debug( "Checking if project {} should build from master {}", projectInfo, masterServerUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to determine if project " + projectInfo + " should build from master " + masterServerUrl,
+                       e );
+            throw new Exception(
+                "Failed to determine if project " + projectInfo + " should build from master " + masterServerUrl, e );
+        }
+
+        return result;
+    }
+}
diff --git a/continuum-distributed/continuum-distributed-master/continuum-distributed-master-server/pom.xml b/continuum-distributed/continuum-distributed-master/continuum-distributed-master-server/pom.xml
new file mode 100644
index 0000000..4425b4b
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-master/continuum-distributed-master-server/pom.xml
@@ -0,0 +1,58 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <groupId>org.apache.continuum</groupId>
+    <artifactId>continuum-distributed-master</artifactId>
+    <version>1.4.3</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>continuum-distributed-master-server</artifactId>
+  <name>Continuum :: Distributed Build :: Transport :: Master :: Server</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-distributed-master-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-distributed-commons</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-api</artifactId>
+      <exclusions>
+        <exclusion>
+          <groupId>org.apache.archiva</groupId>
+          <artifactId>archiva-common</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.apache.archiva</groupId>
+          <artifactId>archiva-repository-layer</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/continuum-distributed/continuum-distributed-master/continuum-distributed-master-server/src/main/java/org/apache/continuum/distributed/transport/master/MasterBuildAgentTransportServer.java b/continuum-distributed/continuum-distributed-master/continuum-distributed-master-server/src/main/java/org/apache/continuum/distributed/transport/master/MasterBuildAgentTransportServer.java
new file mode 100644
index 0000000..0f84560
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-master/continuum-distributed-master-server/src/main/java/org/apache/continuum/distributed/transport/master/MasterBuildAgentTransportServer.java
@@ -0,0 +1,111 @@
+package org.apache.continuum.distributed.transport.master;
+
+/*
+ * 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 org.apache.continuum.builder.distributed.DistributedBuildService;
+import org.apache.continuum.distributed.commons.utils.ContinuumDistributedUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Map;
+
+/**
+ * MasterBuildAgentTransportServer
+ */
+public class MasterBuildAgentTransportServer
+    implements MasterBuildAgentTransportService
+{
+    private static final Logger log = LoggerFactory.getLogger( MasterBuildAgentTransportServer.class );
+
+    private final DistributedBuildService distributedBuildService;
+
+    public MasterBuildAgentTransportServer( DistributedBuildService distributedBuildService )
+    {
+        this.distributedBuildService = distributedBuildService;
+    }
+
+    public Boolean returnBuildResult( Map<String, Object> buildResult, String buildAgentUrl )
+        throws Exception
+    {
+        distributedBuildService.updateBuildResult( buildResult );
+        log.info( "Project {} build finished in build agent {}. Returned build result.",
+                  ContinuumDistributedUtil.getProjectNameAndId( buildResult ), buildAgentUrl );
+        return Boolean.TRUE;
+    }
+
+    public Boolean ping()
+        throws Exception
+    {
+        log.debug( "Ping master ok" );
+
+        return Boolean.TRUE;
+    }
+
+    public Boolean prepareBuildFinished( Map<String, Object> prepareBuildResult, String buildAgentUrl )
+        throws Exception
+    {
+        distributedBuildService.prepareBuildFinished( prepareBuildResult );
+        log.info( "Prepare build finished for project {} in build agent {}",
+                  ContinuumDistributedUtil.getProjectNameAndId( prepareBuildResult ), buildAgentUrl );
+        return Boolean.TRUE;
+    }
+
+    public Boolean startProjectBuild( Integer projectId, String buildAgentUrl )
+        throws Exception
+    {
+        distributedBuildService.startProjectBuild( projectId );
+        log.info( "Start building project (projectId={}) in build agent {}.", projectId, buildAgentUrl );
+        return Boolean.TRUE;
+    }
+
+    public Boolean startPrepareBuild( Map<String, Object> prepareBuildResult, String buildAgentUrl )
+        throws Exception
+    {
+        distributedBuildService.startPrepareBuild( prepareBuildResult );
+        log.info( "Start preparing build of project {} in build agent {}", ContinuumDistributedUtil.getProjectNameAndId(
+            prepareBuildResult ), buildAgentUrl );
+        return Boolean.TRUE;
+    }
+
+    public Map<String, String> getEnvironments( Integer buildDefinitionId, String installationType )
+        throws Exception
+    {
+        Map<String, String> envs = distributedBuildService.getEnvironments( buildDefinitionId, installationType );
+        log.debug( "Retrieving environments buildDefinitionId={}, installationType={}",
+                   new Object[]{buildDefinitionId, installationType} );
+        return envs;
+    }
+
+    public Boolean updateProject( Map<String, Object> project )
+        throws Exception
+    {
+        distributedBuildService.updateProject( project );
+        log.debug( "Start updating project {}", ContinuumDistributedUtil.getProjectNameAndId( project ) );
+        return Boolean.TRUE;
+    }
+
+    public Boolean shouldBuild( Map<String, Object> context, String buildAgentUrl )
+        throws Exception
+    {
+        log.debug( "Checking if project {} should build in build agent {}",
+                   ContinuumDistributedUtil.getProjectNameAndId( context ), buildAgentUrl );
+        return distributedBuildService.shouldBuild( context );
+    }
+}
diff --git a/continuum-distributed/continuum-distributed-master/pom.xml b/continuum-distributed/continuum-distributed-master/pom.xml
new file mode 100644
index 0000000..d7fcae7
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-master/pom.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <artifactId>continuum-distributed</artifactId>
+    <groupId>org.apache.continuum</groupId>
+    <version>1.4.3</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>continuum-distributed-master</artifactId>
+  <name>Continuum :: Distributed Build :: Transport :: Master</name>
+  <packaging>pom</packaging>
+  <modules>
+    <module>continuum-distributed-master-api</module>
+    <module>continuum-distributed-master-server</module>
+    <module>continuum-distributed-master-client</module>
+  </modules>
+</project>
diff --git a/continuum-distributed/continuum-distributed-slave/continuum-distributed-slave-api/pom.xml b/continuum-distributed/continuum-distributed-slave/continuum-distributed-slave-api/pom.xml
new file mode 100644
index 0000000..5577359
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-slave/continuum-distributed-slave-api/pom.xml
@@ -0,0 +1,36 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <groupId>org.apache.continuum</groupId>
+    <artifactId>continuum-distributed-slave</artifactId>
+    <version>1.4.3</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>continuum-distributed-slave-api</artifactId>
+  <name>Continuum :: Distributed Build :: Transport :: Slave :: API</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>com.atlassian.xmlrpc</groupId>
+      <artifactId>atlassian-xmlrpc-binder-annotations</artifactId>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/continuum-distributed/continuum-distributed-slave/continuum-distributed-slave-api/src/main/java/org/apache/continuum/distributed/transport/slave/SlaveBuildAgentTransportService.java b/continuum-distributed/continuum-distributed-slave/continuum-distributed-slave-api/src/main/java/org/apache/continuum/distributed/transport/slave/SlaveBuildAgentTransportService.java
new file mode 100644
index 0000000..ff67ea0
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-slave/continuum-distributed-slave-api/src/main/java/org/apache/continuum/distributed/transport/slave/SlaveBuildAgentTransportService.java
@@ -0,0 +1,169 @@
+package org.apache.continuum.distributed.transport.slave;
+
+/*
+ * 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 com.atlassian.xmlrpc.ServiceObject;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * SlaveBuildAgentTransportService
+ */
+@ServiceObject( "SlaveBuildAgentTransportService" )
+public interface SlaveBuildAgentTransportService
+{
+    public Boolean buildProjects( List<Map<String, Object>> projectsBuildContext )
+        throws Exception;
+
+    public Map<String, Object> getBuildResult( int projectId )
+        throws Exception;
+
+    public Map<String, Object> getProjectCurrentlyBuilding()
+        throws Exception;
+
+    public List<Map<String, String>> getAvailableInstallations()
+        throws Exception;
+
+    public Boolean ping()
+        throws Exception;
+
+    public Boolean cancelBuild()
+        throws Exception;
+
+    public String generateWorkingCopyContent( int projectId, String directory, String baseUrl, String imagesBaseUrl )
+        throws Exception;
+
+    public Map<String, Object> getProjectFile( int projectId, String directory, String filename )
+        throws Exception;
+
+    public Map getReleasePluginParameters( int projectId, String pomFilename )
+        throws Exception;
+
+    public List<Map<String, String>> processProject( int projectId, String pomFilename, boolean autoVersionSubmodules )
+        throws Exception;
+
+    public String releasePrepare( Map project, Properties properties, Map releaseVersion, Map developmentVersion,
+                                  Map environments, String username )
+        throws Exception;
+
+    public Map<String, Object> getReleaseResult( String releaseId )
+        throws Exception;
+
+    public Map<String, Object> getListener( String releaseId )
+        throws Exception;
+
+    public Boolean removeListener( String releaseId )
+        throws Exception;
+
+    public String getPreparedReleaseName( String releaseId )
+        throws Exception;
+
+    public Boolean releasePerform( String releaseId, String goals, String arguments, boolean useReleaseProfile,
+                                   Map repository, String username )
+        throws Exception;
+
+    public String releasePerformFromScm( String goals, String arguments, boolean useReleaseProfile, Map repository,
+                                         String scmUrl, String scmUsername, String scmPassword, String scmTag,
+                                         String scmTagBase, Map environments, String username )
+        throws Exception;
+
+    public String releaseCleanup( String releaseId )
+        throws Exception;
+
+    public Boolean releaseRollback( String releaseId, int projectId )
+        throws Exception;
+
+    public Integer getBuildSizeOfAgent()
+        throws Exception;
+
+    public List<Map<String, Object>> getProjectsInPrepareBuildQueue()
+        throws Exception;
+
+    public List<Map<String, Object>> getProjectsAndBuildDefinitionsInPrepareBuildQueue()
+        throws Exception;
+
+    public List<Map<String, Object>> getProjectsInBuildQueue()
+        throws Exception;
+
+    public Map<String, Object> getProjectCurrentlyPreparingBuild()
+        throws Exception;
+
+    public List<Map<String, Object>> getProjectsAndBuildDefinitionsCurrentlyPreparingBuild()
+        throws Exception;
+
+    public Boolean isProjectGroupInQueue( int projectGroupId )
+        throws Exception;
+
+    public Boolean isProjectScmRootInQueue( int projectScmRootId, List<Integer> projectIds )
+        throws Exception;
+
+    public Boolean isProjectCurrentlyBuilding( int projectId, int buildDefinitionId )
+        throws Exception;
+
+    public Boolean isProjectInBuildQueue( int projectId, int buildDefinitionId )
+        throws Exception;
+
+    public Boolean isProjectCurrentlyPreparingBuild( int projectId, int buildDefinitionId )
+        throws Exception;
+
+    public Boolean isProjectInPrepareBuildQueue( int projectId, int buildDefinitionId )
+        throws Exception;
+
+    public Boolean isProjectGroupInPrepareBuildQueue( int projectGroupId )
+        throws Exception;
+
+    public Boolean isProjectGroupCurrentlyPreparingBuild( int projectGroupId )
+        throws Exception;
+
+    public Boolean removeFromPrepareBuildQueue( int projectGroupId, int scmRootId )
+        throws Exception;
+
+    public Boolean removeFromPrepareBuildQueue( List<String> hashCodes )
+        throws Exception;
+
+    public Boolean removeFromBuildQueue( int projectId, int buildDefinitionId )
+        throws Exception;
+
+    public Boolean removeFromBuildQueue( List<String> hashCodes )
+        throws Exception;
+
+    /**
+     * Get build agent's platform.
+     *
+     * @return The operating system name of the build agent
+     * @throws Exception
+     */
+    public String getBuildAgentPlatform()
+        throws Exception;
+
+    /**
+     * Execute a directory purge on the build agent
+     *
+     * @param directoryType  valid types are <i>working</i> and <i>releases</i>
+     * @param daysOlder      days older
+     * @param retentionCount retention count
+     * @param deleteAll      delete all flag
+     * @throws Exception error that will occur during the purge
+     */
+    public void executeDirectoryPurge( String directoryType, int daysOlder, int retentionCount, boolean deleteAll )
+        throws Exception;
+}
diff --git a/continuum-distributed/continuum-distributed-slave/continuum-distributed-slave-client/pom.xml b/continuum-distributed/continuum-distributed-slave/continuum-distributed-slave-client/pom.xml
new file mode 100644
index 0000000..570bffb
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-slave/continuum-distributed-slave-client/pom.xml
@@ -0,0 +1,67 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <groupId>org.apache.continuum</groupId>
+    <artifactId>continuum-distributed-slave</artifactId>
+    <version>1.4.3</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>continuum-distributed-slave-client</artifactId>
+  <name>Continuum :: Distributed Build :: Transport :: Slave :: Client</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-distributed-commons</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-distributed-slave-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.atlassian.xmlrpc</groupId>
+      <artifactId>atlassian-xmlrpc-binder</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>exec-maven-plugin</artifactId>
+        <configuration>
+          <executable>java</executable>
+          <mainClass>org.apache.continuum.distributed.transport.slave.SampleBuildAgentClient</mainClass>
+          <arguments>
+            <argument>${url}/xmlrpc</argument>
+          </arguments>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <properties>
+    <url>http://localhost:${port}/continuum-buildagent</url>
+    <port>8181</port>
+  </properties>
+</project>
diff --git a/continuum-distributed/continuum-distributed-slave/continuum-distributed-slave-client/src/main/java/org/apache/continuum/distributed/transport/slave/SampleBuildAgentClient.java b/continuum-distributed/continuum-distributed-slave/continuum-distributed-slave-client/src/main/java/org/apache/continuum/distributed/transport/slave/SampleBuildAgentClient.java
new file mode 100644
index 0000000..96ab2a5
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-slave/continuum-distributed-slave-client/src/main/java/org/apache/continuum/distributed/transport/slave/SampleBuildAgentClient.java
@@ -0,0 +1,46 @@
+package org.apache.continuum.distributed.transport.slave;
+
+/*
+ * 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.net.MalformedURLException;
+import java.net.URL;
+
+public class SampleBuildAgentClient
+{
+
+    public static void main( String[] args )
+        throws Exception
+    {
+        try
+        {
+            SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( args[0] ) );
+            client.ping();
+            System.out.println( client.getBuildAgentPlatform() );
+        }
+        catch ( MalformedURLException e )
+        {
+            System.out.println( "Invalid Url." + e );
+        }
+        catch ( Exception e )
+        {
+            System.out.println( "build agent is un reachable. " + e );
+        }
+    }
+}
diff --git a/continuum-distributed/continuum-distributed-slave/continuum-distributed-slave-client/src/main/java/org/apache/continuum/distributed/transport/slave/SlaveBuildAgentTransportClient.java b/continuum-distributed/continuum-distributed-slave/continuum-distributed-slave-client/src/main/java/org/apache/continuum/distributed/transport/slave/SlaveBuildAgentTransportClient.java
new file mode 100644
index 0000000..5070dc4
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-slave/continuum-distributed-slave-client/src/main/java/org/apache/continuum/distributed/transport/slave/SlaveBuildAgentTransportClient.java
@@ -0,0 +1,890 @@
+package org.apache.continuum.distributed.transport.slave;
+
+/*
+ * 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 com.atlassian.xmlrpc.Binder;
+import com.atlassian.xmlrpc.BindingException;
+import com.atlassian.xmlrpc.ConnectionInfo;
+import org.apache.continuum.distributed.commons.utils.ContinuumXmlRpcBinder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.TimeZone;
+
+/**
+ * SlaveBuildAgentTransportClient
+ */
+public class SlaveBuildAgentTransportClient
+    implements SlaveBuildAgentTransportService
+{
+    private static final Logger log = LoggerFactory.getLogger( SlaveBuildAgentTransportClient.class );
+
+    private SlaveBuildAgentTransportService slave;
+
+    private String buildAgentUrl;
+
+    public SlaveBuildAgentTransportClient( URL serviceUrl )
+        throws Exception
+    {
+        this( serviceUrl, null, null );
+    }
+
+    public SlaveBuildAgentTransportClient( URL serviceUrl, String login, String password )
+        throws Exception
+    {
+        Binder binder = ContinuumXmlRpcBinder.getInstance();
+
+        ConnectionInfo connectionInfo = new ConnectionInfo();
+        connectionInfo.setUsername( login );
+        connectionInfo.setPassword( password );
+        connectionInfo.setTimeZone( TimeZone.getDefault() );
+
+        buildAgentUrl = serviceUrl.toString();
+
+        try
+        {
+            slave = binder.bind( SlaveBuildAgentTransportService.class, serviceUrl, connectionInfo );
+        }
+        catch ( BindingException e )
+        {
+            log.error( "Can't bind service interface " + SlaveBuildAgentTransportService.class.getName() + " to " +
+                           serviceUrl.toExternalForm() + " using " + connectionInfo.getUsername() + ", " +
+                           connectionInfo.getPassword(), e );
+            throw new Exception(
+                "Can't bind service interface " + SlaveBuildAgentTransportService.class.getName() + " to " +
+                    serviceUrl.toExternalForm() + " using " + connectionInfo.getUsername() + ", " +
+                    connectionInfo.getPassword(), e );
+        }
+    }
+
+    public Boolean buildProjects( List<Map<String, Object>> projectsBuildContext )
+        throws Exception
+    {
+        Boolean result;
+
+        try
+        {
+            result = slave.buildProjects( projectsBuildContext );
+            log.debug( "Building projects in build agent {}", buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to build projects in build agent " + buildAgentUrl, e );
+            log.error( "Context: " + projectsBuildContext );
+            throw new Exception( "Failed to build projects in build agent " + buildAgentUrl, e );
+        }
+
+        return result;
+    }
+
+    public List<Map<String, String>> getAvailableInstallations()
+        throws Exception
+    {
+        List<Map<String, String>> installations;
+
+        try
+        {
+            installations = slave.getAvailableInstallations();
+            log.debug( "Available installations in build agent {} : {}", buildAgentUrl, installations.size() );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to get available installations in build agent " + buildAgentUrl, e );
+            throw new Exception( "Failed to get available installations in build agent " + buildAgentUrl, e );
+        }
+
+        return installations;
+    }
+
+    public Map<String, Object> getBuildResult( int projectId )
+        throws Exception
+    {
+        Map<String, Object> buildResult;
+
+        try
+        {
+            buildResult = slave.getBuildResult( projectId );
+            log.debug( "Build result for project '{}' acquired from build agent {}", projectId, buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to get build result for project '" + projectId + "' in build agent " + buildAgentUrl,
+                       e );
+            throw new Exception(
+                "Failed to get build result for project '" + projectId + "' in build agent " + buildAgentUrl, e );
+        }
+
+        return buildResult;
+    }
+
+    public Map<String, Object> getProjectCurrentlyBuilding()
+        throws Exception
+    {
+        Map<String, Object> map;
+
+        try
+        {
+            map = slave.getProjectCurrentlyBuilding();
+            log.debug( "Retrieving currently building project in build agent {}", buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to get the currently building project in build agent " + buildAgentUrl, e );
+            throw new Exception( "Failed to get the currently building project in build agent " + buildAgentUrl, e );
+        }
+
+        return map;
+    }
+
+    public Boolean ping()
+        throws Exception
+    {
+        Boolean result;
+
+        try
+        {
+            result = slave.ping();
+            log.debug( "Ping build agent {} : {}", buildAgentUrl, ( result ? "ok" : "failed" ) );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Ping build agent " + buildAgentUrl + " error", e );
+            throw new Exception( "Ping build agent " + buildAgentUrl + " error", e );
+        }
+
+        return result;
+    }
+
+    public Boolean cancelBuild()
+        throws Exception
+    {
+        Boolean result;
+
+        try
+        {
+            result = slave.cancelBuild();
+            log.debug( "Cancelled current build in build agent {}", buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Error cancelling current build in build agent " + buildAgentUrl, e );
+            throw new Exception( "Error cancelling current build in build agent " + buildAgentUrl, e );
+        }
+
+        return result;
+    }
+
+    public String generateWorkingCopyContent( int projectId, String directory, String baseUrl, String imagesBaseUrl )
+        throws Exception
+    {
+        String result;
+
+        try
+        {
+            result = slave.generateWorkingCopyContent( projectId, directory, baseUrl, imagesBaseUrl );
+            log.debug( "Generated working copy content for project '{}' in build agent ", projectId, buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error(
+                "Error generating working copy content for project '" + projectId + "' in build agent " + buildAgentUrl,
+                e );
+            throw new Exception(
+                "Error generating working copy content for project '" + projectId + "' in build agent " + buildAgentUrl,
+                e );
+        }
+
+        return result;
+    }
+
+    public Map<String, Object> getProjectFile( int projectId, String directory, String filename )
+        throws Exception
+    {
+        Map<String, Object> result;
+
+        try
+        {
+            result = slave.getProjectFile( projectId, directory, filename );
+            log.debug( "Retrieved project '{}' file content from build agent {}", projectId, buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Error retrieving project '" + projectId + "' file content from build agent " + buildAgentUrl,
+                       e );
+            throw new Exception(
+                "Error retrieving project '" + projectId + "' file content from build agent " + buildAgentUrl, e );
+        }
+
+        return result;
+    }
+
+    public Map getReleasePluginParameters( int projectId, String pomFilename )
+        throws Exception
+    {
+        Map result;
+
+        try
+        {
+            result = slave.getReleasePluginParameters( projectId, pomFilename );
+            log.debug( "Retrieving release plugin parameters for project '{}' from build agent {}", projectId,
+                       buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Error retrieving release plugin parameters for project '" + projectId + "' from build agent " +
+                           buildAgentUrl, e );
+            throw new Exception(
+                "Error retrieving release plugin parameters for project '" + projectId + "' from build agent " +
+                    buildAgentUrl, e );
+        }
+
+        return result;
+    }
+
+    public List<Map<String, String>> processProject( int projectId, String pomFilename, boolean autoVersionSubmodules )
+        throws Exception
+    {
+        List<Map<String, String>> result;
+
+        try
+        {
+            result = slave.processProject( projectId, pomFilename, autoVersionSubmodules );
+            log.debug( "Processing project '{}' in build agent ", projectId, buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Error processing project '" + projectId + "' in build agent " + buildAgentUrl, e );
+            throw new Exception( "Error processing project '" + projectId + "' in build agent " + buildAgentUrl, e );
+        }
+
+        return result;
+    }
+
+    public String releasePrepare( Map project, Properties properties, Map releaseVersion, Map developmentVersion,
+                                  Map environments, String username )
+        throws Exception
+    {
+        String releaseId;
+
+        try
+        {
+            releaseId = slave.releasePrepare( project, properties, releaseVersion, developmentVersion, environments,
+                                              username );
+            log.debug( "Preparing release '{}' in build agent {}", releaseId, buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Error while preparing release in build agent " + buildAgentUrl, e );
+            throw new Exception( "Error while preparing release in build agent " + buildAgentUrl, e );
+        }
+
+        return releaseId;
+    }
+
+    public Map<String, Object> getReleaseResult( String releaseId )
+        throws Exception
+    {
+        Map<String, Object> result;
+
+        try
+        {
+            result = slave.getReleaseResult( releaseId );
+            log.debug( "Retrieving release result, releaseId={} from build agent {}", releaseId, buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Error retrieving release result, releaseId=" + releaseId + " from build agent " + buildAgentUrl,
+                       e );
+            throw new Exception(
+                "Error retrieving release result, releaseId=" + releaseId + " from build agent " + buildAgentUrl, e );
+        }
+
+        return result;
+    }
+
+    public Map<String, Object>  getListener( String releaseId )
+        throws Exception
+    {
+        Map<String, Object> result;
+
+        try
+        {
+            result = slave.getListener( releaseId );
+            log.debug( "Retrieving listener for releaseId={} from build agent {}", releaseId, buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Error retrieving listener for releaseId=" + releaseId + " from build agent " + buildAgentUrl,
+                       e );
+            throw new Exception(
+                "Error retrieving listener for releaseId=" + releaseId + " from build agent " + buildAgentUrl, e );
+        }
+
+        return result;
+    }
+
+    public Boolean removeListener( String releaseId )
+        throws Exception
+    {
+        Boolean result;
+
+        try
+        {
+            slave.removeListener( releaseId );
+            result = Boolean.FALSE;
+            log.debug( "Removing listener for releaseId={} from build agent {}", releaseId, buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Error removing listener for releaseId=" + releaseId + " from build agent " + buildAgentUrl, e );
+            throw new Exception(
+                "Error removing listener for releaseId=" + releaseId + " from build agent " + buildAgentUrl, e );
+        }
+
+        return result;
+    }
+
+    public String getPreparedReleaseName( String releaseId )
+        throws Exception
+    {
+        String result;
+
+        try
+        {
+            result = slave.getPreparedReleaseName( releaseId );
+            log.debug( "Retrieving prepared release name, releaseId={} from build agent {}", releaseId, buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Error while retrieving prepared release name, releaseId=" + releaseId + " from build agent " +
+                           buildAgentUrl, e );
+            throw new Exception(
+                "Error while retrieving prepared release name, releaseId=" + releaseId + " from build agent " +
+                    buildAgentUrl, e );
+        }
+
+        return result;
+    }
+
+    public Boolean releasePerform( String releaseId, String goals, String arguments, boolean useReleaseProfile,
+                                   Map repository, String username )
+        throws Exception
+    {
+        Boolean result;
+
+        try
+        {
+            slave.releasePerform( releaseId, goals, arguments, useReleaseProfile, repository, username );
+            result = Boolean.FALSE;
+            log.debug( "Performing release of releaseId={} from build agent {}", releaseId, buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Error performing release of releaseId=" + releaseId + " from build agent " + buildAgentUrl, e );
+            throw new Exception(
+                "Error performing release of releaseId=" + releaseId + " from build agent " + buildAgentUrl, e );
+        }
+
+        return result;
+    }
+
+    public String releasePerformFromScm( String goals, String arguments, boolean useReleaseProfile, Map repository,
+                                         String scmUrl, String scmUsername, String scmPassword, String scmTag,
+                                         String scmTagBase, Map environments, String username )
+        throws Exception
+    {
+        String result;
+
+        try
+        {
+            result = slave.releasePerformFromScm( goals, arguments, useReleaseProfile, repository, scmUrl, scmUsername,
+                                                  scmPassword, scmTag, scmTagBase, environments, username );
+            log.debug( "Performing release of scmUrl={} from build agent {}", scmUrl, buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Error performing release from scm '" + scmUrl + "' from build agent " + buildAgentUrl, e );
+            throw new Exception( "Error performing release from scm '" + scmUrl + "' from build agent " + buildAgentUrl,
+                                 e );
+        }
+
+        return result;
+    }
+
+    public String releaseCleanup( String releaseId )
+        throws Exception
+    {
+        String result;
+
+        try
+        {
+            result = slave.releaseCleanup( releaseId );
+            log.debug( "Cleanup release, releaseId={} from build agent {}", releaseId, buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Error cleaning up release, releaseId=" + releaseId + " from build agent " + buildAgentUrl, e );
+            throw new Exception(
+                "Error cleaning up release, releaseId=" + releaseId + " from build agent " + buildAgentUrl, e );
+        }
+
+        return result;
+    }
+
+    public Boolean releaseRollback( String releaseId, int projectId )
+        throws Exception
+    {
+        Boolean result;
+
+        try
+        {
+            slave.releaseRollback( releaseId, projectId );
+            result = Boolean.TRUE;
+            log.debug( "Rollback release. releaseId={}, projectId={} from build agent {}",
+                       new Object[]{releaseId, projectId, buildAgentUrl} );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to rollback release. releaseId=" + releaseId + ", projectId=" + projectId +
+                           " from build agent " + buildAgentUrl, e );
+            throw (Exception) e.getCause().getCause().getCause().getCause();
+        }
+
+        return result;
+    }
+
+    public Integer getBuildSizeOfAgent()
+        throws Exception
+    {
+        Integer size;
+
+        try
+        {
+            size = slave.getBuildSizeOfAgent();
+            log.debug( "Retrieving build size of build agent {}", buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to retrieve build size of build agent " + buildAgentUrl, e );
+            throw new Exception( "Failed to retrieve build size of build agent " + buildAgentUrl, e );
+        }
+
+        return size;
+    }
+
+    public Map<String, Object> getProjectCurrentlyPreparingBuild()
+        throws Exception
+    {
+        Map<String, Object> projects;
+
+        try
+        {
+            projects = slave.getProjectCurrentlyPreparingBuild();
+            log.debug( "Retrieving projects currently preparing build in build agent {}", buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to retrieve projects currently preparing build in build agent " + buildAgentUrl, e );
+            throw new Exception(
+                "Failed to retrieve projects currently preparing build in build agent " + buildAgentUrl, e );
+        }
+
+        return projects;
+    }
+
+    public List<Map<String, Object>> getProjectsAndBuildDefinitionsCurrentlyPreparingBuild()
+        throws Exception
+    {
+        List<Map<String, Object>> projects;
+
+        try
+        {
+            projects = slave.getProjectsAndBuildDefinitionsCurrentlyPreparingBuild();
+            log.debug( "Retrieving projects currently preparing build in build agent {}", buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to retrieve projects currently preparing build in build agent " + buildAgentUrl, e );
+            throw new Exception(
+                "Failed to retrieve projects currently preparing build in build agent " + buildAgentUrl, e );
+        }
+
+        return projects;
+    }
+
+    public List<Map<String, Object>> getProjectsInBuildQueue()
+        throws Exception
+    {
+        List<Map<String, Object>> projects;
+
+        try
+        {
+            projects = slave.getProjectsInBuildQueue();
+            log.debug( "Retrieving projects in build queue of build agent {}", buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to retrieve projects in build queue of build agent " + buildAgentUrl, e );
+            throw new Exception( "Failed to retrieve projects in build queue of build agent " + buildAgentUrl, e );
+        }
+
+        return projects;
+    }
+
+    public List<Map<String, Object>> getProjectsInPrepareBuildQueue()
+        throws Exception
+    {
+        List<Map<String, Object>> projects;
+
+        try
+        {
+            projects = slave.getProjectsInPrepareBuildQueue();
+            log.debug( "Retrieving projects in prepare build queue of build agent {}", buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to retrieve projects in prepare build queue of build agent " + buildAgentUrl, e );
+            throw new Exception( "Failed to retrieve projects in prepare build queue of build agent " + buildAgentUrl,
+                                 e );
+        }
+
+        return projects;
+    }
+
+    public List<Map<String, Object>> getProjectsAndBuildDefinitionsInPrepareBuildQueue()
+        throws Exception
+    {
+        List<Map<String, Object>> projects;
+
+        try
+        {
+            projects = slave.getProjectsAndBuildDefinitionsInPrepareBuildQueue();
+            log.debug( "Retrieving projects in prepare build queue of build agent {}", buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to retrieve projects in prepare build queue of build agent " + buildAgentUrl, e );
+            throw new Exception( "Failed to retrieve projects in prepare build queue of build agent " + buildAgentUrl,
+                                 e );
+        }
+
+        return projects;
+    }
+
+    public Boolean isProjectGroupInQueue( int projectGroupId )
+        throws Exception
+    {
+        Boolean result;
+
+        try
+        {
+            result = slave.isProjectGroupInQueue( projectGroupId );
+            log.debug( "Checking if project group '{}' is in queue in build agent {}", projectGroupId, buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error(
+                "Failed to check if project group '" + projectGroupId + "' is in queue in build agent " + buildAgentUrl,
+                e );
+            throw new Exception(
+                "Failed to check if project group '" + projectGroupId + "' is in queue in build agent " + buildAgentUrl,
+                e );
+        }
+
+        return result;
+    }
+
+    public Boolean isProjectScmRootInQueue( int projectScmRootId, List<Integer> projectIds )
+        throws Exception
+    {
+        Boolean result;
+
+        try
+        {
+            result = slave.isProjectScmRootInQueue( projectScmRootId, projectIds );
+            log.debug( "Checking if project scm root '{}' is in queue in build agent {}", projectScmRootId,
+                       buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to check if project scm root '" + projectScmRootId + "' is in queue in build agent " +
+                           buildAgentUrl, e );
+            throw new Exception(
+                "Failed to check if project scm root '" + projectScmRootId + "' is in queue in build agent " +
+                    buildAgentUrl, e );
+        }
+
+        return result;
+    }
+
+    public Boolean isProjectCurrentlyBuilding( int projectId, int buildDefinitionId )
+        throws Exception
+    {
+        Boolean result;
+
+        try
+        {
+            result = slave.isProjectCurrentlyBuilding( projectId, buildDefinitionId );
+            log.debug( "Checking if projectId={}, buildDefinitionId={} is currently building in build agent {}",
+                       new Object[]{projectId, buildDefinitionId, buildAgentUrl} );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to check if projectId=" + projectId + ", buildDefinitionId=" + buildDefinitionId +
+                           " is currently building in build agent " + buildAgentUrl, e );
+            throw new Exception(
+                "Failed to check if projectId=" + projectId + ", buildDefinitionId=" + buildDefinitionId +
+                    " is currently building in build agent " + buildAgentUrl, e );
+        }
+
+        return result;
+    }
+
+    public Boolean isProjectInBuildQueue( int projectId, int buildDefinitionId )
+        throws Exception
+    {
+        Boolean result;
+
+        try
+        {
+            result = slave.isProjectInBuildQueue( projectId, buildDefinitionId );
+            log.debug( "Checking if projectId={}, buildDefinitionId={} is in build queue of build agent {}",
+                       new Object[]{projectId, buildDefinitionId, buildAgentUrl} );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to check if projectId=" + projectId + ", buildDefinitionId=" + buildDefinitionId +
+                           " is in build queue of build agent " + buildAgentUrl, e );
+            throw new Exception(
+                "Failed to check if projectId=" + projectId + ", buildDefinitionId=" + buildDefinitionId +
+                    " is in build queue of build agent " + buildAgentUrl, e );
+        }
+
+        return result;
+    }
+
+    public Boolean isProjectCurrentlyPreparingBuild( int projectId, int buildDefinitionId )
+        throws Exception
+    {
+        Boolean result;
+
+        try
+        {
+            result = slave.isProjectCurrentlyPreparingBuild( projectId, buildDefinitionId );
+            log.debug( "Checking if projectId={}, buildDefinitionId={} is currently preparing build in build agent {}",
+                       new Object[]{projectId, buildDefinitionId, buildAgentUrl} );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to check if projectId=" + projectId + ", buildDefinitionId=" + buildDefinitionId +
+                           " is currently preparing build in build agent " + buildAgentUrl, e );
+            throw new Exception(
+                "Failed to check if projectId=" + projectId + ", buildDefinitionId=" + buildDefinitionId +
+                    " is currently preparing build in build agent " + buildAgentUrl, e );
+        }
+
+        return result;
+    }
+
+    public Boolean isProjectInPrepareBuildQueue( int projectId, int buildDefinitionId )
+        throws Exception
+    {
+        Boolean result;
+
+        try
+        {
+            result = slave.isProjectInPrepareBuildQueue( projectId, buildDefinitionId );
+            log.debug( "Checking if projectId={}, buildDefinitionId={} is in prepare build queue of build agent {}",
+                       new Object[]{projectId, buildDefinitionId, buildAgentUrl} );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to check if projectId=" + projectId + ", buildDefinitionId=" + buildDefinitionId +
+                           " is in prepare build queue of build agent " + buildAgentUrl, e );
+            throw new Exception(
+                "Failed to check if projectId=" + projectId + ", buildDefinitionId=" + buildDefinitionId +
+                    " is in prepare build queue of build agent " + buildAgentUrl, e );
+        }
+
+        return result;
+    }
+
+    public Boolean isProjectGroupInPrepareBuildQueue( int projectGroupId )
+        throws Exception
+    {
+        Boolean result;
+
+        try
+        {
+            result = slave.isProjectGroupInPrepareBuildQueue( projectGroupId );
+            log.debug( "Checking if projectGroup {} is in prepare build queue of build agent {}", projectGroupId,
+                       buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error(
+                "Failed to check if projectGroup " + projectGroupId + " is in prepare build queue of build agent " +
+                    buildAgentUrl, e );
+            throw new Exception(
+                "Failed to check if projectGroup " + projectGroupId + " is in prepare build queue of build agent " +
+                    buildAgentUrl, e );
+        }
+
+        return result;
+    }
+
+    public Boolean isProjectGroupCurrentlyPreparingBuild( int projectGroupId )
+        throws Exception
+    {
+        Boolean result;
+
+        try
+        {
+            result = slave.isProjectGroupCurrentlyPreparingBuild( projectGroupId );
+            log.debug( "Checking if projectGroup {} is currently preparing build in build agent {}", projectGroupId,
+                       buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error(
+                "Failed to check if projectGroup " + projectGroupId + " is currently preparing build in build agent " +
+                    buildAgentUrl, e );
+            throw new Exception(
+                "Failed to check if projectGroup " + projectGroupId + " is currently preparing build in build agent " +
+                    buildAgentUrl, e );
+        }
+
+        return result;
+    }
+
+    public Boolean removeFromPrepareBuildQueue( int projectGroupId, int scmRootId )
+        throws Exception
+    {
+        Boolean result;
+
+        try
+        {
+            result = slave.removeFromPrepareBuildQueue( projectGroupId, scmRootId );
+            log.debug( "Remove projects from prepare build queue of build agent {}. projectGroupId={}, scmRootId={}",
+                       new Object[]{buildAgentUrl, projectGroupId, scmRootId} );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to remove projects from prepare build queue of build agent " + buildAgentUrl +
+                           ". projectGroupId=" + projectGroupId +
+                           ", scmRootId=" + scmRootId, e );
+            throw new Exception(
+                "Failed to remove from prepare build queue of build agent " + buildAgentUrl + ". projectGroupId=" +
+                    projectGroupId +
+                    " scmRootId=" + scmRootId, e );
+        }
+
+        return result;
+    }
+
+    public Boolean removeFromPrepareBuildQueue( List<String> hashCodes )
+        throws Exception
+    {
+        Boolean result;
+
+        try
+        {
+            result = slave.removeFromPrepareBuildQueue( hashCodes );
+            log.debug( "Removing projects from prepare build queue of build agent {}", buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to remove projects from prepare build queue of build agent " + buildAgentUrl, e );
+            throw new Exception( "Failed to remove projects from prepare build queue of build agent " + buildAgentUrl,
+                                 e );
+        }
+
+        return result;
+    }
+
+    public Boolean removeFromBuildQueue( int projectId, int buildDefinitionId )
+        throws Exception
+    {
+        Boolean result;
+
+        try
+        {
+            result = slave.removeFromBuildQueue( projectId, buildDefinitionId );
+            log.debug( "Removing project '{}' from build queue of build agent {}", projectId, buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to remove project '" + projectId + "' from build queue of build agent " + buildAgentUrl,
+                       e );
+            throw new Exception(
+                "Failed to remove project '" + projectId + "' from build queue of build agent " + buildAgentUrl, e );
+        }
+
+        return result;
+    }
+
+    public Boolean removeFromBuildQueue( List<String> hashCodes )
+        throws Exception
+    {
+        Boolean result;
+
+        try
+        {
+            result = slave.removeFromBuildQueue( hashCodes );
+            log.debug( "Removing projects from build queue of build agent {}", buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to remove projects from build queue of build agent " + buildAgentUrl, e );
+            throw new Exception( "Failed to remove projects from build queue of build agent " + buildAgentUrl, e );
+        }
+
+        return result;
+    }
+
+    public String getBuildAgentPlatform()
+        throws Exception
+    {
+        String result;
+
+        try
+        {
+            result = slave.getBuildAgentPlatform();
+            log.debug( "Retrieved build agent {} platform", buildAgentUrl );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Failed to return build agent " + buildAgentUrl + " platform", e );
+            throw new Exception( "Failed to return build agent " + buildAgentUrl + " platform", e );
+        }
+
+        return result;
+    }
+
+    public void executeDirectoryPurge( String directoryType, int daysOlder, int retentionCount, boolean deleteAll )
+        throws Exception
+    {
+        slave.executeDirectoryPurge( directoryType, daysOlder, retentionCount, deleteAll );
+    }
+}
diff --git a/continuum-distributed/continuum-distributed-slave/continuum-distributed-slave-server/pom.xml b/continuum-distributed/continuum-distributed-slave/continuum-distributed-slave-server/pom.xml
new file mode 100644
index 0000000..0a7dd17
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-slave/continuum-distributed-slave-server/pom.xml
@@ -0,0 +1,54 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <groupId>org.apache.continuum</groupId>
+    <artifactId>continuum-distributed-slave</artifactId>
+    <version>1.4.3</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>continuum-distributed-slave-server</artifactId>
+  <name>Continuum :: Distributed Build :: Transport :: Slave :: Server</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-distributed-slave-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-buildagent-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.xmlrpc</groupId>
+      <artifactId>xmlrpc-server</artifactId>
+      <exclusions>
+        <exclusion>
+          <groupId>commons-logging</groupId>
+          <artifactId>commons-logging</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/continuum-distributed/continuum-distributed-slave/continuum-distributed-slave-server/src/main/java/org/apache/continuum/distributed/transport/slave/SlaveBuildAgentTransportAuthenticator.java b/continuum-distributed/continuum-distributed-slave/continuum-distributed-slave-server/src/main/java/org/apache/continuum/distributed/transport/slave/SlaveBuildAgentTransportAuthenticator.java
new file mode 100644
index 0000000..190fd83
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-slave/continuum-distributed-slave-server/src/main/java/org/apache/continuum/distributed/transport/slave/SlaveBuildAgentTransportAuthenticator.java
@@ -0,0 +1,64 @@
+package org.apache.continuum.distributed.transport.slave;
+
+/*
+ * 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 org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
+import org.apache.xmlrpc.XmlRpcException;
+import org.apache.xmlrpc.XmlRpcRequest;
+import org.apache.xmlrpc.common.XmlRpcHttpRequestConfigImpl;
+import org.apache.xmlrpc.server.AbstractReflectiveHandlerMapping.AuthenticationHandler;
+import org.codehaus.plexus.util.StringUtils;
+
+public class SlaveBuildAgentTransportAuthenticator
+    implements AuthenticationHandler
+{
+    private BuildAgentConfigurationService buildAgentConfigurationService;
+
+    public SlaveBuildAgentTransportAuthenticator( BuildAgentConfigurationService buildAgentConfigurationService )
+    {
+        this.buildAgentConfigurationService = buildAgentConfigurationService;
+    }
+
+    public boolean isAuthorized( XmlRpcRequest pRequest )
+        throws XmlRpcException
+    {
+        if ( pRequest.getConfig() instanceof XmlRpcHttpRequestConfigImpl )
+        {
+            XmlRpcHttpRequestConfigImpl config = (XmlRpcHttpRequestConfigImpl) pRequest.getConfig();
+
+            if ( config.getBasicPassword() == null || StringUtils.isBlank( config.getBasicPassword() ) )
+            {
+                throw new XmlRpcException( "Shared Secret Password is not present in the server request" );
+            }
+
+            if ( buildAgentConfigurationService.getSharedSecretPassword() == null || StringUtils.isBlank(
+                buildAgentConfigurationService.getSharedSecretPassword() ) )
+            {
+                throw new XmlRpcException( "Shared Secret Password is not configured properly on the build agent" );
+            }
+
+            return buildAgentConfigurationService.getSharedSecretPassword().equals( config.getBasicPassword() );
+        }
+
+        throw new XmlRpcException( "Unsupported transport (must be http)" );
+    }
+
+
+}
diff --git a/continuum-distributed/continuum-distributed-slave/continuum-distributed-slave-server/src/main/java/org/apache/continuum/distributed/transport/slave/SlaveBuildAgentTransportServer.java b/continuum-distributed/continuum-distributed-slave/continuum-distributed-slave-server/src/main/java/org/apache/continuum/distributed/transport/slave/SlaveBuildAgentTransportServer.java
new file mode 100644
index 0000000..38c2efa
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-slave/continuum-distributed-slave-server/src/main/java/org/apache/continuum/distributed/transport/slave/SlaveBuildAgentTransportServer.java
@@ -0,0 +1,590 @@
+package org.apache.continuum.distributed.transport.slave;
+
+/*
+ * 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 org.apache.continuum.buildagent.ContinuumBuildAgentException;
+import org.apache.continuum.buildagent.ContinuumBuildAgentService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * ProxyMasterBuildAgentTransportService
+ */
+public class SlaveBuildAgentTransportServer
+    implements SlaveBuildAgentTransportService
+{
+    private Logger log = LoggerFactory.getLogger( this.getClass() );
+
+    private ContinuumBuildAgentService continuumBuildAgentService;
+
+    public SlaveBuildAgentTransportServer( ContinuumBuildAgentService continuumBuildAgentService )
+    {
+        this.continuumBuildAgentService = continuumBuildAgentService;
+    }
+
+    public Boolean buildProjects( List<Map<String, Object>> projectsBuildContext )
+        throws Exception
+    {
+        Boolean result;
+
+        try
+        {
+            continuumBuildAgentService.buildProjects( projectsBuildContext );
+            result = Boolean.TRUE;
+
+            log.info( "Building projects." );
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            log.error( "Failed to build projects.", e );
+            throw e;
+        }
+
+        return result;
+    }
+
+    public List<Map<String, String>> getAvailableInstallations()
+        throws Exception
+    {
+        List<Map<String, String>> installations;
+
+        try
+        {
+            installations = continuumBuildAgentService.getAvailableInstallations();
+            log.debug( "Available installations: {}", installations.size() );
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            log.error( "Failed to get available installations.", e );
+            throw e;
+        }
+
+        return installations;
+    }
+
+    public Map<String, Object> getBuildResult( int projectId )
+        throws Exception
+    {
+        Map<String, Object> buildResult;
+
+        try
+        {
+            buildResult = continuumBuildAgentService.getBuildResult( projectId );
+            log.debug( "Build result for project '{}' acquired.", projectId );
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            log.error( "Failed to get build result for project '" + projectId + "'", e );
+            throw e;
+        }
+
+        return buildResult;
+    }
+
+    public Map<String, Object> getProjectCurrentlyBuilding()
+        throws Exception
+    {
+        Map<String, Object> project = continuumBuildAgentService.getProjectCurrentlyBuilding();
+
+        log.debug( "Retrieving currently building project" );
+
+        return project;
+    }
+
+    public Boolean ping()
+        throws Exception
+    {
+        return continuumBuildAgentService.ping();
+    }
+
+    public Boolean cancelBuild()
+        throws Exception
+    {
+        Boolean result;
+
+        try
+        {
+            continuumBuildAgentService.cancelBuild();
+            result = Boolean.TRUE;
+            log.debug( "Cancelled build" );
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            log.error( "Failed to cancel build", e );
+            throw e;
+        }
+
+        return result;
+    }
+
+    public String generateWorkingCopyContent( int projectId, String directory, String baseUrl, String imagesBaseUrl )
+        throws Exception
+    {
+        try
+        {
+            log.debug( "Generate working copy content for project '{}'", projectId );
+            return continuumBuildAgentService.generateWorkingCopyContent( projectId, directory, baseUrl,
+                                                                          imagesBaseUrl );
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            log.error( "Failed to generate working copy content for projectId=" + projectId, e );
+            throw e;
+        }
+    }
+
+    public Map<String, Object> getProjectFile( int projectId, String directory, String filename )
+        throws Exception
+    {
+        try
+        {
+            log.debug( "Retrieve project '{}' file content", projectId );
+            return continuumBuildAgentService.getProjectFile( projectId, directory, filename );
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            log.error( "Failed to retrieve project '" + projectId + "' file content", e );
+            throw e;
+        }
+    }
+
+    public Map getReleasePluginParameters( int projectId, String pomFilename )
+        throws Exception
+    {
+        try
+        {
+            log.debug( "Retrieving release plugin parameters for project '{}'", projectId );
+            return continuumBuildAgentService.getReleasePluginParameters( projectId, pomFilename );
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            log.error( "Failed to retrieve release plugin parameters for project '" + projectId + "'", e );
+            throw e;
+        }
+    }
+
+    public List<Map<String, String>> processProject( int projectId, String pomFilename, boolean autoVersionSubmodules )
+        throws Exception
+    {
+        try
+        {
+            log.debug( "Processing project '{}'", projectId );
+            return continuumBuildAgentService.processProject( projectId, pomFilename, autoVersionSubmodules );
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            log.error( "Failed to process project '" + projectId + "'", e );
+            throw e;
+        }
+    }
+
+    public String releasePrepare( Map project, Properties properties, Map releaseVersion, Map developmentVersion,
+                                  Map environments, String username )
+        throws Exception
+    {
+        try
+        {
+            log.debug( "Preparing release" );
+            return continuumBuildAgentService.releasePrepare( project, properties, releaseVersion, developmentVersion,
+                                                              environments, username );
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            log.error( "Failed to prepare release", e );
+            throw e;
+        }
+    }
+
+    public Map<String, Object> getListener( String releaseId )
+        throws Exception
+    {
+        try
+        {
+            log.debug( "Retrieving listener for releaseId={}", releaseId );
+            return continuumBuildAgentService.getListener( releaseId );
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            log.error( "Failed to retrieve listener state of releaseId=" + releaseId, e );
+            throw e;
+        }
+    }
+
+    public Map<String, Object> getReleaseResult( String releaseId )
+        throws Exception
+    {
+        try
+        {
+            log.debug( "Retrieving release result, releaseId={}", releaseId );
+            return continuumBuildAgentService.getReleaseResult( releaseId );
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            log.error( "Failed to retrieve release result of releaseId=" + releaseId, e );
+            throw e;
+        }
+    }
+
+    public Boolean removeListener( String releaseId )
+        throws Exception
+    {
+        Boolean result;
+
+        try
+        {
+            continuumBuildAgentService.removeListener( releaseId );
+            result = Boolean.TRUE;
+            log.debug( "Removing listener for releaseId={}", releaseId );
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            log.error( "Failed to remove listener of releaseId=" + releaseId, e );
+            throw e;
+        }
+
+        return result;
+    }
+
+    public String getPreparedReleaseName( String releaseId )
+        throws Exception
+    {
+        try
+        {
+            log.debug( "Retrieving prepared release name, releaseId={}", releaseId );
+            return continuumBuildAgentService.getPreparedReleaseName( releaseId );
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            log.error( "Failed to retrieve prepared release name of releaseId=" + releaseId );
+            throw e;
+        }
+    }
+
+    public Boolean releasePerform( String releaseId, String goals, String arguments, boolean useReleaseProfile,
+                                   Map repository, String username )
+        throws Exception
+    {
+        Boolean result;
+
+        try
+        {
+            continuumBuildAgentService.releasePerform( releaseId, goals, arguments, useReleaseProfile, repository,
+                                                       username );
+            result = Boolean.TRUE;
+            log.debug( "Perform release of releaseId={}", releaseId );
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            log.error( "Unable to perform release of releaseId=" + releaseId, e );
+            throw e;
+        }
+
+        return result;
+    }
+
+    public String releasePerformFromScm( String goals, String arguments, boolean useReleaseProfile, Map repository,
+                                         String scmUrl, String scmUsername, String scmPassword, String scmTag,
+                                         String scmTagBase, Map environments, String username )
+        throws Exception
+    {
+        try
+        {
+            log.debug( "Perform release of scmUrl={}", scmUrl );
+            return continuumBuildAgentService.releasePerformFromScm( goals, arguments, useReleaseProfile, repository,
+                                                                     scmUrl, scmUsername, scmPassword, scmTag,
+                                                                     scmTagBase, environments, username );
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            log.error( "Unable to perform release of scmUrl=" + scmUrl, e );
+            throw e;
+        }
+    }
+
+    public String releaseCleanup( String releaseId )
+        throws Exception
+    {
+        try
+        {
+            log.debug( "Cleanup release, releaseId={}", releaseId );
+            return continuumBuildAgentService.releaseCleanup( releaseId );
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            log.error( "Unable to cleanup release, releaseId=" + releaseId, e );
+            throw e;
+        }
+    }
+
+    public Boolean releaseRollback( String releaseId, int projectId )
+        throws Exception
+    {
+        Boolean result;
+
+        try
+        {
+            continuumBuildAgentService.releaseRollback( releaseId, projectId );
+            result = Boolean.TRUE;
+            log.debug( "Rollback release. releaseId={}, projectId={}", releaseId, projectId );
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            log.error( "Failed to rollback release. releaseId=" + releaseId + ", projectId=" + projectId, e );
+            throw e;
+        }
+
+        return result;
+    }
+
+    public Integer getBuildSizeOfAgent()
+        throws Exception
+    {
+        try
+        {
+            return continuumBuildAgentService.getBuildSizeOfAgent();
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            log.error( "Failed to retrieve build size of agent", e );
+            throw e;
+        }
+    }
+
+    public Map<String, Object> getProjectCurrentlyPreparingBuild()
+        throws Exception
+    {
+        try
+        {
+            return continuumBuildAgentService.getProjectCurrentlyPreparingBuild();
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            log.error( "Failed to retrieve projects currently preparing build", e );
+            throw e;
+        }
+    }
+
+    public List<Map<String, Object>> getProjectsAndBuildDefinitionsCurrentlyPreparingBuild()
+        throws Exception
+    {
+        try
+        {
+            return continuumBuildAgentService.getProjectsAndBuildDefinitionsCurrentlyPreparingBuild();
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            log.error( "Failed to retrieve projects currently preparing build", e );
+            throw e;
+        }
+    }
+
+    public List<Map<String, Object>> getProjectsInBuildQueue()
+        throws Exception
+    {
+        try
+        {
+            log.debug( "Retrieving projects in build queue" );
+            return continuumBuildAgentService.getProjectsInBuildQueue();
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            log.error( "Failed to retrieve projects in build queue", e );
+            throw e;
+        }
+    }
+
+    public List<Map<String, Object>> getProjectsInPrepareBuildQueue()
+        throws Exception
+    {
+        try
+        {
+            log.debug( "Retrieving projects in prepare build queue" );
+            return continuumBuildAgentService.getProjectsInPrepareBuildQueue();
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            log.error( "Failed to retrieve projects in prepare build queue", e );
+            throw e;
+        }
+    }
+
+    public List<Map<String, Object>> getProjectsAndBuildDefinitionsInPrepareBuildQueue()
+        throws Exception
+    {
+        try
+        {
+            log.debug( "Retrieving projects in prepare build queue" );
+            return continuumBuildAgentService.getProjectsAndBuildDefinitionsInPrepareBuildQueue();
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            log.error( "Failed to retrieve projects in prepare build queue", e );
+            throw e;
+        }
+    }
+
+    public Boolean isProjectGroupInQueue( int projectGroupId )
+        throws Exception
+    {
+        log.debug( "Checking if project group '{}' is in queue", projectGroupId );
+        return continuumBuildAgentService.isProjectGroupInQueue( projectGroupId );
+    }
+
+    public Boolean isProjectScmRootInQueue( int projectScmRootId, List<Integer> projectIds )
+        throws Exception
+    {
+        log.debug( "Checking if project scm root '{}' is in queue", projectScmRootId );
+        return continuumBuildAgentService.isProjectScmRootInQueue( projectScmRootId, projectIds );
+    }
+
+    public Boolean isProjectCurrentlyBuilding( int projectId, int buildDefinitionId )
+        throws Exception
+    {
+        log.info( "Checking if projectId={}, buildDefinitionId={} is currently building in agent", projectId,
+                  buildDefinitionId );
+        return continuumBuildAgentService.isProjectCurrentlyBuilding( projectId, buildDefinitionId );
+    }
+
+    public Boolean isProjectInBuildQueue( int projectId, int buildDefinitionId )
+        throws Exception
+    {
+        log.info( "Checking if projectId={}, buildDefinitionId={} is in build queue of agent", projectId,
+                  buildDefinitionId );
+        return continuumBuildAgentService.isProjectInBuildQueue( projectId, buildDefinitionId );
+    }
+
+    public Boolean isProjectCurrentlyPreparingBuild( int projectId, int buildDefinitionId )
+        throws Exception
+    {
+        log.info( "Checking if projectId={}, buildDefinitionId={} is currently preparing build", projectId,
+                  buildDefinitionId );
+        return continuumBuildAgentService.isProjectCurrentlyPreparingBuild( projectId, buildDefinitionId );
+    }
+
+    public Boolean isProjectInPrepareBuildQueue( int projectId, int buildDefinitionId )
+        throws Exception
+    {
+        log.info( "Checking if projectId={}, buildDefinitionId={} is in prepare build queue", projectId,
+                  buildDefinitionId );
+        return continuumBuildAgentService.isProjectInPrepareBuildQueue( projectId, buildDefinitionId );
+    }
+
+    public Boolean isProjectGroupInPrepareBuildQueue( int projectGroupId )
+        throws Exception
+    {
+        log.info( "Checking if project group '" + projectGroupId + "' is in prepare build queue" );
+        return continuumBuildAgentService.isProjectGroupInPrepareBuildQueue( projectGroupId );
+    }
+
+    public Boolean isProjectGroupCurrentlyPreparingBuild( int projectGroupId )
+        throws Exception
+    {
+        log.info( "Checking if project group '" + projectGroupId + "' is currently preparing build" );
+        return continuumBuildAgentService.isProjectGroupCurrentlyPreparingBuild( projectGroupId );
+    }
+
+    public Boolean removeFromPrepareBuildQueue( int projectGroupId, int scmRootId )
+        throws Exception
+    {
+        try
+        {
+            log.info( "Remove projects from prepare build queue. projectGroupId=" + projectGroupId +
+                          ", scmRootId=" + scmRootId );
+            return continuumBuildAgentService.removeFromPrepareBuildQueue( projectGroupId, scmRootId );
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            log.error( "Failed to remove projects from prepare build queue. projectGroupId=" + projectGroupId +
+                           ", scmRootId=" + scmRootId );
+            throw e;
+        }
+    }
+
+    public Boolean removeFromPrepareBuildQueue( List<String> hashCodes )
+        throws Exception
+    {
+        Boolean result;
+
+        try
+        {
+            continuumBuildAgentService.removeFromPrepareBuildQueue( hashCodes );
+            result = Boolean.TRUE;
+            log.info( "Remove projects from prepare build queue" );
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            log.error( "Failed to remove projects from prepare build queue" );
+            throw e;
+        }
+
+        return result;
+    }
+
+    public Boolean removeFromBuildQueue( int projectId, int buildDefinitionId )
+        throws Exception
+    {
+        try
+        {
+            log.debug( "Remove project '" + projectId + "' from build queue" );
+            return continuumBuildAgentService.removeFromBuildQueue( projectId, buildDefinitionId );
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            log.error( "Failed to remove project '" + projectId + "' from build queue" );
+            throw e;
+        }
+    }
+
+    public Boolean removeFromBuildQueue( List<String> hashCodes )
+        throws Exception
+    {
+        Boolean result;
+
+        try
+        {
+            continuumBuildAgentService.removeFromBuildQueue( hashCodes );
+            result = Boolean.TRUE;
+            log.info( "Remove projects from build queue" );
+        }
+        catch ( ContinuumBuildAgentException e )
+        {
+            log.error( "Failed to remove projects from build queue" );
+            throw e;
+        }
+
+        return result;
+    }
+
+    public String getBuildAgentPlatform()
+        throws Exception
+    {
+        return continuumBuildAgentService.getBuildAgentPlatform();
+    }
+
+    public void executeDirectoryPurge( String directoryType, int daysOlder, int retentionCount, boolean deleteAll )
+        throws Exception
+    {
+        continuumBuildAgentService.executeDirectoryPurge( directoryType, daysOlder, retentionCount, deleteAll );
+    }
+}
diff --git a/continuum-distributed/continuum-distributed-slave/pom.xml b/continuum-distributed/continuum-distributed-slave/pom.xml
new file mode 100644
index 0000000..6a2b193
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-slave/pom.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <artifactId>continuum-distributed</artifactId>
+    <groupId>org.apache.continuum</groupId>
+    <version>1.4.3</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>continuum-distributed-slave</artifactId>
+  <name>Continuum :: Distributed Build :: Transport :: Slave</name>
+  <packaging>pom</packaging>
+  <modules>
+    <module>continuum-distributed-slave-api</module>
+    <module>continuum-distributed-slave-server</module>
+    <module>continuum-distributed-slave-client</module>
+  </modules>
+</project>
diff --git a/continuum-distributed/continuum-distributed-tests/pom.xml b/continuum-distributed/continuum-distributed-tests/pom.xml
new file mode 100644
index 0000000..b094b0a
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-tests/pom.xml
@@ -0,0 +1,147 @@
+<?xml version="1.0"?>
+
+<!--
+  ~ 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <artifactId>continuum-distributed</artifactId>
+    <groupId>org.apache.continuum</groupId>
+    <version>1.4.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>continuum-distributed-tests</artifactId>
+  <packaging>war</packaging>
+  <name>Continuum :: Distributed Build :: Transport :: Tests</name>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-distributed-slave-server</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-distributed-slave-client</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-distributed-master-server</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-distributed-master-client</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-buildagent-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-web</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+      <version>2.4</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-slf4j-logging</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <testSourceDirectory>src/test/it</testSourceDirectory>
+    <plugins>
+      <plugin>
+        <groupId>org.mortbay.jetty</groupId>
+        <artifactId>maven-jetty-plugin</artifactId>
+        <configuration>
+          <scanIntervalSeconds>10</scanIntervalSeconds>
+          <contextPath>/</contextPath>
+          <stopKey>stopkey</stopKey>
+          <stopPort>9192</stopPort>
+          <jettyEnvXml>${basedir}/src/jetty-env.xml</jettyEnvXml>
+          <connectors>
+            <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
+              <port>9191</port>
+              <maxIdleTime>60000</maxIdleTime>
+            </connector>
+          </connectors>
+          <systemProperties>
+            <systemProperty>
+              <name>appserver.base</name>
+              <value>${project.build.directory}/appserver-base</value>
+            </systemProperty>
+          </systemProperties>
+        </configuration>
+        <executions>
+          <execution>
+            <id>start-jetty</id>
+            <phase>pre-integration-test</phase>
+            <goals>
+              <goal>run</goal>
+            </goals>
+            <configuration>
+              <scanIntervalSeconds>0</scanIntervalSeconds>
+              <daemon>true</daemon>
+            </configuration>
+          </execution>
+          <execution>
+            <id>stop-jetty</id>
+            <phase>post-integration-test</phase>
+            <goals>
+              <goal>stop</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+        <executions>
+          <execution>
+            <id>integration-tests</id>
+            <phase>integration-test</phase>
+            <goals>
+              <goal>test</goal>
+            </goals>
+            <configuration>
+              <skip>false</skip>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/continuum-distributed/continuum-distributed-tests/src/jetty-env.xml b/continuum-distributed/continuum-distributed-tests/src/jetty-env.xml
new file mode 100644
index 0000000..15bc122
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-tests/src/jetty-env.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<!--
+  ~ 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.
+  -->
+
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
+
+<Configure class="org.mortbay.jetty.webapp.WebAppContext"/>
diff --git a/continuum-distributed/continuum-distributed-tests/src/main/java/org/apache/continuum/web/startup/BuildAgentStartup.java b/continuum-distributed/continuum-distributed-tests/src/main/java/org/apache/continuum/web/startup/BuildAgentStartup.java
new file mode 100644
index 0000000..dd4805f
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-tests/src/main/java/org/apache/continuum/web/startup/BuildAgentStartup.java
@@ -0,0 +1,59 @@
+package org.apache.continuum.web.startup;
+
+/*
+ * 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 org.codehaus.plexus.spring.PlexusToSpringUtils;
+import org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+public class BuildAgentStartup
+    implements ServletContextListener
+{
+    private Logger log = LoggerFactory.getLogger( getClass() );
+
+    /**
+     * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent)
+     */
+    public void contextDestroyed( ServletContextEvent sce )
+    {
+        // nothing to do here
+
+    }
+
+    /**
+     * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent)
+     */
+    public void contextInitialized( ServletContextEvent sce )
+    {
+        log.info( "Initializing Build Agent Task Queue Executor" );
+
+        WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(
+            sce.getServletContext() );
+
+        TaskQueueExecutor buildAgent = (TaskQueueExecutor) wac.getBean( PlexusToSpringUtils.buildSpringId(
+            TaskQueueExecutor.class, "build-agent" ) );
+    }
+}
diff --git a/continuum-distributed/continuum-distributed-tests/src/main/resources/META-INF/continuum/continuum-configuration.xml b/continuum-distributed/continuum-distributed-tests/src/main/resources/META-INF/continuum/continuum-configuration.xml
new file mode 100644
index 0000000..ce34638
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-tests/src/main/resources/META-INF/continuum/continuum-configuration.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+
+<!--
+  ~ 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.
+  -->
+
+<configuration>
+  <system/>
+  <jndi prefix="java:comp/env" config-optional="true"/>
+  <xml fileName="${appserver.base}/conf/continuum-buildagent.xml" config-optional="true"
+       config-forceCreate="true" config-name="org.apache.continuum"/>
+  <xml fileName="${user.home}/.m2/continuum-buildagent.xml" config-optional="true"
+       config-forceCreate="true" config-name="org.apache.continuum.user"/>
+</configuration>
diff --git a/continuum-distributed/continuum-distributed-tests/src/main/resources/META-INF/plexus/application.xml b/continuum-distributed/continuum-distributed-tests/src/main/resources/META-INF/plexus/application.xml
new file mode 100644
index 0000000..a7ac617
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-tests/src/main/resources/META-INF/plexus/application.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!--
+  ~ 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.
+  -->
+
+<plexus>
+  <components>
+
+    <!--
+    | Logger manager
+    -->
+    <component>
+      <role>org.codehaus.plexus.logging.LoggerManager</role>
+      <implementation>org.codehaus.plexus.logging.slf4j.Slf4jLoggerManager</implementation>
+      <lifecycle-handler>basic</lifecycle-handler>
+    </component>
+
+  </components>
+
+  <lifecycle-handler-manager implementation="org.codehaus.plexus.lifecycle.DefaultLifecycleHandlerManager">
+    <default-lifecycle-handler-id>plexus</default-lifecycle-handler-id>
+    <lifecycle-handlers>
+      <lifecycle-handler implementation="org.codehaus.plexus.personality.plexus.PlexusLifecycleHandler">
+        <id>plexus</id>
+        <name>Plexus Lifecycle Handler</name>
+        <begin-segment>
+          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.LogEnablePhase"/>
+          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.CompositionPhase"/>
+          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.ContextualizePhase"/>
+          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.AutoConfigurePhase"/>
+          <phase implementation="org.codehaus.plexus.registry.RegistryConfigurePhase"/>
+          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.ServiceablePhase"/>
+          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializePhase"/>
+          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.StartPhase"/>
+        </begin-segment>
+        <suspend-segment>
+          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.SuspendPhase"/>
+        </suspend-segment>
+        <resume-segment>
+          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.ResumePhase"/>
+        </resume-segment>
+        <end-segment>
+          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.StopPhase"/>
+          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.DisposePhase"/>
+          <phase implementation="org.codehaus.plexus.personality.plexus.lifecycle.phase.LogDisablePhase"/>
+        </end-segment>
+      </lifecycle-handler>
+    </lifecycle-handlers>
+  </lifecycle-handler-manager>
+</plexus>
diff --git a/continuum-distributed/continuum-distributed-tests/src/main/resources/applicationContext.xml b/continuum-distributed/continuum-distributed-tests/src/main/resources/applicationContext.xml
new file mode 100644
index 0000000..8bf5040
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-tests/src/main/resources/applicationContext.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+  <bean id="masterBuildAgentTransportServer"
+        class="org.apache.continuum.distributed.transport.master.MasterBuildAgentTransportServer"/>
+
+  <bean id="slaveBuildAgentTransportServer"
+        class="org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportServer">
+    <constructor-arg ref="continuumBuildAgentService"/>
+  </bean>
+
+  <bean name="xmlrpcServicesList" class="java.util.ArrayList">
+    <constructor-arg>
+      <list>
+        <ref bean="slaveBuildAgentTransportServer"/>
+        <ref bean="masterBuildAgentTransportServer"/>
+      </list>
+    </constructor-arg>
+  </bean>
+
+</beans>
diff --git a/continuum-distributed/continuum-distributed-tests/src/main/webapp/WEB-INF/web.xml b/continuum-distributed/continuum-distributed-tests/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..b83b2b0
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-tests/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,91 @@
+<!--
+  ~ 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.
+  -->
+
+<web-app xmlns="http://java.sun.com/xml/ns/j2ee" version="2.4"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+
+  <display-name>Continuum Distributed Build Transport Tests</display-name>
+
+  <listener>
+    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
+  </listener>
+
+  <listener>
+    <!-- TODO: some Spring technique for this? -->
+    <listener-class>org.apache.continuum.web.startup.BuildAgentStartup</listener-class>
+  </listener>
+
+  <context-param>
+    <param-name>contextClass</param-name>
+    <param-value>org.codehaus.plexus.spring.PlexusWebApplicationContext</param-value>
+  </context-param>
+
+  <context-param>
+    <param-name>contextConfigLocation</param-name>
+    <param-value>
+      classpath*:/META-INF/spring-context.xml
+      classpath*:/applicationContext.xml
+      classpath*:/META-INF/plexus/components.xml
+      classpath*:/META-INF/plexus/application.xml
+    </param-value>
+  </context-param>
+
+  <servlet>
+    <servlet-name>MasterXmlRpcServlet</servlet-name>
+    <servlet-class>
+      com.atlassian.xmlrpc.spring.BinderSpringXmlRpcServlet
+    </servlet-class>
+    <init-param>
+      <param-name>serviceListBeanName</param-name>
+      <param-value>xmlrpcServicesList</param-value>
+    </init-param>
+    <init-param>
+      <param-name>enabledForExtensions</param-name>
+      <param-value>true</param-value>
+    </init-param>
+    <load-on-startup>1</load-on-startup>
+  </servlet>
+
+  <servlet>
+    <servlet-name>SlaveXmlRpcServlet</servlet-name>
+    <servlet-class>
+      com.atlassian.xmlrpc.spring.BinderSpringXmlRpcServlet
+    </servlet-class>
+    <init-param>
+      <param-name>serviceListBeanName</param-name>
+      <param-value>xmlrpcServicesList</param-value>
+    </init-param>
+    <init-param>
+      <param-name>enabledForExtensions</param-name>
+      <param-value>true</param-value>
+    </init-param>
+    <load-on-startup>1</load-on-startup>
+  </servlet>
+
+  <servlet-mapping>
+    <servlet-name>MasterXmlRpcServlet</servlet-name>
+    <url-pattern>/master-xmlrpc</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>SlaveXmlRpcServlet</servlet-name>
+    <url-pattern>/slave-xmlrpc</url-pattern>
+  </servlet-mapping>
+</web-app>
diff --git a/continuum-distributed/continuum-distributed-tests/src/main/webapp/index.jsp b/continuum-distributed/continuum-distributed-tests/src/main/webapp/index.jsp
new file mode 100644
index 0000000..2c02d3c
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-tests/src/main/webapp/index.jsp
@@ -0,0 +1,23 @@
+<%--
+  ~ 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.
+  --%>
+<html>
+<body>
+<h2>Hello World!</h2>
+</body>
+</html>
diff --git a/continuum-distributed/continuum-distributed-tests/src/test/it/org/apache/continuum/distributed/transport/tests/MasterBuildAgentTransportServiceTest.java b/continuum-distributed/continuum-distributed-tests/src/test/it/org/apache/continuum/distributed/transport/tests/MasterBuildAgentTransportServiceTest.java
new file mode 100644
index 0000000..94fbf57
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-tests/src/test/it/org/apache/continuum/distributed/transport/tests/MasterBuildAgentTransportServiceTest.java
@@ -0,0 +1,86 @@
+package org.apache.continuum.distributed.transport.tests;
+
+/*
+ * 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 junit.framework.TestCase;
+import org.apache.continuum.distributed.transport.master.MasterBuildAgentTransportClient;
+import org.apache.continuum.distributed.transport.master.MasterBuildAgentTransportService;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.xml.XmlBeanFactory;
+import org.springframework.core.io.ClassPathResource;
+
+import java.net.URL;
+import java.util.HashMap;
+
+/**
+ * MasterBuildAgentTransportServiceTest
+ */
+public class MasterBuildAgentTransportServiceTest
+    extends TestCase
+{
+    private MasterBuildAgentTransportService masterProxy;
+
+    private BeanFactory beanFactory = new XmlBeanFactory( new ClassPathResource( "applicationContext.xml" ) );
+
+    protected void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        masterProxy = new MasterBuildAgentTransportClient( new URL( "http://localhost:9191/master-xmlrpc" ), null,
+                                                           null );
+    }
+
+    public void testReturnBuildResult()
+    {
+        try
+        {
+            masterProxy.returnBuildResult( new HashMap() );
+        }
+        catch ( Exception e )
+        {
+            fail( e.getMessage() );
+        }
+    }
+
+    public void testReturnScmResult()
+    {
+        try
+        {
+            masterProxy.returnScmResult( new HashMap() );
+        }
+        catch ( Exception e )
+        {
+            fail( e.getMessage() );
+        }
+    }
+
+    public void testPing()
+    {
+        try
+        {
+            masterProxy.ping();
+        }
+        catch ( Exception e )
+        {
+            fail( e.getMessage() );
+        }
+    }
+}
diff --git a/continuum-distributed/continuum-distributed-tests/src/test/it/org/apache/continuum/distributed/transport/tests/SlaveBuildAgentTransportServiceTest.java b/continuum-distributed/continuum-distributed-tests/src/test/it/org/apache/continuum/distributed/transport/tests/SlaveBuildAgentTransportServiceTest.java
new file mode 100644
index 0000000..a7657ed
--- /dev/null
+++ b/continuum-distributed/continuum-distributed-tests/src/test/it/org/apache/continuum/distributed/transport/tests/SlaveBuildAgentTransportServiceTest.java
@@ -0,0 +1,121 @@
+package org.apache.continuum.distributed.transport.tests;
+
+/*
+ * 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 junit.framework.TestCase;
+import org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportClient;
+import org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportService;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.xml.XmlBeanFactory;
+import org.springframework.core.io.ClassPathResource;
+
+import java.net.URL;
+import java.util.Collections;
+
+/**
+ * SlaveBuildAgentTransportServiceTest
+ */
+public class SlaveBuildAgentTransportServiceTest
+    extends TestCase
+{
+    private SlaveBuildAgentTransportService slaveProxy;
+
+    private BeanFactory beanFactory = new XmlBeanFactory( new ClassPathResource( "applicationContext.xml" ) );
+
+    protected void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        slaveProxy = new SlaveBuildAgentTransportClient( new URL( "http://localhost:9191/slave-xmlrpc" ), null, null );
+    }
+
+    public void testBuildProjects()
+    {
+        try
+        {
+            slaveProxy.buildProjects( Collections.EMPTY_LIST );
+        }
+        catch ( Exception e )
+        {
+            fail( e.getMessage() );
+        }
+    }
+
+    public void testGetAvailableInstallations()
+    {
+        try
+        {
+            slaveProxy.getAvailableInstallations();
+        }
+        catch ( Exception e )
+        {
+            fail( e.getMessage() );
+        }
+    }
+
+    public void testGetBuildResult()
+    {
+        try
+        {
+            slaveProxy.getBuildResult( 0 );
+        }
+        catch ( Exception e )
+        {
+            fail( e.getMessage() );
+        }
+    }
+
+    public void testGetProjectCurrentlyBuilding()
+    {
+        try
+        {
+            slaveProxy.getProjectCurrentlyBuilding();
+        }
+        catch ( Exception e )
+        {
+            fail( e.getMessage() );
+        }
+    }
+
+    public void testPing()
+    {
+        try
+        {
+            slaveProxy.ping();
+        }
+        catch ( Exception e )
+        {
+            fail( e.getMessage() );
+        }
+    }
+
+    public void testExecuteDirectoryPurge()
+    {
+        try
+        {
+            slaveProxy.executeDirectoryPurge( "releases", 1, 2, false );
+        }
+        catch ( Exception e )
+        {
+            fail( e.getMessage() );
+        }
+    }
+}
diff --git a/continuum-distributed/pom.xml b/continuum-distributed/pom.xml
new file mode 100644
index 0000000..66ac7fe
--- /dev/null
+++ b/continuum-distributed/pom.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <groupId>org.apache.continuum</groupId>
+    <artifactId>continuum</artifactId>
+    <version>1.4.3</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>continuum-distributed</artifactId>
+  <name>Continuum :: Distributed Build :: Transport</name>
+  <packaging>pom</packaging>
+  <modules>
+    <module>continuum-distributed-master</module>
+    <module>continuum-distributed-slave</module>
+    <module>continuum-distributed-commons</module>
+    <!-- <module>continuum-distributed-tests</module> -->
+  </modules>
+</project>
diff --git a/continuum-docs/pom.xml b/continuum-docs/pom.xml
index 0c57fb2..ed66ddf 100644
--- a/continuum-docs/pom.xml
+++ b/continuum-docs/pom.xml
@@ -17,37 +17,47 @@
   ~ under the License.
   -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
     <groupId>org.apache.continuum</groupId>
     <artifactId>continuum</artifactId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3-SNAPSHOT</version>
   </parent>
   <artifactId>continuum-docs</artifactId>
-  <groupId>org.apache.continuum</groupId>
-  <name>Continuum :: docs</name>
+  <name>Continuum :: Documentation</name>
   <packaging>pom</packaging>
-  <url>http://continuum.apache.org/docs/${project.version}</url>
-  <distributionManagement>
-    <site>
-      <id>apache</id>
-      <url>scpexe://people.apache.org/www/continuum.apache.org/docs/${project.version}</url>
-    </site>
-  </distributionManagement>
-  <scm>
-    <connection>scm:svn:http://svn.apache.org/repos/asf/continuum/trunk/</connection>
-    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/continuum/trunk/</developerConnection>
-    <url>http://svn.apache.org/viewvc/continuum/trunk/</url>
-  </scm>
+  <url>http://continuum.apache.org/docs/latest</url>
   <build>
-    <extensions>
-      <extension>
-        <groupId>org.apache.maven.wagon</groupId>
-        <artifactId>wagon-ssh-external</artifactId>
-        <version>${wagon.version}</version>
-      </extension>
-    </extensions>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-scm-publish-plugin</artifactId>
+          <configuration>
+            <pubScmUrl>scm:svn:${svnUrl}</pubScmUrl>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+    <plugins>
+      <plugin>
+        <artifactId>maven-pdf-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>site-pdf</id>
+            <phase>site</phase>
+            <goals>
+              <goal>pdf</goal>
+            </goals>
+            <configuration>
+              <outputDirectory>${project.reporting.outputDirectory}</outputDirectory>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
   </build>
   <reporting>
     <excludeDefaults>true</excludeDefaults>
@@ -55,7 +65,6 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-project-info-reports-plugin</artifactId>
-        <version>2.1</version>
         <reportSets>
           <reportSet>
             <reports>
@@ -76,4 +85,47 @@
       </plugin>
     </plugins>
   </reporting>
+  <profiles>
+    <profile>
+      <id>tag</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>exec-maven-plugin</artifactId>
+            <version>1.2.1</version>
+            <executions>
+              <execution>
+                <id>tag-publish-site</id>
+                <configuration>
+                  <executable>svn</executable>
+                  <arguments>
+                    <argument>--non-interactive</argument>
+                    <argument>cp</argument>
+                    <argument>-m"Copy versioned documentation"</argument>
+                    <argument>${svnUrl}</argument>
+                    <argument>https://svn.apache.org/repos/asf/continuum/site-publish/docs/${project.version}</argument>
+                  </arguments>
+                </configuration>
+                <phase>site-deploy</phase>
+                <goals>
+                  <goal>exec</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+  <properties>
+    <svnUrl>https://svn.apache.org/repos/asf/continuum/site-publish/docs/latest</svnUrl>
+  </properties>
+  <distributionManagement>
+    <!-- Site base required here for site:stage to calculate correct URLs -->
+    <site>
+      <id>apache</id>
+      <url>scm:svn:${rootSitePublishUrl}</url>
+    </site>
+  </distributionManagement>
 </project>
diff --git a/continuum-docs/src/site/apt/administrator_guides/appearance.apt b/continuum-docs/src/site/apt/administrator_guides/appearance.apt
index 67d6c8b..79caeb9 100755
--- a/continuum-docs/src/site/apt/administrator_guides/appearance.apt
+++ b/continuum-docs/src/site/apt/administrator_guides/appearance.apt
@@ -3,18 +3,35 @@
  ------
  Olivier Lamy
  ------
- Nov 13 2007
+ 2010-02-22
  ------
- 
+
+~~ 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.
+
 Configure Appearance
- 
+
 ~~%{toc|section=0}
- 
+
 * {Banner}
 
   You can configure the right logo of the banner including title and link on the image.
-  You have to add some information in a pom (like a company pom) (coming from org.apache:apache in this example) :
-  
+  You have to add some information in a POM (like a company POM) (coming from org.apache:apache in this example):
+
 +----------------------------+
   <organization>
     <name>The Apache Software Foundation</name>
@@ -23,31 +40,31 @@
   <properties>
     <organization.logo>http://www.apache.org/images/asf_logo_wide.gif</organization.logo>
   </properties>
-+----------------------------+  
++----------------------------+
 
-  From the menu, choose the 'Appearance' entry :
-  
+  From the menu, choose the <<Appearance>> entry :
+
 [../images/configure-appearance.png] Appearance
 
-  Use the 'Select a Company POM' link :
-  
-[../images/select-company-pom.png] 'Select a Company POM'   
+  Use the <<Select a Company POM>> link :
 
-  The result will be displayed (using org.apache:apache in this example) :
-  
-[../images/selected-company-pom.png] 'Selected a Company POM'  
+[../images/select-company-pom.png] 'Select a Company POM'
 
-  Note : the pom is searched in central repository and the repositories available for the active profiles from your <<<${user.home}/.m2/settings.xml>>> 
- 
+  The result will be displayed (using org.apache:apache in this example):
+
+[../images/selected-company-pom.png] 'Selected a Company POM'
+
+  <<Note:>> the POM is searched for in the central repository and in the repositories available for the active profiles from your <<<${user.home}/.m2/settings.xml>>>.
+
 * {Footer}
- 
-  You can configure the footer by putting your own html content in the 'Appearance' entry of the menu.
- 
+
+  You can configure the footer by putting your own html content in the <<Appearance>> entry of the menu.
+
 [../images/configuration-footer.png] 'Configure footer'
 
   The default value is :
-    
+
 +----------------------------+
-<div class="xright">Copyright &copy; 2005-${currentYear}&nbsp;The Apache Software Foundation</div> <div class="clear"><hr/></div> 
-+----------------------------+      
- 
+<div class="xright">Copyright &copy; 2005-${currentYear}&nbsp;The Apache Software Foundation</div> <div class="clear"><hr/></div>
++----------------------------+
+
diff --git a/continuum-docs/src/site/apt/administrator_guides/build-agent-groups.apt b/continuum-docs/src/site/apt/administrator_guides/build-agent-groups.apt
new file mode 100644
index 0000000..d7a81dd
--- /dev/null
+++ b/continuum-docs/src/site/apt/administrator_guides/build-agent-groups.apt
@@ -0,0 +1,46 @@
+ ------
+ Managing Build Agent Groups
+ ------
+
+~~ 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.
+
+Managing Build Agent Groups
+
+  A Build Agent Group provides a logical association of Build Agents so that it can be attached to a Build Environment providing the user control on which agents it wants the project to be built.
+  
+  From the menu, choose the 'Build Agents' item
+
+[../images/build-agents-menu.png] Build Agents Menu
+
+  You will see a list of the existing Build Agent Groups in the Build Agent Groups Section, if any.
+
+[../images/build-agent-groups.png] Build Agent Groups List
+
+  To add a new Build Agent Group, click the 'Add' button.
+
+  To edit an existing Build Agent Group, click the 'edit' link to the right of the entry.
+
+  You will be prompted to enter or edit the Build Agent Group Name and its associated Build Agent(s):
+
+[../images/build-agent-groups-edit.png] Add/Edit Build Agent Group
+
+  Build Agent can be associated to one or more Build Agent Group
+
+  To use a Build Agent Group in a Project, you need to attach it to a build environment.
+
+  Refer to {{{./buildEnvironment.html}Attach Build Agent Group to a Build Environment}}
diff --git a/continuum-docs/src/site/apt/administrator_guides/build-agents.apt b/continuum-docs/src/site/apt/administrator_guides/build-agents.apt
index 1a7c414..6ed5b6a 100644
--- a/continuum-docs/src/site/apt/administrator_guides/build-agents.apt
+++ b/continuum-docs/src/site/apt/administrator_guides/build-agents.apt
@@ -2,12 +2,30 @@
  Managing Build Agents
  ------
 
+~~ 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.
+
 Managing Build Agents
 
-  Before this, you may want to enable the Distributed Builds option in the {{{configuration.html}General Configuration}}
-  and {{{../installation/build-agent.html}install a Build Agent}}.
+  Before this, you may want to enable the Distributed Builds option in the {{{./configuration.html}General Configuration}}
+  and {{{../installation/build-agent.html}install a Build Agent}}, or read about the {{{./distributed-builds.html}Distributed
+  Builds}} feature.
 
-  From the menu, choose the 'Build Agents' item
+  From the menu, choose the <<Build Agents>> item
 
 [../images/build-agents-menu.png] Build Agents Menu
 
@@ -15,15 +33,18 @@
 
 [../images/build-agents.png] Build Agents List
 
-  To add a new Build Agent, click the 'Add' button
+  To add a new Build Agent, click the <<Add>> button.
+  You will be prompted to enter the Build Agent URL and Description.
 
-  To edit an existing Build Agent, click the 'edit' link to the right of the entry.
 
-  You will be prompted to enter or edit the Build Agent URL and Description:
+  To edit an existing Build Agent, click the <<Edit>> link to the right of the entry.
+  You will be prompted to edit the Build Agent Description.
+
+  <<Note:>> Once a Build Agent has been saved you can not change its URL.
 
 [../images/build-agent-edit.png] Add/Edit Build Agent
 
-  Be sure to enable the agent by checking the 'Enabled' checkbox.
+  Be sure to enable the agent by checking the <<Enabled>> checkbox.
 
-  After you save your changes, verify that 'Enabled' is true.  If it is false, most likely Continuum was unable to ping
+  After you save your changes, verify that the <<Enabled>> checkbox is checked.  If it is not checked, most likely Continuum was unable to ping
   the agent.  Consult the log file for additional information.
diff --git a/continuum-docs/src/site/apt/administrator_guides/buildEnvironment.apt b/continuum-docs/src/site/apt/administrator_guides/buildEnvironment.apt
new file mode 100755
index 0000000..e95b1dd
--- /dev/null
+++ b/continuum-docs/src/site/apt/administrator_guides/buildEnvironment.apt
@@ -0,0 +1,114 @@
+ ------
+ Continuum :: Build Environment
+ ------
+ Olivier Lamy
+ ------
+ Oct 17 2007
+ ------
+
+~~ 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.
+
+~~%{toc|section=0}
+
+Managing Build Environments
+
+ In continuum, Build Environments allow you to create and manage multiple build
+ configurations. Once you have defined the Build Environments you can configure
+ project Build Definitions or {{{./builddefTemplate.html}Build Definition
+ Templates}} to use them.
+
+ <Note: Build Environments affect the versions of specific tools used to execute
+ builds and their environments. They are not intended to replace things like
+ Maven build profiles.>
+
+*Build Environments
+
+ Build Environments are named groupings of {{{./builder.html}Installations}}. By
+ grouping the collection of Tools and Environment Variables, you define a
+ configuration that can be used to build a project. To define a Build
+ Environment, you specify a human friendly name and add one or more
+ Installations. Once defined, the Build Environment is available for use. You
+ can then specify what Build Environment to use in your project's Build
+ Definitions or in your Build Definition Templates. When continuum detects that
+ a project needs to be built, it uses the Tool Installations to construct the
+ paths to the expected executables (ie. Maven build definitions construct paths
+ to the mvn executable and the java executable). Additional Installations are
+ translated into name/value pairs that are passed through to the constructed
+ command's environment.
+
+  As of Continuum 1.2.1, build environments can be used in releasing projects.
+  This is set upon supplying the release prepare parameters during the
+  {{{../user_guides/release/prepare.html} Release preparation}} of the project.
+
+**Creating a Build Environment
+
+  From the menu, choose the 'Build Environments' entry
+
+[../images/buildenv-menu.png] Build Environment Menu
+
+  Enter a name
+
+[../images/buildenv-add.png] Add Build Environment
+
+** {Attach Build Agent Group to a Build Environment}
+
+  The list box contains all available Build Agent Groups. The list box will only be visible if Distributed Builds is enabled in the {{{./configuration.html}General Configuration}} Page
+
+[../images/profile-build-agent-group.png] Add Build Agent Group to Build Environment
+
+**Attaching the related Installations
+
+ When editing a Build Environment, the Installation list box contains all
+ defined Installations. You can only specify a single Tool Installation per type
+ (jdk, maven, maven2, ant). However, you may specify multiple Environment
+ Variable Installations.
+
+[../images/buildenv-setup-jdk.png] Adding Installations to Build Environment
+
+**Setting a Build Definition's Build Environment
+
+ The way you configure builds to use your newly created Build Environments is by
+ setting it in either a project Build Definition or in the continuum Build
+ Definition Templates. The following example sets the Build Environment of a
+ specific project's Build Definition. 
+
+[../images/buildenv-in-builddef.png] Setup Build Environment
+
+**Installations used in Notification mail
+
+  Build notifications send along information about the environment in which the
+  project was built.
+
+  * Java Home version : coming from $JAVA_HOME/bin/java -version.
+
+  * Builder version : coming from builder used version arg (mvn  used -v, ant
+  use -version). 
+  
+  []
+
++-------------------------------+
+  Java Home version : 
+          java version "1.6.0_11"
+          Java(TM) SE Runtime Environment (build 1.6.0_11-b03)
+          Java HotSpot(TM) Client VM (build 11.0-b16, mixed mode, sharing)
+        
+  Builder version :
+          Maven version: 2.0.9
+          Java version: 1.6.0_11
+          OS name: "linux" version: "2.6.16.60-0.23-default" arch: "i386" Family: "unix"
++-------------------------------+
diff --git a/continuum-docs/src/site/apt/administrator_guides/buildQueue.apt b/continuum-docs/src/site/apt/administrator_guides/buildQueue.apt
new file mode 100644
index 0000000..899c172
--- /dev/null
+++ b/continuum-docs/src/site/apt/administrator_guides/buildQueue.apt
@@ -0,0 +1,53 @@
+ ------
+ Managing Build Queues
+ ------
+ Jevica Arianne B. Zurbano
+ ------
+ May 21 2009
+ ------
+
+~~ 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.
+
+Managing Build Queues
+
+* Adding a Build Queue
+
+    By default, there is already a DEFAULT_BUILD_QUEUE that cannot be deleted configured in Continuum. To add more build queues..
+
+    Click the <<Build Queue>> link under the <<Administration>> section.
+
+[../images/buildQueue.png] Build Queue
+
+    You will see all the build queues.
+
+[../images/listBuildQueue.png] Build Queues list
+
+    Here you can add/delete the build queue. Take note that you would only be allowed to create N number of build queues, where
+    N = the Number of Allowed Builds in Parallel set in the Configuration page.
+
+    Input the name for the build queue and save.           
+
+[../images/addBuildQueue.png] Add Parallel Build Queue
+
+* Deleting a Build Queue
+    
+    From  the build queue page, you can delete a build queue by clicking the delete icon
+
+[../images/delete.gif] Delete icon
+
+
diff --git a/continuum-docs/src/site/apt/administrator_guides/builddefTemplate.apt b/continuum-docs/src/site/apt/administrator_guides/builddefTemplate.apt
index 21c61aa..da651d0 100644
--- a/continuum-docs/src/site/apt/administrator_guides/builddefTemplate.apt
+++ b/continuum-docs/src/site/apt/administrator_guides/builddefTemplate.apt
@@ -6,6 +6,23 @@
  Oct 3 2007
  ------
 
+~~ 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.
+
 Build Definition Template
 
   From the menu, choose the 'Build Definition Templates' entry
diff --git a/continuum-docs/src/site/apt/administrator_guides/builder.apt b/continuum-docs/src/site/apt/administrator_guides/builder.apt
index 7f07f7a..69818f5 100755
--- a/continuum-docs/src/site/apt/administrator_guides/builder.apt
+++ b/continuum-docs/src/site/apt/administrator_guides/builder.apt
@@ -1,14 +1,67 @@
  ------
- Managing Building Tool
+ Managing Installations
  ------
  Olivier Lamy
  ------
  Oct 11 2007
  ------
  
-Managing Building Tool
+~~ 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.
 
-  From the menu, choose the 'Installations' entry 
+Managing Installations
+
+ Continuum allows you to configure the build tools it uses to build projects by
+ defining {{{./buildEnvironment.html}Build Environments}}. Installations allow defining
+ environment settings and are the basic unit of a Build Environment.
+ 
+ For example, say you need to maintain two build environments.  One using JDK 5
+ and Maven 2.0.9 and another using JDK 6 and Maven 2.1.0-M1. To achieve this,
+ you would need to do the following:
+
+ [[1]] Create Installations for the versions of Java and Maven.
+ 
+ [[2]] Create Installations for any environment variables you want to set such
+ as MAVEN_OPTS and ANT_OPTS.
+
+ [[3]] Create the desired Build Environments, specifying the combination of
+ Installations to use. 
+
+ [[4]] Assign the Build Environments to your Build Definition Templates or
+ project-specific Build Definitions.
+
+ []
+
+*Installations
+
+ Installations are essentially named environment variables. There are currently
+ two types of Installations: Tools and Environment Variables. 
+
+**Tools
+
+ Tools are meant to provide locations to pre-defined tool types. Currently,
+ continuum allows you to define locations for the JDK, Maven 2, Maven 1 and Ant.
+ When you create a tool installation, you specify a human-friendly name, the
+ tool type, and the path to tool. Continuum verifies that the specified tool
+ type resides in that location or fails to create the Installation.
+
+***Example: Defining a Maven2 Installation
+ 
+ From the menu, choose the 'Installations' entry 
   
 [../images/installations.png] Installations
 
@@ -20,9 +73,7 @@
 
 [../images/installation-tool-edit.png] Tool Setup
 
-  You can use the checkbox if you want to add a Profile with the same name as your tool name.
-  
-  The value 'Value/Path' field must contains the path to the tool :
+  The value 'Value/Path' field must specify the path to the tool:
   
   * For maven2 : it must be similar to your M2_HOME
   
@@ -30,14 +81,46 @@
   
   * For ant : it must be similar to your ANT_HOME
 
-  A control will be made to validate the path value :
+  []
+
+  Continuum validates the path specified depending on the type of Tool:
   
-  * For maven2 : path/bin/mvn -v will be tested
+  * For maven2 : \<path\>/bin/mvn -v will be tested
   
-  * For maven1 : path/bin/maven -v will be tested
+  * For maven1 : \<path\>/bin/maven -v will be tested
   
-  * For ant : path/bin/ant -v will be tested
+  * For ant : \<path\>/bin/ant -v will be tested
+
+  []
   
-  It the the test, the following error will be displayed 
+  If the path you specify fails the test, the following error will be displayed:
   
 [../images/installation-validation-failed.png] Installation validation failed   
+  
+ You can use the checkbox if you want to create a Build Environment with the
+ same name as your Tool name. 
+
+**Environment Variables
+ 
+ Environment Variables are simply a means to store environment settings using a
+ human-friendly name. Once defined, they can be used to affect the build tools
+ used to build your projects. They consist of a human-friendly name, the name of
+ the environment variable to set and the value. Unlike Tools, Environment
+ Variables are not constrained by continuum. No validation is performed to
+ validate the values. 
+
+***Example: Defining a Java Heap size Environment Variable for Maven2 Tools
+
+ From the menu, choose the 'Installations' entry
+
+[../images/installations.png] Installations
+
+ Select the Environment Variable Installation type
+
+[../images/installation-type-choice-envvar.png] Select env var as tool type
+
+ And finally, specify the human-friendly name, the environment variable name and
+ the corresponding value. Here we define MAVEN_OPTS that will set the Java heap
+ size to 256 Megabytes.
+ 
+[../images/installation-envvar-edit.png] Define the env var name and value
diff --git a/continuum-docs/src/site/apt/administrator_guides/chroot.apt b/continuum-docs/src/site/apt/administrator_guides/chroot.apt
index 89a1b14..ec0d7b2 100644
--- a/continuum-docs/src/site/apt/administrator_guides/chroot.apt
+++ b/continuum-docs/src/site/apt/administrator_guides/chroot.apt
@@ -6,6 +6,23 @@
  June 5 2008
  ------
 
+~~ 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.
+
 Running builds in chroot jail
 
  Feature not yet finished! See {{{http://jira.codehaus.org/browse/CONTINUUM-1731}CONTINUUM-1731}}
diff --git a/continuum-docs/src/site/apt/administrator_guides/configuration.apt b/continuum-docs/src/site/apt/administrator_guides/configuration.apt
index 17dd377..933cf60 100644
--- a/continuum-docs/src/site/apt/administrator_guides/configuration.apt
+++ b/continuum-docs/src/site/apt/administrator_guides/configuration.apt
@@ -6,6 +6,23 @@
  Oct 11 2007
  ------
 
+~~ 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.
+
 Managing General Configuration
 
     The first time you start Continuum, you will see the 'General Configuration' page. This page is preconfigured with default values.
@@ -17,14 +34,20 @@
 *---------------------------------+------------------------------------------------------+
 | Build Output Directory          | The directory where all build output will be stored |
 *---------------------------------+------------------------------------------------------+
+| Release Output Directory        | The directory where all release output will be stored |
+*---------------------------------+------------------------------------------------------+
 | Deployment Repository Directory | The directory where generated maven2 artifacts will be stored. This directory will be respect a repository structure. It is independant of the maven deploy phase |
 *---------------------------------+------------------------------------------------------+
 | Base URL                        | The base Continuum URL. This URL is used in notifications |
 *---------------------------------+------------------------------------------------------+
+| Number of Allowed Builds in Parallel | The number of build queues that will be utilized to build projects. This allows concurrent checkouts and builds of multiple projects. Available since version 1.3.1. |
+*---------------------------------+------------------------------------------------------+
 | Enable Distributed Builds       | When checked, this Continuum instance will delegate all builds to configured agents. |
 *---------------------------------+------------------------------------------------------+
+| Shared Secret Password          | The pre-shared key (PSK) between the master and all configured agents. The PSK will need to be copied to all configured agents. |
+*---------------------------------+------------------------------------------------------+
 
-    You can modify values or keep defaults then save.
+    You can modify values or keep defaults then save. 
 
     Although Continuum defaults to storing its data within the installation, it is a best practice to separate the
     installation and data directories.
diff --git a/continuum-docs/src/site/apt/administrator_guides/distributed-builds.apt b/continuum-docs/src/site/apt/administrator_guides/distributed-builds.apt
index 10d0b27..0281c72 100644
--- a/continuum-docs/src/site/apt/administrator_guides/distributed-builds.apt
+++ b/continuum-docs/src/site/apt/administrator_guides/distributed-builds.apt
@@ -1,25 +1,155 @@
  ------------------
  Distributed Builds
  ------------------
+ ------------------
+ 2010-02-22
+ ------------------
 
+~~ 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.
 
 Understanding Distributed Builds
 
-  When the 'Distributed Builds' option in General Configuration is enabled, the Continuum instance will become the
-  Master and will delegate all builds to configured Build Agents.
+* Introduction
 
-  There is a one to many relationship between the master and the agents.  A master may have many agents, but each
-  agent only has one master.
+    The Distributed Builds is an extension to the base Continuum
+    functionalities that gives us the ability to process multiple independent
+    builds beyond the capacity of a single server's processing power.  It also
+    enables us to execute builds on multiple different platforms while
+    retaining a unified view of all project builds.
 
-  Communication happens over XML-RPC, first with the Master contacting an agent to supply the necessary info and invoke
-  a build, and then with the agent later contacting the master to return the build results.
+* Architecture
 
-  An agent may be installed on the same server as the master, or on a separate server.
+    Continuum follows a Client-Server model using XML-RPC as the protocol.
+    However, since it uses a bi-directional XML-RPC implementation, we instead
+    distinguish the components by calling them Master and Build Agent.
 
-  More than one agent may be installed on a server.
+    The Master is a Continuum instance that has the ability to
+    delegate the builds to registered Build Agents.
 
-  TODO:  When a build is enqueued, the choice of which agent to use is defined by ____.
+    The Build Agent is a standalone Jetty-bundled webapp that
+    listens for any build requests from the Master it is
+    assigned to.
 
-  TODO:  How are multi-module projects handled?
+    There is a one-to-many relationship between the Master and the Build Agents.
+    A Master may have many Build Agents, but each Build Agent can only have one Master.
 
-  TODO:  How are releases handled?
+~~TODO: insert image here
+
+* Behavior
+
+    Distributed Builds happen at the project group level of Continuum.
+    When the entire project group is built in the Master, independent projects
+    (single project or multi-module project) are distributed to a single
+    registered Build Agent.
+
+    In a project group containing a mix of projects, the distribution of work
+    goes through the following steps:
+
+    [[1]] In the Master, a build in the project group is triggered.
+
+    [[2]] Every independent project within the project group is identified,
+    whether as a single project or a multi-module project.  Projects with
+    inter-dependencies cannot be distributed separately, so multi-module
+    projects are delegated to a Build Agent as one build.
+
+    [[3]] For each independent project, the Master iterates over the list of
+    registered Build Agents and queries each if available.  The query is an XML-RPC
+    <<<ping()>>> followed by a <<<getBuildSizeOfAgent()>>> invocation.
+
+    [[4]] If there is a Build Agent available, the Master collects the information
+    necessary for the build (SCM URL, project id, etc.) and passes it when
+    invoking <<<buildProjects()>>> to the Build Agent with the smallest number of
+    tasks in its queue. The Master also passes the <<<name>>> of the local repository
+    of the project's project group. Make sure that a local repository with the same <<<name>>>
+    is configured in the Build Agent's configuration file since that is what will be 
+    used when the project is built in the build agent. Otherwise, it will use the 
+    local repository set in the build agent's <<<settings.xml>>> file.
+
+    [[5]] In the Build Agent, the build request is processed: the build is queued and
+    executed.  Upon execution, the Build Agent first performs an SCM checkout or an SCM
+    update followed by an SCM changelog to get the latest update date, then the actual build follows.
+
+    [[6]] At this point, when the build is running, the Master can invoke
+    <<<cancelBuild()>>> which returns a transient build result, and
+    <<<getBuildResult()>>> that updates the build output viewed in the Master.
+
+    [[7]] After the build, the Build Agent returns the complete build result to the
+    Master by invoking the callback method <<<returnBuildResult()>>>, which the
+    Master aggregates to provide a unified view of projects.
+
+    A <<<ping()>>> is always called before each XML-RPC invocation to check if 
+    the agent is available. If it's not, the agent will be disabled.
+
+~~TODO: insert sequence diagram here
+
+* Setup
+
+    * {{{./configuration.html}Enable}} the Distributed Builds option and set the Shared Secret Password in the General Configuration.
+
+    * {{{../installation/build-agent.html}Install and Configure}} one or more Build Agents.
+
+    * {{{./build-agents.html}Add}} your Build Agents to the Continuum Master.
+
+    * {{{./build-agent-groups.html}Add}} your Build Agents to a Build Agent Group.
+
+    * {{{./buildEnvironment.html} Add}} your Build Agent Group to a Build Environment.
+
+    * Configure a project to use that Build Environment.
+
+    * Make sure that the {{{./localRepository.html} local repository}} of the {{{./projectgroup.html} project group}} is properly configured.
+    In this case, it should point to the path of the repository where the Build Agent is installed/running.
+
+    []
+
+    <<Warning:>> You need to have a central remote repository to store the artifacts created from the Build Agent so that other agents will be able to use the new artifacts.
+
+* Limitations
+
+    * Only system administrator can enable/disable distributed builds
+
+    * Credentials (i.e. svn credentials) are passed along if specified, but if server cache is used it will need to be done individually on the Build Agents
+
+    * There is no tracking of SCM changes
+
+    * The Build Agent needs a configuration web interface
+
+    * All projects in a project group will be distributed to the same Build Agent
+
+* Future Enhancements
+
+    * Remote builders
+
+        * Builders can be installed on remote machines, a Continuum manager will send actions to run to builders. An action can be something to run on all builders, on some of them or eventually only to an available builder if we don't want to run more than one build. Actions can be sent with JMS and builders can apply some filters if they don't want to receive all actions. With that, we can do some parallel builds but the dependency tree must be respected for the build order. To work correctly with dependencies, each builder must use a central local repository. Maybe we can use an internal Archiva.
+
+        * With Continuum builders configured to receive all commands, users can run multi-platform build for each build definition execution.
+
+        * With Continuum builders configured to receive only some project types, users can use a different builder by project group. In this case, the build of all projects will be done quickly because commands are balanced on several servers.
+
+        * With Continuum builders configured to build something when it is available, users can install builders on several machine to balance the charge. In this case, it will be possible to run some parallel builds.
+
+        * When the builders work is done, a message will be sent to the manager to notify the end of the process.
+
+        * With JMS used for the communication, we can add some listeners to create reports/statistics, log some information.
+
+    * Policy-based distribution
+
+        * Next available
+
+        * Load balanced
+
+        * Targeted environment matching
diff --git a/continuum-docs/src/site/apt/administrator_guides/external-db.apt b/continuum-docs/src/site/apt/administrator_guides/external-db.apt
index a12f45d..e51f916 100644
--- a/continuum-docs/src/site/apt/administrator_guides/external-db.apt
+++ b/continuum-docs/src/site/apt/administrator_guides/external-db.apt
@@ -6,6 +6,23 @@
  Oct 12 2007
  ------
 
+~~ 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.
+
 How to use an external database?
 
 * Supported databases
@@ -14,18 +31,52 @@
 
     * MySQL
 
-    * MS SQL Server
+    * Postgres
 
-    * Oracle (not yet, but coming soon)
+    * MS SQL Server (with modifications)
+
+    * Oracle (with modifications)
 
 * Configure Continuum
 
+  There is some information in the installation guides for the {{{../installation/standalone.html} standalone Continuum
+  installation}} and the {{{../installation/tomcat.html} Continuum web application deployed to Tomcat}}.
+
 ** Standalone version
 
-    To use an external database with Continuum standalone, you must configure DataSources in <<<$CONTINUUM_HOME/conf/jetty.xml>>>
+    To use an external database with Continuum standalone, you must configure DataSources in <<<$CONTINUUM_HOME/contexts/continuum.xml>>>
 
-%{snippet|id=datasources|url=http://svn.apache.org/repos/asf/continuum/trunk/continuum-jetty/src/main/conf/jetty.xml}
+%{snippet|id=datasources|url=http://svn.apache.org/repos/asf/continuum/trunk/continuum-jetty/src/main/contexts/continuum.xml}
 
-** Webapp
+    In addition, you must add the JDBC driver to the <<<$CONTINUUM_HOME/lib>>> directory, and update
+    <<<$CONTINUUM_HOME/conf/wrapper.conf>>> to list the driver instead of Derby. For example:
 
-    To use an external database with the Continuum webapp, you should configure the DataSource in your container.
+----
+wrapper.java.classpath.15=%REPO_DIR%/postgresql-8.4-702.jdbc3.jar
+----
+
+    If you use MS SQL Server or Oracle, you will need to adjust the
+    <<<$CONTINUUM_HOME/apps/continuum/WEB-INF/classes/META-INF/plexus/application.xml>>> file to change the
+    <<<javax.jdo.option.Mapping>>> value from <<<default>>> to <<<mssql>>> or <<<oracle>>> respectively. Bear in mind that
+    this change will need to be made again across release upgrades.
+
+%{snippet|id=mapping|url=http://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp/src/main/resources/META-INF/plexus/application.xml}
+
+** Web Application
+
+    To use an external database with the Continuum web application, you should configure the DataSource in your container.
+
+    Make sure the JDBC driver is available in the expected location for your container.
+
+    If you use MS SQL Server or Oracle, you will need to adjust the
+    <<<WEB-INF/classes/META-INF/plexus/application.xml>>> file in the unpacked web application to change the
+    <<<javax.jdo.option.Mapping>>> value from <<<default>>> to <<<mssql>>> or <<<oracle>>> respectively. Bear in mind that
+    this change will need to be made again across release upgrades.
+
+%{snippet|id=mapping|url=http://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp/src/main/resources/META-INF/plexus/application.xml}
+
+* Shutdown Procedure
+
+   When using an external database, it is very important to stop Continuum prior to stopping or restarting the database.
+   Continuum may exhibit unpredictable behavior if the database disappears while it is running, and may not recover
+   once the database comes back up.  If this happens, you must re-start Continuum.
diff --git a/continuum-docs/src/site/apt/administrator_guides/index.apt b/continuum-docs/src/site/apt/administrator_guides/index.apt
index 7a3e47a..c899495 100644
--- a/continuum-docs/src/site/apt/administrator_guides/index.apt
+++ b/continuum-docs/src/site/apt/administrator_guides/index.apt
@@ -3,39 +3,66 @@
  ------
  Emmanuel Venisse
  ------
- Oct 3 2007
+ 2010-02-18
  ------
 
+~~ 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.
+
 Administrator's Guides
 
- * {{{security/index.html}Managing Users and Security}}
+ * {{{./security/index.html}Managing Users and Security}}
 
- * {{{projectgroup.html}Adding a Project Group}}
+ * {{{./projectgroup.html}Managing Project Groups}}
 
- * {{{builder.html}Managing Builders}}
+ * {{{./builder.html}Managing Installations}}
 
- * {{{jdk.html}Managing JDKs}}
+ * {{{./buildEnvironment.html}Managing Build Environments}}
 
- * {{{profiles.html}Managing Build Environments}}
+ * {{{./build-agents.html}Managing Build Agents}}
 
- * {{{build-agents.html}Managing Build Agents}}
+ * {{{./build-agent-groups.html}Managing Build Agent Groups}}
 
- * {{{schedules.html}Managing Schedules}}
+ * {{{./schedules.html}Managing Schedules}}
 
- * {{{configuration.html}Managing General Configuration}}
+ * {{{./configuration.html}Managing General Configuration}}
 
- * {{{localRepository.html}Managing Local Repositories}}
+ * {{{./localRepository.html}Managing Local Repositories}}
 
- * {{{purgeConfiguration.html}Managing Purge Configuration}}
+ * {{{./purgeConfiguration.html}Managing Purge Configuration}}
 
- * {{{external-db.html}External Databases}}
+ * {{{./parallelBuilds.html}Managing Parallel Builds}}
 
- * {{{monitoring.html}Monitoring Continuum}}
+ * {{{./buildQueue.html}Managing Build Queues}}
 
- * {{{appearance.html}Appearance Configuration}}
+ * {{{./queues.html}Managing Project Queues}}
 
- * {{{builddefTemplate.html}Build Definition Templates}}
+ * {{{./external-db.html}External Databases}}
 
- * {{{shutdown.html}Shutting Down Continuum}}
+ * {{{./monitoring.html}Monitoring Continuum}}
 
- * {{{distributed-builds.html}Distributed Builds}}
\ No newline at end of file
+ * {{{./logging/index.html} Log Files}}
+
+ * {{{./appearance.html}Appearance Configuration}}
+
+ * {{{./builddefTemplate.html}Build Definition Templates}}
+
+ * {{{./shutdown.html}Shutting Down Continuum}}
+
+ * {{{./distributed-builds.html}Understanding Distributed Builds}}
+
+ * {{{./webdav.html} Accessing remote working copies using WebDAV}}
diff --git a/continuum-docs/src/site/apt/administrator_guides/jdk.apt b/continuum-docs/src/site/apt/administrator_guides/jdk.apt
deleted file mode 100755
index 6cc24ff..0000000
--- a/continuum-docs/src/site/apt/administrator_guides/jdk.apt
+++ /dev/null
@@ -1,31 +0,0 @@
- ------
- Managing JDKs
- ------
- Olivier Lamy
- ------
- Oct 11 2007
- ------
- 
-Managing JDKs
-
-  From the menu, choose the 'Installations' entry 
-  
-[../images/installations.png] Installations
-
-  Here you must choose the Installation Type you want to add (here a Tool)
-
-[../images/installation-type-choice.png] Installation Type Choice
-
-  You must configure the tool you want to add
-
-[../images/add-jdk.png] Tool Setup
-
-  You can use the checkbox if you want to add a Profile with the same name as your jdk name.
-  
-  The value 'Value/Path' field must contain the jdk path (as a <<<JAVA_HOME>>> value).
-  
-  The value will validated by testing path<<</bin/java -version>>>
-  
-  If the test fails, the following error will be displayed
-  
-[../images/jdk-validation-failed.png] Jdk validation failed   
diff --git a/continuum-docs/src/site/apt/administrator_guides/localRepository.apt b/continuum-docs/src/site/apt/administrator_guides/localRepository.apt
index a1ebe9c..b8860b3 100644
--- a/continuum-docs/src/site/apt/administrator_guides/localRepository.apt
+++ b/continuum-docs/src/site/apt/administrator_guides/localRepository.apt
@@ -1,39 +1,66 @@
  ------
  Local Repository
  ------
- 
+ ------
+ 2010-02-18
+ ------
+
+~~ 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.
+
 Local Repository
 
+  Local repositories can be configured for a specific project group's use.
+  This is where the artifacts used for building the projects can be found
+  instead of the default (<<<$USER_HOME/.m2/repository>>>).
+
 	Click the <<Local Repositories>> link under the <<Administration>> section
 
 [../images/localrepositories.png] Local Repositories
 
 	You will see all the local repositories that have been created.
-	
+
 	To display:
-	
+
 [../images/localrepositories-view.png]
-	
-	In this screen you can add/edit/delete/purge a local repository. 
-	
-	You can purge a repository if it has a default {{{purgeConfiguration.html} Purge Configuration}}, otherwise the purge icon is disabled.
+
+	In this screen you can add/edit/delete/purge a local repository.
+
+	You can purge a repository if it has a default {{{./purgeConfiguration.html} Purge Configuration}}, otherwise the purge icon is disabled.
 
 [../images/disabled_purgenow.gif] disabled purge icon
 
 
 * Adding / Editing a Local Repository
 
-	All fields are mandatory. 
-	
+	All fields are mandatory.
+
 	* Name: must be a unique repository name.
-	
+
 	* Location: must be the absolute path of a unique repository location.
-	
+
 	* Layout: "default" or "legacy". Default layout is for maven2, while legacy layout is for maven1.
 
 [../images/localrepository-add.png]
+
+	Adding a local repository will automatically create a default {{{./purgeConfiguration.html} Purge Configuration}} for that repository.
 	
-	Adding a local repository will automatically create a default {{{purgeConfiguration.html} Purge Configuration}} for that repository.
+	If you're using distributed builds, you must configure a <<<localRepository>>> with the same <<<name>>> in the build agent's configuration file where the
+	<<<location>>> is the local path to the local repository in the build agent machine. See {{{./distributed-builds.html}Distributed Builds}} for more details.
 
 * Default
 
@@ -41,3 +68,6 @@
 
     The default local repository location comes from the settings of the user running Continuum.  The location cannot be
     edited within Continuum, but can be changed by specifying it in <<<~/.m2/settings.xml>>>.
+    
+    On Windows 7, you can pass the argument <<<-Duser.home=C:\Users\\\<Username\>\\>>> to the JVM explicitly. Since running Continuum as an Administrator
+    will give you a different <<<user.home>>> value.
diff --git a/continuum-docs/src/site/apt/administrator_guides/logging/audit-logs.apt b/continuum-docs/src/site/apt/administrator_guides/logging/audit-logs.apt
new file mode 100644
index 0000000..6e39265
--- /dev/null
+++ b/continuum-docs/src/site/apt/administrator_guides/logging/audit-logs.apt
@@ -0,0 +1,63 @@
+ ------
+ Audit Logs
+ ------
+ Jevica Arianne B. Zurbano
+ ------
+ 23 Jul 2009
+ ------
+
+~~ 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.
+
+Audit Logs
+
+  Continuum's <<<logs>>> directory contains an audit log file named <<<continuum-audit.log>>>,
+  which tracks events that occur in the server.
+  For security measure, passwords are masked behind asterisks.
+
+  A typical record looks like this:
+
+----
+2009-07-22 12:27:58 - admin - BUILD_SCHEDULE BI_HOURLY - Added Build Schedule
+2009-07-22 12:28:23 - admin - BUILD_SCHEDULE BI_HOURLY - Modified Build Schedule
+2009-07-22 12:29:56 - admin - PROJECT http://svn.apache.org/repos/asf/continuum/trunk/pom.xml - Added M2 Project
+2009-07-22 12:31:00 - admin - PROJECT Project Group id=6 - Forced Project Build
+----
+
+  The space delimited records are:
+
+    * date and time (server local time)
+
+    * user that enacted the change (or guest if none)
+
+    * the project or configurations affected
+
+    * the event that occurred
+
+  Currently, the following events are logged:
+
+    * add/delete of projects
+    
+    * forced project builds
+    
+    * release prepare/perform/rollback
+    
+    * add/edit/delete of schedules
+    
+    * add/edit/delete of build definition templates
+    
+    []
diff --git a/continuum-docs/src/site/apt/administrator_guides/logging/continuum-logs.apt b/continuum-docs/src/site/apt/administrator_guides/logging/continuum-logs.apt
new file mode 100644
index 0000000..8c305ec
--- /dev/null
+++ b/continuum-docs/src/site/apt/administrator_guides/logging/continuum-logs.apt
@@ -0,0 +1,59 @@
+ ------
+ Continuum Logs
+ ------
+ Jevica Arianne B. Zurbano
+ ------
+ 23 Jul 2009
+ ------
+ 
+~~ 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.
+
+Continuum Logs
+
+  Continuum's <<<logs>>> directory contains an continuum log file named <<<continuum.log>>>,
+  which logs all the startup information of Continuum.
+
+  A typical record looks like this:
+
+------
+2009-07-22 11:57:48,397 [WrapperSimpleAppMain] INFO  org.apache.maven.continuum.DefaultContinuum  - Initializing Continuum.
+2009-07-22 11:57:48,397 [WrapperSimpleAppMain] INFO  org.apache.maven.continuum.DefaultContinuum  - Showing all groups:
+2009-07-22 11:57:48,912 [WrapperSimpleAppMain] INFO  org.apache.maven.continuum.DefaultContinuum  - Showing all projects: 
+2009-07-22 11:57:49,081 [WrapperSimpleAppMain] INFO  org.apache.maven.continuum.DefaultContinuum  - Starting Continuum.
+2009-07-22 11:57:49,082 [WrapperSimpleAppMain] INFO  org.apache.maven.continuum.DefaultContinuum  - 
+2009-07-22 11:57:49,082 [WrapperSimpleAppMain] INFO  org.apache.maven.continuum.DefaultContinuum  - 
+2009-07-22 11:57:49,083 [WrapperSimpleAppMain] INFO  org.apache.maven.continuum.DefaultContinuum  - < Continuum 1.3.2 started! >
+2009-07-22 11:57:49,083 [WrapperSimpleAppMain] INFO  org.apache.maven.continuum.DefaultContinuum  - ------------------------------------
+2009-07-22 11:57:49,083 [WrapperSimpleAppMain] INFO  org.apache.maven.continuum.DefaultContinuum  -        \   ^__^
+2009-07-22 11:57:49,083 [WrapperSimpleAppMain] INFO  org.apache.maven.continuum.DefaultContinuum  -         \  (oo)\_______
+2009-07-22 11:57:49,083 [WrapperSimpleAppMain] INFO  org.apache.maven.continuum.DefaultContinuum  -            (__)\       )\/\
+2009-07-22 11:57:49,083 [WrapperSimpleAppMain] INFO  org.apache.maven.continuum.DefaultContinuum  -                ||----w |
+2009-07-22 11:57:49,084 [WrapperSimpleAppMain] INFO  org.apache.maven.continuum.DefaultContinuum  -                ||     ||
+2009-07-22 11:57:49,084 [WrapperSimpleAppMain] INFO  org.apache.maven.continuum.DefaultContinuum  - 
+2009-07-22 11:57:49,084 [WrapperSimpleAppMain] INFO  org.apache.maven.continuum.DefaultContinuum  - 
+2009-07-22 11:57:49,084 [WrapperSimpleAppMain] INFO  org.apache.maven.continuum.initialization.DefaultContinuumInitializer  -
+  Continuum initializer running ...
+2009-07-22 11:57:49,177 [WrapperSimpleAppMain] INFO  org.apache.maven.continuum.initialization.DefaultContinuumInitializer  -
+  Default Project Group exists
+2009-07-22 11:57:49,177 [WrapperSimpleAppMain] INFO  org.apache.maven.continuum.initialization.DefaultContinuumInitializer  -
+  Continuum initializer end running ...
+2009-07-22 11:57:49,186 [WrapperSimpleAppMain] INFO  org.apache.maven.continuum.build.settings.DefaultSchedulesActivator  -
+  Activating schedules ...
+2009-07-22 11:57:49,236 [WrapperSimpleAppMain] INFO  org.apache.maven.continuum.build.settings.DefaultSchedulesActivator  -
+  DEFAULT_SCHEDULE: next fire time ->Wed Jul 22 12:00:00 PHT 2009
+------
diff --git a/continuum-docs/src/site/apt/administrator_guides/logging/index.apt b/continuum-docs/src/site/apt/administrator_guides/logging/index.apt
new file mode 100644
index 0000000..39865f7
--- /dev/null
+++ b/continuum-docs/src/site/apt/administrator_guides/logging/index.apt
@@ -0,0 +1,41 @@
+ ------
+ Log Files
+ ------
+ Jevica Arianne B. Zurbano
+ ------
+ 2010-02-19
+ ------
+
+~~ 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.
+
+Log Files
+
+  To keep track of the Continuum performance and problems, log files are created during runtime.
+  These files can be found in the <<<logs/>>> directory.
+
+  * {{{./continuum-logs.html} <<continuum.log>>}} - contains all the start-up information for Continuum.
+
+  * {{{./audit-logs.html} <<continuum-audit.log>>}} - contains information regarding the project operations and configurations being modified.
+                            For example, projects added are logged here, with date and timestamp,
+                            userId of who performed the deploy, and the project that was built.
+                            For security measure, passwords are masked behind asterisks.
+
+  * {{{./security-logs.html} <<continuum-security-audit.log>>}} - contains information regarding Continuum's security.
+                            For example, a successful login of a user or a user account is created.
+
+  []
diff --git a/continuum-docs/src/site/apt/administrator_guides/logging/security-logs.apt b/continuum-docs/src/site/apt/administrator_guides/logging/security-logs.apt
new file mode 100644
index 0000000..3139fb9
--- /dev/null
+++ b/continuum-docs/src/site/apt/administrator_guides/logging/security-logs.apt
@@ -0,0 +1,59 @@
+ ------
+ Security Logs
+ ------
+ Jevica Arianne B. Zurbano
+ ------
+ 23 Jul 2009
+ ------
+ 
+~~ 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.
+
+Security Logs
+
+  Continuum's <<<logs>>> directory contains a security log file named <<<continuum-security-audit.log>>>,
+  which keeps track of all the security operations.
+  
+  A typical record looks like this:
+
+------
+2009-07-22 12:32:00 - admin - User Created: continuum
+2009-07-22 12:32:10 - admin - Role Assigned to user continuum: Continuum Group Project Administrator
+2009-07-22 12:32:17 - admin - User Modified: continuum
+2009-07-22 12:32:34 -  - Logged Out user admin
+2009-07-22 12:32:47 -  - Successful Login for user continuum
+------
+
+  The hyphen delimited records are:
+
+    * date and time (server local time)
+    
+    * current user performing the operation
+    
+    * the operation performed
+    
+    []
+    
+  Currently, the following events are logged:
+
+    * user creation/modification/deletion
+    
+    * user log in/out
+    
+    * assigning roles to a user
+    
+    []
diff --git a/continuum-docs/src/site/apt/administrator_guides/monitoring.apt b/continuum-docs/src/site/apt/administrator_guides/monitoring.apt
index 153fd2a..7d2d191 100644
--- a/continuum-docs/src/site/apt/administrator_guides/monitoring.apt
+++ b/continuum-docs/src/site/apt/administrator_guides/monitoring.apt
@@ -6,11 +6,28 @@
  Oct 3 2007
  ------
 
+~~ 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.
+
 Monitoring a Continuum instance
 
 * JConsole
 
-    * Edit $CONTINUUM_HOME/bin/\[platform\]/wrapper.conf to add:
+    * Edit <<<$CONTINUUM_HOME/bin/\[platform\]/wrapper.conf>>> to add:
 
 ------------------------
 wrapper.java.additional.9=-Dcom.sun.management.jmxremote
@@ -63,4 +80,4 @@
 
 * References
 
-    * [http://java.sun.com/developer/technicalArticles/J2SE/jconsole.html]
+    * {{http://java.sun.com/developer/technicalArticles/J2SE/jconsole.html}}
diff --git a/continuum-docs/src/site/apt/administrator_guides/parallelBuilds.apt b/continuum-docs/src/site/apt/administrator_guides/parallelBuilds.apt
new file mode 100644
index 0000000..11cd0f0
--- /dev/null
+++ b/continuum-docs/src/site/apt/administrator_guides/parallelBuilds.apt
@@ -0,0 +1,64 @@
+ ------
+ Parallel Build Queue
+ ------
+ ------
+ 2010-02-18
+ ------
+
+~~ 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.
+
+Managing Parallel Builds
+
+    Since 1.3.1, Continuum can be configured to checkout and build projects in parallel or concurrently.
+
+* Configuring Parallel Builds
+
+    The number of build queues to be used when checking out or building projects can be configured in the Configuration page, via
+    the Number of Allowed Builds in Parallel field (see {{{./configuration.html} Managing General Configuration}}).
+    The value should be greater than one (1) to be able to create a build queue aside from the default.
+
+    Another thing to note is that if Distributed Builds is enabled, Parallel Builds is automatically disabled. To make it
+    short, you're only allowed to use one of these functionalities at a time in the current implementation.
+
+    To configure parallel builds:
+
+    [[1]] Create a build queue to be used for the projects.
+          Refer to {{{./buildQueue.html} Managing Build Queues}}
+
+    [[2]] Attach the build queue(s) to a build schedule.
+          Refer to {{{./schedules.html} Attaching Build Queue to a Schedule}}
+
+    [[3]] Create or edit the project's build definition to use the build schedule configured with the build queue(s).
+          Refer to {{{../user_guides/managing_builddef/index.html} Managing Build Definitions}}
+
+    []
+
+    A screen similar to the following is displayed under the <<Queues>> page when the project is built (force/sheduled).
+
+[../images/parallelBuildsQueues.png] Queues
+
+* Limitations
+
+    Below are some feature limitations for the current implementation:
+
+    [[1]] Project groups cannot be built multiple times simulateously.
+
+    [[2]] Concurrent build of inter-dependent projects in a group is not yet supported.
+
+    [[3]] All projects in a project group will be enqueued to the same {{{./buildQueue.html} Build Queue}}.
+
diff --git a/continuum-docs/src/site/apt/administrator_guides/profiles.apt b/continuum-docs/src/site/apt/administrator_guides/profiles.apt
deleted file mode 100755
index c10e77b..0000000
--- a/continuum-docs/src/site/apt/administrator_guides/profiles.apt
+++ /dev/null
@@ -1,62 +0,0 @@
- ------
- Continuum :: Build Environment
- ------
- Olivier Lamy
- ------
- Oct 17 2007
- ------
-
-Build Environment
-
-~~%{toc|section=0}
-
-* Goal
-
-  The main goal is to compile/test sources against the targeted jvm, mvn/maven version, ant version and to add defined
-  envvar (MAVEN_OPTS, ANT_OPTS ...).  This is now possible at the build definition level (in 1.1).
-
-* Setup Build Environments/Installations
-
-** {Creating a Build Environment}
-
-  From the menu, choose the 'Build Environments' entry
-
-[../images/buildenv-menu.png] Build Environment Menu
-
-  Enter a name
-
-[../images/buildenv-add.png] Add Build Environment
-
-** {Attach JDK to a Build Environment}
-
-  The list box contains all available installations (jdk, mvn etc..). The installation's type is automatically recognized.
-  In the modification mode of a build environment, adding an already attached type will override the existing one.
-
-[../images/buildenv-setup-jdk.png] Add JDK to Build Environment
-
-** {Link Build Environment to Build Definition}
-
-  The list box contains all availables installations (jdk, mvn etc..). The installation's type is automatically recognized.
-  In the modification mode of a build environment, adding an already attached type will override the existing one.
-
-[../images/buildenv-in-builddef.png] Setup Build Environment
-
-** {Installations used in Notification mail}
-
-  The notification mail contains the following informations :
-
-  * Java Home version : coming from $JAVA_HOME/bin/java -version.
-
-  * Builder version : coming from builder used version arg (mvn  used -v, ant use -version).
-
-  []
-
-+-------------------------------+
-  Java Home version : 
-          java version "1.4.2_06"
-          Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_06-b03)
-          Java HotSpot(TM) Client VM (build 1.4.2_06-b03, mixed mode)
-        
-  Builder version :
-          Maven version: 2.0.5 
-+-------------------------------+
diff --git a/continuum-docs/src/site/apt/administrator_guides/projectgroup.apt b/continuum-docs/src/site/apt/administrator_guides/projectgroup.apt
index 5397b94..100e037 100755
--- a/continuum-docs/src/site/apt/administrator_guides/projectgroup.apt
+++ b/continuum-docs/src/site/apt/administrator_guides/projectgroup.apt
@@ -1,26 +1,88 @@
  ------
- Adding Project Group
+ Managing Project Groups
  ------
  Olivier Lamy
  ------
- Oct 11 2007
+ 2010-02-18
  ------
 
-Adding Project Group
+~~ 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.
 
-  From the home page (Group Summary) Use the the 'Add Project Group' button
-  
+Managing Project Groups
+
+[../images/project-groups.png] Group Summary homepage
+
+* Adding a Project Group
+
+  From the home page (Group Summary) Use the the <<<Add Project Group>>> button
+
 [../images/add-project-group.png] Add Project Group
 
-  Then You will have the project Group detail. 
-    
+  Then You will have the project Group detail.
+
 [../images/add-project-group-detail.png] Edit Project Group detail
 
   Some fields are mandatory :
-    
+
   * Project Group Name
-    
+
   * Project Group Id
 
- 
-  
+  []
+
+* Editing a Project Group
+
+  From the home page (Group Summary), click the project group name link.
+
+  The project group information will then be displayed.
+
+[../images/project-group-summary.png] Project Group Summary
+
+  Then, click on the <<<Edit>>> button.
+
+[../images/update-project-group.png] Update Project Group
+
+  The following fields can be updated:
+
+  * <<Project Group Name>>: The name of the project group.
+
+  * <<Description>>: A brief description about the group.
+
+  * {{{./localRepository.html} <<Local Repository>>}}: The specific repository used for the project
+  which points to the exact location of the repository in the machine used for building.
+
+  * <<Homepage Url>>: The site of the project.
+
+  []
+
+  And, projects can be moved to another project group.
+
+* Deleting a Project Group
+
+  There are two ways to delete a project group.
+
+  From the home page (Group Summary), click the Delete icon to the right of the group you wish to delete.
+
+  From the Project Group Summary page, click the <<<Delete Group>>> button.
+
+  Confirm the deletion
+
+  Note that user roles for this project group will not be removed.  This is intentional so that if you are
+  sharing a user database among several Continuum instances, users will still be able to access the same
+  group on a different server.
+
diff --git a/continuum-docs/src/site/apt/administrator_guides/purgeConfiguration.apt b/continuum-docs/src/site/apt/administrator_guides/purgeConfiguration.apt
index 6ab91a2..b5c6762 100644
--- a/continuum-docs/src/site/apt/administrator_guides/purgeConfiguration.apt
+++ b/continuum-docs/src/site/apt/administrator_guides/purgeConfiguration.apt
@@ -2,6 +2,23 @@
  Purge Configuration
  ------
  
+~~ 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.
+
 Purge Configuration
 
 	Click the <<Purge Configurations>> link under the <<Administration>> section.
@@ -10,12 +27,15 @@
 
     You will see all repository purge configurations and all directory purge configurations.
 
+    *Note:* If you have distributed builds enabled, then repository purging is not currently available on build agents.
+    See {{{http://jira.codehaus.org/browse/CONTINUUM-2697} CONTINUUM-2697}} for information.
+
 [../images/purgeconfigurations-view.png]
 
     Here you can add/edit/delete the purge configuration.
     
     You can also purge the repository or directory by clicking the corresponding purge icon of the purge configuration.
-    
+
 [../images/purgenow.gif] purge now icon
 
 
@@ -76,4 +96,4 @@
 	* Delete released snapshots purging will always be performed if it is checked, unless the Delete All is also checked or it's a directory purging.
 	
 	
-	       
\ No newline at end of file
+	       
diff --git a/continuum-docs/src/site/apt/administrator_guides/queues.apt b/continuum-docs/src/site/apt/administrator_guides/queues.apt
index 181aaef..61b6945 100644
--- a/continuum-docs/src/site/apt/administrator_guides/queues.apt
+++ b/continuum-docs/src/site/apt/administrator_guides/queues.apt
@@ -6,20 +6,49 @@
  June 02 2008
  ------
 
+~~ 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.
+
 Managing Queues
 
-	Click the <<Queues>> link under the <<Administration>> section
+    Current checkouts and builds, and all other projects queued in the checkout, build, and prepare build queues
+    can be viewed in the <<Queues>> page.
 
 [../images/queues.png] Queues
 
-  To display :
+    Prepare Build Queue
   
-[../images/queues-view.png] Queues View  
-	
-	You must have a <<"Manage Continuum Queues">> role for you to:
+[../images/queues-prepare.png] Prepare Build Queue
 
-    [[1]] Cancel the current checkout, the current build, one of the checkout queue or build queue by clicking the  
+    Build Queues
+
+[../images/queues-view.png] Queues View  
+
+    Checkout Queue
+
+[../images/queues-checkout.png] Checkout Queue
+	
+	You must have a <<Manage Continuum Queues>> role for you to:
+
+    [[1]] Cancel current checkouts, current builds, queued prepare builds, queued checkouts and queued builds by clicking the  
 
 [../images/cancelbuild.gif] cancel build icon.
   
-    [[2]] Cancel multiple queues by selecting the corresponding checkboxes of the queues you want to cancel and then click the <<Cancel Entries>> button.
\ No newline at end of file
+    [[2]] Cancel multiple queued tasks by selecting the corresponding checkboxes of the checkouts, builds, or project updates
+    you want to cancel and then click the <<Cancel Entries>> button.
+
+    Note: Cancelling current prepare build is not allowed to prevent data corruption.
diff --git a/continuum-docs/src/site/apt/administrator_guides/schedules.apt b/continuum-docs/src/site/apt/administrator_guides/schedules.apt
index 404ad09..93565b3 100755
--- a/continuum-docs/src/site/apt/administrator_guides/schedules.apt
+++ b/continuum-docs/src/site/apt/administrator_guides/schedules.apt
@@ -6,6 +6,75 @@
  Oct 11 2007
  ------
  
+~~ 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.
+
 Managing Schedules
 
-    Coming Soon
\ No newline at end of file
+    Schedules initiates the building of projects continuously. In this section,
+    adding, modifying, and deleting of schedules are discussed.
+    
+    Clicking the <<Schedules>> link from the menu on the left will display the following page:
+
+[../images/schedules.png] List of schedules page
+
+* Adding Schedules
+
+    To add a schedule, follow these steps:
+    
+    [[1]] Click the <<Add>> button below the list of schedules.
+    
+    [[2]] Fill in the needed information in the <<Edit Schedules>> page shown below.
+
+[../images/editSchedule.png] Adding a build schedule
+    
+        * <<Name>> The unique identifier of the schedule. This is a required field.
+        
+        * <<Description>> Brief description of the configured schedule. This is a required field.
+        
+        * <<Cron Expression>> Determines the exact time interval that the build schedule executes.
+        
+        * <<Maximum job execution time (seconds)>> This sets the maximum time for a job to be executed.
+            This is a required field.
+        
+        * <<Quiet Period (seconds)>> This a setting that delays the build if there has been a commit
+            in the defined number of seconds prior. This is useful when using CVS, since commits are
+            not atomic and a developer might be committing midway through an update. It is not typically
+            needed if using Subversion.
+        
+        *<<Add Build Queue>> Move build queues from the left hand list box to the right hand list box by
+            clicking the appropriate buttons in between the two list boxes. All build queues on the right
+            hand list box will be attached to the schedule.
+        
+        * <<Enabled>> When selected, scheduled build will be executed.
+        []
+
+    [[3]] Click <<Save>>.
+
+* Editing Schedules
+
+    To edit a schedule, follow these steps:
+    
+    [[1]] Click the edit icon which can be found to the right of the schedule.
+    
+    [[2]] Modify the fields in the <<Edit Schedules>> page.
+    
+    [[3]] Click <<Save>>.
+
+* Deleting Schedules
+    
+    To delete a schedule, click the delete icon, the rightmost icon inline with the schedule to be deleted.
diff --git a/continuum-docs/src/site/apt/administrator_guides/security/customising-security.apt b/continuum-docs/src/site/apt/administrator_guides/security/customising-security.apt
index 011e4dd..0b24a44 100644
--- a/continuum-docs/src/site/apt/administrator_guides/security/customising-security.apt
+++ b/continuum-docs/src/site/apt/administrator_guides/security/customising-security.apt
@@ -3,6 +3,23 @@
  -----
  2008-09-01
 
+~~ 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.
+
 Continuum Security Configuration
 
  Security properties and password rules can be configured in the
@@ -10,6 +27,8 @@
 
    * <<<~/.m2/security.properties>>>
   
+   * <<<$CONTINUUM_BASE/conf/security.properties>>>
+
    * <<<$CONTINUUM_HOME/conf/security.properties>>>
 
    []
@@ -50,3 +69,19 @@
  can be found in:
  <<<$CONTINUUM_HOME/apps/continuum/webapp/WEB-INF/classes/META-INF/plexus/application.xml>>>
 
+* Additional CSRF Prevention
+
+  To help prevent cross-site request forgery, it is possible to enable a basic check that the referrer is the current
+  site.
+
+  <Note:> This is only a generic solution that may prevent some types of attacks but not others. It may cause problems
+  with certain user agents. By default, the check is off.
+
+  To enable the check, change the following configuration value in the <<<struts.xml>>> file in the <<<WEB-INF/classes>>>
+  directory of the web application (2 locations):
+
+----
+<interceptor-ref name="redbackSecureActions">
+  <param name="enableReferrerCheck">false</param>
+</interceptor-ref>
+----
diff --git a/continuum-docs/src/site/apt/administrator_guides/security/index.apt b/continuum-docs/src/site/apt/administrator_guides/security/index.apt
index e9df223..ea8fa5c 100644
--- a/continuum-docs/src/site/apt/administrator_guides/security/index.apt
+++ b/continuum-docs/src/site/apt/administrator_guides/security/index.apt
@@ -3,11 +3,28 @@
  ------
  Emmanuel Venisse
  ------
- Oct 3 2007
+ 2010-02-18
  ------
 
+~~ 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.
+
 Managing Users and Security
 
-    {{{customising-security.html}Security Configuration}}
+    {{{./customising-security.html}Customising Security Configuration}}
 
-    {{{ldap.html}LDAP Configuration}}
+    {{{./ldap.html}LDAP Configuration}}
diff --git a/continuum-docs/src/site/apt/administrator_guides/security/ldap.apt b/continuum-docs/src/site/apt/administrator_guides/security/ldap.apt
index 4d5d7dd..c593cbc 100644
--- a/continuum-docs/src/site/apt/administrator_guides/security/ldap.apt
+++ b/continuum-docs/src/site/apt/administrator_guides/security/ldap.apt
@@ -6,35 +6,59 @@
  Oct 3 2007
  ------
 
+~~ 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.
+
 LDAP Configuration
 
     Continuum supports LDAP for authentication. To configure it, you should follow these steps:
 
     * Shutdown Continuum
 
-    * Open <<<apps/continuum/webapp/WEB-INF/classes/META-INF/plexus/application.xml>>> and uncomment the following xml
-
-    []
-
-%{snippet|id=ldap|url=http://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp/src/main/resources/META-INF/plexus/application.xml}
-
-    All you need to configure is the ConfigurableLdapConnectionFactory and LdapUserMapper components
-
-    * Add a security.properties files under $CONTINUUM_HOME/conf/ with the following content:
+    * Add a <<<security.properties>>> files under <<<$CONTINUUM_HOME/conf/>>> or <<<$CONTINUUM_BASE/conf>>> with the
+    following content:
 
 --------------------------------------------
+security.policy.password.expiration.enabled=false
+
 user.manager.impl=ldap
 ldap.bind.authenticator.enabled=true
-redback.default.admin=adminuser
-redback.default.guest=guestuser
-security.policy.password.expiration.enabled=false
-user.manager.impl=cached
-ldap.bind.authenticator.enabled=true
+
+ldap.config.context.factory=com.sun.jndi.ldap.LdapCtxFactory
+ldap.config.hostname=[ldap_hostname]
+ldap.config.base.dn=[ldap_base_dn]
+ldap.config.port=[ldap_port]
+ldap.config.mapper.attribute.user.id=cn
+ldap.config.mapper.attribute.user.email=email
+ldap.config.mapper.attribute.fullname=givenName
+ldap.config.mapper.attribute.password=userPassword
+
+redback.default.admin=[adminuser]
+# Optional
+# redback.default.guest=[guestuser]
 --------------------------------------------
 
-    <<adminuser>> is a LDAP user and will be the default Continuum admin. <<guestuser>> is a LDAP user and will be used for the <<<guest>>> role, generally, it is an utility LDAP account.
+    <<adminuser>> is a LDAP user and will be the default Continuum admin.
+    <<guestuser>> is a LDAP user and will be used for the <<<guest>>> role, generally, it is an utility LDAP account.
+    If not specified, then a built-in guest account will be used.
 
     * Restart Continuum
+    
+    []
 
 * Other resources
 
diff --git a/continuum-docs/src/site/apt/administrator_guides/shutdown.apt b/continuum-docs/src/site/apt/administrator_guides/shutdown.apt
index 5fd113e..26bc100 100644
--- a/continuum-docs/src/site/apt/administrator_guides/shutdown.apt
+++ b/continuum-docs/src/site/apt/administrator_guides/shutdown.apt
@@ -6,6 +6,23 @@
  Oct 5 2007
  ------
 
+~~ 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.
+
 Shutdown Continuum
 
     Shutting down Continuum while a project is building or queued is NOT recommended. The build queues page should be used to cancel any currently running and queued builds before shutting down.
diff --git a/continuum-docs/src/site/apt/administrator_guides/webdav.apt b/continuum-docs/src/site/apt/administrator_guides/webdav.apt
new file mode 100644
index 0000000..e036d5f
--- /dev/null
+++ b/continuum-docs/src/site/apt/administrator_guides/webdav.apt
@@ -0,0 +1,46 @@
+ --------------------
+ WebDAV support for working copies
+ --------------------
+ --------------------
+ --------------------
+
+~~ 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.
+
+WebDAV support for working copies
+
+  The WebDAV support is added in the continuum build agent only for retrieving the working copies of projects.
+
+* Example using Sardine
+
+  You can use {{{http://code.google.com/p/sardine/} Sardine}} for the WebDAV client.
+
+  The first sample will retrieve the directory listing for the project with id of 1.
+
+----
+Sardine sardine = SardineFactory.begin();
+List<DavResource> resources = sardine.getResources( "http://buildagenturl/workingcopy/1/" );
+----
+
+  The next sample will get an <<<InputStream>>> reference to a remote file.
+
+----
+Sardine sardine = SardineFactory.begin();
+InputStream is = sardine.getInputStream( "http://buildagenturl/workingcopy/1/pom.xml" );
+----
+
+
diff --git a/continuum-docs/src/site/apt/developer_guides/building.apt b/continuum-docs/src/site/apt/developer_guides/building.apt
index ecc6248..07beffe 100644
--- a/continuum-docs/src/site/apt/developer_guides/building.apt
+++ b/continuum-docs/src/site/apt/developer_guides/building.apt
@@ -1,31 +1,49 @@
  ------
- Guide to build Continuum
+ Guide to building Continuum
  ------
  Emmanuel Venisse
  ------
  Oct 3 2007
  ------
 
+~~ 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.
+
 Guide to building Continuum
 
 * Why would I want to build Continuum?
 
   You might want to build Continuum yourself for one of two reasons:
 
+    * To build the source release of Continuum
+
     * to try out a bleeding edge feature or bugfix (issues can be found in
       {{{http://jira.codehaus.org/browse/CONTINUUM} JIRA}}), but you can try our SNAPSHOTs: {{http://vmbuild.apache.org/}}
 
     * to fix a problem you are having and submit a patch to the development team.
 
-  Note that you don't need to build Continuum for day to day use. While we encourage getting
-  involved and fixing bugs that you find, for day to day use we recommend using the latest release.
+  Note that for releases, you may also make use of pre-built binaries.
 
 * Checking out the sources
 
-  All of the source code for Continuum and its related libraries is in a {{{http://subversion.tigris.org/} Subversion}} repository.
+  All of the source code for Continuum and its related libraries is in a Subversion repository.
   You can also {{{http://svn.apache.org/viewvc/continuum/} browse the repository}}, or checkout specific modules directly.
 
-  All SVN instructions are available on the {{{../../../source-repository.html}Source Repository page}}.
+  All SVN instructions are available on the {{{http://continuum.apache.org/source-repository.html}Source Repository page}}.
 
 * Building the sources
 
@@ -33,7 +51,7 @@
 
     * JDK 5 or greater
 
-    * Maven 2
+    * Maven 2.0.7 or greater
 	
 ** Building
 
@@ -41,4 +59,4 @@
 
 -----------------
 mvn clean install
------------------
\ No newline at end of file
+-----------------
diff --git a/continuum-docs/src/site/apt/developer_guides/index.apt b/continuum-docs/src/site/apt/developer_guides/index.apt
index 8e9ebb1..2767dbf 100644
--- a/continuum-docs/src/site/apt/developer_guides/index.apt
+++ b/continuum-docs/src/site/apt/developer_guides/index.apt
@@ -3,11 +3,28 @@
  ------
  Emmanuel Venisse
  ------
- Oct 3 2007
+ 2010-02-18
  ------
 
+~~ 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.
+
 Developer's Guides
 
- * {{{building.html}Building Continuum}}
+ * {{{./building.html}Building Continuum}}
 
- * {{{xmlrpc.html}XML-RPC}}
+ * {{{./xmlrpc.html}XML-RPC}}
diff --git a/continuum-docs/src/site/apt/developer_guides/xmlrpc.apt b/continuum-docs/src/site/apt/developer_guides/xmlrpc.apt
index 0d360ec..8f88a77 100644
--- a/continuum-docs/src/site/apt/developer_guides/xmlrpc.apt
+++ b/continuum-docs/src/site/apt/developer_guides/xmlrpc.apt
@@ -6,6 +6,23 @@
  Nov 12 2007
  ------
 
+~~ 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.
+
 Guide to use XML-RPC with Continuum
 
 ~~%{toc|section=0}
diff --git a/continuum-docs/src/site/apt/getting-started.apt b/continuum-docs/src/site/apt/getting-started.apt
index 2380b5d..a8871fa 100644
--- a/continuum-docs/src/site/apt/getting-started.apt
+++ b/continuum-docs/src/site/apt/getting-started.apt
@@ -4,19 +4,63 @@
  Emmanuel Venisse
  Olivier Lamy
  ------
- Oct 5 2007
+ 2010-02-18
  ------
 
+~~ 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.
+
 Getting Started
 
+    Getting started with Continuum's default configuration is very easy.
+
+    After unpacking the binary distribution, run the following command from the <<<bin>>> directory:
+
+----
+continuum console
+----
+
+    Continuum will be started from the command line and run until quit with Ctrl-C. For more instructions on installing
+    Continuum as a service or under an existing application server, refer to the {{{./installation/index.html}
+    Installation Guides}}.
+
     When you start Continuum for the first time (without an existing database), the first thing you will
-    do is create the admin account and perform the {{{administrator_guides/configuration.html}General Configuration}}.
-    
+    do is create the administrator account and perform the {{{./administrator_guides/configuration.html}General
+    Configuration}}.
+
 [images/admin-account-creation.png] Admin account creation
 
-    After admin account creation, you can log as the admin. The next thing you will see is the General Configuration
-    page.
+    After the administrator account has been created, you can log as the <<<admin>>> user with the password you selected.
+    The next thing you will see is the <<General Configuration>> page.
 
 [images/configuration.png] General Configuration
 
-    You may also create users, {{{user_guides/managing_project/addProject.html}add projects}}, etc.
\ No newline at end of file
+    The defaults are usually sufficient, so you can save the configuration. You may later make changes to this page if
+    you are enabling Distributed Builds, for example.
+
+Next Steps
+
+    Once the server is running, you will likely want to do the following:
+
+    * Create more users via the <<Users>> menu item, so that you no longer need to use the administrator account for
+      daily tasks.
+
+    * {{{./user_guides/managing_project/addProject.html}Add Projects}} to build
+
+    * Configure Continuum to work with distributed builds if you intend to have multiple build slave machines
+
+    * Configure installed software packages and environment variables for project templates
diff --git a/continuum-docs/src/site/apt/index.apt b/continuum-docs/src/site/apt/index.apt
index e9980dc..767c10a 100644
--- a/continuum-docs/src/site/apt/index.apt
+++ b/continuum-docs/src/site/apt/index.apt
@@ -3,60 +3,61 @@
  ------
  Emmanuel Venisse
  ------
- Oct 3 2007
+ 2010-02-18
+ ------
+
+~~ 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.
 
 Welcome to Apache Continuum
 
   Apache Continuum is an enterprise-ready continuous integration server with features such as automated builds,
-  release management, role-based security, and integration with popular build tools and source control management
+  release management, role-based security and integration with popular build tools and source control management
   systems. Whether you have a centralized build team or want to put control of releases in the hands of developers,
-  Continuum can help you improve quality and maintain a consistent build environment. 
+  Continuum can help you improve quality and maintain a consistent build environment.
 
-Documentation
+* Documentation
 
-* Installation/Upgrade Guides
+  * {{{./release-notes.html} Release Notes}}
 
-** {{{installation/index.html}Installation}}
+  * {{{./getting-started.html} Getting Started}}
 
-*** Standalone version
+  * {{{./installation/index.html}Installation and Upgrade Guide}}
 
-    {{{installation/standalone.html}Standard (Linux, Mac OSX, Solaris, Windows, others) as a service or not}}
+      * {{{./installation/standalone.html}Installing as a standalone service (Linux, Mac OSX, Solaris, Windows, others)}}
 
-*** Webapp
+      * {{{./installation/tomcat.html}Installing the Web Application under a Tomcat server}}
 
-    {{{installation/tomcat.html}Tomcat}},
-    {{{installation/jetty.html}Jetty}},
-    {{{installation/jboss.html}JBoss}},
-    {{{installation/geronimo.html}Geronimo}},
-    {{{installation/glassfish.html}GlassFish}},
-    ...
+      * {{{./installation/upgrade.html} How to upgrade from a previous version}}
 
-** Release Notes
+      []
 
-    {{{release-notes.html} Release Notes}}
+  * {{{./user_guides/index.html} User's Guide}}
 
-** Upgrade
+  * {{{./administrator_guides/index.html} Administrator's Guide}}
 
-    {{{installation/upgrade.html} How to upgrade from a previous version}}
+  * {{{./developer_guides/building.html} Developer's Guide to building Continuum}}
 
-* User's Guide
-
-    {{{user_guides/index.html} User's Guide}}
-
-* Administrator's Guide
-
-    {{{administrator_guides/index.html} Administrator's Guide}}
-
-* Developer's Guide
-
-    {{{developer_guides/building.html}Guide to building Continuum}}
+   This documentation is also available in {{{./apache-continuum.pdf}PDF}} format.
 
 * Knowledge Base
 
-    {{{http://continuum.apache.org/faqs.html}Frequently Asked Questions}}
+  * {{{http://continuum.apache.org/faqs.html}Frequently Asked Questions}}
 
-    {{{http://cwiki.apache.org/confluence/display/CONTINUUM}Wiki}}
+  * {{{http://cwiki.apache.org/confluence/display/CONTINUUM}Wiki}}
 
-    {{{http://docs.codehaus.org/display/CONTINUUMUSER/Home}Old Wiki}}
 
-    {{{http://apache-continuum.blogspot.com/}Blog}}
diff --git a/continuum-docs/src/site/apt/installation/build-agent.apt b/continuum-docs/src/site/apt/installation/build-agent.apt
index b833e0f..f53fdc1 100644
--- a/continuum-docs/src/site/apt/installation/build-agent.apt
+++ b/continuum-docs/src/site/apt/installation/build-agent.apt
@@ -1,52 +1,147 @@
+ ------
+ Installing and Configuring a Build Agent
+ ------
+ ------
+ 2010-02-22
+ ------
 
+~~ 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.
 
+Installing and Configuring a Build Agent
 
-Installing a Build Agent
+    Installing a build agent follows a very similar process to the Continuum master installation.
 
+    First, {{{http://continuum.apache.org/download.html}download}} the Continuum Build Agent standalone
+    distribution or web application.
 
-  The build agent is available as a web application which you will need to install into a container.
+    <<Note>>: It is recommended to use Build Agents that come with the release of Continuum (Continuum Master) to be
+    used. While 1.3.x Build Agents can be used with 1.4.x Continuum (Continuum Master), using a later version of Build
+    Agent than the Continuum (Continuum Master) will not work.
 
-  First, {{{../../download.html}download}} the webapp.
+* Standalone
 
-  Next, configure the environment.
+    The Build Agent is available as a separate standalone Jetty-bundled
+    application.  Installing it is as simple as extracting it to a preferred
+    directory.
 
-  The build agent needs two things in order to function properly:  A CONTINUUM_BUILDAGENT_HOME environment variable, and a
-  continuum-buildagent.xml configuration file in a conf/ directory under $CONTINUUM_BUILDAGENT_HOME.
+    The Build Agent runs on a specific port (defaulting to 8181), so it is possible
+    to install multiple Build Agents in one machine.  It is also possible to
+    install Build Agents in the same machine as the Master.  To configure the Build Agent
+    to run using a different port, edit the
+    <<<$CONTINUUM_BUILDAGENT_HOME/conf/jetty.xml>>> file.
 
-  Set the environment variable:
-
-  export CONTINUUM_BUILDAGENT_HOME=/path/to/build/agent/home
-
-  or
-
-  set CONTINUUM_BUILDAGENT_HOME=c:\path\to\build\agent\home
-
-  Create a directory called 'conf' under [CONTINUUM_BUILDAGENT_HOME].
-
-  In the 'conf' directory, save the continuum-buildagent.xml file:
+    Another configuration file to look at is the
+    <<<$CONTINUUM_BUILDAGENT_HOME/conf/continuum-buildagent.xml>>>.  This file must
+    be manually edited, as there is no web interface for this configuration.
 
 +--------------+
 <continuum-buildagent-configuration>
-<buildOutputDirectory>/path/to/build/agent/data/build-output-directory</buildOutputDirectory>
- <workingDirectory>/path/to/build/agent/data/working-directory</workingDirectory>
- <continuumServerUrl>http://builds.example.com:8080/continuum/master-xmlrpc</continuumServerUrl>
- <installations>
-  <installation>
-    <name>Maven 2 Home</name>
-    <type>maven2</type>
-    <varValue>/Applications/apache-maven-2.0.9</varValue>
-  </installation>
- </installations>
+  <buildOutputDirectory>/path/to/build/agent/data/build-output-directory</buildOutputDirectory>
+  <workingDirectory>/path/to/build/agent/data/working-directory</workingDirectory>
+  <continuumServerUrl>http://builds.example.com:8080/continuum/master-xmlrpc</continuumServerUrl>
+  <installations>
+    <installation>
+      <name>Maven Home</name>
+      <type>maven2</type>
+      <varValue>/Applications/apache-maven-2.0.9</varValue>
+    </installation>
+  </installations>
+  <localRepositories>
+    <localRepository>
+      <name>default</name>
+      <location>/home/user/.m2/repository</location>
+      <layout>default</layout>
+    </localRepository>
+  </localRepositories>
+  <sharedSecretPassword>PSK</sharedSecretPassword>
 </continuum-buildagent-configuration>
 +----------------+
 
-  List all of the installations available on the build agent, including Maven, Ant, JDK, etc.
+    The configuration will have the following fields:
 
-  Note that all of your agents need to be identical, as there is no way to control which agent Continuum chooses.
+      * <<<continuumServerUrl>>> - the URL pointing to the XML-RPC context of the Continuum Master
 
-  Finally, drop the webapp into your container, and start it.
+      * <<<sharedSecretPassword>>> - the pre-shared key (PSK) between master and agent. Copy the PSK that was configured
+        in the Continuum Master configuration file <<<continuum.xml>>> (or corresponding web interface field).
 
-  Next, enable the Distributed Builds option in the {{{../administrator_guides/configuration.html}General Configuration}},
-  and {{{../administrator_guides/build-agents.html}add the agent}} to the Continuum master server.
+      * <<<buildOutputDirectory>>> - similar to the build output directory of Continuum.
 
-  TODO:  Provide a Jetty bundle for the agent webapp.
+      * <<<workingDirectory>>> - similar to the working directory of Continuum
+
+      * <<<installations>>> - an optional list of the installations available on the Build Agent, including Maven, Ant,
+        JDK, etc.
+    
+      * <<<localRepositories>>> - an optional list of the local repositories that will be used by the build agent when
+        building and releasing projects. The local repository <<<name>>> must match that of the local repository
+        configured in the Continuum Master. This configuration is only available in Continuum 1.4.0+.
+
+  Note that all of your agents need not be identical, as there is a way to control which agent Continuum chooses by
+  using a {{{../administrator_guides/build-agent-groups.html}Build Agent Group}}. In addition, you need to
+  {{{../administrator_guides/buildEnvironment.html} configure}} the Build Environment from the Master in order to
+  specify which installation to use for the build.
+
+  Now start the Build Agent by executing the startup script available in
+  <<<$CONTINUUM_BUILDAGENT_HOME/bin/>>>.  For example:
+
++---+
+continuum-buildagent start
++---+
+
+  or if you are on Windows
+
++---+
+continuum-buildagent.bat console
++---+
+
+  Next, {{{../administrator_guides/build-agents.html}add the agent}} to the Continuum Master server. 
+
+  Note that agent will be automatically disabled if the PSK is not configured properly or if the agent is unreachable by
+  the Continuum Master.
+
+  To conclude the installation, you should set it up as a service, following the same instructions as those shown for
+  Continuum for {{{./standalone.html#Installing_as_a_Windows_Service} Windows}} or
+  {{{./standalone.html#Installing_as_a_Linux_Service} Linux}}.
+
+* Web Application
+
+  The Build Agent is also available as a web application which you can install into your own container. Unlike Continuum
+  itself, you do not need to configure Mail and Databases, so the deployment is much simpler.
+
+  The Build Agent needs the following in order to function properly:
+
+    [[1]] a <<<appserver.base>>> system property
+
+    [[2]] a <<<continuum-buildagent.xml>>> configuration file in <<<$\{appserver.base\}/conf>>>
+
+    [[3]] a working area with <<<logs>>> and <<<temp>>> directories
+
+  Set the system property using the recommended method for your application server. An example for Tomcat is shown in
+  the {{{./tomcat.html#Configure_the_appserver.base_Java_system_property} same instructions as those shown for Continuum}}.
+
+  Next, create the <<<continuum-buildagent.xml>>> file as shown in the Standalone section above, and save it in
+  <<<$\{appserver.base\}/conf>>>. You will need to create these directories, as well as <<<$\{appserver.base\}/logs>>>
+  and <<<$\{appserver.base\}/temp>>>.
+
+  Finally, drop the web application into your container, and start it.
+
+* {Installing with Puppet}
+
+  As with Continuum, if you use Puppet to manage your infrastructure, and wish to install the standalone build agent,
+  you can use a third-party Puppet module.
+
+  * {{{https://github.com/maestrodev/puppet-continuum} Puppet module for Apache Continuum and Continuum build agents}}
diff --git a/continuum-docs/src/site/apt/installation/geronimo.apt b/continuum-docs/src/site/apt/installation/geronimo.apt
deleted file mode 100644
index 8dc1f0a..0000000
--- a/continuum-docs/src/site/apt/installation/geronimo.apt
+++ /dev/null
@@ -1,95 +0,0 @@
- ------
- Guide to Install Continuum on Geronimo
- ------
- Emmanuel Venisse
- ------
- Oct 25 2007
- ------
-
-Guide to Install Continuum on Geronimo
-
-    Instructions for installing, deploying, configuring Continuum for Apache Geronimo.
-
-    Sections:
-
-~~%{toc|section=0}
-
-* {Datasource Configuration}
-
-    Continuum uses two datasources (<<<jdbc/continuum>>> and <<<jdbc/users>>>). You can create one or two databases for them.
-
-    Here, we create only one database '<<<continuum>>>' used by both datasources.
-    Look at {{{http://cwiki.apache.org/GMOxDOC20/configuring-database-pools.html}Configuring database pools}} in Geronimo User's Guide.
-
-* {Deployment Plan}
-
-    When your datasource is created, before you install Continuum, you must create a <<Geronimo Deployment Plan>> like this one (Geronimo 2.0.2):
-
------------------------------
-<?xml version="1.0" encoding="UTF-8"?>
-<web-app
-    xmlns="http://geronimo.apache.org/xml/ns/j2ee/web-1.1">
-    <environment>
-        <moduleId>
-            <groupId>org.apache.continuum</artifactId>
-            <artifactId>continuum</artifactId>
-            <version>1.2</version>
-        </moduleId>
-        <dependencies>
-            <dependency>
-                <groupId>console.dbpool</groupId>
-                <artifactId>continuum</artifactId>
-            </dependency>
-    	    <dependency>
-                <groupId>org.apache.geronimo.configs</groupId>
-                <artifactId>javamail</artifactId>
-                <version>2.0.2</version>
-                <type>car</type>
-            </dependency>
-    	    <dependency>
-    		    <groupId>commons-lang</groupId>
-    		    <artifactId>commons-lang</artifactId>
-    		    <version>2.2</version>
-    		    <type>jar</type>
-            </dependency>
-        </dependencies>
-
-        <hidden-classes>
-            <filter>org.apache.commons.lang.</filter>
-            <filter>org.jaxen.</filter>
-        </hidden-classes>
-    </environment>
-
-    <context-root>/continuum</context-root>
-
-    <resource-ref>
-        <ref-name>jdbc/continuum</ref-name>
-        <resource-link>continuum</resource-link>
-    </resource-ref>
-    <resource-ref>
-        <ref-name>jdbc/users</ref-name>
-        <resource-link>continuum</resource-link>
-    </resource-ref>
-    <resource-ref>
-        <ref-name>mail/Session</ref-name>
-        <resource-link>mail/MailSession</resource-link>
-    </resource-ref>
-</web-app>
------------------------------
-
-    The '<<<continuum>>>' string used in <<<console.dbpool>>> and <<<\<resource-link\>>>> is the name of the datasource created in the previous part.
-
-    <<<commons-lang 2.2>>> is required by Continuum and must be installed in the geronimo repository.
-
-    <<<org.jaxen.>>> needs to be added as a <<<\<filter\>>>> in the <<<\<hidden-classes\>>>> section because of {{{https://issues.apache.org/jira/browse/GERONIMO-3894}GERONIMO-3894}}
-
-* {Install Continuum}
-
-    To Install Continuum, you'll need the Continuum war and the deployment plan.
-
-    Look at {{{http://cwiki.apache.org/GMOxDOC20/installing-and-removing-applications.html}Installing and removing applications}} in Geronimo.
-
-* {Continuum Configuration}
-
-    By default, the '<<<working directory>>>' and the '<<<build output directory>>>' are stored under the WEB-INF directory. If you want to change them (necessary on Windows
-    due to the path length limitation), you can configure them in the {{{../administrator_guides/configuration.html}Configuration page}}.
diff --git a/continuum-docs/src/site/apt/installation/glassfish.apt b/continuum-docs/src/site/apt/installation/glassfish.apt
deleted file mode 100644
index abf5e42..0000000
--- a/continuum-docs/src/site/apt/installation/glassfish.apt
+++ /dev/null
@@ -1,35 +0,0 @@
- ------
- Guide to Install Continuum on GlassFish
- ------
- Emmanuel Venisse
- ------
- Oct 26 2007
- ------
-
-Guide to Install Continuum on GlassFish V2
-
-
-    Instructions for installing, deploying, configuring Continuum for GlassFish.
-
-    Sections:
-
-~~%{toc|section=0}
-
-* {Datasource Configuration}
-
-    * Create a connection pool named '<<continuum>>' for your database
-
-    * Create a JDBC resource named '<<jdbc/continuum>>' linked to the '<<continuum>>' connection pool
-
-    * Create a JDBC resource named '<<jdbc/users>>' linked to the '<<continuum>>' connection pool
-
-* {Install Continuum}
-
-    To Install Continuum, you'll need the Continuum war.
-
-    Look at {{{https://glassfish.dev.java.net/downloads/quickstart/index.html#ProcedureTo_Deploy_From_the_Admin}Procedure To Deploy From the Admin Console}} in GlassFish.
-
-* {Continuum Configuration}
-
-    By default, the '<<<working directory>>>' and the '<<<build output directory>>>' are stored under the WEB-INF directory. If you want to change them (necessary on Windows
-    due to the path length limitation), you can configure them in the {{{../administrator_guides/configuration.html}Configuration page}}.
diff --git a/continuum-docs/src/site/apt/installation/index.apt b/continuum-docs/src/site/apt/installation/index.apt
index 2b82571..9f1c02c 100644
--- a/continuum-docs/src/site/apt/installation/index.apt
+++ b/continuum-docs/src/site/apt/installation/index.apt
@@ -3,17 +3,46 @@
  ------
  Emmanuel Venisse
  ------
- Oct 3 2007
+ 2010-02-18
  ------
 
+~~ 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.
+
 Installation/Upgrade Guides
 
-    In this section, you'll find informations about Continuum installations:
+    In this section, you'll find information about Continuum installations:
 
-    * {{{requirements.html}System Requirements}}
+    * {{{./standalone.html}Installing as a standalone service (Linux, Mac OSX, Solaris, Windows, others)}}
 
-    * {{{installation.html}Installation in different environment (standalone, webapp, service)}}
+    * {{{./tomcat.html}Installing the Web Application under a Tomcat server}}
 
-    * {{{../release-notes.html}Release Notes}}
+    * {{{./upgrade.html}How to upgrade from a previous version?}}
 
-    * {{{upgrade.html}How to upgrade from a previous version?}}
+    * {{{./build-agent.html}Installation of Build Agent for Distributed Builds}}
+
+System Requirements
+
+*----------------------+--------------------------------------------------------------------------------------------------------------------------------+
+|  <<Java>>            | Java 5 (deploying WAR files) or Java 6 (when using the standalone version with Jetty 8)                                        |
+*----------------------+--------------------------------------------------------------------------------------------------------------------------------+
+| <<Memory>>           | No minimum requirement                                                                                                         |
+*----------------------+--------------------------------------------------------------------------------------------------------------------------------+
+| <<Disk>>             | The Continuum application package is less than 30MB but will use more disk space when it's checking out and building sources   |
+*----------------------+--------------------------------------------------------------------------------------------------------------------------------+
+| <<Operating System>> | No minimum requirement. Tested on Windows XP, Debian, Fedora Core, Solaris and Mac OS X                                        |
+*----------------------+--------------------------------------------------------------------------------------------------------------------------------+
diff --git a/continuum-docs/src/site/apt/installation/installation.apt b/continuum-docs/src/site/apt/installation/installation.apt
deleted file mode 100644
index 8eab288..0000000
--- a/continuum-docs/src/site/apt/installation/installation.apt
+++ /dev/null
@@ -1,23 +0,0 @@
- ------
- Continuum Installation
- ------
- Emmanuel Venisse
- ------
- Oct 3 2007
- ------
-
-Continuum Installation
-
-    In this section, you'll find all information about Continuum installation:
-
-    * {{{standalone.html}Standalone}}
-
-    * {{{tomcat.html}Tomcat}}
-
-    * {{{jboss.html}JBoss}}
-
-    * {{{jetty.html}Jetty}}
-
-    * {{{geronimo.html}Geronimo}}
-
-    * {{{glassfish.html}GlassFish}}
diff --git a/continuum-docs/src/site/apt/installation/jboss.apt b/continuum-docs/src/site/apt/installation/jboss.apt
deleted file mode 100644
index cd58662..0000000
--- a/continuum-docs/src/site/apt/installation/jboss.apt
+++ /dev/null
@@ -1,100 +0,0 @@
- ------
- Guide to Install Continuum on JBoss
- ------
- Emmanuel Venisse
- ------
- Nov 12 2007
- ------
-
-Guide to Install Continuum on JBoss
-
-    Instructions for installing, deploying, configuring Continuum in JBoss. Tested with JBoss 4.2.2.GA and 4.0.5.GA.
-
-    Sections:
-
-~~%{toc|section=0}
-
-* {DataSource Configuration}
-
-    * Copy {{{http://repo1.maven.org/maven2/org/apache/derby/derby/10.1.3.1/derby-10.1.3.1.jar}derby-10.1.3.1.jar}} into <<<$JBOSS_HOME/server/default/lib/>>>
-
-    * Create a JDBC deployment configuration file named <<<derby-continuum-ds.xml>>> in <<<$JBOSS_HOME/server/default/deploy>>> with the following contents:
-
-+--------------------------------+
-<?xml version="1.0" encoding="UTF-8"?>
-<datasources>
-  <local-tx-datasource>
-     <!-- The jndi name of the DataSource, it is prefixed with java:/ -->
-     <!-- Datasources are not available outside the virtual machine -->
-     <jndi-name>continuum</jndi-name>
-     <!-- for in-process persistent db, saved when jboss stops. The
-     org.jboss.jdbc.DerbyDatabase mbean is necessary for properly db shutdown -->
-     <connection-url>jdbc:derby:../database/continuum;create=true</connection-url>
-     <!-- The driver class -->
-     <driver-class>org.apache.derby.jdbc.EmbeddedDriver</driver-class>
-     <!-- The login and password -->
-     <user-name>sa</user-name>
-     <password></password>
-     <!-- The minimum connections in a pool/sub-pool. Pools are lazily constructed on first use -->
-     <min-pool-size>5</min-pool-size>
-     <!-- The maximum connections in a pool/sub-pool -->
-     <max-pool-size>20</max-pool-size>
-     <!-- The time before an unused connection is destroyed -->
-     <idle-timeout-minutes>5</idle-timeout-minutes>
-     <!-- Whether to check all statements are closed when the connection is returned to the pool,
-          this is a debugging feature that should be turned off in production -->
-     <track-statements/>
-  </local-tx-datasource>
-</datasources>
-+--------------------------------+
-
-    * Create a JDBC deployment configuration file named <<<derby-users-ds.xml>>> in <<<$JBOSS_HOME/server/default/deploy>>> with the following contents:
-
-+--------------------------------+
-<?xml version="1.0" encoding="UTF-8"?>
-<datasources>
-  <local-tx-datasource>
-     <!-- The jndi name of the DataSource, it is prefixed with java:/ -->
-     <!-- Datasources are not available outside the virtual machine -->
-     <jndi-name>users</jndi-name>
-     <!-- for in-process persistent db, saved when jboss stops. The
-     org.jboss.jdbc.DerbyDatabase mbean is necessary for properly db shutdown -->
-     <connection-url>jdbc:derby:../database/users;create=true</connection-url>
-     <!-- The driver class -->
-     <driver-class>org.apache.derby.jdbc.EmbeddedDriver</driver-class>
-     <!-- The login and password -->
-     <user-name>sa</user-name>
-     <password></password>
-     <!-- The minimum connections in a pool/sub-pool. Pools are lazily constructed on first use -->
-     <min-pool-size>5</min-pool-size>
-     <!-- The maximum connections in a pool/sub-pool -->
-     <max-pool-size>20</max-pool-size>
-     <!-- The time before an unused connection is destroyed -->
-     <idle-timeout-minutes>5</idle-timeout-minutes>
-     <!-- Whether to check all statements are closed when the connection is returned to the pool,
-          this is a debugging feature that should be turned off in production -->
-     <track-statements/>
-  </local-tx-datasource>
-</datasources>
-+--------------------------------+
-
-    With <<<../database>>> used for the derby db path, databases will be created into <<<$JBOSS_HOME>>>
-
-* {Mail Configuration}
-
-    Edit <<<$JBOSS_HOME/server/default/deploy/mail-service.xml>>>
-
-* {Install Continuum}
-
-    To Install Continuum, you'll need the Continuum war.
-
-    Extract the Continuum war into <<<$JBOSS_HOME/server/default/deploy/continuum.war>>>
-
-* {Continuum Configuration}
-
-    By default, the '<<<working directory>>>' and the '<<<build output directory>>>' are stored under the WEB-INF directory. If you want to change them (necessary on Windows
-    due to the path length limitation), you can configure them in the {{{../administrator_guides/configuration.html}Configuration page}}.
-
-    By default, Continuum logs are stored into <<<${appserver.base}/logs/>>>. appserver.base is a system property. If you don't define it in the JBoss startup script, it will be empty,
-    so the Continuum logs directory will be at the root of your disk. If you want to use another location, you should modify
-    <<<$JBOSS_HOME/server/default/deploy/continuum.war/WEB-INF/classes/log4j.xml>>>
diff --git a/continuum-docs/src/site/apt/installation/jetty.apt b/continuum-docs/src/site/apt/installation/jetty.apt
deleted file mode 100644
index 5e85a5b..0000000
--- a/continuum-docs/src/site/apt/installation/jetty.apt
+++ /dev/null
@@ -1,114 +0,0 @@
- ------
- Guide to Install Continuum on Jetty
- ------
- Emmanuel Venisse
- ------
- Nov 12 2007
- ------
-
-Guide to Install Continuum on Jetty
-
-    Instructions for installing, deploying, configuring Continuum for Jetty. Tested with Jetty 6.1.5.
-
-    Sections:
-
-~~%{toc|section=0}
-
-* {Datasource Configuration}
-
-    * Create a JDBC resource named '<<jdbc/continuum>>'
-
-    * Create a JDBC resource named '<<jdbc/users>>'
-
-    For derby you can copy the following configuration in your <<<$JETTY_HOME/etc/jetty.xml>>>
-
-    For other databases see {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp/src/jetty-env-postgres.xml}PostgreSQL}} 
-    and {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp/src/jetty-env-mysql.xml}MySQL}}
-
-+-------------------------------------+
-    <!-- =========================================================== -->
-    <!-- Continuum datasources                                       -->
-    <!-- =========================================================== -->
-    <New id="continuum" class="org.mortbay.jetty.plus.naming.Resource">
-      <Arg>jdbc/continuum</Arg>
-      <Arg>
-        <New class="org.apache.derby.jdbc.EmbeddedDataSource">
-          <Set name="DatabaseName">your_directory/continuum_database</Set>
-          <Set name="user">sa</Set>
-          <Set name="createDatabase">create</Set>
-        </New>
-      </Arg>
-    </New>
-    <New id="continuum_shutdown" class="org.mortbay.jetty.plus.naming.Resource">
-      <Arg>jdbc/continuum_shutdown</Arg>
-      <Arg>
-        <New class="org.apache.derby.jdbc.EmbeddedDataSource">
-          <Set name="DatabaseName">your_directory/continuum_database</Set>
-          <Set name="user">sa</Set>
-          <Set name="shutdownDatabase">shutdown</Set>
-        </New>
-      </Arg>
-    </New>
-    <New id="users" class="org.mortbay.jetty.plus.naming.Resource">
-      <Arg>jdbc/users</Arg>
-      <Arg>
-        <New class="org.apache.derby.jdbc.EmbeddedDataSource">
-          <Set name="DatabaseName">your_directory/users_database</Set>
-          <Set name="user">sa</Set>
-          <Set name="createDatabase">create</Set>
-        </New>
-      </Arg>
-    </New>
-    <New id="users_shutdown" class="org.mortbay.jetty.plus.naming.Resource">
-      <Arg>jdbc/users_shutdown</Arg>
-      <Arg>
-        <New class="org.apache.derby.jdbc.EmbeddedDataSource">
-          <Set name="DatabaseName">your_directory/users_database</Set>
-          <Set name="user">sa</Set>
-          <Set name="shutdownDatabase">shutdown</Set>
-        </New>
-      </Arg>
-    </New>
-+-------------------------------------+
-
-* {Mail Configuration}
-
-    The following xml can be used for the jetty mail configuration:
-
-+-------------------------------------+
-    <!-- =========================================================== -->
-    <!-- Mail configuration                                          -->
-    <!-- =========================================================== -->
-    <New id="validation_mail" class="org.mortbay.jetty.plus.naming.Resource">
-      <Arg>mail/Session</Arg>
-      <Arg>
-        <New class="org.mortbay.naming.factories.MailSessionReference">
-          <Set name="user"></Set>
-          <Set name="password"></Set>
-          <Set name="properties">
-            <New class="java.util.Properties">
-              <Put name="mail.smtp.host">localhost</Put>
-              <Put name="mail.from">continuum@localhost</Put>
-              <Put name="mail.senderName">Continuum</Put>
-              <Put name="mail.debug">true</Put>
-            </New>
-          </Set>
-        </New>
-      </Arg>
-    </New>
-+-------------------------------------+
-
-* {Install Continuum}
-
-    To Install Continuum, you'll need the Continuum war.
-
-    Copy or extract the Continuum war into $JETTY_HOME/webapps-plus/
-
-* {Start Jetty}
-
-    To start Jetty, you'll need to use $JETTY_HOME/etc/jetty.xml <<and>> $JETTY_HOME/etc/jetty-plus.xml due to the datasources and mail configuration.
-
-* {Continuum Configuration}
-
-    By default, the '<<<working directory>>>' and the '<<<build output directory>>>' are stored under the WEB-INF directory. If you want to change them (necessary on Windows
-    due to the path length limitation), you can configure them in the {{{../administrator_guides/configuration.html}Configuration page}}.
diff --git a/continuum-docs/src/site/apt/installation/requirements.apt b/continuum-docs/src/site/apt/installation/requirements.apt
deleted file mode 100644
index c6aa894..0000000
--- a/continuum-docs/src/site/apt/installation/requirements.apt
+++ /dev/null
@@ -1,19 +0,0 @@
- ------
- System Requirements
- ------
- Emmanuel Venisse
- ------
- Oct 3 2007
- ------
-
-System Requirements
-
-*----------------------+--------------------------------------------------------------------------------------------------------------------------------+
-|  <<JDK>>             | 1.5 or above                                                                                                                   |
-*----------------------+--------------------------------------------------------------------------------------------------------------------------------+
-| <<Memory>>           | No minimum requirement                                                                                                         |
-*----------------------+--------------------------------------------------------------------------------------------------------------------------------+
-| <<Disk>>             | The Continuum application package is less than 30MB but will use more disk space when it's checking out and building sources |
-*----------------------+--------------------------------------------------------------------------------------------------------------------------------+
-| <<Operating System>> | No minimum requirement. Tested on Windows XP, Debian, Fedora Core, Solaris and Mac OS X                                        |
-*----------------------+--------------------------------------------------------------------------------------------------------------------------------+
diff --git a/continuum-docs/src/site/apt/installation/standalone.apt b/continuum-docs/src/site/apt/installation/standalone.apt
deleted file mode 100644
index 312d22b..0000000
--- a/continuum-docs/src/site/apt/installation/standalone.apt
+++ /dev/null
@@ -1,158 +0,0 @@
- ------
- Installing Continuum Standalone
- ------
- Emmanuel Venisse
- ------
- 2008-09-01
- ------
-
-Installing Continuum Standalone
-
-~~%{toc|section=0}
-
-* {Basics & Fundamentals}
-
-    * Download the standalone version from the {{{../../../download.html} Download page}}
-
-    * Extract the file
-    
-    * Set a JAVA_HOME environment variable which use a jdk >= 1.5 
-
-** {Defining JNDI Resources}
-
-*** {Mail server configuration}
-
-    Before to start Continuum, you must configure your SMTP configuration for mail notification. The configuration to do is in <<<$CONTINUUM_HOME/conf/jetty.xml>>>:
-
-%{snippet|id=mail|url=http://svn.apache.org/repos/asf/continuum/trunk/continuum-jetty/src/main/conf/jetty.xml}
-
-*** {Databases configuration}
-
-    By default, Continuum use an embedded {{{http://db.apache.org/derby}Derby}} database. If you want to use an other database, you can modify the JNDI
-    configuration in <<<$CONTINUUM_HOME/conf/jetty.xml>>>:
-
-%{snippet|id=datasources|url=http://svn.apache.org/repos/asf/continuum/trunk/continuum-jetty/src/main/conf/jetty.xml}
-
-* {Installing as a Windows Service}
-
-    * Go to <<<$CONTINUUM_HOME/bin/>>> and run the following command:
-
-------------------
-continuum.bat install
-------------------
-
-    * Edit the <<<'Apache Continuum'>>> service
-
-        * To see the services that are on your computer go to Start|Run and enter <<<'services.msc'>>>.
-
-    * Select the <<<'Startup Type'>>>
-
-    * Go to the <<<'Log On'>>> tab and select a real user. A real user is required because you'll need a home directory for maven repository and some other things
-
-    * Validate your changes
-
-* {Installing as a Linux Service}
-
-    Since the Continuum linux script bin/linux/run.sh understands the same arguments as linux boot scripts, there is no need to write a particular
-    startup script to add Continuum to the linux boot process. All you need to do, as root, is:
-    
-** {Basic script in /etc/init.d}
-
-    * Create a <<<'continuum'>>> file under <<</etc/init.d/>>> with the following content (replacing <<<continuum_user>>> with the name of an account you have already created):
-
-------------------
-#!/bin/sh
-
-CONTINUUM_HOME=/opt/continuum-1.2
-su - continuum_user -c "$CONTINUUM_HOME/bin/continuum console $@ &"
-------------------
-
-** {In a Debian-based system}
-
-------------------
-ln -s /usr/local/continuum-[VERSION]/bin/linux/run.sh /etc/init.d/continuum
-------------------
-
-    At this point you have Continuum ready to be symlinked from different runlevels. This might sound a bit esoteric, but it is not, you will find these words
-    very fast as soon as you start reading about the init process. Fortunately, Debian GNU/Linux comes with a very handy utility to create this links, just run as root:
-
-------------------
-update-rc.d -n continuum defaults 80
-------------------
-
-    If you run this command, you will see something like this:
-
-------------------
- Adding system startup for /etc/init.d/continuum ...
-   /etc/rc0.d/K80continuum -> ../init.d/continuum
-   /etc/rc1.d/K80continuum -> ../init.d/continuum
-   /etc/rc6.d/K80continuum -> ../init.d/continuum
-   /etc/rc2.d/S80continuum -> ../init.d/continuum
-   /etc/rc3.d/S80continuum -> ../init.d/continuum
-   /etc/rc4.d/S80continuum -> ../init.d/continuum
-   /etc/rc5.d/S80continuum -> ../init.d/continuum
-------------------
-
-    What you see is the symlinks that would be created. The above command didn't do anything because of the -n  switch, remove it to get the real links created.
-
-** {In a RedHat-based system}
-
-    Configuring Continuum in a RedHat-based system (like Fedora Core) is slightly different: Instead of running update-rc.d, you need to add a new
-    service using chkconfig. And in order to add Continuum to chkconfig, it is necessary to add some comments to the /etc/rc.d/init.d/continuum script
-    and run a couple of commands; these tasks are automatically executed by running the chkconfig_install.sh script (note that _continuum_user_ needs to be
-    replaced by the name of an account you have already created):
-
-------------------
-#! /bin/sh
-#
-# chkconfig_install.sh - install Continuum on a chkconfig-bases system
-# 
-# Author: Felipe Leme <felipeal at apache.org>
-#
-
-# figure out what's Continuum's directory
-CONTINUUM_HOME=`dirname $0`
-cd ${CONTINUUM_HOME}
-CONTINUUM_HOME=`pwd`
-
-INITD_SCRIPT=/etc/rc.d/init.d/continuum
-
-if [ -f ${INITD_SCRIPT} ]
-then
-  echo "File ${INITD_SCRIPT} already exists. Please remove it and try again."
-  exit 1
-fi
-
-echo "Creating file ${INITD_SCRIPT}"  
-cat >> ${INITD_SCRIPT} <<EOF
-#! /bin/sh
-# chkconfig: 345 90 10
-# description: Apache Continuum server
-
-# uncoment to set JAVA_HOME as the value present when Continuum installed
-#export JAVA_HOME=${JAVA_HOME}
-
-if [ -z "\${JAVA_HOME}" ]
-then
-  echo "Cannot manage Continuum without variable JAVA_HOME set"
-  echo "  (try to set it on file ${INITD_SCRIPT})"
-  exit 1
-fi
-# run Continuum as root
-cd ${CONTINUUM_HOME}
-./run.sh \$*
-# run Continuum as user _continuum_user_
-#su - _continuum_user_ -c "cd ${CONTINUUM_HOME}; ./run.sh \$*"
-EOF
-chmod +x ${INITD_SCRIPT}
-
-echo "Adding Continuum to chkconfig"  
-chkconfig --add continuum
-
-echo "Enabling Continuum on chkconfig"  
-chkconfig continuum on
-echo "Continuum set to start on run levels 3, 4 and 5."
-echo "To start continuum now, run 'service continuum start'"
-
-------------------
-
diff --git a/continuum-docs/src/site/apt/installation/standalone.apt.vm b/continuum-docs/src/site/apt/installation/standalone.apt.vm
new file mode 100644
index 0000000..05f214f
--- /dev/null
+++ b/continuum-docs/src/site/apt/installation/standalone.apt.vm
@@ -0,0 +1,213 @@
+ ------
+ Installing Continuum Standalone
+ ------
+ Emmanuel Venisse
+ ------
+ 2010-02-19
+ ------
+
+~~ 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.
+
+Installing Continuum Standalone
+
+~~%{toc|section=0}
+
+* {Download and Configuration}
+
+    * Download the standalone version from the {{{http://continuum.apache.org/download.html} Download page}}
+
+    * Extract the file
+
+  <Note>: The standalone version ships with Jetty 8, which requires Java 6.
+
+** {Defining JNDI Resources}
+
+*** {Mail server configuration}
+
+    Before you start Continuum, you must configure your SMTP configuration for mail notification. In many servers, the
+    default of delivering to localhost with no authentication will be properly relayed. However, if you need to
+    configure a different SMTP server, the configuration is in <<<$CONTINUUM_HOME/contexts/continuum.xml>>>:
+
+%{snippet|id=mail|url=http://svn.apache.org/repos/asf/continuum/trunk/continuum-jetty/src/main/contexts/continuum.xml}
+
+*** {Database configuration}
+
+    By default, Continuum use an embedded {{{http://db.apache.org/derby}Derby}} database. If you want to use a different
+    database, you can modify the JNDI configuration in <<<$CONTINUUM_HOME/contexts/continuum.xml>>>:
+
+%{snippet|id=datasources|url=http://svn.apache.org/repos/asf/continuum/trunk/continuum-jetty/src/main/contexts/continuum.xml}
+
+    Please refer to the documentation for your JDBC driver for the correct settings to use. You may need to alter the
+    <<<validationQuery>>> to one that can successfully execute on your database (or remove the setting if you do not
+    want to validate connections before using them).
+
+    You must ensure the JDBC driver is available in the classpath, by copying it to the <<<$CONTINUUM_HOME/lib>>>
+    directory and updating <<<$CONTINUUM_HOME/conf/wrapper.conf>>> to ensure it is listed instead of the Derby JAR.
+
+    Refer to the {{{http://commons.apache.org/dbcp/} Commons DBCP}} documentation for more advanced configuration of the
+    connection pool.
+
+    More information on supported databases is available in the Administrator's Guide on
+    {{{../administrator_guides/external-db.html} External Databases}}.
+
+** Testing the Configuration
+
+  Start Continuum from the console in the <<<$CONTINUUM_HOME/bin/>>> directory:
+
+----
+continuum console
+----
+
+  If it appears to be working correctly, it is a good idea to set it up as a service so that it will run in the
+  background under a suitable role account, and can be set to start whenever the server has started.
+
+* {Installing as a Windows Service}
+
+    * Go to <<<$CONTINUUM_HOME/bin/>>> and run the following command:
+
+------------------
+continuum.bat install
+------------------
+
+    * Edit the <<Apache Continuum>> service
+
+        * To see the services that are on your computer go to <Start>|<Run> and enter <<<services.msc>>>.
+
+    * Select the <<Startup Type>>
+
+    * Go to the <<Log On>> tab and select a real user. A real user is required because you'll need a home directory for Maven repository and some other things
+
+    * Validate your changes
+
+* {Installing as a Linux Service}
+
+    Since the Continuum Linux script <<<bin/continuum>>> understands the same arguments as Linux boot scripts, there is no need to write a particular
+    startup script to add Continuum to the Linux boot process. All you need to do, as root, is:
+
+------------------
+ln -s /usr/local/continuum-[VERSION]/bin/continuum /etc/init.d/continuum
+------------------
+
+   This will allow you to run <<<service continuum start>>> and other commands.
+
+   To have the service start on boot, follow the instructions below for your particular family of operating system.
+
+** {On a Debian-based system}
+
+    At this point you have Continuum ready to be symlinked from different runlevels. Debian GNU/Linux comes with a very
+    handy utility to create these links, just run as root:
+
+------------------
+update-rc.d continuum defaults 80
+------------------
+
+    If you run this command, you will see something like this:
+
+------------------
+ Adding system startup for /etc/init.d/continuum ...
+   /etc/rc0.d/K80continuum -> ../init.d/continuum
+   /etc/rc1.d/K80continuum -> ../init.d/continuum
+   /etc/rc6.d/K80continuum -> ../init.d/continuum
+   /etc/rc2.d/S80continuum -> ../init.d/continuum
+   /etc/rc3.d/S80continuum -> ../init.d/continuum
+   /etc/rc4.d/S80continuum -> ../init.d/continuum
+   /etc/rc5.d/S80continuum -> ../init.d/continuum
+------------------
+
+    What you see is the symlinks that would be created.
+
+** {On a RedHat-based system}
+
+    Configuring Continuum on a RedHat-based system (like Fedora Core) is slightly different. Instead of running
+    <<<update-rc.d>>>, you need to add a new service using the <<<chkconfig>>> command.
+
+------------------
+chkconfig --add continuum
+chkconfig continuum on
+------------------
+
+* {Installing as a Mac OS X Service}
+
+  On OS X, you can use <<<launchd>>> to run a service. Create the following
+  as root in <<</Library/LaunchDaemons/org.apache.continuum.plist>>>:
+
++----+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
+"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+    <key>Label</key>
+    <string>org.apache.continuum</string>
+    <key>ProgramArguments</key>
+    <array>
+        <string>/Applications/Continuum/apache-continuum-${project.version}/bin/continuum</string>
+        <string>console</string>
+    </array>
+    <key>Disabled</key>
+    <false/>
+    <key>RunAtLoad</key>
+    <true/>
+    <key>UserName</key>
+    <string>continuum</string>
+    <key>StandardOutPath</key>
+    <string>/Applications/Continuum/apache-continuum-${project.version}/logs/launchd.log</string>
+    <!-- Optional - store data separate from installation -->
+    <key>EnvironmentVariables</key>
+    <dict>
+      <key>CONTINUUM_BASE</key>
+      <string>/Users/continuum/Library/Continuum</string>
+    </dict>
+    <!-- Optional: force it to keep running
+    <key>KeepAlive</key>
+    <true/>
+    -->
+</dict>
+</plist>
++----+
+
+  To install the service, run the following:
+
++----+
+$ sudo chown root:wheel /Library/LaunchDaemons/org.apache.continuum.plist
+$ sudo launchctl load -w /Library/LaunchDaemons/org.apache.continuum.plist
++----+
+
+  Start and stop the service with:
+
++----+
+$ sudo launchctl start org.apache.continuum.plist
+$ sudo launchctl stop org.apache.continuum.plist
++----+
+
+  To uninstall the service:
+
++----+
+$ sudo launchctl unload -w /Library/LaunchDaemons/org.apache.continuum.plist
++----+
+
+  You can follow the same steps to install build agents as a service by
+  replacing the appropriate paths, and changing <<<org.apache.continuum>>> to
+  <<<org.apache.continuum.buildagent>>> in the label and <<<plist>>> filename.
+
+* {Installing with Puppet}
+
+  If you use Puppet to manage your infrastructure, you can use a third-party Puppet module to install Continuum. This
+  will take care of adding the required users, databases and configuration based on official release tarballs.
+
+  * {{{https://github.com/maestrodev/puppet-continuum} Puppet module for Apache Continuum and Continuum build agents}}
diff --git a/continuum-docs/src/site/apt/installation/tomcat.apt b/continuum-docs/src/site/apt/installation/tomcat.apt
deleted file mode 100644
index 475add9..0000000
--- a/continuum-docs/src/site/apt/installation/tomcat.apt
+++ /dev/null
@@ -1,257 +0,0 @@
- ------
- Guide to Install Continuum on Tomcat
- ------
- Joakim Erdfelt
- Emmanuel Venisse
- ------
- 2008-09-01
- ------
-
-Guide to Install Continuum on Tomcat
-
-    Instructions for installing, deploying, configuring Continuum for the Apache Tomcat web container.
-
-    Sections:
-
-~~%{toc|section=0}
-
-* {Basics & Fundamentals}
-
-    With every Tomcat version you will need a few things before you can deploy Continuum.
-
-    [[1]] Use at least Java JDK 1.5.0_11 to run Tomcat w/Continuum.
-
-    [[1]] A defined \<Context\> xml section to define the JNDI resources.
-
-    [[1]] The JavaMail / Activation JAR files.
-
-    [[1]] The Apache Derby JAR files.
-
-    [[1]] Configure $\{appserver.base\} java property.
-
-** {Defining JNDI Resources}.
-
-    Continuum will, on startup, ask the web container for a few JNDI configured resources, two JDBC DataSources, and one JavaMail session.
-
-    To configure these JNDI resources in the Tomcat Web Container, you will need to specify a \<Context\> section that Tomcat can utilize for those requests coming from Continuum.
-
-    Tomcat has 3 main ways to accomplish this (ordered by most recommended to least recommended)
-
-    [[1]] Creating a $CATALINA_HOME/webapps/continuum/META-INF/context.xml containing a \<Context\> element.
-
-    [[1]] Creating a $CATALINA_HOME/conf/Catalina/localhost/continuum.xml containing a \<Context\> element.
-
-    [[1]] Adding a \<Context\> Section into the $CATALINA_HOME/conf/server.xml
-
-    The following are the JNDI names you will need to provide:
-
-    * <<<mail/Session>>>
-
-    * <<<jdbc/continuum>>>
-
-    * <<<jdbc/users>>>
-
-    The individual techniques for describing these resources, and the parameters associated with them are specific to the Tomcat version, resource type, and even JDBC implementation type.
-
-    For the purposes of this document, the following assumptions are made.
-    
-    [[1]] You are an Apache Tomcat administrator.
-
-    [[1]] You have an SMTP Server on localhost, port 25, with no login / password.
-
-    [[1]] You will be using the embedded Apache Derby database. (not an external database, that's another show)
-
-    [[1]] Details specific to Apache Tomcat, JavaMail, or Apache Derby are left for the reader to research on those projects websites.
-
-** {The JavaMail / Activation JAR files}
-
-    <<Note:>> Continuum requires JavaMail 1.4 (or later)
-
-    Apache Tomcat does not typically ship with a copy of the JavaMail or Activation jar files. 
-    In your role as the Apache Tomcat administrator of your installation, you will need to obtain these jar files and place it into your preferred lib directory.
-
-    The appropriate lib directory to choose is a personal preference, and we do not encourage or enforce a specific location for it, as all installations of Apache Tomcat are different.
-
-    For the record, we personally put them in the <<<$CATALINA_HOME/common/lib/>>> directory.
-
-    Direct download links for these jar files.
-
-    * JavaMail 1.4 - {{{http://repo1.maven.org/maven2/javax/mail/mail/1.4/mail-1.4.jar}mail-1.4.jar}}
-
-    * Java Activation Framework 1.1 - {{{http://repo1.maven.org/maven2/javax/activation/activation/1.1/activation-1.1.jar}activation-1.1.jar}}
-
-** {The Apache Derby JAR files}
-
-    <<Note:>>Continuum 1.2 has been tested with Apache Derby 10.1.3.1
-
-    The default installation of Continuum uses the Apache Derby 100% Java database to maintain Continuum-specific information, and also the Users / Security Database.
-
-    You will need to obtain the derby.jar and derbytools.jar and place them into your preferred lib directory.
-
-    We put them into the <<<$CATALINA_HOME/common/lib/>>> directory.
-
-    Direct download links for these jar files:
-
-    * {{{http://repo1.maven.org/maven2/org/apache/derby/derby/10.1.3.1/derby-10.1.3.1.jar}derby-10.1.3.1.jar}}
-
-    * {{{http://repo1.maven.org/maven2/org/apache/derby/derbytools/10.1.3.1/derbytools-10.1.3.1.jar}derbytools-10.1.3.1.jar}}
-
-** {Configure the appserver.base java property}
-
-    The <<<$\{appserver.base\}>>> java property is used by the Continuum internal logging configuration to determine where to output its logs to.
-    It is important to define this property either in the <<<$CATALINA_OPTS>>> system environment variable (if Tomcat is being launched via
-    the command line) or the service properties (if being launched as a service or daemon).
-
-    The format typically expected is <<<\-Dappserver.base=\<SOMEWHERE\>>>>
-
-    You can utilize the <<<$CATALINA_HOME/bin/setenv.sh>>> script to set this value in a tomcat specific way.
-
-------------------------------------------
-#!/bin/bash
-# Keep the appserver.home and appserver.base values the same when running under Tomcat
-
-export CATALINA_OPTS="-Dappserver.home=$CATALINA_HOME -Dappserver.base=$CATALINA_HOME"
-------------------------------------------
-
-* {Tomcat 5.0.x Specifics}
-
-    Tested on Tomcat v5.0.28
-
-    These instructions explain how to deploy the Continuum 1.2 web application in an existing installation of Tomcat 5.0.x.
-
-    <<Extra Jars:>>
-
-        * You will need the {{{http://repo1.maven.org/maven2/xalan/xalan/2.7.0/xalan-2.7.0.jar}xalan-2.7.0.jar}} copied into your <<<$CATALINA_HOME/common/lib/>>> directory.
-
-        * The Xerces XML Implementation provided in Tomcat 5.0.x is old and will cause problems with Continuum and
-        the internal JAXP implementation in JDK 1.5, we recommend that you remove the files in <<<$CATALINA_HOME/common/endorsed/>>>.
-
-------------------------------------------
-<Context path="/continuum" docBase="/path/to/continuum-webapp-1.2.war" debug="0">
-
-  <!-- JNDI Datasource for User/Security Database (REQUIRED) -->
-  <Resource name="jdbc/users" auth="Container" type="javax.sql.DataSource"/>
-  <ResourceParams name="jdbc/users">
-    <parameter>
-      <name>driverClassName</name>
-      <value>org.apache.derby.jdbc.EmbeddedDriver</value>
-    </parameter>
-    <parameter>
-      <name>factory</name>
-      <value>org.apache.commons.dbcp.BasicDataSourceFactory</value> <!-- Sets up Database Connection Pooling -->
-    </parameter>
-    <parameter>
-      <name>url</name>
-      <value>jdbc:derby:database/users;create=true</value> <!-- Adjust path to suit -->
-    </parameter>
-    <parameter>
-      <name>username</name>
-      <value>sa</value>
-    </parameter>
-    <parameter>
-      <name>password</name>
-      <value></value>
-    </parameter>
-  </ResourceParams>
-
-  <!-- JNDI Datasource for Continuum Database (REQUIRED) -->
-  <Resource name="jdbc/continuum" auth="Container" type="javax.sql.DataSource"/>
-  <ResourceParams name="jdbc/continuum">
-    <parameter>
-      <name>driverClassName</name>
-      <value>org.apache.derby.jdbc.EmbeddedDriver</value>
-    </parameter>
-    <parameter>
-      <name>factory</name>
-      <value>org.apache.commons.dbcp.BasicDataSourceFactory</value> <!-- Sets up Database Connection Pooling -->
-    </parameter>
-    <parameter>
-      <name>url</name>
-      <value>jdbc:derby:database/continuum;create=true</value> <!-- Adjust path to suit -->
-    </parameter>
-    <parameter>
-      <name>username</name>
-      <value>sa</value>
-    </parameter>
-    <parameter>
-      <name>password</name>
-      <value></value>
-    </parameter>
-  </ResourceParams>
-
-  <Resource name="mail/Session" auth="Container" type="javax.mail.Session"/>
-  <ResourceParams name="mail/Session">
-    <parameter>
-      <name>mail.smtp.host</name>
-      <value>localhost</value>
-    </parameter>
- </ResourceParams>
-</Context>
-------------------------------------------
-
-* {Tomcat 5.5.x Specifics}
-
-    Tested on Tomcat v5.5.17 and v5.5.25
-
-    This example \<Context\> assumes technique #2 in the {{{#Defining_JNDI_Resources}Define JNDI Resource}} list. (This example lists out the <<<docBase>>> to the war file itself.)
-
-------------------------------------------
-<Context path="/continuum"
-         docBase="/path/to/continuum-webapp-1.2.war">
-
-  <Resource name="jdbc/users"
-            auth="Container"
-            type="javax.sql.DataSource"
-            username="sa"
-            password=""
-            driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
-            url="jdbc:derby:database/users;create=true" />
-
-  <Resource name="jdbc/continuum"
-            auth="Container"
-            type="javax.sql.DataSource"
-            username="sa"
-            password=""
-            driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
-            url="jdbc:derby:database/continuum;create=true" />
-
-  <Resource name="mail/Session"
-            auth="Container"
-            type="javax.mail.Session"
-            mail.smtp.host="localhost"/>
-</Context>
-------------------------------------------
-
-    <<Warning:>> The Tomcat 5.5.20 and 5.5.23 releases are missing MailSessionFactory and a few other classes. 
-    JNDI mail sessions will <<not>> work.  Use Tomcat 5.5.17 or see the workaround on {{{http://issues.apache.org/bugzilla/show_bug.cgi?id=40668}Bug 40668}}.
-
-* {Tomcat 6.0.x Specifics}
-
-    Tested on Tomcat v6.0.14
-
-------------------------------------------
-<Context path="/continuum"
-         docBase="/path/to/continuum-webapp-1.2.war">
-
-  <Resource name="jdbc/users"
-            auth="Container"
-            type="javax.sql.DataSource"
-            username="sa"
-            password=""
-            driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
-            url="jdbc:derby:database/users;create=true" />
-
-  <Resource name="jdbc/continuum"
-            auth="Container"
-            type="javax.sql.DataSource"
-            username="sa"
-            password=""
-            driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
-            url="jdbc:derby:database/continuum;create=true" />
-
-  <Resource name="mail/Session"
-            auth="Container"
-            type="javax.mail.Session"
-            mail.smtp.host="localhost"/>
-</Context>
-------------------------------------------
diff --git a/continuum-docs/src/site/apt/installation/tomcat.apt.vm b/continuum-docs/src/site/apt/installation/tomcat.apt.vm
new file mode 100644
index 0000000..d353716
--- /dev/null
+++ b/continuum-docs/src/site/apt/installation/tomcat.apt.vm
@@ -0,0 +1,165 @@
+ ------
+ Guide to Install Continuum on Tomcat
+ ------
+ Joakim Erdfelt
+ Emmanuel Venisse
+ ------
+ 2010-02-18
+ ------
+
+~~ 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.
+
+Guide to Install Continuum on Tomcat
+
+    Instructions for installing, deploying, configuring Continuum for the Apache Tomcat web container.
+
+~~%{toc|section=0}
+
+* {Server Configuration}
+
+    With every Tomcat version you will need a few things before you can deploy Continuum.
+
+    [[1]] Use at least Java JDK 1.5.0_11 to run Tomcat with Continuum.
+
+    [[2]] A defined <<<\<Context\>>>> xml section to define the JNDI resources.
+
+    [[3]] The JavaMail / Activation JAR files.
+
+    [[4]] The Apache Derby JAR files.
+
+    [[5]] Configure <<<$\{appserver.base\}>>> Java system property.
+
+** {Defining JNDI Resources}
+
+    Continuum will, on startup, ask the web container for a few JNDI configured resources, two JDBC DataSources, and one
+    JavaMail session.
+
+    To configure these JNDI resources in the Tomcat Web Container, you will need to specify a <<<\<Context\>>>> section
+    that Tomcat can utilize for those requests coming from Continuum.
+
+    Tomcat has several ways to accomplish this, with the most practical being to create a
+    <<<$CATALINA_HOME/conf/Catalina/localhost/continuum.xml>>> file containing a <<<\<Context\>>>> element.
+
+    The following are the JNDI names you will need to provide:
+
+      * <<<mail/Session>>>
+
+      * <<<jdbc/continuum>>>
+
+      * <<<jdbc/users>>>
+
+    The individual techniques for describing these resources, and the parameters associated with them are specific to
+    the Tomcat version, resource type, and even JDBC implementation type.
+
+    For the purposes of this document, the following assumptions are made.
+
+      [[1]] You are an Apache Tomcat administrator.
+
+      [[2]] You have an SMTP Server on localhost, port 25, with no login / password.
+
+      [[3]] You will be using the embedded Apache Derby database, rather than an external database.
+
+      [[4]] Details specific to Apache Tomcat, JavaMail, or Apache Derby are left for the reader to research on those
+            projects websites.
+
+    More information on using other supported databases is available in the Administrator's Guide on
+    {{{../administrator_guides/external-db.html} External Databases}}.
+
+** {The JavaMail / Activation JAR files}
+
+    <<Note:>> Continuum requires JavaMail 1.4 (or later)
+
+    Apache Tomcat does not typically ship with a copy of the JavaMail or Activation JAR files.
+    In your role as the Apache Tomcat administrator of your installation, you will need to obtain these JAR files and
+    place it into your preferred <<<lib>>> directory.
+
+    The appropriate <<<lib>>> directory to choose is a personal preference, and we do not encourage or enforce a
+    specific location for it, as all installations of Apache Tomcat are different.
+
+    For the record, we personally put them in the <<<$CATALINA_HOME/common/lib/>>> directory.
+
+    Direct download links for these JAR files.
+
+    * JavaMail 1.4 - {{{http://repo1.maven.org/maven2/javax/mail/mail/1.4/mail-1.4.jar}mail-1.4.jar}}
+
+    * Java Activation Framework 1.1 - {{{http://repo1.maven.org/maven2/javax/activation/activation/1.1/activation-1.1.jar}activation-1.1.jar}}
+
+** {The Apache Derby JAR files}
+
+    <<Note:>>Continuum has been tested with Apache Derby 10.1.3.1
+
+    The default installation of Continuum uses the Apache Derby 100% Java database to maintain Continuum-specific
+    information, and also the Users / Security Database.
+
+    You will need to obtain <<<derby.jar>>> and place it into your preferred <<<lib>>> directory.
+
+    We put them into the <<<$CATALINA_HOME/common/lib/>>> directory.
+
+    Direct download links for this JAR file:
+
+    * Derby 10.1.3.1 - {{{http://repo1.maven.org/maven2/org/apache/derby/derby/10.1.3.1/derby-10.1.3.1.jar}derby-10.1.3.1.jar}}
+
+    If you have configured a different database, please copy that JDBC driver in place of the Derby driver.
+
+** {Configure the appserver.base Java system property}
+
+    The <<<$\{appserver.base\}>>> system property is used by the Continuum internal logging configuration to determine
+    where to output its logs to. It is important to define this property either in the <<<$CATALINA_OPTS>>> system
+    environment variable (if Tomcat is being launched via the command line) or the service properties (if being launched
+    as a service or daemon).
+
+    The format typically expected is <<<\-Dappserver.base=/path/to/continuum-base>>>
+
+    You can utilize the <<<$CATALINA_HOME/bin/setenv.sh>>> script to set this value in a Tomcat specific way.
+
+------------------------------------------
+#!/bin/bash
+# Keep the appserver.home and appserver.base values the same when running under Tomcat
+
+export CATALINA_OPTS="-Dappserver.home=$CATALINA_HOME -Dappserver.base=$CATALINA_HOME"
+------------------------------------------
+
+** {Context XML Example}
+
+    The following context.xml has been tested on Tomcat v5.5.25 and Tomcat v6.0.14.
+
+------------------------------------------
+<Context path="/continuum" docBase="/path/to/continuum-webapp-${project.version}.war">
+
+  <Resource name="jdbc/users"
+            auth="Container"
+            type="javax.sql.DataSource"
+            username="sa"
+            password=""
+            driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
+            url="jdbc:derby:database/users;create=true" />
+
+  <Resource name="jdbc/continuum"
+            auth="Container"
+            type="javax.sql.DataSource"
+            username="sa"
+            password=""
+            driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
+            url="jdbc:derby:database/continuum;create=true" />
+
+  <Resource name="mail/Session"
+            auth="Container"
+            type="javax.mail.Session"
+            mail.smtp.host="localhost"/>
+</Context>
+------------------------------------------
diff --git a/continuum-docs/src/site/apt/installation/upgrade.apt b/continuum-docs/src/site/apt/installation/upgrade.apt
deleted file mode 100644
index 7680e10..0000000
--- a/continuum-docs/src/site/apt/installation/upgrade.apt
+++ /dev/null
@@ -1,112 +0,0 @@
- ------
- Upgrade
- ------
- Olivier Lamy
- Emmanuel Venisse
- ------
- Sep 10 2008
- ------
-
-Upgrade
-
-* Goal
-
-    When upgrading Continuum, it could have some database model changes. This tool exports data from old database model and imports the data into the new database model.
-
-    There are 2 databases that need to be converted, one for the builds and one for the users.
-    
-    <<Note>> If you are upgrading from 1.1 to 1.2, no upgrade tool is needed.
-    
-    Due the fix of {{{http://jira.codehaus.org/browse/CONTINUUM-1688}CONTINUUM-1688}} :
-    
-    * if you use mssql server : you have to uncomment lines in a file in the webapp (WEB-INF/classes/META-INF/plexus/application.xml) (search mssql support).
-    
-    * if you use a 1.1 database you have to change manually the size of a column (in order to have the fix) :
-    
-+------------------------------------------+    
--- command tested with derby database
-alter table CHANGESET alter column CHANGECOMMENT SET DATA TYPE varchar(8192)  
-+------------------------------------------+   
-
-* Download The Tool
-
-    The tool is a standalone jar that you can download from the central repo.
-
-    You will need to download 2 versions of the tool, one for the export out of the old version and one for the import into the new version:
-
-        * {{http://repo1.maven.org/maven2/org/apache/maven/continuum/data-management-cli/1.1-beta-3/data-management-cli-1.1-beta-3-app.jar}}
-
-        * {{http://repo1.maven.org/maven2/org/apache/maven/continuum/data-management-cli/1.1-beta-4/data-management-cli-1.1-beta-4-app.jar}}
-
-        * {{http://repo1.maven.org/maven2/org/apache/maven/continuum/data-management-cli/1.1/data-management-cli-1.1-app.jar}}
-        
-        * {{http://repo1.maven.org/maven2/org/apache/continuum/data-management-cli/1.2/data-management-cli-1.2-app.jar}}
-
-    The first version of this tool is 1.1-beta-2
-
-* Exporting Data from the old version
-
-    Follow these steps:
-
-        * Stop the old version of continuum
-
-        * Export the build and user data from the old version using the jar for the old version:
-
-+------------------------------------------+
-java -Xmx512m -jar data-management-cli-1.1-beta-4-app.jar -buildsJdbcUrl jdbc:derby:${old.continuum.home}/data/continuum/database -mode EXPORT -directory backups
-java -Xmx512m -jar data-management-cli-1.1-beta-4-app.jar -usersJdbcUrl jdbc:derby:${old.continuum.home}/data/users/database -mode EXPORT -directory backups
-+------------------------------------------+
-
-* Importing Data to the new version
-
-    Follow these steps:
-
-        * Start the new version continuum to create the new data model.
-
-        * Stop continuum
-
-        * Run the specific steps for your version, described below
-
-        * Import the build and user data into the new version using the jar for the new version:
-
-+------------------------------------------+
-java -Xmx512m -jar data-management-cli-1.1-app.jar -buildsJdbcUrl jdbc:derby:${new.continuum.home}/data/continuum/database -mode IMPORT -directory backups
-java -Xmx512m -jar data-management-cli-1.2-app.jar -usersJdbcUrl jdbc:derby:${new.continuum.home}/data/users/database -mode IMPORT -directory backups
-+------------------------------------------+
-
-        * <<NEXT_VAL values in SEQUENCE_TABLE must be checked before restarting continuum>>
-
-            * Normally, the SEQUENCE_TABLE is ok but in some cases the values are wrong.
-
-            * Before starting Continuum for the first time after the import, connect to the db with a client like {{{http://squirrel-sql.sourceforge.net/}Squirrel SQL}} and check the values in the <<NEXT_VAL>> column.
-
-            * Values must be greater than the max id value in each table.
-
-            * For example, the next value of "org.apache.maven.continuum.model.Project" must be greater than the greatest id in Project table.
-
-        * Start the new version of continuum.
-
-* Specific steps to do before import
-
-** 1.1 import
-
-    Before to import from an older version (before 1.1-beta-4 to 1.1 final, you must open the builds.xml file under backup directory and remove all <<'testResults'>> tags.
-    You can remove them with the following XSL:
-
-+------------------------------------------+
-<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
-<xsl:output method="xml"/>
- <xsl:template match="testResult"/>
-  <xsl:template match="@*|node()">
-    <xsl:copy>
-      <xsl:apply-templates select="@*|node()"/>
-    </xsl:copy>
-  </xsl:template>
-</xsl:stylesheet>
-+------------------------------------------+
-
-    And you can run it with this command:
-
-+------------------------------------------+
-xsltproc copy.xsl builds.xml > fixed-builds.xml
-+------------------------------------------+
diff --git a/continuum-docs/src/site/apt/installation/upgrade.apt.vm b/continuum-docs/src/site/apt/installation/upgrade.apt.vm
new file mode 100644
index 0000000..2b31571
--- /dev/null
+++ b/continuum-docs/src/site/apt/installation/upgrade.apt.vm
@@ -0,0 +1,159 @@
+ ------
+ Upgrade
+ ------
+ Olivier Lamy
+ Emmanuel Venisse
+ ------
+ Sep 10 2008
+ ------
+
+~~ 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.
+
+Upgrading Continuum
+
+    This document will help you upgrade Continuum from 1.2.x to 1.3.3 and above.
+
+    When upgrading Continuum, it could have some database model changes. Usually these changes will be migrated for you,
+    but in some cases you may need to use a backup from the previous version and restore that data into the new version.
+    The Data Management tool exports data from the old database model and imports the data into the new database model.
+
+    If you had used the <<<APP_BASE>>> environment variable in Continuum 1.2 to differentiate your configuration from
+    the installation, you should rename it to <<<CONTINUUM_BASE>>> in Continuum 1.3.
+    
+* Changes to Take Note of in Continuum 1.4.x
+    
+    The Jetty version in Continuum 1.4.1 and above has been upgraded to 8.1.7. When upgrading to Continuum 1.4.1 or
+    higher, there is a need to update the contents of <<<$CONTINUUM_BASE/conf/wrapper.conf>>> to match the one included
+    in the new distribution if any copies or modifications have been made. The <<<jetty.xml>>> format has also changed,
+    and should be re-added from the distribution with any modifications previously made. It is no longer read from
+    <<<$CONTINUUM_BASE>>>, and JNDI connections can now be managed via the files in the <<<contexts>>> directory.
+
+* Changes to Take Note of in Continuum 1.3.x
+
+    The Jetty version in Continuum 1.3.4 and above has been upgraded to 6.1.19. When upgrading to Continuum 1.3.4 or
+    higher, there is a need to update the library contents listed in <<<$CONTINUUM_BASE/conf/wrapper.conf>>> with the
+    ones included in the new distribution especially if the <<<$CONTINUUM_BASE>>> directory is separate from the
+    installation.
+
+    In Continuum 1.3.6, configuration for local repositories in build agents were added. This is used to match the local
+    repository in the build agent to that of the local repository (used by the project to be built) set in the master.
+    So if you are upgrading from a lower version, you might need to add the <<<localRepositories>>> configuration in
+    your build agent's configuration file. For more details, read {{{./build-agent.html}Installing and Configuring a
+    Build Agent}}.
+
+* Using Backup and Restore to upgrade
+
+    There are 2 databases that need to be considered: one for the builds and one for the users.
+
+    While the databases typically auto-upgrade across releases, you may wish to perform an export and import to have
+    full control of the upgrade, make modifications to the data, or retain a backup in case a downgrade is needed.
+
+    First, download the Data Management tools you will need.  The tool is a standalone JAR that you can download from
+    the central repo.
+
+    You will need to download two versions of the tool, one for the export out of the old version and one for the import
+    into the new version:
+
+    <<Note:>> The 1.2, 1.2.2 and 1.2.3 released versions of this tool have a bug.
+     To export databases from 1.2.2 or 1.2.3, you will need to use version 1.2.3.1 of the tool.
+     To export databases from 1.2, you may use the 1.1 version of the tool.
+
+        * {{{http://repo1.maven.org/maven2/org/apache/continuum/data-management-cli/${project.version}/data-management-cli-${project.version}-app.jar} Data Management CLI for Continuum ${project.version}}}
+
+        * {{{http://repo1.maven.org/maven2/org/apache/continuum/data-management-cli/1.3.8/data-management-cli-1.3.8-app.jar} Data Management CLI for Continuum 1.3.8}}
+
+        * {{{http://repo1.maven.org/maven2/org/apache/continuum/data-management-cli/1.2.3.1/data-management-cli-1.2.3.1-app.jar} Data Management CLI for Continuum 1.2.x}}
+
+        * {{{http://repo1.maven.org/maven2/org/apache/maven/continuum/data-management-cli/1.1/data-management-cli-1.1-app.jar} Data Management CLI for Continuum 1.1}}
+
+
+    Next, follow these steps to export data from the old version
+
+        * Stop the old version of Continuum
+
+        * Execute this command to create the <<<builds.xml>>> export file
+
++------------------------------------------+
+java -Xmx512m -jar data-management-cli-1.2.3.1-app.jar \
+  -buildsJdbcUrl jdbc:derby:${old.continuum.home}/data/databases/continuum \
+  -mode EXPORT \
+  -directory backups
++------------------------------------------+
+
+    Then, follow these steps to import the data to the new version
+
+        * Start the new version of Continuum to create the new data model, but do not configure it.
+
+        * Stop Continuum
+
+        * Execute this command to import the builds data from the XML file you created earlier:
+
++------------------------------------------+
+java -Xmx512m -jar data-management-cli-${project.version}-app.jar \
+  -buildsJdbcUrl jdbc:derby:${new.continuum.home}/data/databases/continuum \
+  -mode IMPORT \
+  -directory backups -strict
++------------------------------------------+
+
+    <<Note:>> Remove <<<-strict>>> when importing data from 1.3.1 to 1.3.x to ignore unrecognized tags due to model
+    changes.
+
+    Finally, be aware that sometimes the <<<NEXT_VAL>>> values in the <<<SEQUENCE_TABLE>>> need to be adjusted. Before
+    starting Continuum for the first time after the import, connect to the database with a client like
+    {{{http://squirrel-sql.sourceforge.net/}Squirrel SQL}} and check the values in the <<<NEXT_VAL>>> column of the
+    <<<SEQUENCE_TABLE>>>.
+
+    Values must be greater than the max ID value in each table. For example, the next value of
+    <<<org.apache.maven.continuum.model.Project>>> must be greater than the greatest ID in <<<Project>>> table.
+
+    Here are some example SQL statements.  You may need to add or remove lines depending on the contents of your database.
+
++-----------------------------------------+
+UPDATE SEQUENCE_TABLE set NEXT_VAL = (select max(systemconfiguration_id)+1 from SYSTEMCONFIGURATION)
+  WHERE SEQUENCE_NAME='org.apache.maven.continuum.model.system.SystemConfiguration';
+
+UPDATE SEQUENCE_TABLE set NEXT_VAL = (select max(id)+1 from BUILDQUEUE)
+  WHERE SEQUENCE_NAME='org.apache.maven.continuum.model.project.BuildQueue';
+
+UPDATE SEQUENCE_TABLE set NEXT_VAL = (select max(id)+1 from SCHEDULE)
+  WHERE SEQUENCE_NAME='org.apache.maven.continuum.model.project.Schedule';
+
+UPDATE SEQUENCE_TABLE set NEXT_VAL = (select max(id)+1 from BUILDDEFINITION)
+  WHERE SEQUENCE_NAME='org.apache.maven.continuum.model.project.BuildDefinition';
+
+UPDATE SEQUENCE_TABLE set NEXT_VAL = (select max(id)+1 from LOCALREPOSITORY)
+  WHERE SEQUENCE_NAME='org.apache.continuum.model.repository.LocalRepository';
+
+UPDATE SEQUENCE_TABLE set NEXT_VAL = (select max(id)+1 from PROJECTGROUP)
+  WHERE SEQUENCE_NAME='org.apache.maven.continuum.model.project.ProjectGroup';
+
+UPDATE SEQUENCE_TABLE set NEXT_VAL = (select max(scmresult_id)+1 from SCMRESULT)
+  WHERE SEQUENCE_NAME='org.apache.maven.continuum.model.scm.ScmResult';
+
+UPDATE SEQUENCE_TABLE set NEXT_VAL = (select max(projectdependency_id)+1 from PROJECTDEPENDENCY)
+  WHERE SEQUENCE_NAME='org.apache.maven.continuum.model.project.ProjectDependency';
+
+UPDATE SEQUENCE_TABLE set NEXT_VAL = (select max(id)+1 from BUILDDEFINITIONTEMPLATE)
+  WHERE SEQUENCE_NAME='org.apache.maven.continuum.model.project.BuildDefinitionTemplate';
+
+UPDATE SEQUENCE_TABLE set NEXT_VAL = (select max(id)+1 from ABSTRACTPURGECONFIGURATION)
+  WHERE SEQUENCE_NAME='org.apache.continuum.model.repository.AbstractPurgeConfiguration';
++-----------------------------------------+
+
+    Now you can start your new version of Continuum.
+
diff --git a/continuum-docs/src/site/apt/user_guides/building_project/build_results.apt b/continuum-docs/src/site/apt/user_guides/building_project/build_results.apt
new file mode 100644
index 0000000..8da96ca
--- /dev/null
+++ b/continuum-docs/src/site/apt/user_guides/building_project/build_results.apt
@@ -0,0 +1,63 @@
+ ------
+ Build Results Management
+ ------
+ ------
+ Feb 23 2009
+ ------
+
+~~ 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.
+
+Build Results Management
+
+[../../images/build_result-2.png] Builds tab
+
+    To view the result of the build:
+
+    [[1]] Click the link for the project group of the project you want to view - the link will be
+    under the <<Name>> column.
+
+    [[2]] Click the build number link under the <<Build>> column of the project you want to view.
+    Or you can click the project link again and click the <<Builds>> link at the top of the page, then click
+    the <<Result>> link, next to the <<State>> column.
+
+    []
+
+    When builds are executed frequently, deleting unnecessary and failed build results is needed.
+    To delete build results, follow these steps:
+
+    [[1]] Click the name of the project group.
+
+    [[2]] Click on the build number under the <<Build>> column. You will be directed to the build result
+    page as shown below.
+
+    \ 
+
+[../../images/build_result-1.png] Build Results page
+
+    The <<Triggered by>> field displays the username of the person who forced the build,
+    or the name of the schedule if the build is triggered by a schedule.
+
+    Or you can click on the name of the project that you want to delete build results from.
+
+        * Click the <<Builds>> tab. The build results list will be displayed.
+
+        * Check the box of the build results that you want to delete.
+
+        []
+
+    [[3]] Click the <<Delete>> button.
diff --git a/continuum-docs/src/site/apt/user_guides/building_project/cancelling_build.apt b/continuum-docs/src/site/apt/user_guides/building_project/cancelling_build.apt
new file mode 100644
index 0000000..253e31b
--- /dev/null
+++ b/continuum-docs/src/site/apt/user_guides/building_project/cancelling_build.apt
@@ -0,0 +1,40 @@
+ ------
+ Cancelling Builds
+ ------
+ Maria Catherine Tan
+ ------
+ Jan 16 2009
+ ------
+
+~~ 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.
+
+Cancelling Project Build
+
+    This will cancel the build of the selected project.
+
+    To cancel the build for project, click the <<Cancel>> button of the project on the <<Project Group Summary>> page or on the <<Queues>> page.
+
+[../../images/cancelbuild.gif] Cancel Button
+
+Cancelling Project Group Build
+
+    This will cancel all builds of the project group and will also remove the projects from the build queue.
+
+    In the Project Group Summary page, click the
+
+[../../images/cancel-group-build.png] Cancel Group Build Button
diff --git a/continuum-docs/src/site/apt/user_guides/building_project/forced_build.apt b/continuum-docs/src/site/apt/user_guides/building_project/forced_build.apt
new file mode 100644
index 0000000..afb20a1
--- /dev/null
+++ b/continuum-docs/src/site/apt/user_guides/building_project/forced_build.apt
@@ -0,0 +1,68 @@
+ ------
+ Force Project Build
+ ------
+ ------
+ 2010-02-18
+ ------
+
+~~ 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.
+
+Force Project Build
+
+    Occasionally you may want to force a build outside of the regular schedule.
+    When builds are triggered manually, the following happens:
+
+    * Projects are updated from the SCM.
+      These are queued under the <<Prepare Build Queues>> section in <<Queues>> page.
+
+    * Builds of the projects are executed.
+      These are queued under the <<Build Queues>> in <<Queues>> page.
+
+    []
+
+    To manually build a project perform the following steps:
+
+    [[1]] Click <<Show Project Groups>>.
+
+    [[2]] Click the project group link of the project you want to build.
+    This will put you on the <<Summary>> page of the project group.
+
+    [[3]] You can click <<Build all projects>> button under <<Group Actions>> to build all
+    the projects in the project group.
+
+[../../images/force_build.png] Project Group Actions
+
+    [[4]] To build an individual project, you can click on the build icon that is found
+    along the row of the project you want to build. It is the first icon on the right of
+    the project name. This will execute the default build goal you have defined for that project.
+
+    To build selected projects, check the box beside the name of the project,
+    then click the <<Build Project(s)>> button.
+
+    If you want to build the project according to a specific build goal other than the
+    default build goal, click on the project name to go to the <<Project's Information>> page.
+    All build goal definitions for the project are listed under the <<Build Definitions>> section.
+    Click on the build icon to the right of the specific build goal you want to execute.
+
+    []
+    
+    *Note* In a distributed build setup, the project builds are not executed if no build agent is
+    configured or if a build agent group with no build agent, is configured in the build environment 
+    that is attached to the project's build definition.
+
+    To view the results of the build, refer to {{{./build_results.html}Build Results Management}}.
diff --git a/continuum-docs/src/site/apt/user_guides/building_project/index.apt b/continuum-docs/src/site/apt/user_guides/building_project/index.apt
index 7aa962d..25e0a03 100644
--- a/continuum-docs/src/site/apt/user_guides/building_project/index.apt
+++ b/continuum-docs/src/site/apt/user_guides/building_project/index.apt
@@ -3,24 +3,69 @@
  ------
  Emmanuel Venisse
  ------
- Oct 3 2007
+ 2010-02-18
  ------
 
+~~ 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.
+
 Building Projects
 
-    For Ant and maven builds the following system properties will be added via -D command line:
-    
-    * continuum.project.group.name
-    
-    * continuum.project.lastBuild.state : last build state int flag
-    
-    * continuum.project.lastBuild.number
-    
-    * continuum.project.nextBuild.number
-    
-    * continuum.project.id
-    
-    * continuum.project.name
-    
-    * continuum.project.version 
-    
\ No newline at end of file
+    For Ant and Maven builds the following system properties will be added via -D command line:
+
+      * <<<continuum.project.group.name>>>
+
+      * <<<continuum.project.lastBuild.state>>> : last build state int flag
+
+      * <<<continuum.project.lastBuild.number>>>
+
+      * <<<continuum.project.nextBuild.number>>>
+
+      * <<<continuum.project.id>>>
+
+      * <<<continuum.project.name>>>
+
+      * <<<continuum.project.version>>>
+
+      []
+
+    When building projects, the build order is determined by the inter-dependency of the projects.
+    This would mean that the dependencies of a project are built first.
+
+    In cases when a project group can build projects in parallel build queues but one of those projects depend
+    on another project, the inter-dependent projects will build in the same build queue.
+
+    Projects can be built in two ways:
+
+      [[1]] {{{./schedule_build.html} Scheduled Builds}}
+
+      [[2]] {{{./forced_build.html} Forced Builds}}
+
+      []
+
+    Projects will have the <<in queue>> icon once the forced build or a scheduled build is triggered. This means that the project is either in the <<prepare build
+    queue>> or in the <<build queue>>.
+
+[../../images/inqueue.gif]
+
+    Checkout or update of projects takes longer with distributed builds enabled because after an SCM checkout or SCM update, an SCM changelog follows to get the "latest
+    update date" needed to determine whether projects should build or not.
+
+* Cancelling builds
+
+    If a build has been started, you can cancel it before it completes. See
+    {{{./cancelling_build.html} Cancelling Builds}} for more information.
diff --git a/continuum-docs/src/site/apt/user_guides/building_project/schedule_build.apt b/continuum-docs/src/site/apt/user_guides/building_project/schedule_build.apt
new file mode 100644
index 0000000..6d4433c
--- /dev/null
+++ b/continuum-docs/src/site/apt/user_guides/building_project/schedule_build.apt
@@ -0,0 +1,55 @@
+ ------
+ Scheduling Project Build
+ ------
+ ------
+ 2010-02-18
+ ------
+
+~~ 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.
+
+Scheduling Project Build
+
+    Schedules determine the project's time interval to build.
+
+    When scheduled builds are triggered, there is no dependency ordering between project groups
+    and the following happens:
+
+      * Projects are updated from the SCM.
+        These are queued under the <<Prepare Build Queues>> section in <<Queues>> page.
+
+      * Builds of the projects are executed.
+        These are queued under the <<Build Queues>> in <<Queues>> page.
+
+      []
+
+    To configure a scheduled build:
+
+      [[1]] Create a schedule. You can refer to {{{../../administrator_guides/schedules.html} Managing Schedules}} section.
+
+      [[2]] Add a build definition to a project using the schedule created in step 1 for the <<Schedule>> field.
+            You can refer to the section {{{../managing_builddef/index.html} Managing Build Definitions}}.
+
+[../../images/schedule_build.png] Scheduling build
+
+      []
+    
+    <<Note:>> In a distributed build setup, the project builds are not executed if no build agent is
+    configured or if a build agent group with no build agent, is configured in the build environment 
+    that is attached to the project's build definition.
+
+    To view the results of the build, refer to {{{./build_results.html}Build Results Management}}.
diff --git a/continuum-docs/src/site/apt/user_guides/index.apt b/continuum-docs/src/site/apt/user_guides/index.apt
index 208bdd6..a656357 100644
--- a/continuum-docs/src/site/apt/user_guides/index.apt
+++ b/continuum-docs/src/site/apt/user_guides/index.apt
@@ -1,15 +1,37 @@
  ------
  User's Guides
  ------
+ ------
+ 2010-02-18
+ ------
+
+~~ 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.
 
 User's Guides
 
- * {{{building_project/index.html}Building Projects}}
+ * {{{./building_project/index.html}Building Projects}}
 
- * {{{managing_builddef/index.html}Managing Build Definitions}}
+ * {{{./managing_builddef/index.html}Managing Build Definitions}}
 
- * {{{managing_project/index.html}Managing Projects}}
+ * {{{./managing_project/index.html}Managing Projects}}
 
- * {{{notification/index.html}Notifications}}
+ * {{{./notification/index.html}Notifications}}
 
- * {{{release/index.html}Releasing Projects}}
\ No newline at end of file
+ * {{{./release/index.html}Releasing Projects}}
+
+ * {{{./report/index.html}Project Builds Report}}
diff --git a/continuum-docs/src/site/apt/user_guides/managing_builddef/builddefGroup.apt b/continuum-docs/src/site/apt/user_guides/managing_builddef/builddefGroup.apt
deleted file mode 100644
index f533c9d..0000000
--- a/continuum-docs/src/site/apt/user_guides/managing_builddef/builddefGroup.apt
+++ /dev/null
@@ -1,11 +0,0 @@
- ------
- Project Group Build Definition
- ------
- Emmanuel Venisse
- ------
- Oct 3 2007
- ------
-
-Project Group Build Definition
-
-    To write
\ No newline at end of file
diff --git a/continuum-docs/src/site/apt/user_guides/managing_builddef/builddefProject.apt b/continuum-docs/src/site/apt/user_guides/managing_builddef/builddefProject.apt
deleted file mode 100644
index 0dc3c38..0000000
--- a/continuum-docs/src/site/apt/user_guides/managing_builddef/builddefProject.apt
+++ /dev/null
@@ -1,11 +0,0 @@
- ------
- Project Build Definition
- ------
- Emmanuel Venisse
- ------
- Oct 3 2007
- ------
-
-Project Build Definition
-
-    To write
\ No newline at end of file
diff --git a/continuum-docs/src/site/apt/user_guides/managing_builddef/index.apt b/continuum-docs/src/site/apt/user_guides/managing_builddef/index.apt
index f745bb9..8ec7c68 100644
--- a/continuum-docs/src/site/apt/user_guides/managing_builddef/index.apt
+++ b/continuum-docs/src/site/apt/user_guides/managing_builddef/index.apt
@@ -4,17 +4,86 @@
  Emmanuel Venisse
  Olivier Lamy
  ------
- Oct 3 2007
+ 2010-02-18
  ------
 
+~~ 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.
+
 Managing Build Definitions
 
     Each project or project group must have at least one attached build definition in order to build.
-    
+
     Depending on the project, you can define different values which will be used in order to build your project.
-    
-    Continuum includes some default build definitions which can be changed in the <<{{{../../administrator_guides/builddefTemplate.html}Build Definition Templates screen}}>>.
-    
-    You can add or edit build definitions at the <<{{{builddefGroup.html}Project Group level}}>> or at the <<{{{builddefProject.html}Project level}}>>.
-    
-     
\ No newline at end of file
+
+    Continuum includes some default build definitions which can be changed in the <<{{{../../administrator_guides/builddefTemplate.html}Build Definition Templates}}>> screen.
+
+    You can add or edit build definitions at the <<Project Group level>> or at the <<Project level>>.
+
+Project Group Build Definition
+
+    The project group level build definition is executed on all of the projects in the group. The following description
+    covers the fields for a Maven project, though the fields for other types are similar.
+
+[../../images/buildDefGroup.png] Project Group Build Definitions
+
+    To add a build definition to your project group, under the <<Build Definitions>> tab in the <<Project Information>>
+    screen, click <<Add>>.
+
+    Supply the values for the necessary fields:
+
+      * Enter your <<POM filename>>, which is very likely the same as previous builds, <<<pom.xml>>>.
+
+      * In the <<Goals>> text box, enter your new goals. For example, <<<clean site deploy>>> or <<<release:branch>>>.
+
+      * You may have arguments for Maven, such as <<<--batch-mode --non-recursive>>>.
+          Add your arguments in the <<Arguments>> text box or leave it empty.
+
+      * Check <<Build Fresh>> to do a fresh checkout from SCM before the build process.
+      Check <<Always Build>> if you want to execute the goal every time you build the project.
+      If you want this build definition to be your default for building your project,
+      check the <<Is it default?>> check box.
+
+      * Select your build schedule from the pull-down menu. There will only be the <<<DEFAULT_SCHEDULE>>>
+      if you have not defined any others.
+
+      * Select from the pull-down menu the <<Build Environment>> for the build definition.
+
+      * Select the <<Type>> from the pull-down menu.
+
+      * Select the <<Update Policy>> from the pull-down menu. This describes when a Continuum project definition should
+        be updated if changes are detected in the Maven POM.
+
+      * You can supply a short description of the build definition (<<Description>>).
+
+      []
+
+[../../images/add-build-definition.png]
+
+    Click <<Save>> to complete the changes.
+
+Project Build Definition
+
+    The project level build definition is executed for a specific project where the build definition is defined. The
+    following description covers the fields for a Maven project, though the fields for other types are similar.
+
+[../../images/buildDefProject.png] Project Build Definitions
+
+    To add a build definition to your project, select a project within the group and under the <<Build Definitions>>
+    section in the <<Project Information>> screen, click <<Add>>.
+
+    The fields are the same as for a project group build definition.
diff --git a/continuum-docs/src/site/apt/user_guides/managing_project/addProject.apt b/continuum-docs/src/site/apt/user_guides/managing_project/addProject.apt
index 07f49f1..9bee0b7 100644
--- a/continuum-docs/src/site/apt/user_guides/managing_project/addProject.apt
+++ b/continuum-docs/src/site/apt/user_guides/managing_project/addProject.apt
@@ -7,72 +7,214 @@
  Oct 11 2007
  ------
 
+~~ 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.
+
 Add a Project
 
 ~~%{toc|section=0}
 
-* {Maven 2 project}
+* {Maven project (Maven 2 or Maven 3)}
 
-  From the menu, choose the 'Maven 2.0.x Project' entry
-    
-[../../images/add-m2-project-menu.png] Add a maven2 project
+  From the menu, choose the <<Maven Project>> entry
 
-  The pom.xml file must be available through one of the following protocols: http, https, or ftp 
-  (The file protocol is also supported but is disabled by default for security and must enabled manually).
-    
-  Or it can be uploaded from a local file (Note this doesn't support multi modules project).
-    
-[../../images/add-m2-project.png] Add a maven2 project
+[../../images/add-m2-project-menu.png] Add a Maven project
 
-  You can define username/password if the POM URL requires authentication.
+  The <<<pom.xml>>> file must be available through one of the following protocols: http, https, or ftp.
 
-  If your SCM stores credentials like CVS or SVN and you want to use the SCM Credentials cache, check the "Use SCM Credentials Cache" field.
+  <<Note:>> The file protocol is also supported but is disabled by default for security and must be enabled manually.
 
-  You can define the group you want to use or "Defined by POM" in this case project.name will be use as Project Group.
+~~ TODO: Explain how to enable the file protocol
 
-  By default, Continuum adds each sub-module POM as an individual Continuum Project. If you want to add only the root POM without sub-modules, check the "load only root as recursive build" field.
-  
-  You can choose a Build Definition Template which will be applied to your project.  If you choose a Build Definition
-  Template, the build definitions from the template will be added in addition to any build definitions that are defined
+  The <<<pom.xml>>> can also be uploaded from a local file.
+
+  <<Note:>> This doesn't support multi module projects.
+
+[../../images/add-m2-project.png] Add a Maven project
+
+  You can supply a username and password if the POM URL requires authentication.  This information will be stored in the database in plain text and reused later for SCM checkouts and updates.
+
+  If your SCM stores credentials like CVS or SVN and you want to use the SCM Credentials cache, check the <<Use SCM Credentials Cache>> field.
+
+~~ TODO:  If 'use cached credentials' is checked, then the credentials should NOT be stored in the database.  Need to see whether that's actually true before documenting it.
+
+  You can define the group you want to use or <<Defined by POM>> in this case <<<project.name>>> will be used as <<Project Group>>.
+
+  You cannot add a duplicate project (duplicates would mean another instance of a project with the same groupId, artifactId, and version) in the same Project Group.
+
+  If <<Checkout multi-module project in separate directories>> radio box is selected when a project is added to Continuum, each sub-module POM would be added as an individual Continuum Project.
+  Each of these Continuum projects having it's own working directory. For example, you have a multi-module project with the following structure:
+
++----------------------------+
+simple-multi-module-project
+|-- module-a
+|   |-- pom.xml
+|   `-- src
+|       |-- main
+|       |   `-- java
+|       |       `-- ...
+|       `-- test
+|           `-- java
+|               `-- ...
+|-- module-b
+|   |-- pom.xml
+|   `-- src
+|       |-- main
+|       |   `-- java
+|       |       `-- ...
+|       `-- test
+|           `-- java
+|               `-- ...
+`-- pom.xml
++----------------------------+
+
+  This project tree means that there will be three Continuum Projects added in Continuum. Let's say, the top level project was assigned
+  a <<<project id>>> of '1' when it was added in Continuum and module-a got a <<<project id>>> of '2' and module-b got a <<<project id>>> of '3'. Now in
+  Continuum's working directory, you will see these projects checked out as below. Note that their <<<project ids>>> correspond to their own
+  working directories.
+
++----------------------------+
+|-- 1
+|   |-- module-a
+|   |   |-- pom.xml
+|   |   `-- src
+|   |       |-- main
+|   |       |   `-- java
+|   |       |       `-- ...
+|   |       `-- test
+|   |           `-- java
+|   |               `-- ...
+|   |-- module-b
+|   |   |-- pom.xml
+|   |   `-- src
+|   |       |-- main
+|   |       |   `-- java
+|   |       |       `-- ...
+|   |       `-- test
+|   |           `-- java
+|   |               `-- ...
+|   `-- pom.xml
+|-- 2
+|   |-- pom.xml
+|   `-- src
+|       |-- main
+|       |   `-- java
+|       |       `-- ...
+|       `-- test
+|           `-- java
+|               `-- ...
+`-- 3
+    |-- pom.xml
+    `-- src
+        |-- main
+        |   `-- java
+        |       `-- ...
+        `-- test
+            `-- java
+                `-- ...
++----------------------------+
+
+  You can force Continuum to check out the entire project into a single directory by selecting the <<Checkout multi-module project
+  in single directory>> radio box.
+
+  <<Note:>> If your project has a flat structure similar to the one below, you might want to check out
+  your project into a single directory to be able to release it in Continuum.
+
++----------------------------+
+simple-flat-multi-module
+|-- root-project
+|   `-- pom.xml
+|-- module-a
+|   |-- pom.xml
+|   `-- src
+|       |-- main
+|       |   `-- java
+|       |       `-- ...
+|       `-- test
+|           `-- java
+|               `-- ...
+`-- module-b
+   |-- pom.xml
+   `-- src
+       `-- main
+           `-- ...
++----------------------------+
+
+  If you want to add the multi-module project as a single Continuum project, select the <<load only root as recursive build>>
+  radio box.
+
+  For a project or POM that was added as a single Continuum project and as it's own project group, the <<<--non-recursive>>>
+  flag in the default project group build definition will be removed. But if the project or POM was added as a single
+  Continuum project to an already existing project group, a project level build definition with the <<<--non-recursive>>> flag
+  stripped from the <<<arguments>>> field will be created for the project and will be set as the project's default build definition.
+  See {{{http://jira.codehaus.org/browse/CONTINUUM-2563} CONTINUUM-2563}} for the related issue.
+
+  You can choose a <<Build Definition Template>> which will be applied to your project.  If you choose a <<Build Definition
+  Template>>, the build definitions from the template will be added in addition to any build definitions that are defined
   at the project group level.
 
-* {Maven 1 project}
-    
-  From the menu, choose the 'Maven 1.x Project' entry
-    
-[../../images/add-m1-project-menu.png] Add a maven1 project
+  When adding projects whose parent project is building on another server,
+  make sure that the <<<settings.xml>>> with the necessary repositories exists in <<<[USER_HOME]/.m2/>>> directory.
+  Continuum uses <<<[USER_HOME]/.m2/settings.xml>>> and not the one found in <<<[M2_HOME]/conf/>>>.
 
-  The project.xml file must be available through one of the following format : http, https and ftp 
-  (file protocol is off by default for security and must enabled manually).
-    
-  Or it can be uploaded (Note this doesn't support multi modules project).
+  The scm connection url must be present in the POM and must match the actual location of the pom in the scm repository.
+
+* {Maven 1 project}
+
+  From the menu, choose the <<Maven 1.x Project>> entry
+
+[../../images/add-m1-project-menu.png] Add a Maven 1 project
+
+  The <<<project.xml>>> file must be available through one of the following format : http, https and ftp.
+
+  <<Note:>> The file protocol is off by default for security and must enabled manually.
+
+  The <<<project.xml>>> can also be uploaded from a local file.
+
+  <<Note:>> This doesn't support multi modules project.
 
   The project you're adding can't use a parent.
-    
-[../../images/add-m1-project.png] Add a maven1 project
+
+[../../images/add-m1-project.png] Add a Maven 1 project
 
   You can define username/password if the POM URL require an authentication.
 
-  If your SCM store credentials like CVS or SVN and you want to use the SCM Credentials cache, check the "Use SCM Credentials Cache" field.
+  If your SCM store credentials like CVS or SVN and you want to use the SCM Credentials cache, check the <<Use SCM Credentials Cache>> field.
 
-  You can define the group you want to use or "Defined by POM." In this case project.name will be used as the Project Group.
-  
-  You can choose a Build Definition Template which will be applied to your project.
+  You can define the group you want to use or <<Defined by POM>>. In this case <<<project.name>>> will be used as the <<Project Group>>.
+
+  You cannot add a duplicate project (duplicates would mean another instance of a project with the same groupId, artifactId, and version) in the same <<Project Group>>.
+
+  You can choose a <<Build Definition Template>> which will be applied to your project.
 
 * {ANT Project}
 
-  From the menu, choose the 'Ant Project' entry
-    
-[../../images/add-ant-project-menu.png] Add a Ant project
+  From the menu, choose the <<Ant Project>> entry
+
+[../../images/add-ant-project-menu.png] Add an Ant project
 
     TO WRITE
 
-[../../images/add-ant-project.png] Add a Ant project
+[../../images/add-ant-project.png] Add an Ant project
 
 * {Shell Project}
 
-  From the menu, choose the 'Shell Project' entry
-    
+  From the menu, choose the <<Shell Project>> entry
+
 [../../images/add-shell-project-menu.png] Add a shell project
 
     TO WRITE
@@ -81,11 +223,11 @@
 
 * {Add a project from the Project Group}
 
-    From the Project Group, you can add a project without using the menu. With this operation, the Project Group will be set to the current group.
+    From the <<Project Group>>, you can add a project without using the menu. With this operation, the <<Project Group>> will be set to the current group.
 
 [../../images/add-project-from-group.png] Add a project from a project group
 
-* {Scm hints}
+* {SCM hints}
 
 ** {ClearCase}
 
@@ -109,4 +251,4 @@
 +----------------------------+
 
     This configuration won't work with each ClearCase installation because each ClearCase configuration is different, so we recommend reading the
-    {{{http://maven.apache.org/scm/clearcase.html}ClearCase page}} on the Maven-SCM site.
+    {{{http://maven.apache.org/scm/clearcase.html}ClearCase page}} on the Maven SCM site.
diff --git a/continuum-docs/src/site/apt/user_guides/managing_project/editProject.apt b/continuum-docs/src/site/apt/user_guides/managing_project/editProject.apt
index 4aa1a5d..129c2b1 100644
--- a/continuum-docs/src/site/apt/user_guides/managing_project/editProject.apt
+++ b/continuum-docs/src/site/apt/user_guides/managing_project/editProject.apt
@@ -7,20 +7,37 @@
  Oct 3 2007
  ------
 
+~~ 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.
+
 Edit a Project
 
 ~~%{toc|section=0}
 
 * {Project View}
 
-  When you edit a project from the Group Summary page, you will see basic information.
+  When you edit a project from the <<Group Summary>> page, you will see basic information.
   The first part of the page contains information regarding:
 
   * project name
 
-  * project version 
+  * project version
 
-  * project scm url
+  * project SCM URL
 
   * project Last Build Date
 
@@ -30,16 +47,16 @@
 
 [../../images/project-view-top.png] Project View Top
 
-  With the <<<'Edit'>>> button, you can change some project informations like the scm url if your project was moved.
-  With the <<<'Build Now'>>> button, you build the project manually with the default build definition.
+  With the <<Edit>> button, you can change some project information like the SCM URL if your project was moved.
+  With the <<Build Now>> button, you build the project manually with the default build definition.
 
-  Second part contains information regarding:
+  The second part contains information regarding:
 
   * project notifiers
 
   * project dependencies
 
-  * project developpers
+  * project developers
 
   []
 
@@ -47,9 +64,9 @@
 
 * {Build Results}
 
-  You can view all project's Build Results with the link Builds 
-  You will see all build results summary : start/end Time, result.
-  It's possible to delete some build results with checkboxes
+  You can view all project's <<Build Results>> with the link <<Builds>>.
+  You will see all build results summary: start/end time, result.
+  It's possible to delete some build results with checkboxes.
 
 [../../images/build-results.png] Build Results
 
@@ -57,11 +74,11 @@
 
 * {Build Result}
 
-  Editing a build result will display :
+  Editing a build result will display:
 
-  * scm changes (author and file path)
+  * SCM changes (author and file path)
 
-  * project dependencies (project recorded in this continuum instance)
+  * project dependencies (project recorded in this Continuum instance)
 
   * detail of the build definition used
 
@@ -70,7 +87,3 @@
   []
 
 [../../images/build-result.png] Build Result
-
-
-
-
diff --git a/continuum-docs/src/site/apt/user_guides/managing_project/index.apt b/continuum-docs/src/site/apt/user_guides/managing_project/index.apt
index 70177f8..3417880 100644
--- a/continuum-docs/src/site/apt/user_guides/managing_project/index.apt
+++ b/continuum-docs/src/site/apt/user_guides/managing_project/index.apt
@@ -3,13 +3,32 @@
  ------
  Emmanuel Venisse
  ------
- Nov 15 2007
+ 2010-02-18
  ------
 
+~~ 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.
+
 Managing Projects
 
-    * {{{addProject.html}How to add a project}}
+    * {{{./addProject.html}How to add a project}}
 
-    * {{{editProject.html}How to edit a project}}
+    * {{{./editProject.html}How to edit a project}}
 
-    * {{{removeProject.html}How to remove a project}}
+    * {{{./removeProject.html}How to remove a project}}
+
+    * {{{./workingCopy.html}Viewing the project's working copy}}
diff --git a/continuum-docs/src/site/apt/user_guides/managing_project/removeProject.apt b/continuum-docs/src/site/apt/user_guides/managing_project/removeProject.apt
index c62cc69..f4288d9 100644
--- a/continuum-docs/src/site/apt/user_guides/managing_project/removeProject.apt
+++ b/continuum-docs/src/site/apt/user_guides/managing_project/removeProject.apt
@@ -6,10 +6,27 @@
  Nov 15 2007
  ------
 
+~~ 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.
+
 Remove a Project
 
-    To remove a project, go to the Project Group Summary and click the <<delete>> icon.
+    To remove a project, go to the <<Project Group Summary>> and click the <<delete>> icon.
 
 [../../images/delete.gif] Delete icon
 
-    You can also use the <<<'Delete group'>>> button in the Project Group Summary to remove the whole project group.
+    You can also use the <<Delete group>> button in the <<Project Group Summary>> to remove the whole project group.
diff --git a/continuum-docs/src/site/apt/user_guides/managing_project/workingCopy.apt b/continuum-docs/src/site/apt/user_guides/managing_project/workingCopy.apt
new file mode 100644
index 0000000..6ee2c50
--- /dev/null
+++ b/continuum-docs/src/site/apt/user_guides/managing_project/workingCopy.apt
@@ -0,0 +1,34 @@
+ ------
+ Project Working Copy
+ ------
+ Jevica Arianne B. Zurbano
+ ------
+ Feb 01, 2010
+ ------
+
+~~ 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.
+
+Project Working Copy
+
+    The <<Working Copy>> tab displays the working copy used for the project.
+    
+    The source files can be viewed by clicking the filename and can be downloaded as text using the <<Download as Text>> link.
+    
+    <<Note>>: The file is automatically loaded as an attachment for download when it exceeds 100KB in size.
+
+[../../images/workingCopy.png] Working Copy
diff --git a/continuum-docs/src/site/apt/user_guides/notification/index.apt b/continuum-docs/src/site/apt/user_guides/notification/index.apt
index c8ce119..ecf79d1 100644
--- a/continuum-docs/src/site/apt/user_guides/notification/index.apt
+++ b/continuum-docs/src/site/apt/user_guides/notification/index.apt
@@ -3,15 +3,32 @@
  ------
  Emmanuel Venisse
  ------
- Oct 3 2007
+ 2010-02-18
  ------
 
+~~ 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.
+
 Managing Notification
 
-  Notifiers can be attached to a Maven project by adding them to the pom in the {{{http://maven.apache.org/pom.html#Continuous_Integration_Management}ciManagement section}}.
-  
+  Notifiers can be attached to a Maven project by adding them to the POM in the {{{http://maven.apache.org/pom.html#Continuous_Integration_Management}ciManagement section}}.
+
 +-------------------------------+
-  
+
   <ciManagement>
     <system>continuum</system>
     <url>http://127.0.0.1:8080/continuum</url>
@@ -27,32 +44,32 @@
         </configuration>
       </notifier>
     </notifiers>
-  </ciManagement>  
-  
-+-------------------------------+  
+  </ciManagement>
 
-  Or they can be added to a Project Group with the Notifiers link:
-  
-[../../images/notifiers-link-project-group.png] Notifiers Link  
-  
-  Or to a project with the Add button on the Edit Project page:
-  
-[../../images/notifiers-button-project.png] Notifier Button 
++-------------------------------+
 
-  Here you select between Notifier implementations provided with Continuum:
+  Or they can be added to a <<Project Group>> with the <<Notifiers>> link:
+
+[../../images/notifiers-link-project-group.png] Notifiers Link
+
+  Or added to a project with the <<Add>> button on the <<Edit Project>> page:
+
+[../../images/notifiers-button-project.png] Notifier Button
+
+  Here you select between the Notifier implementations provided with Continuum:
 
 [../../images/notifiers-type-choice.png] Notifier Type Choice
 
   You have the following choices:
-  
-  * {{{mail.html}Mail}}
-  
-  * {{{irc.html}IRC}}
-  
-  * {{{jabber.html}Jabber}}
-  
-  * {{{msn.html}MSN}}
-  
-  * {{{wagon.html}Wagon}}
-    
-   
+
+  * {{{./mail.html}Mail}}
+
+  * {{{./irc.html}IRC}}
+
+  * {{{./jabber.html}Jabber}}
+
+  * {{{./msn.html}MSN}}
+
+  * {{{./wagon.html}Wagon}}
+
+
diff --git a/continuum-docs/src/site/apt/user_guides/notification/irc.apt b/continuum-docs/src/site/apt/user_guides/notification/irc.apt
index 794a280..595fa99 100755
--- a/continuum-docs/src/site/apt/user_guides/notification/irc.apt
+++ b/continuum-docs/src/site/apt/user_guides/notification/irc.apt
@@ -1,11 +1,57 @@
  ------
- Irc Notification
+ IRC Notification
  ------
  Olivier Lamy
  ------
  Oct 23 2007
  ------
 
-Notification
+~~ 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.
 
-    To Write
+IRC Notification
+
+  [[1]] Under <<Notifiers>> from the <<Project Information>> page, click <<Add>>.
+
+  [[2]] On the <<Add Notifier>> form select <<IRC>> from the pull-down menu and click <<Submit>>.
+
+  [[3]] On the next page, fill out the form with the following information:
+
+    * IRC Host
+
+    * IRC Port
+
+    * IRC Channel
+
+    * Nick Name
+
+    * Alternate Nick Name
+
+    * User Name
+
+    * Full Name
+
+    * Password which can be left blank if you did not specify one in your IRC account
+
+    []
+
+[../../images/notifier-irc-add.png] Add IRC Notifier
+
+  [[4]] Select the <<Send on ...>> options you want.
+
+  [[5]] Click <<Save>>. The IRC notifier you just added will be listed under <<Notifiers>> on the <<Project
+  Information>> page along with the other notifiers you may have set up prior to this.
diff --git a/continuum-docs/src/site/apt/user_guides/notification/jabber.apt b/continuum-docs/src/site/apt/user_guides/notification/jabber.apt
index dc97461..e46815a 100755
--- a/continuum-docs/src/site/apt/user_guides/notification/jabber.apt
+++ b/continuum-docs/src/site/apt/user_guides/notification/jabber.apt
@@ -6,6 +6,51 @@
  Nov 19 2007
  ------
 
-Notification
+~~ 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.
 
-    To Write
\ No newline at end of file
+Jabber Notification
+
+  [[1]] Under <<Notifiers>> from the <<Project Information>> page, click <<Add>>.
+
+  [[2]] Select <<Jabber>> from the pull-down menu and click Submit.
+
+  [[3]] On the <<Add/Edit Jabber Notifier>> page, fill out the form with the following:
+
+    * Jabber Host
+
+    * Jabber Port is typically 5222
+
+    * Jabber Login
+
+    * Jabber Password
+
+    * Jabber Domain Name is the fully qualified domain name of your Jabber login
+
+    * Jabber Recipient Address
+
+    []
+
+[../../images/notifier-jabber-add.png] Add Jabber Notifier
+
+  The Jabber login and Jabber recipient address must be different. The Jabber
+  recipient must also be added in the contact list of the sender (at least for Google talk).
+
+  [[4]] Select the <<Send on ...>> options you want.
+
+  [[5]] Click <<Save>>. The Jabber notifier you just added will be listed under <<Notifiers>> on the <<Project
+  Information>> page along with the other notifiers you may have set up prior to this.
diff --git a/continuum-docs/src/site/apt/user_guides/notification/mail.apt b/continuum-docs/src/site/apt/user_guides/notification/mail.apt
index c9a1cbc..39c9c77 100755
--- a/continuum-docs/src/site/apt/user_guides/notification/mail.apt
+++ b/continuum-docs/src/site/apt/user_guides/notification/mail.apt
@@ -3,28 +3,61 @@
  ------
  Olivier Lamy
  ------
- Oct 23 2007
+ 2010-03-02
  ------
 
+~~ 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.
+
 Mail Notification
 
-  Email notification will be add automatically from reading pom (you can add as many notifier as you need) :
-    
+  If you are using Maven 2.0+, email notifiers configured in <<<pom.xml>>> will be automatically added, and you may
+  have as many as you need.
+
 +-------------------------------+
-  
+
   <ciManagement>
     <system>continuum</system>
     <notifiers>
       <notifier>
         <configuration>
           <address>email adress</address>
+          <committers>true</committers>
+          <developers>true</developers>
         </configuration>
       </notifier>
     </notifiers>
-  </ciManagement>  
-  
-+-------------------------------+     
+  </ciManagement>
 
-  Or can you can add manually mail notifier to you project group and/or project
-  
-[../../images/notifier-mail-add.png] Add Email Notifier 
++-------------------------------+
+
+  Or can you can manually add mail notifiers at the project group or individual project level.
+
+  On the <<Add Notifier>> form select <<Mail>> from the pull-down menu and click <<Submit>>.
+
+[../../images/notifier-mail-add.png] Add Email Notifier
+
+  You must either provide a single email address, or select to notify the latest committers or project
+  developers.
+
+~~ TODO:  Does notifying an email address in addition to the latest committers also work?
+
+  In addition you may select one or more <<Send on...>> options.
+
+~~ TODO:  What is "Send on Warning"?  We only have three build states:  error, failure, success
+
+  Then, click <<Save>>.
diff --git a/continuum-docs/src/site/apt/user_guides/notification/msn.apt b/continuum-docs/src/site/apt/user_guides/notification/msn.apt
index dc97461..2e177ec 100755
--- a/continuum-docs/src/site/apt/user_guides/notification/msn.apt
+++ b/continuum-docs/src/site/apt/user_guides/notification/msn.apt
@@ -6,6 +6,42 @@
  Nov 19 2007
  ------
 
-Notification
+~~ 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.
 
-    To Write
\ No newline at end of file
+MSN Notification
+
+  [[1]] Under <<Notifiers>> from the <<Project Information>> page, click <<Add>>.
+
+  [[2]] On the <<Add Notifier>> form select <<MSN>> from the pull-down menu and click <<Submit>>.
+
+  [[3]] On the next page, fill out the form with the following:
+
+    * MSN Login
+
+    * MSN Password
+
+    * MSN Recipient Address
+
+    []
+
+[../../images/notifier-msn-add.png] Add MSN Notifier
+
+  [[4]] Select the <<Send on ...>> options you want.
+
+  [[5]] Click <<Save>>. The MSN notifier you just added will be listed under <<Notifiers>> on the <<Project
+  Information>> page along with the other notifiers you may have set up prior to this.
diff --git a/continuum-docs/src/site/apt/user_guides/notification/wagon.apt b/continuum-docs/src/site/apt/user_guides/notification/wagon.apt
index dc97461..5a12388 100755
--- a/continuum-docs/src/site/apt/user_guides/notification/wagon.apt
+++ b/continuum-docs/src/site/apt/user_guides/notification/wagon.apt
@@ -1,11 +1,69 @@
  ------
- Jabber Notification
+ Wagon Notification
  ------
  Olivier Lamy
  ------
  Nov 19 2007
  ------
 
-Notification
+~~ 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.
 
-    To Write
\ No newline at end of file
+Wagon Notification
+
+  [[1]] Under <<Notifiers>> from the <<Project Information>> page, click <<Add>>.
+
+  [[2]] On the <<Add Notifier>> form select <<Wagon>> from the pull-down menu and click <<Submit>>.
+
+  [[3]] On the next page, enter the Project Site URL.
+
+  It must be a Wagon URL like the URL used in <<<distributionManagement>>>. For the Webdav protocol,
+  you can use <<<dav:[http_url]>>>, or <<<file:///path_to_the_directory>>> if you want to copy it locally
+  with the file protocol.
+
+  [[4]] Enter the ServerId. This should match the value of the <<<\<id\>>>> in the server configuration found in
+  <<<settings.xml>>>. Sample configuration follows:
+
++------+
+  <server>
+    <username>admin</username>
+    <password>admin123</password>
+    <id>continuum.site</id>
+  </server>
++------+
+
+  Using the server configuration in <<<[user_home]/.m2/settings.xml>>> is a workaround
+  for user authentication using the Wagon notifier.
+
+  The <<<\<username\>>>> and <<<\<password\>>>> should be set to the user account that has the <<Site
+  Producer>> and <<Site Observer>> roles.
+
+[../../images/notifier-wagon-add.png] Add Wagon Notifier
+
+  [[5]] Select the <<Send on ...>> options you want.
+
+  [[6]] Click <<Save>>. The Wagon notifier you just added will be listed under <<Notifiers>> on the <<Project
+  Information>> page along with the other notifiers you may have set up prior to this.
+
+  []
+
+  The file protocol will create a <<<buildresult.txt>>> file locally in the location specified in the
+  Wagon Notifier configuration. If you use the Webdav protocol, a <<<buildresult.txt>>> file will
+  be copied to your disk, relative to where you told it to be placed when you set up the Wagon
+  notifier.
+
+  You can also view the <<<buildresult.txt>>> file from a browser at the Project Site URL you specified.
diff --git a/continuum-docs/src/site/apt/user_guides/release/index.apt b/continuum-docs/src/site/apt/user_guides/release/index.apt
index 55daf97..b3c4e5f 100644
--- a/continuum-docs/src/site/apt/user_guides/release/index.apt
+++ b/continuum-docs/src/site/apt/user_guides/release/index.apt
@@ -1,8 +1,101 @@
  ------
  Releasing Projects
  ------
+ ------
+ 2010-02-18
+ ------
+
+~~ 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.
 
 Releasing Projects
 
- The release process has two steps, {{{prepare.html}Prepare}} and {{{perform.html}Perform}}.
+    The release process has two steps, {{{./prepare.html}Prepare}} and {{{./perform.html}Perform}}.
+
+    [[1]] First, it prepares your project for release by doing the following:
+
+        * Checks that your project is in a "releasable" state.
+
+        * Updates the POMs for the new development version.
+
+        * Runs a test build.
+
+        * Generates a tag for the release.
+
+        * Generates the artifact to be deployed, such as a JAR file.
+
+        * Generates the site and deploys it.
+
+        * Commits the new POMs with the new development version. It will do the commit to the SCM
+        connection URL you specify (explained later).
+
+        []
+
+    [[2]] Then the release management system performs the release by checking out a clean copy
+    of the tagged release and deploying the artifacts and site.
+
+    []
+
+* Modifying POM for Release
+
+    The source code control system you use must be specified in your POM file in an <<<\<scm\>>>> entry
+    similar to the one shown here:
+
++----------------------------------------------------------------------------------+
+        <scm>
+          <connection>
+            scm:svn:http://svn.apache.org/repos/asf/maven/components/trunk
+          </connection>
+          <developerConnection>
+            scm:svn:https://svn.apache.org/repos/asf/maven/components/trunk
+          </developerConnection>
+          <url>http://svn.apache.org/viewcvs.cgi/maven/components/trunk</url>
+        </scm>
++---------------------------------------------------------------------------------+
+
+    To determine what to enter for your connection URL (the <<<\<connection\>>>> tag) go to the link
+    {{http://maven.apache.org/scm/scms-overview.html}} for a list of supported SCMs and click on your
+    source code control system to see the appropriate syntax for your particular software.
+
+    In general the format for an SCM URL is:
+    <<< scm:<scm_provider><delimiter><provider_specific_part> >>>
+
+    In the example above, the <<<scm_provider>>> is <<<svn>>> (Subversion). The <<<delimiter>>> is a colon.
+    And the rest of the line is the <<<provider_specific_part>>>.
+
+    It is important to prepare the release just before performing the release. The reason these
+    processes have been separated into two steps is to allow the user to confirm that everything has been
+    set correctly before the actual release. If between the prepare and performing of the release there is
+    a change to the SCM tree, an error will occur causing the prepare process to restart.
+
+    []
+
+
+* Releasing Projects with Flat Structure
+
+    In order to release projects with flat structure in Continuum, the project must be checked out in a single directory.
+    You can do this by checking the "Checkout multi-module project in single directory" field when you add your Maven Two
+    project in Continuum. See {{{../managing_project/addProject.html}Add a Project}} for more details.
+
+    Projects with flat structures are released in the same process described above.
+
+* Releasing projects in a distributed build
+
+    Release will happen in the Build Agent where the last build of project occurred.
+
+    To view on-going releases from different build agents, click the <<Releases>> button under the <<Distributed Builds>> menu.
 
diff --git a/continuum-docs/src/site/apt/user_guides/release/perform.apt b/continuum-docs/src/site/apt/user_guides/release/perform.apt
index e68f0f8..590a1f0 100644
--- a/continuum-docs/src/site/apt/user_guides/release/perform.apt
+++ b/continuum-docs/src/site/apt/user_guides/release/perform.apt
@@ -1,17 +1,44 @@
  ------
  Perform Release
  ------
+ ------
+ 2010-02-19
+ ------
+
+~~ 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.
 
 Perform Release
 
- Choose "Perform Release" and the version number
+ Choose <<Perform Release>> and the version number
 
 [../../images/release-choose-perform-goal.png]
 
- Fill in the form and click Submit
+ Fill in the form and click <<Submit>>
+
+ To specify a different Maven goal to execute during the release, fill in the <<Perform Goals>> field with another goal.
+ By default, the goal for this field is <<<clean deploy>>>.
+
+ To specify additional arguments during execution, fill in the <<Arguments>> field.
 
 [../../images/release-perform-parameters.png]
 
- Wait for the process to complete, then click Done.
+ Wait for the process to complete, then click <<Done>>.
 
 [../../images/release-perform-executing.png]
+
+ To view the release perform results, refer to {{{./release_results.html}Release Results Management}}.
diff --git a/continuum-docs/src/site/apt/user_guides/release/prepare.apt b/continuum-docs/src/site/apt/user_guides/release/prepare.apt
index a80de90..d2c5883 100644
--- a/continuum-docs/src/site/apt/user_guides/release/prepare.apt
+++ b/continuum-docs/src/site/apt/user_guides/release/prepare.apt
@@ -1,25 +1,67 @@
  ------
  Preparing for Release
  ------
+ ------
+ 2010-02-19
+ ------
+
+~~ 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.
 
 Prepare for Release
 
- Navigate to the Project Group Summary and click the Release button or icon.
+ Navigate to the <<Project Group Summary>> and click the <<Release>> button or icon.
 
 [../../images/release-project-group-summary.png] Release
 
- Choose "Prepare project for release" and click "Submit"
+ Choose <<Prepare project for release>> and click <<Submit>>.
 
 [../../images/release-choose-prepare-goal.png] Release
 
- Complete the form, providing the scm tag name, etc.
+ Complete the form, providing the SCM tag name, etc.
+
+ Check the <<Use edit mode>> checkbox if you are using an SCM system that requires you to obtain a lock before editing.
+
+ Click <<Submit>>.
+ 
+ When releasing in a {{{../../administrator_guides/distributed-builds.html} distributed builds}} setup, a <<Build environment>>
+ should be selected containing at least one enabled build agent. If none is selected, then Continuum will attempt to use
+ a default agent, starting with the one last used to build the project.
+
+ Furthermore, the release will not happen in the following cases:
+ 
+   * no build agent found in the build agent group attached to the build environment
+   
+   * all build agents configured in the selected build environment are disabled
+ 
+ []
 
 [../../images/release-prepare-parameters.png] Release Prepare parameters
 
- Wait for the process to complete, then click Done.
+ Wait for the process to complete, then click <<Done>>.
+
+ <<Note:>> Hitting the <<Rollback>> button does not roll back or delete the SCM tag created during the <<<scm-tag>>> phase.
+ So when re-doing the release prepare of the same version, make sure that the tag does not exist in SVN, if so,
+ the tag should be manually deleted.
 
 [../../images/release-prepare-executing.png]
 
- You will be returned to this page to make another selection
+ You will be returned to this page to make another selection.
 
 [../../images/release-choose-perform-goal.png]
+
+ To view the release prepare results, refer to {{{./release_results.html}Release Results Management}}.
diff --git a/continuum-docs/src/site/apt/user_guides/release/release_results.apt b/continuum-docs/src/site/apt/user_guides/release/release_results.apt
new file mode 100644
index 0000000..558752d
--- /dev/null
+++ b/continuum-docs/src/site/apt/user_guides/release/release_results.apt
@@ -0,0 +1,40 @@
+ ------
+ Release Results Management
+ ------
+ ------
+ Feb 23 2009
+ ------
+
+~~ 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.
+
+Release Results Management
+
+    The <<Release Results>> tab from the <<Project Information>> page displays all the release results of a
+    project when executing the release goals prepare and perform.
+
+~~TODO What does the last part of the above mean?
+
+[../../images/release_result-1.png] Release Results page
+
+    To view the release result, click the <<View Result>> link in-line with the release goal being executed.
+    
+    The <<Triggered by>> field displays the username of the person who initiated the release.
+
+[../../images/release_result-2.png] Release Summary
+
+    To delete release results, select the boxes beside the project name then click <<Delete>>.
diff --git a/continuum-docs/src/site/apt/user_guides/report/index.apt b/continuum-docs/src/site/apt/user_guides/report/index.apt
new file mode 100644
index 0000000..7e5e706
--- /dev/null
+++ b/continuum-docs/src/site/apt/user_guides/report/index.apt
@@ -0,0 +1,59 @@
+ ------
+ Project Builds Report
+ ------
+ Jevica Arianne B. Zurbano
+ ------
+ 03 June 2010
+ ------
+
+~~ 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.
+
+Project Builds Report
+
+  Project Builds Report page displays project builds and its information provided with search criteria.
+  
+[../../images/projectBuildsReport.png] Builds Report Page
+  
+  Searching using the default values of the fields will display all the project builds.
+  
+  Search Criteria:
+  
+  * <<Project Group>> - selected from the list of existing project groups.
+    Default value is <<<ALL>>>.
+  
+  * <<Date>> of the build (the start and/or end dates of the build)
+  
+  * <<Build Status>> - selected from the list which can be <<<ALL>>>, <<<Ok>>>, <<<Failed>>>, or <<<Error>>>.
+    Default value is <<<ALL>>>.
+    
+  * <<Triggered By>> - user or build schedule which triggered the build.
+  
+  * <<Row Count>> - sets the display of the number of build results to be displayed in a result page.
+    Default value is <<<30>>> and the minimum required row count is <<<10>>>.
+  
+  []
+  
+  To generate the report, click the <<View Report>> button.
+  
+  To restore the default values of the fields, click the <<Reset>> button.
+
+* Project Builds Report Sample
+
+  To export the builds report to a CSV file, click the link <<Export to CSV>>
+
+[../../images/projectBuildsReportResults.png] Project Builds Report
diff --git a/continuum-docs/src/site/apt/user_guides/viewing_queues/index.apt b/continuum-docs/src/site/apt/user_guides/viewing_queues/index.apt
index 5a54e46..642f1ad 100644
--- a/continuum-docs/src/site/apt/user_guides/viewing_queues/index.apt
+++ b/continuum-docs/src/site/apt/user_guides/viewing_queues/index.apt
@@ -6,12 +6,29 @@
  June 02 2008
  ------
 
+~~ 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.
+
 Viewing Queues
 
-	Click the <<Queues>> link under the <<Administration>> section
+  Click the <<Queues>> link under the <<Administration>> section.
 
 [../../images/queues.png] Queues
 
-	You can only view the current checkout, current build, checkout queues and build queues. 
- 
-[../../images/queues-view.png] Queues View 
+  You can only view the current checkout, current prepare build, current build, checkout queues, prepare build queues and build queues.
+
+[../../images/queues-view.png] Queues View
diff --git a/continuum-docs/src/site/continuum-site.vm b/continuum-docs/src/site/continuum-site.vm
new file mode 100755
index 0000000..b31c867
--- /dev/null
+++ b/continuum-docs/src/site/continuum-site.vm
@@ -0,0 +1,375 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+#*
+  ~ 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.
+*#
+
+#macro ( link $href $name )
+  #if ( ( $href.toLowerCase().startsWith("http") || $href.toLowerCase().startsWith("https") ) )
+    <a href="$href" class="externalLink">$name</a>
+  #else
+    <a href="$href">$name</a>
+  #end
+#end
+
+#macro ( banner $banner $id )
+  #if ( $banner )
+    #if( $banner.href )
+      <a href="$banner.href" id="$id">
+    #else
+        <span id="$id">
+    #end
+
+    #if( $banner.src )
+        #set ( $src = $banner.src )
+        #if ( ! ( $src.toLowerCase().startsWith("http") || $src.toLowerCase().startsWith("https") ) )
+            #set ( $src = $PathTool.calculateLink( $src, $relativePath ) )
+            #set ( $src = $src.replaceAll( "\\", "/" ) )
+        #end
+        #if ( $banner.alt )
+            #set ( $alt = $banner.alt )
+        #else
+            #set ( $alt = "" )
+        #end
+        <img src="$src" alt="$alt" />
+    #else
+        $banner.name
+    #end
+
+    #if( $banner.href )
+        </a>
+    #else
+        </span>
+    #end
+  #end
+#end
+
+#macro ( links $links )
+  #set ( $counter = 0 )
+  #foreach( $item in $links )
+    #set ( $counter = $counter + 1 )
+    #set ( $currentItemHref = $PathTool.calculateLink( $item.href, $relativePath ) )
+    #set ( $currentItemHref = $currentItemHref.replaceAll( "\\", "/" ) )
+    #link( $currentItemHref $item.name )
+    #if ( $links.size() > $counter )
+      |
+    #end
+  #end
+#end
+
+#macro ( breadcrumbs $breadcrumbs )
+  #set ( $counter = 0 )
+  #foreach( $item in $breadcrumbs )
+    #set ( $counter = $counter + 1 )
+    #set ( $currentItemHref = $PathTool.calculateLink( $item.href, $relativePath ) )
+    #set ( $currentItemHref = $currentItemHref.replaceAll( "\\", "/" ) )
+
+    #if ( $currentItemHref == $alignedFileName || $currentItemHref == "" )
+      $item.name
+    #else
+      #link( $currentItemHref $item.name )
+    #end
+    #if ( $breadcrumbs.size() > $counter )
+      &gt;
+    #end
+  #end
+#end
+
+#macro ( displayTree $display $item )
+  #if ( $item && $item.items && $item.items.size() > 0 )
+    #foreach( $subitem in $item.items )
+      #set ( $subitemHref = $PathTool.calculateLink( $subitem.href, $relativePath ) )
+      #set ( $subitemHref = $subitemHref.replaceAll( "\\", "/" ) )
+
+      #if ( $alignedFileName == $subitemHref )
+        #set ( $display = true )
+      #end
+
+      #displayTree( $display $subitem )
+    #end
+  #end
+#end
+
+#macro ( menuItem $item )
+  #set ( $collapse = "none" )
+  #set ( $currentItemHref = $PathTool.calculateLink( $item.href, $relativePath ) )
+  #set ( $currentItemHref = $currentItemHref.replaceAll( "\\", "/" ) )
+
+  #if ( $item && $item.items && $item.items.size() > 0 )
+    #if ( $item.collapse == false )
+      #set ( $collapse = "expanded" )
+    #else
+      ## By default collapsed
+      #set ( $collapse = "collapsed" )
+    #end
+
+    #set ( $display = false )
+    #displayTree( $display $item )
+
+    #if ( $alignedFileName == $currentItemHref || $display )
+      #set ( $collapse = "expanded" )
+    #end
+  #end
+  <li class="$collapse">
+    #if ( $item.img )
+      #if ( ! ( $item.img.toLowerCase().startsWith("http") || $item.img.toLowerCase().startsWith("https") ) )
+        #set ( $src = $PathTool.calculateLink( $item.img, $relativePath ) )
+        #set ( $src = $src.replaceAll( "\\", "/" ) )
+        <img src="$src"/>
+      #else
+        <img src="$item.img" align="absbottom" style="border-width: 0"/>
+      #end
+    #end
+    #if ( $alignedFileName == $currentItemHref )
+      <strong>$item.name</strong>
+    #else
+      #link( $currentItemHref $item.name )
+    #end
+  #if ( $item && $item.items && $item.items.size() > 0 )
+    #if ( $collapse == "expanded" )
+      <ul>
+        #foreach( $subitem in $item.items )
+          #menuItem( $subitem )
+        #end
+      </ul>
+    #end
+  #end
+  </li>
+#end
+
+#macro ( mainMenu $menus )
+  #foreach( $menu in $menus )
+    #if ( $menu.name )
+    <h5>$menu.name</h5>
+    #end
+    #if ( $menu.items && $menu.items.size() > 0 )
+    <ul>
+      #foreach( $item in $menu.items )
+        #menuItem( $item )
+      #end
+    </ul>
+    #end
+  #end
+#end
+
+#macro ( copyright )
+  #if ( $project )
+    #set ( $currentYear = ${currentDate.year} + 1900 )
+
+    #if ( ${project.inceptionYear} && ( ${project.inceptionYear} != ${currentYear.toString()} ) )
+      ${project.inceptionYear}-${currentYear}
+    #else
+      ${currentYear}
+    #end
+
+    #if ( ${project.organization} && ${project.organization.name} )
+      ${project.organization.name}
+    #end
+  #end
+#end
+
+#macro ( publishDate $position $publishDate $version )
+  #if ( $publishDate && $publishDate.format )
+    #set ( $format = $publishDate.format )
+  #else
+    #set ( $format = "yyyy-MM-dd" )
+  #end
+
+  $dateFormat.applyPattern( $format )
+
+  #set ( $dateToday = $dateFormat.format( $currentDate ) )
+
+  #if ( $publishDate && $publishDate.position )
+    #set ( $datePosition = $publishDate.position )
+  #else
+    #set ( $datePosition = "left" )
+  #end
+
+  #if ( $version )
+    #if ( $version.position )
+      #set ( $versionPosition = $version.position )
+    #else
+      #set ( $versionPosition = "left" )
+    #end
+  #end
+
+  #set ( $breadcrumbs = $decoration.body.breadcrumbs )
+  #set ( $links = $decoration.body.links )
+
+  #if ( $datePosition.equalsIgnoreCase( "right" ) && $links && $links.size() > 0 )
+    #set ( $prefix = "&nbsp;|" )
+  #else
+    #set ( $prefix = "" )
+  #end
+
+  #if ( $datePosition.equalsIgnoreCase( $position ) )
+    #if ( ( $datePosition.equalsIgnoreCase( "right" ) ) || ( $datePosition.equalsIgnoreCase( "bottom" ) ) )
+      $prefix $i18n.getString( "site-renderer", $locale, "template.lastpublished" ): $dateToday
+      #if ( $versionPosition.equalsIgnoreCase( $position ) )
+        &nbsp;| $i18n.getString( "site-renderer", $locale, "template.version" ): ${project.version}
+      #end
+    #elseif ( ( $datePosition.equalsIgnoreCase( "navigation-bottom" ) ) || ( $datePosition.equalsIgnoreCase( "navigation-top" ) ) )
+      <div id="lastPublished">
+        $i18n.getString( "site-renderer", $locale, "template.lastpublished" ): $dateToday
+        #if ( $versionPosition.equalsIgnoreCase( $position ) )
+          &nbsp;| $i18n.getString( "site-renderer", $locale, "template.version" ): ${project.version}
+        #end
+      </div>
+    #elseif ( $datePosition.equalsIgnoreCase("left") )
+      <div class="xleft">
+        $i18n.getString( "site-renderer", $locale, "template.lastpublished" ): $dateToday
+        #if ( $versionPosition.equalsIgnoreCase( $position ) )
+          &nbsp;| $i18n.getString( "site-renderer", $locale, "template.version" ): ${project.version}
+        #end
+        #if ( $breadcrumbs && $breadcrumbs.size() > 0 )
+          | #breadcrumbs( $breadcrumbs )
+        #end
+      </div>
+    #end
+  #elseif ( $versionPosition.equalsIgnoreCase( $position ) )
+    #if ( ( $versionPosition.equalsIgnoreCase( "right" ) ) || ( $versionPosition.equalsIgnoreCase( "bottom" ) ) )
+      $prefix $i18n.getString( "site-renderer", $locale, "template.version" ): ${project.version}
+    #elseif ( ( $versionPosition.equalsIgnoreCase( "navigation-bottom" ) ) || ( $versionPosition.equalsIgnoreCase( "navigation-top" ) ) )
+      <div id="lastPublished">
+        $i18n.getString( "site-renderer", $locale, "template.version" ): ${project.version}
+      </div>
+    #elseif ( $versionPosition.equalsIgnoreCase("left") )
+      <div class="xleft">
+        $i18n.getString( "site-renderer", $locale, "template.version" ): ${project.version}
+        #if ( $breadcrumbs && $breadcrumbs.size() > 0 )
+          | #breadcrumbs( $breadcrumbs )
+        #end
+      </div>
+    #end
+  #elseif ( $position.equalsIgnoreCase( "left" ) )
+    #if ( $breadcrumbs && $breadcrumbs.size() > 0 )
+      <div class="xleft">
+        #breadcrumbs( $breadcrumbs )
+      </div>
+    #end
+  #end
+#end
+
+#macro ( poweredByLogo $poweredBy )
+    #if( $poweredBy )
+        #foreach ($item in $poweredBy)
+            #if( $item.href )
+                #set ( $href = $PathTool.calculateLink( $item.href, $relativePath ) )
+                #set ( $href = $href.replaceAll( "\\", "/" ) )
+            #else
+                #set ( $href="http://maven.apache.org/" )
+            #end
+
+            #if( $item.name )
+                #set ( $name = $item.name )
+            #else
+                #set ( $name = $i18n.getString( "site-renderer", $locale, "template.builtby" )  )
+                #set ( $name = "${name} Maven"  )
+            #end
+
+            #if( $item.img )
+                #set ( $img = $item.img )
+            #else
+                #set ( $img = "images/logos/maven-feather.png" )
+            #end
+
+            <a href="$href" title="$name" class="poweredBy">
+              #set ( $img = $PathTool.calculateLink( $img, $relativePath ) )
+              #set ( $img = $img.replaceAll( "\\", "/" ) )
+              <img alt="$name" src="$img" />
+            </a>
+        #end
+        #if( $poweredBy.isEmpty() )
+          <a href="http://maven.apache.org/" title="$i18n.getString( "site-renderer", $locale, "template.builtby" ) Maven" class="poweredBy">
+            <img alt="$i18n.getString( "site-renderer", $locale, "template.builtby" ) Maven" src="$relativePath/images/logos/maven-feather.png"></img>
+          </a>
+        #end
+    #else
+        <a href="http://maven.apache.org/" title="$i18n.getString( "site-renderer", $locale, "template.builtby" ) Maven" class="poweredBy">
+          <img alt="$i18n.getString( "site-renderer", $locale, "template.builtby" ) Maven" src="$relativePath/images/logos/maven-feather.png"></img>
+        </a>
+    #end
+#end
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>$title</title>
+    <style type="text/css" media="all">
+      @import url("$relativePath/css/maven-base.css");
+      @import url("$relativePath/css/maven-theme.css");
+      @import url("$relativePath/css/site.css");
+    </style>
+    <link rel="stylesheet" href="$relativePath/css/print.css" type="text/css" media="print" />
+    #foreach( $author in $authors )
+      <meta name="author" content="$author" />
+    #end
+    <meta http-equiv="Content-Type" content="text/html; charset=${outputEncoding}" />
+    #if ( $decoration.body.head )
+      #foreach( $item in $decoration.body.head.getChildren() )
+        ## Workaround for DOXIA-150 due to a non-desired behaviour in p-u
+        ## @see org.codehaus.plexus.util.xml.Xpp3Dom#toString()
+        ## @see org.codehaus.plexus.util.xml.Xpp3Dom#toUnescapedString()
+        #set ( $documentHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" )
+        #set ( $documentHeader = $documentHeader.replaceAll( "\\", "" ) )
+        #if ( $item.name == "script" )
+          $StringUtils.replace( $item.toUnescapedString(), $documentHeader, "" )
+        #else
+          $StringUtils.replace( $item.toString(), $documentHeader, "" )
+        #end
+      #end
+    #end
+  </head>
+  <body class="composite">
+    <div id="banner">
+      #banner( $decoration.bannerLeft "bannerLeft" )
+      #banner( $decoration.bannerRight "bannerRight" )
+      <div class="clear">
+        <hr/>
+      </div>
+    </div>
+    <div id="breadcrumbs">
+      #publishDate( "left" $decoration.publishDate $decoration.version )
+      <div class="xright">#links( $decoration.body.links )#publishDate( "right" $decoration.publishDate $decoration.version )</div>
+      <div class="clear">
+        <hr/>
+      </div>
+    </div>
+    <div id="leftColumn">
+      <div id="navcolumn">
+       #publishDate( "navigation-top" $decoration.publishDate $decoration.version )
+       #mainMenu( $decoration.body.menus )
+       #poweredByLogo( $decoration.poweredBy )
+       #publishDate( "navigation-bottom" $decoration.publishDate $decoration.version )
+      </div>
+    </div>
+    <div id="bodyColumn">
+      <div id="contentBox">
+        $bodyContent
+      </div>
+    </div>
+    <div class="clear">
+      <hr/>
+    </div>
+    <div id="footer">
+      <div class="xright">&#169;#copyright()#publishDate( "bottom" $decoration.publishDate $decoration.version ) - <a href="http://continuum.apache.org/privacy-policy.html">Privacy Policy</a></div>
+      <div class="clear">
+        <hr/>
+      </div>
+    </div>
+  </body>
+</html>
diff --git a/continuum-docs/src/site/pdf.xml b/continuum-docs/src/site/pdf.xml
new file mode 100644
index 0000000..0e35e71
--- /dev/null
+++ b/continuum-docs/src/site/pdf.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+  ~ 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.
+  -->
+
+<document outputName="apache-continuum">
+
+  <meta>
+    <title>Apache Continuum ${project.version}</title>
+    <author>The Apache Continuum Project</author>
+  </meta>
+
+  <toc name="Documentation">
+    <item name="Index (category)" ref="index.html"/>
+    <item name="Getting Started" ref="getting-started.html"/>
+
+    <item name="Installation/Upgrade Guides" ref="installation/index.html"/>
+    <item name="Installing Standalone" ref="installation/standalone.html"/>
+    <item name="Installing in Tomcat" ref="installation/tomcat.html"/>
+    <item name="Upgrade" ref="installation/upgrade.html"/>
+    <item name="Installing a Build Agent" ref="installation/build-agent.html"/>
+
+    <item name="User's Guides" ref="user_guides/index.html"/>
+    <item name="Managing Projects" ref="user_guides/managing_project/index.html"/>
+    <item name="Add a Project" ref="user_guides/managing_project/addProject.html"/>
+    <item name="Edit a Project" ref="user_guides/managing_project/editProject.html"/>
+    <item name="Remove a Project" ref="user_guides/managing_project/removeProject.html"/>
+    <item name="Working Copy" ref="user_guides/managing_project/workingCopy.html"/>
+    <item name="Managing Build Definitions" ref="user_guides/managing_builddef/index.html"/>
+    <item name="Managing Notification" ref="user_guides/notification/index.html"/>
+    <item name="Mail Notification" ref="user_guides/notification/mail.html"/>
+    <item name="IRC Notification" ref="user_guides/notification/irc.html"/>
+    <item name="Jabber Notification" ref="user_guides/notification/jabber.html"/>
+    <item name="MSN Notification" ref="user_guides/notification/msn.html"/>
+    <item name="Wagon Notification" ref="user_guides/notification/wagon.html"/>
+    <item name="Building a project" ref="user_guides/building_project/index.html"/>
+    <item name="Scheduled Build" ref="user_guides/building_project/schedule_build.html"/>
+    <item name="Forced Build" ref="user_guides/building_project/forced_build.html"/>
+    <item name="Build Results Management" ref="user_guides/building_project/build_results.html"/>
+    <item name="Cancelling builds" ref="user_guides/building_project/cancelling_build.html"/>
+    <item name="Release Management" ref="user_guides/release/index.html"/>
+    <item name="Prepare Project Release" ref="user_guides/release/prepare.html"/>
+    <item name="Perform Project Release" ref="user_guides/release/perform.html"/>
+    <item name="Release Results Management" ref="user_guides/release/release_results.html"/>
+    <item name="Project Builds Report" ref="user_guides/report/index.html"/>
+
+    <item name="Administrator's Guides" ref="administrator_guides/index.html"/>
+    <item name="Managing Users and Security" ref="administrator_guides/security/index.html"/>
+    <item name="Security Configuration" ref="administrator_guides/security/customising-security.html"/>
+    <item name="LDAP Configuration" ref="administrator_guides/security/ldap.html"/>
+    <item name="Managing Project Groups" ref="administrator_guides/projectgroup.html"/>
+    <item name="Managing Installations" ref="administrator_guides/builder.html"/>
+    <item name="Managing Build Environments" ref="administrator_guides/profiles.html"/>
+    <item name="Managing Schedules" ref="administrator_guides/schedules.html"/>
+    <item name="Managing General Configuration" ref="administrator_guides/configuration.html"/>
+    <item name="Managing Local Repositories" ref="administrator_guides/localRepository.html"/>
+    <item name="Managing Purge Configuration" ref="administrator_guides/purgeConfiguration.html"/>
+    <item name="Managing Parallel Builds" ref="administrator_guides/parallelBuilds.html"/>
+    <item name="Managing Build Queues" ref="administrator_guides/buildQueue.html"/>
+    <item name="Managing Build Agents" ref="administrator_guides/build-agents.html"/>
+    <item name="Managing Build Agent Groups" ref="administrator_guides/build-agent-groups.html"/>
+    <item name="Managing Project Queues" ref="administrator_guides/queues.html"/>
+    <item name="External databases" ref="administrator_guides/external-db.html"/>
+    <item name="Monitoring Continuum" ref="administrator_guides/monitoring.html"/>
+    <item name="Log Files" ref="administrator_guides/logging/index.html"/>
+    <item name="Audit Logs" ref="administrator_guides/logging/audit-logs.html"/>
+    <item name="Continuum Logs" ref="administrator_guides/logging/continuum-logs.html"/>
+    <item name="Security Logs" ref="administrator_guides/logging/security-logs.html"/>
+    <item name="Appearance Configuration" ref="administrator_guides/appearance.html"/>
+    <item name="Build Definition Template" ref="administrator_guides/builddefTemplate.html"/>
+    <item name="Shutdown Continuum" ref="administrator_guides/shutdown.html"/>
+    <item name="Understanding Distributed Builds" ref="administrator_guides/distributed-builds.html"/>
+    <item name="WebDAV for Agent Working Copies" ref="administrator_guides/webdav.html"/>
+    <!-- <item name="Running builds in a chroot jail" ref="administrator_guides/chroot.html"/> -->
+
+    <item name="Developer's Guides" ref="developer_guides/index.html"/>
+    <item name="Building Continuum" ref="developer_guides/building.html"/>
+    <item name="XML-RPC" ref="developer_guides/xmlrpc.html"/>
+
+  </toc>
+
+</document>
diff --git a/continuum-docs/src/site/resources/css/site.css b/continuum-docs/src/site/resources/css/site.css
deleted file mode 100644
index 82c07bd..0000000
--- a/continuum-docs/src/site/resources/css/site.css
+++ /dev/null
@@ -1,8 +0,0 @@
-#banner {
-  background: none;
-}
-
-#banner img {
-  margin: 10px;
-}
-
diff --git a/continuum-docs/src/site/resources/images/add-build-definition.png b/continuum-docs/src/site/resources/images/add-build-definition.png
new file mode 100755
index 0000000..6ef94fc
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/add-build-definition.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/add-installation.png b/continuum-docs/src/site/resources/images/add-installation.png
deleted file mode 100644
index 78821fb..0000000
--- a/continuum-docs/src/site/resources/images/add-installation.png
+++ /dev/null
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/add-jdk.png b/continuum-docs/src/site/resources/images/add-jdk.png
deleted file mode 100644
index d8f6bc1..0000000
--- a/continuum-docs/src/site/resources/images/add-jdk.png
+++ /dev/null
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/add-m2-project-menu.png b/continuum-docs/src/site/resources/images/add-m2-project-menu.png
index 4d9260e..47db6bd 100644
--- a/continuum-docs/src/site/resources/images/add-m2-project-menu.png
+++ b/continuum-docs/src/site/resources/images/add-m2-project-menu.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/add-m2-project.png b/continuum-docs/src/site/resources/images/add-m2-project.png
index ae8a539..fbc831d 100644
--- a/continuum-docs/src/site/resources/images/add-m2-project.png
+++ b/continuum-docs/src/site/resources/images/add-m2-project.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/addBuildQueue.png b/continuum-docs/src/site/resources/images/addBuildQueue.png
new file mode 100644
index 0000000..8b801f4
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/addBuildQueue.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/bg.jpg b/continuum-docs/src/site/resources/images/bg.jpg
deleted file mode 100644
index ea64263..0000000
--- a/continuum-docs/src/site/resources/images/bg.jpg
+++ /dev/null
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/build-agent-edit.png b/continuum-docs/src/site/resources/images/build-agent-edit.png
index ce54ecc..d0dfa74 100644
--- a/continuum-docs/src/site/resources/images/build-agent-edit.png
+++ b/continuum-docs/src/site/resources/images/build-agent-edit.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/build-agent-groups-edit.png b/continuum-docs/src/site/resources/images/build-agent-groups-edit.png
new file mode 100644
index 0000000..802c803
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/build-agent-groups-edit.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/build-agent-groups.png b/continuum-docs/src/site/resources/images/build-agent-groups.png
new file mode 100644
index 0000000..35279e4
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/build-agent-groups.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/build-agents.png b/continuum-docs/src/site/resources/images/build-agents.png
index 21b1b80..559b0d3 100644
--- a/continuum-docs/src/site/resources/images/build-agents.png
+++ b/continuum-docs/src/site/resources/images/build-agents.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/buildDefGroup.png b/continuum-docs/src/site/resources/images/buildDefGroup.png
new file mode 100755
index 0000000..8510af9
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/buildDefGroup.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/buildDefProject.png b/continuum-docs/src/site/resources/images/buildDefProject.png
new file mode 100755
index 0000000..ac189a0
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/buildDefProject.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/buildQueue.png b/continuum-docs/src/site/resources/images/buildQueue.png
new file mode 100644
index 0000000..dad732a
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/buildQueue.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/build_result-1.png b/continuum-docs/src/site/resources/images/build_result-1.png
new file mode 100755
index 0000000..74baa6c
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/build_result-1.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/build_result-2.png b/continuum-docs/src/site/resources/images/build_result-2.png
new file mode 100755
index 0000000..2c328a1
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/build_result-2.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/buildenv-add.png b/continuum-docs/src/site/resources/images/buildenv-add.png
index fdde1b0..355c3f7 100644
--- a/continuum-docs/src/site/resources/images/buildenv-add.png
+++ b/continuum-docs/src/site/resources/images/buildenv-add.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/buildenv-in-builddef.png b/continuum-docs/src/site/resources/images/buildenv-in-builddef.png
index 64e2db5..b7eea70 100644
--- a/continuum-docs/src/site/resources/images/buildenv-in-builddef.png
+++ b/continuum-docs/src/site/resources/images/buildenv-in-builddef.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/buildenv-setup-jdk.png b/continuum-docs/src/site/resources/images/buildenv-setup-jdk.png
index 528580b..338f455 100644
--- a/continuum-docs/src/site/resources/images/buildenv-setup-jdk.png
+++ b/continuum-docs/src/site/resources/images/buildenv-setup-jdk.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/cancel-group-build.png b/continuum-docs/src/site/resources/images/cancel-group-build.png
new file mode 100644
index 0000000..444b029
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/cancel-group-build.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/configuration.png b/continuum-docs/src/site/resources/images/configuration.png
index 67901dd..2ba0195 100644
--- a/continuum-docs/src/site/resources/images/configuration.png
+++ b/continuum-docs/src/site/resources/images/configuration.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/continuum_logo_75.gif b/continuum-docs/src/site/resources/images/continuum_logo_75.gif
deleted file mode 100644
index 7875d40..0000000
--- a/continuum-docs/src/site/resources/images/continuum_logo_75.gif
+++ /dev/null
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/editSchedule.png b/continuum-docs/src/site/resources/images/editSchedule.png
new file mode 100644
index 0000000..15fe8dd
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/editSchedule.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/force_build.png b/continuum-docs/src/site/resources/images/force_build.png
new file mode 100755
index 0000000..83fe6b3
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/force_build.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/inqueue.gif b/continuum-docs/src/site/resources/images/inqueue.gif
new file mode 100644
index 0000000..e9907fb
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/inqueue.gif
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/installation-envvar-edit.png b/continuum-docs/src/site/resources/images/installation-envvar-edit.png
new file mode 100755
index 0000000..6fe1bfb
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/installation-envvar-edit.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/installation-tool-edit.png b/continuum-docs/src/site/resources/images/installation-tool-edit.png
index b413f01..8fba006 100644
--- a/continuum-docs/src/site/resources/images/installation-tool-edit.png
+++ b/continuum-docs/src/site/resources/images/installation-tool-edit.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/installation-type-choice-envvar.png b/continuum-docs/src/site/resources/images/installation-type-choice-envvar.png
new file mode 100755
index 0000000..808c6a2
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/installation-type-choice-envvar.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/installation-type-choice.png b/continuum-docs/src/site/resources/images/installation-type-choice.png
index 7730a9c..b334b9c 100644
--- a/continuum-docs/src/site/resources/images/installation-type-choice.png
+++ b/continuum-docs/src/site/resources/images/installation-type-choice.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/installation-validation-failed.png b/continuum-docs/src/site/resources/images/installation-validation-failed.png
index c879801..a9269a9 100644
--- a/continuum-docs/src/site/resources/images/installation-validation-failed.png
+++ b/continuum-docs/src/site/resources/images/installation-validation-failed.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/jdk-validation-failed.png b/continuum-docs/src/site/resources/images/jdk-validation-failed.png
deleted file mode 100644
index d1027ff..0000000
--- a/continuum-docs/src/site/resources/images/jdk-validation-failed.png
+++ /dev/null
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/listBuildQueue.png b/continuum-docs/src/site/resources/images/listBuildQueue.png
new file mode 100644
index 0000000..36fc866
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/listBuildQueue.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/logo_apache.jpg b/continuum-docs/src/site/resources/images/logo_apache.jpg
deleted file mode 100644
index 6c096ec..0000000
--- a/continuum-docs/src/site/resources/images/logo_apache.jpg
+++ /dev/null
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/logo_maven.jpg b/continuum-docs/src/site/resources/images/logo_maven.jpg
deleted file mode 100644
index 3264271..0000000
--- a/continuum-docs/src/site/resources/images/logo_maven.jpg
+++ /dev/null
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/logos/maven-feather.png b/continuum-docs/src/site/resources/images/logos/maven-feather.png
new file mode 100644
index 0000000..b5ada83
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/logos/maven-feather.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/maven-logo-2.gif b/continuum-docs/src/site/resources/images/maven-logo-2.gif
deleted file mode 100644
index 3264271..0000000
--- a/continuum-docs/src/site/resources/images/maven-logo-2.gif
+++ /dev/null
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/notifier-irc-add.png b/continuum-docs/src/site/resources/images/notifier-irc-add.png
new file mode 100755
index 0000000..53a95ac
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/notifier-irc-add.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/notifier-jabber-add.png b/continuum-docs/src/site/resources/images/notifier-jabber-add.png
new file mode 100755
index 0000000..0229d68
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/notifier-jabber-add.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/notifier-mail-add.png b/continuum-docs/src/site/resources/images/notifier-mail-add.png
index 39061c7..31bee16 100755
--- a/continuum-docs/src/site/resources/images/notifier-mail-add.png
+++ b/continuum-docs/src/site/resources/images/notifier-mail-add.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/notifier-msn-add.png b/continuum-docs/src/site/resources/images/notifier-msn-add.png
new file mode 100755
index 0000000..6d4edf0
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/notifier-msn-add.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/notifier-wagon-add.png b/continuum-docs/src/site/resources/images/notifier-wagon-add.png
new file mode 100755
index 0000000..829450c
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/notifier-wagon-add.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/parallelBuildsQueues.png b/continuum-docs/src/site/resources/images/parallelBuildsQueues.png
new file mode 100644
index 0000000..11b58cd
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/parallelBuildsQueues.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/profile-build-agent-group.png b/continuum-docs/src/site/resources/images/profile-build-agent-group.png
new file mode 100644
index 0000000..7a983a5
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/profile-build-agent-group.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/project-group-summary.png b/continuum-docs/src/site/resources/images/project-group-summary.png
new file mode 100644
index 0000000..c8ef3dc
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/project-group-summary.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/project-groups.png b/continuum-docs/src/site/resources/images/project-groups.png
new file mode 100644
index 0000000..926268e
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/project-groups.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/projectBuildsReport.png b/continuum-docs/src/site/resources/images/projectBuildsReport.png
new file mode 100644
index 0000000..11079d1
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/projectBuildsReport.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/projectBuildsReportResults.png b/continuum-docs/src/site/resources/images/projectBuildsReportResults.png
new file mode 100644
index 0000000..369ce28
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/projectBuildsReportResults.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/queues-checkout.png b/continuum-docs/src/site/resources/images/queues-checkout.png
new file mode 100644
index 0000000..02a15be
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/queues-checkout.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/queues-prepare.png b/continuum-docs/src/site/resources/images/queues-prepare.png
new file mode 100644
index 0000000..6ed7334
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/queues-prepare.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/release-perform-parameters.png b/continuum-docs/src/site/resources/images/release-perform-parameters.png
index 6030e01..397c127 100644
--- a/continuum-docs/src/site/resources/images/release-perform-parameters.png
+++ b/continuum-docs/src/site/resources/images/release-perform-parameters.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/release-prepare-parameters.png b/continuum-docs/src/site/resources/images/release-prepare-parameters.png
index fecb263..94cc25c 100644
--- a/continuum-docs/src/site/resources/images/release-prepare-parameters.png
+++ b/continuum-docs/src/site/resources/images/release-prepare-parameters.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/release_result-1.png b/continuum-docs/src/site/resources/images/release_result-1.png
new file mode 100755
index 0000000..17d4d95
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/release_result-1.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/release_result-2.png b/continuum-docs/src/site/resources/images/release_result-2.png
new file mode 100755
index 0000000..c8afa14
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/release_result-2.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/schedule_build.png b/continuum-docs/src/site/resources/images/schedule_build.png
new file mode 100755
index 0000000..5285091
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/schedule_build.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/schedules.png b/continuum-docs/src/site/resources/images/schedules.png
new file mode 100755
index 0000000..b87d99e
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/schedules.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/update-project-group.png b/continuum-docs/src/site/resources/images/update-project-group.png
new file mode 100644
index 0000000..0c411f6
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/update-project-group.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/images/workingCopy.png b/continuum-docs/src/site/resources/images/workingCopy.png
new file mode 100644
index 0000000..c9a5bba
--- /dev/null
+++ b/continuum-docs/src/site/resources/images/workingCopy.png
Binary files differ
diff --git a/continuum-docs/src/site/resources/pdf-config.xml b/continuum-docs/src/site/resources/pdf-config.xml
new file mode 100644
index 0000000..3a8e202
--- /dev/null
+++ b/continuum-docs/src/site/resources/pdf-config.xml
@@ -0,0 +1,30 @@
+<!--
+  ~ 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.
+  -->
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version="1.0">
+
+  <xsl:attribute-set name="figure.graphics">
+    <xsl:attribute name="height">100%</xsl:attribute>
+    <xsl:attribute name="width">100%</xsl:attribute>
+    <xsl:attribute name="content-height">scale-down-to-fit</xsl:attribute>
+    <xsl:attribute name="content-width">scale-down-to-fit</xsl:attribute>
+  </xsl:attribute-set>
+
+</xsl:stylesheet>
diff --git a/continuum-docs/src/site/site.xml b/continuum-docs/src/site/site.xml
index 639c5f2..49ddcad 100644
--- a/continuum-docs/src/site/site.xml
+++ b/continuum-docs/src/site/site.xml
@@ -21,76 +21,89 @@
 <project name="Apache Continuum">
   <body>
     <breadcrumbs>
-      <item name="1.3.0" href="/" />
+      <item name="Continuum" href="http://continuum.apache.org/" />
+      <item name="${project.version}" href="/"/>
     </breadcrumbs>
+
     <menu name="Documentation">
       <item name="Index (category)" href="index.html"/>
       <item name="Getting Started" href="getting-started.html"/>
+
       <item name="Installation/Upgrade Guides" href="installation/index.html" collapse="true">
-        <item name="System Requirements" href="installation/requirements.html"/>
-        <item name="Installation" href="installation/installation.html" collapse="true">
-          <item name="Standalone" href="installation/standalone.html"/>
-          <item name="Tomcat" href="installation/tomcat.html"/>
-          <item name="JBoss" href="installation/jboss.html"/>
-          <item name="Jetty" href="installation/jetty.html"/>
-          <item name="Geronimo" href="installation/geronimo.html"/>
-          <item name="Glassfish" href="installation/glassfish.html"/>
-        </item>
-        <item name="Release Notes" href="installation/release-notes.html"/>
+        <item name="Installing Standalone" href="installation/standalone.html"/>
+        <item name="Installing in Tomcat" href="installation/tomcat.html"/>
+        <item name="Release Notes" href="release-notes.html"/>
         <item name="Upgrade" href="installation/upgrade.html"/>
+        <item name="Installing a Build Agent" href="installation/build-agent.html"/>
       </item>
+
       <item name="User's Guides" collapse="true" href="user_guides/index.html">
-        <item name="Getting Started" href="getting-started.html"/>
         <item name="Managing Projects" href="user_guides/managing_project/index.html" collapse="true">
           <item name="Add a Project" href="user_guides/managing_project/addProject.html"/>
           <item name="Edit a Project" href="user_guides/managing_project/editProject.html"/>
           <item name="Remove a Project" href="user_guides/managing_project/removeProject.html"/>
-          <!-- item name="SCM security hints"/ -->
+          <item name="Working Copy" href="user_guides/managing_project/workingCopy.html"/>
         </item>
-        <item name="Managing Build Definitions" href="user_guides/managing_builddef/index.html" collapse="true">
-          <item name="Project Build Definition" href="user_guides/managing_builddef/builddefProject.html"/>
-          <item name="Project Group Build Definition" href="user_guides/managing_builddef/builddefGroup.html"/>
-        </item>
+        <item name="Managing Build Definitions" href="user_guides/managing_builddef/index.html"/>
         <item name="Managing Notification" href="user_guides/notification/index.html" collapse="true">
           <item name="Mail Notification" href="user_guides/notification/mail.html"/>
           <item name="IRC Notification" href="user_guides/notification/irc.html"/>
-          <item name="Jabber Notification" href="user_guides/notification/jabber.html">
-            <item name="Google Talk Notification" href="user_guides/notification/jabber.html#GTalk"/>
-          </item>
+          <item name="Jabber Notification" href="user_guides/notification/jabber.html"/>
           <item name="MSN Notification" href="user_guides/notification/msn.html"/>
           <item name="Wagon Notification" href="user_guides/notification/wagon.html"/>
         </item>
         <item name="Building a project" href="user_guides/building_project/index.html" collapse="true">
-          <item name="Scheduled Build" href="user_guides/building_project/index.html#Scheduled Build"/>
-          <item name="Forced Build" href="user_guides/building_project/index.html#Forced Build"/>
+          <item name="Scheduled Build" href="user_guides/building_project/schedule_build.html"/>
+          <item name="Forced Build" href="user_guides/building_project/forced_build.html"/>
+          <item name="Build Results Management" href="user_guides/building_project/build_results.html"/>
+          <item name="Cancelling builds" href="user_guides/building_project/cancelling_build.html"/>
         </item>
-        <item name="Release Management" href="user_guides/release/index.html"/>
+        <item name="Release Management" href="user_guides/release/index.html" collapse="true">
+          <item name="Prepare Project Release" href="user_guides/release/prepare.html"/>
+          <item name="Perform Project Release" href="user_guides/release/perform.html"/>
+          <item name="Release Results Management" href="user_guides/release/release_results.html"/>
+        </item>
+        <item name="Project Builds Report" href="user_guides/report/index.html"/>
       </item>
+
       <item name="Administrator's Guides" href="administrator_guides/index.html" collapse="true">
         <item name="Managing Users and Security" href="administrator_guides/security/index.html" collapse="true">
           <item name="Security Configuration" href="administrator_guides/security/customising-security.html"/>
           <item name="LDAP Configuration" href="administrator_guides/security/ldap.html"/>
         </item>
-        <item name="Adding Project Group" href="administrator_guides/projectgroup.html"/>
-        <item name="Managing Builders" href="administrator_guides/builder.html"/>
-        <item name="Managing JDKs" href="administrator_guides/jdk.html"/>
-        <item name="Managing Build Environments" href="administrator_guides/profiles.html"/>
+        <item name="Managing Project Groups" href="administrator_guides/projectgroup.html"/>
+        <item name="Managing Installations" href="administrator_guides/builder.html"/>
+        <item name="Managing Build Environments" href="administrator_guides/buildEnvironment.html"/>
         <item name="Managing Schedules" href="administrator_guides/schedules.html"/>
-        <item name="Managing General Configuration" href="administrator_guides/configuration.html"/> <!-- (configuration and appearance) -->
+        <item name="Managing General Configuration" href="administrator_guides/configuration.html"/>
         <item name="Managing Local Repositories" href="administrator_guides/localRepository.html"/>
         <item name="Managing Purge Configuration" href="administrator_guides/purgeConfiguration.html"/>
+        <item name="Managing Parallel Builds" href="administrator_guides/parallelBuilds.html"/>
+        <item name="Managing Build Queues" href="administrator_guides/buildQueue.html"/>
+        <item name="Managing Build Agents" href="administrator_guides/build-agents.html"/>
+        <item name="Managing Build Agent Groups" href="administrator_guides/build-agent-groups.html"/>
+        <item name="Managing Project Queues" href="administrator_guides/queues.html"/>
         <item name="External databases" href="administrator_guides/external-db.html"/>
         <item name="Monitoring Continuum" href="administrator_guides/monitoring.html"/>
+        <item name="Log Files" href="administrator_guides/logging/index.html" collapse="true">
+          <item name="Audit Logs" href="administrator_guides/logging/audit-logs.html"/>
+          <item name="Continuum Logs" href="administrator_guides/logging/continuum-logs.html"/>
+          <item name="Security Logs" href="administrator_guides/logging/security-logs.html"/>
+        </item>
         <item name="Appearance Configuration" href="administrator_guides/appearance.html"/>
-        <item name="Build Definition Template" href="administrator_guides/builddefTemplate.html"/>        
+        <item name="Build Definition Template" href="administrator_guides/builddefTemplate.html"/>
         <item name="Shutdown Continuum" href="administrator_guides/shutdown.html"/>
+        <item name="Understanding Distributed Builds" href="administrator_guides/distributed-builds.html"/>
+        <item name="WebDAV for Agent Working Copies" href="administrator_guides/webdav.html"/>
+        <!-- <item name="Running builds in a chroot jail" href="administrator_guides/chroot.html"/> -->
       </item>
+
       <item name="Developer's Guides" href="developer_guides/index.html" collapse="true">
-        <!-- item name="SVN repository structure" href="developer_guides/svn.html"/ -->
         <item name="Building Continuum" href="developer_guides/building.html"/>
-        <!-- item name="Design" href="developer_guides/design.html"/ -->
         <item name="XML-RPC" href="developer_guides/xmlrpc.html"/>
       </item>
+
+      <item name="PDF" href="apache-continuum.pdf"/>
     </menu>
   </body>
 </project>
diff --git a/continuum-docs/src/site/xdoc/release-notes.xml b/continuum-docs/src/site/xdoc/release-notes.xml
index 5fc3754..c8fc664 100644
--- a/continuum-docs/src/site/xdoc/release-notes.xml
+++ b/continuum-docs/src/site/xdoc/release-notes.xml
@@ -1,42 +1,506 @@
+<!--
+  ~ 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.
+  -->
+
 <document>
   <properties>
     <title>Release Notes</title>
-  </properties>  
-<body>
+  </properties>
+  <body>
 
-  <h2>Apache Continuum 1.3.1 Release Notes</h2>
-  
-  <p>The Apache Continuum team is pleased to announce Apache Continuum 1.3.1.</p>
+    <h1>Apache Continuum 1.4.3 Release Notes</h1>
 
-  <p>As the first public release in the 1.3 series, Apache Continuum 1.3.1 includes the following new features:</p>
+    <p>The Apache Continuum team is pleased to announce Apache Continuum 1.4.3.</p>
 
-  <p><b>Transient State</b> -- Continuum now separates transient errors such as an unreachable scm system from build failures.</p>
+    <p>To learn more about how the Continuum dev team versions releases, see our
+      <a href="http://continuum.apache.org/development/release.html">release guidelines</a>.
+    </p>
 
-  <p><b>Migration to Struts 2</b> -- The web framework underlying Continuum has been changed from WebWork to Struts 2.0.12.
-    For more information on the S2 framework, visit <a href="http://struts.apache.org">http://struts.apache.org</a>.</p>
+    <p>
+      This is a maintenance release addressing the struts CSRF vulnerability CVE-2014-7809 and other minor fixes.
+    </p>
 
-  <p>To learn more about how the Continuum dev team versions releases, see our
-      <a href="http://continuum.apache.org/development/release.html">release guidelines</a>.</p>  
+<h2>        Bug
+</h2>
+<ul>
+<li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-1156'>CONTINUUM-1156</a>] -         Continuum will not successfully delete build directories containing symbolic links
+</li>
+<li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2119'>CONTINUUM-2119</a>] -         Cleaning up large working directories fails with OutOfMemoryError
+</li>
+<li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2585'>CONTINUUM-2585</a>] -         Adding a maven pom via url with username drops query parameters
+</li>
+<li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2723'>CONTINUUM-2723</a>] -         Attempting edit a project results in an internal error
+</li>
+</ul>
 
-  <h2>Release Notes - Continuum - Version 1.3.1</h2>    
+<h2>        Task
+</h2>
+<ul>
+<li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2727'>CONTINUUM-2727</a>] -         Upgrade to struts 2.3.20
+</li>
+</ul>
 
-  <h2>Release Notes - Continuum - Version 1.3.0 (test build)</h2>
+    <h1>Changes in Apache Continuum 1.4.2</h1>
 
-  <h2>        Improvement
-  </h2>
-  <ul>
-  <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-1829'>CONTINUUM-1829</a>] -         separate transient errors from build failures in notification and display
-  </li>
-  <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-1864'>CONTINUUM-1864</a>] -         Transient State
-  </li>
-  <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-1962'>CONTINUUM-1962</a>] -         Migrate to Struts 2
-  </li>
-  </ul>
+<h2>        Bug
+</h2>
+<ul>
+<li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-1777'>CONTINUUM-1777</a>] -         Able to create a build template without build definition
+</li>
+<li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2222'>CONTINUUM-2222</a>] -         pom.xml is deleted if validation fails
+</li>
+<li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2486'>CONTINUUM-2486</a>] -         Error in backup output of builddefinition templates 
+</li>
+<li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2495'>CONTINUUM-2495</a>] -         appearance.jsp should use POST instead of GET
+</li>
+<li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2669'>CONTINUUM-2669</a>] -         org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportClient
+</li>
+<li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2699'>CONTINUUM-2699</a>] -         Document installing Continuum as a Mac OS X service with launchd
+</li>
+<li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2702'>CONTINUUM-2702</a>] -         Cannot add an argument to remove a profile ( -P!profile) 
+</li>
+<li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2703'>CONTINUUM-2703</a>] -         reduce logging from RbacAuthorizer
+</li>
+<li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2704'>CONTINUUM-2704</a>] -         Shell builds are not executing concurrently
+</li>
+<li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2705'>CONTINUUM-2705</a>] -         Can&#39;t build projects with null builddef fields 
+</li>
+<li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2709'>CONTINUUM-2709</a>] -         Goals/phases aren&#39;t required when editing maven build types 
+</li>
+<li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2712'>CONTINUUM-2712</a>] -         Release issue :: Unable to release components
+</li>
+<li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2724'>CONTINUUM-2724</a>] -         Can&#39;t add a project over XMLRPC without a project group
+</li>
+</ul>
+                        
+<h2>        Task
+</h2>
+<ul>
+<li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2149'>CONTINUUM-2149</a>] -         Upgrade to Maven project libraries
+</li>
+</ul>
+        
+    <h1>Changes in Apache Continuum 1.4.1</h1>
 
-Have Fun !
-<br/><br/>
---<br/>
-The Apache Continuum Team  
+    <p>This release includes the following new features:</p>
 
-</body>
-</document>
\ No newline at end of file
+    <p>
+      <b>Improved user recognition</b>
+      - information on who executed releases and forced builds, and better handling of sending notifications to
+      developers who made a change
+    </p>
+
+    <h2>        Bug
+    </h2>
+    <ul>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-1569'>CONTINUUM-1569</a>] -         Release of a flat structure multi-module project doesn&#39;t work
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-1689'>CONTINUUM-1689</a>] -         Bad string replacement of entities in build result
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2003'>CONTINUUM-2003</a>] -         Edit roles deletes all existing roles when sharing a user database
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2346'>CONTINUUM-2346</a>] -         NPE in log on forced build and project never builds
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2384'>CONTINUUM-2384</a>] -         Cannot download from distributed build working directory
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2420'>CONTINUUM-2420</a>] -         missing default values of scm tag, preparation goals and release perform goals when distributed build is enabled
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2436'>CONTINUUM-2436</a>] -         Scheduled Build occurs even when Always Build = false and no changes have occurred
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2443'>CONTINUUM-2443</a>] -         adding duplicate build agent  with trailing whitespace should not be allowed
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2454'>CONTINUUM-2454</a>] -         Failed to build a shell project when &#39;distributed builds&#39; is enabled
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2500'>CONTINUUM-2500</a>] -         Problems with quotation marks in projectgroup names
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2503'>CONTINUUM-2503</a>] -         &#39;Triggered by&#39; should not be blank when it&#39;s a scheduled build
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2507'>CONTINUUM-2507</a>] -         Error releasing project with POM encoded in UTF-8 with BOM
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2508'>CONTINUUM-2508</a>] -         Invalid web.xml in continuum-distrubuted-tests module
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2510'>CONTINUUM-2510</a>] -         Experiencing slow performance when there are many roles
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2519'>CONTINUUM-2519</a>] -         Database upgrade script fails
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2520'>CONTINUUM-2520</a>] -         NullPointerException in org.apache.maven.continuum.notification.mail.MailContinuumNotifier
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2531'>CONTINUUM-2531</a>] -         Cannot change DEFAULT local repository via settings.xml in Windows 7
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2532'>CONTINUUM-2532</a>] -         Editing Build Definition doesn&#39;t reflect changes when saved
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2533'>CONTINUUM-2533</a>] -         UpdateWorkingCopyPhaseTest fails in continuum-release, file url is incorrect
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2538'>CONTINUUM-2538</a>] -         [Regression] Unable to release using provide parameters
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2543'>CONTINUUM-2543</a>] -         LDAP integration and empty passwords
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2547'>CONTINUUM-2547</a>] -         French I18n : typos
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2554'>CONTINUUM-2554</a>] -         Forced directory purges should show up in the audit log
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2563'>CONTINUUM-2563</a>] -         &#39;--non-recursive&#39; argument is not stripped in project&#39;s build definition if project was added to an existing project group with &#39;For multi-module project, load only root as recursive build&#39; selected
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2568'>CONTINUUM-2568</a>] -         Exception when calling  &#39;continuumXmlRpcClient.getReleaseResultsForProjectGroup(projectGroupId)&#39;
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2569'>CONTINUUM-2569</a>] -         No continuum release result was created when releasing from continuumxmlrpc
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2571'>CONTINUUM-2571</a>] -         Error in changelog when preparing build with distributed build enabled
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2581'>CONTINUUM-2581</a>] -         Unable to release with distributed builds enabled
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2584'>CONTINUUM-2584</a>] -         Unable to save the Description of Build Definition when creating build defintion using xmlrpc
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2587'>CONTINUUM-2587</a>] -         Able to set distributed builds in the configuration file of continuum.
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2591'>CONTINUUM-2591</a>] -         Git based maven2 builds can&#39;t properly release or checkout on branch
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2595'>CONTINUUM-2595</a>] -         Unable to retrieve projects in continuum through xmlrpc when distributed builds is enabled.
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2603'>CONTINUUM-2603</a>] -         CSRF vulnerability - Continuum doesn&#39;t check which form sends credentials
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2604'>CONTINUUM-2604</a>] -         extremecomponents table should use autoIncludeParameters=&quot;false&quot;
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2607'>CONTINUUM-2607</a>] -         Continuum Build Agent fails to update the project from checkout when a &quot;Null values aren&#39;t supported&quot; is encountered during a build.
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2608'>CONTINUUM-2608</a>] -         username and password are missing when doing a checkout from svn even if useCredentialsCache is set to false.
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2610'>CONTINUUM-2610</a>] -         Profiles are not activated during release
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2616'>CONTINUUM-2616</a>] -         Project state is still building after cancelling a build with distributed builds enabled
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2619'>CONTINUUM-2619</a>] -         Continuum Release scm comment prefix needs to insert whitespace on all commit messages
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2626'>CONTINUUM-2626</a>] -         Email Notification not sent when Distributed Build enabled
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2627'>CONTINUUM-2627</a>] -         Unable to add a project that are in private Github repositories
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2628'>CONTINUUM-2628</a>] -         Continuum uses SCM credentials provided on project add when checking out and updating working copy during project build and during release:prepare when using GIT and SSH in SCM urls
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2631'>CONTINUUM-2631</a>] -         Continuum doesn&#39;t work with MySQL
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2641'>CONTINUUM-2641</a>] -         Exceptions thrown by ContinuumXmlRpcClient when used by multiple threads
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2643'>CONTINUUM-2643</a>] -         Intermittent problem encountered when building projects with distributed builds
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2646'>CONTINUUM-2646</a>] -         Project group was not removed from queue via XMLRPC cancelBuild
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2648'>CONTINUUM-2648</a>] -         Project build is sometimes distributed to the wrong agent
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2650'>CONTINUUM-2650</a>] -         Unable to get the correct build agent url via XMLRPC
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2656'>CONTINUUM-2656</a>] -         Distributed build may never return
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2657'>CONTINUUM-2657</a>] -         Build agent installations should overwrite the installations from the Master when doing a release
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2660'>CONTINUUM-2660</a>] -         A message was logged saying I &#39;Added a build definition&#39; even when I tried to edit one.
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2663'>CONTINUUM-2663</a>] -         Release trying to use the wrong agent
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2666'>CONTINUUM-2666</a>] -         NPE when removing build agent group via XMLRPC
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2670'>CONTINUUM-2670</a>] -         Modifying a project level build definition from the Build Definitions Summary tab results in errors
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2672'>CONTINUUM-2672</a>] -         when a user has the &quot;manage scheduling&quot; role, they are listed as a project administrator/developer on the members tab, even if they are not a developer/administrator of that project.
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2673'>CONTINUUM-2673</a>] -         Failure to do a release rollback should display the error message in the page
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2675'>CONTINUUM-2675</a>] -         ContinuumObjectNotFoundException when deleting build results
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2683'>CONTINUUM-2683</a>] -         Project in group already in queued can cause other group projects not to be queued
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2684'>CONTINUUM-2684</a>] -         defaultStack requires a stronger blacklist of parameter names in the param interceptor
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2687'>CONTINUUM-2687</a>] -         preparing subsequent releases appends timestamp to ID, but never lists them for performing
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2688'>CONTINUUM-2688</a>] -         Build definition goals won&#39;t accept Maven goals with a group ID
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2689'>CONTINUUM-2689</a>] -         release error page incorrectly displayed for unexpected exceptions
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2691'>CONTINUUM-2691</a>] -         validation of build file for Ant build definitions is too strict
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2692'>CONTINUUM-2692</a>] -         if validation fails on an Ant build definition, you are sent to the Maven page
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2693'>CONTINUUM-2693</a>] -         File handle leak with TCP connections in CLOSE_WAIT when using distributed builds
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2694'>CONTINUUM-2694</a>] -         no need to persist configuration changes to database
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2696'>CONTINUUM-2696</a>] -         Attempting to enable a build agent that is down will remove it from the list
+      </li>
+    </ul>
+
+    <h2>        Improvement
+    </h2>
+    <ul>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-1586'>CONTINUUM-1586</a>] -         Oracle DB use in Continuum
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2025'>CONTINUUM-2025</a>] -         Improve description of Build Environments and Installations
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2044'>CONTINUUM-2044</a>] -         Build agent should only accept requests from its master
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2131'>CONTINUUM-2131</a>] -         An unconfigured build agent should not be enabled
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2193'>CONTINUUM-2193</a>] -         Add option to check out a multi-module project into a single working directory
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2202'>CONTINUUM-2202</a>] -         Do not show subversion password in plain text
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2286'>CONTINUUM-2286</a>] -         Run prepare builds/scm update in parallel
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2483'>CONTINUUM-2483</a>] -         Build agents should be enabled by default
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2499'>CONTINUUM-2499</a>] -         Updated and corrected jboss-web.xml files
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2549'>CONTINUUM-2549</a>] -         Overload ContinuumService.addMavenTwoProject() just like that of Continuum interface
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2551'>CONTINUUM-2551</a>] -         Ability to build project as a forced build in XMLRPC
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2553'>CONTINUUM-2553</a>] -         Log more information when purging directories
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2561'>CONTINUUM-2561</a>] -         Ability to check if project is in prepare build queue from Continuum&#39;s XMLRPC
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2562'>CONTINUUM-2562</a>] -         Add support for adding M2 projects non-recursively (instead of one Continuum project per module) from web services
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2565'>CONTINUUM-2565</a>] -         Ability to release a project in XMLRPC
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2572'>CONTINUUM-2572</a>] -         add new methods in continuum build agent for easier checking if projectgroup is in prepare build queue or currently preparing build
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2582'>CONTINUUM-2582</a>] -         Ability to check if project is in queue or currently preparing build/building with distributed builds enabled
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2586'>CONTINUUM-2586</a>] -         &quot;Maven 2.0.x&quot; label is misleading with the advent of Maven 3
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2592'>CONTINUUM-2592</a>] -         Ability for build agent to use installations in its config file
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2599'>CONTINUUM-2599</a>] -         Ability for Continuum XMLRPC to be able to retrieve Individual Build Agent&#39;s Installations
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2602'>CONTINUUM-2602</a>] -         Ability to retrieve projects release and development versions through XMLRPC
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2617'>CONTINUUM-2617</a>] -         Provide method to cancel a project build using the xmlrpc client
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2625'>CONTINUUM-2625</a>] -         Expose ProjectScmRoot methods in the xml-rpc interface
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2633'>CONTINUUM-2633</a>] -         Enable DB caching
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2637'>CONTINUUM-2637</a>] -         Ability to ping build agent through continuum master xmlrpc
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2638'>CONTINUUM-2638</a>] -         Add more logging in Continuum distributed builds
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2639'>CONTINUUM-2639</a>] -         Ability to do user management through xmlrpc
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2640'>CONTINUUM-2640</a>] -         Add &lt;sharedSecretPassword&gt; in build agent configuration
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2644'>CONTINUUM-2644</a>] -         Ability to retrieve url of build agent executing a project via XMLRPC
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2651'>CONTINUUM-2651</a>] -         Include the build agent url in the build result that is returned using XMLRPC
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2654'>CONTINUUM-2654</a>] -         Ability to create a build environment, with build agent groups and installations via xmlrpc
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2658'>CONTINUUM-2658</a>] -         Support purging of working and release directories of build agents on a schedule
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2659'>CONTINUUM-2659</a>] -         Improve error message returned when failed to add a project via xmlrpc
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2662'>CONTINUUM-2662</a>] -         Display the build agent url in the build result
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2667'>CONTINUUM-2667</a>] -         Allow underscore ( _ ) in project group id
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2668'>CONTINUUM-2668</a>] -         Ability to retrieve build agents with their installations in a single call
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2674'>CONTINUUM-2674</a>] -         Add a role for managing distributed builds
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2679'>CONTINUUM-2679</a>] -         Apache project branding requirements: DOAP file [PATCH]
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2685'>CONTINUUM-2685</a>] -         Use the default build agent for a project if no build environment is given on release
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2686'>CONTINUUM-2686</a>] -         list of previously prepared releases should not depend on build agent state
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2690'>CONTINUUM-2690</a>] -         Update to Jetty 8
+      </li>
+    </ul>
+
+    <h2>        New Feature
+    </h2>
+    <ul>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2188'>CONTINUUM-2188</a>] -         Update Policy for BuilDefinition
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2521'>CONTINUUM-2521</a>] -         builds report page
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2545'>CONTINUUM-2545</a>] -         Add WebDAV interface to continuum build agent for displaying the working copies
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2593'>CONTINUUM-2593</a>] -         Webservice for adding/registering, updating, removing, retrieving build agents in continuum
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2597'>CONTINUUM-2597</a>] -         Webservice for getting platform of build agent
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2600'>CONTINUUM-2600</a>] -         Include in webservice to also return platform of buildagent when retrieving a buildagent or list of buildagents
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2611'>CONTINUUM-2611</a>] -         Ability to specify the value of useCredentialCached when adding a maven two project using the ContinuumXmlRpcClient
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2632'>CONTINUUM-2632</a>] -         Secure working copies of Continuum build agents
+      </li>
+    </ul>
+
+    <h2>        Task
+    </h2>
+    <ul>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2613'>CONTINUUM-2613</a>] -         Add xmlrpc service method overload for buildProject that accepts projectId, buildDefinitionId, and buildTrigger as the parameters
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2620'>CONTINUUM-2620</a>] -         Fix XSS vulnerability in Continuum
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2642'>CONTINUUM-2642</a>] -         Features page needs some love
+      </li>
+    </ul>
+
+    <h1>Changes in Apache Continuum 1.4.0 (Beta)</h1>
+
+    <h2>Bug</h2>
+    <ul>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-1578'>CONTINUUM-1578</a>] - No output after a successful
+        perform release
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2114'>CONTINUUM-2114</a>] - cannot login with perforce scm
+        until new version of scm is included
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2170'>CONTINUUM-2170</a>] - No such object error when
+        forcing a build from the group-level Build Definitions tab
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2267'>CONTINUUM-2267</a>] - Error with backslash in
+        Windows path for inatallation tests
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2270'>CONTINUUM-2270</a>] - Selenium tests fail when run
+        with JDK 1.6
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2285'>CONTINUUM-2285</a>] - Queues page turns to blank if
+        build queues are not empty
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2349'>CONTINUUM-2349</a>] - Project should only build in
+        agents that are in the Build agent group assigned to it
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2371'>CONTINUUM-2371</a>] - Unable to view queues after
+        loss of build agent
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2381'>CONTINUUM-2381</a>] - Project is not building even
+        when there is an enabled build agent configured
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2386'>CONTINUUM-2386</a>] - Build environment selection is
+        ignored when releasing with distributed build enabled
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2391'>CONTINUUM-2391</a>] - Master should not pass full
+        path to local repository to the agent
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2395'>CONTINUUM-2395</a>] - Build Environment accepts
+        duplicate name during edit
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2397'>CONTINUUM-2397</a>] - Unable to edit the added local
+        repository
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2440'>CONTINUUM-2440</a>] - Unable to download html file
+        from working copy
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2450'>CONTINUUM-2450</a>] - Intermittent error when
+        releasing in a distributed build
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2451'>CONTINUUM-2451</a>] - Unable to release a project
+        using the &quot;provide parameters&quot; option with distributed builds
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2466'>CONTINUUM-2466</a>] - authorization failed when
+        building ant / shell projects
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2474'>CONTINUUM-2474</a>] - Fix selenium failing test in
+        windows
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2476'>CONTINUUM-2476</a>] - Projects are not built in the
+        correct build agent when the project is already in the build queue and then triggered to be built again
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2479'>CONTINUUM-2479</a>] - Link to cron-help is wrong
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2487'>CONTINUUM-2487</a>] - Selenium tests fail if run at
+        certain times crossing the 'on the hour' default schedule trigger
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2490'>CONTINUUM-2490</a>] - Getting permission denied when
+        running selenium tests in IE
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2493'>CONTINUUM-2493</a>] - &quot;Users Wiki&quot; link on
+        home page points at old wiki
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2494'>CONTINUUM-2494</a>] - Unable to build a project even
+        though the build agent is there.
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2504'>CONTINUUM-2504</a>] - Queues page shows
+        distributedBuild.table.agentUrl for the Agent URL field instead of the actual value
+      </li>
+    </ul>
+
+    <h2>Improvement
+    </h2>
+    <ul>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-493'>CONTINUUM-493</a>] - Allow to add all developpers
+        address in a notifier without duplicate developpers addresses
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-565'>CONTINUUM-565</a>] - Forced builds should say who
+        (which continuum user) forced the build
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2160'>CONTINUUM-2160</a>] - Upgrade to last scm version
+        (1.2) and last release-manager version
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2373'>CONTINUUM-2373</a>] - Distributed Master needs more
+        detailed logging
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2458'>CONTINUUM-2458</a>] - Continuum Release should do a
+        checkout if there is no working copy
+      </li>
+    </ul>
+
+    <h2>New Feature
+    </h2>
+    <ul>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2265'>CONTINUUM-2265</a>] - Need information on who
+        executed a release
+      </li>
+    </ul>
+
+    <h2>Task
+    </h2>
+    <ul>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2252'>CONTINUUM-2252</a>] - Add documentation for Selenium
+        tests
+      </li>
+    </ul>
+
+    <h2>Test
+    </h2>
+    <ul>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2073'>CONTINUUM-2073</a>] - Revive the automated Selenium
+        integration tests
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2268'>CONTINUUM-2268</a>] - Continuum Webapp Tests Capture
+        Screenshot for AbstractSeleniumTest.java
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2271'>CONTINUUM-2271</a>] - Continuum Build Agent Tests
+        and Improvement on Build Queue Test
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2378'>CONTINUUM-2378</a>] - Selenium Test for deleting
+        projects and project groups
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2467'>CONTINUUM-2467</a>] - Selenium test: check for
+        project group SCM update when building projects
+      </li>
+      <li>[<a href='http://jira.codehaus.org/browse/CONTINUUM-2482'>CONTINUUM-2482</a>] - Replace the use of
+        Thread.sleep to Selenium waitForCondition
+      </li>
+    </ul>
+
+  </body>
+</document>
diff --git a/continuum-jetty/pom.xml b/continuum-jetty/pom.xml
old mode 100755
new mode 100644
index 6f3f30e..a03a392
--- a/continuum-jetty/pom.xml
+++ b/continuum-jetty/pom.xml
@@ -1,42 +1,37 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
+  ~ 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.
+  -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
     <artifactId>continuum</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <artifactId>continuum-jetty</artifactId>
   <packaging>pom</packaging>
   <name>Apache Continuum</name>
   <dependencies>
     <dependency>
-      <groupId>org.mortbay.jetty</groupId>
-      <artifactId>jetty</artifactId>
-      <version>${jetty.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.mortbay.jetty</groupId>
-      <artifactId>start</artifactId>
-      <version>${jetty.version}</version>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-server</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.continuum</groupId>
@@ -45,126 +40,66 @@
     </dependency>
     <!-- Runtime dependencies that need to be included in the generated binaries -->
     <dependency>
-      <groupId>org.mortbay.jetty</groupId>
-      <artifactId>jetty-naming</artifactId>
-      <version>${jetty.version}</version>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-start</artifactId>
       <scope>runtime</scope>
     </dependency>
     <dependency>
-      <groupId>org.mortbay.jetty</groupId>
-      <artifactId>servlet-api-2.5</artifactId>
-      <version>${jetty.version}</version>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-deploy</artifactId>
       <scope>runtime</scope>
     </dependency>
     <dependency>
-      <groupId>org.mortbay.jetty</groupId>
-      <artifactId>jsp-api-2.0</artifactId>
-      <version>${jetty.version}</version>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-jndi</artifactId>
       <scope>runtime</scope>
-    </dependency>    
+    </dependency>
     <dependency>
-      <groupId>org.mortbay.jetty</groupId>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-jsp</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.eclipse.jetty</groupId>
       <artifactId>jetty-plus</artifactId>
-      <version>${jetty.version}</version>
       <scope>runtime</scope>
     </dependency>
     <dependency>
       <groupId>org.apache.derby</groupId>
       <artifactId>derby</artifactId>
-      <version>10.1.3.1</version>
       <scope>runtime</scope>
     </dependency>
     <dependency>
       <groupId>javax.mail</groupId>
       <artifactId>mail</artifactId>
-      <version>1.4</version>
       <scope>runtime</scope>
     </dependency>
     <dependency>
-      <groupId>ant</groupId>
-      <artifactId>ant</artifactId>
-      <version>1.6.5</version>
+      <groupId>commons-dbcp</groupId>
+      <artifactId>commons-dbcp</artifactId>
       <scope>runtime</scope>
     </dependency>
-    <dependency>
-      <groupId>commons-el</groupId>
-      <artifactId>commons-el</artifactId>
-      <version>1.0</version>
-      <scope>runtime</scope>
-      <exclusions>
-        <exclusion>
-          <groupId>commons-logging</groupId>
-          <artifactId>commons-logging</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>tomcat</groupId>
-      <artifactId>jasper-compiler</artifactId>
-      <version>5.5.15</version>
-      <scope>runtime</scope>
-      <exclusions>
-        <exclusion>
-          <groupId>javax.servlet</groupId>
-          <artifactId>jsp-api</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>    
-    <dependency>
-      <groupId>tomcat</groupId>
-      <artifactId>jasper-runtime</artifactId>
-      <version>5.5.15</version>
-      <scope>runtime</scope>
-      <exclusions>
-        <exclusion>
-          <groupId>javax.servlet</groupId>
-          <artifactId>servlet-api</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>jcl104-over-slf4j</artifactId>
-      <version>1.5.0</version>
-      <scope>runtime</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-simple</artifactId>
-      <version>1.5.0</version>
-      <scope>runtime</scope>
-    </dependency>
-    <dependency>
-      <groupId>tomcat</groupId>
-      <artifactId>jasper-compiler-jdt</artifactId>
-      <version>5.5.15</version>
-      <scope>runtime</scope>
-      <exclusions>
-        <exclusion>
-          <groupId>org.eclipse.jdt</groupId>
-          <artifactId>core</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
   </dependencies>
   <build>
     <plugins>
-       <plugin>
+      <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>appassembler-maven-plugin</artifactId>
-        <version>1.0-beta-2</version>
         <configuration>
           <daemons>
             <daemon>
               <id>continuum</id>
-              <mainClass>org.mortbay.start.Main</mainClass>
+              <mainClass>org.eclipse.jetty.start.Main</mainClass>
               <commandLineArguments>
                 <commandLineArgument>conf/jetty.xml</commandLineArgument>
-                <commandLineArgument>conf/jetty-logging.xml</commandLineArgument> 
+                <commandLineArgument>conf/jetty-plus.xml</commandLineArgument>
+                <commandLineArgument>conf/jetty-deploy.xml</commandLineArgument>
+                <commandLineArgument>conf/jetty-contexts.xml</commandLineArgument>
+                <commandLineArgument>conf/jetty-requestlog.xml</commandLineArgument>
               </commandLineArguments>
               <platforms>
                 <platform>jsw</platform>
-              </platforms>              
+              </platforms>
               <generatorConfigurations>
                 <generatorConfiguration>
                   <generator>jsw</generator>
@@ -183,15 +118,11 @@
                     </property>
                     <property>
                       <name>wrapper.logfile</name>
-                      <value>%CONTINUUM_BASE%/logs/wrapper.log</value>
+                      <value>%CONTINUUM_BASE%/logs/wrapper.YYYYMMDD.log</value>
                     </property>
                     <property>
-                      <name>wrapper.app.parameter.2</name>
-                      <value>%CONTINUUM_BASE%/conf/jetty.xml</value>
-                    </property>
-                    <property>
-                      <name>wrapper.app.parameter.3</name>
-                      <value>%CONTINUUM_BASE%/conf/jetty-logging.xml</value>
+                      <name>wrapper.logfile.rollmode</name>
+                      <value>DATE</value>
                     </property>
                     <property>
                       <name>app.base.envvar</name>
@@ -209,6 +140,10 @@
                       <name>wrapper.restart.delay</name>
                       <value>30</value>
                     </property>
+                    <property>
+                      <name>wrapper.java.maxmemory</name>
+                      <value>256</value>
+                    </property>
                   </configuration>
                   <includes>
                     <include>linux-x86-32</include>
@@ -231,9 +166,9 @@
                   <systemProperty>jetty.logs=%CONTINUUM_BASE%/logs</systemProperty>
                   <systemProperty>java.io.tmpdir=%CONTINUUM_BASE%/tmp</systemProperty>
                 </systemProperties>
-              </jvmSettings> 
+              </jvmSettings>
             </daemon>
-          </daemons>          
+          </daemons>
           <repoPath>lib</repoPath>
           <repositoryLayout>flat</repositoryLayout>
           <assembleDirectory>target/generated-resources/appassembler/jsw/continuum</assembleDirectory>
@@ -250,7 +185,7 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-assembly-plugin</artifactId>
-        <version>2.1</version>
+        <version>2.4</version>
         <executions>
           <execution>
             <phase>package</phase>
@@ -261,12 +196,11 @@
         </executions>
         <configuration>
           <descriptor>src/main/assembly/bin.xml</descriptor>
-          <finalName>apache-continuum-${version}</finalName>
+          <finalName>apache-continuum-${project.version}</finalName>
         </configuration>
       </plugin>
       <plugin>
         <artifactId>maven-antrun-plugin</artifactId>
-        <version>1.1</version>
         <executions>
           <execution>
             <id>config</id>
@@ -274,9 +208,9 @@
             <configuration>
               <tasks>
                 <copy todir="target/generated-resources/appassembler/jsw/continuum/conf">
-                  <fileset dir="src/main/conf" />                  
+                  <fileset dir="src/main/conf" />
                 </copy>
-                <mkdir dir="target/generated-resources/appassembler/jsw/continuum/logs" />      
+                <mkdir dir="target/generated-resources/appassembler/jsw/continuum/logs" />
               </tasks>
             </configuration>
             <goals>
@@ -286,14 +220,18 @@
         </executions>
       </plugin>
     </plugins>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.rat</groupId>
+          <artifactId>apache-rat-plugin</artifactId>
+          <configuration>
+            <excludes>
+              <exclude>src/main/conf/webdefault.xml</exclude>
+            </excludes>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
   </build>
-  <pluginRepositories>
-    <pluginRepository>
-      <id>codehaus.org</id>
-      <url>http://snapshots.repository.codehaus.org/</url>
-    </pluginRepository>
-  </pluginRepositories>
-  <properties>
-    <jetty.version>6.1.11</jetty.version>
-  </properties>
 </project>
diff --git a/continuum-jetty/src/main/assembly/bin.xml b/continuum-jetty/src/main/assembly/bin.xml
index e16cff1..bf8ebc0 100755
--- a/continuum-jetty/src/main/assembly/bin.xml
+++ b/continuum-jetty/src/main/assembly/bin.xml
@@ -24,7 +24,7 @@
     <format>zip</format>
   </formats>
   <fileSets>
-    <fileSet>      
+    <fileSet>
       <directory>target/generated-resources/appassembler/jsw/continuum/apps</directory>
       <outputDirectory>apps</outputDirectory>
     </fileSet>
@@ -40,7 +40,8 @@
         <exclude>maven-metadata-appassembler.xml</exclude>
       </excludes>
       <fileMode>0755</fileMode>
-    </fileSet> 
+      <directoryMode>0755</directoryMode>
+    </fileSet>
     <fileSet>
       <directory>target/generated-resources/appassembler/jsw/continuum/logs</directory>
       <outputDirectory>logs</outputDirectory>
@@ -48,8 +49,8 @@
     <fileSet>
       <directory>target/generated-resources/appassembler/jsw/continuum/bin</directory>
       <outputDirectory>bin</outputDirectory>
-      <includes>   
-         <include>continuum</include>           
+      <includes>
+        <include>continuum</include>
       </includes>
       <fileMode>0755</fileMode>
       <lineEnding>unix</lineEnding>
@@ -57,20 +58,20 @@
     <fileSet>
       <directory>target/generated-resources/appassembler/jsw/continuum/bin</directory>
       <outputDirectory>bin</outputDirectory>
-      <includes>   
-         <include>wrapper-linux-x86-32</include>
-         <include>wrapper-linux-x86-64</include>
-         <include>wrapper-macosx-universal-32</include>
-         <include>wrapper-solaris-x86-32</include>
-         <include>wrapper-solaris-sparc-32</include>
-         <include>wrapper-solaris-sparc-64</include>
+      <includes>
+        <include>wrapper-linux-x86-32</include>
+        <include>wrapper-linux-x86-64</include>
+        <include>wrapper-macosx-universal-32</include>
+        <include>wrapper-solaris-x86-32</include>
+        <include>wrapper-solaris-sparc-32</include>
+        <include>wrapper-solaris-sparc-64</include>
       </includes>
       <fileMode>0755</fileMode>
     </fileSet>
     <fileSet>
       <directory>target/generated-resources/appassembler/jsw/continuum/bin</directory>
       <outputDirectory>bin</outputDirectory>
-      <includes>        
+      <includes>
         <include>continuum.bat</include>
       </includes>
       <fileMode>0755</fileMode>
@@ -79,7 +80,7 @@
     <fileSet>
       <directory>target/generated-resources/appassembler/jsw/continuum/bin</directory>
       <outputDirectory>bin</outputDirectory>
-      <includes>   
+      <includes>
         <include>wrapper-windows-x86-32.exe</include>
       </includes>
       <fileMode>0755</fileMode>
@@ -102,6 +103,10 @@
       <directory>src/main/tmp/</directory>
       <outputDirectory>/tmp</outputDirectory>
     </fileSet>
+    <fileSet>
+      <directory>src/main/contexts/</directory>
+      <outputDirectory>/contexts</outputDirectory>
+    </fileSet>
   </fileSets>
   <dependencySets>
     <dependencySet>
diff --git a/continuum-jetty/src/main/conf/continuum.xml b/continuum-jetty/src/main/conf/continuum.xml
index 06afa0c..b9183de 100755
--- a/continuum-jetty/src/main/conf/continuum.xml
+++ b/continuum-jetty/src/main/conf/continuum.xml
@@ -1,21 +1,21 @@
 <?xml version='1.0' encoding='UTF-8'?>
 <!--
-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
+  ~ 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.
+  -->
 
-  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.
--->
-
-<continuum-configuration />
+<continuum-configuration/>
diff --git a/continuum-jetty/src/main/conf/jetty-contexts.xml b/continuum-jetty/src/main/conf/jetty-contexts.xml
new file mode 100644
index 0000000..5d6aa96
--- /dev/null
+++ b/continuum-jetty/src/main/conf/jetty-contexts.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<!--
+  ~ 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.
+  -->
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
+
+<!-- =============================================================== -->
+<!-- Add a ContextProvider to the deployment manager                 -->
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<!-- This scans the webapps directory for war files and directories  -->
+<!-- to deploy.                                                      -->
+<!-- This configuration must be used with jetty-deploy.xml, which    -->
+<!-- creates the deployment manager instance                         -->
+<!-- =============================================================== -->
+<Configure id="Server" class="org.eclipse.jetty.server.Server">
+        <Ref id="DeploymentManager">
+          <Call name="addAppProvider">
+            <Arg>
+              <New class="org.eclipse.jetty.deploy.providers.ContextProvider">
+                <Set name="monitoredDirName"><Property name="appserver.base" default="." />/contexts</Set>
+                <Set name="scanInterval">1</Set>
+              </New>
+            </Arg>
+          </Call>
+        </Ref>
+</Configure>
diff --git a/continuum-jetty/src/main/conf/jetty-deploy.xml b/continuum-jetty/src/main/conf/jetty-deploy.xml
new file mode 100644
index 0000000..80a451f
--- /dev/null
+++ b/continuum-jetty/src/main/conf/jetty-deploy.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0"?>
+<!--
+  ~ 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.
+  -->
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
+
+<!-- =============================================================== -->
+<!-- Create the deployment manager                                   -->
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<!-- The deplyment manager handles the lifecycle of deploying web    -->
+<!-- applications. Apps are provided by instances of the             -->
+<!-- AppProvider interface.  Typically these are provided by         -->
+<!-- one or more of:                                                 -->
+<!--   jetty-webapps.xml       - monitors webapps for wars and dirs  -->
+<!--   jetty-contexts.xml      - monitors contexts for context xml   -->
+<!--   jetty-templates.xml     - monitors contexts and templates     -->
+<!-- =============================================================== -->
+<Configure id="Server" class="org.eclipse.jetty.server.Server">
+
+    <Call name="addBean">
+      <Arg>
+        <New id="DeploymentManager" class="org.eclipse.jetty.deploy.DeploymentManager">
+          <Set name="contexts">
+            <Ref id="Contexts" />
+          </Set>
+          <Call name="setContextAttribute">
+            <Arg>org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern</Arg>
+            <Arg>.*/servlet-api-[^/]*\.jar$</Arg>
+          </Call>
+          
+          
+          <!-- Add a customize step to the deployment lifecycle -->
+          <!-- uncomment and replace DebugBinding with your extended AppLifeCycle.Binding class 
+          <Call name="insertLifeCycleNode">
+            <Arg>deployed</Arg>
+            <Arg>starting</Arg>
+            <Arg>customise</Arg>
+          </Call>
+          <Call name="addLifeCycleBinding">
+            <Arg>
+              <New class="org.eclipse.jetty.deploy.bindings.DebugBinding">
+                <Arg>customise</Arg>
+              </New>
+            </Arg>
+          </Call>
+          -->
+          
+        </New>
+      </Arg>
+    </Call>
+</Configure>
diff --git a/continuum-jetty/src/main/conf/jetty-logging.xml b/continuum-jetty/src/main/conf/jetty-logging.xml
deleted file mode 100755
index 379bd13..0000000
--- a/continuum-jetty/src/main/conf/jetty-logging.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
-<!--
-  ~ 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.
-  -->
-
-<!-- =============================================================== -->
-<!-- Configure stderr and stdout to a Jetty rollover log file        -->
-<!-- this configuration file should be used in combination with      -->
-<!-- other configuration files.  e.g.                                -->
-<!--    java -jar start.jar etc/jetty-logging.xml etc/jetty.xml      -->
-<!-- =============================================================== -->
-<Configure id="Server" class="org.mortbay.jetty.Server">
-
-    <New id="ServerLog" class="java.io.PrintStream">
-      <Arg>
-        <New class="org.mortbay.util.RolloverFileOutputStream">
-          <Arg><SystemProperty name="jetty.logs" default="./logs"/>/yyyy_mm_dd.stderrout.log</Arg>
-          <Arg type="boolean">false</Arg>
-          <Arg type="int">90</Arg>
-          <Arg><Call class="java.util.TimeZone" name="getTimeZone"><Arg>GMT</Arg></Call></Arg>
-          <Get id="ServerLogName" name="datedFilename"/>
-        </New>
-      </Arg>
-    </New>
-
-    <Call class="org.mortbay.log.Log" name="info"><Arg>Redirecting stderr/stdout to <Ref id="ServerLogName"/></Arg></Call>
-    <Call class="java.lang.System" name="setErr"><Arg><Ref id="ServerLog"/></Arg></Call>
-    <Call class="java.lang.System" name="setOut"><Arg><Ref id="ServerLog"/></Arg></Call>
-
-</Configure>
-
-
-
diff --git a/continuum-jetty/src/main/conf/jetty-plus.xml b/continuum-jetty/src/main/conf/jetty-plus.xml
new file mode 100644
index 0000000..7a59d1b
--- /dev/null
+++ b/continuum-jetty/src/main/conf/jetty-plus.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0"?>
+<!--
+  ~ 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.
+  -->
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
+
+<!-- =============================================================== -->
+<!-- Configure Jetty Plus features                                   -->
+<!--                                                                 -->
+<!-- This file sets up a WebAppDeployer to automatically deploy all  -->
+<!-- webapps in $jetty.home/webapps-plus at startup time, and to     -->
+<!-- enable all of them with Plus features (jndi etc).               -->
+<!--                                                                 -->
+<!-- You can instead configure individual webapps with Jetty Plus    -->
+<!-- features by using the ContextDeployer (configured in            -->
+<!-- $jetty.home/etc/jetty.xml), and ensuring that you set the       -->
+<!-- same set of classes listed below in the "plusConfig" as the     -->
+<!-- webapp's configurationClasses.                                  -->
+<!--                                                                 -->
+<!-- For more information about Jetty Plus, see the Jetty wiki at    -->
+<!-- http://docs.codehaus.org/display/JETTY/Jetty+Wiki               -->
+<!-- =============================================================== -->
+<Configure id="Server" class="org.eclipse.jetty.server.Server">
+
+  <!-- =========================================================== -->
+  <!-- Example JAAS realm setup.                                   -->
+  <!-- The LoginModuleName must be exactly the same as in the      -->
+  <!-- login.conf file, and the realm Name must be the same as in  -->
+  <!-- the web.xml file.                                           -->
+  <!-- =========================================================== -->
+  <!-- 
+  <Call name="addBean">
+    <Arg>
+      <New class="org.eclipse.jetty.plus.jaas.JAASLoginService">
+	      <Set name="name">xyzrealm</Set>
+	      <Set name="LoginModuleName">xyz</Set>
+	    </New>
+    </Arg>
+  </Call>
+  -->
+
+
+  <!-- =========================================================== -->
+  <!-- Enabling plus feature.                                      -->
+  <!-- Choose one of the following methods. NOTE that by default   -->
+  <!-- the last method (enabled for all webapps on this Server) is -->
+  <!-- enabled.                                                    -->
+  <!--                                                             -->
+  <!-- For a single webapp:                                        -->
+  <!-- Use a context xml file to call                              -->
+  <!--  setConfigurationClasses(plusConfig).                       -->
+  <!--                                                             -->
+  <!-- For all webapps in a directory:                             -->
+  <!-- Uncomment the section entitled  "Apply plusConfig to all    -->
+  <!-- webapps in webapps-plus".                                   -->
+  <!--                                                             -->
+  <!-- For all webapps deployed via this Server instance:          -->
+  <!-- Uncomment the section entitled "Apply plusConfig to all     -->
+  <!-- webapps for this Server". NOTE: this is the default.        -->
+  <!-- =========================================================== -->
+  
+
+  <!-- =========================================================== -->
+  <!-- Sequence of configurations to defining Plus features.       -->
+  <!-- =========================================================== -->
+  <Array id="plusConfig" type="java.lang.String">
+    <Item>org.eclipse.jetty.webapp.WebInfConfiguration</Item>
+    <Item>org.eclipse.jetty.webapp.WebXmlConfiguration</Item>
+    <Item>org.eclipse.jetty.webapp.MetaInfConfiguration</Item>
+    <Item>org.eclipse.jetty.webapp.FragmentConfiguration</Item>
+    <Item>org.eclipse.jetty.plus.webapp.EnvConfiguration</Item>
+    <Item>org.eclipse.jetty.plus.webapp.PlusConfiguration</Item>
+    <Item>org.eclipse.jetty.webapp.JettyWebXmlConfiguration</Item>
+    <Item>org.eclipse.jetty.webapp.TagLibConfiguration</Item>
+  </Array>
+
+  <!-- =========================================================== -->
+  <!-- Apply plusConfig to all webapps in webapps-plus             -->
+  <!-- =========================================================== -->
+  <!-- Uncomment the following to set up a deployer that will      -->
+  <!-- deploy webapps from a directory called webapps-plus. Note   -->
+  <!-- that you will need to create this directory first!          -->
+  <!--
+  <Ref id="DeploymentManager">
+      <Call name="addAppProvider">
+        <Arg>
+          <New class="org.eclipse.jetty.deploy.providers.WebAppProvider">
+            <Set name="monitoredDirName"><Property name="jetty.home" default="." />/webapps-plus</Set>
+            <Set name="defaultsDescriptor"><Property name="jetty.home" default="."/>/etc/webdefault.xml</Set>
+            <Set name="scanInterval">5</Set>
+            <Set name="contextXmlDir"><Property name="jetty.home" default="." />/contexts</Set>
+            <Set name="parentLoaderPriority">false</Set>
+            <Set name="extractWars">true</Set>
+            <Set name="configurationClasses"><Ref id="plusConfig"/></Set>
+          </New>
+        </Arg>
+      </Call>
+  </Ref>
+  -->
+
+  <!-- =========================================================== -->
+  <!-- Apply plusConfig to all webapps for this Server             -->
+  <!-- =========================================================== -->
+    <Call name="setAttribute">
+      <Arg>org.eclipse.jetty.webapp.configuration</Arg>
+      <Arg>
+          <Ref id="plusConfig"/>
+      </Arg>
+    </Call>
+
+</Configure>
+
diff --git a/continuum-jetty/src/main/conf/jetty-requestlog.xml b/continuum-jetty/src/main/conf/jetty-requestlog.xml
new file mode 100644
index 0000000..65ec625
--- /dev/null
+++ b/continuum-jetty/src/main/conf/jetty-requestlog.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+<!--
+  ~ 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.
+  -->
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
+
+<!-- =============================================================== -->
+<!-- Configure the Jetty Request Log                                 -->
+<!-- =============================================================== -->
+
+<Configure id="Server" class="org.eclipse.jetty.server.Server">
+
+    <!-- =========================================================== -->
+    <!-- Configure Request Log                                       -->
+    <!-- =========================================================== -->
+    <Ref id="Handlers">
+      <Call name="addHandler">
+        <Arg>
+          <New id="RequestLog" class="org.eclipse.jetty.server.handler.RequestLogHandler">
+	    <Set name="requestLog">
+	      <New id="RequestLogImpl" class="org.eclipse.jetty.server.NCSARequestLog">
+		<Set name="filename"><Property name="jetty.logs" default="./logs"/>/yyyy_mm_dd.request.log</Set>
+		<Set name="filenameDateFormat">yyyy_MM_dd</Set>
+		<Set name="retainDays">90</Set>
+		<Set name="append">true</Set>
+		<Set name="extended">false</Set>
+		<Set name="logCookies">false</Set>
+		<Set name="LogTimeZone">GMT</Set>
+	      </New>
+	    </Set>
+	  </New>
+        </Arg>
+      </Call>
+    </Ref>
+
+</Configure>
diff --git a/continuum-jetty/src/main/conf/jetty.xml b/continuum-jetty/src/main/conf/jetty.xml
index 17305f9..b51a0d5 100755
--- a/continuum-jetty/src/main/conf/jetty.xml
+++ b/continuum-jetty/src/main/conf/jetty.xml
@@ -1,5 +1,4 @@
 <?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
 <!--
   ~ Licensed to the Apache Software Foundation (ASF) under one
   ~ or more contributor license agreements.  See the NOTICE file
@@ -18,183 +17,72 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
   -->
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
 
 <!-- =============================================================== -->
 <!-- Configure the Jetty Server                                      -->
 <!--                                                                 -->
 <!-- Documentation of this file format can be found at:              -->
-<!-- http://docs.codehaus.org/display/JETTY/jetty.xml                -->
+<!-- http://wiki.eclipse.org/Jetty/Reference/jetty.xml_syntax        -->
 <!--                                                                 -->
+<!-- Additional configuration files are available in $JETTY_HOME/etc -->
+<!-- and can be mixed in.  For example:                              -->
+<!--   java -jar start.jar etc/jetty-ssl.xml                         -->
+<!--                                                                 -->
+<!-- See start.ini file for the default configuraton files           -->
 <!-- =============================================================== -->
 
 
-<Configure id="Server" class="org.mortbay.jetty.Server">
+<Configure id="Server" class="org.eclipse.jetty.server.Server">
 
     <!-- =========================================================== -->
     <!-- Server Thread Pool                                          -->
     <!-- =========================================================== -->
     <Set name="ThreadPool">
-      <!-- Default bounded blocking threadpool 
-      -->
-      <New class="org.mortbay.thread.BoundedThreadPool">
+      <!-- Default queued blocking threadpool -->
+      <New class="org.eclipse.jetty.util.thread.QueuedThreadPool">
         <Set name="minThreads">10</Set>
-        <Set name="maxThreads">250</Set>
-        <Set name="lowThreads">25</Set>
+        <Set name="maxThreads">200</Set>
+        <Set name="detailedDump">false</Set>
       </New>
-
-      <!-- Optional Java 5 bounded threadpool with job queue 
-      <New class="org.mortbay.thread.concurrent.ThreadPool">
-        <Set name="corePoolSize">250</Set>
-        <Set name="maximumPoolSize">250</Set>
-      </New>
-      -->
     </Set>
 
-
-
     <!-- =========================================================== -->
     <!-- Set connectors                                              -->
     <!-- =========================================================== -->
-    <!-- One of each type!                                           -->
-    <!-- =========================================================== -->
 
-    <!-- Use this connector for many frequently idle connections
-         and for threadless continuations.
-    -->    
-    <!-- START SNIPPET: jetty_port -->    
     <Call name="addConnector">
       <Arg>
-          <New class="org.mortbay.jetty.nio.SelectChannelConnector">
-            <Set name="host"><SystemProperty name="jetty.host" /></Set>
-            <Set name="port"><SystemProperty name="jetty.port" default="8080"/></Set>
-            <Set name="maxIdleTime">30000</Set>
+          <New class="org.eclipse.jetty.server.nio.SelectChannelConnector">
+            <Set name="host"><Property name="jetty.host" /></Set>
+            <Set name="port"><Property name="jetty.port" default="8080"/></Set>
+            <Set name="maxIdleTime">300000</Set>
             <Set name="Acceptors">2</Set>
             <Set name="statsOn">false</Set>
             <Set name="confidentialPort">8443</Set>
-	    <Set name="lowResourcesConnections">5000</Set>
+	    <Set name="lowResourcesConnections">20000</Set>
 	    <Set name="lowResourcesMaxIdleTime">5000</Set>
           </New>
       </Arg>
     </Call>
-    <!-- END SNIPPET: jetty_port -->
-
-    <!-- Use this connector if NIO is not available. 
-    <Call name="addConnector">
-      <Arg>
-          <New class="org.mortbay.jetty.bio.SocketConnector">
-            <Set name="port">8081</Set>
-            <Set name="maxIdleTime">50000</Set>
-            <Set name="lowResourceMaxIdleTime">1500</Set>
-          </New>
-      </Arg>
-    </Call>
-    -->
-
-    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
-    <!-- To add a HTTPS SSL listener                                     -->
-    <!-- see jetty-ssl.xml to add an ssl connector. use                  -->
-    <!-- java -jar start.jar etc/jetty.xml etc/jetty-ssl.xml             -->
-    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
-    
-    <!-- =========================================================== -->
-    <!-- Set up global session ID manager                            -->
-    <!-- =========================================================== -->
-    <!--
-    <Set name="sessionIdManager">
-      <New class="org.mortbay.jetty.servlet.HashSessionIdManager">
-        <Set name="workerName">node1</Set>
-      </New>
-    </Set>
-    -->
 
     <!-- =========================================================== -->
     <!-- Set handler Collection Structure                            --> 
     <!-- =========================================================== -->
     <Set name="handler">
-      <New id="Handlers" class="org.mortbay.jetty.handler.HandlerCollection">
+      <New id="Handlers" class="org.eclipse.jetty.server.handler.HandlerCollection">
         <Set name="handlers">
-         <Array type="org.mortbay.jetty.Handler">
+         <Array type="org.eclipse.jetty.server.Handler">
            <Item>
-             <New id="Contexts" class="org.mortbay.jetty.handler.ContextHandlerCollection"/>
+             <New id="Contexts" class="org.eclipse.jetty.server.handler.ContextHandlerCollection"/>
            </Item>
            <Item>
-             <New id="DefaultHandler" class="org.mortbay.jetty.handler.DefaultHandler"/>
-           </Item>
-           <Item>
-             <New id="RequestLog" class="org.mortbay.jetty.handler.RequestLogHandler"/>
+             <New id="DefaultHandler" class="org.eclipse.jetty.server.handler.DefaultHandler"/>
            </Item>
          </Array>
         </Set>
       </New>
     </Set>
-    
-    <!-- =========================================================== -->
-    <!-- Configure the context deployer                              -->
-    <!-- A context deployer will deploy contexts described in        -->
-    <!-- configuration files discovered in a directory.              -->
-    <!-- The configuration directory can be scanned for hot          -->
-    <!-- deployments at the configured scanInterval.                 -->
-    <!--                                                             -->
-    <!-- This deployer is configured to deploy contexts configured   -->
-    <!-- in the $JETTY_HOME/contexts directory                       -->
-    <!--                                                             -->
-    <!-- =========================================================== -->
-    <Call name="addLifeCycle">
-      <Arg>
-        <New class="org.mortbay.jetty.deployer.ContextDeployer">
-          <Set name="contexts"><Ref id="Contexts"/></Set>
-          <Set name="configurationDir"><SystemProperty name="jetty.home" default="."/>/contexts</Set>
-          <Set name="scanInterval">1</Set>
-        </New>
-      </Arg>
-    </Call>
-
-    <!-- =========================================================== -->
-    <!-- Configure the webapp deployer.                              -->
-    <!-- A webapp  deployer will deploy standard webapps discovered  -->
-    <!-- in a directory at startup, without the need for additional  -->
-    <!-- configuration files.    It does not support hot deploy or   -->
-    <!-- non standard contexts (see ContextDeployer above).          -->
-    <!--                                                             -->
-    <!-- This deployer is configured to deploy webapps from the      -->
-    <!-- $JETTY_HOME/webapps directory                               -->
-    <!--                                                             -->
-    <!-- Normally only one type of deployer need be used.            -->
-    <!--                                                             -->
-    <!-- =========================================================== -->
-    <Call name="addLifeCycle">
-      <Arg>
-        <New class="org.mortbay.jetty.deployer.WebAppDeployer">
-          <Set name="contexts"><Ref id="Contexts"/></Set>
-          <Set name="webAppDir"><SystemProperty name="jetty.home" default="."/>/apps</Set>
-	  <Set name="parentLoaderPriority">false</Set>
-	  <Set name="extract">true</Set>
-	  <Set name="allowDuplicates">false</Set>
-          <Set name="defaultsDescriptor"><SystemProperty name="jetty.home" default="."/>/conf/webdefault.xml</Set>
-        </New>
-      </Arg>
-    </Call>
-
-    <!-- =========================================================== -->
-    <!-- Configure Request Log                                       -->
-    <!-- Request logs  may be configured for the entire server here, -->
-    <!-- or they can be configured for a specific web app in a       -->
-    <!-- contexts configuration (see $(jetty.home)/contexts/test.xml -->
-    <!-- for an example).                                            -->
-    <!-- =========================================================== -->
-    <Ref id="RequestLog">
-      <Set name="requestLog">
-        <New id="RequestLogImpl" class="org.mortbay.jetty.NCSARequestLog">
-          <Set name="filename"><SystemProperty name="jetty.logs" default="./logs"/>/yyyy_mm_dd.request.log</Set>
-          <Set name="filenameDateFormat">yyyy_MM_dd</Set>
-          <Set name="retainDays">90</Set>
-          <Set name="append">true</Set>
-          <Set name="extended">true</Set>
-          <Set name="logCookies">false</Set>
-          <Set name="LogTimeZone">GMT</Set>
-        </New>
-      </Set>
-    </Ref>
 
     <!-- =========================================================== -->
     <!-- extra options                                               -->
@@ -203,142 +91,7 @@
     <Set name="sendServerVersion">true</Set>
     <Set name="sendDateHeader">true</Set>
     <Set name="gracefulShutdown">1000</Set>
+    <Set name="dumpAfterStart">false</Set>
+    <Set name="dumpBeforeStop">false</Set>
 
-
- 
- <!-- =========================================================== -->
-  <!-- JNDI java:comp/env                                          -->
-  <!-- To use JNDI with Jetty, you will need to tell your          -->
-  <!-- WebAppContext to process the naming related items in        -->
-  <!-- web.xml. For an example of how to do that, see the test     -->
-  <!-- webapp below. More information can be found at              -->
-  <!-- http://docs.codehaus.org/display/JETTY/Jetty+Wiki           -->
-  <!-- =========================================================== -->
-
-
-  <!-- Configuring <resource-ref> and <resource-env-ref>s          -->
-  <!--                                                             -->
-  <!-- The following are examples of setting up a resource that   -->
-  <!-- can be referenced in a web.xml file as a <resource-ref> or  -->
-  <!-- a <resource-env-ref>. The first argument is the name of the -->
-  <!-- resource relative to java:comp/env and must be the SAME as  -->
-  <!-- the <res-ref-name> or <resource-env-ref-name> in web.xml.   -->
-  <!-- The second argument is the construction of the resource     -->
-  <!-- object. Any object at all can be configured.                -->
-
-
-  <!-- These examples set up a javax.sql.DataSource around an      -->
-  <!-- XADataSource that is provided by the Derby relational db.   -->
-  <!-- The DataSource wrapper that is registered in JNDI is        -->
-  <!--  provided by Atomikos, and works with the Atomikos          -->
-  <!-- transaction manager configured further below. To use these  -->
-  <!-- examples, download Atomikos http://www.atomikos.com and     -->
-  <!-- Derby http://db.apache.org/derby                            -->
-
-
-  <!-- Configuring Transactions                                    -->
-  <!--                                                             -->
-  <!-- The following is a example of a setting up a JTA            -->
-  <!-- transaction manager that can be referenced by looking up    -->
-  <!-- java:comp/UserTransaction. Note that this is just an        -->
-  <!-- example and if you uncomment it, you will need to download  -->
-  <!-- the atomikos jar (see http://www.atomikos.com/download.html)-->
-  <!-- You can configure any transaction manager that implements   -->
-  <!-- javax.transaction.UserTransaction.                          -->
-
-
-
-  <!-- =========================================================== -->
-  <!-- Configurations for WebAppContexts                           -->
-  <!-- Sequence of configurations to be applied to a webapp.       -->
-  <!-- =========================================================== -->
-  <Array id="plusConfig" type="java.lang.String">
-    <Item>org.mortbay.jetty.webapp.WebInfConfiguration</Item>
-    <Item>org.mortbay.jetty.plus.webapp.EnvConfiguration</Item>
-    <Item>org.mortbay.jetty.plus.webapp.Configuration</Item>
-    <Item>org.mortbay.jetty.webapp.JettyWebXmlConfiguration</Item>
-    <Item>org.mortbay.jetty.webapp.TagLibConfiguration</Item>
-  </Array>
-
-  <!-- =========================================================== -->
-  <!-- Deploy all webapps in webapps-plus                          -->
-  <!-- =========================================================== -->
-  <Call class="org.mortbay.jetty.webapp.WebAppContext" name="addWebApplications">
-    <Arg><Ref id="Contexts"/></Arg>
-    <Arg>./apps</Arg>
-    <Arg>org/mortbay/jetty/webapp/webdefault.xml</Arg>
-    <Arg><Ref id="plusConfig"/></Arg>
-    <Arg type="boolean">True</Arg>
-    <Arg type="boolean">False</Arg>
-  </Call>
-  
-  
-  <!-- continuum configuration -->
-  <!-- START SNIPPET: mail -->
-  <New id="validation_mail" class="org.mortbay.jetty.plus.naming.Resource">
-    <Arg>mail/Session</Arg>
-    <Arg>
-      <New class="org.mortbay.naming.factories.MailSessionReference">
-        <Set name="user"></Set>
-        <Set name="password"></Set>
-        <Set name="properties">
-          <New class="java.util.Properties">
-            <Put name="mail.smtp.host">localhost</Put>
-          </New>
-        </Set>
-      </New>
-    </Arg>
-  </New>
-  <!-- END SNIPPET: mail -->
-  
-  <!-- START SNIPPET: datasources -->  
-  <!-- continuum database -->
-   
-  <New id="continuum" class="org.mortbay.jetty.plus.naming.Resource">
-    <Arg>jdbc/continuum</Arg>
-    <Arg>
-      <New class="org.apache.derby.jdbc.EmbeddedDataSource">
-        <Set name="DatabaseName"><SystemProperty name="appserver.base" default=".."/>/data/databases/continuum</Set>
-        <Set name="user">sa</Set>
-        <Set name="createDatabase">create</Set>
-      </New>
-    </Arg>
-  </New>
-
-  <New id="continuumShutdown" class="org.mortbay.jetty.plus.naming.Resource">
-    <Arg>jdbc/continuumShutdown</Arg>
-    <Arg>
-      <New class="org.apache.derby.jdbc.EmbeddedDataSource">
-        <Set name="DatabaseName"><SystemProperty name="appserver.base" default=".."/>/data/databases/continuum</Set>
-        <Set name="user">sa</Set>
-        <Set name="shutdownDatabase">shutdown</Set>
-      </New>
-    </Arg>
-  </New>
- 
-  <!-- Users / Security Database -->
-  
-  <New id="users" class="org.mortbay.jetty.plus.naming.Resource">
-    <Arg>jdbc/users</Arg>
-    <Arg>
-      <New class="org.apache.derby.jdbc.EmbeddedDataSource">
-        <Set name="DatabaseName"><SystemProperty name="appserver.base" default=".."/>/data/databases/users</Set>
-        <Set name="user">sa</Set>
-        <Set name="createDatabase">create</Set>
-      </New>
-    </Arg>
-  </New>
-
-  <New id="usersShutdown" class="org.mortbay.jetty.plus.naming.Resource">
-    <Arg>jdbc/usersShutdown</Arg>
-    <Arg>
-      <New class="org.apache.derby.jdbc.EmbeddedDataSource">
-        <Set name="DatabaseName"><SystemProperty name="appserver.base" default=".."/>/data/databases/users</Set>
-        <Set name="user">sa</Set>
-        <Set name="shutdownDatabase">shutdown</Set>
-      </New>
-    </Arg>
-  </New>
-  
-  <!-- END SNIPPET: datasources -->  
 </Configure>
diff --git a/continuum-jetty/src/main/conf/shared.xml b/continuum-jetty/src/main/conf/shared.xml
index 22850c1..0240149 100755
--- a/continuum-jetty/src/main/conf/shared.xml
+++ b/continuum-jetty/src/main/conf/shared.xml
@@ -1,20 +1,21 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
-<configuration />
+  ~ 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.
+  -->
+<configuration/>
diff --git a/continuum-jetty/src/main/conf/webdefault.xml b/continuum-jetty/src/main/conf/webdefault.xml
index 5604d03..213138b 100755
--- a/continuum-jetty/src/main/conf/webdefault.xml
+++ b/continuum-jetty/src/main/conf/webdefault.xml
@@ -1,132 +1,126 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<!--
-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
+<?xml version="1.0" encoding="ISO-8859-1"?>
 
-  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.
--->
-
-<!-- ===================================================================== -->
-<!-- This file contains the default descriptor for web applications.       -->
-<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
-<!-- The intent of this descriptor is to include jetty specific or common  -->
-<!-- configuration for all webapps.   If a context has a webdefault.xml    -->
-<!-- descriptor, it is applied before the contexts own web.xml file        -->
-<!--                                                                       -->
-<!-- A context may be assigned a default descriptor by:                    -->
-<!--  + Calling WebApplicationContext.setDefaultsDescriptor                -->
-<!--  + Passed an arg to addWebApplications                                -->
-<!--                                                                       -->
-<!-- This file is used both as the resource within the jetty.jar (which is -->
-<!-- used as the default if no explicit defaults descriptor is set) and it -->
-<!-- is copied to the etc directory of the Jetty distro and explicitly     -->
-<!-- by the jetty.xml file.                                                -->
-<!--                                                                       -->
-<!-- ===================================================================== -->
-<web-app 
-   xmlns="http://java.sun.com/xml/ns/javaee" 
-   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
-   metadata-complete="true"
-   version="2.5"> 
+  <!-- ===================================================================== -->
+  <!-- This file contains the default descriptor for web applications.       -->
+  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+  <!-- The intent of this descriptor is to include jetty specific or common  -->
+  <!-- configuration for all webapps.   If a context has a webdefault.xml    -->
+  <!-- descriptor, it is applied before the contexts own web.xml file        -->
+  <!--                                                                       -->
+  <!-- A context may be assigned a default descriptor by:                    -->
+  <!--  + Calling WebApplicationContext.setDefaultsDescriptor                -->
+  <!--  + Passed an arg to addWebApplications                                -->
+  <!--                                                                       -->
+  <!-- This file is used both as the resource within the jetty.jar (which is -->
+  <!-- used as the default if no explicit defaults descriptor is set) and it -->
+  <!-- is copied to the etc directory of the Jetty distro and explicitly     -->
+  <!-- by the jetty.xml file.                                                -->
+  <!--                                                                       -->
+  <!-- ===================================================================== -->
+<web-app
+  xmlns="http://java.sun.com/xml/ns/javaee"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+  metadata-complete="true"
+  version="2.5"
+>
 
   <description>
     Default web.xml file.  
     This file is applied to a Web application before it's own WEB_INF/web.xml file
   </description>
 
+  <!-- ==================================================================== -->
+  <!-- Removes static references to beans from javax.el.BeanELResolver to   -->
+  <!-- ensure webapp classloader can be released on undeploy                -->
+  <!-- ==================================================================== -->
+  <listener>
+   <listener-class>org.eclipse.jetty.servlet.listener.ELContextCleaner</listener-class>
+  </listener>
+  
+  <!-- ==================================================================== -->
+  <!-- Removes static cache of Methods from java.beans.Introspector to      -->
+  <!-- ensure webapp classloader can be released on undeploy                -->
+  <!-- ==================================================================== -->  
+  <listener>
+   <listener-class>org.eclipse.jetty.servlet.listener.IntrospectorCleaner</listener-class>
+  </listener>
+  
 
   <!-- ==================================================================== -->
   <!-- Context params to control Session Cookies                            -->
   <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
-  <!-- UNCOMMENT TO ACTIVATE
-  <context-param>
-    <param-name>org.mortbay.jetty.servlet.SessionDomain</param-name>
-    <param-value>127.0.0.1</param-value>
-  </context-param>
-
-  <context-param>
-    <param-name>org.mortbay.jetty.servlet.SessionPath</param-name>
-    <param-value>/</param-value>
-  </context-param>
-
-  <context-param>
-    <param-name>org.mortbay.jetty.servlet.MaxAge</param-name>
-    <param-value>-1</param-value>
-  </context-param>
+  <!--
+    UNCOMMENT TO ACTIVATE <context-param> <param-name>org.eclipse.jetty.servlet.SessionDomain</param-name> <param-value>127.0.0.1</param-value> </context-param> <context-param>
+    <param-name>org.eclipse.jetty.servlet.SessionPath</param-name> <param-value>/</param-value> </context-param> <context-param> <param-name>org.eclipse.jetty.servlet.MaxAge</param-name>
+    <param-value>-1</param-value> </context-param>
   -->
 
-  <context-param>
-    <param-name>org.mortbay.jetty.webapp.NoTLDJarPattern</param-name>
-    <param-value>start.jar|ant-.*\.jar|dojo-.*\.jar|jetty-.*\.jar|jsp-api-.*\.jar|junit-.*\.jar|servlet-api-.*\.jar|dnsns\.jar|rt\.jar|jsse\.jar|tools\.jar|sunpkcs11\.jar|sunjce_provider\.jar|xerces.*\.jar</param-value>
-  </context-param>
-            
-
-
   <!-- ==================================================================== -->
   <!-- The default servlet.                                                 -->
   <!-- This servlet, normally mapped to /, provides the handling for static -->
   <!-- content, OPTIONS and TRACE methods for the context.                  -->
   <!-- The following initParameters are supported:                          -->
-  <!--                                                                      -->
-  <!--   acceptRanges     If true, range requests and responses are         -->
-  <!--                    supported                                         -->
-  <!--                                                                      -->
-  <!--   dirAllowed       If true, directory listings are returned if no    -->
-  <!--                    welcome file is found. Else 403 Forbidden.        -->
-  <!--                                                                      -->
-  <!--   redirectWelcome  If true, redirect welcome file requests           -->
-  <!--                    else use request dispatcher forwards              -->
-  <!--                                                                      -->
-  <!--   gzip             If set to true, then static content will be served--> 
-  <!--                    as gzip content encoded if a matching resource is -->
-  <!--                    found ending with ".gz"                           -->
-  <!--                                                                      -->
-  <!--   resoureBase      Can be set to replace the context resource base   -->
-  <!--                                                                      -->
-  <!--   relativeResourceBase                                               -->
-  <!--                    Set with a pathname relative to the base of the   -->
-  <!--                    servlet context root. Useful for only serving     -->
-  <!--                    static content from only specific subdirectories. -->
-  <!--                                                                      -->
-  <!--   useFileMappedBuffer                                                -->
-  <!--                    If set to true (the default), a  memory mapped    -->
-  <!--                    file buffer will be used to serve static content  -->
-  <!--                    when using an NIO connector. Setting this value   -->
-  <!--                    to false means that a direct buffer will be used  -->
-  <!--                    instead. If you are having trouble with Windows   -->
-  <!--                    file locking, set this to false.                  -->
-  <!--                                                                      -->
-  <!--  cacheControl      If set, all static content will have this value   -->
-  <!--                    set as the cache-control header.                  -->
-  <!--                                                                      -->
-  <!--  maxCacheSize      Maximum size of the static resource cache         -->
-  <!--                                                                      -->
-  <!--  maxCachedFileSize Maximum size of any single file in the cache      -->
-  <!--                                                                      -->
-  <!--  maxCachedFiles    Maximum number of files in the cache              -->
-  <!--                                                                      -->
-  <!--  cacheType         "nio", "bio" or "both" to determine the type(s)   -->
-  <!--                    of resource cache. A bio cached buffer may be used-->
-  <!--                    by nio but is not as efficient as a nio buffer.   -->
-  <!--                    An nio cached buffer may not be used by bio.      -->
-  <!--                                                                      -->
+  <!--  
+ *  acceptRanges      If true, range requests and responses are
+ *                    supported
+ *
+ *  dirAllowed        If true, directory listings are returned if no
+ *                    welcome file is found. Else 403 Forbidden.
+ *
+ *  welcomeServlets   If true, attempt to dispatch to welcome files
+ *                    that are servlets, but only after no matching static
+ *                    resources could be found. If false, then a welcome
+ *                    file must exist on disk. If "exact", then exact
+ *                    servlet matches are supported without an existing file.
+ *                    Default is true.
+ *
+ *                    This must be false if you want directory listings,
+ *                    but have index.jsp in your welcome file list.
+ *
+ *  redirectWelcome   If true, welcome files are redirected rather than
+ *                    forwarded to.
+ *
+ *  gzip              If set to true, then static content will be served as
+ *                    gzip content encoded if a matching resource is
+ *                    found ending with ".gz"
+ *
+ *  resourceBase      Set to replace the context resource base
+ *
+ *  resourceCache     If set, this is a context attribute name, which the servlet 
+ *                    will use to look for a shared ResourceCache instance. 
+ *                        
+ *  relativeResourceBase
+ *                    Set with a pathname relative to the base of the
+ *                    servlet context root. Useful for only serving static content out
+ *                    of only specific subdirectories.
+ *
+ *  aliases           If True, aliases of resources are allowed (eg. symbolic
+ *                    links and caps variations). May bypass security constraints.
+ *
+ *  maxCacheSize      The maximum total size of the cache or 0 for no cache.
+ *  maxCachedFileSize The maximum size of a file to cache
+ *  maxCachedFiles    The maximum number of files to cache
+ *
+ *  useFileMappedBuffer
+ *                    If set to true, it will use mapped file buffer to serve static content
+ *                    when using NIO connector. Setting this value to false means that
+ *                    a direct buffer will be used instead of a mapped file buffer.
+ *                    By default, this is set to true.
+ *
+ *  cacheControl      If set, all static content will have this value set as the cache-control
+ *                    header.
+ -->
+ 
+ 
   <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
   <servlet>
     <servlet-name>default</servlet-name>
-    <servlet-class>org.mortbay.jetty.servlet.DefaultServlet</servlet-class>
+    <servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class>
+    <init-param>
+      <param-name>aliases</param-name>
+      <param-value>false</param-value>
+    </init-param>
     <init-param>
       <param-name>acceptRanges</param-name>
       <param-value>true</param-value>
@@ -136,6 +130,10 @@
       <param-value>true</param-value>
     </init-param>
     <init-param>
+      <param-name>welcomeServlets</param-name>
+      <param-value>false</param-value>
+    </init-param>
+    <init-param>
       <param-name>redirectWelcome</param-name>
       <param-value>false</param-value>
     </init-param>
@@ -145,15 +143,11 @@
     </init-param>
     <init-param>
       <param-name>maxCachedFileSize</param-name>
-      <param-value>10000000</param-value>
+      <param-value>200000000</param-value>
     </init-param>
     <init-param>
       <param-name>maxCachedFiles</param-name>
-      <param-value>1000</param-value>
-    </init-param>
-    <init-param>
-      <param-name>cacheType</param-name>
-      <param-value>both</param-value>
+      <param-value>2048</param-value>
     </init-param>
     <init-param>
       <param-name>gzip</param-name>
@@ -162,7 +156,13 @@
     <init-param>
       <param-name>useFileMappedBuffer</param-name>
       <param-value>true</param-value>
-    </init-param>  
+    </init-param>
+    <!--
+    <init-param>
+      <param-name>resourceCache</param-name>
+      <param-value>resourceCache</param-value>
+    </init-param>
+    -->
     <!--
     <init-param>
       <param-name>cacheControl</param-name>
@@ -170,10 +170,13 @@
     </init-param>
     -->
     <load-on-startup>0</load-on-startup>
-  </servlet> 
+  </servlet>
 
-  <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
-  
+  <servlet-mapping>
+    <servlet-name>default</servlet-name>
+    <url-pattern>/</url-pattern>
+  </servlet-mapping>
+
 
   <!-- ==================================================================== -->
   <!-- JSP Servlet                                                          -->
@@ -260,20 +263,22 @@
   <!--   If you get an error reporting that jikes can't use UTF-8 encoding, -->
   <!--   try setting the init parameter "javaEncoding" to "ISO-8859-1".     -->
   <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
-  <servlet id="jsp">
+  <servlet
+    id="jsp"
+  >
     <servlet-name>jsp</servlet-name>
     <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
     <init-param>
-        <param-name>logVerbosityLevel</param-name>
-        <param-value>DEBUG</param-value>
+      <param-name>logVerbosityLevel</param-name>
+      <param-value>DEBUG</param-value>
     </init-param>
     <init-param>
-        <param-name>fork</param-name>
-        <param-value>false</param-value>
+      <param-name>fork</param-name>
+      <param-value>false</param-value>
     </init-param>
     <init-param>
-        <param-name>xpoweredBy</param-name>
-        <param-value>false</param-value>
+      <param-name>xpoweredBy</param-name>
+      <param-value>false</param-value>
     </init-param>
     <!--  
     <init-param>
@@ -284,18 +289,18 @@
     <load-on-startup>0</load-on-startup>
   </servlet>
 
-  <servlet-mapping> 
-    <servlet-name>jsp</servlet-name> 
-    <url-pattern>*.jsp</url-pattern> 
+  <servlet-mapping>
+    <servlet-name>jsp</servlet-name>
+    <url-pattern>*.jsp</url-pattern>
     <url-pattern>*.jspf</url-pattern>
     <url-pattern>*.jspx</url-pattern>
     <url-pattern>*.xsp</url-pattern>
-    <url-pattern>*.JSP</url-pattern> 
+    <url-pattern>*.JSP</url-pattern>
     <url-pattern>*.JSPF</url-pattern>
     <url-pattern>*.JSPX</url-pattern>
     <url-pattern>*.XSP</url-pattern>
   </servlet-mapping>
-  
+
   <!-- ==================================================================== -->
   <!-- Dynamic Servlet Invoker.                                             -->
   <!-- This servlet invokes anonymous servlets that have not been defined   -->
@@ -315,26 +320,11 @@
   <!--  *                        All other parameters are copied to the     -->
   <!--                           each dynamic servlet as init parameters    -->
   <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
-  <!-- Uncomment for dynamic invocation
-  <servlet>
-    <servlet-name>invoker</servlet-name>
-    <servlet-class>org.mortbay.jetty.servlet.Invoker</servlet-class>
-    <init-param>
-      <param-name>verbose</param-name>
-      <param-value>false</param-value>
-    </init-param>
-    <init-param>
-      <param-name>nonContextServlets</param-name>
-      <param-value>false</param-value>
-    </init-param>
-    <init-param>
-      <param-name>dynamicParam</param-name>
-      <param-value>anyValue</param-value>
-    </init-param>
-    <load-on-startup>0</load-on-startup>
-  </servlet>
-
-  <servlet-mapping> <servlet-name>invoker</servlet-name> <url-pattern>/servlet/*</url-pattern> </servlet-mapping>
+  <!--
+    Uncomment for dynamic invocation <servlet> <servlet-name>invoker</servlet-name> <servlet-class>org.eclipse.jetty.servlet.Invoker</servlet-class> <init-param> <param-name>verbose</param-name>
+    <param-value>false</param-value> </init-param> <init-param> <param-name>nonContextServlets</param-name> <param-value>false</param-value> </init-param> <init-param>
+    <param-name>dynamicParam</param-name> <param-value>anyValue</param-value> </init-param> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>invoker</servlet-name>
+    <url-pattern>/servlet/*</url-pattern> </servlet-mapping>
   -->
 
 
@@ -347,7 +337,7 @@
   <!-- ==================================================================== -->
   <!-- Default MIME mappings                                                -->
   <!-- The default MIME mappings are provided by the mime.properties        -->
-  <!-- resource in the org.mortbay.jetty.jar file.  Additional or modified  -->
+  <!-- resource in the org.eclipse.jetty.server.jar file.  Additional or modified  -->
   <!-- mappings may be specified here                                       -->
   <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
   <!-- UNCOMMENT TO ACTIVATE
@@ -366,47 +356,164 @@
 
   <!-- ==================================================================== -->
   <locale-encoding-mapping-list>
-    <locale-encoding-mapping><locale>ar</locale><encoding>ISO-8859-6</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>be</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>bg</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>ca</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>cs</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>da</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>de</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>el</locale><encoding>ISO-8859-7</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>en</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>es</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>et</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>fi</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>fr</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>hr</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>hu</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>is</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>it</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>iw</locale><encoding>ISO-8859-8</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>ja</locale><encoding>Shift_JIS</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>ko</locale><encoding>EUC-KR</encoding></locale-encoding-mapping>     
-    <locale-encoding-mapping><locale>lt</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>lv</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>mk</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>nl</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>no</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>pl</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>pt</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>ro</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>ru</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>sh</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>sk</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>sl</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>sq</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>sr</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>sv</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>tr</locale><encoding>ISO-8859-9</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>uk</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>zh</locale><encoding>GB2312</encoding></locale-encoding-mapping>
-    <locale-encoding-mapping><locale>zh_TW</locale><encoding>Big5</encoding></locale-encoding-mapping>   
+    <locale-encoding-mapping>
+      <locale>ar</locale>
+      <encoding>ISO-8859-6</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>be</locale>
+      <encoding>ISO-8859-5</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>bg</locale>
+      <encoding>ISO-8859-5</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>ca</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>cs</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>da</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>de</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>el</locale>
+      <encoding>ISO-8859-7</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>en</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>es</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>et</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>fi</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>fr</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>hr</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>hu</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>is</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>it</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>iw</locale>
+      <encoding>ISO-8859-8</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>ja</locale>
+      <encoding>Shift_JIS</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>ko</locale>
+      <encoding>EUC-KR</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>lt</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>lv</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>mk</locale>
+      <encoding>ISO-8859-5</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>nl</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>no</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>pl</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>pt</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>ro</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>ru</locale>
+      <encoding>ISO-8859-5</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>sh</locale>
+      <encoding>ISO-8859-5</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>sk</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>sl</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>sq</locale>
+      <encoding>ISO-8859-2</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>sr</locale>
+      <encoding>ISO-8859-5</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>sv</locale>
+      <encoding>ISO-8859-1</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>tr</locale>
+      <encoding>ISO-8859-9</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>uk</locale>
+      <encoding>ISO-8859-5</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>zh</locale>
+      <encoding>GB2312</encoding>
+    </locale-encoding-mapping>
+    <locale-encoding-mapping>
+      <locale>zh_TW</locale>
+      <encoding>Big5</encoding>
+    </locale-encoding-mapping>
   </locale-encoding-mapping-list>
-  
+
   <security-constraint>
     <web-resource-collection>
       <web-resource-name>Disable TRACE</web-resource-name>
@@ -415,6 +522,6 @@
     </web-resource-collection>
     <auth-constraint/>
   </security-constraint>
-  
+
 </web-app>
 
diff --git a/continuum-jetty/src/main/contexts/continuum.xml b/continuum-jetty/src/main/contexts/continuum.xml
new file mode 100644
index 0000000..05e7bbd
--- /dev/null
+++ b/continuum-jetty/src/main/contexts/continuum.xml
@@ -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.
+  -->
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
+
+<Configure id='wac' class="org.eclipse.jetty.webapp.WebAppContext">
+
+  <Set name="contextPath">/continuum</Set>
+  <Set name="war"><Property name="jetty.home" default="."/>/apps/continuum</Set>
+
+  <Set name="extractWAR">false</Set>
+  <Set name="copyWebDir">false</Set>
+
+  <!-- START SNIPPET: mail -->
+  <New id="validation_mail" class="org.eclipse.jetty.plus.jndi.Resource">
+    <Arg><Ref id="wac"/></Arg>
+    <Arg>mail/Session</Arg>
+    <Arg>
+      <New class="org.eclipse.jetty.jndi.factories.MailSessionReference">
+        <Set name="user"></Set>
+        <Set name="password"></Set>
+        <Set name="properties">
+          <New class="java.util.Properties">
+            <Put name="mail.smtp.host">localhost</Put>
+          </New>
+        </Set>
+      </New>
+    </Arg>
+  </New>
+  <!-- END SNIPPET: mail -->
+
+  <!-- START SNIPPET: datasources -->
+  <!-- continuum database -->
+
+  <New id="continuum" class="org.eclipse.jetty.plus.jndi.Resource">
+    <Arg><Ref id="wac"/></Arg>
+    <Arg>jdbc/continuum</Arg>
+    <Arg>
+      <New class="org.apache.commons.dbcp.BasicDataSource">
+        <Set name="driverClassName">org.apache.derby.jdbc.EmbeddedDriver</Set>
+        <Set name="url">jdbc:derby:<Property name="appserver.base" default="."/>/data/databases/continuum;create=true</Set>
+        <Set name="username">SA</Set>
+        <Set name="password"></Set>
+        <Set name="testOnBorrow">true</Set>
+        <Set name="validationQuery">SELECT count(*) FROM SYS.SYSTABLES</Set>
+      </New>
+    </Arg>
+  </New>
+
+  <!-- Users / Security Database -->
+
+  <New id="users" class="org.eclipse.jetty.plus.jndi.Resource">
+    <Arg><Ref id="wac"/></Arg>
+    <Arg>jdbc/users</Arg>
+    <Arg>
+      <New class="org.apache.commons.dbcp.BasicDataSource">
+        <Set name="driverClassName">org.apache.derby.jdbc.EmbeddedDriver</Set>
+        <Set name="url">jdbc:derby:<Property name="appserver.base" default="."/>/data/databases/users;create=true</Set>
+        <Set name="username">SA</Set>
+        <Set name="password"></Set>
+        <Set name="testOnBorrow">true</Set>
+        <Set name="validationQuery">SELECT count(*) FROM SYS.SYSTABLES</Set>
+      </New>
+    </Arg>
+  </New>
+
+  <!-- END SNIPPET: datasources -->
+</Configure>
diff --git a/continuum-webapp/src/main/resources/template/default/empty.ftl b/continuum-jetty/src/main/tmp/.gitignore
similarity index 100%
copy from continuum-webapp/src/main/resources/template/default/empty.ftl
copy to continuum-jetty/src/main/tmp/.gitignore
diff --git a/continuum-model/pom.xml b/continuum-model/pom.xml
index e8f7678..d53fab6 100644
--- a/continuum-model/pom.xml
+++ b/continuum-model/pom.xml
@@ -1,27 +1,28 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
+  ~ 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.
+  -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <artifactId>continuum</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>continuum-model</artifactId>
@@ -34,44 +35,27 @@
         <executions>
           <execution>
             <id>modello-continuum</id>
-            <phase>initialize</phase>
+            <phase>generate-sources</phase>
             <goals>
               <goal>java</goal>
               <goal>stax-reader</goal>
               <goal>stax-writer</goal>
-              <goal>jpox-metadata-class</goal>
             </goals>
           </execution>
-          <execution>
-            <id>jpox-jdo-mapping</id>
-            <goals>
-              <goal>jpox-jdo-mapping</goal>
-            </goals>
-            <configuration>
-              <outputDirectory>${basedir}/target/classes/META-INF</outputDirectory>
-            </configuration>
-          </execution>
-          <execution>
-            <id>jpox-jdo-mapping-replication</id>
-            <goals>
-              <goal>jpox-jdo-mapping</goal>
-            </goals>
-            <configuration>
-              <outputDirectory>${basedir}/target/classes/META-INF</outputDirectory>
-              <replicationParameters>true</replicationParameters>
-            </configuration>
-          </execution>
         </executions>
         <configuration>
-          <version>1.1.3</version>
+          <version>1.4.1</version>
           <packageWithVersion>false</packageWithVersion>
-          <model>src/main/mdo/continuum.xml</model>
+          <models>
+            <model>src/main/mdo/continuum.xml</model>
+            <model>src/main/mdo/prepared-releases.mdo</model>
+          </models>
+          <useJava5>true</useJava5>
         </configuration>
       </plugin>
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>jpox-maven-plugin</artifactId>
-        <version>1.1.6</version>
         <executions>
           <execution>
             <goals>
@@ -80,24 +64,54 @@
           </execution>
         </executions>
       </plugin>
+      <plugin>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>copy-resources</id>
+            <phase>process-resources</phase>
+            <configuration>
+              <tasks>
+                <copy file="target/classes/META-INF/package.jdorepl" todir="target/classes" />
+                <copy file="target/classes/META-INF/package.jdo" todir="target/classes" />
+              </tasks>
+            </configuration>
+            <goals>
+              <goal>run</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>com.google.code.maven-replacer-plugin</groupId>
+        <artifactId>replacer</artifactId>
+        <executions>
+          <execution>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>replace</goal>
+            </goals>
+            <configuration>
+              <basedir>${basedir}</basedir>
+              <includes>
+                <include>target/generated-sources/**</include>
+              </includes>
+              <token>Generated by Modello.*</token>
+              <value>Generated by Modello</value>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
     </plugins>
   </build>
   <dependencies>
     <dependency>
       <groupId>net.java.dev.stax-utils</groupId>
       <artifactId>stax-utils</artifactId>
-      <version>20060502</version>
-      <exclusions>
-        <exclusion>
-          <groupId>com.bea.xml</groupId>
-          <artifactId>jsr173-ri</artifactId>
-        </exclusion>
-      </exclusions>
     </dependency>
     <dependency>
       <groupId>stax</groupId>
       <artifactId>stax-api</artifactId>
-      <version>1.0.1</version>
     </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
diff --git a/continuum-model/src/main/java/org/apache/continuum/model/project/ProjectGroupSummary.java b/continuum-model/src/main/java/org/apache/continuum/model/project/ProjectGroupSummary.java
new file mode 100644
index 0000000..382d2af
--- /dev/null
+++ b/continuum-model/src/main/java/org/apache/continuum/model/project/ProjectGroupSummary.java
@@ -0,0 +1,112 @@
+package org.apache.continuum.model.project;
+
+/*
+ * 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.
+ */
+
+public class ProjectGroupSummary
+{
+    private int projectGroupId;
+
+    private int numberOfSuccesses;
+
+    private int numberOfFailures;
+
+    private int numberOfErrors;
+
+    private int numberOfProjects;
+
+    public ProjectGroupSummary()
+    {
+    }
+
+    public ProjectGroupSummary( int projectGroupId )
+    {
+        this.projectGroupId = projectGroupId;
+    }
+
+    public int getProjectGroupId()
+    {
+        return projectGroupId;
+    }
+
+    public void setProjectGroupId( int projectGroupId )
+    {
+        this.projectGroupId = projectGroupId;
+    }
+
+    public void setNumberOfSuccesses( int numberOfSuccesses )
+    {
+        this.numberOfSuccesses = numberOfSuccesses;
+    }
+
+    public int getNumberOfSuccesses()
+    {
+        return numberOfSuccesses;
+    }
+
+    public void setNumberOfFailures( int numberOfFailures )
+    {
+        this.numberOfFailures = numberOfFailures;
+    }
+
+    public int getNumberOfFailures()
+    {
+        return numberOfFailures;
+    }
+
+    public void setNumberOfErrors( int numberOfErrors )
+    {
+        this.numberOfErrors = numberOfErrors;
+    }
+
+    public int getNumberOfErrors()
+    {
+        return numberOfErrors;
+    }
+
+    public void setNumberOfProjects( int numberOfProjects )
+    {
+        this.numberOfProjects = numberOfProjects;
+    }
+
+    public int getNumberOfProjects()
+    {
+        return numberOfProjects;
+    }
+
+    public void addProjects( int projects )
+    {
+        this.numberOfProjects += projects;
+    }
+
+    public void addNumberOfSuccesses( int numberOfSuccesses )
+    {
+        this.numberOfSuccesses += numberOfSuccesses;
+    }
+
+    public void addNumberOfErrors( int numberOfErrors )
+    {
+        this.numberOfErrors += numberOfErrors;
+    }
+
+    public void addNumberOfFailures( int numberOfFailures )
+    {
+        this.numberOfFailures += numberOfFailures;
+    }
+}
diff --git a/continuum-model/src/main/java/org/apache/continuum/model/project/ProjectRunSummary.java b/continuum-model/src/main/java/org/apache/continuum/model/project/ProjectRunSummary.java
new file mode 100644
index 0000000..df68034
--- /dev/null
+++ b/continuum-model/src/main/java/org/apache/continuum/model/project/ProjectRunSummary.java
@@ -0,0 +1,107 @@
+package org.apache.continuum.model.project;
+
+/*
+ * 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.
+ */
+
+public class ProjectRunSummary
+{
+    private int projectId;
+
+    private int buildDefinitionId;
+
+    private int projectGroupId;
+
+    private int projectScmRootId;
+
+    private String buildAgentUrl;
+
+    private int trigger;
+
+    private String triggeredBy;
+
+    public int getProjectId()
+    {
+        return projectId;
+    }
+
+    public void setProjectId( int projectId )
+    {
+        this.projectId = projectId;
+    }
+
+    public int getBuildDefinitionId()
+    {
+        return buildDefinitionId;
+    }
+
+    public void setBuildDefinitionId( int buildDefinitionId )
+    {
+        this.buildDefinitionId = buildDefinitionId;
+    }
+
+    public int getProjectGroupId()
+    {
+        return projectGroupId;
+    }
+
+    public void setProjectGroupId( int projectGroupId )
+    {
+        this.projectGroupId = projectGroupId;
+    }
+
+    public int getProjectScmRootId()
+    {
+        return projectScmRootId;
+    }
+
+    public void setProjectScmRootId( int projectScmRootId )
+    {
+        this.projectScmRootId = projectScmRootId;
+    }
+
+    public String getBuildAgentUrl()
+    {
+        return buildAgentUrl;
+    }
+
+    public void setBuildAgentUrl( String buildAgentUrl )
+    {
+        this.buildAgentUrl = buildAgentUrl;
+    }
+
+    public int getTrigger()
+    {
+        return trigger;
+    }
+
+    public void setTrigger( int trigger )
+    {
+        this.trigger = trigger;
+    }
+
+    public String getTriggeredBy()
+    {
+        return triggeredBy;
+    }
+
+    public void setTriggeredBy( String triggeredBy )
+    {
+        this.triggeredBy = triggeredBy;
+    }
+}
diff --git a/continuum-model/src/main/java/org/apache/continuum/model/project/ProjectSummaryResult.java b/continuum-model/src/main/java/org/apache/continuum/model/project/ProjectSummaryResult.java
new file mode 100644
index 0000000..6858313
--- /dev/null
+++ b/continuum-model/src/main/java/org/apache/continuum/model/project/ProjectSummaryResult.java
@@ -0,0 +1,68 @@
+package org.apache.continuum.model.project;
+
+/*
+ * 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.
+ */
+
+public class ProjectSummaryResult
+{
+    private int projectGroupId;
+
+    private int projectState;
+
+    private long size;
+
+    public ProjectSummaryResult( int projectGroupId, int projectState, long size )
+    {
+        this.projectGroupId = projectGroupId;
+
+        this.projectState = projectState;
+
+        this.size = size;
+    }
+
+    public int getProjectGroupId()
+    {
+        return projectGroupId;
+    }
+
+    public void setProjectGroupId( int projectGroupId )
+    {
+        this.projectGroupId = projectGroupId;
+    }
+
+    public int getProjectState()
+    {
+        return projectState;
+    }
+
+    public void setProjectState( int projectState )
+    {
+        this.projectState = projectState;
+    }
+
+    public long getSize()
+    {
+        return size;
+    }
+
+    public void setSize( long size )
+    {
+        this.size = size;
+    }
+}
diff --git a/continuum-model/src/main/java/org/apache/continuum/model/release/ReleaseListenerSummary.java b/continuum-model/src/main/java/org/apache/continuum/model/release/ReleaseListenerSummary.java
new file mode 100644
index 0000000..5c596d2
--- /dev/null
+++ b/continuum-model/src/main/java/org/apache/continuum/model/release/ReleaseListenerSummary.java
@@ -0,0 +1,109 @@
+package org.apache.continuum.model.release;
+
+/*
+ * 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.List;
+
+public class ReleaseListenerSummary
+{
+    private String goalName;
+
+    private String error;
+
+    private String username;
+
+    private String inProgress;
+
+    private int state;
+
+    private List<String> phases;
+
+    public String getGoalName()
+    {
+        return goalName;
+    }
+
+    public void setGoalName( String goalName )
+    {
+        this.goalName = goalName;
+    }
+
+    public String getError()
+    {
+        return error;
+    }
+
+    public void setError( String error )
+    {
+        this.error = error;
+    }
+
+    public String getUsername()
+    {
+        return username;
+    }
+
+    public void setUsername( String username )
+    {
+        this.username = username;
+    }
+
+    public String getInProgress()
+    {
+        return inProgress;
+    }
+
+    public void setInProgress( String inProgress )
+    {
+        this.inProgress = inProgress;
+    }
+
+    public int getState()
+    {
+        return state;
+    }
+
+    public void setState( int state )
+    {
+        this.state = state;
+    }
+
+    public List<String> getPhases()
+    {
+        return phases;
+    }
+
+    public void setPhases( List<String> phases )
+    {
+        this.phases = phases;
+    }
+
+    public List<String> getCompletedPhases()
+    {
+        return completedPhases;
+    }
+
+    public void setCompletedPhases( List<String> completedPhases )
+    {
+        this.completedPhases = completedPhases;
+    }
+
+    private List<String> completedPhases;
+}
diff --git a/continuum-model/src/main/java/org/apache/maven/continuum/model/project/ContinuumModelloMetadata.java b/continuum-model/src/main/java/org/apache/maven/continuum/model/project/ContinuumModelloMetadata.java
new file mode 100644
index 0000000..2773c20
--- /dev/null
+++ b/continuum-model/src/main/java/org/apache/maven/continuum/model/project/ContinuumModelloMetadata.java
@@ -0,0 +1,36 @@
+package org.apache.maven.continuum.model.project;
+
+/*
+ * 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.
+ */
+
+public class ContinuumModelloMetadata
+{
+    private String modelVersion;
+
+    public String getModelVersion()
+    {
+        return modelVersion;
+    }
+
+    public void setModelVersion( String modelVersion )
+    {
+        this.modelVersion = modelVersion;
+    }
+}
+
diff --git a/continuum-model/src/main/mdo/continuum.xml b/continuum-model/src/main/mdo/continuum.xml
index f94a361..8e2a6bc 100644
--- a/continuum-model/src/main/mdo/continuum.xml
+++ b/continuum-model/src/main/mdo/continuum.xml
@@ -100,12 +100,56 @@
           </association>
         </field>
         <field>
+          <name>distributedDirectoryPurgeConfigurations</name>
+          <version>1.4.1+</version>
+          <association>
+            <type>DistributedDirectoryPurgeConfiguration</type>
+            <multiplicity>*</multiplicity>
+          </association>
+        </field>
+        <field>
           <name>projectScmRoots</name>
           <version>1.1.3+</version>
-          <association>
+          <association java.init="field">
             <type>ProjectScmRoot</type>
             <multiplicity>*</multiplicity>
           </association>
+          <defaultValue>new java.util.ArrayList()</defaultValue>
+        </field>
+        <field>
+          <name>continuumReleaseResults</name>
+          <version>1.1.3+</version>
+          <association java.init="field">
+            <type>ContinuumReleaseResult</type>
+            <multiplicity>*</multiplicity>
+          </association>
+          <defaultValue>new java.util.ArrayList()</defaultValue>
+        </field>
+        <field>
+          <name>buildDefinitionTemplates</name>
+          <version>1.1.3+</version>
+          <association java.init="field">
+            <type>BuildDefinitionTemplate</type>
+            <multiplicity>*</multiplicity>
+          </association>
+          <defaultValue>new java.util.ArrayList()</defaultValue>
+        </field>
+        <field>
+          <name>buildQueues</name>
+          <version>1.3.2+</version>
+          <association java.init="field">
+            <type>BuildQueue</type>
+            <multiplicity>*</multiplicity>
+          </association>
+          <defaultValue>new java.util.ArrayList()</defaultValue>
+        </field>
+        <field>
+          <name>buildDefinitions</name>
+          <version>1.3.3+</version>
+          <association java.init="field">
+            <type>BuildDefinition</type>
+            <multiplicity>*</multiplicity>
+          </association>
         </field>
       </fields>
     </class>
@@ -136,7 +180,8 @@
           <version>1.0.9+</version>
           <type>String</type>
         </field>
-        <field jpox.mapped-by="projectGroup" jpox.fetch-groups="projectgroup-projects project-build-details project-with-scm-result">
+        <field jpox.mapped-by="projectGroup"
+               jpox.fetch-groups="projectgroup-projects project-build-details project-with-scm-result">
           <name>projects</name>
           <version>1.0.9+</version>
           <association jpox.join="false">
@@ -281,6 +326,12 @@
           <version>1.1.0+</version>
           <type>String</type>
         </field>
+        <field jpox.null-value="default">
+          <name>checkedOutInSingleDirectory</name>
+          <version>1.4.1+</version>
+          <type>boolean</type>
+          <defaultValue>false</defaultValue>
+        </field>
         <field jpox.mapped-by="project" jpox.fetch-groups="project-with-builds">
           <name>buildResults</name>
           <version>1.0.9+</version>
@@ -343,13 +394,6 @@
             <type>BuildDefinition</type>
             <multiplicity>*</multiplicity>
           </association>
-        </field>     
-        <field jpox.fetch-groups="project-all-details project-with-scm-details">
-          <name>scmResult</name>
-          <version>1.1.3+</version>
-          <association>
-            <type>ScmResult</type>
-          </association>
         </field>
       </fields>
     </class>
@@ -556,6 +600,11 @@
           <version>1.0.9</version>
           <type>int</type>
         </field>
+        <field>
+          <name>username</name>
+          <version>1.4.0+</version>
+          <type>String</type>
+        </field>
         <field jpox.column="resultstate">
           <name>state</name>
           <version>1.1.0+</version>
@@ -609,6 +658,18 @@
             <multiplicity>*</multiplicity>
           </association>
         </field>
+        <field jpox.null-value="default">
+          <name>lastChangedDate</name>
+          <version>1.3.2+</version>
+          <type>long</type>
+          <defaultValue>0</defaultValue>
+        </field>
+        <field jpox.null-value="default">
+          <name>buildUrl</name>
+          <version>1.3.2+</version>
+          <type>String</type>
+          <defaultValue></defaultValue>
+        </field>
       </fields>
       <codeSegments>
         <codeSegment>
@@ -800,7 +861,7 @@
                     for ( java.util.Iterator i = files.iterator(); i.hasNext(); )
                     {
                         ChangeFile file = (ChangeFile) i.next();
-                        
+
                         if (file != null)
                         {
                             result.append( file ).append( "\n" );
@@ -945,7 +1006,7 @@
           <name>type</name>
           <version>1.1.0+</version>
           <type>String</type>
-          <description>type of the buid defintion</description>          
+          <description>type of the buid defintion</description>
         </field>
         <field>
           <name>schedule</name>
@@ -984,7 +1045,13 @@
           <description>
             true if this buildDefinition is a template
           </description>
-        </field>        
+        </field>
+        <field jpox.null-value="default">
+          <name>updatePolicy</name>
+          <version>1.4.0+</version>
+          <type>int</type>
+          <defaultValue>0</defaultValue>
+        </field>
       </fields>
     </class>
     <class>
@@ -1017,8 +1084,8 @@
           <name>type</name>
           <version>1.1.0+</version>
           <type>String</type>
-          <description>type of the buid BuildDefinitionTemplate use for default</description>          
-        </field>                                
+          <description>type of the buid BuildDefinitionTemplate use for default</description>
+        </field>
         <field xml.reference="true" stash.part="true" jpox.fetch-groups="build-template-build-definitions">
           <name>buildDefinitions</name>
           <version>1.1.0+</version>
@@ -1030,6 +1097,28 @@
       </fields>
     </class>
     <class>
+      <name>BuildQueue</name>
+      <version>1.1.4+</version>
+      <description><![CDATA[
+       Build queue.
+      ]]></description>
+      <fields>
+        <field>
+          <name>id</name>
+          <version>1.1.4+</version>
+          <identifier>true</identifier>
+          <type>int</type>
+        </field>
+        <field jpox.null-value="default">
+          <name>name</name>
+          <version>1.1.4+</version>
+          <type>String</type>
+          <required>true</required>
+          <defaultValue></defaultValue>
+        </field>
+      </fields>
+    </class>
+    <class>
       <name>Schedule</name>
       <version>1.0.9+</version>
       <description><![CDATA[
@@ -1088,6 +1177,15 @@
           <version>1.0.9+</version>
           <type>String</type>
         </field>
+        <field jpox.fetch-groups="schedule-build-queues" java.init="field">
+          <name>buildQueues</name>
+          <version>1.1.4+</version>
+          <association xml.reference="true" stash.part="true" jpox.dependent="false">
+            <type>BuildQueue</type>
+            <multiplicity>*</multiplicity>
+          </association>
+          <defaultValue>new java.util.ArrayList()</defaultValue>
+        </field>
       </fields>
     </class>
 
@@ -1127,6 +1225,13 @@
           <version>1.1.0+</version>
           <type>boolean</type>
         </field>
+        <field jpox.null-value="default">
+          <name>buildAgentGroup</name>
+          <version>1.3.2+</version>
+          <type>String</type>
+          <required>false</required>
+          <defaultValue></defaultValue>
+        </field>
         <field>
           <name>jdk</name>
           <version>1.1.0+</version>
@@ -1244,10 +1349,17 @@
           <type>String</type>
           <defaultValue>release-output-directory</defaultValue>
         </field>
+        <field jpox.null-value="default">
+          <name>numberOfBuildsInParallel</name>
+          <version>1.1.4+</version>
+          <type>int</type>
+          <defaultValue>1</defaultValue>
+        </field>
         <field>
           <name>distributedBuildEnabled</name>
-          <version>1.1.3+</version>
+          <version>1.1.4+</version>
           <type>boolean</type>
+          <defaultValue>false</defaultValue>
         </field>
       </fields>
     </class>
@@ -1306,8 +1418,8 @@
       </fields>
       <codeSegments>
         <codeSegment>
-           <version>1.1.0+</version>
-           <code><![CDATA[
+          <version>1.1.0+</version>
+          <code><![CDATA[
     public final static int NEW = 1;
     public final static int OK = 2;
     public final static int FAILED = 3;
@@ -1381,7 +1493,7 @@
           <type>String</type>
           <required>true</required>
           <description>
-          The file system location for this repository
+            The file system location for this repository
           </description>
         </field>
         <field>
@@ -1390,12 +1502,12 @@
           <type>String</type>
           <defaultValue>default</defaultValue>
           <description>
-          The layout of the repository. Valid values are "default" and "legacy"
+            The layout of the repository. Valid values are "default" and "legacy"
           </description>
         </field>
       </fields>
     </class>
-    
+
     <class>
       <name>AbstractPurgeConfiguration</name>
       <version>1.1.1+</version>
@@ -1425,7 +1537,7 @@
           <type>int</type>
           <defaultValue>2</defaultValue>
           <description>
-          The total count of the artifact for each snapshot or the release/build output folder to be retained.
+            The total count of the artifact for each snapshot or the release/build output folder to be retained.
           </description>
         </field>
         <field>
@@ -1434,7 +1546,7 @@
           <type>int</type>
           <defaultValue>100</defaultValue>
           <description>
-          The number of days old which will be the basis for removing a snapshot or a folder.
+            The number of days old which will be the basis for removing a snapshot or a folder.
           </description>
         </field>
         <field>
@@ -1508,7 +1620,32 @@
         </field>
       </fields>
     </class>
-       
+    <class>
+      <name>DistributedDirectoryPurgeConfiguration</name>
+      <version>1.4.1+</version>
+      <superClass>AbstractPurgeConfiguration</superClass>
+      <packageName>org.apache.continuum.model.repository</packageName>
+      <fields>
+        <field>
+          <name>buildAgentUrl</name>
+          <version>1.4.1+</version>
+          <type>String</type>
+          <description>
+            BuildAgent URL
+          </description>
+          <required>true</required>
+        </field>
+        <field>
+          <name>directoryType</name>
+          <version>1.4.1+</version>
+          <type>String</type>
+          <description>
+            The type of directory. Valid values are "releases" and "working"
+          </description>
+        </field>
+      </fields>
+    </class>
+
     <class>
       <name>ContinuumReleaseResult</name>
       <version>1.1.2+</version>
@@ -1554,8 +1691,13 @@
           <version>1.1.2+</version>
           <type>String</type>
         </field>
+        <field>
+          <name>username</name>
+          <version>1.4.0+</version>
+          <type>String</type>
+        </field>
       </fields>
-    </class> 
+    </class>
 
     <class>
       <name>ProjectScmRoot</name>
@@ -1599,6 +1741,5 @@
         </field>
       </fields>
     </class>
-    
   </classes>
 </model>
diff --git a/continuum-model/src/main/mdo/prepared-releases.mdo b/continuum-model/src/main/mdo/prepared-releases.mdo
new file mode 100644
index 0000000..ccad43e
--- /dev/null
+++ b/continuum-model/src/main/mdo/prepared-releases.mdo
@@ -0,0 +1,97 @@
+<?xml version="1.0"?>
+
+<!--
+  ~ 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.
+  -->
+
+<model>
+  <id>continuum-prepared-releases</id>
+  <name>ContinuumPrepareReleasesModel</name>
+  <defaults>
+    <default>
+      <key>package</key>
+      <value>org.apache.continuum.release.model</value>
+    </default>
+  </defaults>
+  <classes>
+    <class rootElement="true" xml.tagName="prepared-releases">
+      <name>PreparedReleaseModel</name>
+      <version>1.0.0+</version>
+      <fields>
+        <field>
+          <name>preparedReleases</name>
+          <version>1.0.0+</version>
+          <description></description>
+          <required>true</required>
+          <association>
+            <type>PreparedRelease</type>
+            <multiplicity>*</multiplicity>
+          </association>
+        </field>
+      </fields>
+    </class>
+    <class>
+      <name>PreparedRelease</name>
+      <version>1.0.0+</version>
+      <fields>
+        <field>
+          <name>releaseId</name>
+          <version>1.0.0+</version>
+          <required>true</required>
+          <description>release id</description>
+          <type>String</type>
+        </field>
+        <field>
+          <name>releaseName</name>
+          <version>1.0.0+</version>
+          <required>true</required>
+          <description>prepared release name</description>
+          <type>String</type>
+        </field>
+        <field>
+          <name>buildAgentUrl</name>
+          <version>1.0.0+</version>
+          <required>true</required>
+          <description>build agent url</description>
+          <type>String</type>
+        </field>
+        <field>
+          <name>releaseType</name>
+          <version>1.4.0+</version>
+          <required>true</required>
+          <description>type of release. possible values are "prepare" or "perform"</description>
+          <type>String</type>
+        </field>
+        <field>
+          <name>releaseGoals</name>
+          <version>1.4.1+</version>
+          <required>true</required>
+          <description>release goals</description>
+          <type>String</type>
+        </field>
+        <field>
+          <name>releaseBy</name>
+          <version>1.4.1+</version>
+          <required>true</required>
+          <description>release by</description>
+          <type>String</type>
+        </field>
+      </fields>
+    </class>
+  </classes>
+</model>
\ No newline at end of file
diff --git a/continuum-model/src/main/resources/META-INF/package.jdo b/continuum-model/src/main/resources/META-INF/package.jdo
new file mode 100644
index 0000000..6651e81
--- /dev/null
+++ b/continuum-model/src/main/resources/META-INF/package.jdo
@@ -0,0 +1,437 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ 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.
+  -->
+
+<!DOCTYPE jdo PUBLIC
+  "-//Sun Microsystems, Inc.//DTD Java Data Objects Metadata 2.0//EN"
+  "http://java.sun.com/dtd/jdo_2_0.dtd">
+
+<jdo>
+  <package name="org.apache.continuum.model.project">
+    <class name="ProjectScmRoot" detachable="true" table="ProjectScmRoot" identity-type="application" objectid-class="javax.jdo.identity.IntIdentity">
+      <field name="id" primary-key="true" value-strategy="native"/>
+      <field name="scmRootAddress" null-value="exception"/>
+      <field name="oldState"/>
+      <field name="state">
+        <column name="scmRootState"/>
+      </field>
+      <field name="error">
+        <column length="8192"/>
+      </field>
+      <field name="projectGroup" null-value="exception" default-fetch-group="true"/>
+    </class>
+  </package>
+  <package name="org.apache.maven.continuum.model.project">
+    <class name="ProjectGroup" detachable="true" table="ProjectGroup" identity-type="application" objectid-class="javax.jdo.identity.IntIdentity">
+      <field name="id" null-value="exception" primary-key="true" value-strategy="native"/>
+      <field name="groupId"/>
+      <field name="name"/>
+      <field name="description">
+        <column length="8192"/>
+      </field>
+      <field name="projects" mapped-by="projectGroup">
+        <collection element-type="Project" dependent-element="true"/>
+      </field>
+      <field name="notifiers">
+        <collection element-type="ProjectNotifier" dependent-element="true"/>
+        <join/>
+      </field>
+      <field name="buildDefinitions">
+        <collection element-type="BuildDefinition" dependent-element="true"/>
+        <join/>
+      </field>
+      <field name="localRepository" default-fetch-group="true"/>
+      <fetch-group name="ProjectGroup_detail">
+        <field name="projects"/>
+        <field name="notifiers"/>
+        <field name="buildDefinitions"/>
+      </fetch-group>
+      <fetch-group name="project-build-details">
+        <field name="projects"/>
+        <field name="notifiers"/>
+        <field name="buildDefinitions"/>
+      </fetch-group>
+      <fetch-group name="projectgroup-projects">
+        <field name="projects"/>
+      </fetch-group>
+      <fetch-group name="project-with-scm-result">
+        <field name="projects"/>
+      </fetch-group>
+    </class>
+    <class name="Project" detachable="true" table="Project" identity-type="application" objectid-class="javax.jdo.identity.IntIdentity">
+      <field name="id" null-value="exception" primary-key="true" value-strategy="native"/>
+      <field name="groupId"/>
+      <field name="artifactId"/>
+      <field name="executorId"/>
+      <field name="name"/>
+      <field name="description">
+        <column length="8192"/>
+      </field>
+      <field name="url">
+        <column length="256"/>
+      </field>
+      <field name="scmUrl">
+        <column length="256"/>
+      </field>
+      <field name="scmTag"/>
+      <field name="scmUsername"/>
+      <field name="scmPassword"/>
+      <field name="scmUseCache"/>
+      <field name="version"/>
+      <field name="state">
+        <column name="projectstate"/>
+      </field>
+      <field name="oldState"/>
+      <field name="latestBuildId"/>
+      <field name="buildNumber"/>
+      <field name="workingDirectory">
+        <column length="256"/>
+      </field>
+      <field name="relativePath"/>
+      <field name="checkedOutInSingleDirectory" null-value="default"/>
+      <field name="buildResults" mapped-by="project">
+        <collection element-type="BuildResult" dependent-element="true"/>
+      </field>
+      <field name="checkoutResult" dependent="true"/>
+      <field name="developers">
+        <collection element-type="ProjectDeveloper" dependent-element="true"/>
+      </field>
+      <field name="parent" dependent="true"/>
+      <field name="dependencies">
+        <collection element-type="ProjectDependency" dependent-element="true"/>
+      </field>
+      <field name="projectGroup" null-value="exception" default-fetch-group="true"/>
+      <field name="notifiers">
+        <collection element-type="ProjectNotifier" dependent-element="true"/>
+        <join/>
+      </field>
+      <field name="buildDefinitions">
+        <collection element-type="BuildDefinition" dependent-element="true"/>
+        <join/>
+      </field>
+      <fetch-group name="Project_detail">
+        <field name="buildResults"/>
+        <field name="checkoutResult"/>
+        <field name="developers"/>
+        <field name="parent"/>
+        <field name="dependencies"/>
+        <field name="notifiers"/>
+        <field name="buildDefinitions"/>
+      </fetch-group>
+      <fetch-group name="project-all-details">
+        <field name="developers"/>
+        <field name="parent"/>
+        <field name="dependencies"/>
+        <field name="notifiers"/>
+        <field name="buildDefinitions"/>
+      </fetch-group>
+      <fetch-group name="project-build-details">
+        <field name="notifiers"/>
+        <field name="buildDefinitions"/>
+      </fetch-group>
+      <fetch-group name="project-with-builds">
+        <field name="buildResults"/>
+      </fetch-group>
+      <fetch-group name="project-dependencies">
+        <field name="parent"/>
+        <field name="dependencies"/>
+      </fetch-group>
+      <fetch-group name="project-with-checkout-result">
+        <field name="checkoutResult"/>
+      </fetch-group>
+    </class>
+    <class name="ProjectNotifier" detachable="true" table="ProjectNotifier" identity-type="application" objectid-class="javax.jdo.identity.IntIdentity">
+      <field name="id" null-value="exception" primary-key="true" value-strategy="native"/>
+      <field name="type">
+        <column name="notifiertype"/>
+      </field>
+      <field name="from">
+        <column name="notifierorigin"/>
+      </field>
+      <field name="enabled"/>
+      <field name="recipientType"/>
+      <field name="sendOnSuccess"/>
+      <field name="sendOnFailure"/>
+      <field name="sendOnError"/>
+      <field name="sendOnWarning"/>
+      <field name="configuration" default-fetch-group="true">
+        <map key-type="java.lang.String" value-type="java.lang.String" dependent-key="true" dependent-value="true"/>
+        <join/>
+      </field>
+      <field name="sendOnScmFailure"/>
+    </class>
+    <class name="ProjectDeveloper" detachable="true" table="ProjectDeveloper">
+      <field name="scmId"/>
+      <field name="name"/>
+      <field name="email"/>
+      <field name="continuumId"/>
+    </class>
+    <class name="ProjectDependency" detachable="true" table="ProjectDependency">
+      <field name="groupId"/>
+      <field name="artifactId"/>
+      <field name="version"/>
+    </class>
+    <class name="BuildResult" detachable="true" table="BuildResult" identity-type="application" objectid-class="javax.jdo.identity.IntIdentity">
+      <field name="project" default-fetch-group="true"/>
+      <field name="buildDefinition" default-fetch-group="true"/>
+      <field name="id" primary-key="true" value-strategy="native"/>
+      <field name="buildNumber"/>
+      <field name="username"/>
+      <field name="state">
+        <column name="resultstate"/>
+      </field>
+      <field name="trigger">
+        <column name="resulttrigger"/>
+      </field>
+      <field name="startTime"/>
+      <field name="endTime"/>
+      <field name="error">
+        <column length="8192"/>
+      </field>
+      <field name="success"/>
+      <field name="exitCode"/>
+      <field name="scmResult" dependent="true"/>
+      <field name="modifiedDependencies">
+        <collection element-type="ProjectDependency" dependent-element="true"/>
+      </field>
+      <field name="lastChangedDate" null-value="default">
+        <column default-value="0"/>
+      </field>
+      <field name="buildUrl" null-value="default">
+        <column default-value=""/>
+      </field>
+      <fetch-group name="BuildResult_detail">
+        <field name="scmResult"/>
+        <field name="modifiedDependencies"/>
+      </fetch-group>
+      <fetch-group name="build-result-with-details">
+        <field name="scmResult"/>
+        <field name="modifiedDependencies"/>
+      </fetch-group>
+    </class>
+    <class name="BuildDefinition" detachable="true" table="BuildDefinition" identity-type="application" objectid-class="javax.jdo.identity.IntIdentity">
+      <field name="id" null-value="exception" primary-key="true" value-strategy="native"/>
+      <field name="defaultForProject"/>
+      <field name="goals"/>
+      <field name="arguments"/>
+      <field name="buildFile"/>
+      <field name="buildFresh"/>
+      <field name="description"/>
+      <field name="type">
+        <column name="builddefinition_type"/>
+      </field>
+      <field name="schedule" default-fetch-group="true"/>
+      <field name="profile" default-fetch-group="true"/>
+      <field name="alwaysBuild"/>
+      <field name="template">
+        <column name="is_template"/>
+      </field>
+      <field name="updatePolicy" null-value="default">
+        <column default-value="0"/>
+      </field>
+    </class>
+    <class name="BuildDefinitionTemplate" detachable="true" table="BuildDefinitionTemplate" identity-type="application" objectid-class="javax.jdo.identity.IntIdentity">
+      <field name="id" primary-key="true" value-strategy="native"/>
+      <field name="name" null-value="exception"/>
+      <field name="continuumDefault"/>
+      <field name="type">
+        <column name="builddefinition_template_type"/>
+      </field>
+      <field name="buildDefinitions" default-fetch-group="true">
+        <collection element-type="BuildDefinition" dependent-element="false"/>
+        <join/>
+      </field>
+      <fetch-group name="build-template-build-definitions">
+        <field name="buildDefinitions"/>
+      </fetch-group>
+    </class>
+    <class name="BuildQueue" detachable="true" table="BuildQueue" identity-type="application" objectid-class="javax.jdo.identity.IntIdentity">
+      <field name="id" primary-key="true" value-strategy="native"/>
+      <field name="name" null-value="exception">
+        <column default-value=""/>
+      </field>
+    </class>
+    <class name="Schedule" detachable="true" table="Schedule" identity-type="application" objectid-class="javax.jdo.identity.IntIdentity">
+      <field name="id" primary-key="true" value-strategy="native"/>
+      <field name="active"/>
+      <field name="name"/>
+      <field name="description"/>
+      <field name="delay">
+        <column name="scheduledelay"/>
+      </field>
+      <field name="maxJobExecutionTime"/>
+      <field name="cronExpression"/>
+      <field name="buildQueues" default-fetch-group="true">
+        <collection element-type="BuildQueue" dependent-element="false"/>
+        <join/>
+      </field>
+      <fetch-group name="schedule-build-queues">
+        <field name="buildQueues"/>
+      </fetch-group>
+    </class>
+    <class name="ContinuumModelloMetadata" detachable="true">
+      <field name="modelVersion" null-value="default">
+        <column default-value="1.4.1"/>
+      </field>
+    </class>
+  </package>
+  <package name="org.apache.maven.continuum.model.system">
+    <class name="Profile" detachable="true" table="profiles" identity-type="application" objectid-class="javax.jdo.identity.IntIdentity">
+      <field name="id" primary-key="true" value-strategy="native"/>
+      <field name="active"/>
+      <field name="name"/>
+      <field name="description"/>
+      <field name="scmMode"/>
+      <field name="buildWithoutChanges"/>
+      <field name="buildAgentGroup" null-value="default">
+        <column default-value=""/>
+      </field>
+      <field name="jdk" default-fetch-group="true"/>
+      <field name="builder" default-fetch-group="true"/>
+      <field name="environmentVariables" default-fetch-group="true">
+        <collection element-type="Installation" dependent-element="false"/>
+        <join/>
+      </field>
+    </class>
+    <class name="Installation" detachable="true" table="Installation" identity-type="application" objectid-class="javax.jdo.identity.IntIdentity">
+      <field name="type">
+        <column name="installationtype"/>
+      </field>
+      <field name="varValue"/>
+      <field name="varName"/>
+      <field name="name"/>
+      <field name="installationId" primary-key="true" value-strategy="native"/>
+    </class>
+    <class name="SystemConfiguration" detachable="true" table="SystemConfiguration">
+      <field name="guestAccountEnabled"/>
+      <field name="defaultScheduleDescription"/>
+      <field name="defaultScheduleCronExpression"/>
+      <field name="workingDirectory"/>
+      <field name="buildOutputDirectory"/>
+      <field name="deploymentRepositoryDirectory"/>
+      <field name="baseUrl"/>
+      <field name="initialized"/>
+      <field name="releaseOutputDirectory"/>
+      <field name="numberOfBuildsInParallel" null-value="default">
+        <column default-value="1"/>
+      </field>
+      <field name="distributedBuildEnabled"/>
+    </class>
+    <class name="NotificationAddress" detachable="true" table="NotificationAddress">
+      <field name="type">
+        <column name="notifiertype"/>
+      </field>
+      <field name="address"/>
+      <field name="configuration" default-fetch-group="true">
+        <map key-type="java.lang.String" value-type="java.lang.String" dependent-key="true" dependent-value="true"/>
+        <join/>
+      </field>
+    </class>
+  </package>
+  <package name="org.apache.continuum.model.release">
+    <class name="ContinuumReleaseResult" detachable="true" table="ContinuumReleaseResult" identity-type="application" objectid-class="javax.jdo.identity.IntIdentity">
+      <field name="id" primary-key="true" value-strategy="native"/>
+      <field name="startTime"/>
+      <field name="endTime"/>
+      <field name="resultCode"/>
+      <field name="projectGroup" default-fetch-group="true"/>
+      <field name="project" default-fetch-group="true"/>
+      <field name="releaseGoal"/>
+      <field name="username"/>
+    </class>
+  </package>
+  <package name="org.apache.continuum.model.repository">
+    <class name="LocalRepository" detachable="true" table="LocalRepository" identity-type="application" objectid-class="javax.jdo.identity.IntIdentity">
+      <field name="id" primary-key="true" value-strategy="native"/>
+      <field name="name" null-value="exception"/>
+      <field name="location" null-value="exception">
+        <column name="repoLocation"/>
+      </field>
+      <field name="layout"/>
+    </class>
+    <class name="AbstractPurgeConfiguration" detachable="true" table="AbstractPurgeConfiguration" identity-type="application" objectid-class="javax.jdo.identity.IntIdentity">
+      <field name="id" primary-key="true" value-strategy="native"/>
+      <field name="description"/>
+      <field name="deleteAll"/>
+      <field name="retentionCount"/>
+      <field name="daysOlder"/>
+      <field name="enabled"/>
+      <field name="schedule" default-fetch-group="true"/>
+      <field name="defaultPurge"/>
+    </class>
+    <class name="RepositoryPurgeConfiguration" persistence-capable-superclass="org.apache.continuum.model.repository.AbstractPurgeConfiguration" detachable="true" table="RepositoryPurgeConfiguration">
+      <inheritance strategy="new-table"/>
+      <field name="repository" null-value="exception" default-fetch-group="true"/>
+      <field name="deleteReleasedSnapshots"/>
+    </class>
+    <class name="DirectoryPurgeConfiguration" persistence-capable-superclass="org.apache.continuum.model.repository.AbstractPurgeConfiguration" detachable="true" table="DirectoryPurgeConfiguration">
+      <inheritance strategy="new-table"/>
+      <field name="location" null-value="exception">
+        <column name="directoryLocation"/>
+      </field>
+      <field name="directoryType"/>
+    </class>
+    <class name="DistributedDirectoryPurgeConfiguration" persistence-capable-superclass="org.apache.continuum.model.repository.AbstractPurgeConfiguration" detachable="true" table="DistributedDirectoryPurgeConfiguration">
+      <inheritance strategy="new-table"/>
+      <field name="buildAgentUrl" null-value="exception"/>
+      <field name="directoryType"/>
+    </class>
+  </package>
+  <package name="org.apache.maven.continuum.model.scm">
+    <class name="ScmResult" detachable="true" table="ScmResult">
+      <field name="success"/>
+      <field name="commandLine">
+        <column length="1024"/>
+      </field>
+      <field name="providerMessage">
+        <column length="1024"/>
+      </field>
+      <field name="commandOutput">
+        <column length="1024"/>
+      </field>
+      <field name="exception">
+        <column name="exceptionstring" length="8192"/>
+      </field>
+      <field name="changes" default-fetch-group="true">
+        <collection element-type="ChangeSet" dependent-element="true"/>
+      </field>
+    </class>
+    <class name="ChangeSet" detachable="true" table="ChangeSet">
+      <field name="id"/>
+      <field name="author"/>
+      <field name="comment">
+        <column name="changecomment" length="8192"/>
+      </field>
+      <field name="date">
+        <column name="changedate"/>
+      </field>
+      <field name="files" default-fetch-group="true">
+        <collection element-type="ChangeFile" dependent-element="true"/>
+      </field>
+    </class>
+    <class name="ChangeFile" detachable="true" table="ChangeFile">
+      <field name="name">
+        <column length="1024"/>
+      </field>
+      <field name="revision"/>
+      <field name="status"/>
+    </class>
+  </package>
+</jdo>
diff --git a/continuum-model/src/main/resources/META-INF/package.jdorepl b/continuum-model/src/main/resources/META-INF/package.jdorepl
new file mode 100644
index 0000000..0e64206
--- /dev/null
+++ b/continuum-model/src/main/resources/META-INF/package.jdorepl
@@ -0,0 +1,437 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ 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.
+  -->
+
+<!DOCTYPE jdo PUBLIC
+  "-//Sun Microsystems, Inc.//DTD Java Data Objects Metadata 2.0//EN"
+  "http://java.sun.com/dtd/jdo_2_0.dtd">
+
+<jdo>
+  <package name="org.apache.continuum.model.project">
+    <class name="ProjectScmRoot" detachable="true" table="ProjectScmRoot" identity-type="application">
+      <field name="id" primary-key="true"/>
+      <field name="scmRootAddress" null-value="exception"/>
+      <field name="oldState"/>
+      <field name="state">
+        <column name="scmRootState"/>
+      </field>
+      <field name="error">
+        <column length="8192"/>
+      </field>
+      <field name="projectGroup" null-value="exception" default-fetch-group="true"/>
+    </class>
+  </package>
+  <package name="org.apache.maven.continuum.model.project">
+    <class name="ProjectGroup" detachable="true" table="ProjectGroup" identity-type="application">
+      <field name="id" null-value="exception" primary-key="true"/>
+      <field name="groupId"/>
+      <field name="name"/>
+      <field name="description">
+        <column length="8192"/>
+      </field>
+      <field name="projects" mapped-by="projectGroup">
+        <collection element-type="Project" dependent-element="true"/>
+      </field>
+      <field name="notifiers">
+        <collection element-type="ProjectNotifier" dependent-element="true"/>
+        <join/>
+      </field>
+      <field name="buildDefinitions">
+        <collection element-type="BuildDefinition" dependent-element="true"/>
+        <join/>
+      </field>
+      <field name="localRepository" default-fetch-group="true"/>
+      <fetch-group name="ProjectGroup_detail">
+        <field name="projects"/>
+        <field name="notifiers"/>
+        <field name="buildDefinitions"/>
+      </fetch-group>
+      <fetch-group name="project-build-details">
+        <field name="projects"/>
+        <field name="notifiers"/>
+        <field name="buildDefinitions"/>
+      </fetch-group>
+      <fetch-group name="projectgroup-projects">
+        <field name="projects"/>
+      </fetch-group>
+      <fetch-group name="project-with-scm-result">
+        <field name="projects"/>
+      </fetch-group>
+    </class>
+    <class name="Project" detachable="true" table="Project" identity-type="application">
+      <field name="id" null-value="exception" primary-key="true"/>
+      <field name="groupId"/>
+      <field name="artifactId"/>
+      <field name="executorId"/>
+      <field name="name"/>
+      <field name="description">
+        <column length="8192"/>
+      </field>
+      <field name="url">
+        <column length="256"/>
+      </field>
+      <field name="scmUrl">
+        <column length="256"/>
+      </field>
+      <field name="scmTag"/>
+      <field name="scmUsername"/>
+      <field name="scmPassword"/>
+      <field name="scmUseCache"/>
+      <field name="version"/>
+      <field name="state">
+        <column name="projectstate"/>
+      </field>
+      <field name="oldState"/>
+      <field name="latestBuildId"/>
+      <field name="buildNumber"/>
+      <field name="workingDirectory">
+        <column length="256"/>
+      </field>
+      <field name="relativePath"/>
+      <field name="checkedOutInSingleDirectory" null-value="default"/>
+      <field name="buildResults" mapped-by="project">
+        <collection element-type="BuildResult" dependent-element="true"/>
+      </field>
+      <field name="checkoutResult" dependent="true"/>
+      <field name="developers">
+        <collection element-type="ProjectDeveloper" dependent-element="true"/>
+      </field>
+      <field name="parent" dependent="true"/>
+      <field name="dependencies">
+        <collection element-type="ProjectDependency" dependent-element="true"/>
+      </field>
+      <field name="projectGroup" null-value="exception" default-fetch-group="true"/>
+      <field name="notifiers">
+        <collection element-type="ProjectNotifier" dependent-element="true"/>
+        <join/>
+      </field>
+      <field name="buildDefinitions">
+        <collection element-type="BuildDefinition" dependent-element="true"/>
+        <join/>
+      </field>
+      <fetch-group name="Project_detail">
+        <field name="buildResults"/>
+        <field name="checkoutResult"/>
+        <field name="developers"/>
+        <field name="parent"/>
+        <field name="dependencies"/>
+        <field name="notifiers"/>
+        <field name="buildDefinitions"/>
+      </fetch-group>
+      <fetch-group name="project-all-details">
+        <field name="developers"/>
+        <field name="parent"/>
+        <field name="dependencies"/>
+        <field name="notifiers"/>
+        <field name="buildDefinitions"/>
+      </fetch-group>
+      <fetch-group name="project-build-details">
+        <field name="notifiers"/>
+        <field name="buildDefinitions"/>
+      </fetch-group>
+      <fetch-group name="project-with-builds">
+        <field name="buildResults"/>
+      </fetch-group>
+      <fetch-group name="project-dependencies">
+        <field name="parent"/>
+        <field name="dependencies"/>
+      </fetch-group>
+      <fetch-group name="project-with-checkout-result">
+        <field name="checkoutResult"/>
+      </fetch-group>
+    </class>
+    <class name="ProjectNotifier" detachable="true" table="ProjectNotifier" identity-type="application">
+      <field name="id" null-value="exception" primary-key="true"/>
+      <field name="type">
+        <column name="notifiertype"/>
+      </field>
+      <field name="from">
+        <column name="notifierorigin"/>
+      </field>
+      <field name="enabled"/>
+      <field name="recipientType"/>
+      <field name="sendOnSuccess"/>
+      <field name="sendOnFailure"/>
+      <field name="sendOnError"/>
+      <field name="sendOnWarning"/>
+      <field name="configuration" default-fetch-group="true">
+        <map key-type="java.lang.String" value-type="java.lang.String" dependent-key="true" dependent-value="true"/>
+        <join/>
+      </field>
+      <field name="sendOnScmFailure"/>
+    </class>
+    <class name="ProjectDeveloper" detachable="true" table="ProjectDeveloper">
+      <field name="scmId"/>
+      <field name="name"/>
+      <field name="email"/>
+      <field name="continuumId"/>
+    </class>
+    <class name="ProjectDependency" detachable="true" table="ProjectDependency">
+      <field name="groupId"/>
+      <field name="artifactId"/>
+      <field name="version"/>
+    </class>
+    <class name="BuildResult" detachable="true" table="BuildResult" identity-type="application">
+      <field name="project" default-fetch-group="true"/>
+      <field name="buildDefinition" default-fetch-group="true"/>
+      <field name="id" primary-key="true"/>
+      <field name="buildNumber"/>
+      <field name="username"/>
+      <field name="state">
+        <column name="resultstate"/>
+      </field>
+      <field name="trigger">
+        <column name="resulttrigger"/>
+      </field>
+      <field name="startTime"/>
+      <field name="endTime"/>
+      <field name="error">
+        <column length="8192"/>
+      </field>
+      <field name="success"/>
+      <field name="exitCode"/>
+      <field name="scmResult" dependent="true"/>
+      <field name="modifiedDependencies">
+        <collection element-type="ProjectDependency" dependent-element="true"/>
+      </field>
+      <field name="lastChangedDate" null-value="default">
+        <column default-value="0"/>
+      </field>
+      <field name="buildUrl" null-value="default">
+        <column default-value=""/>
+      </field>
+      <fetch-group name="BuildResult_detail">
+        <field name="scmResult"/>
+        <field name="modifiedDependencies"/>
+      </fetch-group>
+      <fetch-group name="build-result-with-details">
+        <field name="scmResult"/>
+        <field name="modifiedDependencies"/>
+      </fetch-group>
+    </class>
+    <class name="BuildDefinition" detachable="true" table="BuildDefinition" identity-type="application">
+      <field name="id" null-value="exception" primary-key="true"/>
+      <field name="defaultForProject"/>
+      <field name="goals"/>
+      <field name="arguments"/>
+      <field name="buildFile"/>
+      <field name="buildFresh"/>
+      <field name="description"/>
+      <field name="type">
+        <column name="builddefinition_type"/>
+      </field>
+      <field name="schedule" default-fetch-group="true"/>
+      <field name="profile" default-fetch-group="true"/>
+      <field name="alwaysBuild"/>
+      <field name="template">
+        <column name="is_template"/>
+      </field>
+      <field name="updatePolicy" null-value="default">
+        <column default-value="0"/>
+      </field>
+    </class>
+    <class name="BuildDefinitionTemplate" detachable="true" table="BuildDefinitionTemplate" identity-type="application">
+      <field name="id" primary-key="true"/>
+      <field name="name" null-value="exception"/>
+      <field name="continuumDefault"/>
+      <field name="type">
+        <column name="builddefinition_template_type"/>
+      </field>
+      <field name="buildDefinitions" default-fetch-group="true">
+        <collection element-type="BuildDefinition" dependent-element="false"/>
+        <join/>
+      </field>
+      <fetch-group name="build-template-build-definitions">
+        <field name="buildDefinitions"/>
+      </fetch-group>
+    </class>
+    <class name="BuildQueue" detachable="true" table="BuildQueue" identity-type="application">
+      <field name="id" primary-key="true"/>
+      <field name="name" null-value="exception">
+        <column default-value=""/>
+      </field>
+    </class>
+    <class name="Schedule" detachable="true" table="Schedule" identity-type="application">
+      <field name="id" primary-key="true"/>
+      <field name="active"/>
+      <field name="name"/>
+      <field name="description"/>
+      <field name="delay">
+        <column name="scheduledelay"/>
+      </field>
+      <field name="maxJobExecutionTime"/>
+      <field name="cronExpression"/>
+      <field name="buildQueues" default-fetch-group="true">
+        <collection element-type="BuildQueue" dependent-element="false"/>
+        <join/>
+      </field>
+      <fetch-group name="schedule-build-queues">
+        <field name="buildQueues"/>
+      </fetch-group>
+    </class>
+    <class name="ContinuumModelloMetadata" detachable="true">
+      <field name="modelVersion" null-value="default">
+        <column default-value="1.4.1"/>
+      </field>
+    </class>
+  </package>
+  <package name="org.apache.maven.continuum.model.system">
+    <class name="Profile" detachable="true" table="profiles" identity-type="application">
+      <field name="id" primary-key="true"/>
+      <field name="active"/>
+      <field name="name"/>
+      <field name="description"/>
+      <field name="scmMode"/>
+      <field name="buildWithoutChanges"/>
+      <field name="buildAgentGroup" null-value="default">
+        <column default-value=""/>
+      </field>
+      <field name="jdk" default-fetch-group="true"/>
+      <field name="builder" default-fetch-group="true"/>
+      <field name="environmentVariables" default-fetch-group="true">
+        <collection element-type="Installation" dependent-element="false"/>
+        <join/>
+      </field>
+    </class>
+    <class name="Installation" detachable="true" table="Installation" identity-type="application">
+      <field name="type">
+        <column name="installationtype"/>
+      </field>
+      <field name="varValue"/>
+      <field name="varName"/>
+      <field name="name"/>
+      <field name="installationId" primary-key="true"/>
+    </class>
+    <class name="SystemConfiguration" detachable="true" table="SystemConfiguration">
+      <field name="guestAccountEnabled"/>
+      <field name="defaultScheduleDescription"/>
+      <field name="defaultScheduleCronExpression"/>
+      <field name="workingDirectory"/>
+      <field name="buildOutputDirectory"/>
+      <field name="deploymentRepositoryDirectory"/>
+      <field name="baseUrl"/>
+      <field name="initialized"/>
+      <field name="releaseOutputDirectory"/>
+      <field name="numberOfBuildsInParallel" null-value="default">
+        <column default-value="1"/>
+      </field>
+      <field name="distributedBuildEnabled"/>
+    </class>
+    <class name="NotificationAddress" detachable="true" table="NotificationAddress">
+      <field name="type">
+        <column name="notifiertype"/>
+      </field>
+      <field name="address"/>
+      <field name="configuration" default-fetch-group="true">
+        <map key-type="java.lang.String" value-type="java.lang.String" dependent-key="true" dependent-value="true"/>
+        <join/>
+      </field>
+    </class>
+  </package>
+  <package name="org.apache.continuum.model.release">
+    <class name="ContinuumReleaseResult" detachable="true" table="ContinuumReleaseResult" identity-type="application">
+      <field name="id" primary-key="true"/>
+      <field name="startTime"/>
+      <field name="endTime"/>
+      <field name="resultCode"/>
+      <field name="projectGroup" default-fetch-group="true"/>
+      <field name="project" default-fetch-group="true"/>
+      <field name="releaseGoal"/>
+      <field name="username"/>
+    </class>
+  </package>
+  <package name="org.apache.continuum.model.repository">
+    <class name="LocalRepository" detachable="true" table="LocalRepository" identity-type="application">
+      <field name="id" primary-key="true"/>
+      <field name="name" null-value="exception"/>
+      <field name="location" null-value="exception">
+        <column name="repoLocation"/>
+      </field>
+      <field name="layout"/>
+    </class>
+    <class name="AbstractPurgeConfiguration" detachable="true" table="AbstractPurgeConfiguration" identity-type="application">
+      <field name="id" primary-key="true"/>
+      <field name="description"/>
+      <field name="deleteAll"/>
+      <field name="retentionCount"/>
+      <field name="daysOlder"/>
+      <field name="enabled"/>
+      <field name="schedule" default-fetch-group="true"/>
+      <field name="defaultPurge"/>
+    </class>
+    <class name="RepositoryPurgeConfiguration" persistence-capable-superclass="org.apache.continuum.model.repository.AbstractPurgeConfiguration" detachable="true" table="RepositoryPurgeConfiguration">
+      <inheritance strategy="new-table"/>
+      <field name="repository" null-value="exception" default-fetch-group="true"/>
+      <field name="deleteReleasedSnapshots"/>
+    </class>
+    <class name="DirectoryPurgeConfiguration" persistence-capable-superclass="org.apache.continuum.model.repository.AbstractPurgeConfiguration" detachable="true" table="DirectoryPurgeConfiguration">
+      <inheritance strategy="new-table"/>
+      <field name="location" null-value="exception">
+        <column name="directoryLocation"/>
+      </field>
+      <field name="directoryType"/>
+    </class>
+    <class name="DistributedDirectoryPurgeConfiguration" persistence-capable-superclass="org.apache.continuum.model.repository.AbstractPurgeConfiguration" detachable="true" table="DistributedDirectoryPurgeConfiguration">
+      <inheritance strategy="new-table"/>
+      <field name="buildAgentUrl" null-value="exception"/>
+      <field name="directoryType"/>
+    </class>
+  </package>
+  <package name="org.apache.maven.continuum.model.scm">
+    <class name="ScmResult" detachable="true" table="ScmResult">
+      <field name="success"/>
+      <field name="commandLine">
+        <column length="1024"/>
+      </field>
+      <field name="providerMessage">
+        <column length="1024"/>
+      </field>
+      <field name="commandOutput">
+        <column length="1024"/>
+      </field>
+      <field name="exception">
+        <column name="exceptionstring" length="8192"/>
+      </field>
+      <field name="changes" default-fetch-group="true">
+        <collection element-type="ChangeSet" dependent-element="true"/>
+      </field>
+    </class>
+    <class name="ChangeSet" detachable="true" table="ChangeSet">
+      <field name="id"/>
+      <field name="author"/>
+      <field name="comment">
+        <column name="changecomment" length="8192"/>
+      </field>
+      <field name="date">
+        <column name="changedate"/>
+      </field>
+      <field name="files" default-fetch-group="true">
+        <collection element-type="ChangeFile" dependent-element="true"/>
+      </field>
+    </class>
+    <class name="ChangeFile" detachable="true" table="ChangeFile">
+      <field name="name">
+        <column length="1024"/>
+      </field>
+      <field name="revision"/>
+      <field name="status"/>
+    </class>
+  </package>
+</jdo>
diff --git a/continuum-model/src/main/resources/package-default.orm b/continuum-model/src/main/resources/package-default.orm
new file mode 100644
index 0000000..e86e6f1
--- /dev/null
+++ b/continuum-model/src/main/resources/package-default.orm
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ 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.
+  -->
+
+<!DOCTYPE orm PUBLIC
+    "-//Sun Microsystems, Inc.//DTD Java Data Objects Mapping Metadata 2.0//EN"
+    "http://java.sun.com/dtd/jdo_orm_2_0.dtd">
+
+<orm>
+  <package name="org.apache.maven.continuum.model.project">
+    <class name="ProjectNotifier">
+      <field name="sendOnScmFailure" null-value="default">
+        <column jdbc-type="CHAR" default-value="N" />
+      </field>
+    </class>
+    <class name="Project">
+      <field name="checkedOutInSingleDirectory" null-value="default">
+        <column jdbc-type="CHAR" default-value="N" />
+      </field>
+    </class>
+  </package>
+  <package name="org.apache.maven.continuum.model.system">
+    <class name="SystemConfiguration">
+      <field name="distributedBuildEnabled" null-value="default">
+        <column jdbc-type="CHAR" default-value="N" />
+      </field>
+    </class>
+  </package>
+</orm>
diff --git a/continuum-model/src/main/resources/package-mssql.orm b/continuum-model/src/main/resources/package-mssql.orm
index 62d5684..2f5f3e1 100644
--- a/continuum-model/src/main/resources/package-mssql.orm
+++ b/continuum-model/src/main/resources/package-mssql.orm
@@ -1,42 +1,63 @@
-<?xml version="1.0" encoding="UTF-8"?>

-<!DOCTYPE orm PUBLIC

-    "-//Sun Microsystems, Inc.//DTD Java Data Objects Mapping Metadata 2.0//EN"

-    "http://java.sun.com/dtd/jdo_orm_2_0.dtd">

-<orm>

-  <package name="org.apache.maven.continuum.model.project">

-    <class name="ProjectGroup">

-      <field name="description">

-        <column length="4000" jdbc-type="VARCHAR"/>

-      </field>

-    </class>

-    <class name="Project">

-      <field name="description">

-        <column length="4000" jdbc-type="VARCHAR"/>

-      </field>

-    </class>

-    <class name="BuildResult">

-      <field name="error">

-        <column length="4000" jdbc-type="VARCHAR"/>

-      </field>

-    </class>

-  </package>

-  <package name="org.apache.maven.continuum.model.scm">

-    <class name="ScmResult">

-      <field name="exception">

-        <column name="exceptionstring" length="4000" jdbc-type="VARCHAR"/>

-      </field>

-    </class>

-    <class name="ChangeSet">

-      <field name="comment">

-        <column name="changecomment" length="4000" jdbc-type="VARCHAR"/>

-      </field>

-    </class>

-  </package>

-  <package name="org.apache.continuum.model.project">

-    <class name="ProjectScmRoot">

-      <field name="error">

-        <column length="4000" jdbc-type="VARCHAR"/>

-      </field>

-    </class>

-  </package>

-</orm>

+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ 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.
+  -->
+
+<!DOCTYPE orm PUBLIC
+    "-//Sun Microsystems, Inc.//DTD Java Data Objects Mapping Metadata 2.0//EN"
+    "http://java.sun.com/dtd/jdo_orm_2_0.dtd">
+
+<orm>
+  <package name="org.apache.maven.continuum.model.project">
+    <class name="ProjectGroup">
+      <field name="description">
+        <column length="4000" jdbc-type="VARCHAR"/>
+      </field>
+    </class>
+    <class name="Project">
+      <field name="description">
+        <column length="4000" jdbc-type="VARCHAR"/>
+      </field>
+    </class>
+    <class name="BuildResult">
+      <field name="error">
+        <column length="4000" jdbc-type="VARCHAR"/>
+      </field>
+    </class>
+  </package>
+  <package name="org.apache.maven.continuum.model.scm">
+    <class name="ScmResult">
+      <field name="exception">
+        <column name="exceptionstring" length="4000" jdbc-type="VARCHAR"/>
+      </field>
+    </class>
+    <class name="ChangeSet">
+      <field name="comment">
+        <column name="changecomment" length="4000" jdbc-type="VARCHAR"/>
+      </field>
+    </class>
+  </package>
+  <package name="org.apache.continuum.model.project">
+    <class name="ProjectScmRoot">
+      <field name="error">
+        <column length="4000" jdbc-type="VARCHAR"/>
+      </field>
+    </class>
+  </package>
+</orm>
diff --git a/continuum-model/src/main/resources/package-oracle.orm b/continuum-model/src/main/resources/package-oracle.orm
new file mode 100644
index 0000000..2f5f3e1
--- /dev/null
+++ b/continuum-model/src/main/resources/package-oracle.orm
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ 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.
+  -->
+
+<!DOCTYPE orm PUBLIC
+    "-//Sun Microsystems, Inc.//DTD Java Data Objects Mapping Metadata 2.0//EN"
+    "http://java.sun.com/dtd/jdo_orm_2_0.dtd">
+
+<orm>
+  <package name="org.apache.maven.continuum.model.project">
+    <class name="ProjectGroup">
+      <field name="description">
+        <column length="4000" jdbc-type="VARCHAR"/>
+      </field>
+    </class>
+    <class name="Project">
+      <field name="description">
+        <column length="4000" jdbc-type="VARCHAR"/>
+      </field>
+    </class>
+    <class name="BuildResult">
+      <field name="error">
+        <column length="4000" jdbc-type="VARCHAR"/>
+      </field>
+    </class>
+  </package>
+  <package name="org.apache.maven.continuum.model.scm">
+    <class name="ScmResult">
+      <field name="exception">
+        <column name="exceptionstring" length="4000" jdbc-type="VARCHAR"/>
+      </field>
+    </class>
+    <class name="ChangeSet">
+      <field name="comment">
+        <column name="changecomment" length="4000" jdbc-type="VARCHAR"/>
+      </field>
+    </class>
+  </package>
+  <package name="org.apache.continuum.model.project">
+    <class name="ProjectScmRoot">
+      <field name="error">
+        <column length="4000" jdbc-type="VARCHAR"/>
+      </field>
+    </class>
+  </package>
+</orm>
diff --git a/continuum-notifiers/continuum-notifier-api/pom.xml b/continuum-notifiers/continuum-notifier-api/pom.xml
index d8d6049..2ff9b4b 100644
--- a/continuum-notifiers/continuum-notifier-api/pom.xml
+++ b/continuum-notifiers/continuum-notifier-api/pom.xml
@@ -1,27 +1,28 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
+  ~ 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.
+  -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <artifactId>continuum-notifiers</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>continuum-notifier-api</artifactId>
@@ -30,14 +31,14 @@
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
-	</dependency>
-  <dependency>
-    <groupId>org.springframework</groupId>
-    <artifactId>spring-context-support</artifactId>
-  </dependency>      
-  <dependency>
-    <groupId>javax.annotation</groupId>
-    <artifactId>jsr250-api</artifactId>
-  </dependency>      	
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-model</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>javax.annotation</groupId>
+      <artifactId>jsr250-api</artifactId>
+    </dependency>
   </dependencies>
 </project>
diff --git a/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/AbstractContinuumNotifier.java b/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/AbstractContinuumNotifier.java
index 511fa43..0539e63 100644
--- a/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/AbstractContinuumNotifier.java
+++ b/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/AbstractContinuumNotifier.java
@@ -39,17 +39,18 @@
 import org.slf4j.LoggerFactory;
 
 import java.util.List;
-
 import javax.annotation.Resource;
 
 public abstract class AbstractContinuumNotifier
     implements Notifier
 {
-    public static String ADDRESS_FIELD = "address";
+    public static final String ADDRESS_FIELD = "address";
 
-    public static String COMMITTER_FIELD = "committers";
+    public static final String COMMITTER_FIELD = "committers";
 
-    private Logger log = LoggerFactory.getLogger( getClass() );
+    public static final String DEVELOPER_FIELD = "developers";
+
+    private static final Logger log = LoggerFactory.getLogger( AbstractContinuumNotifier.class );
 
     @Resource
     private ConfigurationService configurationService;
@@ -118,8 +119,8 @@
                     buf.append( "/" );
                 }
 
-                buf.append( "buildResult.action?buildId=" ).append( build.getId() ).append( "&projectId=" )
-                    .append( project.getId() );
+                buf.append( "buildResult.action?buildId=" ).append( build.getId() ).append( "&projectId=" ).append(
+                    project.getId() );
             }
 
             return buf.toString();
@@ -134,7 +135,7 @@
         }
     }
 
-    public String getReportUrl( ProjectGroup projectGroup, ProjectScmRoot projectScmRoot, 
+    public String getReportUrl( ProjectGroup projectGroup, ProjectScmRoot projectScmRoot,
                                 ConfigurationService configurationService )
         throws ContinuumException
     {
@@ -144,20 +145,20 @@
             {
                 configurationService.reload();
             }
-    
+
             StringBuffer buf = new StringBuffer( configurationService.getUrl() );
-    
+
             if ( projectGroup != null && projectScmRoot != null )
             {
-                if ( !buf.toString().endsWith( "/" ) )                
+                if ( !buf.toString().endsWith( "/" ) )
                 {
                     buf.append( "/" );
                 }
 
-                buf.append( "scmResult.action?projectScmRootId=" ).append( projectScmRoot.getId() )
-                   .append( "&projectGroupId=" ).append( projectGroup.getId() );
+                buf.append( "scmResult.action?projectScmRootId=" ).append( projectScmRoot.getId() ).append(
+                    "&projectGroupId=" ).append( projectGroup.getId() );
             }
-    
+
             return buf.toString();
         }
         catch ( ConfigurationLoadingException e )
@@ -169,7 +170,7 @@
             throw new ContinuumException( "Can't obtain the base url from configuration.", e );
         }
     }
-    
+
     /**
      * Determine if message must be sent
      *
@@ -223,12 +224,8 @@
                 return projectNotifier.isSendOnSuccess();
             }
 
-            if ( build.getState() == ContinuumProjectState.WARNING )
-            {
-                return projectNotifier.isSendOnWarning();
-            }
+            return build.getState() != ContinuumProjectState.WARNING || projectNotifier.isSendOnWarning();
 
-            return true;
         }
 
         // Send if the state has changed
@@ -255,12 +252,8 @@
                 return projectNotifier.isSendOnSuccess();
             }
 
-            if ( build.getState() == ContinuumProjectState.WARNING )
-            {
-                return projectNotifier.isSendOnWarning();
-            }
+            return build.getState() != ContinuumProjectState.WARNING || projectNotifier.isSendOnWarning();
 
-            return true;
         }
 
         log.info( "Same state, not sending message." );
@@ -275,24 +268,12 @@
             projectNotifier = new ProjectNotifier();
         }
 
-        if ( projectScmRoot == null )
-        {
-            return false;
-        }
+        return projectScmRoot != null && ( alwaysSend ||
+            projectScmRoot.getState() == ContinuumProjectState.ERROR && projectNotifier.isSendOnScmFailure() &&
+                projectScmRoot.getOldState() != projectScmRoot.getState() );
 
-        if ( alwaysSend )
-        {
-            return true;
-        }
-
-        if ( projectScmRoot.getState() == ContinuumProjectState.ERROR && projectNotifier.isSendOnScmFailure() )
-        {
-            return true;
-        }
-
-        return false;
     }
-    
+
     protected BuildResult getPreviousBuild( Project project, BuildDefinition buildDef, BuildResult currentBuild )
         throws NotificationException
     {
@@ -351,19 +332,19 @@
             throw new NotificationException( "Unable to obtain project builds", e );
         }
     }
-    
+
     protected String generateMessage( Project project, BuildResult build, ConfigurationService configurationService )
         throws NotificationException
     {
         int state = project.getState();
-    
+
         if ( build != null )
         {
             state = build.getState();
         }
-    
+
         String message;
-    
+
         if ( state == ContinuumProjectState.OK )
         {
             message = "BUILD SUCCESSFUL: " + project.getName();
@@ -379,10 +360,10 @@
         else
         {
             log.warn( "Unknown build state " + state + " for project " + project.getId() );
-    
+
             message = "ERROR: Unknown build state " + state + " for " + project.getName() + " project";
         }
-    
+
         try
         {
             return message + " " + getReportUrl( project, build, configurationService );
@@ -392,15 +373,15 @@
             throw new NotificationException( "Cannot generate message", e );
         }
     }
-    
+
     protected String generateMessage( ProjectScmRoot projectScmRoot, ConfigurationService configurationService )
         throws NotificationException
     {
         int state = projectScmRoot.getState();
         String scmRootAddress = projectScmRoot.getScmRootAddress();
-    
+
         String message;
-    
+
         if ( state == ContinuumProjectState.UPDATED )
         {
             message = "PREPARE BUILD SUCCESSFUL: " + scmRootAddress;
@@ -412,13 +393,14 @@
         else
         {
             log.warn( "Unknown prepare build state " + state + " for SCM root URL " + scmRootAddress );
-    
+
             message = "ERROR: Unknown prepare build state " + state + " for SCM root URL" + scmRootAddress;
         }
-    
+
         try
         {
-            return message + " " + getReportUrl( projectScmRoot.getProjectGroup(), projectScmRoot, configurationService );
+            return message + " " +
+                getReportUrl( projectScmRoot.getProjectGroup(), projectScmRoot, configurationService );
         }
         catch ( ContinuumException e )
         {
diff --git a/continuum-notifiers/continuum-notifier-api/src/main/resources/META-INF/spring-context.xml b/continuum-notifiers/continuum-notifier-api/src/main/resources/META-INF/spring-context.xml
index 7165b10..e83d596 100644
--- a/continuum-notifiers/continuum-notifier-api/src/main/resources/META-INF/spring-context.xml
+++ b/continuum-notifiers/continuum-notifier-api/src/main/resources/META-INF/spring-context.xml
@@ -18,6 +18,7 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
   -->
+
 <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
@@ -26,7 +27,7 @@
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-2.5.xsd">
 
-  <context:annotation-config />
+  <context:annotation-config/>
   <context:component-scan base-package="org.apache.maven.continuum.notification"/>
- 
+
 </beans>
\ No newline at end of file
diff --git a/continuum-notifiers/continuum-notifier-irc/pom.xml b/continuum-notifiers/continuum-notifier-irc/pom.xml
index 162bd8b..5ed3bd7 100644
--- a/continuum-notifiers/continuum-notifier-irc/pom.xml
+++ b/continuum-notifiers/continuum-notifier-irc/pom.xml
@@ -1,27 +1,28 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
+  ~ 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.
+  -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <artifactId>continuum-notifiers</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>continuum-notifier-irc</artifactId>
@@ -31,19 +32,34 @@
       <groupId>org.schwering</groupId>
       <artifactId>irclib</artifactId>
       <version>1.10</version>
-    </dependency>    
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-notifier-api</artifactId>
-      <version>${pom.version}</version>
     </dependency>
     <dependency>
       <groupId>org.springframework</groupId>
-      <artifactId>spring-context-support</artifactId>
-    </dependency>      
+      <artifactId>spring-context</artifactId>
+    </dependency>
     <dependency>
       <groupId>javax.annotation</groupId>
       <artifactId>jsr250-api</artifactId>
-    </dependency>        
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-model</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-utils</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-component-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-notifier-api</artifactId>
+    </dependency>
   </dependencies>
 </project>
diff --git a/continuum-notifiers/continuum-notifier-irc/src/main/java/org/apache/maven/continuum/notification/irc/IrcContinuumNotifier.java b/continuum-notifiers/continuum-notifier-irc/src/main/java/org/apache/maven/continuum/notification/irc/IrcContinuumNotifier.java
index 0621866..8f16f43 100644
--- a/continuum-notifiers/continuum-notifier-irc/src/main/java/org/apache/maven/continuum/notification/irc/IrcContinuumNotifier.java
+++ b/continuum-notifiers/continuum-notifier-irc/src/main/java/org/apache/maven/continuum/notification/irc/IrcContinuumNotifier.java
@@ -47,7 +47,6 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-
 import javax.annotation.Resource;
 
 /**
@@ -55,14 +54,13 @@
  *
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
  * @version $Id$
- * 
  */
-@Service("notifier#irc")
+@Service( "notifier#irc" )
 public class IrcContinuumNotifier
     extends AbstractContinuumNotifier
     implements Disposable
 {
-    private Logger log = LoggerFactory.getLogger( getClass() );
+    private static final Logger log = LoggerFactory.getLogger( IrcContinuumNotifier.class );
 
     // ----------------------------------------------------------------------
     // Requirements
@@ -232,14 +230,14 @@
 
         ProjectScmRoot projectScmRoot = context.getProjectScmRoot();
 
-        boolean isPrepareBuildComplete = 
-            messageId.equals( ContinuumNotificationDispatcher.MESSAGE_ID_PREPARE_BUILD_COMPLETE );
-        
+        boolean isPrepareBuildComplete = messageId.equals(
+            ContinuumNotificationDispatcher.MESSAGE_ID_PREPARE_BUILD_COMPLETE );
+
         if ( projectScmRoot == null && isPrepareBuildComplete )
         {
             return;
         }
-        
+
         // ----------------------------------------------------------------------
         // If there wasn't any building done, don't notify
         // ----------------------------------------------------------------------
@@ -298,9 +296,9 @@
         {
             return;
         }
-        
+
         sendMessage( projectNotifier.getConfiguration(), generateMessage( projectScmRoot, configurationService ) );
-    }    
+    }
 
     private void sendMessage( Map<String, String> configuration, String message )
         throws NotificationException
diff --git a/continuum-notifiers/continuum-notifier-irc/src/main/resources/META-INF/spring-context.xml b/continuum-notifiers/continuum-notifier-irc/src/main/resources/META-INF/spring-context.xml
index 677b126..10f7ae4 100644
--- a/continuum-notifiers/continuum-notifier-irc/src/main/resources/META-INF/spring-context.xml
+++ b/continuum-notifiers/continuum-notifier-irc/src/main/resources/META-INF/spring-context.xml
@@ -18,6 +18,7 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
   -->
+
 <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
@@ -26,7 +27,7 @@
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-2.5.xsd">
 
-  <context:annotation-config />
+  <context:annotation-config/>
   <context:component-scan base-package="org.apache.maven.continuum.notification.irc"/>
- 
+
 </beans>
\ No newline at end of file
diff --git a/continuum-notifiers/continuum-notifier-jabber/pom.xml b/continuum-notifiers/continuum-notifier-jabber/pom.xml
index e56110a..6541380 100644
--- a/continuum-notifiers/continuum-notifier-jabber/pom.xml
+++ b/continuum-notifiers/continuum-notifier-jabber/pom.xml
@@ -1,45 +1,45 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
+  ~ 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.
+  -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <artifactId>continuum-notifiers</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>continuum-notifier-jabber</artifactId>
   <name>Continuum :: Jabber Notifier</name>
   <dependencies>
     <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-notifier-api</artifactId>
-      <version>${pom.version}</version>
-    </dependency>
-    <dependency>
       <groupId>org.springframework</groupId>
-      <artifactId>spring-context-support</artifactId>
-    </dependency>      
+      <artifactId>spring-context</artifactId>
+    </dependency>
     <dependency>
       <groupId>javax.annotation</groupId>
       <artifactId>jsr250-api</artifactId>
-    </dependency>     
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-utils</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-jabber</artifactId>
@@ -51,5 +51,17 @@
         </exclusion>
       </exclusions>
     </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-model</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-notifier-api</artifactId>
+    </dependency>
   </dependencies>
 </project>
diff --git a/continuum-notifiers/continuum-notifier-jabber/src/main/java/org/apache/maven/continuum/notification/jabber/JabberContinuumNotifier.java b/continuum-notifiers/continuum-notifier-jabber/src/main/java/org/apache/maven/continuum/notification/jabber/JabberContinuumNotifier.java
index 8e08b89..80aae74 100644
--- a/continuum-notifiers/continuum-notifier-jabber/src/main/java/org/apache/maven/continuum/notification/jabber/JabberContinuumNotifier.java
+++ b/continuum-notifiers/continuum-notifier-jabber/src/main/java/org/apache/maven/continuum/notification/jabber/JabberContinuumNotifier.java
@@ -39,18 +39,17 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
-
 import javax.annotation.Resource;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
  * @version $Id$
  */
-@Service("notifier#jabber")
+@Service( "notifier#jabber" )
 public class JabberContinuumNotifier
     extends AbstractContinuumNotifier
 {
-    private Logger log = LoggerFactory.getLogger( getClass() );
+    private static final Logger log = LoggerFactory.getLogger( JabberContinuumNotifier.class );
 
     // ----------------------------------------------------------------------
     // Requirements
@@ -115,8 +114,8 @@
         BuildResult build = context.getBuildResult();
         ProjectScmRoot projectScmRoot = context.getProjectScmRoot();
 
-        boolean isPrepareBuildComplete = 
-            messageId.equals( ContinuumNotificationDispatcher.MESSAGE_ID_PREPARE_BUILD_COMPLETE );
+        boolean isPrepareBuildComplete = messageId.equals(
+            ContinuumNotificationDispatcher.MESSAGE_ID_PREPARE_BUILD_COMPLETE );
 
         if ( projectScmRoot == null && isPrepareBuildComplete )
         {
@@ -204,7 +203,7 @@
 
         sendMessage( notifier.getConfiguration(), generateMessage( projectScmRoot, configurationService ) );
     }
-    
+
     private void sendMessage( Map<String, String> configuration, String message )
         throws NotificationException
     {
@@ -226,9 +225,9 @@
 
             jabberClient.logon();
 
-            if ( configuration != null && StringUtils.isNotEmpty( (String) configuration.get( ADDRESS_FIELD ) ) )
+            if ( configuration != null && StringUtils.isNotEmpty( configuration.get( ADDRESS_FIELD ) ) )
             {
-                String address = (String) configuration.get( ADDRESS_FIELD );
+                String address = configuration.get( ADDRESS_FIELD );
                 String[] recipients = StringUtils.split( address, "," );
                 for ( String recipient : recipients )
                 {
@@ -260,17 +259,17 @@
         }
     }
 
-    private String getHost( Map configuration )
+    private String getHost( Map<String, String> configuration )
     {
         if ( configuration.containsKey( "host" ) )
         {
-            return (String) configuration.get( "host" );
+            return configuration.get( "host" );
         }
         else
         {
             if ( configuration.containsKey( "address" ) )
             {
-                String username = (String) configuration.get( "address" );
+                String username = configuration.get( "address" );
 
                 if ( username.indexOf( "@" ) > 0 )
                 {
@@ -282,13 +281,13 @@
         return host;
     }
 
-    private int getPort( Map configuration )
+    private int getPort( Map<String, String> configuration )
     {
         if ( configuration.containsKey( "port" ) )
         {
             try
             {
-                return Integer.parseInt( (String) configuration.get( "port" ) );
+                return Integer.parseInt( configuration.get( "port" ) );
             }
             catch ( NumberFormatException e )
             {
@@ -310,11 +309,11 @@
         }
     }
 
-    private String getUsername( Map configuration )
+    private String getUsername( Map<String, String> configuration )
     {
         if ( configuration.containsKey( "login" ) )
         {
-            String username = (String) configuration.get( "login" );
+            String username = configuration.get( "login" );
 
             if ( username.indexOf( "@" ) > 0 )
             {
@@ -327,39 +326,39 @@
         return fromAddress;
     }
 
-    private String getPassword( Map configuration )
+    private String getPassword( Map<String, String> configuration )
     {
         if ( configuration.containsKey( "password" ) )
         {
-            return (String) configuration.get( "password" );
+            return configuration.get( "password" );
         }
 
         return fromPassword;
     }
 
-    private boolean isSslConnection( Map configuration )
+    private boolean isSslConnection( Map<String, String> configuration )
     {
         if ( configuration.containsKey( "sslConnection" ) )
         {
-            return convertBoolean( (String) configuration.get( "sslConnection" ) );
+            return convertBoolean( configuration.get( "sslConnection" ) );
         }
 
         return sslConnection;
     }
 
-    private String getImDomainName( Map configuration )
+    private String getImDomainName( Map<String, String> configuration )
     {
         if ( configuration.containsKey( "domainName" ) )
         {
-            return (String) configuration.get( "domainName" );
+            return configuration.get( "domainName" );
         }
 
         return imDomainName;
     }
 
-    private boolean isGroup( Map configuration )
+    private boolean isGroup( Map<String, String> configuration )
     {
-        return configuration.containsKey( "isGroup" ) && convertBoolean( (String) configuration.get( "isGroup" ) );
+        return configuration.containsKey( "isGroup" ) && convertBoolean( configuration.get( "isGroup" ) );
     }
 
     private boolean convertBoolean( String value )
diff --git a/continuum-notifiers/continuum-notifier-jabber/src/main/resources/META-INF/spring-context.xml b/continuum-notifiers/continuum-notifier-jabber/src/main/resources/META-INF/spring-context.xml
index 7fbbda5..29b2de9 100644
--- a/continuum-notifiers/continuum-notifier-jabber/src/main/resources/META-INF/spring-context.xml
+++ b/continuum-notifiers/continuum-notifier-jabber/src/main/resources/META-INF/spring-context.xml
@@ -18,6 +18,7 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
   -->
+
 <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
@@ -26,7 +27,7 @@
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-2.5.xsd">
 
-  <context:annotation-config />
+  <context:annotation-config/>
   <context:component-scan base-package="org.apache.maven.continuum.notification.jabber"/>
- 
+
 </beans>
\ No newline at end of file
diff --git a/continuum-notifiers/continuum-notifier-msn/pom.xml b/continuum-notifiers/continuum-notifier-msn/pom.xml
index 5c3e20d..4128676 100644
--- a/continuum-notifiers/continuum-notifier-msn/pom.xml
+++ b/continuum-notifiers/continuum-notifier-msn/pom.xml
@@ -1,27 +1,28 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
+  ~ 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.
+  -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <artifactId>continuum-notifiers</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>continuum-notifier-msn</artifactId>
@@ -29,6 +30,10 @@
   <dependencies>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-utils</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-msn</artifactId>
       <version>1.0-alpha-2</version>
       <exclusions>
@@ -39,17 +44,24 @@
       </exclusions>
     </dependency>
     <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-notifier-api</artifactId>
-      <version>${pom.version}</version>
-    </dependency>
-    <dependency>
       <groupId>org.springframework</groupId>
-      <artifactId>spring-context-support</artifactId>
-    </dependency>      
+      <artifactId>spring-context</artifactId>
+    </dependency>
     <dependency>
       <groupId>javax.annotation</groupId>
       <artifactId>jsr250-api</artifactId>
-    </dependency>     
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-model</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-notifier-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
   </dependencies>
 </project>
diff --git a/continuum-notifiers/continuum-notifier-msn/src/main/java/org/apache/maven/continuum/notification/msn/MsnContinuumNotifier.java b/continuum-notifiers/continuum-notifier-msn/src/main/java/org/apache/maven/continuum/notification/msn/MsnContinuumNotifier.java
index d2670a6..8f8171e 100644
--- a/continuum-notifiers/continuum-notifier-msn/src/main/java/org/apache/maven/continuum/notification/msn/MsnContinuumNotifier.java
+++ b/continuum-notifiers/continuum-notifier-msn/src/main/java/org/apache/maven/continuum/notification/msn/MsnContinuumNotifier.java
@@ -39,18 +39,17 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
-
 import javax.annotation.Resource;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
  * @version $Id$
  */
-@Service("notifier#msn")
+@Service( "notifier#msn" )
 public class MsnContinuumNotifier
     extends AbstractContinuumNotifier
 {
-    private Logger log = LoggerFactory.getLogger( getClass() );
+    private static final Logger log = LoggerFactory.getLogger( MsnContinuumNotifier.class );
 
     // ----------------------------------------------------------------------
     // Requirements
@@ -102,8 +101,8 @@
 
         ProjectScmRoot projectScmRoot = context.getProjectScmRoot();
 
-        boolean isPrepareBuildComplete = 
-            messageId.equals( ContinuumNotificationDispatcher.MESSAGE_ID_PREPARE_BUILD_COMPLETE );
+        boolean isPrepareBuildComplete = messageId.equals(
+            ContinuumNotificationDispatcher.MESSAGE_ID_PREPARE_BUILD_COMPLETE );
 
         if ( projectScmRoot == null && isPrepareBuildComplete )
         {
@@ -202,9 +201,9 @@
         {
             msnClient.login();
 
-            if ( configuration != null && StringUtils.isNotEmpty( (String) configuration.get( ADDRESS_FIELD ) ) )
+            if ( configuration != null && StringUtils.isNotEmpty( configuration.get( ADDRESS_FIELD ) ) )
             {
-                String address = (String) configuration.get( ADDRESS_FIELD );
+                String address = configuration.get( ADDRESS_FIELD );
                 String[] recipients = StringUtils.split( address, "," );
                 for ( String recipient : recipients )
                 {
@@ -229,21 +228,21 @@
         }
     }
 
-    private String getUsername( Map configuration )
+    private String getUsername( Map<String, String> configuration )
     {
         if ( configuration.containsKey( "login" ) )
         {
-            return (String) configuration.get( "login" );
+            return configuration.get( "login" );
         }
 
         return fromAddress;
     }
 
-    private String getPassword( Map configuration )
+    private String getPassword( Map<String, String> configuration )
     {
         if ( configuration.containsKey( "password" ) )
         {
-            return (String) configuration.get( "password" );
+            return configuration.get( "password" );
         }
 
         return fromPassword;
diff --git a/continuum-notifiers/continuum-notifier-msn/src/main/resources/META-INF/spring-context.xml b/continuum-notifiers/continuum-notifier-msn/src/main/resources/META-INF/spring-context.xml
index c40b729..bfaaa81 100644
--- a/continuum-notifiers/continuum-notifier-msn/src/main/resources/META-INF/spring-context.xml
+++ b/continuum-notifiers/continuum-notifier-msn/src/main/resources/META-INF/spring-context.xml
@@ -18,6 +18,7 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
   -->
+
 <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
@@ -26,7 +27,7 @@
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-2.5.xsd">
 
-  <context:annotation-config />
+  <context:annotation-config/>
   <context:component-scan base-package="org.apache.maven.continuum.notification.msn"/>
- 
+
 </beans>
\ No newline at end of file
diff --git a/continuum-notifiers/continuum-notifier-wagon/pom.xml b/continuum-notifiers/continuum-notifier-wagon/pom.xml
index 9e60012..046b72f 100644
--- a/continuum-notifiers/continuum-notifier-wagon/pom.xml
+++ b/continuum-notifiers/continuum-notifier-wagon/pom.xml
@@ -1,27 +1,28 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
+  ~ 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.
+  -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <artifactId>continuum-notifiers</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>continuum-notifier-wagon</artifactId>
@@ -29,42 +30,80 @@
   <dependencies>
     <dependency>
       <groupId>org.apache.maven</groupId>
+      <artifactId>maven-artifact</artifactId>
+    </dependency>
+    <!-- start - order matters, requires maven 2.0.9+ -->
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-artifact-manager</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-artifact-manager</artifactId>
+    </dependency>
+    <!-- end - order matters -->
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-model</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-settings</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
       <artifactId>maven-project</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-core</artifactId>
-      <version>${pom.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-notifier-api</artifactId>
-      <version>${pom.version}</version>
+      <artifactId>continuum-model</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.maven.wagon</groupId>
       <artifactId>wagon-provider-api</artifactId>
-    </dependency>      
+    </dependency>
     <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-component-api</artifactId>
-    </dependency>    
-    <dependency>
-      <groupId>org.springframework</groupId>
-      <artifactId>spring-context-support</artifactId>
-    </dependency>      
-    <dependency>
-      <groupId>javax.annotation</groupId>
-      <artifactId>jsr250-api</artifactId>
-    </dependency>     
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-test</artifactId>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-simple</artifactId>
       <scope>test</scope>
     </dependency>
     <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>jcl-over-slf4j</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-utils</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>plexus-spring</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-component-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-context</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>javax.annotation</groupId>
+      <artifactId>jsr250-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-notifier-api</artifactId>
+    </dependency>
+    <dependency>
       <groupId>org.apache.maven.wagon</groupId>
-      <artifactId>wagon-webdav</artifactId>
+      <artifactId>wagon-webdav-jackrabbit</artifactId>
       <scope>test</scope>
     </dependency>
     <dependency>
@@ -72,6 +111,12 @@
       <artifactId>webdav</artifactId>
       <version>0.4</version>
       <scope>test</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>javax.servlet</groupId>
+          <artifactId>servlet-api</artifactId>
+        </exclusion>
+      </exclusions>
     </dependency>
     <dependency>
       <groupId>org.mortbay.jetty</groupId>
@@ -89,8 +134,21 @@
           <!-- TODO remove hack when solution found -->
           <skip>true</skip>
           <argLine>-noverify</argLine>
-        </configuration>    
-      </plugin>		
+        </configuration>
+      </plugin>
     </plugins>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.rat</groupId>
+          <artifactId>apache-rat-plugin</artifactId>
+          <configuration>
+            <excludes>
+              <exclude>src/test/resources/build-output-directory/**</exclude>
+            </excludes>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
   </build>
 </project>
diff --git a/continuum-notifiers/continuum-notifier-wagon/src/main/java/org/apache/maven/continuum/notification/wagon/WagonContinuumNotifier.java b/continuum-notifiers/continuum-notifier-wagon/src/main/java/org/apache/maven/continuum/notification/wagon/WagonContinuumNotifier.java
index 70c6416..37f1db2 100644
--- a/continuum-notifiers/continuum-notifier-wagon/src/main/java/org/apache/maven/continuum/notification/wagon/WagonContinuumNotifier.java
+++ b/continuum-notifiers/continuum-notifier-wagon/src/main/java/org/apache/maven/continuum/notification/wagon/WagonContinuumNotifier.java
@@ -73,23 +73,20 @@
 import java.io.IOException;
 import java.util.List;
 import java.util.Map;
-
 import javax.annotation.Resource;
 
 /**
  * @author <a href="mailto:hisidro@exist.com">Henry Isidro</a>
  * @author <a href="mailto:nramirez@exist.com">Napoleon Esmundo C. Ramirez</a>
  */
-@Service("notifier#wagon")
+@Service( "notifier#wagon" )
 public class WagonContinuumNotifier
     extends AbstractContinuumNotifier
     implements Contextualizable
 {
     public static final String BUILD_OUTPUT_FILE_NAME = "buildresult.txt";
 
-    private static final String CONTEXT_MAVEN_PROJECT = "CONTEXT_MAVEN_PROJECT";
-
-    private Logger log = LoggerFactory.getLogger( getClass() );
+    private static final Logger log = LoggerFactory.getLogger( WagonContinuumNotifier.class );
 
     @Resource
     private ConfigurationService configurationService;
@@ -295,8 +292,8 @@
     private MavenProject getMavenProject( Project project, BuildDefinition buildDefinition )
         throws ContinuumException
     {
-        File projectWorkingDir =
-            new File( configurationService.getWorkingDirectory(), Integer.toString( project.getId() ) );
+        File projectWorkingDir = new File( configurationService.getWorkingDirectory(), Integer.toString(
+            project.getId() ) );
         File pomFile = new File( projectWorkingDir, buildDefinition.getBuildFile() );
 
         MavenProject mavenProject;
diff --git a/continuum-notifiers/continuum-notifier-wagon/src/main/resources/META-INF/spring-context.xml b/continuum-notifiers/continuum-notifier-wagon/src/main/resources/META-INF/spring-context.xml
index 71f639c..85f1267 100644
--- a/continuum-notifiers/continuum-notifier-wagon/src/main/resources/META-INF/spring-context.xml
+++ b/continuum-notifiers/continuum-notifier-wagon/src/main/resources/META-INF/spring-context.xml
@@ -18,6 +18,7 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
   -->
+
 <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
@@ -26,7 +27,7 @@
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-2.5.xsd">
 
-  <context:annotation-config />
+  <context:annotation-config/>
   <context:component-scan base-package="org.apache.maven.continuum.notification.wagon"/>
- 
+
 </beans>
\ No newline at end of file
diff --git a/continuum-notifiers/continuum-notifier-wagon/src/test/java/org/apache/maven/continuum/wagon/Context.java b/continuum-notifiers/continuum-notifier-wagon/src/test/java/org/apache/maven/continuum/wagon/Context.java
index 7de6a6d..232ddad 100644
--- a/continuum-notifiers/continuum-notifier-wagon/src/test/java/org/apache/maven/continuum/wagon/Context.java
+++ b/continuum-notifiers/continuum-notifier-wagon/src/test/java/org/apache/maven/continuum/wagon/Context.java
@@ -19,13 +19,13 @@
  * under the License.
  */
 
-import java.util.List;
-
 import org.apache.maven.wagon.authentication.AuthenticationInfo;
 
+import java.util.List;
+
 /**
  * Context
- * 
+ *
  * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
  */
 public class Context
diff --git a/continuum-notifiers/continuum-notifier-wagon/src/test/java/org/apache/maven/continuum/wagon/Servlet.java b/continuum-notifiers/continuum-notifier-wagon/src/test/java/org/apache/maven/continuum/wagon/Servlet.java
index 4865d99..b263095 100644
--- a/continuum-notifiers/continuum-notifier-wagon/src/test/java/org/apache/maven/continuum/wagon/Servlet.java
+++ b/continuum-notifiers/continuum-notifier-wagon/src/test/java/org/apache/maven/continuum/wagon/Servlet.java
@@ -23,7 +23,7 @@
 
 /**
  * Servlet
- * 
+ *
  * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
  */
 public class Servlet
@@ -33,7 +33,7 @@
     private Properties parameters;
 
     private String path;
-    
+
     private String servlet;
 
     public String getId()
diff --git a/continuum-notifiers/continuum-notifier-wagon/src/test/java/org/apache/maven/continuum/wagon/ServletServer.java b/continuum-notifiers/continuum-notifier-wagon/src/test/java/org/apache/maven/continuum/wagon/ServletServer.java
index 137aba5..7dfd8f3 100644
--- a/continuum-notifiers/continuum-notifier-wagon/src/test/java/org/apache/maven/continuum/wagon/ServletServer.java
+++ b/continuum-notifiers/continuum-notifier-wagon/src/test/java/org/apache/maven/continuum/wagon/ServletServer.java
@@ -19,11 +19,6 @@
  * under the License.
  */
 
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
 import org.apache.maven.wagon.authentication.AuthenticationInfo;
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
@@ -40,16 +35,21 @@
 import org.mortbay.jetty.servlet.ServletHttpContext;
 import org.mortbay.util.MultiException;
 
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
 /**
  * Plexus Component to start a Jetty Server with servlet settings.
- * 
+ *
  * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
  */
 public class ServletServer
     implements Initializable, Startable
 {
     public static final String ROLE = ServletServer.class.getName();
-    
+
     private Server server;
 
     private int port;
diff --git a/continuum-notifiers/continuum-notifier-wagon/src/test/resources/org/apache/maven/continuum/wagon/WagonContinuumNotifierTest.xml b/continuum-notifiers/continuum-notifier-wagon/src/test/resources/org/apache/maven/continuum/wagon/WagonContinuumNotifierTest.xml
index 470b1bc..c2ab252 100644
--- a/continuum-notifiers/continuum-notifier-wagon/src/test/resources/org/apache/maven/continuum/wagon/WagonContinuumNotifierTest.xml
+++ b/continuum-notifiers/continuum-notifier-wagon/src/test/resources/org/apache/maven/continuum/wagon/WagonContinuumNotifierTest.xml
@@ -35,7 +35,7 @@
                 <parameters>
                   <property>
                     <name>rootPath</name>
-                      <value>${basedir}/target</value>
+                    <value>${basedir}/target</value>
                   </property>
                   <property>
                     <name>xmlOnly</name>
@@ -48,7 +48,7 @@
         </contexts>
       </configuration>
     </component>
-    
+
     <component>
       <role>org.apache.maven.continuum.notification.Notifier</role>
       <role-hint>wagon</role-hint>
@@ -71,16 +71,16 @@
         <localRepository>~/.m2/repository</localRepository>
       </configuration>
     </component>
-    
+
     <component>
       <role>org.apache.maven.continuum.configuration.ConfigurationService</role>
       <implementation>org.apache.maven.continuum.configuration.ConfigurationServiceMock</implementation>
     </component>
-    
+
     <component>
       <role>org.apache.maven.artifact.manager.WagonManager</role>
       <implementation>org.apache.maven.artifact.manager.DefaultWagonManager</implementation>
     </component>
-    
+
   </components>
 </plexus>
\ No newline at end of file
diff --git a/continuum-notifiers/continuum-notifier-wagon/src/test/resources/working-directory/2/pom.xml b/continuum-notifiers/continuum-notifier-wagon/src/test/resources/working-directory/2/pom.xml
index 7416aea..cf33070 100644
--- a/continuum-notifiers/continuum-notifier-wagon/src/test/resources/working-directory/2/pom.xml
+++ b/continuum-notifiers/continuum-notifier-wagon/src/test/resources/working-directory/2/pom.xml
@@ -17,7 +17,8 @@
   ~ under the License.
   -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>groupId</groupId>
   <artifactId>artifactId</artifactId>
diff --git a/continuum-notifiers/pom.xml b/continuum-notifiers/pom.xml
index 186f9a1..a1966c5 100644
--- a/continuum-notifiers/pom.xml
+++ b/continuum-notifiers/pom.xml
@@ -1,27 +1,28 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
+  ~ 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.
+  -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <artifactId>continuum</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>continuum-notifiers</artifactId>
diff --git a/continuum-purge/pom.xml b/continuum-purge/pom.xml
index 35e6053..6b3de7e 100644
--- a/continuum-purge/pom.xml
+++ b/continuum-purge/pom.xml
@@ -1,94 +1,129 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
+  ~ 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.
+  -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
     <artifactId>continuum</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <artifactId>continuum-purge</artifactId>
   <name>Continuum :: Purge System</name>
   <dependencies>
     <dependency>
+      <groupId>jpox</groupId>
+      <artifactId>jpox</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>commons-collections</groupId>
+      <artifactId>commons-collections</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-store</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
       <groupId>org.apache.continuum</groupId>
       <artifactId>continuum-api</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-commons</artifactId>
+      <artifactId>continuum-model</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-release</artifactId>
+      <artifactId>continuum-distributed-slave-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-distributed-slave-client</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>jcl-over-slf4j</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>javax.jdo</groupId>
+      <artifactId>jdo2-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-jdo2</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>plexus-spring</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-component-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-utils</artifactId>
     </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-taskqueue</artifactId>
     </dependency>
-	<dependency>
+    <dependency>
+      <groupId>org.apache.archiva</groupId>
+      <artifactId>archiva-model</artifactId>
+    </dependency>
+    <dependency>
       <groupId>org.apache.archiva</groupId>
       <artifactId>archiva-common</artifactId>
-      <version>${archiva.version}</version>
     </dependency>
     <dependency>
       <groupId>org.apache.archiva</groupId>
       <artifactId>archiva-core-consumers</artifactId>
-      <version>${archiva.version}</version>
-      <exclusions>
-        <exclusion>
-          <groupId>org.apache.archiva</groupId>
-          <artifactId>archiva-database</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>org.apache.archiva</groupId>
-          <artifactId>archiva-configuration</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>org.apache.archiva</groupId>
-          <artifactId>archiva-indexer</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>org.apache.archiva</groupId>
-          <artifactId>archiva-consumer-api</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>org.apache.archiva</groupId>
-          <artifactId>archiva-repository-layer</artifactId>
-        </exclusion>
-      </exclusions>
     </dependency>
     <dependency>
       <groupId>org.apache.archiva</groupId>
       <artifactId>archiva-repository-layer</artifactId>
-      <version>${archiva.version}</version>
-      <exclusions>
-        <exclusion>
-          <groupId>org.apache.archiva</groupId>
-          <artifactId>archiva-configuration</artifactId>
-        </exclusion>
-      </exclusions>
     </dependency>
-    
+
     <!-- === Testing Dependencies === -->
     <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-simple</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
       <groupId>hsqldb</groupId>
       <artifactId>hsqldb</artifactId>
       <scope>test</scope>
@@ -99,7 +134,7 @@
       <scope>test</scope>
     </dependency>
   </dependencies>
-  
+
   <build>
     <plugins>
       <plugin>
@@ -108,12 +143,21 @@
         <executions>
           <execution>
             <id>generate</id>
+            <phase>generate-resources</phase>
             <goals>
               <goal>descriptor</goal>
             </goals>
           </execution>
           <execution>
             <id>merge</id>
+            <phase>process-resources</phase>
+            <configuration>
+              <descriptors>
+                <descriptor>${basedir}/src/main/resources/META-INF/plexus/components-fragment.xml</descriptor>
+                <descriptor>${project.build.outputDirectory}/META-INF/plexus/components.xml</descriptor>
+              </descriptors>
+              <output>${project.build.outputDirectory}/META-INF/plexus/components.xml</output>
+            </configuration>
             <goals>
               <goal>merge-descriptors</goal>
             </goals>
@@ -121,10 +165,5 @@
         </executions>
       </plugin>
     </plugins>
-    <testResources>
-      <testResource>
-        <directory>src/test/resources</directory>
-      </testResource>
-    </testResources>
   </build>
 </project>
diff --git a/continuum-purge/src/main/java/org/apache/continuum/purge/ContinuumPurgeConstants.java b/continuum-purge/src/main/java/org/apache/continuum/purge/ContinuumPurgeConstants.java
index e99b3f3..e2210d6 100644
--- a/continuum-purge/src/main/java/org/apache/continuum/purge/ContinuumPurgeConstants.java
+++ b/continuum-purge/src/main/java/org/apache/continuum/purge/ContinuumPurgeConstants.java
@@ -31,4 +31,16 @@
     public static final String PURGE_DIRECTORY_RELEASES = "releases";
 
     public static final String PURGE_DIRECTORY_BUILDOUTPUT = "buildOutput";
+
+    public static final String PURGE = "PURGE";
+
+    public static final String PURGE_REPO_CONTENTS = "Purge All Repository Contents";
+
+    public static final String PURGE_DIR_CONTENTS = "Purge All Directory Contents";
+
+    public static final String PURGE_ARTIFACT = "Purge Artifact File";
+
+    public static final String PURGE_FILE = "Purge Support File";
+
+    public static final String PURGE_PROJECT = "Purge Project";
 }
diff --git a/continuum-purge/src/main/java/org/apache/continuum/purge/DefaultPurgeConfigurationService.java b/continuum-purge/src/main/java/org/apache/continuum/purge/DefaultPurgeConfigurationService.java
index 1a7bd89..20cf0cf 100644
--- a/continuum-purge/src/main/java/org/apache/continuum/purge/DefaultPurgeConfigurationService.java
+++ b/continuum-purge/src/main/java/org/apache/continuum/purge/DefaultPurgeConfigurationService.java
@@ -20,10 +20,12 @@
  */
 
 import org.apache.continuum.dao.DirectoryPurgeConfigurationDao;
+import org.apache.continuum.dao.DistributedDirectoryPurgeConfigurationDao;
 import org.apache.continuum.dao.LocalRepositoryDao;
 import org.apache.continuum.dao.RepositoryPurgeConfigurationDao;
 import org.apache.continuum.model.repository.AbstractPurgeConfiguration;
 import org.apache.continuum.model.repository.DirectoryPurgeConfiguration;
+import org.apache.continuum.model.repository.DistributedDirectoryPurgeConfiguration;
 import org.apache.continuum.model.repository.LocalRepository;
 import org.apache.continuum.model.repository.RepositoryPurgeConfiguration;
 import org.apache.continuum.purge.repository.content.RepositoryManagedContent;
@@ -65,6 +67,11 @@
      */
     private RepositoryPurgeConfigurationDao repositoryPurgeConfigurationDao;
 
+    /**
+     * @plexus.requirement
+     */
+    private DistributedDirectoryPurgeConfigurationDao distributedDirectoryPurgeConfigurationDao;
+
     private PlexusContainer container;
 
     public AbstractPurgeConfiguration addPurgeConfiguration( AbstractPurgeConfiguration purgeConfig )
@@ -80,6 +87,11 @@
         {
             purgeConfiguration = addDirectoryPurgeConfiguration( (DirectoryPurgeConfiguration) purgeConfig );
         }
+        else if ( purgeConfig instanceof DistributedDirectoryPurgeConfiguration )
+        {
+            purgeConfiguration = addDistributedDirectoryPurgeConfiguration(
+                (DistributedDirectoryPurgeConfiguration) purgeConfig );
+        }
 
         return purgeConfiguration;
     }
@@ -95,6 +107,10 @@
         {
             updateDirectoryPurgeConfiguration( (DirectoryPurgeConfiguration) purgeConfig );
         }
+        else if ( purgeConfig instanceof DistributedDirectoryPurgeConfiguration )
+        {
+            updateDistributedDirectoryPurgeConfiguration( (DistributedDirectoryPurgeConfiguration) purgeConfig );
+        }
     }
 
     public void removePurgeConfiguration( int purgeConfigId )
@@ -110,12 +126,16 @@
         {
             removeDirectoryPurgeConfiguration( (DirectoryPurgeConfiguration) purgeConfig );
         }
+        else if ( purgeConfig instanceof DistributedDirectoryPurgeConfiguration )
+        {
+            removeDistributedDirectoryPurgeConfiguration( (DistributedDirectoryPurgeConfiguration) purgeConfig );
+        }
     }
 
     public DirectoryPurgeConfiguration addDirectoryPurgeConfiguration( DirectoryPurgeConfiguration dirPurge )
         throws PurgeConfigurationServiceException
     {
-        DirectoryPurgeConfiguration dirPurgeConfig = null;
+        DirectoryPurgeConfiguration dirPurgeConfig;
 
         try
         {
@@ -132,7 +152,7 @@
     public RepositoryPurgeConfiguration addRepositoryPurgeConfiguration( RepositoryPurgeConfiguration repoPurge )
         throws PurgeConfigurationServiceException
     {
-        RepositoryPurgeConfiguration repoPurgeConfig = null;
+        RepositoryPurgeConfiguration repoPurgeConfig;
 
         try
         {
@@ -210,6 +230,11 @@
         return directoryPurgeConfigurationDao.getDirectoryPurgeConfigurationsBySchedule( scheduleId );
     }
 
+    public List<DirectoryPurgeConfiguration> getEnableDirectoryPurgeConfigurationsBySchedule( int scheduleId )
+    {
+        return directoryPurgeConfigurationDao.getEnableDirectoryPurgeConfigurationsBySchedule( scheduleId );
+    }
+
     public List<RepositoryPurgeConfiguration> getRepositoryPurgeConfigurationsByRepository( int repositoryId )
     {
         return repositoryPurgeConfigurationDao.getRepositoryPurgeConfigurationsByLocalRepository( repositoryId );
@@ -220,6 +245,11 @@
         return repositoryPurgeConfigurationDao.getRepositoryPurgeConfigurationsBySchedule( scheduleId );
     }
 
+    public List<RepositoryPurgeConfiguration> getEnableRepositoryPurgeConfigurationsBySchedule( int scheduleId )
+    {
+        return repositoryPurgeConfigurationDao.getEnableRepositoryPurgeConfigurationsBySchedule( scheduleId );
+    }
+
     public void removeDirectoryPurgeConfiguration( DirectoryPurgeConfiguration purgeConfig )
         throws PurgeConfigurationServiceException
     {
@@ -331,6 +361,18 @@
             }
         }
 
+        if ( purgeConfig == null )
+        {
+            try
+            {
+                purgeConfig = getDistributedDirectoryPurgeConfiguration( purgeConfigId );
+            }
+            catch ( PurgeConfigurationServiceException e )
+            {
+                // purgeConfigId is not of type directory purge configuration
+            }
+        }
+
         return purgeConfig;
     }
 
@@ -343,8 +385,8 @@
 
             RepositoryManagedContent repoContent;
 
-            repoContent =
-                (RepositoryManagedContent) container.lookup( RepositoryManagedContent.class, repository.getLayout() );
+            repoContent = (RepositoryManagedContent) container.lookup( RepositoryManagedContent.class,
+                                                                       repository.getLayout() );
             repoContent.setRepository( repository );
 
             return repoContent;
@@ -366,6 +408,81 @@
         }
     }
 
+    public List<DistributedDirectoryPurgeConfiguration> getAllDistributedDirectoryPurgeConfigurations()
+    {
+        return distributedDirectoryPurgeConfigurationDao.getAllDistributedDirectoryPurgeConfigurations();
+    }
+
+    public DistributedDirectoryPurgeConfiguration addDistributedDirectoryPurgeConfiguration(
+        DistributedDirectoryPurgeConfiguration dirPurge )
+        throws PurgeConfigurationServiceException
+    {
+        DistributedDirectoryPurgeConfiguration dirPurgeConfig;
+
+        try
+        {
+            dirPurgeConfig = distributedDirectoryPurgeConfigurationDao.addDistributedDirectoryPurgeConfiguration(
+                dirPurge );
+        }
+        catch ( ContinuumStoreException e )
+        {
+            throw new PurgeConfigurationServiceException( e.getMessage(), e );
+        }
+
+        return dirPurgeConfig;
+
+    }
+
+    public DistributedDirectoryPurgeConfiguration getDistributedDirectoryPurgeConfiguration( int dirPurgeId )
+        throws PurgeConfigurationServiceException
+    {
+        try
+        {
+            return distributedDirectoryPurgeConfigurationDao.getDistributedDirectoryPurgeConfiguration( dirPurgeId );
+        }
+        catch ( ContinuumObjectNotFoundException e )
+        {
+            throw new PurgeConfigurationServiceException( e.getMessage(), e );
+        }
+        catch ( ContinuumStoreException e )
+        {
+            throw new PurgeConfigurationServiceException( e.getMessage(), e );
+        }
+    }
+
+    public void updateDistributedDirectoryPurgeConfiguration( DistributedDirectoryPurgeConfiguration dirPurge )
+        throws PurgeConfigurationServiceException
+    {
+        try
+        {
+            distributedDirectoryPurgeConfigurationDao.updateDistributedDirectoryPurgeConfiguration( dirPurge );
+        }
+        catch ( ContinuumStoreException e )
+        {
+            throw new PurgeConfigurationServiceException( e.getMessage(), e );
+        }
+    }
+
+    public void removeDistributedDirectoryPurgeConfiguration( DistributedDirectoryPurgeConfiguration purgeConfig )
+        throws PurgeConfigurationServiceException
+    {
+        try
+        {
+            distributedDirectoryPurgeConfigurationDao.removeDistributedDirectoryPurgeConfiguration( purgeConfig );
+        }
+        catch ( ContinuumStoreException e )
+        {
+            throw new PurgeConfigurationServiceException( e.getMessage(), e );
+        }
+    }
+
+    public List<DistributedDirectoryPurgeConfiguration> getEnableDistributedDirectoryPurgeConfigurationsBySchedule(
+        int scheduleId )
+    {
+        return distributedDirectoryPurgeConfigurationDao.getEnableDistributedDirectoryPurgeConfigurationsBySchedule(
+            scheduleId );
+    }
+
     public void contextualize( Context context )
         throws ContextException
     {
diff --git a/continuum-purge/src/main/java/org/apache/continuum/purge/controller/DirectoryPurgeController.java b/continuum-purge/src/main/java/org/apache/continuum/purge/controller/DirectoryPurgeController.java
index 00f3103..5c26d0b 100644
--- a/continuum-purge/src/main/java/org/apache/continuum/purge/controller/DirectoryPurgeController.java
+++ b/continuum-purge/src/main/java/org/apache/continuum/purge/controller/DirectoryPurgeController.java
@@ -38,12 +38,19 @@
 public class DirectoryPurgeController
     implements PurgeController
 {
-    private Logger log = LoggerFactory.getLogger( DirectoryPurgeController.class );
+    private static final Logger log = LoggerFactory.getLogger( DirectoryPurgeController.class );
 
     private ContinuumPurgeExecutor purgeExecutor;
 
+    public void doPurge( AbstractPurgeConfiguration purgeConfig )
+    {
+        DirectoryPurgeConfiguration dirPurge = (DirectoryPurgeConfiguration) purgeConfig;
+        doPurge( dirPurge.getLocation() );
+    }
+
     public void doPurge( String path )
     {
+        log.info( "--- Start: Purging directory path '{}'---", path );
         try
         {
             purgeExecutor.purge( path );
@@ -52,6 +59,7 @@
         {
             log.error( e.getMessage(), e );
         }
+        log.info( "--- End: Purging directory path '{}'---", path );
     }
 
     public void initializeExecutors( AbstractPurgeConfiguration purgeConfig )
@@ -70,8 +78,8 @@
         }
         else
         {
-            purgeExecutor =
-                new RetentionCountDirectoryPurgeExecutor( dirPurge.getRetentionCount(), dirPurge.getDirectoryType() );
+            purgeExecutor = new RetentionCountDirectoryPurgeExecutor( dirPurge.getRetentionCount(),
+                                                                      dirPurge.getDirectoryType() );
         }
     }
 }
diff --git a/continuum-purge/src/main/java/org/apache/continuum/purge/controller/DistributedDirectoryPurgeController.java b/continuum-purge/src/main/java/org/apache/continuum/purge/controller/DistributedDirectoryPurgeController.java
new file mode 100644
index 0000000..78d169d
--- /dev/null
+++ b/continuum-purge/src/main/java/org/apache/continuum/purge/controller/DistributedDirectoryPurgeController.java
@@ -0,0 +1,96 @@
+package org.apache.continuum.purge.controller;
+
+/*
+ * 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 org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportClient;
+import org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportService;
+import org.apache.continuum.model.repository.AbstractPurgeConfiguration;
+import org.apache.continuum.model.repository.DistributedDirectoryPurgeConfiguration;
+import org.apache.continuum.purge.executor.ContinuumPurgeExecutorException;
+import org.apache.maven.continuum.configuration.ConfigurationService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.URL;
+
+/**
+ * DirectoryPurgeController
+ *
+ * @author
+ * @plexus.component role="org.apache.continuum.purge.controller.PurgeController" role-hint="purge-distributed-directory"
+ */
+public class DistributedDirectoryPurgeController
+    implements PurgeController
+{
+    private static final Logger log = LoggerFactory.getLogger( DistributedDirectoryPurgeController.class );
+
+    /**
+     * @plexus.requirement
+     */
+    private ConfigurationService configurationService;
+
+    private SlaveBuildAgentTransportService transportClient;
+
+    public void doPurge( String path )
+    {
+        log.warn( "doPurge( String ) is not supported for DistributedDirectoryPurgeController" );
+    }
+
+    public void doPurge( AbstractPurgeConfiguration purgeConfig )
+    {
+        DistributedDirectoryPurgeConfiguration dirPurge = (DistributedDirectoryPurgeConfiguration) purgeConfig;
+        try
+        {
+            transportClient.ping();
+
+            StringBuilder logMsg = new StringBuilder().append(
+                "Executing directory purge with the following settings[directoryType=" ).
+                append( dirPurge.getDirectoryType() ).append( ",daysOlder=" ).
+                append( dirPurge.getDaysOlder() ).append( ", retentionCount=" ).
+                append( dirPurge.getRetentionCount() ).append( ", deleteAll=" ).
+                append( dirPurge.isDeleteAll() ).append( "]" );
+
+            log.debug( logMsg.toString() );
+
+            transportClient.executeDirectoryPurge( dirPurge.getDirectoryType(), dirPurge.getDaysOlder(),
+                                                   dirPurge.getRetentionCount(), dirPurge.isDeleteAll() );
+        }
+        catch ( Exception e )
+        {
+            log.error( "Unable to execute purge: " + e.getMessage(), e );
+        }
+    }
+
+    public void initializeExecutors( AbstractPurgeConfiguration purgeConfig )
+        throws ContinuumPurgeExecutorException
+    {
+        DistributedDirectoryPurgeConfiguration dirPurge = (DistributedDirectoryPurgeConfiguration) purgeConfig;
+
+        try
+        {
+            transportClient = new SlaveBuildAgentTransportClient( new URL( dirPurge.getBuildAgentUrl() ), "",
+                                                                  configurationService.getSharedSecretPassword() );
+        }
+        catch ( Exception e )
+        {
+            throw new ContinuumPurgeExecutorException( e.getMessage(), e );
+        }
+    }
+}
diff --git a/continuum-purge/src/main/java/org/apache/continuum/purge/controller/RepositoryPurgeController.java b/continuum-purge/src/main/java/org/apache/continuum/purge/controller/RepositoryPurgeController.java
index 21770df..5eb62b7 100644
--- a/continuum-purge/src/main/java/org/apache/continuum/purge/controller/RepositoryPurgeController.java
+++ b/continuum-purge/src/main/java/org/apache/continuum/purge/controller/RepositoryPurgeController.java
@@ -43,7 +43,7 @@
 public class RepositoryPurgeController
     implements PurgeController
 {
-    private Logger log = LoggerFactory.getLogger( RepositoryPurgeController.class );
+    private static final Logger log = LoggerFactory.getLogger( RepositoryPurgeController.class );
 
     private ContinuumPurgeExecutor purgeExecutor;
 
@@ -65,8 +65,8 @@
 
         try
         {
-            repositoryContent =
-                purgeConfigurationService.getManagedRepositoryContent( repoPurge.getRepository().getId() );
+            repositoryContent = purgeConfigurationService.getManagedRepositoryContent(
+                repoPurge.getRepository().getId() );
         }
         catch ( PurgeConfigurationServiceException e )
         {
@@ -86,8 +86,8 @@
             }
             else
             {
-                purgeExecutor =
-                    new RetentionCountRepositoryPurgeExecutor( repositoryContent, repoPurge.getRetentionCount() );
+                purgeExecutor = new RetentionCountRepositoryPurgeExecutor( repositoryContent,
+                                                                           repoPurge.getRetentionCount() );
             }
 
             purgeReleasedSnapshotsExecutor = new ReleasedSnapshotsRepositoryPurgeExecutor( repositoryContent );
@@ -95,6 +95,16 @@
         }
     }
 
+    public void doPurge( AbstractPurgeConfiguration purgeConfig )
+    {
+        RepositoryPurgeConfiguration repoPurge = (RepositoryPurgeConfiguration) purgeConfig;
+        log.info( "--- Start: Purging repository [{}] {} ---", repoPurge.getRepository().getId(),
+                  repoPurge.getRepository().getLocation() );
+        doPurge( repoPurge.getRepository().getLocation() );
+        log.info( "--- End: Purging repository [{}] {} ---", repoPurge.getRepository().getId(),
+                  repoPurge.getRepository().getLocation() );
+    }
+
     public void doPurge( String path )
     {
         try
diff --git a/continuum-purge/src/main/java/org/apache/continuum/purge/executor/AbstractContinuumPurgeExecutor.java b/continuum-purge/src/main/java/org/apache/continuum/purge/executor/AbstractContinuumPurgeExecutor.java
index 648cd12..9f08870 100644
--- a/continuum-purge/src/main/java/org/apache/continuum/purge/executor/AbstractContinuumPurgeExecutor.java
+++ b/continuum-purge/src/main/java/org/apache/continuum/purge/executor/AbstractContinuumPurgeExecutor.java
@@ -19,6 +19,7 @@
  * under the License.
  */
 
+import org.apache.continuum.purge.ContinuumPurgeConstants;
 import org.apache.continuum.purge.repository.content.RepositoryManagedContent;
 import org.apache.maven.archiva.consumers.core.repository.ArtifactFilenameFilter;
 import org.apache.maven.archiva.model.ArtifactReference;
@@ -37,8 +38,8 @@
 public abstract class AbstractContinuumPurgeExecutor
     implements ContinuumPurgeExecutor
 {
-    private Logger log = LoggerFactory.getLogger( AbstractContinuumPurgeExecutor.class );
-    
+    private static final Logger log = LoggerFactory.getLogger( AbstractContinuumPurgeExecutor.class );
+
     public void purge( Set<ArtifactReference> references, RepositoryManagedContent repository )
     {
         if ( references != null && !references.isEmpty() )
@@ -47,7 +48,7 @@
             {
                 File artifactFile = repository.toFile( reference );
                 artifactFile.delete();
-                log.info( "Purge artifact " + artifactFile.getName() );
+                log.info( ContinuumPurgeConstants.PURGE_ARTIFACT + " - " + artifactFile.getName() );
                 purgeSupportFiles( artifactFile, artifactFile.getName() );
                 // purge maven metadata
                 purgeSupportFiles( artifactFile.getParentFile(), "maven-metadata" );
@@ -83,8 +84,8 @@
             if ( file.exists() && file.isFile() )
             {
                 file.delete();
-                log.info( "Purge support file: " + file.getName() );
+                log.info( ContinuumPurgeConstants.PURGE_FILE + " - " + file.getName() );
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/continuum-purge/src/main/java/org/apache/continuum/purge/executor/CleanAllPurgeExecutor.java b/continuum-purge/src/main/java/org/apache/continuum/purge/executor/CleanAllPurgeExecutor.java
index 84ad16f..5ae53a7 100644
--- a/continuum-purge/src/main/java/org/apache/continuum/purge/executor/CleanAllPurgeExecutor.java
+++ b/continuum-purge/src/main/java/org/apache/continuum/purge/executor/CleanAllPurgeExecutor.java
@@ -23,6 +23,8 @@
 import org.apache.continuum.purge.ContinuumPurgeConstants;
 import org.apache.maven.archiva.consumers.core.repository.ArtifactFilenameFilter;
 import org.codehaus.plexus.util.FileUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.io.File;
 import java.io.FileFilter;
@@ -35,7 +37,9 @@
 public class CleanAllPurgeExecutor
     extends AbstractContinuumPurgeExecutor
 {
-    private String purgeType;
+    private Logger log = LoggerFactory.getLogger( CleanAllPurgeExecutor.class );
+
+    private final String purgeType;
 
     public CleanAllPurgeExecutor( String purgeType )
     {
@@ -71,6 +75,7 @@
             throw new ContinuumPurgeExecutorException( "Error while purging all artifacts or directories in " + path,
                                                        e );
         }
+        log.info( ContinuumPurgeConstants.PURGE_REPO_CONTENTS + " - " + path );
     }
 
     private void purgeReleases( String path )
@@ -87,6 +92,7 @@
             for ( File releaseDir : releasesDir )
             {
                 FileUtils.deleteDirectory( releaseDir );
+                log.info( ContinuumPurgeConstants.PURGE_DIR_CONTENTS + " - " + releaseDir.getName() );
             }
         }
         catch ( IOException e )
@@ -109,6 +115,7 @@
             for ( File projectDir : projectsDir )
             {
                 FileUtils.cleanDirectory( projectDir );
+                log.info( ContinuumPurgeConstants.PURGE_DIR_CONTENTS + " - " + projectDir.getName() );
             }
         }
         catch ( IOException e )
diff --git a/continuum-purge/src/main/java/org/apache/continuum/purge/executor/DaysOldDirectoryPurgeExecutor.java b/continuum-purge/src/main/java/org/apache/continuum/purge/executor/DaysOldDirectoryPurgeExecutor.java
index c3bfaa5..3bc2182 100644
--- a/continuum-purge/src/main/java/org/apache/continuum/purge/executor/DaysOldDirectoryPurgeExecutor.java
+++ b/continuum-purge/src/main/java/org/apache/continuum/purge/executor/DaysOldDirectoryPurgeExecutor.java
@@ -25,6 +25,8 @@
 import org.apache.commons.lang.time.DateUtils;
 import org.apache.continuum.purge.ContinuumPurgeConstants;
 import org.apache.maven.archiva.consumers.core.repository.ArtifactFilenameFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.io.File;
 import java.io.FileFilter;
@@ -40,11 +42,13 @@
     extends AbstractContinuumPurgeExecutor
     implements ContinuumPurgeExecutor
 {
-    private int daysOlder;
+    private Logger log = LoggerFactory.getLogger( DaysOldDirectoryPurgeExecutor.class );
 
-    private int retentionCount;
+    private final int daysOlder;
 
-    private String directoryType;
+    private final int retentionCount;
+
+    private final String directoryType;
 
     public DaysOldDirectoryPurgeExecutor( int daysOlder, int retentionCount, String directoryType )
     {
@@ -99,6 +103,7 @@
             {
                 try
                 {
+                    log.info( ContinuumPurgeConstants.PURGE_DIR_CONTENTS + " - " + dir.getName() );
                     FileUtils.deleteDirectory( dir );
                     countToPurge--;
                 }
@@ -145,11 +150,13 @@
                 {
                     try
                     {
+                        log.info( ContinuumPurgeConstants.PURGE_DIR_CONTENTS + " - " + buildDir.getName() );
                         FileUtils.deleteDirectory( buildDir );
                         File logFile = new File( buildDir.getAbsoluteFile() + ".log.txt" );
 
                         if ( logFile.exists() )
                         {
+                            log.info( ContinuumPurgeConstants.PURGE_FILE + " - " + logFile.getName() );
                             logFile.delete();
                         }
 
diff --git a/continuum-purge/src/main/java/org/apache/continuum/purge/executor/DaysOldRepositoryPurgeExecutor.java b/continuum-purge/src/main/java/org/apache/continuum/purge/executor/DaysOldRepositoryPurgeExecutor.java
index 64e1891..a1e3af4 100644
--- a/continuum-purge/src/main/java/org/apache/continuum/purge/executor/DaysOldRepositoryPurgeExecutor.java
+++ b/continuum-purge/src/main/java/org/apache/continuum/purge/executor/DaysOldRepositoryPurgeExecutor.java
@@ -48,13 +48,13 @@
     extends AbstractContinuumPurgeExecutor
     implements ContinuumPurgeExecutor
 {
-    private int daysOlder;
+    private final int daysOlder;
 
-    private int retentionCount;
+    private final int retentionCount;
 
-    private RepositoryManagedContent repository;
+    private final RepositoryManagedContent repository;
 
-    private SimpleDateFormat timestampParser;
+    private final SimpleDateFormat timestampParser;
 
     public DaysOldRepositoryPurgeExecutor( RepositoryManagedContent repository, int daysOlder, int retentionCount )
     {
@@ -107,8 +107,8 @@
                     break;
                 }
 
-                ArtifactReference newArtifactReference =
-                    repository.toArtifactReference( artifactFile.getAbsolutePath() );
+                ArtifactReference newArtifactReference = repository.toArtifactReference(
+                    artifactFile.getAbsolutePath() );
                 newArtifactReference.setVersion( version );
 
                 File newArtifactFile = repository.toFile( newArtifactReference );
diff --git a/continuum-purge/src/main/java/org/apache/continuum/purge/executor/ReleasedSnapshotsRepositoryPurgeExecutor.java b/continuum-purge/src/main/java/org/apache/continuum/purge/executor/ReleasedSnapshotsRepositoryPurgeExecutor.java
index 04498c1..404e62a 100644
--- a/continuum-purge/src/main/java/org/apache/continuum/purge/executor/ReleasedSnapshotsRepositoryPurgeExecutor.java
+++ b/continuum-purge/src/main/java/org/apache/continuum/purge/executor/ReleasedSnapshotsRepositoryPurgeExecutor.java
@@ -19,6 +19,7 @@
  * under the License.
  */
 
+import org.apache.continuum.purge.ContinuumPurgeConstants;
 import org.apache.continuum.purge.repository.content.RepositoryManagedContent;
 import org.apache.maven.archiva.common.utils.VersionComparator;
 import org.apache.maven.archiva.common.utils.VersionUtil;
@@ -27,6 +28,8 @@
 import org.apache.maven.archiva.model.VersionedReference;
 import org.apache.maven.archiva.repository.ContentNotFoundException;
 import org.apache.maven.archiva.repository.layout.LayoutException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -41,7 +44,9 @@
 public class ReleasedSnapshotsRepositoryPurgeExecutor
     extends AbstractContinuumPurgeExecutor
 {
-    private RepositoryManagedContent repository;
+    private Logger log = LoggerFactory.getLogger( ReleasedSnapshotsRepositoryPurgeExecutor.class );
+
+    private final RepositoryManagedContent repository;
 
     public ReleasedSnapshotsRepositoryPurgeExecutor( RepositoryManagedContent repository )
     {
@@ -107,6 +112,8 @@
                     versionRef.setVersion( version );
                     repository.deleteVersion( versionRef );
 
+                    log.info( ContinuumPurgeConstants.PURGE_PROJECT + " - " + VersionedReference.toKey( versionRef ) );
+
                     removeMetadata( versionRef );
                 }
             }
@@ -131,4 +138,4 @@
 
         purgeSupportFiles( projectDir, "maven-metadata" );
     }
-}
\ No newline at end of file
+}
diff --git a/continuum-purge/src/main/java/org/apache/continuum/purge/executor/RetentionCountDirectoryPurgeExecutor.java b/continuum-purge/src/main/java/org/apache/continuum/purge/executor/RetentionCountDirectoryPurgeExecutor.java
index 3176f28..6f76b69 100644
--- a/continuum-purge/src/main/java/org/apache/continuum/purge/executor/RetentionCountDirectoryPurgeExecutor.java
+++ b/continuum-purge/src/main/java/org/apache/continuum/purge/executor/RetentionCountDirectoryPurgeExecutor.java
@@ -38,9 +38,9 @@
     extends AbstractContinuumPurgeExecutor
     implements ContinuumPurgeExecutor
 {
-    private int retentionCount;
+    private final int retentionCount;
 
-    private String directoryType;
+    private final String directoryType;
 
     public RetentionCountDirectoryPurgeExecutor( int retentionCount, String directoryType )
     {
@@ -81,7 +81,7 @@
 
         for ( File file : files )
         {
-            if ( countToPurge-- <= 0 )
+            if ( countToPurge <= 0 )
             {
                 break;
             }
diff --git a/continuum-purge/src/main/java/org/apache/continuum/purge/executor/RetentionCountRepositoryPurgeExecutor.java b/continuum-purge/src/main/java/org/apache/continuum/purge/executor/RetentionCountRepositoryPurgeExecutor.java
index eb4f017..32c6fd1 100644
--- a/continuum-purge/src/main/java/org/apache/continuum/purge/executor/RetentionCountRepositoryPurgeExecutor.java
+++ b/continuum-purge/src/main/java/org/apache/continuum/purge/executor/RetentionCountRepositoryPurgeExecutor.java
@@ -42,9 +42,9 @@
     extends AbstractContinuumPurgeExecutor
     implements ContinuumPurgeExecutor
 {
-    private int retentionCount;
+    private final int retentionCount;
 
-    private RepositoryManagedContent repository;
+    private final RepositoryManagedContent repository;
 
     public RetentionCountRepositoryPurgeExecutor( RepositoryManagedContent repository, int retentionCount )
     {
diff --git a/continuum-purge/src/main/java/org/apache/continuum/purge/repository/content/ManagedDefaultRepositoryContent.java b/continuum-purge/src/main/java/org/apache/continuum/purge/repository/content/ManagedDefaultRepositoryContent.java
index 297cfbc..130c0ad 100644
--- a/continuum-purge/src/main/java/org/apache/continuum/purge/repository/content/ManagedDefaultRepositoryContent.java
+++ b/continuum-purge/src/main/java/org/apache/continuum/purge/repository/content/ManagedDefaultRepositoryContent.java
@@ -49,15 +49,15 @@
 public class ManagedDefaultRepositoryContent
     implements RepositoryManagedContent
 {
-    public static final String MAVEN_METADATA = "maven-metadata.xml";
+    private static final String MAVEN_METADATA = "maven-metadata.xml";
 
-    protected static final char PATH_SEPARATOR = '/';
+    private static final char PATH_SEPARATOR = '/';
 
-    protected static final char GROUP_SEPARATOR = '.';
+    private static final char GROUP_SEPARATOR = '.';
 
-    protected static final char ARTIFACT_SEPARATOR = '-';
+    private static final char ARTIFACT_SEPARATOR = '-';
 
-    private PathParser defaultPathParser = new DefaultPathParser();
+    private final PathParser defaultPathParser = new DefaultPathParser();
 
     /**
      * @plexus.requirement role-hint="file-types"
@@ -112,16 +112,15 @@
         Set<ArtifactReference> foundArtifacts = new HashSet<ArtifactReference>();
 
         // First gather up the versions found as artifacts in the managed repository.
-        File repoFiles[] = repoDir.listFiles();
-        for ( int i = 0; i < repoFiles.length; i++ )
+        for ( File repoFile : repoDir.listFiles() )
         {
-            if ( repoFiles[i].isDirectory() )
+            if ( repoFile.isDirectory() )
             {
                 // Skip it. it's a directory.
                 continue;
             }
 
-            String relativePath = PathUtil.getRelative( repository.getLocation(), repoFiles[i] );
+            String relativePath = PathUtil.getRelative( repository.getLocation(), repoFile );
 
             if ( filetypes.matchesArtifactPattern( relativePath ) )
             {
@@ -155,7 +154,7 @@
      * information.
      *
      * @return the Set of available versions, based on the project reference.
-     * @throws LayoutException
+     * @throws ContentNotFoundException
      * @throws LayoutException
      */
     public Set<String> getVersions( ProjectReference reference )
@@ -188,17 +187,16 @@
         versionRef.setGroupId( reference.getGroupId() );
         versionRef.setArtifactId( reference.getArtifactId() );
 
-        File repoFiles[] = repoDir.listFiles();
-        for ( int i = 0; i < repoFiles.length; i++ )
+        for ( File repoFile : repoDir.listFiles() )
         {
-            if ( !repoFiles[i].isDirectory() )
+            if ( !repoFile.isDirectory() )
             {
                 // Skip it. not a directory.
                 continue;
             }
 
             // Test if dir has an artifact, which proves to us that it is a valid version directory.
-            String version = repoFiles[i].getName();
+            String version = repoFile.getName();
             versionRef.setVersion( version );
 
             if ( hasArtifact( versionRef ) )
@@ -239,16 +237,15 @@
         Set<String> foundVersions = new HashSet<String>();
 
         // First gather up the versions found as artifacts in the managed repository.
-        File repoFiles[] = repoDir.listFiles();
-        for ( int i = 0; i < repoFiles.length; i++ )
+        for ( File repoFile : repoDir.listFiles() )
         {
-            if ( repoFiles[i].isDirectory() )
+            if ( repoFile.isDirectory() )
             {
                 // Skip it. it's a directory.
                 continue;
             }
 
-            String relativePath = PathUtil.getRelative( repository.getLocation(), repoFiles[i] );
+            String relativePath = PathUtil.getRelative( repository.getLocation(), repoFile );
 
             if ( filetypes.matchesDefaultExclusions( relativePath ) )
             {
@@ -337,12 +334,11 @@
     /**
      * Get the first Artifact found in the provided VersionedReference location.
      *
-     * @param managedRepository the repository to search within.
-     * @param reference         the reference to the versioned reference to search within
+     * @param reference the reference to the versioned reference to search within
      * @return the ArtifactReference to the first artifact located within the versioned reference. or null if
      *         no artifact was found within the versioned reference.
      * @throws IOException     if the versioned reference is invalid (example: doesn't exist, or isn't a directory)
-     * @throws LayoutException
+     * @throws LayoutException if the path cannot be converted to an artifact reference.
      */
     private ArtifactReference getFirstArtifact( VersionedReference reference )
         throws LayoutException, IOException
@@ -360,7 +356,7 @@
         if ( !repoDir.exists() )
         {
             throw new IOException( "Unable to gather the list of snapshot versions on a non-existant directory: " +
-                repoDir.getAbsolutePath() );
+                                       repoDir.getAbsolutePath() );
         }
 
         if ( !repoDir.isDirectory() )
@@ -369,22 +365,19 @@
                 "Unable to gather the list of snapshot versions on a non-directory: " + repoDir.getAbsolutePath() );
         }
 
-        File repoFiles[] = repoDir.listFiles();
-        for ( int i = 0; i < repoFiles.length; i++ )
+        for ( File repoFile : repoDir.listFiles() )
         {
-            if ( repoFiles[i].isDirectory() )
+            if ( repoFile.isDirectory() )
             {
                 // Skip it. it's a directory.
                 continue;
             }
 
-            String relativePath = PathUtil.getRelative( repository.getLocation(), repoFiles[i] );
+            String relativePath = PathUtil.getRelative( repository.getLocation(), repoFile );
 
             if ( filetypes.matchesArtifactPattern( relativePath ) )
             {
-                ArtifactReference artifact = toArtifactReference( relativePath );
-
-                return artifact;
+                return toArtifactReference( relativePath );
             }
         }
 
diff --git a/continuum-purge/src/main/java/org/apache/continuum/purge/repository/content/ManagedLegacyRepositoryContent.java b/continuum-purge/src/main/java/org/apache/continuum/purge/repository/content/ManagedLegacyRepositoryContent.java
index a1235b4..b12e50c 100644
--- a/continuum-purge/src/main/java/org/apache/continuum/purge/repository/content/ManagedLegacyRepositoryContent.java
+++ b/continuum-purge/src/main/java/org/apache/continuum/purge/repository/content/ManagedLegacyRepositoryContent.java
@@ -338,8 +338,8 @@
             throw new IllegalArgumentException( "Artifact reference cannot be null" );
         }
 
-        return toPath( reference.getGroupId(), reference.getArtifactId(), reference.getVersion(), reference
-            .getClassifier(), reference.getType() );
+        return toPath( reference.getGroupId(), reference.getArtifactId(), reference.getVersion(),
+                       reference.getClassifier(), reference.getType() );
     }
 
     public void setRepository( LocalRepository repo )
@@ -380,16 +380,15 @@
 
     private void getRelatedArtifacts( File typeDir, ArtifactReference reference, Set<ArtifactReference> foundArtifacts )
     {
-        File repoFiles[] = typeDir.listFiles();
-        for ( int i = 0; i < repoFiles.length; i++ )
+        for ( File repoFile : typeDir.listFiles() )
         {
-            if ( repoFiles[i].isDirectory() )
+            if ( repoFile.isDirectory() )
             {
                 // Skip it. it's a directory.
                 continue;
             }
 
-            String relativePath = PathUtil.getRelative( repository.getLocation(), repoFiles[i] );
+            String relativePath = PathUtil.getRelative( repository.getLocation(), repoFile );
 
             if ( filetypes.matchesArtifactPattern( relativePath ) )
             {
@@ -412,16 +411,15 @@
 
     private void getVersionedVersions( File typeDir, VersionedReference reference, Set<String> foundVersions )
     {
-        File repoFiles[] = typeDir.listFiles();
-        for ( int i = 0; i < repoFiles.length; i++ )
+        for ( File repoFile : typeDir.listFiles() )
         {
-            if ( repoFiles[i].isDirectory() )
+            if ( repoFile.isDirectory() )
             {
                 // Skip it. it's a directory.
                 continue;
             }
 
-            String relativePath = PathUtil.getRelative( repository.getLocation(), repoFiles[i] );
+            String relativePath = PathUtil.getRelative( repository.getLocation(), repoFile );
 
             if ( filetypes.matchesArtifactPattern( relativePath ) )
             {
@@ -447,7 +445,7 @@
         StringBuffer path = new StringBuffer();
 
         path.append( groupId ).append( PATH_SEPARATOR );
-        path.append( getDirectory( classifier, type ) ).append( PATH_SEPARATOR );
+        path.append( getDirectory( type ) ).append( PATH_SEPARATOR );
 
         if ( version != null )
         {
@@ -464,9 +462,9 @@
         return path.toString();
     }
 
-    private String getDirectory( String classifier, String type )
+    private String getDirectory( String type )
     {
-        String dirname = (String) typeToDirectoryMap.get( type );
+        String dirname = typeToDirectoryMap.get( type );
 
         if ( dirname != null )
         {
diff --git a/continuum-purge/src/main/java/org/apache/continuum/purge/repository/scanner/RepositoryScannerInstance.java b/continuum-purge/src/main/java/org/apache/continuum/purge/repository/scanner/RepositoryScannerInstance.java
index a0b538c..addb58c 100644
--- a/continuum-purge/src/main/java/org/apache/continuum/purge/repository/scanner/RepositoryScannerInstance.java
+++ b/continuum-purge/src/main/java/org/apache/continuum/purge/repository/scanner/RepositoryScannerInstance.java
@@ -34,11 +34,11 @@
 public class RepositoryScannerInstance
     implements DirectoryWalkListener
 {
-    private Logger log = LoggerFactory.getLogger( RepositoryScannerInstance.class );
+    private static final Logger log = LoggerFactory.getLogger( RepositoryScannerInstance.class );
 
-    private LocalRepository repository;
+    private final LocalRepository repository;
 
-    private PurgeController purgeController;
+    private final PurgeController purgeController;
 
     public RepositoryScannerInstance( LocalRepository repository, PurgeController purgeController )
     {
diff --git a/continuum-purge/src/main/java/org/apache/continuum/purge/repository/utils/FileTypes.java b/continuum-purge/src/main/java/org/apache/continuum/purge/repository/utils/FileTypes.java
index f03bb49..cba5f89 100644
--- a/continuum-purge/src/main/java/org/apache/continuum/purge/repository/utils/FileTypes.java
+++ b/continuum-purge/src/main/java/org/apache/continuum/purge/repository/utils/FileTypes.java
@@ -62,7 +62,7 @@
             return false;
         }
 
-        for ( String pattern : (List<String>) artifactFileTypePatterns )
+        for ( String pattern : artifactFileTypePatterns )
         {
             if ( SelectorUtils.matchPath( pattern, relativePath, false ) )
             {
diff --git a/continuum-purge/src/main/java/org/apache/continuum/purge/repository/utils/FilenameParser.java b/continuum-purge/src/main/java/org/apache/continuum/purge/repository/utils/FilenameParser.java
index d7044f6..94c81d9 100644
--- a/continuum-purge/src/main/java/org/apache/continuum/purge/repository/utils/FilenameParser.java
+++ b/continuum-purge/src/main/java/org/apache/continuum/purge/repository/utils/FilenameParser.java
@@ -37,12 +37,12 @@
 
     private static final Pattern mavenPluginPattern = Pattern.compile( "(maven-.*-plugin)|(.*-maven-plugin)" );
 
-    private static final Pattern extensionPattern =
-        Pattern.compile( "(\\.tar\\.gz$)|(\\.tar\\.bz2$)|(\\.[\\-a-z0-9]*$)", Pattern.CASE_INSENSITIVE );
+    private static final Pattern extensionPattern = Pattern.compile(
+        "(\\.tar\\.gz$)|(\\.tar\\.bz2$)|(\\.[\\-a-z0-9]*$)", Pattern.CASE_INSENSITIVE );
 
     private static final Pattern section = Pattern.compile( "([^-]*)" );
 
-    private Matcher matcher;
+    private final Matcher matcher;
 
     public FilenameParser( String filename )
     {
diff --git a/continuum-purge/src/main/java/org/apache/continuum/purge/repository/utils/LegacyPathParser.java b/continuum-purge/src/main/java/org/apache/continuum/purge/repository/utils/LegacyPathParser.java
index 3c3f022..fc9f21e 100644
--- a/continuum-purge/src/main/java/org/apache/continuum/purge/repository/utils/LegacyPathParser.java
+++ b/continuum-purge/src/main/java/org/apache/continuum/purge/repository/utils/LegacyPathParser.java
@@ -57,8 +57,8 @@
         {
             // Illegal Path Parts Length.
             throw new LayoutException( INVALID_ARTIFACT_PATH +
-                "legacy paths should only have 3 parts [groupId]/[type]s/[artifactId]-[version].[type], found " +
-                pathParts.length + " instead." );
+                                           "legacy paths should only have 3 parts [groupId]/[type]s/[artifactId]-[version].[type], found " +
+                                           pathParts.length + " instead." );
         }
 
         // The Group ID.
@@ -71,7 +71,7 @@
         if ( !expectedType.endsWith( "s" ) )
         {
             throw new LayoutException( INVALID_ARTIFACT_PATH +
-                "legacy paths should have an expected type ending in [s] in the second part of the path." );
+                                           "legacy paths should have an expected type ending in [s] in the second part of the path." );
         }
 
         // The Filename.
@@ -148,8 +148,8 @@
 
         // Set Type
         String defaultExtension = expectedType.substring( 0, expectedType.length() - 1 );
-        artifact.setType(
-            ArtifactExtensionMapping.mapExtensionAndClassifierToType( classifier, extension, defaultExtension ) );
+        artifact.setType( ArtifactExtensionMapping.mapExtensionAndClassifierToType( classifier, extension,
+                                                                                    defaultExtension ) );
 
         // Sanity Check: does it have an extension?
         if ( StringUtils.isEmpty( artifact.getType() ) )
@@ -170,8 +170,9 @@
             if ( !expectedExtension.equals( extension ) )
             {
                 throw new LayoutException( INVALID_ARTIFACT_PATH + "mismatch on extension [" + extension +
-                    "] and layout specified type [" + artifact.getType() + "] (which maps to extension: [" +
-                    expectedExtension + "]) on path [" + path + "]" );
+                                               "] and layout specified type [" + artifact.getType() +
+                                               "] (which maps to extension: [" +
+                                               expectedExtension + "]) on path [" + path + "]" );
             }
         }
 
diff --git a/continuum-purge/src/main/java/org/apache/continuum/purge/task/PurgeTask.java b/continuum-purge/src/main/java/org/apache/continuum/purge/task/PurgeTask.java
index 427016f..5977dd0 100644
--- a/continuum-purge/src/main/java/org/apache/continuum/purge/task/PurgeTask.java
+++ b/continuum-purge/src/main/java/org/apache/continuum/purge/task/PurgeTask.java
@@ -29,7 +29,7 @@
 {
     private int purgeConfigurationId;
 
-    private long timestamp;
+    private final long timestamp;
 
     private long maxExecutionTime;
 
diff --git a/continuum-purge/src/main/java/org/apache/continuum/purge/task/PurgeTaskExecutor.java b/continuum-purge/src/main/java/org/apache/continuum/purge/task/PurgeTaskExecutor.java
index 4096cdf..4b0595d 100644
--- a/continuum-purge/src/main/java/org/apache/continuum/purge/task/PurgeTaskExecutor.java
+++ b/continuum-purge/src/main/java/org/apache/continuum/purge/task/PurgeTaskExecutor.java
@@ -21,6 +21,7 @@
 
 import org.apache.continuum.model.repository.AbstractPurgeConfiguration;
 import org.apache.continuum.model.repository.DirectoryPurgeConfiguration;
+import org.apache.continuum.model.repository.DistributedDirectoryPurgeConfiguration;
 import org.apache.continuum.model.repository.LocalRepository;
 import org.apache.continuum.model.repository.RepositoryPurgeConfiguration;
 import org.apache.continuum.purge.PurgeConfigurationService;
@@ -43,8 +44,6 @@
 public class PurgeTaskExecutor
     implements TaskExecutor, Contextualizable
 {
-    private PurgeController purgeController;
-
     /**
      * @plexus.requirement
      */
@@ -62,8 +61,8 @@
     {
         PurgeTask purgeTask = (PurgeTask) task;
 
-        AbstractPurgeConfiguration purgeConfig =
-            purgeConfigurationService.getPurgeConfiguration( purgeTask.getPurgeConfigurationId() );
+        AbstractPurgeConfiguration purgeConfig = purgeConfigurationService.getPurgeConfiguration(
+            purgeTask.getPurgeConfigurationId() );
 
         try
         {
@@ -79,13 +78,14 @@
                         "Error while executing purge repository task: no repository set" );
                 }
 
-                purgeController = (PurgeController) container.lookup( PurgeController.ROLE, "purge-repository" );
+                PurgeController purgeController = (PurgeController) container.lookup( PurgeController.ROLE,
+                                                                                      "purge-repository" );
 
                 purgeController.initializeExecutors( repoPurge );
 
                 if ( repoPurge.isDeleteAll() )
                 {
-                    purgeController.doPurge( repository.getLocation() );
+                    purgeController.doPurge( repoPurge );
                 }
                 else
                 {
@@ -96,12 +96,24 @@
             {
                 DirectoryPurgeConfiguration dirPurge = (DirectoryPurgeConfiguration) purgeConfig;
 
-                purgeController = (PurgeController) container.lookup( PurgeController.ROLE, "purge-directory" );
+                PurgeController purgeController = (PurgeController) container.lookup( PurgeController.ROLE,
+                                                                                      "purge-directory" );
 
                 purgeController.initializeExecutors( dirPurge );
 
                 purgeController.doPurge( dirPurge.getLocation() );
             }
+            else if ( purgeConfig instanceof DistributedDirectoryPurgeConfiguration )
+            {
+                DistributedDirectoryPurgeConfiguration dirPurge = (DistributedDirectoryPurgeConfiguration) purgeConfig;
+
+                PurgeController purgeController = (PurgeController) container.lookup( PurgeController.ROLE,
+                                                                                      "purge-distributed-directory" );
+
+                purgeController.initializeExecutors( dirPurge );
+
+                purgeController.doPurge( dirPurge );
+            }
 
         }
         catch ( ComponentLookupException e )
diff --git a/continuum-purge/src/main/resources/META-INF/plexus/components.xml b/continuum-purge/src/main/resources/META-INF/plexus/components-fragment.xml
similarity index 100%
rename from continuum-purge/src/main/resources/META-INF/plexus/components.xml
rename to continuum-purge/src/main/resources/META-INF/plexus/components-fragment.xml
diff --git a/continuum-purge/src/main/resources/log4j.xml b/continuum-purge/src/main/resources/log4j.xml
deleted file mode 100644
index dd86458..0000000
--- a/continuum-purge/src/main/resources/log4j.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
-<!-- ===================================================================== -->
-<!-- Log4j Configuration -->
-<!-- ===================================================================== -->
-
-<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
-  debug="false">
-
-  <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
-    <param name="Target" value="System.out"/>
-    <layout class="org.apache.log4j.PatternLayout">
-      <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}.%M](%L) %m%n"/>
-    </layout>
-  </appender>
-
-  <!-- quiet spring loading :-) -->
-  <category name="org.springframework">
-    <priority value="ERROR"/>
-  </category>
-  <category name="org.codehaus.plexus">
-    <priority value="ERROR"/>
-  </category>
-  
-  <category name="org.apache.commons">
-    <priority value="ERROR"/>
-  </category>  
-
-  <!-- JPOX -->
-  <category name="JPOX">
-    <priority value="WARN"/>
-  </category>
-  <category name="JPOX.RDBMS">
-    <priority value="ERROR"/>
-  </category>
-
-  <root>
-    <priority value="INFO"/>
-    <appender-ref ref="CONSOLE"/>
-  </root>
-
-</log4j:configuration>
\ No newline at end of file
diff --git a/continuum-purge/src/test/java/org/apache/continuum/purge/AbstractPurgeTest.java b/continuum-purge/src/test/java/org/apache/continuum/purge/AbstractPurgeTest.java
index 036709c..4ce966a 100644
--- a/continuum-purge/src/test/java/org/apache/continuum/purge/AbstractPurgeTest.java
+++ b/continuum-purge/src/test/java/org/apache/continuum/purge/AbstractPurgeTest.java
@@ -20,6 +20,7 @@
  */
 
 import org.apache.continuum.dao.DirectoryPurgeConfigurationDao;
+import org.apache.continuum.dao.DistributedDirectoryPurgeConfigurationDao;
 import org.apache.continuum.dao.LocalRepositoryDao;
 import org.apache.continuum.dao.RepositoryPurgeConfigurationDao;
 import org.apache.continuum.model.repository.DirectoryPurgeConfiguration;
@@ -30,12 +31,12 @@
 import org.codehaus.plexus.spring.PlexusInSpringTestCase;
 import org.jpox.SchemaTool;
 
-import javax.jdo.PersistenceManager;
-import javax.jdo.PersistenceManagerFactory;
 import java.io.File;
 import java.net.URL;
 import java.util.Map;
 import java.util.Properties;
+import javax.jdo.PersistenceManager;
+import javax.jdo.PersistenceManagerFactory;
 
 /**
  * @author Maria Catherine Tan
@@ -51,6 +52,8 @@
 
     private static final String TEST_DEFAULT_BUILDOUTPUT_DIR = "target/build-output-directory";
 
+    protected static final String TEST_BUILD_AGENT_URL = "http://localhost:8181/continuum-buildagent/xmlrpc";
+
     protected static final int TEST_DAYS_OLDER = 30;
 
     protected static final int TEST_RETENTION_COUNT = 2;
@@ -59,12 +62,16 @@
 
     protected static final String TEST_BUILDOUTPUT_DIRECTORY_TYPE = "buildOutput";
 
+    protected static final String TEST_WORKING_DIRECTORY_TYPE = "working";
+
     protected LocalRepositoryDao localRepositoryDao;
 
     protected DirectoryPurgeConfigurationDao directoryPurgeConfigurationDao;
 
     protected RepositoryPurgeConfigurationDao repositoryPurgeConfigurationDao;
 
+    protected DistributedDirectoryPurgeConfigurationDao distributedDirectoryPurgeConfigurationDao;
+
     protected RepositoryPurgeConfiguration defaultRepoPurge;
 
     protected DirectoryPurgeConfiguration defaultReleasesDirPurge;
@@ -83,10 +90,15 @@
 
         localRepositoryDao = (LocalRepositoryDao) lookup( LocalRepositoryDao.class.getName() );
 
-        repositoryPurgeConfigurationDao = (RepositoryPurgeConfigurationDao) lookup( RepositoryPurgeConfigurationDao.class );
-        
-        directoryPurgeConfigurationDao = (DirectoryPurgeConfigurationDao) lookup( DirectoryPurgeConfigurationDao.class );
-        
+        repositoryPurgeConfigurationDao = (RepositoryPurgeConfigurationDao) lookup(
+            RepositoryPurgeConfigurationDao.class );
+
+        directoryPurgeConfigurationDao = (DirectoryPurgeConfigurationDao) lookup(
+            DirectoryPurgeConfigurationDao.class );
+
+        distributedDirectoryPurgeConfigurationDao = (DistributedDirectoryPurgeConfigurationDao) lookup(
+            DistributedDirectoryPurgeConfigurationDao.class );
+
         if ( localRepositoryDao.getAllLocalRepositories().size() == 0 )
         {
             createDefaultRepository();
@@ -168,12 +180,11 @@
             System.setProperty( (String) entry.getKey(), (String) entry.getValue() );
         }
 
-        SchemaTool.createSchemaTables( new URL[]{getClass().getResource( "/META-INF/package.jdo" )}, new URL[]{}, null,
-                                       false, null );
+        SchemaTool.createSchemaTables( new URL[]{getClass().getResource( "/package.jdo" )}, new URL[]{}, null, false,
+                                       null );
     }
 
     protected File getDefaultRepositoryLocation()
-        throws Exception
     {
         File repositoryLocation = getTestFile( TEST_DEFAULT_REPO_DIR );
 
@@ -191,7 +202,7 @@
 
         if ( !releasesDirectory.exists() )
         {
-            releasesDirectory.mkdir();
+            releasesDirectory.mkdirs();
         }
 
         return releasesDirectory;
@@ -203,7 +214,7 @@
 
         if ( !buildOutputDir.exists() )
         {
-            buildOutputDir.mkdir();
+            buildOutputDir.mkdirs();
         }
 
         return buildOutputDir;
diff --git a/continuum-purge/src/test/java/org/apache/continuum/purge/DefaultPurgeConfigurationServiceTest.java b/continuum-purge/src/test/java/org/apache/continuum/purge/DefaultPurgeConfigurationServiceTest.java
index 1d8fa28..92ea166 100644
--- a/continuum-purge/src/test/java/org/apache/continuum/purge/DefaultPurgeConfigurationServiceTest.java
+++ b/continuum-purge/src/test/java/org/apache/continuum/purge/DefaultPurgeConfigurationServiceTest.java
@@ -20,6 +20,7 @@
  */
 
 import org.apache.continuum.model.repository.DirectoryPurgeConfiguration;
+import org.apache.continuum.model.repository.DistributedDirectoryPurgeConfiguration;
 import org.apache.continuum.model.repository.RepositoryPurgeConfiguration;
 import org.apache.continuum.purge.repository.content.ManagedDefaultRepositoryContent;
 import org.apache.continuum.purge.repository.content.RepositoryManagedContent;
@@ -55,8 +56,8 @@
 
         assertNotNull( repoConfig );
 
-        RepositoryPurgeConfiguration retrieved =
-            repositoryPurgeConfigurationDao.getRepositoryPurgeConfiguration( repoConfig.getId() );
+        RepositoryPurgeConfiguration retrieved = repositoryPurgeConfigurationDao.getRepositoryPurgeConfiguration(
+            repoConfig.getId() );
         assertEquals( repoConfig, retrieved );
 
         purgeConfigurationService.removeRepositoryPurgeConfiguration( repoConfig );
@@ -65,8 +66,8 @@
             purgeConfigurationService.getAllRepositoryPurgeConfigurations();
 
         assertFalse( "check if repo purge configuration was removed", repoConfigs.contains( repoConfig ) );
-        assertNotNull( "check if repository still exists",
-                       localRepositoryDao.getLocalRepository( defaultRepository.getId() ) );
+        assertNotNull( "check if repository still exists", localRepositoryDao.getLocalRepository(
+            defaultRepository.getId() ) );
     }
 
     public void testDirectoryPurgeConfiguration()
@@ -83,8 +84,8 @@
 
         assertNotNull( dirConfig );
 
-        DirectoryPurgeConfiguration retrieved =
-            directoryPurgeConfigurationDao.getDirectoryPurgeConfiguration( dirConfig.getId() );
+        DirectoryPurgeConfiguration retrieved = directoryPurgeConfigurationDao.getDirectoryPurgeConfiguration(
+            dirConfig.getId() );
         assertEquals( dirConfig, retrieved );
 
         dirConfig.setDirectoryType( TEST_BUILDOUTPUT_DIRECTORY_TYPE );
@@ -98,11 +99,42 @@
         assertFalse( "check if dir purge configuration was removed", dirConfigs.contains( dirConfig ) );
     }
 
+    public void testDistributedDirectoryPurgeConfiguration()
+        throws Exception
+    {
+        DistributedDirectoryPurgeConfiguration dirConfig = new DistributedDirectoryPurgeConfiguration();
+
+        dirConfig.setBuildAgentUrl( TEST_BUILD_AGENT_URL );
+        dirConfig.setDirectoryType( TEST_RELEASES_DIRECTORY_TYPE );
+        dirConfig.setDaysOlder( TEST_DAYS_OLDER );
+        dirConfig.setRetentionCount( TEST_RETENTION_COUNT );
+
+        dirConfig = purgeConfigurationService.addDistributedDirectoryPurgeConfiguration( dirConfig );
+
+        assertNotNull( dirConfig );
+
+        DistributedDirectoryPurgeConfiguration retrieved =
+            distributedDirectoryPurgeConfigurationDao.getDistributedDirectoryPurgeConfiguration( dirConfig.getId() );
+        assertEquals( dirConfig, retrieved );
+
+        dirConfig.setDirectoryType( TEST_WORKING_DIRECTORY_TYPE );
+        purgeConfigurationService.updateDistributedDirectoryPurgeConfiguration( dirConfig );
+        retrieved = distributedDirectoryPurgeConfigurationDao.getDistributedDirectoryPurgeConfiguration(
+            dirConfig.getId() );
+        assertEquals( dirConfig, retrieved );
+
+        purgeConfigurationService.removeDistributedDirectoryPurgeConfiguration( dirConfig );
+
+        List<DistributedDirectoryPurgeConfiguration> dirConfigs =
+            purgeConfigurationService.getAllDistributedDirectoryPurgeConfigurations();
+        assertFalse( "check if dir purge configuration was removed", dirConfigs.contains( dirConfig ) );
+    }
+
     public void testRepositoryManagedContent()
         throws Exception
     {
-        RepositoryManagedContent repo =
-            purgeConfigurationService.getManagedRepositoryContent( defaultRepository.getId() );
+        RepositoryManagedContent repo = purgeConfigurationService.getManagedRepositoryContent(
+            defaultRepository.getId() );
 
         assertTrue( "check repository managed content", ( repo instanceof ManagedDefaultRepositoryContent ) );
         assertEquals( "check repository of the managed content", defaultRepository, repo.getRepository() );
diff --git a/continuum-purge/src/test/java/org/apache/continuum/purge/executor/AbstractPurgeExecutorTest.java b/continuum-purge/src/test/java/org/apache/continuum/purge/executor/AbstractPurgeExecutorTest.java
index c1de534..344a8e0 100644
--- a/continuum-purge/src/test/java/org/apache/continuum/purge/executor/AbstractPurgeExecutorTest.java
+++ b/continuum-purge/src/test/java/org/apache/continuum/purge/executor/AbstractPurgeExecutorTest.java
@@ -42,7 +42,7 @@
 
     private static final String[] metadata_extensions = new String[]{".xml", ".xml.sha1", ".xml.md5"};
 
-    public static final String TEST_MAVEN_METADATA = "maven-metadata-central";
+    private static final String TEST_MAVEN_METADATA = "maven-metadata-central";
 
     private RepositoryPurgeConfiguration repoConfig;
 
@@ -187,14 +187,13 @@
 
         if ( recurse )
         {
-            File[] contents = dir.listFiles();
-            for ( int i = 0; i < contents.length; i++ )
+            for ( File content : dir.listFiles() )
             {
-                contents[i].setLastModified( lastModified );
+                content.setLastModified( lastModified );
 
-                if ( contents[i].list() != null && contents[i].list().length > 0 )
+                if ( content.list() != null && content.list().length > 0 )
                 {
-                    setLastModified( contents[i].getAbsolutePath(), lastModified, true );
+                    setLastModified( content.getAbsolutePath(), lastModified, true );
                 }
             }
         }
@@ -300,9 +299,9 @@
 
         String[] folders = new String[]{"1", "releases-4234729018", "", "releases-1234567809", "releases-1234567890"};
 
-        for ( int i = 0; i < folders.length; i++ )
+        for ( String folder : folders )
         {
-            File dir = new File( repoPath, folders[i] );
+            File dir = new File( repoPath, folder );
             dir.mkdir();
         }
     }
@@ -350,25 +349,25 @@
             versionDir.mkdirs();
 
             // create maven-metadata* files
-            for ( int i = 0; i < metadata_extensions.length; i++ )
+            for ( String metadata_extension : metadata_extensions )
             {
                 File metadata = new File( versionDir.getParentFile().getAbsolutePath(),
-                                          TEST_MAVEN_METADATA + metadata_extensions[i] );
+                                          TEST_MAVEN_METADATA + metadata_extension );
                 metadata.createNewFile();
             }
         }
 
         for ( String version : versions )
         {
-            for ( int i = 0; i < jar_extensions.length; i++ )
+            for ( String jar_extension : jar_extensions )
             {
-                File file = new File( versionDir.getAbsolutePath(), artifactId + "-" + version + jar_extensions[i] );
+                File file = new File( versionDir.getAbsolutePath(), artifactId + "-" + version + jar_extension );
                 file.createNewFile();
             }
 
-            for ( int i = 0; i < pom_extensions.length; i++ )
+            for ( String pom_extension : pom_extensions )
             {
-                File file = new File( versionDir.getAbsolutePath(), artifactId + "-" + version + pom_extensions[i] );
+                File file = new File( versionDir.getAbsolutePath(), artifactId + "-" + version + pom_extension );
                 file.createNewFile();
             }
         }
diff --git a/continuum-release/pom.xml b/continuum-release/pom.xml
index aa93312..4b4edc0 100644
--- a/continuum-release/pom.xml
+++ b/continuum-release/pom.xml
@@ -1,28 +1,29 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
+  ~ 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.
+  -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
     <artifactId>continuum</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <artifactId>continuum-release</artifactId>
   <name>Continuum :: Release System</name>
@@ -32,12 +33,30 @@
   </description>
   <dependencies>
     <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-simple</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>jcl-over-slf4j</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-model</artifactId>
+    </dependency>
+    <dependency>
       <groupId>org.apache.continuum</groupId>
       <artifactId>continuum-api</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-commons</artifactId>
+      <artifactId>continuum-scm</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.maven</groupId>
@@ -62,20 +81,38 @@
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-artifact</artifactId>
     </dependency>
+    <!-- start - order matters, requires maven 2.0.9+ -->
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-artifact-manager</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-artifact-manager</artifactId>
     </dependency>
+    <!-- end - order matters, requires maven 2.0.9+ -->
     <dependency>
       <groupId>org.apache.maven.release</groupId>
       <artifactId>maven-release-manager</artifactId>
-      <version>1.0-alpha-3</version>
-      <exclusions>
-        <exclusion>
-          <groupId>org.codehaus.plexus</groupId>
-          <artifactId>plexus-container-default</artifactId>
-        </exclusion>
-      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>plexus-spring</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.scm</groupId>
+      <artifactId>maven-scm-provider-gitexe</artifactId>
+      <version>1.4</version>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-component-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-utils</artifactId>
     </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
@@ -87,28 +124,22 @@
     </dependency>
     <dependency>
       <groupId>org.apache.maven.scm</groupId>
-      <artifactId>maven-scm-providers-standard</artifactId>
-      <type>pom</type>
-    </dependency>  
+      <artifactId>maven-scm-manager-plexus</artifactId>
+      <scope>compile</scope>
+    </dependency>
     <dependency>
-      <groupId>org.apache.maven.scm</groupId>
-      <artifactId>maven-scm-provider-cvs-commons</artifactId>
-    </dependency>    
-    <dependency>
-      <groupId>org.apache.maven.scm</groupId>
-      <artifactId>maven-scm-provider-svn-commons</artifactId>
-    </dependency>       
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-util</artifactId>
+      <!-- TODO: change this to jetty.version when we're happy to use Java 6
+           as a minimum -->
+      <version>7.6.9.v20130131</version>
+    </dependency>
     <!-- === Testing Dependencies === -->
     <dependency>
       <groupId>hsqldb</groupId>
       <artifactId>hsqldb</artifactId>
       <scope>test</scope>
     </dependency>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-test</artifactId>
-      <scope>test</scope>
-    </dependency>
   </dependencies>
   <build>
     <testResources>
@@ -120,5 +151,18 @@
         <targetPath>../scm-src</targetPath>
       </testResource>
     </testResources>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.rat</groupId>
+          <artifactId>apache-rat-plugin</artifactId>
+          <configuration>
+            <excludes combine.children="append">
+              <exclude>src/test/scm/**</exclude>
+            </excludes>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
   </build>
 </project>
diff --git a/continuum-release/src/main/java/org/apache/continuum/release/config/ContinuumPropertiesReleaseDescriptorStore.java b/continuum-release/src/main/java/org/apache/continuum/release/config/ContinuumPropertiesReleaseDescriptorStore.java
index 26b3c78..9e905df 100644
--- a/continuum-release/src/main/java/org/apache/continuum/release/config/ContinuumPropertiesReleaseDescriptorStore.java
+++ b/continuum-release/src/main/java/org/apache/continuum/release/config/ContinuumPropertiesReleaseDescriptorStore.java
@@ -19,6 +19,14 @@
  * under the License.
  */
 
+import org.apache.maven.model.Scm;
+import org.apache.maven.shared.release.config.PropertiesReleaseDescriptorStore;
+import org.apache.maven.shared.release.config.ReleaseDescriptor;
+import org.apache.maven.shared.release.config.ReleaseDescriptorStoreException;
+import org.apache.maven.shared.release.config.ReleaseUtils;
+import org.codehaus.plexus.util.IOUtil;
+import org.eclipse.jetty.util.security.Password;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -29,16 +37,9 @@
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Properties;
 import java.util.Set;
-import java.util.Map.Entry;
-
-import org.apache.maven.model.Scm;
-import org.apache.maven.shared.release.config.PropertiesReleaseDescriptorStore;
-import org.apache.maven.shared.release.config.ReleaseDescriptor;
-import org.apache.maven.shared.release.config.ReleaseDescriptorStoreException;
-import org.apache.maven.shared.release.config.ReleaseUtils;
-import org.codehaus.plexus.util.IOUtil;
 
 public class ContinuumPropertiesReleaseDescriptorStore
     extends PropertiesReleaseDescriptorStore
@@ -47,12 +48,12 @@
         throws ReleaseDescriptorStoreException
     {
         Properties properties = new Properties();
-    
+
         InputStream inStream = null;
         try
         {
             inStream = new FileInputStream( file );
-    
+
             properties.load( inStream );
         }
         catch ( FileNotFoundException e )
@@ -68,12 +69,21 @@
         {
             IOUtil.close( inStream );
         }
-    
+
         ContinuumReleaseDescriptor releaseDescriptor = new ContinuumReleaseDescriptor();
         releaseDescriptor.setCompletedPhase( properties.getProperty( "completedPhase" ) );
         releaseDescriptor.setScmSourceUrl( properties.getProperty( "scm.url" ) );
         releaseDescriptor.setScmUsername( properties.getProperty( "scm.username" ) );
-        releaseDescriptor.setScmPassword( properties.getProperty( "scm.password" ) );
+
+        String password = properties.getProperty( "scm.password" );
+        if ( password != null && password.startsWith( "OBF:" ) )
+        {
+            releaseDescriptor.setScmPassword( Password.deobfuscate( password ) );
+        }
+        else
+        {
+            releaseDescriptor.setScmPassword( password );
+        }
         releaseDescriptor.setScmPrivateKey( properties.getProperty( "scm.privateKey" ) );
         releaseDescriptor.setScmPrivateKeyPassPhrase( properties.getProperty( "scm.passphrase" ) );
         releaseDescriptor.setScmTagBase( properties.getProperty( "scm.tagBase" ) );
@@ -82,14 +92,16 @@
         releaseDescriptor.setAdditionalArguments( properties.getProperty( "exec.additionalArguments" ) );
         releaseDescriptor.setPomFileName( properties.getProperty( "exec.pomFileName" ) );
         releaseDescriptor.setPreparationGoals( properties.getProperty( "preparationGoals" ) );
-    
+        releaseDescriptor.setExecutable( properties.getProperty( "build.executable" ) );
+        releaseDescriptor.setReleaseBy( properties.getProperty( "release.by" ) );
+
         loadResolvedDependencies( properties, releaseDescriptor );
-    
+
         // boolean properties are not written to the properties file because the value from the caller is always used
-    
-        for ( Iterator i = properties.keySet().iterator(); i.hasNext(); )
+
+        for ( Object o : properties.keySet() )
         {
-            String property = (String) i.next();
+            String property = (String) o;
             if ( property.startsWith( "project.rel." ) )
             {
                 releaseDescriptor.mapReleaseVersion( property.substring( "project.rel.".length() ),
@@ -106,7 +118,7 @@
                 if ( index > "project.scm.".length() )
                 {
                     String key = property.substring( "project.scm.".length(), index );
-    
+
                     if ( !releaseDescriptor.getOriginalScmInfo().containsKey( key ) )
                     {
                         if ( properties.getProperty( "project.scm." + key + ".empty" ) != null )
@@ -117,11 +129,11 @@
                         {
                             Scm scm = new Scm();
                             scm.setConnection( properties.getProperty( "project.scm." + key + ".connection" ) );
-                            scm.setDeveloperConnection(
-                                properties.getProperty( "project.scm." + key + ".developerConnection" ) );
+                            scm.setDeveloperConnection( properties.getProperty(
+                                "project.scm." + key + ".developerConnection" ) );
                             scm.setUrl( properties.getProperty( "project.scm." + key + ".url" ) );
                             scm.setTag( properties.getProperty( "project.scm." + key + ".tag" ) );
-    
+
                             releaseDescriptor.mapOriginalScmInfo( key, scm );
                         }
                     }
@@ -129,17 +141,17 @@
             }
             else if ( property.startsWith( "build.env." ) )
             {
-                releaseDescriptor.mapEnvironments( property.substring( "build.env.".length() ),
-                                                   properties.getProperty( property ) );
+                releaseDescriptor.mapEnvironments( property.substring( "build.env.".length() ), properties.getProperty(
+                    property ) );
             }
         }
-    
+
         if ( mergeDescriptor != null )
         {
             releaseDescriptor = (ContinuumReleaseDescriptor) ReleaseUtils.merge( releaseDescriptor, mergeDescriptor );
-            releaseDescriptor.setEnvironments( ( (ContinuumReleaseDescriptor)mergeDescriptor ).getEnvironments() );
+            releaseDescriptor.setEnvironments( ( (ContinuumReleaseDescriptor) mergeDescriptor ).getEnvironments() );
         }
-    
+
         return releaseDescriptor;
     }
 
@@ -156,7 +168,8 @@
         }
         if ( config.getScmPassword() != null )
         {
-            properties.setProperty( "scm.password", config.getScmPassword() );
+            // obfuscate password
+            properties.setProperty( "scm.password", Password.obfuscate( config.getScmPassword() ) );
         }
         if ( config.getScmPrivateKey() != null )
         {
@@ -190,24 +203,24 @@
         {
             properties.setProperty( "preparationGoals", config.getPreparationGoals() );
         }
-    
+
         // boolean properties are not written to the properties file because the value from the caller is always used
-    
-        for ( Iterator i = config.getReleaseVersions().entrySet().iterator(); i.hasNext(); )
+
+        for ( Object o : config.getReleaseVersions().entrySet() )
         {
-            Map.Entry entry = (Map.Entry) i.next();
+            Entry entry = (Entry) o;
             properties.setProperty( "project.rel." + entry.getKey(), (String) entry.getValue() );
         }
-    
-        for ( Iterator i = config.getDevelopmentVersions().entrySet().iterator(); i.hasNext(); )
+
+        for ( Object o : config.getDevelopmentVersions().entrySet() )
         {
-            Map.Entry entry = (Map.Entry) i.next();
+            Entry entry = (Entry) o;
             properties.setProperty( "project.dev." + entry.getKey(), (String) entry.getValue() );
         }
-    
-        for ( Iterator i = config.getOriginalScmInfo().entrySet().iterator(); i.hasNext(); )
+
+        for ( Object o : config.getOriginalScmInfo().entrySet() )
         {
-            Map.Entry entry = (Map.Entry) i.next();
+            Entry entry = (Entry) o;
             Scm scm = (Scm) entry.getValue();
             String prefix = "project.scm." + entry.getKey();
             if ( scm != null )
@@ -235,24 +248,36 @@
             }
         }
 
-        for ( Iterator i = config.getEnvironments().entrySet().iterator(); i.hasNext(); )
+        for ( Object o : config.getEnvironments().entrySet() )
         {
-            Map.Entry entry = (Map.Entry) i.next();
+            Entry entry = (Entry) o;
             properties.setProperty( "build.env." + entry.getKey(), (String) entry.getValue() );
         }
-    
+
         if ( ( config.getResolvedSnapshotDependencies() != null ) &&
             ( config.getResolvedSnapshotDependencies().size() > 0 ) )
         {
             processResolvedDependencies( properties, config.getResolvedSnapshotDependencies() );
         }
-    
+
+        // executables
+        if ( config.getExecutable() != null )
+        {
+            properties.setProperty( "build.executable", config.getExecutable() );
+        }
+
+        // release by
+        if ( config.getReleaseBy() != null )
+        {
+            properties.setProperty( "release.by", config.getReleaseBy() );
+        }
+
         OutputStream outStream = null;
         //noinspection OverlyBroadCatchBlock
         try
         {
             outStream = new FileOutputStream( file );
-    
+
             properties.store( outStream, "release configuration" );
         }
         catch ( IOException e )
@@ -264,58 +289,52 @@
         {
             IOUtil.close( outStream );
         }
-    
+
     }
-    
+
     private void processResolvedDependencies( Properties prop, Map resolvedDependencies )
     {
         Set entries = resolvedDependencies.entrySet();
         Iterator iterator = entries.iterator();
         Entry currentEntry;
-    
+
         while ( iterator.hasNext() )
         {
             currentEntry = (Entry) iterator.next();
-    
+
             Map versionMap = (Map) currentEntry.getValue();
-    
-            prop.setProperty( "dependency." + currentEntry.getKey() + ".release",
-                              (String) versionMap.get( ReleaseDescriptor.RELEASE_KEY ) );
-            prop.setProperty( "dependency." + currentEntry.getKey() + ".development",
-                              (String) versionMap.get( ReleaseDescriptor.DEVELOPMENT_KEY ) );
+
+            prop.setProperty( "dependency." + currentEntry.getKey() + ".release", (String) versionMap.get(
+                ReleaseDescriptor.RELEASE_KEY ) );
+            prop.setProperty( "dependency." + currentEntry.getKey() + ".development", (String) versionMap.get(
+                ReleaseDescriptor.DEVELOPMENT_KEY ) );
         }
     }
-    
-    private static File getDefaultReleasePropertiesFile( ReleaseDescriptor mergeDescriptor )
-    {
-        return new File( mergeDescriptor.getWorkingDirectory(), "release.properties" );
-    }
-    
+
     private void loadResolvedDependencies( Properties prop, ReleaseDescriptor descriptor )
     {
-        Map resolvedDependencies = new HashMap();
-    
+        Map<String, Map<String, Object>> resolvedDependencies = new HashMap<String, Map<String, Object>>();
+
         Set entries = prop.entrySet();
         Iterator iterator = entries.iterator();
         String propertyName;
         Entry currentEntry;
-    
+
         while ( iterator.hasNext() )
         {
             currentEntry = (Entry) iterator.next();
             propertyName = (String) currentEntry.getKey();
-    
+
             if ( propertyName.startsWith( "dependency." ) )
             {
-                Map versionMap;
+                Map<String, Object> versionMap;
                 String artifactVersionlessKey;
                 int startIndex;
                 int endIndex;
                 String versionType;
-    
-                versionMap = new HashMap();
+
                 startIndex = propertyName.lastIndexOf( "dependency." );
-    
+
                 if ( propertyName.indexOf( ".development" ) != -1 )
                 {
                     endIndex = propertyName.indexOf( ".development" );
@@ -326,23 +345,23 @@
                     endIndex = propertyName.indexOf( ".release" );
                     versionType = ReleaseDescriptor.RELEASE_KEY;
                 }
-    
+
                 artifactVersionlessKey = propertyName.substring( startIndex, endIndex );
-    
+
                 if ( resolvedDependencies.containsKey( artifactVersionlessKey ) )
                 {
-                    versionMap = (Map) resolvedDependencies.get( artifactVersionlessKey );
+                    versionMap = resolvedDependencies.get( artifactVersionlessKey );
                 }
                 else
                 {
-                    versionMap = new HashMap();
+                    versionMap = new HashMap<String, Object>();
                     resolvedDependencies.put( artifactVersionlessKey, versionMap );
                 }
-    
+
                 versionMap.put( versionType, currentEntry.getValue() );
             }
         }
-    
+
         descriptor.setResolvedSnapshotDependencies( resolvedDependencies );
     }
 }
diff --git a/continuum-release/src/main/java/org/apache/continuum/release/config/ContinuumReleaseDescriptor.java b/continuum-release/src/main/java/org/apache/continuum/release/config/ContinuumReleaseDescriptor.java
index 7047229..fab1e3d 100644
--- a/continuum-release/src/main/java/org/apache/continuum/release/config/ContinuumReleaseDescriptor.java
+++ b/continuum-release/src/main/java/org/apache/continuum/release/config/ContinuumReleaseDescriptor.java
@@ -19,11 +19,11 @@
  * under the License.
  */
 
+import org.apache.maven.shared.release.config.ReleaseDescriptor;
+
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.maven.shared.release.config.ReleaseDescriptor;
-
 /**
  * @author <a href="mailto:ctan@apache.org">Maria Catherine Tan</a>
  */
@@ -32,6 +32,10 @@
 {
     private Map<String, String> environments;
 
+    private String executable;
+
+    private String releaseBy;
+
     public void addEnvironment( String name, String value )
     {
         getEnvironments().put( name, value );
@@ -47,7 +51,7 @@
         return environments;
     }
 
-    public void mapEnvironments( String name, String value)
+    public void mapEnvironments( String name, String value )
     {
         if ( environments == null )
         {
@@ -65,4 +69,24 @@
     {
         this.environments = environments;
     }
+
+    public String getExecutable()
+    {
+        return executable;
+    }
+
+    public void setExecutable( String executable )
+    {
+        this.executable = executable;
+    }
+
+    public String getReleaseBy()
+    {
+        return releaseBy;
+    }
+
+    public void setReleaseBy( String releaseBy )
+    {
+        this.releaseBy = releaseBy;
+    }
 }
diff --git a/continuum-release/src/main/java/org/apache/continuum/release/phase/AbstractContinuumRunGoalsPhase.java b/continuum-release/src/main/java/org/apache/continuum/release/phase/AbstractContinuumRunGoalsPhase.java
index c3f980d..90918a7 100644
--- a/continuum-release/src/main/java/org/apache/continuum/release/phase/AbstractContinuumRunGoalsPhase.java
+++ b/continuum-release/src/main/java/org/apache/continuum/release/phase/AbstractContinuumRunGoalsPhase.java
@@ -19,17 +19,21 @@
  * under the License.
  */
 
-import java.io.File;
-import java.util.Map;
-
 import org.apache.continuum.release.config.ContinuumReleaseDescriptor;
 import org.apache.continuum.utils.shell.ShellCommandHelper;
+import org.apache.maven.continuum.installation.InstallationService;
 import org.apache.maven.shared.release.ReleaseExecutionException;
+import org.apache.maven.shared.release.ReleaseFailureException;
 import org.apache.maven.shared.release.ReleaseResult;
 import org.apache.maven.shared.release.config.ReleaseDescriptor;
+import org.apache.maven.shared.release.env.ReleaseEnvironment;
 import org.apache.maven.shared.release.phase.AbstractRunGoalsPhase;
 import org.codehaus.plexus.util.StringUtils;
 
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+
 /**
  * @author <a href="mailto:ctan@apache.org">Maria Catherine Tan</a>
  */
@@ -41,37 +45,72 @@
      */
     private ShellCommandHelper shellCommandHelper;
 
+    /**
+     * @plexus.requirement
+     */
+    private InstallationService installationService;
+
+    /**
+     * TODO olamy use maven-invoker with an installation (jdk, mvn path, env var)
+     */
     public ReleaseResult execute( ReleaseDescriptor releaseDescriptor, File workingDirectory,
                                   String additionalArguments )
         throws ReleaseExecutionException
     {
         ReleaseResult result = new ReleaseResult();
-        
+
         try
         {
             String goals = getGoals( releaseDescriptor );
             if ( !StringUtils.isEmpty( goals ) )
             {
                 Map<String, String> environments = null;
-                
+
+                String executable = null;
+
                 if ( releaseDescriptor instanceof ContinuumReleaseDescriptor )
                 {
                     environments = ( (ContinuumReleaseDescriptor) releaseDescriptor ).getEnvironments();
+
+                    executable = ( (ContinuumReleaseDescriptor) releaseDescriptor ).getExecutable();
                 }
-                
                 shellCommandHelper.executeGoals( determineWorkingDirectory( workingDirectory,
                                                                             releaseDescriptor.getScmRelativePathProjectDirectory() ),
-                                                 goals, releaseDescriptor.isInteractive(), additionalArguments, result, 
-                                                 environments );
+                                                 executable, goals, releaseDescriptor.isInteractive(),
+                                                 additionalArguments, result, environments );
             }
         }
         catch ( Exception e )
         {
-            throw new ReleaseExecutionException( e.getMessage(), e );
+            throw new ReleaseExecutionException( result.getOutput(), e );
         }
 
         result.setResultCode( ReleaseResult.SUCCESS );
 
         return result;
     }
+
+    @Override
+    public ReleaseResult execute( ReleaseDescriptor arg0, ReleaseEnvironment arg1, File arg2, String arg3 )
+        throws ReleaseExecutionException
+    {
+        return super.execute( arg0, arg1, arg2, arg3 );
+    }
+
+    public ReleaseResult execute( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
+                                  List reactorProjects )
+        throws ReleaseExecutionException, ReleaseFailureException
+    {
+
+        return execute( releaseDescriptor, new File( releaseDescriptor.getWorkingDirectory() ),
+                        releaseDescriptor.getAdditionalArguments() );
+    }
+
+    public ReleaseResult simulate( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
+                                   List reactorProjects )
+        throws ReleaseExecutionException, ReleaseFailureException
+    {
+        return execute( releaseDescriptor, new File( releaseDescriptor.getWorkingDirectory() ),
+                        releaseDescriptor.getAdditionalArguments() );
+    }
 }
diff --git a/continuum-release/src/main/java/org/apache/continuum/release/phase/RunPerformGoalsPhase.java b/continuum-release/src/main/java/org/apache/continuum/release/phase/RunPerformGoalsPhase.java
index f1c9dd3..66bba11 100644
--- a/continuum-release/src/main/java/org/apache/continuum/release/phase/RunPerformGoalsPhase.java
+++ b/continuum-release/src/main/java/org/apache/continuum/release/phase/RunPerformGoalsPhase.java
@@ -19,18 +19,20 @@
  * under the License.
  */
 
-import java.io.File;
-import java.util.List;
-
 import org.apache.maven.settings.Settings;
 import org.apache.maven.shared.release.ReleaseExecutionException;
 import org.apache.maven.shared.release.ReleaseFailureException;
 import org.apache.maven.shared.release.ReleaseResult;
 import org.apache.maven.shared.release.config.ReleaseDescriptor;
+import org.apache.maven.shared.release.env.ReleaseEnvironment;
 import org.codehaus.plexus.util.StringUtils;
 
+import java.io.File;
+import java.util.List;
+
 /**
  * Run Release Perform Goals
+ *
  * @plexus.component role="org.apache.maven.shared.release.phase.ReleasePhase" role-hint="run-release-perform-goals"
  */
 public class RunPerformGoalsPhase
@@ -42,9 +44,11 @@
         return releaseDescriptor.getPerformGoals();
     }
 
-    public ReleaseResult execute( ReleaseDescriptor releaseDescriptor, Settings settings, List reactorProjects )
+    public ReleaseResult execute( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
+                                  List reactorProjects )
         throws ReleaseExecutionException, ReleaseFailureException
     {
+
         String additionalArguments = releaseDescriptor.getAdditionalArguments();
 
         if ( releaseDescriptor.isUseReleaseProfile() )
diff --git a/continuum-release/src/main/java/org/apache/continuum/release/phase/RunPrepareGoalsPhase.java b/continuum-release/src/main/java/org/apache/continuum/release/phase/RunPrepareGoalsPhase.java
index 9f00bcc..59139b6 100644
--- a/continuum-release/src/main/java/org/apache/continuum/release/phase/RunPrepareGoalsPhase.java
+++ b/continuum-release/src/main/java/org/apache/continuum/release/phase/RunPrepareGoalsPhase.java
@@ -19,17 +19,18 @@
  * under the License.
  */
 
-import java.io.File;
-import java.util.List;
-
-import org.apache.maven.settings.Settings;
 import org.apache.maven.shared.release.ReleaseExecutionException;
 import org.apache.maven.shared.release.ReleaseFailureException;
 import org.apache.maven.shared.release.ReleaseResult;
 import org.apache.maven.shared.release.config.ReleaseDescriptor;
+import org.apache.maven.shared.release.env.ReleaseEnvironment;
+
+import java.io.File;
+import java.util.List;
 
 /**
  * Run Release Preparation Goals
+ *
  * @plexus.component role="org.apache.maven.shared.release.phase.ReleasePhase" role-hint="run-release-prepare-goals"
  */
 public class RunPrepareGoalsPhase
@@ -41,14 +42,17 @@
         return releaseDescriptor.getPreparationGoals();
     }
 
-    public ReleaseResult execute( ReleaseDescriptor releaseDescriptor, Settings settings, List reactorProjects )
+    public ReleaseResult execute( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
+                                  List reactorProjects )
         throws ReleaseExecutionException, ReleaseFailureException
     {
-        return execute( releaseDescriptor, new File( releaseDescriptor.getWorkingDirectory() ), 
+
+        return execute( releaseDescriptor, new File( releaseDescriptor.getWorkingDirectory() ),
                         releaseDescriptor.getAdditionalArguments() );
     }
 
-    public ReleaseResult simulate( ReleaseDescriptor releaseDescriptor, Settings settings, List reactorProjects )
+    public ReleaseResult simulate( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
+                                   List reactorProjects )
         throws ReleaseExecutionException, ReleaseFailureException
     {
         ReleaseResult result = new ReleaseResult();
@@ -56,7 +60,7 @@
         logInfo( result, "Executing preparation goals - since this is simulation mode it is running against the " +
             "original project, not the rewritten ones" );
 
-        execute( releaseDescriptor, settings, reactorProjects );
+        execute( releaseDescriptor, releaseEnvironment, reactorProjects );
 
         return result;
     }
diff --git a/continuum-release/src/main/java/org/apache/maven/continuum/release/DefaultContinuumReleaseManager.java b/continuum-release/src/main/java/org/apache/maven/continuum/release/DefaultContinuumReleaseManager.java
index b361979..12052f6 100644
--- a/continuum-release/src/main/java/org/apache/maven/continuum/release/DefaultContinuumReleaseManager.java
+++ b/continuum-release/src/main/java/org/apache/maven/continuum/release/DefaultContinuumReleaseManager.java
@@ -20,30 +20,38 @@
  */
 
 import org.apache.commons.lang.BooleanUtils;
+import org.apache.continuum.model.release.ReleaseListenerSummary;
 import org.apache.continuum.model.repository.LocalRepository;
 import org.apache.continuum.release.config.ContinuumReleaseDescriptor;
-import org.apache.maven.continuum.installation.InstallationService;
+import org.apache.continuum.taskqueue.manager.TaskQueueManagerException;
+import org.apache.maven.artifact.ArtifactUtils;
 import org.apache.maven.continuum.model.project.Project;
-import org.apache.maven.continuum.model.system.Installation;
-import org.apache.maven.continuum.model.system.Profile;
 import org.apache.maven.continuum.release.tasks.PerformReleaseProjectTask;
 import org.apache.maven.continuum.release.tasks.PrepareReleaseProjectTask;
 import org.apache.maven.continuum.release.tasks.RollbackReleaseProjectTask;
-import org.apache.maven.continuum.utils.WorkingDirectoryService;
+import org.apache.maven.scm.manager.ScmManager;
+import org.apache.maven.scm.provider.ScmProvider;
+import org.apache.maven.scm.repository.ScmRepository;
 import org.apache.maven.shared.release.ReleaseManagerListener;
 import org.apache.maven.shared.release.config.ReleaseDescriptor;
 import org.apache.maven.shared.release.config.ReleaseDescriptorStore;
 import org.apache.maven.shared.release.config.ReleaseDescriptorStoreException;
+import org.codehaus.plexus.PlexusConstants;
+import org.codehaus.plexus.PlexusContainer;
+import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+import org.codehaus.plexus.context.Context;
+import org.codehaus.plexus.context.ContextException;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
 import org.codehaus.plexus.taskqueue.Task;
 import org.codehaus.plexus.taskqueue.TaskQueue;
 import org.codehaus.plexus.taskqueue.TaskQueueException;
+import org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor;
 import org.codehaus.plexus.util.StringUtils;
 
 import java.io.File;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.Hashtable;
-import java.util.List;
+import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Properties;
 
@@ -53,8 +61,15 @@
  * @version $Id$
  */
 public class DefaultContinuumReleaseManager
-    implements ContinuumReleaseManager
+    implements ContinuumReleaseManager, Contextualizable
 {
+
+    private static final String PLEXUS_KEY_PERFORM_RELEASE_TASKQUEUE_EXECUTOR = "perform-release";
+
+    private static final String PLEXUS_KEY_PREPARE_RELEASE_TASKQUEUE_EXECUTOR = "prepare-release";
+
+    private static final String PLEXUS_KEY_ROLLBACK_RELEASE_TASKQUEUE_EXECUTOR = "rollback-release";
+
     /**
      * @plexus.requirement
      */
@@ -78,21 +93,18 @@
     /**
      * @plexus.requirement
      */
-    private WorkingDirectoryService workingDirectoryService;
+    private ScmManager scmManager;
 
-    /**
-     * @plexus.requirement
-     */
-    private InstallationService installationService;
-    
-    private Map listeners;
+    private PlexusContainer container;
+
+    private Map<String, ContinuumReleaseManagerListener> listeners;
 
     /**
      * contains previous release:prepare descriptors; one per project
      *
      * @todo remove static when singleton strategy is working
      */
-    private static Map preparedReleases;
+    private static Map<String, ReleaseDescriptor> preparedReleases;
 
     /**
      * contains results
@@ -101,28 +113,42 @@
      */
     private static Map releaseResults;
 
-    public String prepare( Project project, Properties releaseProperties, Map relVersions, Map devVersions,
-                           ContinuumReleaseManagerListener listener )
+    public String prepare( Project project, Properties releaseProperties, Map<String, String> relVersions,
+                           Map<String, String> devVersions, ContinuumReleaseManagerListener listener,
+                           String workingDirectory )
         throws ContinuumReleaseException
     {
-        return prepare( project, releaseProperties, relVersions, devVersions, listener, null );
+        return prepare( project, releaseProperties, relVersions, devVersions, listener, workingDirectory, null, null );
     }
 
-    public String prepare( Project project, Properties releaseProperties, Map relVersions, Map devVersions,
-                           ContinuumReleaseManagerListener listener, Profile profile )
+    public String prepare( Project project, Properties releaseProperties, Map<String, String> relVersions,
+                           Map<String, String> devVersions, ContinuumReleaseManagerListener listener,
+                           String workingDirectory, Map<String, String> environments, String executable )
         throws ContinuumReleaseException
     {
         String releaseId = project.getGroupId() + ":" + project.getArtifactId();
 
-        ReleaseDescriptor descriptor = getReleaseDescriptor( project, releaseProperties, relVersions, devVersions, profile );
+        ReleaseDescriptor descriptor = getReleaseDescriptor( project, releaseProperties, relVersions, devVersions,
+                                                             environments, workingDirectory, executable );
+
+        if ( listener == null )
+        {
+            listener = new DefaultReleaseManagerListener();
+            listener.setUsername( releaseProperties.getProperty( "release-by" ) );
+        }
+
+        // check if releaseId exists
+        while ( getPreparedReleases().get( releaseId ) != null )
+        {
+            releaseId = releaseId + ":" + String.valueOf( System.currentTimeMillis() );
+        }
 
         getListeners().put( releaseId, listener );
 
         try
         {
-            prepareReleaseQueue.put(
-                new PrepareReleaseProjectTask( releaseId, descriptor, (ReleaseManagerListener) listener, profile ) );
-
+            prepareReleaseQueue.put( new PrepareReleaseProjectTask( releaseId, descriptor,
+                                                                    (ReleaseManagerListener) listener ) );
         }
         catch ( TaskQueueException e )
         {
@@ -132,45 +158,59 @@
         return releaseId;
     }
 
-    public void perform( String releaseId, File buildDirectory, String goals, boolean useReleaseProfile,
-                         ContinuumReleaseManagerListener listener )
+    public void perform( String releaseId, File buildDirectory, String goals, String arguments,
+                         boolean useReleaseProfile, ContinuumReleaseManagerListener listener )
         throws ContinuumReleaseException
     {
-        perform( releaseId, buildDirectory, goals, useReleaseProfile, listener, null );
+        perform( releaseId, buildDirectory, goals, arguments, useReleaseProfile, listener, null );
     }
-    
-    public void perform( String releaseId, File buildDirectory, String goals, boolean useReleaseProfile,
-                         ContinuumReleaseManagerListener listener, LocalRepository repository )
+
+    public void perform( String releaseId, File buildDirectory, String goals, String arguments,
+                         boolean useReleaseProfile, ContinuumReleaseManagerListener listener,
+                         LocalRepository repository )
         throws ContinuumReleaseException
     {
-        ReleaseDescriptor descriptor = (ReleaseDescriptor) getPreparedReleases().get( releaseId );
+        ReleaseDescriptor descriptor = getPreparedReleases().get( releaseId );
         if ( descriptor != null )
         {
-            perform( releaseId, descriptor, buildDirectory, goals, useReleaseProfile, listener, repository );
+            perform( releaseId, descriptor, buildDirectory, goals, arguments, useReleaseProfile, listener, repository );
         }
     }
 
-    public void perform( String releaseId, String workingDirectory, File buildDirectory, String goals,
+    public void perform( String releaseId, String workingDirectory, File buildDirectory, String goals, String arguments,
                          boolean useReleaseProfile, ContinuumReleaseManagerListener listener )
         throws ContinuumReleaseException
     {
         ReleaseDescriptor descriptor = readReleaseDescriptor( workingDirectory );
-
-        perform( releaseId, descriptor, buildDirectory, goals, useReleaseProfile, listener, null );
+        perform( releaseId, descriptor, buildDirectory, goals, arguments, useReleaseProfile, listener, null );
     }
 
     private void perform( String releaseId, ReleaseDescriptor descriptor, File buildDirectory, String goals,
-                          boolean useReleaseProfile, ContinuumReleaseManagerListener listener, LocalRepository repository )
+                          String arguments, boolean useReleaseProfile, ContinuumReleaseManagerListener listener,
+                          LocalRepository repository )
         throws ContinuumReleaseException
     {
+        if ( descriptor != null )
+        {
+            descriptor.setAdditionalArguments( arguments );
+        }
+
+        if ( listener == null )
+        {
+            listener = new DefaultReleaseManagerListener();
+            if ( descriptor instanceof ContinuumReleaseDescriptor )
+            {
+                listener.setUsername( ( (ContinuumReleaseDescriptor) descriptor ).getReleaseBy() );
+            }
+        }
+
         try
         {
             getListeners().put( releaseId, listener );
 
             performReleaseQueue.put( new PerformReleaseProjectTask( releaseId, descriptor, buildDirectory, goals,
                                                                     useReleaseProfile,
-                                                                    (ReleaseManagerListener) listener,
-                                                                    repository ) );
+                                                                    (ReleaseManagerListener) listener, repository ) );
         }
         catch ( TaskQueueException e )
         {
@@ -183,6 +223,15 @@
     {
         ReleaseDescriptor descriptor = readReleaseDescriptor( workingDirectory );
 
+        if ( listener == null )
+        {
+            listener = new DefaultReleaseManagerListener();
+            if ( descriptor instanceof ContinuumReleaseDescriptor )
+            {
+                listener.setUsername( ( (ContinuumReleaseDescriptor) descriptor ).getReleaseBy() );
+            }
+        }
+
         rollback( releaseId, descriptor, listener );
     }
 
@@ -201,16 +250,36 @@
         }
     }
 
-    public Map getPreparedReleases()
+    public Map<String, ReleaseDescriptor> getPreparedReleases()
     {
         if ( preparedReleases == null )
         {
-            preparedReleases = new Hashtable();
+            preparedReleases = Collections.synchronizedMap( new LinkedHashMap<String, ReleaseDescriptor>() );
         }
 
         return preparedReleases;
     }
 
+    public Map<String, String> getPreparedReleasesForProject( String groupId, String artifactId )
+    {
+        String key = ArtifactUtils.versionlessKey( groupId, artifactId );
+
+        Map<String, String> projectPreparedReleases = new LinkedHashMap<String, String>();
+        Map<String, ReleaseDescriptor> preparedReleases = getPreparedReleases();
+        for ( String releaseId : preparedReleases.keySet() )
+        {
+            // get exact match, or one with a timestamp appended
+            if ( releaseId.equals( key ) || releaseId.startsWith( key + ":" ) )
+            {
+                ReleaseDescriptor descriptor = preparedReleases.get( releaseId );
+
+                // use key to lookup, not release ID - versions don't get any timestamp appended
+                projectPreparedReleases.put( releaseId, descriptor.getReleaseVersions().get( key ).toString() );
+            }
+        }
+        return projectPreparedReleases;
+    }
+
     public Map getReleaseResults()
     {
         if ( releaseResults == null )
@@ -221,85 +290,80 @@
         return releaseResults;
     }
 
-    public Map<String, String> getEnvironments( Profile profile )
-    {
-        if ( profile == null )
-        {
-            return Collections.EMPTY_MAP;
-        }
-
-        Map<String, String> envVars = new HashMap<String, String>();
-        if ( profile == null )
-        {
-            return envVars;
-        }
-
-        String javaHome = getJavaHomeValue( profile );
-        if ( !StringUtils.isEmpty( javaHome ) )
-        {
-            envVars.put( installationService.getEnvVar( InstallationService.JDK_TYPE ), javaHome );
-        }
-
-        Installation builder = profile.getBuilder();
-        if ( builder != null )
-        {
-            envVars.put( installationService.getEnvVar( InstallationService.MAVEN2_TYPE ), builder.getVarValue() );
-        }
-
-        List<Installation> installations = profile.getEnvironmentVariables();
-        for ( Installation installation : installations )
-        {
-            envVars.put( installation.getVarName(), installation.getVarValue() );
-        }
-        return envVars;
-    }
-
-    private ReleaseDescriptor getReleaseDescriptor( Project project, Properties releaseProperties, Map relVersions,
-                                                    Map devVersions, Profile profile )
+    private ReleaseDescriptor getReleaseDescriptor( Project project, Properties releaseProperties,
+                                                    Map<String, String> relVersions, Map<String, String> devVersions,
+                                                    Map<String, String> environments, String workingDirectory,
+                                                    String executable )
     {
         ContinuumReleaseDescriptor descriptor = new ContinuumReleaseDescriptor();
-        String workingDirectory = workingDirectoryService.getWorkingDirectory( project ).getPath(); 
 
         //release properties from the project
         descriptor.setWorkingDirectory( workingDirectory );
         descriptor.setScmSourceUrl( project.getScmUrl() );
 
         //required properties
-        descriptor.setScmReleaseLabel( releaseProperties.getProperty( "tag" ) );
-        descriptor.setScmTagBase( releaseProperties.getProperty( "tagBase" ) );
+        descriptor.setScmReleaseLabel( releaseProperties.getProperty( "scm-tag" ) );
+        descriptor.setScmTagBase( releaseProperties.getProperty( "scm-tagbase" ) );
         descriptor.setReleaseVersions( relVersions );
         descriptor.setDevelopmentVersions( devVersions );
-        descriptor.setPreparationGoals( releaseProperties.getProperty( "prepareGoals" ) );
-        
-        String useEditMode = releaseProperties.getProperty( "useEditMode" );
+        descriptor.setPreparationGoals( releaseProperties.getProperty( "preparation-goals" ) );
+        descriptor.setAdditionalArguments( releaseProperties.getProperty( "arguments" ) );
+        descriptor.setAddSchema( Boolean.valueOf( releaseProperties.getProperty( "add-schema" ) ) );
+        descriptor.setAutoVersionSubmodules( Boolean.valueOf( releaseProperties.getProperty(
+            "auto-version-submodules" ) ) );
+
+        String useEditMode = releaseProperties.getProperty( "use-edit-mode" );
         if ( BooleanUtils.toBoolean( useEditMode ) )
         {
             descriptor.setScmUseEditMode( Boolean.valueOf( useEditMode ) );
-        } 
-        
+        }
+
         LocalRepository repository = project.getProjectGroup().getLocalRepository();
-        
+
         if ( repository != null )
         {
-            descriptor.setAdditionalArguments( "\"-Dmaven.repo.local=" + repository.getLocation() + "\"" );
+            String args = descriptor.getAdditionalArguments();
+
+            if ( StringUtils.isNotEmpty( args ) )
+            {
+                descriptor.setAdditionalArguments( args +
+                                                       " \"-Dmaven.repo.local=" + repository.getLocation() + "\"" );
+            }
+            else
+            {
+                descriptor.setAdditionalArguments( "\"-Dmaven.repo.local=" + repository.getLocation() + "\"" );
+            }
         }
-        
+
         //other properties
-        if ( releaseProperties.containsKey( "username" ) )
+        if ( releaseProperties.containsKey( "scm-username" ) )
         {
-            descriptor.setScmUsername( releaseProperties.getProperty( "username" ) );
+            descriptor.setScmUsername( releaseProperties.getProperty( "scm-username" ) );
         }
-        if ( releaseProperties.containsKey( "password" ) )
+        if ( releaseProperties.containsKey( "scm-password" ) )
         {
-            descriptor.setScmPassword( releaseProperties.getProperty( "password" ) );
+            descriptor.setScmPassword( releaseProperties.getProperty( "scm-password" ) );
+        }
+        if ( releaseProperties.containsKey( "scm-comment-prefix" ) )
+        {
+            descriptor.setScmCommentPrefix( releaseProperties.getProperty( "scm-comment-prefix" ) );
+        }
+        if ( releaseProperties.containsKey( "use-release-profile" ) )
+        {
+            descriptor.setUseReleaseProfile( Boolean.valueOf( releaseProperties.getProperty(
+                "use-release-profile" ) ) );
         }
 
         //forced properties
         descriptor.setInteractive( false );
-        
+
         //set environments
-        descriptor.setEnvironments( getEnvironments( profile ) );
-        
+        descriptor.setEnvironments( environments );
+        descriptor.setExecutable( executable );
+
+        //release by
+        descriptor.setReleaseBy( releaseProperties.getProperty( "release-by" ) );
+
         return descriptor;
     }
 
@@ -321,23 +385,102 @@
         return descriptor;
     }
 
-    public Map getListeners()
+    public Map<String, ContinuumReleaseManagerListener> getListeners()
     {
         if ( listeners == null )
         {
-            listeners = new Hashtable();
+            listeners = new Hashtable<String, ContinuumReleaseManagerListener>();
         }
 
         return listeners;
     }
 
-    private String getJavaHomeValue( Profile profile )
+    public String sanitizeTagName( String scmUrl, String tagName )
+        throws Exception
     {
-        Installation jdk = profile.getJdk();
-        if ( jdk == null )
+        ScmRepository scmRepo = scmManager.makeScmRepository( scmUrl );
+        ScmProvider scmProvider = scmManager.getProviderByRepository( scmRepo );
+        return scmProvider.sanitizeTagName( tagName );
+    }
+
+    public ReleaseListenerSummary getListener( String releaseId )
+    {
+        ContinuumReleaseManagerListener listener = (ContinuumReleaseManagerListener) getListeners().get( releaseId );
+
+        if ( listener != null )
         {
-            return null;
+            ReleaseListenerSummary listenerSummary = new ReleaseListenerSummary();
+            listenerSummary.setGoalName( listener.getGoalName() );
+            listenerSummary.setError( listener.getError() );
+            listenerSummary.setInProgress( listener.getInProgress() );
+            listenerSummary.setState( listener.getState() );
+            listenerSummary.setPhases( listener.getPhases() );
+            listenerSummary.setCompletedPhases( listener.getCompletedPhases() );
+            listenerSummary.setUsername( listener.getUsername() );
+
+            return listenerSummary;
         }
-        return jdk.getVarValue();
+
+        return null;
+    }
+
+    public boolean isExecutingRelease()
+        throws Exception
+    {
+        return prepareReleaseQueue.getQueueSnapshot().size() > 0 ||
+            performReleaseQueue.getQueueSnapshot().size() > 0 ||
+            rollbackReleaseQueue.getQueueSnapshot().size() > 0 ||
+            getPerformReleaseTaskQueueExecutor().getCurrentTask() != null ||
+            getPrepareReleaseTaskQueueExecutor().getCurrentTask() != null ||
+            getRollbackReleaseTaskQueueExecutor().getCurrentTask() != null;
+    }
+
+
+    public TaskQueueExecutor getPerformReleaseTaskQueueExecutor()
+        throws TaskQueueManagerException
+    {
+        try
+        {
+            return (TaskQueueExecutor) container.lookup( TaskQueueExecutor.class,
+                                                         PLEXUS_KEY_PERFORM_RELEASE_TASKQUEUE_EXECUTOR );
+        }
+        catch ( ComponentLookupException e )
+        {
+            throw new TaskQueueManagerException( e.getMessage(), e );
+        }
+    }
+
+    public TaskQueueExecutor getPrepareReleaseTaskQueueExecutor()
+        throws TaskQueueManagerException
+    {
+        try
+        {
+            return (TaskQueueExecutor) container.lookup( TaskQueueExecutor.class,
+                                                         PLEXUS_KEY_PREPARE_RELEASE_TASKQUEUE_EXECUTOR );
+        }
+        catch ( ComponentLookupException e )
+        {
+            throw new TaskQueueManagerException( e.getMessage(), e );
+        }
+    }
+
+    public TaskQueueExecutor getRollbackReleaseTaskQueueExecutor()
+        throws TaskQueueManagerException
+    {
+        try
+        {
+            return (TaskQueueExecutor) container.lookup( TaskQueueExecutor.class,
+                                                         PLEXUS_KEY_ROLLBACK_RELEASE_TASKQUEUE_EXECUTOR );
+        }
+        catch ( ComponentLookupException e )
+        {
+            throw new TaskQueueManagerException( e.getMessage(), e );
+        }
+    }
+
+    public void contextualize( Context context )
+        throws ContextException
+    {
+        container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
     }
 }
diff --git a/continuum-release/src/main/java/org/apache/maven/continuum/release/DefaultReleaseManagerListener.java b/continuum-release/src/main/java/org/apache/maven/continuum/release/DefaultReleaseManagerListener.java
index c0de542..6e25fe5 100644
--- a/continuum-release/src/main/java/org/apache/maven/continuum/release/DefaultReleaseManagerListener.java
+++ b/continuum-release/src/main/java/org/apache/maven/continuum/release/DefaultReleaseManagerListener.java
@@ -34,22 +34,24 @@
 {
     private String goalName;
 
-    private List completedPhases;
+    private List<String> completedPhases;
 
     private String inProgress;
 
-    private List phases;
+    private List<String> phases;
 
     private String error;
 
     private int state;
 
+    private String username;
+
     public void goalStart( String name, List phases )
     {
         state = LISTENING;
         goalName = name;
         this.phases = phases;
-        completedPhases = Collections.synchronizedList( new ArrayList() );
+        completedPhases = Collections.synchronizedList( new ArrayList<String>() );
         inProgress = null;
     }
 
@@ -81,7 +83,7 @@
         goalEnd();
     }
 
-    public List getCompletedPhases()
+    public List<String> getCompletedPhases()
     {
         return completedPhases;
     }
@@ -91,7 +93,7 @@
         return inProgress;
     }
 
-    public List getPhases()
+    public List<String> getPhases()
     {
         return phases;
     }
@@ -110,4 +112,14 @@
     {
         return state;
     }
+
+    public void setUsername( String username )
+    {
+        this.username = username;
+    }
+
+    public String getUsername()
+    {
+        return username;
+    }
 }
diff --git a/continuum-release/src/main/java/org/apache/maven/continuum/release/executors/PerformReleaseTaskExecutor.java b/continuum-release/src/main/java/org/apache/maven/continuum/release/executors/PerformReleaseTaskExecutor.java
index 50cd26a..5cb7024 100644
--- a/continuum-release/src/main/java/org/apache/maven/continuum/release/executors/PerformReleaseTaskExecutor.java
+++ b/continuum-release/src/main/java/org/apache/maven/continuum/release/executors/PerformReleaseTaskExecutor.java
@@ -31,12 +31,14 @@
 import org.apache.maven.project.DuplicateProjectException;
 import org.apache.maven.project.MavenProject;
 import org.apache.maven.project.MavenProjectBuilder;
+import org.apache.maven.project.MissingProjectException;
 import org.apache.maven.project.ProjectBuildingException;
 import org.apache.maven.project.ProjectSorter;
 import org.apache.maven.settings.Settings;
 import org.apache.maven.shared.release.ReleaseManagerListener;
 import org.apache.maven.shared.release.ReleaseResult;
 import org.apache.maven.shared.release.config.ReleaseDescriptor;
+import org.apache.maven.shared.release.env.DefaultReleaseEnvironment;
 import org.codehaus.plexus.PlexusConstants;
 import org.codehaus.plexus.PlexusContainer;
 import org.codehaus.plexus.context.Context;
@@ -48,7 +50,7 @@
 
 import java.io.File;
 import java.util.ArrayList;
-import java.util.Iterator;
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -67,7 +69,7 @@
     private ProfileManager profileManager;
 
     private PlexusContainer container;
-    
+
     private LocalRepository repository;
 
     public void execute( ReleaseProjectTask task )
@@ -81,12 +83,48 @@
         descriptor.setUseReleaseProfile( performTask.isUseReleaseProfile() );
         descriptor.setPerformGoals( performTask.getGoals() );
         descriptor.setCheckoutDirectory( performTask.getBuildDirectory().getAbsolutePath() );
-        
-        repository = performTask.getLocalRepository();
-        
-        List reactorProjects = getReactorProjects( performTask );
 
-        ReleaseResult result = releaseManager.performWithResult( descriptor, settings, reactorProjects, listener );
+        repository = performTask.getLocalRepository();
+
+        List reactorProjects;
+
+        try
+        {
+            if ( !StringUtils.isEmpty( descriptor.getWorkingDirectory() ) )
+            {
+                MavenProject mavenProject = getMavenProject( performTask );
+                reactorProjects = getReactorProjects( descriptor, mavenProject );
+            }
+            else
+            {
+                //Perform with provided release parameters (CONTINUUM-1541)
+                descriptor.setCheckoutDirectory( performTask.getBuildDirectory().getAbsolutePath() );
+
+                // Workaround bugs in maven-release-manager 2.1 that require a project even though it will ultimately
+                // not be used. TODO: check if upgrading will fix, and return to being an empty list
+                // The project is fake and won't exist in this location
+                MavenProject project = new MavenProject();
+                project.setFile( new File( descriptor.getCheckoutDirectory(), "pom.xml" ) );
+                reactorProjects = Collections.singletonList( project );
+//                reactorProjects = Collections.emptyList();
+            }
+        }
+        catch ( ContinuumReleaseException e )
+        {
+            ReleaseResult result = createReleaseResult();
+
+            result.appendError( e );
+
+            continuumReleaseManager.getReleaseResults().put( performTask.getReleaseId(), result );
+
+            performTask.getListener().error( e.getMessage() );
+
+            throw new TaskExecutionException( "Failed to build reactor projects.", e );
+        }
+
+        ReleaseResult result = releaseManager.performWithResult( descriptor,
+                                                                 new DefaultReleaseEnvironment().setSettings(
+                                                                     settings ), reactorProjects, listener );
 
         //override to show the actual start time
         result.setStartTime( getStartTime() );
@@ -99,61 +137,17 @@
         continuumReleaseManager.getReleaseResults().put( performTask.getReleaseId(), result );
     }
 
-    protected List<MavenProject> getReactorProjects( PerformReleaseProjectTask releaseTask )
-        throws TaskExecutionException
-    {
-        List<MavenProject> reactorProjects;
-        ReleaseDescriptor descriptor = releaseTask.getDescriptor();
-
-        if ( StringUtils.isEmpty( descriptor.getWorkingDirectory() ) )
-        {
-            //Perform with provided release parameters (CONTINUUM-1541)
-            descriptor.setCheckoutDirectory( releaseTask.getBuildDirectory().getAbsolutePath() );
-            return null;
-        }
-
-        try
-        {
-            reactorProjects = getReactorProjects( descriptor );
-        }
-        catch ( ContinuumReleaseException e )
-        {
-            ReleaseResult result = createReleaseResult();
-
-            result.appendError( e );
-
-            continuumReleaseManager.getReleaseResults().put( releaseTask.getReleaseId(), result );
-
-            releaseTask.getListener().error( e.getMessage() );
-
-            throw new TaskExecutionException( "Failed to build reactor projects.", e );
-        }
-
-        return reactorProjects;
-    }
-
     /**
      * @todo remove and use generate-reactor-projects phase
      */
-    protected List<MavenProject> getReactorProjects( ReleaseDescriptor descriptor )
+    protected List<MavenProject> getReactorProjects( ReleaseDescriptor descriptor, MavenProject project )
         throws ContinuumReleaseException
     {
         List<MavenProject> reactorProjects = new ArrayList<MavenProject>();
 
-        MavenProject project;
-        try
-        {
-            project = projectBuilder.build( getProjectDescriptorFile( descriptor ), getLocalRepository(),
-                                            getProfileManager( settings ) );
+        reactorProjects.add( project );
 
-            reactorProjects.add( project );
-
-            addModules( reactorProjects, project );
-        }
-        catch ( ProjectBuildingException e )
-        {
-            throw new ContinuumReleaseException( "Failed to build project.", e );
-        }
+        addModules( reactorProjects, project );
 
         try
         {
@@ -167,24 +161,27 @@
         {
             throw new ContinuumReleaseException( "Failed to sort projects.", e );
         }
+        catch ( MissingProjectException e )
+        {
+            throw new ContinuumReleaseException( "Failed to sort projects.", e );
+        }
 
         return reactorProjects;
     }
 
-    private void addModules( List reactorProjects, MavenProject project )
+    private void addModules( List<MavenProject> reactorProjects, MavenProject project )
         throws ContinuumReleaseException
     {
-        for ( Iterator modules = project.getModules().iterator(); modules.hasNext(); )
+        for ( Object o : project.getModules() )
         {
-            String moduleDir = modules.next().toString();
+            String moduleDir = o.toString();
 
             File pomFile = new File( project.getBasedir(), moduleDir + "/pom.xml" );
-            System.out.println( pomFile.getAbsolutePath() );
 
             try
             {
-                MavenProject reactorProject =
-                    projectBuilder.build( pomFile, getLocalRepository(), getProfileManager( settings ) );
+                MavenProject reactorProject = projectBuilder.build( pomFile, getLocalRepository(), getProfileManager(
+                    settings ) );
 
                 reactorProjects.add( reactorProject );
 
@@ -239,4 +236,23 @@
     {
         container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
     }
+
+    protected MavenProject getMavenProject( PerformReleaseProjectTask releaseTask )
+        throws ContinuumReleaseException
+    {
+        ReleaseDescriptor descriptor = releaseTask.getDescriptor();
+
+        MavenProject project;
+        try
+        {
+            project = projectBuilder.build( getProjectDescriptorFile( descriptor ), getLocalRepository(),
+                                            getProfileManager( settings ) );
+        }
+        catch ( ProjectBuildingException e )
+        {
+            throw new ContinuumReleaseException( "Failed to build project.", e );
+        }
+
+        return project;
+    }
 }
diff --git a/continuum-release/src/main/java/org/apache/maven/continuum/release/executors/PrepareReleaseTaskExecutor.java b/continuum-release/src/main/java/org/apache/maven/continuum/release/executors/PrepareReleaseTaskExecutor.java
index b953c9c..a785e9a 100644
--- a/continuum-release/src/main/java/org/apache/maven/continuum/release/executors/PrepareReleaseTaskExecutor.java
+++ b/continuum-release/src/main/java/org/apache/maven/continuum/release/executors/PrepareReleaseTaskExecutor.java
@@ -23,6 +23,8 @@
 import org.apache.maven.continuum.release.tasks.ReleaseProjectTask;
 import org.apache.maven.shared.release.ReleaseResult;
 import org.apache.maven.shared.release.config.ReleaseDescriptor;
+import org.apache.maven.shared.release.env.DefaultReleaseEnvironment;
+import org.apache.maven.shared.release.env.ReleaseEnvironment;
 import org.codehaus.plexus.taskqueue.execution.TaskExecutionException;
 
 import java.util.ArrayList;
@@ -41,8 +43,10 @@
 
         ReleaseDescriptor descriptor = prepareTask.getDescriptor();
 
-        ReleaseResult result = releaseManager.prepareWithResult( descriptor, settings, new ArrayList(), false, false,
-                                                                 prepareTask.getListener() );
+        ReleaseEnvironment releaseEnvironment = new DefaultReleaseEnvironment();
+        releaseEnvironment.setSettings( settings );
+        ReleaseResult result = releaseManager.prepareWithResult( descriptor, releaseEnvironment, new ArrayList(), false,
+                                                                 false, prepareTask.getListener() );
 
         //override to show the actual start time
         result.setStartTime( getStartTime() );
diff --git a/continuum-release/src/main/java/org/apache/maven/continuum/release/executors/RollbackReleaseTaskExecutor.java b/continuum-release/src/main/java/org/apache/maven/continuum/release/executors/RollbackReleaseTaskExecutor.java
index f0847db..fd98c29 100644
--- a/continuum-release/src/main/java/org/apache/maven/continuum/release/executors/RollbackReleaseTaskExecutor.java
+++ b/continuum-release/src/main/java/org/apache/maven/continuum/release/executors/RollbackReleaseTaskExecutor.java
@@ -22,6 +22,7 @@
 import org.apache.maven.continuum.release.tasks.ReleaseProjectTask;
 import org.apache.maven.shared.release.ReleaseExecutionException;
 import org.apache.maven.shared.release.ReleaseFailureException;
+import org.apache.maven.shared.release.ReleaseManagerListener;
 import org.codehaus.plexus.taskqueue.execution.TaskExecutionException;
 
 import java.util.ArrayList;
@@ -43,11 +44,18 @@
         }
         catch ( ReleaseExecutionException e )
         {
+            updateListener( releaseTask.getListener(), e.getMessage() );
             throw new TaskExecutionException( "Failed to rollback release", e );
         }
         catch ( ReleaseFailureException e )
         {
+            updateListener( releaseTask.getListener(), e.getMessage() );
             throw new TaskExecutionException( "Failed to rollback release", e );
         }
     }
+
+    private void updateListener( ReleaseManagerListener listener, String name )
+    {
+        listener.error( name );
+    }
 }
diff --git a/continuum-release/src/main/java/org/apache/maven/continuum/release/phase/GenerateReactorProjectsPhase.java b/continuum-release/src/main/java/org/apache/maven/continuum/release/phase/GenerateReactorProjectsPhase.java
index 8edc80d..36b865b 100644
--- a/continuum-release/src/main/java/org/apache/maven/continuum/release/phase/GenerateReactorProjectsPhase.java
+++ b/continuum-release/src/main/java/org/apache/maven/continuum/release/phase/GenerateReactorProjectsPhase.java
@@ -19,17 +19,22 @@
  * under the License.
  */
 
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.GnuParser;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
 import org.apache.maven.artifact.repository.ArtifactRepository;
 import org.apache.maven.artifact.repository.DefaultArtifactRepository;
 import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
-import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
-import org.apache.maven.artifact.resolver.ArtifactResolutionException;
 import org.apache.maven.continuum.release.ContinuumReleaseException;
 import org.apache.maven.profiles.DefaultProfileManager;
 import org.apache.maven.profiles.ProfileManager;
 import org.apache.maven.project.DuplicateProjectException;
 import org.apache.maven.project.MavenProject;
 import org.apache.maven.project.MavenProjectBuilder;
+import org.apache.maven.project.MissingProjectException;
 import org.apache.maven.project.ProjectBuildingException;
 import org.apache.maven.project.ProjectSorter;
 import org.apache.maven.settings.MavenSettingsBuilder;
@@ -38,20 +43,23 @@
 import org.apache.maven.shared.release.ReleaseFailureException;
 import org.apache.maven.shared.release.ReleaseResult;
 import org.apache.maven.shared.release.config.ReleaseDescriptor;
+import org.apache.maven.shared.release.env.ReleaseEnvironment;
 import org.apache.maven.shared.release.phase.AbstractReleasePhase;
 import org.codehaus.plexus.PlexusConstants;
 import org.codehaus.plexus.PlexusContainer;
 import org.codehaus.plexus.context.Context;
 import org.codehaus.plexus.context.ContextException;
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
+import org.codehaus.plexus.util.StringUtils;
 import org.codehaus.plexus.util.dag.CycleDetectedException;
 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
 
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
+import java.util.Properties;
+import java.util.StringTokenizer;
 
 /**
  * Generate the reactor projects
@@ -69,6 +77,10 @@
 
     private PlexusContainer container;
 
+    private static final char SET_SYSTEM_PROPERTY = 'D';
+
+    private static final char ACTIVATE_PROFILES = 'P';
+
     public ReleaseResult execute( ReleaseDescriptor releaseDescriptor, Settings settings, List reactorProjects )
         throws ReleaseExecutionException, ReleaseFailureException
     {
@@ -94,35 +106,52 @@
         return execute( releaseDescriptor, settings, reactorProjects );
     }
 
+
+    public ReleaseResult execute( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
+                                  List reactorProjects )
+        throws ReleaseExecutionException, ReleaseFailureException
+    {
+        return execute( releaseDescriptor, releaseEnvironment.getSettings(), reactorProjects );
+    }
+
+    public ReleaseResult simulate( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
+                                   List reactorProjects )
+        throws ReleaseExecutionException, ReleaseFailureException
+    {
+        return execute( releaseDescriptor, releaseEnvironment.getSettings(), reactorProjects );
+    }
+
     private List getReactorProjects( ReleaseDescriptor descriptor )
         throws ContinuumReleaseException
     {
-        List reactorProjects = new ArrayList();
+        List<MavenProject> reactorProjects = new ArrayList<MavenProject>();
 
         MavenProject project;
         try
         {
-            ArtifactRepository repository = getLocalRepository( descriptor.getAdditionalArguments() );
+            String arguments = descriptor.getAdditionalArguments();
+            ArtifactRepository repository = getLocalRepository( arguments );
+            ProfileManager profileManager = getProfileManager( getSettings() );
 
-            project = projectBuilder.buildWithDependencies( getProjectDescriptorFile( descriptor ),
-                                                            repository, getProfileManager( getSettings() ) );
+            if ( arguments != null )
+            {
+                activateProfiles( arguments, profileManager );
+            }
+
+            project = projectBuilder.build( getProjectDescriptorFile( descriptor ), repository, profileManager );
 
             reactorProjects.add( project );
 
             addModules( reactorProjects, project, repository );
         }
+        catch ( ParseException e )
+        {
+            throw new ContinuumReleaseException( "Unable to parse arguments.", e );
+        }
         catch ( ProjectBuildingException e )
         {
             throw new ContinuumReleaseException( "Failed to build project.", e );
         }
-        catch ( ArtifactNotFoundException e )
-        {
-            throw new ContinuumReleaseException( "Failed to build project.", e );
-        }
-        catch ( ArtifactResolutionException e )
-        {
-            throw new ContinuumReleaseException( "Failed to build project.", e );
-        }
 
         try
         {
@@ -136,24 +165,27 @@
         {
             throw new ContinuumReleaseException( "Failed to sort projects.", e );
         }
+        catch ( MissingProjectException e )
+        {
+            throw new ContinuumReleaseException( "Failed to sort projects.", e );
+        }
 
         return reactorProjects;
     }
 
-    private void addModules( List reactorProjects, MavenProject project, ArtifactRepository repository )
+    private void addModules( List<MavenProject> reactorProjects, MavenProject project, ArtifactRepository repository )
         throws ContinuumReleaseException
     {
-        for ( Iterator modules = project.getModules().iterator(); modules.hasNext(); )
+        for ( Object o : project.getModules() )
         {
-            String moduleDir = modules.next().toString();
+            String moduleDir = StringUtils.replace( o.toString(), '\\', '/' );
 
             File pomFile = new File( project.getBasedir(), moduleDir + "/pom.xml" );
 
             try
             {
-                MavenProject reactorProject = projectBuilder.buildWithDependencies( pomFile, repository,
-                                                                                    getProfileManager(
-                                                                                        getSettings() ) );
+                MavenProject reactorProject = projectBuilder.build( pomFile, repository, getProfileManager(
+                    getSettings() ) );
 
                 reactorProjects.add( reactorProject );
 
@@ -163,14 +195,6 @@
             {
                 throw new ContinuumReleaseException( "Failed to build project.", e );
             }
-            catch ( ArtifactNotFoundException e )
-            {
-                throw new ContinuumReleaseException( "Failed to build project.", e );
-            }
-            catch ( ArtifactResolutionException e )
-            {
-                throw new ContinuumReleaseException( "Failed to build project.", e );
-            }
         }
     }
 
@@ -191,17 +215,37 @@
         throws ContinuumReleaseException
     {
         String localRepository = null;
+        boolean found = false;
 
         if ( arguments != null )
         {
             String[] args = arguments.split( " " );
-            
-            for ( int i = 0; i < args.length; i++ )
+
+            for ( String arg : args )
             {
-                if ( args[i].contains( "-Dmaven.repo.local=" ) )
+                if ( arg.contains( "-Dmaven.repo.local=" ) )
                 {
-                    localRepository = args[i].substring( args[i].indexOf( "=" ) + 1 );
-                    break;
+                    localRepository = arg.substring( arg.indexOf( "=" ) + 1 );
+
+                    if ( localRepository.endsWith( "\"" ) )
+                    {
+                        localRepository = localRepository.substring( 0, localRepository.indexOf( "\"" ) );
+                        break;
+                    }
+
+                    found = true;
+                    continue;
+                }
+
+                if ( found )
+                {
+                    localRepository += " " + arg;
+
+                    if ( localRepository.endsWith( "\"" ) )
+                    {
+                        localRepository = localRepository.substring( 0, localRepository.indexOf( "\"" ) );
+                        break;
+                    }
                 }
             }
         }
@@ -210,10 +254,6 @@
         {
             localRepository = getSettings().getLocalRepository();
         }
-        else if ( localRepository.endsWith( "\"" ) )
-        {
-            localRepository = localRepository.substring( 0, localRepository.indexOf( "\"" ) );
-        }
 
         return new DefaultArtifactRepository( "local-repository", "file://" + localRepository,
                                               new DefaultRepositoryLayout() );
@@ -221,7 +261,8 @@
 
     private ProfileManager getProfileManager( Settings settings )
     {
-        return new DefaultProfileManager( container, settings );
+        Properties props = new Properties();
+        return new DefaultProfileManager( container, settings, props );
     }
 
     private Settings getSettings()
@@ -241,9 +282,61 @@
         }
     }
 
+    @SuppressWarnings( "static-access" )
+    private void activateProfiles( String arguments, ProfileManager profileManager )
+        throws ParseException
+    {
+        CommandLineParser parser = new GnuParser();
+
+        Options options = new Options();
+
+        options.addOption( OptionBuilder.withLongOpt( "activate-profiles" ).withDescription(
+            "Comma-delimited list of profiles to activate" ).hasArg().create( ACTIVATE_PROFILES ) );
+
+        options.addOption( OptionBuilder.withLongOpt( "define" ).hasArg().withDescription(
+            "Define a system property" ).create( SET_SYSTEM_PROPERTY ) );
+
+        String[] args = StringUtils.split( arguments );
+
+        CommandLine commandLine = parser.parse( options, args );
+
+        if ( commandLine.hasOption( ACTIVATE_PROFILES ) )
+        {
+            String[] profileOptionValues = commandLine.getOptionValues( ACTIVATE_PROFILES );
+
+            if ( profileOptionValues != null )
+            {
+                for ( int i = 0; i < profileOptionValues.length; ++i )
+                {
+                    StringTokenizer profileTokens = new StringTokenizer( profileOptionValues[i], "," );
+
+                    while ( profileTokens.hasMoreTokens() )
+                    {
+                        String profileAction = profileTokens.nextToken().trim();
+
+                        if ( profileAction.startsWith( "-" ) || profileAction.startsWith( "!" ) )
+                        {
+                            profileManager.explicitlyDeactivate( profileAction.substring( 1 ) );
+                        }
+                        else if ( profileAction.startsWith( "+" ) )
+                        {
+                            profileManager.explicitlyActivate( profileAction.substring( 1 ) );
+                        }
+                        else
+                        {
+                            profileManager.explicitlyActivate( profileAction );
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     public void contextualize( Context context )
         throws ContextException
     {
         container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
     }
+
+
 }
diff --git a/continuum-release/src/main/java/org/apache/maven/continuum/release/phase/UpdateWorkingCopyPhase.java b/continuum-release/src/main/java/org/apache/maven/continuum/release/phase/UpdateWorkingCopyPhase.java
index 12e7d36..a6adb5c 100644
--- a/continuum-release/src/main/java/org/apache/maven/continuum/release/phase/UpdateWorkingCopyPhase.java
+++ b/continuum-release/src/main/java/org/apache/maven/continuum/release/phase/UpdateWorkingCopyPhase.java
@@ -19,12 +19,21 @@
  * under the License.
  */
 
+import org.apache.commons.lang.StringUtils;
+import org.apache.continuum.scm.ContinuumScmUtils;
+import org.apache.maven.scm.ScmBranch;
 import org.apache.maven.scm.ScmException;
 import org.apache.maven.scm.ScmFileSet;
 import org.apache.maven.scm.ScmVersion;
+import org.apache.maven.scm.command.checkout.CheckOutScmResult;
 import org.apache.maven.scm.command.update.UpdateScmResult;
 import org.apache.maven.scm.manager.NoSuchScmProviderException;
+import org.apache.maven.scm.manager.plexus.PlexusLogger;
 import org.apache.maven.scm.provider.ScmProvider;
+import org.apache.maven.scm.provider.ScmProviderRepository;
+import org.apache.maven.scm.provider.ScmUrlUtils;
+import org.apache.maven.scm.provider.git.gitexe.command.branch.GitBranchCommand;
+import org.apache.maven.scm.provider.git.repository.GitScmProviderRepository;
 import org.apache.maven.scm.repository.ScmRepository;
 import org.apache.maven.scm.repository.ScmRepositoryException;
 import org.apache.maven.settings.Settings;
@@ -32,6 +41,7 @@
 import org.apache.maven.shared.release.ReleaseFailureException;
 import org.apache.maven.shared.release.ReleaseResult;
 import org.apache.maven.shared.release.config.ReleaseDescriptor;
+import org.apache.maven.shared.release.env.ReleaseEnvironment;
 import org.apache.maven.shared.release.phase.AbstractReleasePhase;
 import org.apache.maven.shared.release.scm.ReleaseScmCommandException;
 import org.apache.maven.shared.release.scm.ReleaseScmRepositoryException;
@@ -65,6 +75,54 @@
 
         ScmRepository repository;
         ScmProvider provider;
+
+        // CONTINUUM-2628
+        // if git ssh, use credentials specified in scm url if present. otherwise, use the scm credentials of project
+        String providerType = ScmUrlUtils.getProvider( releaseDescriptor.getScmSourceUrl() );
+        String scmSpecificUrl = releaseDescriptor.getScmSourceUrl().substring( providerType.length() + 5 );
+
+        if ( providerType.contains( ContinuumScmUtils.GIT_SCM_PROVIDERTYPE ) && scmSpecificUrl.startsWith(
+            GitScmProviderRepository.PROTOCOL_SSH ) )
+        {
+            scmSpecificUrl = scmSpecificUrl.substring( GitScmProviderRepository.PROTOCOL_SSH.length() + 3 );
+
+            // extract user information
+            int indexAt = scmSpecificUrl.indexOf( "@" );
+            String sshScmUsername = "";
+            String sshScmPassword = "";
+
+            if ( indexAt >= 0 )
+            {
+                String userInfo = scmSpecificUrl.substring( 0, indexAt );
+                sshScmUsername = userInfo;
+
+                int indexPwdSep = userInfo.indexOf( ":" );
+                // password is specified in the url
+                if ( indexPwdSep < 0 )
+                {
+                    sshScmUsername = userInfo.substring( indexPwdSep + 1 );
+                }
+                else
+                {
+                    sshScmUsername = userInfo.substring( 0, indexPwdSep );
+                    sshScmPassword = userInfo.substring( indexPwdSep + 1 );
+                }
+            }
+
+            if ( !StringUtils.isBlank( sshScmUsername ) )
+            {
+                releaseDescriptor.setScmUsername( sshScmUsername );
+                if ( !StringUtils.isBlank( sshScmPassword ) )
+                {
+                    releaseDescriptor.setScmPassword( sshScmPassword );
+                }
+                else
+                {
+                    releaseDescriptor.setScmPassword( null );
+                }
+            }
+        }
+
         try
         {
             repository = scmRepositoryConfigurator.getConfiguredRepository( releaseDescriptor, settings );
@@ -81,11 +139,41 @@
             throw new ReleaseExecutionException( "Unable to configure SCM repository: " + e.getMessage(), e );
         }
 
-        UpdateScmResult result;
+        UpdateScmResult updateScmResult = null;
+        CheckOutScmResult checkOutScmResult = null;
+
+        File workingDirectory = new File( releaseDescriptor.getWorkingDirectory() );
+        ScmFileSet workingDirSet = new ScmFileSet( workingDirectory );
+
         try
         {
-            result = provider.update( repository, new ScmFileSet( new File( releaseDescriptor.getWorkingDirectory() ) ),
-                                      (ScmVersion) null );
+            if ( !workingDirectory.exists() )
+            {
+                workingDirectory.mkdirs();
+            }
+
+            ScmVersion scmTag = null;
+
+            ScmProviderRepository providerRepo = repository.getProviderRepository();
+
+            // FIXME: This should be handled by the maven-scm git provider
+            if ( providerRepo instanceof GitScmProviderRepository )
+            {
+                String branchName = GitBranchCommand.getCurrentBranch( new PlexusLogger( getLogger() ),
+                                                                       (GitScmProviderRepository) providerRepo,
+                                                                       workingDirSet );
+                scmTag = new ScmBranch( branchName );
+            }
+
+            if ( workingDirectory.listFiles().length > 1 )
+            {
+                updateScmResult = provider.update( repository, workingDirSet, scmTag );
+            }
+            else
+            {
+                checkOutScmResult = provider.checkOut( repository, new ScmFileSet( workingDirectory ) );
+                checkOutScmResult = provider.checkOut( repository, workingDirSet, scmTag );
+            }
         }
         catch ( ScmException e )
         {
@@ -93,12 +181,24 @@
                                                  e );
         }
 
-        if ( !result.isSuccess() )
+        if ( updateScmResult != null )
         {
-            throw new ReleaseScmCommandException( "Unable to update current working copy", result );
-        }
+            if ( !updateScmResult.isSuccess() )
+            {
+                throw new ReleaseScmCommandException( "Unable to update current working copy", updateScmResult );
+            }
 
-        copyUpdated = ( result.getUpdatedFiles().size() > 0 );
+            copyUpdated = updateScmResult.getUpdatedFiles().size() > 0;
+        }
+        else
+        {
+            if ( !checkOutScmResult.isSuccess() )
+            {
+                throw new ReleaseScmCommandException( "Unable to checkout project", checkOutScmResult );
+            }
+
+            copyUpdated = checkOutScmResult.getCheckedOutFiles().size() > 0;
+        }
 
         relResult.setResultCode( ReleaseResult.SUCCESS );
 
@@ -120,4 +220,18 @@
     {
         this.copyUpdated = copyUpdated;
     }
+
+    public ReleaseResult execute( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
+                                  List reactorProjects )
+        throws ReleaseExecutionException, ReleaseFailureException
+    {
+        return execute( releaseDescriptor, releaseEnvironment.getSettings(), reactorProjects );
+    }
+
+    public ReleaseResult simulate( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
+                                   List reactorProjects )
+        throws ReleaseExecutionException, ReleaseFailureException
+    {
+        return execute( releaseDescriptor, releaseEnvironment.getSettings(), reactorProjects );
+    }
 }
diff --git a/continuum-release/src/main/java/org/apache/maven/continuum/release/tasks/AbstractReleaseProjectTask.java b/continuum-release/src/main/java/org/apache/maven/continuum/release/tasks/AbstractReleaseProjectTask.java
index a36ec2c..9723910 100644
--- a/continuum-release/src/main/java/org/apache/maven/continuum/release/tasks/AbstractReleaseProjectTask.java
+++ b/continuum-release/src/main/java/org/apache/maven/continuum/release/tasks/AbstractReleaseProjectTask.java
@@ -19,7 +19,6 @@
  * under the License.
  */
 
-import org.apache.maven.continuum.model.system.Profile;
 import org.apache.maven.shared.release.ReleaseManagerListener;
 import org.apache.maven.shared.release.config.ReleaseDescriptor;
 import org.codehaus.plexus.taskqueue.Task;
@@ -39,15 +38,11 @@
 
     private long maxExecutionTime;
 
-    private Profile profile;
-
-    public AbstractReleaseProjectTask( String releaseId, ReleaseDescriptor descriptor, ReleaseManagerListener listener,
-                                       Profile profile )
+    public AbstractReleaseProjectTask( String releaseId, ReleaseDescriptor descriptor, ReleaseManagerListener listener )
     {
         this.releaseId = releaseId;
         this.descriptor = descriptor;
         this.listener = listener;
-        this.profile = profile;
     }
 
     public ReleaseDescriptor getDescriptor()
@@ -89,14 +84,4 @@
     {
         this.maxExecutionTime = maxTime;
     }
-
-    public Profile getProfile()
-    {
-        return profile;
-    }
-
-    public void setProfile( Profile profile )
-    {
-        this.profile = profile;
-    }
 }
diff --git a/continuum-release/src/main/java/org/apache/maven/continuum/release/tasks/PerformReleaseProjectTask.java b/continuum-release/src/main/java/org/apache/maven/continuum/release/tasks/PerformReleaseProjectTask.java
index 3e24836..30bffaa 100644
--- a/continuum-release/src/main/java/org/apache/maven/continuum/release/tasks/PerformReleaseProjectTask.java
+++ b/continuum-release/src/main/java/org/apache/maven/continuum/release/tasks/PerformReleaseProjectTask.java
@@ -20,7 +20,6 @@
  */
 
 import org.apache.continuum.model.repository.LocalRepository;
-import org.apache.maven.continuum.model.system.Profile;
 import org.apache.maven.shared.release.ReleaseManagerListener;
 import org.apache.maven.shared.release.config.ReleaseDescriptor;
 
@@ -38,32 +37,26 @@
     private String goals;
 
     private boolean useReleaseProfile = true;
-    
+
     private LocalRepository localRepository;
 
     public PerformReleaseProjectTask( String releaseId, ReleaseDescriptor descriptor, File buildDirectory, String goals,
                                       boolean useReleaseProfile, ReleaseManagerListener listener )
     {
-        this( releaseId, descriptor, buildDirectory, goals, useReleaseProfile, listener, null, null );
+        this( releaseId, descriptor, buildDirectory, goals, useReleaseProfile, listener, null );
     }
 
     public PerformReleaseProjectTask( String releaseId, ReleaseDescriptor descriptor, File buildDirectory, String goals,
-                                      boolean useReleaseProfile, ReleaseManagerListener listener, LocalRepository repository )
+                                      boolean useReleaseProfile, ReleaseManagerListener listener,
+                                      LocalRepository repository )
     {
-        this( releaseId, descriptor, buildDirectory, goals, useReleaseProfile, listener, repository, null );
-    }
-    
-    public PerformReleaseProjectTask( String releaseId, ReleaseDescriptor descriptor, File buildDirectory, String goals,
-                                      boolean useReleaseProfile, ReleaseManagerListener listener, LocalRepository repository,
-                                      Profile profile )
-    {
-        super( releaseId, descriptor, listener, profile );
+        super( releaseId, descriptor, listener );
         setBuildDirectory( buildDirectory );
         setGoals( goals );
         setUseReleaseProfile( useReleaseProfile );
         setLocalRepository( repository );
     }
-    
+
     public String getGoals()
     {
         return goals;
@@ -93,12 +86,12 @@
     {
         this.buildDirectory = buildDirectory;
     }
-    
+
     public LocalRepository getLocalRepository()
     {
         return localRepository;
     }
-    
+
     public void setLocalRepository( LocalRepository localRepository )
     {
         this.localRepository = localRepository;
diff --git a/continuum-release/src/main/java/org/apache/maven/continuum/release/tasks/PrepareReleaseProjectTask.java b/continuum-release/src/main/java/org/apache/maven/continuum/release/tasks/PrepareReleaseProjectTask.java
index 73da0b8..67831a3 100644
--- a/continuum-release/src/main/java/org/apache/maven/continuum/release/tasks/PrepareReleaseProjectTask.java
+++ b/continuum-release/src/main/java/org/apache/maven/continuum/release/tasks/PrepareReleaseProjectTask.java
@@ -19,7 +19,6 @@
  * under the License.
  */
 
-import org.apache.maven.continuum.model.system.Profile;
 import org.apache.maven.shared.release.ReleaseManagerListener;
 import org.apache.maven.shared.release.config.ReleaseDescriptor;
 
@@ -32,11 +31,6 @@
 {
     public PrepareReleaseProjectTask( String releaseId, ReleaseDescriptor descriptor, ReleaseManagerListener listener )
     {
-        this( releaseId, descriptor, listener, null );
-    }
-    
-    public PrepareReleaseProjectTask( String releaseId, ReleaseDescriptor descriptor, ReleaseManagerListener listener, Profile profile )
-    {
-        super( releaseId, descriptor, listener, profile );
+        super( releaseId, descriptor, listener );
     }
 }
diff --git a/continuum-release/src/main/java/org/apache/maven/continuum/release/tasks/RollbackReleaseProjectTask.java b/continuum-release/src/main/java/org/apache/maven/continuum/release/tasks/RollbackReleaseProjectTask.java
index 2c2a0f0..d4ed782 100644
--- a/continuum-release/src/main/java/org/apache/maven/continuum/release/tasks/RollbackReleaseProjectTask.java
+++ b/continuum-release/src/main/java/org/apache/maven/continuum/release/tasks/RollbackReleaseProjectTask.java
@@ -1,6 +1,5 @@
 package org.apache.maven.continuum.release.tasks;
 
-import org.apache.maven.continuum.model.system.Profile;
 import org.apache.maven.shared.release.ReleaseManagerListener;
 import org.apache.maven.shared.release.config.ReleaseDescriptor;
 
@@ -32,11 +31,6 @@
 {
     public RollbackReleaseProjectTask( String releaseId, ReleaseDescriptor descriptor, ReleaseManagerListener listener )
     {
-        this( releaseId, descriptor, listener, null );
-    }
-    
-    public RollbackReleaseProjectTask( String releaseId, ReleaseDescriptor descriptor, ReleaseManagerListener listener, Profile profile )
-    {
-        super( releaseId, descriptor, listener, profile );
+        super( releaseId, descriptor, listener );
     }
 }
diff --git a/continuum-release/src/main/resources/META-INF/plexus/components.xml b/continuum-release/src/main/resources/META-INF/plexus/components.xml
index 0ba557d..cf97901 100644
--- a/continuum-release/src/main/resources/META-INF/plexus/components.xml
+++ b/continuum-release/src/main/resources/META-INF/plexus/components.xml
@@ -44,10 +44,7 @@
           <field-name>rollbackReleaseQueue</field-name>
         </requirement>
         <requirement>
-          <role>org.apache.maven.continuum.utils.WorkingDirectoryService</role>
-        </requirement>
-        <requirement>
-          <role>org.apache.maven.continuum.installation.InstallationService</role>
+          <role>org.apache.maven.scm.manager.ScmManager</role>
         </requirement>
       </requirements>
     </component>
@@ -282,6 +279,21 @@
           <phase>scm-commit-rollback</phase>
           <phase>remove-scm-tag</phase>
         </rollbackPhases>
+        <!-- Set <branchPhases> even though it is not used in Continuum. Having this empty causes an NPE when cleaning up the release
+             in maven-release 2.0! -->
+        <branchPhases>
+          <phase>create-backup-poms</phase>
+          <phase>check-poms</phase>
+          <phase>scm-check-modifications</phase>
+          <phase>map-branch-versions</phase>
+          <phase>map-development-versions</phase>
+          <phase>rewrite-poms-for-branch</phase>
+          <phase>scm-commit-branch</phase>
+          <phase>scm-branch</phase>
+          <phase>rewrite-poms-for-development</phase>
+          <phase>scm-commit-release</phase>
+          <phase>end-release</phase>
+        </branchPhases>
       </configuration>
     </component>
     <component>
@@ -327,7 +339,7 @@
         </requirement>
       </requirements>
     </component>
-    
+
     <!-- This needs to be removed once we can upgrade maven-project to 2.1-SNAPSHOT or later. -->
     <component>
       <role>org.apache.maven.artifact.metadata.ArtifactMetadataSource</role>
diff --git a/continuum-release/src/test/java/org/apache/maven/continuum/release/executors/ReleaseTaskExecutorTest.java b/continuum-release/src/test/java/org/apache/maven/continuum/release/executors/ReleaseTaskExecutorTest.java
index 8ccb635..5cb162d 100644
--- a/continuum-release/src/test/java/org/apache/maven/continuum/release/executors/ReleaseTaskExecutorTest.java
+++ b/continuum-release/src/test/java/org/apache/maven/continuum/release/executors/ReleaseTaskExecutorTest.java
@@ -19,8 +19,6 @@
  * under the License.
  */
 
-import java.io.File;
-
 import org.apache.continuum.release.config.ContinuumReleaseDescriptor;
 import org.apache.maven.continuum.release.ContinuumReleaseManager;
 import org.apache.maven.continuum.release.tasks.PerformReleaseProjectTask;
@@ -39,6 +37,14 @@
 import org.codehaus.plexus.taskqueue.execution.TaskExecutionException;
 import org.codehaus.plexus.taskqueue.execution.TaskExecutor;
 import org.codehaus.plexus.util.FileUtils;
+import org.codehaus.plexus.util.IOUtil;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Properties;
 
 /**
  * @author Edwin Punzalan
@@ -130,6 +136,9 @@
         releaseSimpleProject();
         releaseAndRollbackProject();
         releaseSimpleProjectWithNextVersion();
+        releasePerformWithExecutableInDescriptor();
+        releaseProjectWithDependencyOfCustomPackagingType();
+        releaseProjectWithProfile();
     }
 
     public void releaseSimpleProjectWithNextVersion()
@@ -167,6 +176,7 @@
         pom = FileUtils.fileRead( new File( testDir, "pom.xml" ) );
         assertTrue( "Test released version", pom.indexOf( "<version>2.0</version>" ) > 0 );
 
+/* CONTINUUM-2559
         performExec.executeTask(
             getPerformTask( "testRelease", descriptor, new File( getBasedir(), "target/test-classes/build-dir" ) ) );
 
@@ -175,6 +185,7 @@
         {
             fail( "Error in release:perform. Release output follows:\n" + result.getOutput() );
         }
+*/
     }
 
     public void releaseAndRollbackProject()
@@ -215,13 +226,178 @@
         pom = FileUtils.fileRead( new File( workDir, "pom.xml" ) );
         assertTrue( "Test rollback version", pom.indexOf( "<version>1.1-SNAPSHOT</version>" ) > 0 );
 
-        assertFalse( "Test that release.properties has been cleaned",
-                     new File( workDir, "release.properties" ).exists() );
+        assertFalse( "Test that release.properties has been cleaned", new File( workDir,
+                                                                                "release.properties" ).exists() );
         assertFalse( "Test that backup file has been cleaned", new File( workDir, "pom.xml.releaseBackup" ).exists() );
 
         //@todo when implemented already, check if tag was also removed
     }
 
+    public void releasePerformWithExecutableInDescriptor()
+        throws Exception
+    {
+        String scmPath = new File( getBasedir(), "target/scm-test" ).getAbsolutePath().replace( '\\', '/' );
+        File workDir = new File( getBasedir(), "target/test-classes/work-dir" );
+        FileUtils.deleteDirectory( workDir );
+        File testDir = new File( getBasedir(), "target/test-classes/test-dir" );
+        FileUtils.deleteDirectory( testDir );
+
+        ContinuumReleaseDescriptor descriptor = new ContinuumReleaseDescriptor();
+        descriptor.setInteractive( false );
+        descriptor.setScmSourceUrl( "scm:svn:file://localhost/" + scmPath + "/trunk" );
+        descriptor.setWorkingDirectory( workDir.getAbsolutePath() );
+
+        ScmRepository repository = getScmRepositorty( descriptor.getScmSourceUrl() );
+        ScmFileSet fileSet = new ScmFileSet( workDir );
+        scmManager.getProviderByRepository( repository ).checkOut( repository, fileSet, (ScmVersion) null );
+
+        String pom = FileUtils.fileRead( new File( workDir, "pom.xml" ) );
+        assertTrue( "Test dev version", pom.indexOf( "<version>2.1-SNAPSHOT</version>" ) > 0 );
+
+        doPrepareWithNoError( descriptor );
+
+        pom = FileUtils.fileRead( new File( workDir, "pom.xml" ) );
+        assertTrue( "Test version increment", pom.indexOf( "<version>2.2-SNAPSHOT</version>" ) > 0 );
+
+        repository = getScmRepositorty( "scm:svn:file://localhost/" + scmPath + "/tags/test-artifact-2.1" );
+        fileSet = new ScmFileSet( testDir );
+        scmManager.getProviderByRepository( repository ).checkOut( repository, fileSet, (ScmVersion) null );
+
+        pom = FileUtils.fileRead( new File( testDir, "pom.xml" ) );
+        assertTrue( "Test released version", pom.indexOf( "<version>2.1</version>" ) > 0 );
+
+        File file = new File( descriptor.getWorkingDirectory(), "release.properties" );
+        assertTrue( "release.properties file does not exist", file.exists() );
+
+        Properties properties = new Properties();
+
+        InputStream inStream = null;
+        OutputStream outStream = null;
+
+        try
+        {
+            inStream = new FileInputStream( file );
+
+            properties.load( inStream );
+
+            properties.setProperty( "build.executable", "test/executable/mvn" );
+
+            outStream = new FileOutputStream( file );
+
+            properties.store( outStream, "release configuration" );
+        }
+        finally
+        {
+            IOUtil.close( inStream );
+        }
+
+        performExec.executeTask( getPerformTask( "testRelease", descriptor, new File( getBasedir(),
+                                                                                      "target/test-classes/build-dir" ) ) );
+
+        ReleaseResult result = (ReleaseResult) releaseManager.getReleaseResults().get( "testRelease" );
+
+        if ( !result.getOutput().replace( "\\", "/" ).contains( "test/executable/mvn" ) )
+        {
+            fail( "Error in release:perform. Missing executable" );
+        }
+    }
+
+    // CONTINUUM-1814
+    public void releaseProjectWithDependencyOfCustomPackagingType()
+        throws Exception
+    {
+        String scmPath = new File( getBasedir(), "target/scm-test/continuum-1814" ).getAbsolutePath().replace( '\\',
+                                                                                                               '/' );
+        File workDir = new File( getBasedir(), "target/test-classes/continuum-1814" );
+        FileUtils.deleteDirectory( workDir );
+        File testDir = new File( getBasedir(), "target/test-classes/test-dir" );
+        FileUtils.deleteDirectory( testDir );
+
+        ContinuumReleaseDescriptor descriptor = new ContinuumReleaseDescriptor();
+        descriptor.setInteractive( false );
+        descriptor.setScmSourceUrl( "scm:svn:file://localhost/" + scmPath + "/trunk" );
+        descriptor.setWorkingDirectory( workDir.getAbsolutePath() );
+
+        ScmRepository repository = getScmRepositorty( descriptor.getScmSourceUrl() );
+        ScmFileSet fileSet = new ScmFileSet( workDir );
+        scmManager.getProviderByRepository( repository ).checkOut( repository, fileSet, (ScmVersion) null );
+
+        String pom = FileUtils.fileRead( new File( workDir, "pom.xml" ) );
+        assertTrue( "Test dev version", pom.indexOf( "<version>1.6-SNAPSHOT</version>" ) > 0 );
+
+        doPrepareWithNoError( descriptor );
+
+        pom = FileUtils.fileRead( new File( workDir, "pom.xml" ) );
+        assertTrue( "Test version increment", pom.indexOf( "<version>1.7-SNAPSHOT</version>" ) > 0 );
+
+        repository = getScmRepositorty( "scm:svn:file://localhost/" + scmPath + "/tags/continuum-1814-1.6" );
+        fileSet = new ScmFileSet( testDir );
+        scmManager.getProviderByRepository( repository ).checkOut( repository, fileSet, (ScmVersion) null );
+
+        pom = FileUtils.fileRead( new File( testDir, "pom.xml" ) );
+        assertTrue( "Test released version", pom.indexOf( "<version>1.6</version>" ) > 0 );
+
+/* CONTINUUM-2559
+        performExec.executeTask(
+                getPerformTask( "testRelease", descriptor, new File( getBasedir(), "target/test-classes/build-dir" ) ) );
+
+        ReleaseResult result = (ReleaseResult) releaseManager.getReleaseResults().get( "testRelease" );
+        if ( result.getResultCode() != ReleaseResult.SUCCESS )
+        {
+            fail( "Error in release:perform. Release output follows:\n" + result.getOutput() );
+        }
+*/
+    }
+
+    // CONTINUUM-2610
+    public void releaseProjectWithProfile()
+        throws Exception
+    {
+        String scmPath = new File( getBasedir(), "target/scm-test/continuum-2610" ).getAbsolutePath().replace( '\\',
+                                                                                                               '/' );
+        File workDir = new File( getBasedir(), "target/test-classes/continuum-2610" );
+        FileUtils.deleteDirectory( workDir );
+        File testDir = new File( getBasedir(), "target/test-classes/test-dir" );
+        FileUtils.deleteDirectory( testDir );
+
+        ContinuumReleaseDescriptor descriptor = new ContinuumReleaseDescriptor();
+        descriptor.setInteractive( false );
+        descriptor.setScmSourceUrl( "scm:svn:file://localhost/" + scmPath + "/trunk" );
+        descriptor.setWorkingDirectory( workDir.getAbsolutePath() );
+        descriptor.setAdditionalArguments( "-Pall" );
+
+        ScmRepository repository = getScmRepositorty( descriptor.getScmSourceUrl() );
+        ScmFileSet fileSet = new ScmFileSet( workDir );
+        scmManager.getProviderByRepository( repository ).checkOut( repository, fileSet, (ScmVersion) null );
+
+        String pom = FileUtils.fileRead( new File( workDir, "pom.xml" ) );
+        assertTrue( "Test root dev version", pom.indexOf( "<version>1.0-SNAPSHOT</version>" ) > 0 );
+        String moduleAPom = FileUtils.fileRead( new File( workDir, "module-A/pom.xml" ) );
+        assertTrue( "Test module A dev version", moduleAPom.indexOf( "<version>1.0-SNAPSHOT</version>" ) > 0 );
+        String moduleBPom = FileUtils.fileRead( new File( workDir, "module-B/pom.xml" ) );
+        assertTrue( "Test module B dev version", moduleBPom.indexOf( "<version>1.0-SNAPSHOT</version>" ) > 0 );
+
+        doPrepareWithNoError( descriptor );
+
+        pom = FileUtils.fileRead( new File( workDir, "pom.xml" ) );
+        assertTrue( "Test root version increment", pom.indexOf( "<version>1.1-SNAPSHOT</version>" ) > 0 );
+        moduleAPom = FileUtils.fileRead( new File( workDir, "module-A/pom.xml" ) );
+        assertTrue( "Test module A version increment", moduleAPom.indexOf( "<version>1.1-SNAPSHOT</version>" ) > 0 );
+        moduleBPom = FileUtils.fileRead( new File( workDir, "module-B/pom.xml" ) );
+        assertTrue( "Test module B version increment", moduleBPom.indexOf( "<version>1.1-SNAPSHOT</version>" ) > 0 );
+
+        repository = getScmRepositorty( "scm:svn:file://localhost/" + scmPath + "/tags/continuum-2610-1.0" );
+        fileSet = new ScmFileSet( testDir );
+        scmManager.getProviderByRepository( repository ).checkOut( repository, fileSet, (ScmVersion) null );
+
+        pom = FileUtils.fileRead( new File( testDir, "pom.xml" ) );
+        assertTrue( "Test root released version", pom.indexOf( "<version>1.0</version>" ) > 0 );
+        moduleAPom = FileUtils.fileRead( new File( testDir, "module-A/pom.xml" ) );
+        assertTrue( "Test module A released version", moduleAPom.indexOf( "<version>1.0</version>" ) > 0 );
+        moduleBPom = FileUtils.fileRead( new File( testDir, "module-B/pom.xml" ) );
+        assertTrue( "Test module B released version", moduleBPom.indexOf( "<version>1.0</version>" ) > 0 );
+    }
+
     private void doPrepareWithNoError( ReleaseDescriptor descriptor )
         throws TaskExecutionException
     {
@@ -236,16 +412,12 @@
 
     private Task getPrepareTask( String releaseId, ReleaseDescriptor descriptor )
     {
-        Task task = new PrepareReleaseProjectTask( releaseId, descriptor, null );
-
-        return task;
+        return new PrepareReleaseProjectTask( releaseId, descriptor, null );
     }
 
     private Task getPerformTask( String releaseId, ReleaseDescriptor descriptor, File buildDir )
     {
-        Task task = new PerformReleaseProjectTask( releaseId, descriptor, buildDir, "package", true, null );
-
-        return task;
+        return new PerformReleaseProjectTask( releaseId, descriptor, buildDir, "package", true, null );
     }
 
     private ScmRepository getScmRepositorty( String scmUrl )
diff --git a/continuum-release/src/test/java/org/apache/maven/continuum/release/phase/UpdateWorkingCopyPhaseTest.java b/continuum-release/src/test/java/org/apache/maven/continuum/release/phase/UpdateWorkingCopyPhaseTest.java
new file mode 100644
index 0000000..8d1a9e2
--- /dev/null
+++ b/continuum-release/src/test/java/org/apache/maven/continuum/release/phase/UpdateWorkingCopyPhaseTest.java
@@ -0,0 +1,113 @@
+package org.apache.maven.continuum.release.phase;
+
+/*
+ * 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 org.apache.continuum.release.config.ContinuumReleaseDescriptor;
+import org.apache.maven.settings.Settings;
+import org.apache.maven.shared.release.phase.ReleasePhase;
+import org.codehaus.plexus.spring.PlexusInSpringTestCase;
+import org.codehaus.plexus.util.FileUtils;
+
+import java.io.File;
+
+public class UpdateWorkingCopyPhaseTest
+    extends PlexusInSpringTestCase
+{
+    private UpdateWorkingCopyPhase phase;
+    private ContinuumReleaseDescriptor releaseDescriptor;
+    private File workingDirectory;
+
+    protected void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        phase = (UpdateWorkingCopyPhase) lookup( ReleasePhase.ROLE, "update-working-copy" );
+        assertNotNull( phase );
+
+        releaseDescriptor = createReleaseDescriptor();
+
+        workingDirectory = new File( releaseDescriptor.getWorkingDirectory() );
+
+        // Ensure every test method starts with no working dir
+        FileUtils.deleteDirectory( workingDirectory );
+        assertFalse( workingDirectory.exists() );
+
+        // set up project scm
+        File scmPathFile = new File( getBasedir(), "target/scm-src" ).getAbsoluteFile();
+        File scmTargetPathFile = new File( getBasedir(), "/target/scm-test" ).getAbsoluteFile();
+        FileUtils.copyDirectoryStructure( scmPathFile, scmTargetPathFile );
+    }
+
+    public void testWorkingDirDoesNotExist()
+        throws Exception
+    {
+        phase.execute( releaseDescriptor, new Settings(), null );
+        assertPopulatedWorkingDirectory();
+    }
+
+    public void testWorkingDirAlreadyExistsWithProjectCheckout()
+        throws Exception
+    {
+        // Run the update once, should checkout out the project into working dir
+        phase.execute( releaseDescriptor, new Settings(), null );
+        assertPopulatedWorkingDirectory();
+
+        // Run again, to ensure nothing funny happened
+        phase.execute( releaseDescriptor, new Settings(), null );
+        assertPopulatedWorkingDirectory();
+    }
+
+    public void testWorkingDirAlreadyExistsNoProjectCheckout()
+        throws Exception
+    {
+        workingDirectory.mkdirs();
+        assertEmptyWorkingDirectory();
+
+        phase.execute( releaseDescriptor, new Settings(), null );
+        assertPopulatedWorkingDirectory();
+    }
+
+    private void assertEmptyWorkingDirectory()
+    {
+        assertTrue( workingDirectory.exists() );
+        assertTrue( workingDirectory.listFiles().length == 0 );
+    }
+
+    private void assertPopulatedWorkingDirectory()
+    {
+        assertTrue( workingDirectory.exists() );
+        assertTrue( workingDirectory.listFiles().length > 0 );
+    }
+
+    private ContinuumReleaseDescriptor createReleaseDescriptor()
+    {
+        // project source and working directory paths
+        String projectUrl = getBasedir() + "/target/scm-test/trunk";
+        String workingDirPath = getBasedir() + "/target/test-classes/updateWorkingCopy_working-directory";
+
+        // create release descriptor
+        ContinuumReleaseDescriptor releaseDescriptor = new ContinuumReleaseDescriptor();
+        releaseDescriptor.setScmSourceUrl( "scm:svn:file://localhost/" + projectUrl );
+        releaseDescriptor.setWorkingDirectory( workingDirPath );
+
+        return releaseDescriptor;
+    }
+}
diff --git a/continuum-release/src/test/resources/META-INF/continuum/continuum-configuration.xml b/continuum-release/src/test/resources/META-INF/continuum/continuum-configuration.xml
index d273425..7168804 100755
--- a/continuum-release/src/test/resources/META-INF/continuum/continuum-configuration.xml
+++ b/continuum-release/src/test/resources/META-INF/continuum/continuum-configuration.xml
@@ -21,9 +21,9 @@
 
 <configuration>
   <system/>
-  <jndi prefix="java:comp/env" config-optional="true"/>  
+  <jndi prefix="java:comp/env" config-optional="true"/>
   <xml fileName="${appserver.base}/conf/continuum.xml" config-optional="true"
        config-forceCreate="true" config-name="org.apache.continuum"/>
   <xml fileName="${user.home}/.m2/continuum.xml" config-optional="true"
-       config-forceCreate="true" config-name="org.apache.continuum.user"/>  
+       config-forceCreate="true" config-name="org.apache.continuum.user"/>
 </configuration>
diff --git a/continuum-store/src/test/resources/log4j.xml b/continuum-release/src/test/resources/log4j.xml
similarity index 100%
rename from continuum-store/src/test/resources/log4j.xml
rename to continuum-release/src/test/resources/log4j.xml
diff --git a/continuum-release/src/test/scm/db/current b/continuum-release/src/test/scm/db/current
index 64b1838..7b64432 100644
--- a/continuum-release/src/test/scm/db/current
+++ b/continuum-release/src/test/scm/db/current
@@ -1 +1 @@
-2 5 1
+6 2e 1
diff --git a/continuum-release/src/test/scm/db/revprops/3 b/continuum-release/src/test/scm/db/revprops/3
new file mode 100644
index 0000000..0fa2fb3
--- /dev/null
+++ b/continuum-release/src/test/scm/db/revprops/3
@@ -0,0 +1,14 @@
+K 10
+svn:author
+V 4
+deng
+K 8
+svn:date
+V 27
+2010-03-01T10:12:34.122774Z
+K 7
+svn:log
+V 39
+import test project for continuum-1814
+
+END
diff --git a/continuum-release/src/test/scm/db/revprops/4 b/continuum-release/src/test/scm/db/revprops/4
new file mode 100644
index 0000000..067bf22
--- /dev/null
+++ b/continuum-release/src/test/scm/db/revprops/4
@@ -0,0 +1,14 @@
+K 10
+svn:author
+V 4
+deng
+K 8
+svn:date
+V 27
+2010-03-01T10:13:02.056710Z
+K 7
+svn:log
+V 48
+create tags dir for continuum-1814 test project
+
+END
diff --git a/continuum-release/src/test/scm/db/revprops/5 b/continuum-release/src/test/scm/db/revprops/5
new file mode 100644
index 0000000..5a187ea
--- /dev/null
+++ b/continuum-release/src/test/scm/db/revprops/5
@@ -0,0 +1,14 @@
+K 10
+svn:author
+V 4
+deng
+K 8
+svn:date
+V 27
+2010-03-01T10:43:19.644938Z
+K 7
+svn:log
+V 20
+set <name> elements
+
+END
diff --git a/continuum-release/src/test/scm/db/revprops/6 b/continuum-release/src/test/scm/db/revprops/6
new file mode 100755
index 0000000..cb630dc
--- /dev/null
+++ b/continuum-release/src/test/scm/db/revprops/6
@@ -0,0 +1,13 @@
+K 10
+svn:author
+V 6
+marica
+K 8
+svn:date
+V 27
+2011-02-14T23:59:29.491812Z
+K 7
+svn:log
+V 37
+added test project for CONTINUUM-2610
+END
diff --git a/continuum-release/src/test/scm/db/revs/3 b/continuum-release/src/test/scm/db/revs/3
new file mode 100644
index 0000000..d2e29df
--- /dev/null
+++ b/continuum-release/src/test/scm/db/revs/3
Binary files differ
diff --git a/continuum-release/src/test/scm/db/revs/4 b/continuum-release/src/test/scm/db/revs/4
new file mode 100644
index 0000000..37f5847
--- /dev/null
+++ b/continuum-release/src/test/scm/db/revs/4
@@ -0,0 +1,52 @@
+id: h.0.r4/0
+type: dir
+count: 0
+cpath: /continuum-1814/tags
+copyroot: 0 /
+
+PLAIN
+K 4
+tags
+V 12
+dir h.0.r4/0
+K 5
+trunk
+V 15
+dir 6.0.r3/3840
+END
+ENDREP
+id: 5.0.r4/150
+type: dir
+pred: 5.0.r3/4021
+count: 1
+text: 4 75 62 62 0f542496a7d441a9d7a22151515328c8
+cpath: /continuum-1814
+copyroot: 0 /
+
+PLAIN
+K 14
+continuum-1814
+V 14
+dir 5.0.r4/150
+K 4
+tags
+V 14
+dir 2.0.r2/712
+K 5
+trunk
+V 14
+dir 3.0.r2/598
+END
+ENDREP
+id: 0.0.r4/406
+type: dir
+pred: 0.0.r3/4263
+count: 4
+text: 4 290 103 103 6b3929e554925dc771dfde26a278dda6
+cpath: /
+copyroot: 0 /
+
+_0.0.t3-1 add false false /continuum-1814/tags
+
+
+406 535
diff --git a/continuum-release/src/test/scm/db/revs/5 b/continuum-release/src/test/scm/db/revs/5
new file mode 100644
index 0000000..e962319
--- /dev/null
+++ b/continuum-release/src/test/scm/db/revs/5
Binary files differ
diff --git a/continuum-release/src/test/scm/db/revs/6 b/continuum-release/src/test/scm/db/revs/6
new file mode 100755
index 0000000..7e823ac
--- /dev/null
+++ b/continuum-release/src/test/scm/db/revs/6
Binary files differ
diff --git a/continuum-reports/pom.xml b/continuum-reports/pom.xml
index 9b90aa8..7a9401b 100644
--- a/continuum-reports/pom.xml
+++ b/continuum-reports/pom.xml
@@ -1,54 +1,88 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
+  ~ 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.
+  -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
     <artifactId>continuum</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <artifactId>continuum-reports</artifactId>
   <name>Continuum :: Reports</name>
   <dependencies>
     <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-simple</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>jcl-over-slf4j</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
       <groupId>org.apache.continuum</groupId>
       <artifactId>continuum-api</artifactId>
     </dependency>
     <dependency>
       <groupId>org.springframework</groupId>
-      <artifactId>spring-context-support</artifactId>
-    </dependency>     
+      <artifactId>spring-context</artifactId>
+    </dependency>
     <dependency>
       <groupId>javax.annotation</groupId>
       <artifactId>jsr250-api</artifactId>
-    </dependency>       
-    <!-- Not needed for the moment
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-store</artifactId>
     </dependency>
-    -->
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-utils</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-component-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>plexus-spring</artifactId>
+      <scope>test</scope>
+    </dependency>
     <dependency>
       <groupId>org.apache.continuum</groupId>
       <artifactId>continuum-test</artifactId>
       <scope>test</scope>
     </dependency>
   </dependencies>
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.rat</groupId>
+          <artifactId>apache-rat-plugin</artifactId>
+          <configuration>
+            <excludes>
+              <exclude>src/test/resources/continuum-core/**</exclude>
+              <exclude>src/test/resources/**/TEST-*.xml</exclude>
+            </excludes>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
 </project>
diff --git a/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/DefaultReportTestSuiteGenerator.java b/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/DefaultReportTestSuiteGenerator.java
index 21b3f64..d30544c 100644
--- a/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/DefaultReportTestSuiteGenerator.java
+++ b/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/DefaultReportTestSuiteGenerator.java
@@ -1,3 +1,5 @@
+package org.apache.maven.continuum.reports.surefire;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,7 +18,6 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.continuum.reports.surefire;
 
 import org.apache.maven.continuum.configuration.ConfigurationException;
 import org.apache.maven.continuum.configuration.ConfigurationService;
@@ -26,21 +27,21 @@
 import org.springframework.stereotype.Service;
 import org.xml.sax.SAXException;
 
-import javax.annotation.Resource;
-import javax.xml.parsers.ParserConfigurationException;
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
+import javax.annotation.Resource;
+import javax.xml.parsers.ParserConfigurationException;
 
 /**
  * @author <a href="mailto:olamy@apache.org">olamy</a>
  * @version $Id$
  * @since 12 nov. 07
  */
-@Service("reportTestSuiteGenerator")
+@Service( "reportTestSuiteGenerator" )
 public class DefaultReportTestSuiteGenerator
     implements ReportTestSuiteGenerator, Initializable
 {
diff --git a/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportFailure.java b/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportFailure.java
index 132b72c..5b99293 100644
--- a/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportFailure.java
+++ b/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportFailure.java
@@ -1,3 +1,5 @@
+package org.apache.maven.continuum.reports.surefire;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,19 +18,18 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.continuum.reports.surefire;
 
 /**
  * @author <a href="mailto:olamy@apache.org">olamy</a>
- * @since 13 nov. 07
  * @version $Id$
+ * @since 13 nov. 07
  */
 public class ReportFailure
 {
     private String type;
 
     private String exception;
-    
+
     private String testName;
 
     public ReportFailure( String type, String exception, String testName )
@@ -57,7 +58,7 @@
     {
         this.exception = exception;
     }
-    
+
     public String getTestName()
     {
         return testName;
@@ -66,5 +67,5 @@
     public void setTestName( String testName )
     {
         this.testName = testName;
-    }    
+    }
 }
diff --git a/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportTest.java b/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportTest.java
index bbb7c27..78ac016 100644
--- a/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportTest.java
+++ b/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportTest.java
@@ -1,3 +1,5 @@
+package org.apache.maven.continuum.reports.surefire;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,15 +18,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.continuum.reports.surefire;
 
 import java.util.ArrayList;
 import java.util.List;
 
 /**
  * @author <a href="mailto:olamy@apache.org">olamy</a>
- * @since 12 nov. 07
  * @version $Id$
+ * @since 12 nov. 07
  */
 public class ReportTest
 {
diff --git a/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportTestCase.java b/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportTestCase.java
index 6d982e0..24b9cec 100644
--- a/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportTestCase.java
+++ b/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportTestCase.java
@@ -1,3 +1,5 @@
+package org.apache.maven.continuum.reports.surefire;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,13 +18,13 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.continuum.reports.surefire;
 
 /**
  * Taken from maven-surefire-report-plugin
+ *
  * @author <a href="mailto:olamy@apache.org">olamy</a>
- * @since 12 nov. 07
  * @version $Id$
+ * @since 12 nov. 07
  */
 public class ReportTestCase
 {
diff --git a/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportTestResult.java b/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportTestResult.java
index 0206877..58d61e8 100644
--- a/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportTestResult.java
+++ b/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportTestResult.java
@@ -1,3 +1,5 @@
+package org.apache.maven.continuum.reports.surefire;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,7 +18,6 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.continuum.reports.surefire;
 
 import java.util.LinkedList;
 import java.util.List;
diff --git a/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportTestSuite.java b/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportTestSuite.java
index 9b08dfc..0f5bba7 100644
--- a/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportTestSuite.java
+++ b/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportTestSuite.java
@@ -1,3 +1,4 @@
+package org.apache.maven.continuum.reports.surefire;
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,15 +17,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.continuum.reports.surefire;
 
 import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
 import org.xml.sax.helpers.DefaultHandler;
 
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
 import java.io.File;
 import java.io.IOException;
 import java.text.NumberFormat;
@@ -32,6 +29,9 @@
 import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
 
 /**
  * @author <a href="mailto:olamy@apache.org">olamy</a>
@@ -57,7 +57,7 @@
 
     private float timeElapsed;
 
-    private NumberFormat numberFormat = NumberFormat.getInstance();
+    private final NumberFormat numberFormat = NumberFormat.getInstance();
 
     /**
      * @noinspection StringBufferField
@@ -139,7 +139,7 @@
 
                 String timeAsString = attributes.getValue( "time" );
 
-                Number time = new Integer( 0 );
+                Number time = 0;
 
                 if ( timeAsString != null )
                 {
@@ -177,14 +177,14 @@
         else if ( "failure".equals( qName ) )
         {
             testCase.setFailureDetails( currentElement.toString() );
-            this.addReportFailure(
-                new ReportFailure( testCase.getFailureType(), testCase.getFailureDetails(), testCase.getName() ) );
+            this.addReportFailure( new ReportFailure( testCase.getFailureType(), testCase.getFailureDetails(),
+                                                      testCase.getName() ) );
         }
         else if ( "error".equals( qName ) )
         {
             testCase.setFailureDetails( currentElement.toString() );
-            this.addReportFailure(
-                new ReportFailure( testCase.getFailureType(), testCase.getFailureDetails(), testCase.getName() ) );
+            this.addReportFailure( new ReportFailure( testCase.getFailureType(), testCase.getFailureDetails(),
+                                                      testCase.getName() ) );
         }
     }
 
@@ -307,7 +307,7 @@
         this.testCases = Collections.unmodifiableList( testCases );
     }
 
-    @SuppressWarnings("unchecked")
+    @SuppressWarnings( "unchecked" )
     public List<ReportFailure> getReportFailures()
     {
         return reportFailures == null ? Collections.EMPTY_LIST : reportFailures;
diff --git a/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportTestSuiteGenerator.java b/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportTestSuiteGenerator.java
index a3f2b22..d7da76b 100644
--- a/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportTestSuiteGenerator.java
+++ b/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportTestSuiteGenerator.java
@@ -1,3 +1,5 @@
+package org.apache.maven.continuum.reports.surefire;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,52 +18,56 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.continuum.reports.surefire;
 
 import java.io.File;
 import java.util.List;
 
 /**
  * @author <a href="mailto:olamy@apache.org">olamy</a>
- * @since 12 nov. 07
  * @version $Id$
+ * @since 12 nov. 07
  */
 public interface ReportTestSuiteGenerator
 {
 
     /**
      * @param directory directory containing surefire tests files
-     * @param includes file types to include
-     * @param excludes file types to exclude
+     * @param includes  file types to include
+     * @param excludes  file types to exclude
      * @return List of {@link ReportTestSuite}
      * @throws ReportTestSuiteGeneratorException
+     *
      */
     List<ReportTestSuite> generateReports( File directory, List<String> includes, List<String> excludes )
         throws ReportTestSuiteGeneratorException;
-    
+
     /**
      * Use generateReports with default includes *.xml and default excludes *.txt
+     *
      * @param directory directory containing surefire tests files
      * @return List of {@link ReportTestSuite}
      * @throws ReportTestSuiteGeneratorException
+     *
      */
     List<ReportTestSuite> generateReports( File directory )
-        throws ReportTestSuiteGeneratorException;  
-    
+        throws ReportTestSuiteGeneratorException;
+
     /**
      * @param buildId
      * @param projectId
      * @return List of {@link ReportTestSuite}
      * @throws ReportTestSuiteGeneratorException
+     *
      */
     List<ReportTestSuite> generateReports( int buildId, int projectId )
         throws ReportTestSuiteGeneratorException;
-    
+
     /**
      * @param buildId
      * @param projectId
-     * @return List of {@link TestResult}
+     * @return List of {@link ReportTestResult}
      * @throws ReportTestSuiteGeneratorException
+     *
      */
     ReportTestResult generateReportTestResult( int buildId, int projectId )
         throws ReportTestSuiteGeneratorException;
diff --git a/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportTestSuiteGeneratorException.java b/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportTestSuiteGeneratorException.java
index 8f10236..7fa85b7 100644
--- a/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportTestSuiteGeneratorException.java
+++ b/continuum-reports/src/main/java/org/apache/maven/continuum/reports/surefire/ReportTestSuiteGeneratorException.java
@@ -1,3 +1,5 @@
+package org.apache.maven.continuum.reports.surefire;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,19 +18,18 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.continuum.reports.surefire;
 
 /**
  * @author <a href="mailto:olamy@apache.org">olamy</a>
- * @since 12 nov. 07
  * @version $Id$
+ * @since 12 nov. 07
  */
 public class ReportTestSuiteGeneratorException
     extends Exception
 {
 
     /**
-     * 
+     *
      */
     public ReportTestSuiteGeneratorException()
     {
diff --git a/continuum-reports/src/main/resources/META-INF/spring-context.xml b/continuum-reports/src/main/resources/META-INF/spring-context.xml
index 99c0fbc..565a1ee 100644
--- a/continuum-reports/src/main/resources/META-INF/spring-context.xml
+++ b/continuum-reports/src/main/resources/META-INF/spring-context.xml
@@ -18,6 +18,7 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
   -->
+
 <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
@@ -26,7 +27,7 @@
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-2.5.xsd">
 
-  <context:annotation-config />
-  <context:component-scan 
-    base-package="org.apache.maven.continuum.reports.surefire"/>  
+  <context:annotation-config/>
+  <context:component-scan
+      base-package="org.apache.maven.continuum.reports.surefire"/>
 </beans>
\ No newline at end of file
diff --git a/continuum-reports/src/test/java/org/apache/maven/continuum/reports/surefire/ConfigurationServiceMock.java b/continuum-reports/src/test/java/org/apache/maven/continuum/reports/surefire/ConfigurationServiceMock.java
index a5dbf0a..6620c97 100644
--- a/continuum-reports/src/test/java/org/apache/maven/continuum/reports/surefire/ConfigurationServiceMock.java
+++ b/continuum-reports/src/test/java/org/apache/maven/continuum/reports/surefire/ConfigurationServiceMock.java
@@ -1,9 +1,28 @@
 package org.apache.maven.continuum.reports.surefire;
 
-import java.io.File;
+/*
+ * 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 org.apache.maven.continuum.configuration.ConfigurationException;
 
+import java.io.File;
+
 public class ConfigurationServiceMock
     extends org.apache.maven.continuum.configuration.ConfigurationServiceMock
 {
@@ -11,6 +30,6 @@
         throws ConfigurationException
     {
         return new File( "src" + File.separatorChar + "test" + File.separatorChar + "resources" + File.separatorChar +
-            "continuum-core" );
+                             "continuum-core" );
     }
 }
diff --git a/continuum-reports/src/test/java/org/apache/maven/continuum/reports/surefire/DefaultReportTestSuiteGeneratorTest.java b/continuum-reports/src/test/java/org/apache/maven/continuum/reports/surefire/DefaultReportTestSuiteGeneratorTest.java
index 4848ff3..80121e4 100644
--- a/continuum-reports/src/test/java/org/apache/maven/continuum/reports/surefire/DefaultReportTestSuiteGeneratorTest.java
+++ b/continuum-reports/src/test/java/org/apache/maven/continuum/reports/surefire/DefaultReportTestSuiteGeneratorTest.java
@@ -1,3 +1,5 @@
+package org.apache.maven.continuum.reports.surefire;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,7 +18,6 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.continuum.reports.surefire;
 
 import org.codehaus.plexus.spring.PlexusInSpringTestCase;
 
@@ -35,7 +36,7 @@
     private File getReportsDirectory( String pathDir )
     {
         return new File( getBasedir() + File.separatorChar + "src" + File.separatorChar + "test" + File.separatorChar +
-            "resources" + File.separatorChar + pathDir );
+                             "resources" + File.separatorChar + pathDir );
     }
 
     public void testSimpleFile()
@@ -43,8 +44,8 @@
     {
         File testDirectory = getReportsDirectory( "simplereport" );
 
-        ReportTestSuiteGenerator generator =
-            (ReportTestSuiteGenerator) lookup( ReportTestSuiteGenerator.class, "default" );
+        ReportTestSuiteGenerator generator = (ReportTestSuiteGenerator) lookup( ReportTestSuiteGenerator.class,
+                                                                                "default" );
 
         List<ReportTestSuite> reports = generator.generateReports( testDirectory );
         assertEquals( 1, reports.size() );
@@ -59,16 +60,16 @@
     public void testContinuumCore()
         throws Exception
     {
-        ReportTestSuiteGenerator generator =
-            (ReportTestSuiteGenerator) lookup( ReportTestSuiteGenerator.class, "default" );
+        ReportTestSuiteGenerator generator = (ReportTestSuiteGenerator) lookup( ReportTestSuiteGenerator.class,
+                                                                                "default" );
         List<ReportTestSuite> reports = generator.generateReports( 1, 1 );
 
         assertEquals( 18, reports.size() );
 
         for ( ReportTestSuite report : reports )
         {
-            if ( report.getName().equals( "MailContinuumNotifierTest" ) &&
-                report.getPackageName().equals( "org.apache.maven.continuum.notification.mail" ) )
+            if ( report.getName().equals( "MailContinuumNotifierTest" ) && report.getPackageName().equals(
+                "org.apache.maven.continuum.notification.mail" ) )
             {
                 assertEquals( 1, report.getNumberOfFailures() );
                 // don't test this because can plate forme dependant
@@ -92,8 +93,8 @@
     public void testgenerateReportTestResult()
         throws Exception
     {
-        ReportTestSuiteGenerator generator =
-            (ReportTestSuiteGenerator) lookup( ReportTestSuiteGenerator.class, "default" );
+        ReportTestSuiteGenerator generator = (ReportTestSuiteGenerator) lookup( ReportTestSuiteGenerator.class,
+                                                                                "default" );
         ReportTestResult reportTestResult = generator.generateReportTestResult( 1, 1 );
         assertEquals( 18, reportTestResult.getSuiteResults().size() );
         assertEquals( 1, reportTestResult.getFailureCount() );
diff --git a/continuum-reports/src/test/resources/log4j.xml b/continuum-reports/src/test/resources/log4j.xml
deleted file mode 100644
index fabe3f9..0000000
--- a/continuum-reports/src/test/resources/log4j.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
-<!-- ===================================================================== -->
-<!-- Log4j Configuration -->
-<!-- ===================================================================== -->
-
-<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
-  debug="false">
-
-  <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
-    <param name="Target" value="System.out"/>
-    <layout class="org.apache.log4j.PatternLayout">
-      <param name="ConversionPattern" value="%d %-5p [%c{1}.%M](%L) %m%n"/>
-    </layout>
-  </appender>
-
-  <!-- quiet spring loading :-) -->
-  <category name="org.springframework">
-    <priority value="INFO"/>
-  </category>
-  <category name="org.codehaus.plexus">
-    <priority value="ERROR"/>
-  </category>
-  <category name="org.apache.continuum.configuration">
-    <priority value="DEBUG"/>
-  </category>
-
-  <category name="org.apache.commons.configuration">
-    <priority value="ERROR"/>
-  </category>
-
-  <!-- JPOX -->
-  <category name="JPOX">
-    <priority value="WARN"/>
-  </category>
-  <category name="JPOX.RDBMS">
-    <priority value="ERROR"/>
-  </category>
-
-  <root>
-    <priority value="INFO"/>
-    <appender-ref ref="CONSOLE"/>
-  </root>
-
-</log4j:configuration>
diff --git a/continuum-security/pom.xml b/continuum-security/pom.xml
index a3b8f92..a338b34 100644
--- a/continuum-security/pom.xml
+++ b/continuum-security/pom.xml
@@ -1,30 +1,30 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
+  ~ 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.
+  -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <artifactId>continuum</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>continuum-security</artifactId>
   <name>Continuum :: Security</name>
-  <packaging>jar</packaging>
 </project>
diff --git a/continuum-security/src/main/java/org/apache/maven/continuum/security/ContinuumRoleConstants.java b/continuum-security/src/main/java/org/apache/maven/continuum/security/ContinuumRoleConstants.java
index 6d133bd..964f7c7 100644
--- a/continuum-security/src/main/java/org/apache/maven/continuum/security/ContinuumRoleConstants.java
+++ b/continuum-security/src/main/java/org/apache/maven/continuum/security/ContinuumRoleConstants.java
@@ -21,8 +21,8 @@
 /**
  * ContinuumRoleConstants:
  *
- * @author: Jesse McConnell <jmcconnell@apache.org>
- * @version: $Id$
+ * @author Jesse McConnell <jmcconnell@apache.org>
+ * @version $Id$
  */
 public class ContinuumRoleConstants
 {
@@ -109,18 +109,24 @@
     public static final String USER_MANAGEMENT_USER_ROLE_OPERATION = "user-management-user-role";
 
     public static final String CONTINUUM_MANAGE_INSTALLATIONS = "continuum-manage-installations";
-    
+
     public static final String CONTINUUM_MANAGE_PROFILES = "continuum-manage-profiles";
-    
+
     public static final String CONTINUUM_MANAGE_BUILD_TEMPLATES = "continuum-manage-build-templates";
-    
+
     public static final String CONTINUUM_MANAGE_QUEUES = "continuum-manage-queues";
-    
+
     public static final String CONTINUUM_VIEW_QUEUES = "continuum-view-queues";
-    
+
     public static final String CONTINUUM_MANAGE_REPOSITORIES = "continuum-manage-repositories";
-    
+
     public static final String CONTINUUM_MANAGE_PURGING = "continuum-manage-purging";
 
     public static final String CONTINUUM_MANAGE_DISTRIBUTED_BUILDS = "continuum-manage-distributed-builds";
+
+    public static final String CONTINUUM_VIEW_RELEASE = "continuum-view-release";
+
+    public static final String CONTINUUM_MANAGE_PARALLEL_BUILDS = "continuum-manage-parallel-builds";
+
+    public static final String CONTINUUM_VIEW_REPORT = "continuum-view-report";
 }
diff --git a/continuum-security/src/main/resources/META-INF/redback/redback.xml b/continuum-security/src/main/resources/META-INF/redback/redback.xml
index 0865181..cabb04b 100644
--- a/continuum-security/src/main/resources/META-INF/redback/redback.xml
+++ b/continuum-security/src/main/resources/META-INF/redback/redback.xml
@@ -18,6 +18,7 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
   -->
+
 <redback-role-model>
   <modelVersion>1.0.0</modelVersion>
   <applications>
@@ -29,7 +30,7 @@
           <id>continuum-manage-queues</id>
           <name>continuum-manage-queues</name>
           <description>Manage Continuum Queues</description>
-        </operation>    
+        </operation>
         <operation>
           <id>continuum-view-queues</id>
           <name>continuum-view-queues</name>
@@ -39,7 +40,7 @@
           <id>continuum-manage-build-templates</id>
           <name>continuum-manage-build-templates</name>
           <description>Manage Continuum Build Definition Templates</description>
-        </operation>    
+        </operation>
         <operation>
           <id>continuum-manage-schedules</id>
           <name>continuum-manage-schedules</name>
@@ -174,7 +175,7 @@
           <id>continuum-manage-profiles</id>
           <name>continuum-manage-profiles</name>
           <description>Continuum Manage Installations</description>
-        </operation>        
+        </operation>
         <operation>
           <id>continuum-manage-repositories</id>
           <name>continuum-manage-repositories</name>
@@ -190,6 +191,21 @@
           <name>continuum-manage-distributed-builds</name>
           <description>Continuum Manage Distributed Builds</description>
         </operation>
+        <operation>
+          <id>continuum-view-release</id>
+          <name>continuum-view-release</name>
+          <description>Continuum View Release</description>
+        </operation>
+        <operation>
+          <id>continuum-manage-parallel-builds</id>
+          <name>continuum-manage-parallel-builds</name>
+          <description>Continuum Manage Parallel Builds</description>
+        </operation>
+        <operation>
+          <id>continuum-view-report</id>
+          <name>continuum-view-report</name>
+          <description>Continuum View Report</description>
+        </operation>
       </operations>
       <roles>
         <role>
@@ -212,6 +228,20 @@
               <operation>continuum-manage-distributed-builds</operation>
               <resource>global</resource>
             </permission>
+            <permission>
+              <id>continuum-view-release</id>
+              <name>Continuum View Release</name>
+              <permanent>true</permanent>
+              <operation>continuum-view-release</operation>
+              <resource>global</resource>
+            </permission>
+            <permission>
+              <id>continuum-manage-parallel-builds</id>
+              <name>Manage Continuum Parallel Builds</name>
+              <permanent>true</permanent>
+              <operation>continuum-manage-parallel-builds</operation>
+              <resource>global</resource>
+            </permission>
           </permissions>
           <parentRoles>
             <parentRole>system-administrator</parentRole>
@@ -239,7 +269,7 @@
               <permanent>true</permanent>
               <operation>continuum-manage-users</operation>
               <resource>global</resource>
-            </permission>        
+            </permission>
           </permissions>
           <parentRoles>
             <parentRole>user-administrator</parentRole>
@@ -257,14 +287,14 @@
               <permanent>true</permanent>
               <operation>continuum-add-group</operation>
               <resource>global</resource>
-            </permission> 
+            </permission>
             <permission>
               <id>continuum-manage-schedules</id>
               <name>Manage Continuum Schedules</name>
               <permanent>true</permanent>
               <operation>continuum-manage-schedules</operation>
               <resource>global</resource>
-            </permission>        
+            </permission>
           </permissions>
           <childRoles>
             <childRole>continuum-group-project-developer</childRole>
@@ -315,7 +345,7 @@
               <permanent>true</permanent>
               <operation>continuum-manage-installations</operation>
               <resource>global</resource>
-            </permission>        
+            </permission>
           </permissions>
         </role>
         <role>
@@ -330,9 +360,9 @@
               <permanent>true</permanent>
               <operation>continuum-manage-profiles</operation>
               <resource>global</resource>
-            </permission>        
+            </permission>
           </permissions>
-        </role> 
+        </role>
         <role>
           <id>continuum-manage-schedules</id>
           <name>Continuum Manage Scheduling</name>
@@ -341,12 +371,12 @@
           <permissions>
             <permission>
               <id>continuum-manage-schedules</id>
-              <name>Continuum Manage Scheduling</name>  
+              <name>Continuum Manage Scheduling</name>
               <permanent>true</permanent>
               <operation>continuum-manage-schedules</operation>
               <resource>global</resource>
             </permission>
-          </permissions>		
+          </permissions>
         </role>
         <role>
           <id>continuum-manage-build-templates</id>
@@ -360,9 +390,9 @@
               <permanent>true</permanent>
               <operation>continuum-manage-build-templates</operation>
               <resource>global</resource>
-            </permission>  
+            </permission>
           </permissions>
-        </role>    
+        </role>
         <role>
           <id>continuum-manage-queues</id>
           <name>Continuum Manage Queues</name>
@@ -384,10 +414,10 @@
               <resource>global</resource>
             </permission>
           </permissions>
-        </role>   
+        </role>
         <role>
           <id>continuum-manage-repositories</id>
-          <name>continuum-manage-repositories</name>
+          <name>Continuum Manage Local Repositories</name>
           <assignable>true</assignable>
           <permanent>true</permanent>
           <permissions>
@@ -402,7 +432,7 @@
         </role>
         <role>
           <id>continuum-manage-purging</id>
-          <name>continuum-manage-purging</name>
+          <name>Continuum Manage Purging</name>
           <assignable>true</assignable>
           <permanent>true</permanent>
           <permissions>
@@ -415,6 +445,21 @@
             </permission>
           </permissions>
         </role>
+        <role>
+          <id>continuum-manage-distributed-builds</id>
+          <name>Continuum Manage Distributed Builds</name>
+          <assignable>true</assignable>
+          <permanent>true</permanent>
+          <permissions>
+            <permission>
+              <id>continuum-manage-distributed-builds</id>
+              <name>Manage Continuum Distributed Builds</name>
+              <permanent>true</permanent>
+              <operation>continuum-manage-distributed-builds</operation>
+              <resource>global</resource>
+            </permission>
+          </permissions>
+        </role>
       </roles>
       <templates>
         <template>
@@ -592,7 +637,13 @@
               <operation>continuum-view-queues</operation>
               <resource>global</resource>
             </permission>
-          </permissions>  	  
+            <permission>
+              <id>continuum-view-report</id>
+              <name>Continuum View Report</name>
+              <operation>continuum-view-report</operation>
+              <resource>global</resource>
+            </permission>
+          </permissions>
           <parentRoles>
             <parentRole>continuum-group-project-user</parentRole>
           </parentRoles>
@@ -601,4 +652,3 @@
     </application>
   </applications>
 </redback-role-model>
-
diff --git a/continuum-store/pom.xml b/continuum-store/pom.xml
index 72755cf..5d216c4 100644
--- a/continuum-store/pom.xml
+++ b/continuum-store/pom.xml
@@ -1,36 +1,50 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
+  ~ 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.
+  -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <artifactId>continuum</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>continuum-store</artifactId>
   <name>Continuum :: Store</name>
   <dependencies>
     <dependency>
+      <groupId>javax.jdo</groupId>
+      <artifactId>jdo2-api</artifactId>
+    </dependency>
+    <dependency>
       <groupId>javax.annotation</groupId>
       <artifactId>jsr250-api</artifactId>
-    </dependency>    
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-context</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>plexus-spring</artifactId>
+      <scope>test</scope>
+    </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-jdo2</artifactId>
@@ -39,6 +53,7 @@
     <dependency>
       <groupId>org.apache.bcel</groupId>
       <artifactId>bcel</artifactId>
+      <scope>runtime</scope>
     </dependency>
     <dependency>
       <groupId>org.apache.continuum</groupId>
@@ -67,10 +82,15 @@
       <artifactId>slf4j-api</artifactId>
     </dependency>
     <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-slf4j-logging</artifactId>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-simple</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>jcl-over-slf4j</artifactId>
+      <scope>runtime</scope>
+    </dependency>
   </dependencies>
   <build>
     <plugins>
@@ -85,6 +105,17 @@
           </execution>
         </executions>
       </plugin>
+      <plugin>
+        <groupId>org.codehaus.plexus</groupId>
+        <artifactId>plexus-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <goals>
+              <goal>descriptor</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
     </plugins>
   </build>
 </project>
diff --git a/continuum-store/src/main/java/org/apache/continuum/dao/AbstractDao.java b/continuum-store/src/main/java/org/apache/continuum/dao/AbstractDao.java
index ec36f7c..31eb5ce 100644
--- a/continuum-store/src/main/java/org/apache/continuum/dao/AbstractDao.java
+++ b/continuum-store/src/main/java/org/apache/continuum/dao/AbstractDao.java
@@ -25,12 +25,12 @@
 import org.codehaus.plexus.jdo.PlexusObjectNotFoundException;
 import org.codehaus.plexus.jdo.PlexusStoreException;
 
+import java.util.List;
 import javax.annotation.Resource;
 import javax.jdo.FetchPlan;
 import javax.jdo.PersistenceManager;
 import javax.jdo.PersistenceManagerFactory;
 import javax.jdo.Transaction;
-import java.util.List;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
@@ -58,8 +58,9 @@
 
     protected static final String BUILD_TEMPLATE_BUILD_DEFINITIONS = "build-template-build-definitions";
 
-    protected static final String PROJECT_WITH_SCM_DETAILS_FETCH_GROUP = "project-with-scm-details";
-
+    /**
+     * @plexus.requirement
+     */
     @Resource
     private StoreUtilities storeUtilities;
 
diff --git a/continuum-store/src/main/java/org/apache/continuum/dao/BuildDefinitionDaoImpl.java b/continuum-store/src/main/java/org/apache/continuum/dao/BuildDefinitionDaoImpl.java
index 62a32f7..0fd0305 100644
--- a/continuum-store/src/main/java/org/apache/continuum/dao/BuildDefinitionDaoImpl.java
+++ b/continuum-store/src/main/java/org/apache/continuum/dao/BuildDefinitionDaoImpl.java
@@ -30,31 +30,38 @@
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Repository;
 
-import javax.annotation.Resource;
-import javax.jdo.Extent;
-import javax.jdo.PersistenceManager;
-import javax.jdo.Query;
-import javax.jdo.Transaction;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import javax.annotation.Resource;
+import javax.jdo.Extent;
+import javax.jdo.PersistenceManager;
+import javax.jdo.Query;
+import javax.jdo.Transaction;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
  * @version $Id$
+ * @plexus.component role="org.apache.continuum.dao.BuildDefinitionDao"
  */
-@Repository("buildDefinitionDao")
+@Repository( "buildDefinitionDao" )
 public class BuildDefinitionDaoImpl
     extends AbstractDao
     implements BuildDefinitionDao
 {
-    private Logger log = LoggerFactory.getLogger( BuildDefinitionDaoImpl.class );
+    private static final Logger log = LoggerFactory.getLogger( BuildDefinitionDaoImpl.class );
 
+    /**
+     * @plexus.requirement role="org.apache.continuum.dao.ProjectDao"
+     */
     @Resource
     private ProjectDao projectDao;
 
+    /**
+     * @plexus.requirement role="org.apache.continuum.dao.ProjectGroupDao"
+     */
     @Resource
     private ProjectGroupDao projectGroupDao;
 
@@ -346,7 +353,7 @@
 
             query.setFilter( "this.schedule.id == scheduleId" );
 
-            List result = (List) query.execute( new Integer( scheduleId ) );
+            List result = (List) query.execute( scheduleId );
 
             return result == null ? Collections.EMPTY_LIST : (List) pm.detachCopyAll( result );
         }
diff --git a/continuum-store/src/main/java/org/apache/continuum/dao/BuildDefinitionTemplateDaoImpl.java b/continuum-store/src/main/java/org/apache/continuum/dao/BuildDefinitionTemplateDaoImpl.java
index 241024b..f892172 100644
--- a/continuum-store/src/main/java/org/apache/continuum/dao/BuildDefinitionTemplateDaoImpl.java
+++ b/continuum-store/src/main/java/org/apache/continuum/dao/BuildDefinitionTemplateDaoImpl.java
@@ -23,18 +23,19 @@
 import org.apache.maven.continuum.store.ContinuumStoreException;
 import org.springframework.stereotype.Repository;
 
+import java.util.Collections;
+import java.util.List;
 import javax.jdo.Extent;
 import javax.jdo.PersistenceManager;
 import javax.jdo.Query;
 import javax.jdo.Transaction;
-import java.util.Collections;
-import java.util.List;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
  * @version $Id$
+ * @plexus.component role="org.apache.continuum.dao.BuildDefinitionTemplateDao"
  */
-@Repository("buildDefinitionTemplateDao")
+@Repository( "buildDefinitionTemplateDao" )
 public class BuildDefinitionTemplateDaoImpl
     extends AbstractDao
     implements BuildDefinitionTemplateDao
diff --git a/continuum-store/src/main/java/org/apache/continuum/dao/BuildQueueDaoImpl.java b/continuum-store/src/main/java/org/apache/continuum/dao/BuildQueueDaoImpl.java
new file mode 100644
index 0000000..db4dfbc
--- /dev/null
+++ b/continuum-store/src/main/java/org/apache/continuum/dao/BuildQueueDaoImpl.java
@@ -0,0 +1,141 @@
+package org.apache.continuum.dao;
+
+/*
+ * 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 org.apache.maven.continuum.model.project.BuildQueue;
+import org.apache.maven.continuum.store.ContinuumStoreException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Repository;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import javax.jdo.Extent;
+import javax.jdo.PersistenceManager;
+import javax.jdo.Query;
+import javax.jdo.Transaction;
+
+/**
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ * @plexus.component role="org.apache.continuum.dao.BuildQueueDao"
+ */
+@Repository( "buildQueueDao" )
+public class BuildQueueDaoImpl
+    extends AbstractDao
+    implements BuildQueueDao
+{
+    private static Logger log = LoggerFactory.getLogger( BuildQueueDaoImpl.class );
+
+    public BuildQueue addBuildQueue( BuildQueue buildQueue )
+        throws ContinuumStoreException
+    {
+        return (BuildQueue) addObject( buildQueue );
+    }
+
+    public List<BuildQueue> getAllBuildQueues()
+        throws ContinuumStoreException
+    {
+        PersistenceManager pm = getPersistenceManager();
+
+        Transaction tx = pm.currentTransaction();
+
+        try
+        {
+            tx.begin();
+
+            Extent extent = pm.getExtent( BuildQueue.class, true );
+
+            Query query = pm.newQuery( extent );
+
+            List result = (List) query.execute();
+
+            return result == null ? Collections.EMPTY_LIST : (List<BuildQueue>) pm.detachCopyAll( result );
+        }
+        finally
+        {
+            tx.commit();
+
+            rollback( tx );
+        }
+    }
+
+    public BuildQueue getBuildQueue( int buildQueueId )
+        throws ContinuumStoreException
+    {
+        return (BuildQueue) getObjectById( BuildQueue.class, buildQueueId );
+    }
+
+    public BuildQueue getBuildQueueByName( String name )
+        throws ContinuumStoreException
+    {
+        PersistenceManager pm = getPersistenceManager();
+
+        Transaction tx = pm.currentTransaction();
+
+        try
+        {
+            tx.begin();
+
+            Extent extent = pm.getExtent( BuildQueue.class, true );
+
+            Query query = pm.newQuery( extent );
+
+            query.declareImports( "import java.lang.String" );
+
+            query.declareParameters( "String name" );
+
+            query.setFilter( "this.name == name" );
+
+            Collection result = (Collection) query.execute( name );
+
+            if ( result.size() == 0 )
+            {
+                tx.commit();
+
+                return null;
+            }
+
+            Object object = pm.detachCopy( result.iterator().next() );
+
+            tx.commit();
+
+            return (BuildQueue) object;
+        }
+        finally
+        {
+            rollback( tx );
+        }
+    }
+
+    public void removeBuildQueue( BuildQueue buildQueue )
+        throws ContinuumStoreException
+    {
+        removeObject( buildQueue );
+    }
+
+    public BuildQueue storeBuildQueue( BuildQueue buildQueue )
+        throws ContinuumStoreException
+    {
+        updateObject( buildQueue );
+
+        return buildQueue;
+    }
+}
diff --git a/continuum-store/src/main/java/org/apache/continuum/dao/BuildResultDaoImpl.java b/continuum-store/src/main/java/org/apache/continuum/dao/BuildResultDaoImpl.java
index 72e6370..d203cba 100644
--- a/continuum-store/src/main/java/org/apache/continuum/dao/BuildResultDaoImpl.java
+++ b/continuum-store/src/main/java/org/apache/continuum/dao/BuildResultDaoImpl.java
@@ -25,21 +25,23 @@
 import org.apache.maven.continuum.store.ContinuumStoreException;
 import org.springframework.stereotype.Repository;
 
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import javax.jdo.Extent;
 import javax.jdo.JDOHelper;
 import javax.jdo.PersistenceManager;
 import javax.jdo.Query;
 import javax.jdo.Transaction;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
  * @version $Id$
+ * @plexus.component role="org.apache.continuum.dao.BuildResultDao"
  */
-@Repository("buildResultDao")
+@Repository( "buildResultDao" )
 public class BuildResultDaoImpl
     extends AbstractDao
     implements BuildResultDao
@@ -70,6 +72,7 @@
 
             project.setState( build.getState() );
 
+            //TODO: Use projectDao
             pm.makePersistent( project );
 
             tx.commit();
@@ -141,7 +144,45 @@
 
             if ( result != null && !result.isEmpty() )
             {
-                return (BuildResult) result.get( 0 );
+                return result.get( 0 );
+            }
+        }
+        finally
+        {
+            rollback( tx );
+        }
+        return null;
+    }
+
+    public BuildResult getLatestBuildResultForProjectWithDetails( int projectId )
+    {
+        PersistenceManager pm = getPersistenceManager();
+
+        Transaction tx = pm.currentTransaction();
+
+        try
+        {
+            tx.begin();
+
+            pm.getFetchPlan().addGroup( BUILD_RESULT_WITH_DETAILS_FETCH_GROUP );
+
+            Extent extent = pm.getExtent( BuildResult.class, true );
+
+            Query query = pm.newQuery( extent );
+
+            query.declareParameters( "int projectId" );
+
+            query.setFilter( "this.project.id == projectId && this.project.latestBuildId == this.id" );
+
+            List<BuildResult> result = (List<BuildResult>) query.execute( projectId );
+
+            result = (List<BuildResult>) pm.detachCopyAll( result );
+
+            tx.commit();
+
+            if ( result != null && !result.isEmpty() )
+            {
+                return result.get( 0 );
             }
         }
         finally
@@ -182,7 +223,7 @@
 
             if ( result != null && !result.isEmpty() )
             {
-                return (BuildResult) result.get( 0 );
+                return result.get( 0 );
             }
         }
         finally
@@ -250,11 +291,6 @@
         return null;
     }
 
-    public Map<Integer, BuildResult> getLatestBuildResults()
-    {
-        return getLatestBuildResultsByProjectGroupId( -1 );
-    }
-
     public void removeBuildResult( BuildResult buildResult )
     {
         removeObject( buildResult );
@@ -271,15 +307,15 @@
             tx.begin();
 
             Query query = pm.newQuery( "SELECT FROM " + BuildResult.class.getName() +
-                " WHERE project.id == projectId PARAMETERS int projectId ORDER BY endTime DESC" );
+                                           " WHERE project.id == projectId PARAMETERS int projectId ORDER BY endTime DESC" );
 
             query.declareImports( "import java.lang.Integer" );
 
             query.declareParameters( "Integer projectId" );
 
-            List result = (List) query.execute( projectId );
+            List<BuildResult> result = (List<BuildResult>) query.execute( projectId );
 
-            result = (List) pm.detachCopyAll( result );
+            result = (List<BuildResult>) pm.detachCopyAll( result );
 
             tx.commit();
 
@@ -315,9 +351,9 @@
 
             query.setFilter( "this.project.id == projectId && this.buildNumber == buildNumber" );
 
-            List result = (List) query.execute( projectId, buildNumber );
+            List<BuildResult> result = (List<BuildResult>) query.execute( projectId, buildNumber );
 
-            result = (List) pm.detachCopyAll( result );
+            result = (List<BuildResult>) pm.detachCopyAll( result );
 
             tx.commit();
 
@@ -402,9 +438,93 @@
         }
     }
 
+    public long getNbBuildResultsInSuccessForProject( int projectId, long fromDate )
+    {
+        PersistenceManager pm = getPersistenceManager();
+
+        Transaction tx = pm.currentTransaction();
+
+        try
+        {
+            tx.begin();
+
+            Extent extent = pm.getExtent( BuildResult.class, true );
+
+            Query query = pm.newQuery( extent );
+
+            query.declareParameters( "int projectId, long fromDate, int state" );
+
+            query.setFilter( "this.project.id == projectId && this.startTime > fromDate && this.state == state" );
+
+            query.setResult( "count(this)" );
+
+            long result = (Long) query.execute( projectId, fromDate, ContinuumProjectState.OK );
+
+            tx.commit();
+
+            return result;
+        }
+        finally
+        {
+            rollback( tx );
+        }
+    }
+
+    public List<BuildResult> getBuildResultsForProjectWithDetails( int projectId, long fromDate, int tobuildResultId )
+    {
+        PersistenceManager pm = getPersistenceManager();
+
+        Transaction tx = pm.currentTransaction();
+
+        try
+        {
+            tx.begin();
+
+            Extent extent = pm.getExtent( BuildResult.class, true );
+            pm.getFetchPlan().addGroup( BUILD_RESULT_WITH_DETAILS_FETCH_GROUP );
+
+            Query query = pm.newQuery( extent );
+
+            String parameters = "int projectId, long fromDate";
+            String filter = "this.project.id == projectId && this.startTime > fromDate";
+
+            if ( tobuildResultId > 0 )
+            {
+                parameters += ", int buildResultId";
+                filter += " && this.id < buildResultId";
+            }
+            query.declareParameters( parameters );
+
+            query.setFilter( filter );
+
+            query.setOrdering( "this.id descending" );
+
+            List<BuildResult> result;
+
+            if ( tobuildResultId > 0 )
+            {
+                result = (List<BuildResult>) query.execute( projectId, fromDate, tobuildResultId );
+            }
+            else
+            {
+                result = (List<BuildResult>) query.execute( projectId, fromDate );
+            }
+
+            result = (List<BuildResult>) pm.detachCopyAll( result );
+
+            tx.commit();
+
+            return result;
+        }
+        finally
+        {
+            rollback( tx );
+        }
+    }
+
     public List<BuildResult> getBuildResultsForProject( int projectId )
     {
-        return getBuildResultsForProject( projectId, -1, -1 );
+        return getBuildResultsForProjectWithDetails( projectId, -1, -1 );
     }
 
     public List<BuildResult> getBuildResultsForProject( int projectId, long startIndex, long endIndex )
@@ -412,7 +532,7 @@
         PersistenceManager pm = getPersistenceManager();
 
         Transaction tx = pm.currentTransaction();
-        
+
         try
         {
             tx.begin();
@@ -432,9 +552,9 @@
                 query.setRange( startIndex, endIndex );
             }
 
-            List result = (List) query.execute( projectId );
+            List<BuildResult> result = (List<BuildResult>) query.execute( projectId );
 
-            result = (List) pm.detachCopyAll( result );
+            result = (List<BuildResult>) pm.detachCopyAll( result );
 
             tx.commit();
 
@@ -445,7 +565,7 @@
             rollback( tx );
         }
     }
-    
+
     public List<BuildResult> getBuildResultsForProjectFromId( int projectId, long startId )
         throws ContinuumStoreException
     {
@@ -454,7 +574,7 @@
         Transaction tx = pm.currentTransaction();
 
         pm.getFetchPlan().addGroup( BUILD_RESULT_WITH_DETAILS_FETCH_GROUP );
-        
+
         try
         {
             tx.begin();
@@ -464,14 +584,14 @@
             Query query = pm.newQuery( extent );
 
             query.declareParameters( "int projectId, int buildNumber" );
-           
+
             query.setFilter( "this.project.id == projectId && this.buildNumber >= buildNumber" );
-            
+
             query.setOrdering( "this.startTime descending" );
 
-            List result = (List) query.execute( projectId, startId );
+            List<BuildResult> result = (List<BuildResult>) query.execute( projectId, startId );
 
-            result = (List) pm.detachCopyAll( result );
+            result = (List<BuildResult>) pm.detachCopyAll( result );
 
             tx.commit();
 
@@ -487,14 +607,12 @@
         }
     }
 
-    public List<BuildResult> getBuildResultsForProject( int projectId, long fromDate )
+    public BuildResult getLatestBuildResultInSuccess( int projectId )
     {
         PersistenceManager pm = getPersistenceManager();
 
         Transaction tx = pm.currentTransaction();
 
-        pm.getFetchPlan().addGroup( BUILD_RESULT_WITH_DETAILS_FETCH_GROUP );
-
         try
         {
             tx.begin();
@@ -503,13 +621,17 @@
 
             Query query = pm.newQuery( extent );
 
-            query.declareParameters( "int projectId, long fromDate" );
+            query.declareParameters( "int projectId" );
 
-            query.setFilter( "this.project.id == projectId && this.startTime > fromDate" );
+            String filter = "this.project.buildNumber == this.buildNumber && this.project.id == projectId";
 
-            List result = (List) query.execute( projectId, fromDate );
+            query.setFilter( filter );
 
-            result = (List) pm.detachCopyAll( result );
+            query.setUnique( true );
+
+            BuildResult result = (BuildResult) query.execute( projectId );
+
+            result = (BuildResult) pm.detachCopy( result );
 
             tx.commit();
 
@@ -521,23 +643,52 @@
         }
     }
 
-    public List<BuildResult> getBuildResultsInSuccessForProject( int projectId, long fromDate )
+    private int getPreviousBuildResultIdInSuccess( int projectId, int buildResultId )
     {
-        List<BuildResult> buildResults = getBuildResultsForProject( projectId, fromDate );
+        PersistenceManager pm = getPersistenceManager();
 
-        List<BuildResult> results = new ArrayList<BuildResult>();
+        Transaction tx = pm.currentTransaction();
 
-        if ( buildResults != null )
+        try
         {
-            for ( BuildResult res : buildResults )
-            {
-                if ( res.getState() == ContinuumProjectState.OK )
-                {
-                    results.add( res );
-                }
-            }
+            tx.begin();
+
+            Extent extent = pm.getExtent( BuildResult.class, true );
+
+            Query query = pm.newQuery( extent );
+
+            query.declareParameters( "int projectId, int buildResultId" );
+
+            String filter = "this.id < buildResultId && this.state == " + ContinuumProjectState.OK +
+                "  && this.project.id == projectId";
+
+            query.setFilter( filter );
+
+            query.setResult( "max(this.id)" );
+
+            int result = (Integer) query.execute( projectId, buildResultId );
+
+            tx.commit();
+
+            return result;
         }
-        return results;
+        finally
+        {
+            rollback( tx );
+        }
+    }
+
+    public BuildResult getPreviousBuildResultInSuccess( int projectId, int buildResultId )
+        throws ContinuumStoreException
+    {
+        try
+        {
+            return getBuildResult( getPreviousBuildResultIdInSuccess( projectId, buildResultId ) );
+        }
+        catch ( NullPointerException e )
+        {
+            return null;
+        }
     }
 
     public Map<Integer, BuildResult> getBuildResultsInSuccessByProjectGroupId( int projectGroupId )
@@ -599,9 +750,96 @@
         return null;
     }
 
-    public Map<Integer, BuildResult> getBuildResultsInSuccess()
+    @SuppressWarnings( "unchecked" )
+    public List<BuildResult> getBuildResultsInRange( Date fromDate, Date toDate, int state, String triggeredBy,
+                                                     int projectGroupId )
     {
-        return getBuildResultsInSuccessByProjectGroupId( -1 );
-    }
+        PersistenceManager pm = getPersistenceManager();
 
+        Transaction tx = pm.currentTransaction();
+
+        try
+        {
+            tx.begin();
+
+            pm.getFetchPlan().addGroup( BUILD_RESULT_WITH_DETAILS_FETCH_GROUP );
+
+            Extent extent = pm.getExtent( BuildResult.class, true );
+
+            Query query = pm.newQuery( extent );
+
+            String parameters = "";
+            String filter = "";
+
+            Map params = new HashMap();
+
+            int ctr = 0;
+
+            if ( state > 0 )
+            {
+                params.put( "state", state );
+                ctr++;
+                parameters += "int state, ";
+                filter += "this.state == state && ";
+            }
+
+            if ( projectGroupId > 0 )
+            {
+                params.put( "projectGroupId", projectGroupId );
+                ctr++;
+                parameters += "int projectGroupId, ";
+                filter += "this.project.projectGroup.id == projectGroupId && ";
+            }
+
+            if ( triggeredBy != null && !triggeredBy.equals( "" ) )
+            {
+                params.put( "triggeredBy", triggeredBy );
+                ctr++;
+                query.declareImports( "import java.lang.String" );
+                parameters += "String triggeredBy, ";
+                filter += "this.username == triggeredBy && ";
+            }
+
+            if ( fromDate != null )
+            {
+                params.put( "fromDate", fromDate.getTime() );
+                ctr++;
+                parameters += "long fromDate, ";
+                filter += "this.startTime >= fromDate && ";
+            }
+
+            if ( toDate != null )
+            {
+                Calendar cal = Calendar.getInstance();
+                cal.setTime( toDate );
+                cal.add( Calendar.DAY_OF_MONTH, 1 );
+
+                params.put( "toDate", cal.getTimeInMillis() );
+                ctr++;
+                parameters += "long toDate";
+                filter += "this.startTime < toDate";
+            }
+
+            if ( filter.endsWith( "&& " ) )
+            {
+                filter = filter.substring( 0, filter.length() - 3 );
+                parameters = parameters.substring( 0, parameters.length() - 2 );
+            }
+
+            query.declareParameters( parameters );
+            query.setFilter( filter );
+
+            List<BuildResult> result = (List<BuildResult>) query.executeWithMap( params );
+
+            result = (List<BuildResult>) pm.detachCopyAll( result );
+
+            tx.commit();
+
+            return result;
+        }
+        finally
+        {
+            rollback( tx );
+        }
+    }
 }
diff --git a/continuum-store/src/main/java/org/apache/continuum/dao/ContinuumReleaseResultDaoImpl.java b/continuum-store/src/main/java/org/apache/continuum/dao/ContinuumReleaseResultDaoImpl.java
index 1178c53..8cd422c 100644
--- a/continuum-store/src/main/java/org/apache/continuum/dao/ContinuumReleaseResultDaoImpl.java
+++ b/continuum-store/src/main/java/org/apache/continuum/dao/ContinuumReleaseResultDaoImpl.java
@@ -19,23 +19,23 @@
  * under the License.
  */
 
-import java.util.Collection;
-import java.util.List;
-
-import javax.jdo.Extent;
-import javax.jdo.PersistenceManager;
-import javax.jdo.Query;
-import javax.jdo.Transaction;
-
 import org.apache.continuum.model.release.ContinuumReleaseResult;
 import org.apache.maven.continuum.store.ContinuumObjectNotFoundException;
 import org.apache.maven.continuum.store.ContinuumStoreException;
 import org.springframework.stereotype.Repository;
 
+import java.util.Collection;
+import java.util.List;
+import javax.jdo.Extent;
+import javax.jdo.PersistenceManager;
+import javax.jdo.Query;
+import javax.jdo.Transaction;
+
 /**
  * @author <a href="mailto:ctan@apache.org">Maria Catherine Tan</a>
+ * @plexus.component role="org.apache.continuum.dao.ContinuumReleaseResultDao"
  */
-@Repository("continuumReleaseResultDao")
+@Repository( "continuumReleaseResultDao" )
 public class ContinuumReleaseResultDaoImpl
     extends AbstractDao
     implements ContinuumReleaseResultDao
@@ -57,7 +57,8 @@
         return (ContinuumReleaseResult) getObjectById( ContinuumReleaseResult.class, releaseResultId );
     }
 
-    public ContinuumReleaseResult getContinuumReleaseResult( int projectId, String releaseGoal, long startTime, long endTime )
+    public ContinuumReleaseResult getContinuumReleaseResult( int projectId, String releaseGoal, long startTime,
+                                                             long endTime )
         throws ContinuumStoreException
     {
         PersistenceManager pm = getPersistenceManager();
@@ -67,17 +68,18 @@
         try
         {
             tx.begin();
-            
+
             Extent extent = pm.getExtent( ContinuumReleaseResult.class, true );
 
             Query query = pm.newQuery( extent );
 
             query.declareImports( "import java.lang.String" );
-            
+
             query.declareParameters( "int projectId, String releaseGoal, long startTime, long endTime" );
-            
-            query.setFilter( "this.project.id == projectId && this.releaseGoal == releaseGoal && this.startTime == startTime && this.endTime == endTime" );
-            
+
+            query.setFilter(
+                "this.project.id == projectId && this.releaseGoal == releaseGoal && this.startTime == startTime && this.endTime == endTime" );
+
             Object[] params = new Object[4];
             params[0] = projectId;
             params[1] = releaseGoal;
@@ -96,7 +98,7 @@
             Object object = pm.detachCopy( result.iterator().next() );
 
             tx.commit();
-            
+
             return (ContinuumReleaseResult) object;
         }
         finally
@@ -105,7 +107,7 @@
         }
 
     }
-    
+
     public List<ContinuumReleaseResult> getContinuumReleaseResultsByProjectGroup( int projectGroupId )
     {
         PersistenceManager pm = getPersistenceManager();
diff --git a/continuum-store/src/main/java/org/apache/continuum/dao/DaoUtilsImpl.java b/continuum-store/src/main/java/org/apache/continuum/dao/DaoUtilsImpl.java
index e3b68e3..b6f899d 100644
--- a/continuum-store/src/main/java/org/apache/continuum/dao/DaoUtilsImpl.java
+++ b/continuum-store/src/main/java/org/apache/continuum/dao/DaoUtilsImpl.java
@@ -26,6 +26,7 @@
 import org.apache.continuum.model.repository.RepositoryPurgeConfiguration;
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.BuildDefinitionTemplate;
+import org.apache.maven.continuum.model.project.BuildQueue;
 import org.apache.maven.continuum.model.project.BuildResult;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.project.ProjectDependency;
@@ -43,6 +44,11 @@
 import org.codehaus.plexus.jdo.PlexusJdoUtils;
 import org.springframework.stereotype.Repository;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 import javax.annotation.Resource;
 import javax.jdo.Extent;
 import javax.jdo.JDOUserException;
@@ -50,21 +56,20 @@
 import javax.jdo.PersistenceManagerFactory;
 import javax.jdo.Query;
 import javax.jdo.Transaction;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
  * @version $Id$
+ * @plexus.component role="org.apache.continuum.dao.DaoUtils"
  */
-@Repository("daoUtils")
+@Repository( "daoUtils" )
 public class DaoUtilsImpl
     extends AbstractDao
     implements DaoUtils
 {
+    /**
+     * @plexus.requirement role="org.apache.continuum.dao.ProjectDao"
+     */
     @Resource
     private ProjectDao projectDao;
 
@@ -75,8 +80,8 @@
 
     public void eraseDatabase()
     {
-        PlexusJdoUtils.removeAll( getPersistenceManager(), BuildDefinitionTemplate.class );
         PlexusJdoUtils.removeAll( getPersistenceManager(), BuildResult.class );
+        PlexusJdoUtils.removeAll( getPersistenceManager(), BuildDefinitionTemplate.class );
         PlexusJdoUtils.removeAll( getPersistenceManager(), ContinuumReleaseResult.class );
         PlexusJdoUtils.removeAll( getPersistenceManager(), ProjectScmRoot.class );
         PlexusJdoUtils.removeAll( getPersistenceManager(), ProjectGroup.class );
@@ -86,6 +91,7 @@
         PlexusJdoUtils.removeAll( getPersistenceManager(), LocalRepository.class );
         PlexusJdoUtils.removeAll( getPersistenceManager(), DirectoryPurgeConfiguration.class );
         PlexusJdoUtils.removeAll( getPersistenceManager(), Schedule.class );
+        PlexusJdoUtils.removeAll( getPersistenceManager(), BuildQueue.class );
         PlexusJdoUtils.removeAll( getPersistenceManager(), Profile.class );
         PlexusJdoUtils.removeAll( getPersistenceManager(), Installation.class );
         PlexusJdoUtils.removeAll( getPersistenceManager(), ScmResult.class );
@@ -112,10 +118,6 @@
                 {
                     pmf.close();
                 }
-                catch ( SecurityException e )
-                {
-                    throw e;
-                }
                 catch ( JDOUserException e )
                 {
                     if ( numTry < 5 )
@@ -150,13 +152,13 @@
      *
      * @todo Move to a better place
      */
-    public Map getAggregatedProjectIdsAndBuildDefinitionIdsBySchedule( int scheduleId )
+    public Map<Integer, Object> getAggregatedProjectIdsAndBuildDefinitionIdsBySchedule( int scheduleId )
         throws ContinuumStoreException
     {
-        Map projectSource = getProjectIdsAndBuildDefinitionsIdsBySchedule( scheduleId );
-        Map projectGroupSource = getProjectGroupIdsAndBuildDefinitionsIdsBySchedule( scheduleId );
+        Map<Integer, Object> projectSource = getProjectIdsAndBuildDefinitionsIdsBySchedule( scheduleId );
+        Map<Integer, Object> projectGroupSource = getProjectGroupIdsAndBuildDefinitionsIdsBySchedule( scheduleId );
 
-        Map aggregate = new HashMap();
+        Map<Integer, Object> aggregate = new HashMap<Integer, Object>();
 
         // start out by checking if we have projects with this scheduleId
         if ( projectSource != null )
@@ -169,14 +171,13 @@
         // might define their own build definitions
         if ( projectGroupSource != null )
         {
-            for ( Iterator i = projectGroupSource.keySet().iterator(); i.hasNext(); )
+            for ( Integer projectGroupId : projectGroupSource.keySet() )
             {
-                Integer projectGroupId = (Integer) i.next();
-                List projectsInGroup = projectDao.getProjectsInGroup( projectGroupId.intValue() );
+                List<Project> projectsInGroup = projectDao.getProjectsInGroup( projectGroupId );
 
-                for ( Iterator j = projectsInGroup.iterator(); j.hasNext(); )
+                for ( Project p : projectsInGroup )
                 {
-                    Integer projectId = new Integer( ( (Project) j.next() ).getId() );
+                    Integer projectId = p.getId();
                     if ( !aggregate.keySet().contains( projectId ) )
                     {
                         aggregate.put( projectId, projectGroupSource.get( projectGroupId ) );
@@ -193,7 +194,7 @@
      * @throws ContinuumStoreException
      * @todo Move to a better place
      */
-    public Map getProjectIdsAndBuildDefinitionsIdsBySchedule( int scheduleId )
+    public Map<Integer, Object> getProjectIdsAndBuildDefinitionsIdsBySchedule( int scheduleId )
         throws ContinuumStoreException
     {
         PersistenceManager pm = getPersistenceManager();
@@ -218,7 +219,7 @@
 
             query.setResult( "this.id, buildDef.id" );
 
-            List result = (List) query.execute( new Integer( scheduleId ) );
+            List result = (List) query.execute( scheduleId );
 
             Map projects = new HashMap();
 
@@ -267,7 +268,7 @@
      * @throws ContinuumStoreException
      * @todo Move to a better place
      */
-    public Map getProjectGroupIdsAndBuildDefinitionsIdsBySchedule( int scheduleId )
+    public Map<Integer, Object> getProjectGroupIdsAndBuildDefinitionsIdsBySchedule( int scheduleId )
         throws ContinuumStoreException
     {
         PersistenceManager pm = getPersistenceManager();
@@ -329,5 +330,4 @@
         }
         return null;
     }
-
 }
diff --git a/continuum-store/src/main/java/org/apache/continuum/dao/DirectoryPurgeConfigurationDaoImpl.java b/continuum-store/src/main/java/org/apache/continuum/dao/DirectoryPurgeConfigurationDaoImpl.java
index f5ab520..d78118d 100644
--- a/continuum-store/src/main/java/org/apache/continuum/dao/DirectoryPurgeConfigurationDaoImpl.java
+++ b/continuum-store/src/main/java/org/apache/continuum/dao/DirectoryPurgeConfigurationDaoImpl.java
@@ -23,18 +23,19 @@
 import org.apache.maven.continuum.store.ContinuumStoreException;
 import org.springframework.stereotype.Repository;
 
+import java.util.Collections;
+import java.util.List;
 import javax.jdo.Extent;
 import javax.jdo.PersistenceManager;
 import javax.jdo.Query;
 import javax.jdo.Transaction;
-import java.util.Collections;
-import java.util.List;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
  * @version $Id$
+ * @plexus.component role="org.apache.continuum.dao.DirectoryPurgeConfigurationDao"
  */
-@Repository("directoryPurgeConfigurationDao")
+@Repository( "directoryPurgeConfigurationDao" )
 public class DirectoryPurgeConfigurationDaoImpl
     extends AbstractDao
     implements DirectoryPurgeConfigurationDao
@@ -62,7 +63,37 @@
 
             query.setFilter( "this.schedule.id == scheduleId" );
 
-            List result = (List) query.execute( new Integer( scheduleId ) );
+            List result = (List) query.execute( scheduleId );
+
+            return result == null ? Collections.EMPTY_LIST : (List) pm.detachCopyAll( result );
+        }
+        finally
+        {
+            tx.commit();
+
+            rollback( tx );
+        }
+    }
+
+    public List<DirectoryPurgeConfiguration> getEnableDirectoryPurgeConfigurationsBySchedule( int scheduleId )
+    {
+        PersistenceManager pm = getPersistenceManager();
+
+        Transaction tx = pm.currentTransaction();
+
+        try
+        {
+            tx.begin();
+
+            Extent extent = pm.getExtent( DirectoryPurgeConfiguration.class, true );
+
+            Query query = pm.newQuery( extent );
+
+            query.declareParameters( "int scheduleId" );
+
+            query.setFilter( "this.schedule.id == scheduleId && this.enabled == true" );
+
+            List result = (List) query.execute( scheduleId );
 
             return result == null ? Collections.EMPTY_LIST : (List) pm.detachCopyAll( result );
         }
diff --git a/continuum-store/src/main/java/org/apache/continuum/dao/DistributedDirectoryPurgeConfigurationDaoImpl.java b/continuum-store/src/main/java/org/apache/continuum/dao/DistributedDirectoryPurgeConfigurationDaoImpl.java
new file mode 100644
index 0000000..bb14a5c
--- /dev/null
+++ b/continuum-store/src/main/java/org/apache/continuum/dao/DistributedDirectoryPurgeConfigurationDaoImpl.java
@@ -0,0 +1,169 @@
+package org.apache.continuum.dao;
+
+/*
+ * 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 org.apache.continuum.model.repository.DistributedDirectoryPurgeConfiguration;
+import org.apache.maven.continuum.store.ContinuumStoreException;
+import org.springframework.stereotype.Repository;
+
+import java.util.Collections;
+import java.util.List;
+import javax.jdo.Extent;
+import javax.jdo.PersistenceManager;
+import javax.jdo.Query;
+import javax.jdo.Transaction;
+
+/**
+ * @author
+ * @version $Id$
+ * @plexus.component role="org.apache.continuum.dao.DistributedDirectoryPurgeConfigurationDao"
+ */
+@Repository( "distributedDirectoryPurgeConfigurationDao" )
+public class DistributedDirectoryPurgeConfigurationDaoImpl
+    extends AbstractDao
+    implements DistributedDirectoryPurgeConfigurationDao
+{
+    public List<DistributedDirectoryPurgeConfiguration> getAllDistributedDirectoryPurgeConfigurations()
+    {
+        return getAllObjectsDetached( DistributedDirectoryPurgeConfiguration.class );
+    }
+
+    public List<DistributedDirectoryPurgeConfiguration> getDistributedDirectoryPurgeConfigurationsBySchedule(
+        int scheduleId )
+    {
+        PersistenceManager pm = getPersistenceManager();
+
+        Transaction tx = pm.currentTransaction();
+
+        try
+        {
+            tx.begin();
+
+            Extent extent = pm.getExtent( DistributedDirectoryPurgeConfiguration.class, true );
+
+            Query query = pm.newQuery( extent );
+
+            query.declareParameters( "int scheduleId" );
+
+            query.setFilter( "this.schedule.id == scheduleId" );
+
+            List result = (List) query.execute( scheduleId );
+
+            return result == null ? Collections.EMPTY_LIST : (List) pm.detachCopyAll( result );
+        }
+        finally
+        {
+            tx.commit();
+
+            rollback( tx );
+        }
+    }
+
+    public List<DistributedDirectoryPurgeConfiguration> getEnableDistributedDirectoryPurgeConfigurationsBySchedule(
+        int scheduleId )
+    {
+        PersistenceManager pm = getPersistenceManager();
+
+        Transaction tx = pm.currentTransaction();
+
+        try
+        {
+            tx.begin();
+
+            Extent extent = pm.getExtent( DistributedDirectoryPurgeConfiguration.class, true );
+
+            Query query = pm.newQuery( extent );
+
+            query.declareParameters( "int scheduleId" );
+
+            query.setFilter( "this.schedule.id == scheduleId && this.enabled == true" );
+
+            List result = (List) query.execute( scheduleId );
+
+            return result == null ? Collections.EMPTY_LIST : (List) pm.detachCopyAll( result );
+        }
+        finally
+        {
+            tx.commit();
+
+            rollback( tx );
+        }
+    }
+
+    public List<DistributedDirectoryPurgeConfiguration> getDistributedDirectoryPurgeConfigurationsByType( String type )
+    {
+        PersistenceManager pm = getPersistenceManager();
+
+        Transaction tx = pm.currentTransaction();
+
+        try
+        {
+            tx.begin();
+
+            Extent extent = pm.getExtent( DistributedDirectoryPurgeConfiguration.class, true );
+
+            Query query = pm.newQuery( extent );
+
+            query.declareImports( "import java.lang.String" );
+
+            query.declareParameters( "String type" );
+
+            query.setFilter( "this.directoryType == type" );
+
+            List result = (List) query.execute( type );
+
+            return result == null ? Collections.EMPTY_LIST : (List) pm.detachCopyAll( result );
+        }
+        finally
+        {
+            tx.commit();
+
+            rollback( tx );
+        }
+    }
+
+    public DistributedDirectoryPurgeConfiguration getDistributedDirectoryPurgeConfiguration( int configurationId )
+        throws ContinuumStoreException
+    {
+        return (DistributedDirectoryPurgeConfiguration) getObjectById( DistributedDirectoryPurgeConfiguration.class,
+                                                                       configurationId );
+    }
+
+    public DistributedDirectoryPurgeConfiguration addDistributedDirectoryPurgeConfiguration(
+        DistributedDirectoryPurgeConfiguration purgeConfiguration )
+        throws ContinuumStoreException
+    {
+        return (DistributedDirectoryPurgeConfiguration) addObject( purgeConfiguration );
+    }
+
+    public void updateDistributedDirectoryPurgeConfiguration(
+        DistributedDirectoryPurgeConfiguration purgeConfiguration )
+        throws ContinuumStoreException
+    {
+        updateObject( purgeConfiguration );
+    }
+
+    public void removeDistributedDirectoryPurgeConfiguration(
+        DistributedDirectoryPurgeConfiguration purgeConfiguration )
+        throws ContinuumStoreException
+    {
+        removeObject( purgeConfiguration );
+    }
+}
diff --git a/continuum-store/src/main/java/org/apache/continuum/dao/InstallationDaoImpl.java b/continuum-store/src/main/java/org/apache/continuum/dao/InstallationDaoImpl.java
index 786b3c4..3241769 100644
--- a/continuum-store/src/main/java/org/apache/continuum/dao/InstallationDaoImpl.java
+++ b/continuum-store/src/main/java/org/apache/continuum/dao/InstallationDaoImpl.java
@@ -25,20 +25,20 @@
 import org.codehaus.plexus.util.StringUtils;
 import org.springframework.stereotype.Repository;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
 import javax.jdo.Extent;
 import javax.jdo.PersistenceManager;
 import javax.jdo.Query;
 import javax.jdo.Transaction;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
  * @version $Id$
+ * @plexus.component role="org.apache.continuum.dao.InstallationDao"
  */
-@Repository("installationDao")
+@Repository( "installationDao" )
 public class InstallationDaoImpl
     extends AbstractDao
     implements InstallationDao
@@ -84,9 +84,8 @@
 
             if ( result.size() != 0 )
             {
-                for ( Iterator<Profile> iterator = result.iterator(); iterator.hasNext(); )
+                for ( Profile profile : result )
                 {
-                    Profile profile = iterator.next();
                     profile.setJdk( null );
                     pm.makePersistent( profile );
                 }
@@ -105,9 +104,8 @@
 
             if ( result.size() != 0 )
             {
-                for ( Iterator<Profile> iterator = result.iterator(); iterator.hasNext(); )
+                for ( Profile profile : result )
                 {
-                    Profile profile = iterator.next();
                     profile.setBuilder( null );
                     pm.makePersistent( profile );
                 }
@@ -177,8 +175,6 @@
 
             Query query = pm.newQuery( extent );
 
-            query.declareImports( "import java.lang.String" );
-
             query.declareParameters( "int installationId" );
 
             query.setFilter( "this.installationId == installationId" );
@@ -203,4 +199,46 @@
             rollback( tx );
         }
     }
+
+    public Installation getInstallation( String installationName )
+        throws ContinuumStoreException
+    {
+        PersistenceManager pm = getPersistenceManager();
+
+        Transaction tx = pm.currentTransaction();
+
+        try
+        {
+            tx.begin();
+
+            Extent extent = pm.getExtent( Installation.class, true );
+
+            Query query = pm.newQuery( extent );
+
+            query.declareImports( "import java.lang.String" );
+
+            query.declareParameters( "String name" );
+
+            query.setFilter( "this.name == name" );
+
+            Collection result = (Collection) query.execute( installationName );
+
+            if ( result.size() == 0 )
+            {
+                tx.commit();
+
+                return null;
+            }
+
+            Object object = pm.detachCopy( result.iterator().next() );
+
+            tx.commit();
+
+            return (Installation) object;
+        }
+        finally
+        {
+            rollback( tx );
+        }
+    }
 }
diff --git a/continuum-store/src/main/java/org/apache/continuum/dao/LocalRepositoryDaoImpl.java b/continuum-store/src/main/java/org/apache/continuum/dao/LocalRepositoryDaoImpl.java
index 66e5f1d..0da6027 100644
--- a/continuum-store/src/main/java/org/apache/continuum/dao/LocalRepositoryDaoImpl.java
+++ b/continuum-store/src/main/java/org/apache/continuum/dao/LocalRepositoryDaoImpl.java
@@ -23,19 +23,20 @@
 import org.apache.maven.continuum.store.ContinuumStoreException;
 import org.springframework.stereotype.Repository;
 
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
 import javax.jdo.Extent;
 import javax.jdo.PersistenceManager;
 import javax.jdo.Query;
 import javax.jdo.Transaction;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
  * @version $Id$
+ * @plexus.component role="org.apache.continuum.dao.LocalRepositoryDao"
  */
-@Repository("localRepositoryDao")
+@Repository( "localRepositoryDao" )
 public class LocalRepositoryDaoImpl
     extends AbstractDao
     implements LocalRepositoryDao
diff --git a/continuum-store/src/main/java/org/apache/continuum/dao/NotifierDaoImpl.java b/continuum-store/src/main/java/org/apache/continuum/dao/NotifierDaoImpl.java
index 9baf029..b7e65f1 100644
--- a/continuum-store/src/main/java/org/apache/continuum/dao/NotifierDaoImpl.java
+++ b/continuum-store/src/main/java/org/apache/continuum/dao/NotifierDaoImpl.java
@@ -27,7 +27,7 @@
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
  * @version $Id$
  */
-@Repository("notifierDao")
+@Repository( "notifierDao" )
 public class NotifierDaoImpl
     extends AbstractDao
     implements NotifierDao
diff --git a/continuum-store/src/main/java/org/apache/continuum/dao/ProfileDaoImpl.java b/continuum-store/src/main/java/org/apache/continuum/dao/ProfileDaoImpl.java
index 6bf413e..7164ded 100644
--- a/continuum-store/src/main/java/org/apache/continuum/dao/ProfileDaoImpl.java
+++ b/continuum-store/src/main/java/org/apache/continuum/dao/ProfileDaoImpl.java
@@ -23,18 +23,19 @@
 import org.apache.maven.continuum.store.ContinuumStoreException;
 import org.springframework.stereotype.Repository;
 
+import java.util.Collection;
+import java.util.List;
 import javax.jdo.Extent;
 import javax.jdo.PersistenceManager;
 import javax.jdo.Query;
 import javax.jdo.Transaction;
-import java.util.Collection;
-import java.util.List;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
  * @version $Id$
+ * @plexus.component role="org.apache.continuum.dao.ProfileDao"
  */
-@Repository("profileDao")
+@Repository( "profileDao" )
 public class ProfileDaoImpl
     extends AbstractDao
     implements ProfileDao
diff --git a/continuum-store/src/main/java/org/apache/continuum/dao/ProjectDaoImpl.java b/continuum-store/src/main/java/org/apache/continuum/dao/ProjectDaoImpl.java
index 191534b..0c65da5 100644
--- a/continuum-store/src/main/java/org/apache/continuum/dao/ProjectDaoImpl.java
+++ b/continuum-store/src/main/java/org/apache/continuum/dao/ProjectDaoImpl.java
@@ -19,25 +19,29 @@
  * under the License.
  */
 
+import org.apache.continuum.model.project.ProjectGroupSummary;
+import org.apache.continuum.model.project.ProjectSummaryResult;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.project.ProjectGroup;
 import org.apache.maven.continuum.store.ContinuumObjectNotFoundException;
 import org.apache.maven.continuum.store.ContinuumStoreException;
 import org.springframework.stereotype.Repository;
 
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import javax.jdo.Extent;
 import javax.jdo.PersistenceManager;
 import javax.jdo.Query;
 import javax.jdo.Transaction;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
  * @version $Id$
+ * @plexus.component role="org.apache.continuum.dao.ProjectDao"
  */
-@Repository("projectDao")
+@Repository( "projectDao" )
 public class ProjectDaoImpl
     extends AbstractDao
     implements ProjectDao
@@ -148,22 +152,33 @@
         }
     }
 
-    // todo get this natively supported in the store
     public List<Project> getProjectsWithDependenciesByGroupId( int projectGroupId )
     {
-        List<Project> allProjects =
-            getAllObjectsDetached( Project.class, "name ascending", PROJECT_DEPENDENCIES_FETCH_GROUP );
+        PersistenceManager pm = getPersistenceManager();
 
-        List<Project> groupProjects = new ArrayList<Project>();
+        Transaction tx = pm.currentTransaction();
 
-        for ( Project project : allProjects )
+        try
         {
-            if ( project.getProjectGroup().getId() == projectGroupId )
-            {
-                groupProjects.add( project );
-            }
+            tx.begin();
+
+            Extent extent = pm.getExtent( Project.class, true );
+
+            Query query = pm.newQuery( extent, "projectGroup.id == " + projectGroupId );
+
+            pm.getFetchPlan().addGroup( PROJECT_DEPENDENCIES_FETCH_GROUP );
+            List<Project> result = (List<Project>) query.execute();
+
+            result = (List<Project>) pm.detachCopyAll( result );
+
+            tx.commit();
+
+            return result;
         }
-        return groupProjects;
+        finally
+        {
+            rollback( tx );
+        }
     }
 
     public Project getProjectWithBuilds( int projectId )
@@ -184,12 +199,6 @@
         return (Project) getObjectById( Project.class, projectId, PROJECT_WITH_CHECKOUT_RESULT_FETCH_GROUP );
     }
 
-    public Project getProjectWithScmDetails( int projectId )
-        throws ContinuumStoreException
-    {
-        return (Project) getObjectById( Project.class, projectId, PROJECT_WITH_SCM_DETAILS_FETCH_GROUP );
-    }
-
     public List<Project> getProjectsInGroup( int projectGroupId )
         throws ContinuumStoreException
     {
@@ -207,9 +216,9 @@
 
             query.setOrdering( "name ascending" );
 
-            List result = (List) query.execute();
+            List<Project> result = (List<Project>) query.execute();
 
-            result = (List) pm.detachCopyAll( result );
+            result = (List<Project>) pm.detachCopyAll( result );
 
             tx.commit();
 
@@ -242,9 +251,9 @@
 
             pm.getFetchPlan().addGroup( PROJECTGROUP_PROJECTS_FETCH_GROUP );
 
-            List result = (List) query.execute();
+            List<Project> result = (List<Project>) query.execute();
 
-            result = (List) pm.detachCopyAll( result );
+            result = (List<Project>) pm.detachCopyAll( result );
 
             tx.commit();
 
@@ -256,12 +265,6 @@
         }
     }
 
-
-    public List<Project> getAllProjectsWithAllDetails()
-    {
-        return getAllObjectsDetached( Project.class, "name ascending", PROJECT_ALL_DETAILS_FETCH_GROUP );
-    }
-
     public Project getProjectWithAllDetails( int projectId )
         throws ContinuumStoreException
     {
@@ -304,4 +307,78 @@
     {
         return (Project) getObjectById( Project.class, projectId, PROJECT_DEPENDENCIES_FETCH_GROUP );
     }
+
+    public Map<Integer, ProjectGroupSummary> getProjectsSummary()
+    {
+        PersistenceManager pm = getPersistenceManager();
+
+        Transaction tx = pm.currentTransaction();
+
+        try
+        {
+            tx.begin();
+
+            Extent extent = pm.getExtent( Project.class );
+
+            Query query = pm.newQuery( extent );
+
+            query.setResult( "projectGroup.id as projectGroupId, state as projectState, count(state) as size" );
+
+            query.setResultClass( ProjectSummaryResult.class );
+
+            query.setGrouping( "projectGroup.id, state" );
+
+            List<ProjectSummaryResult> results = (List<ProjectSummaryResult>) query.execute();
+
+            Map<Integer, ProjectGroupSummary> summaries = processProjectGroupSummary( results );
+
+            tx.commit();
+
+            return summaries;
+        }
+        finally
+        {
+            rollback( tx );
+        }
+    }
+
+    private Map<Integer, ProjectGroupSummary> processProjectGroupSummary( List<ProjectSummaryResult> results )
+    {
+        Map<Integer, ProjectGroupSummary> map = new HashMap<Integer, ProjectGroupSummary>();
+
+        for ( ProjectSummaryResult result : results )
+        {
+            ProjectGroupSummary summary;
+            int projectGroupId = result.getProjectGroupId();
+            int size = new Long( result.getSize() ).intValue();
+            int state = result.getProjectState();
+
+            if ( map.containsKey( projectGroupId ) )
+            {
+                summary = map.get( projectGroupId );
+            }
+            else
+            {
+                summary = new ProjectGroupSummary( projectGroupId );
+            }
+
+            summary.addProjects( size );
+
+            if ( state == 2 )
+            {
+                summary.addNumberOfSuccesses( size );
+            }
+            else if ( state == 3 )
+            {
+                summary.addNumberOfFailures( size );
+            }
+            else if ( state == 4 )
+            {
+                summary.addNumberOfErrors( size );
+            }
+
+            map.put( projectGroupId, summary );
+        }
+        return map;
+    }
 }
diff --git a/continuum-store/src/main/java/org/apache/continuum/dao/ProjectGroupDaoImpl.java b/continuum-store/src/main/java/org/apache/continuum/dao/ProjectGroupDaoImpl.java
index 103e7c4..c13c640 100644
--- a/continuum-store/src/main/java/org/apache/continuum/dao/ProjectGroupDaoImpl.java
+++ b/continuum-store/src/main/java/org/apache/continuum/dao/ProjectGroupDaoImpl.java
@@ -19,6 +19,7 @@
  * under the License.
  */
 
+import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.project.ProjectGroup;
 import org.apache.maven.continuum.store.ContinuumObjectNotFoundException;
@@ -26,25 +27,31 @@
 import org.codehaus.plexus.jdo.PlexusJdoUtils;
 import org.springframework.stereotype.Repository;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
 import javax.annotation.Resource;
 import javax.jdo.Extent;
 import javax.jdo.PersistenceManager;
 import javax.jdo.Query;
 import javax.jdo.Transaction;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
  * @version $Id$
+ * @plexus.component role="org.apache.continuum.dao.ProjectGroupDao"
  */
-@Repository("projectGroupDao")
+@Repository( "projectGroupDao" )
 public class ProjectGroupDaoImpl
     extends AbstractDao
     implements ProjectGroupDao
 {
+    /**
+     * @plexus.requirement role=org.apache.continuum.dao.ProjectDao"
+     */
     @Resource
     private ProjectDao projectDao;
 
@@ -58,7 +65,7 @@
         ProjectGroup pg = null;
         try
         {
-            pg = getProjectGroupWithProjects( projectGroup.getId() );
+            pg = getProjectGroupWithBuildDetailsByProjectGroupId( projectGroup.getId() );
         }
         catch ( Exception e )
         {
@@ -74,6 +81,35 @@
             {
                 projectDao.removeProject( p );
             }
+
+            List<BuildDefinition> buildDefs = new ArrayList<BuildDefinition>();
+            Iterator<BuildDefinition> it = pg.getBuildDefinitions().listIterator();
+            boolean template = false;
+            while ( it.hasNext() )
+            {
+                BuildDefinition bd = it.next();
+                if ( bd.isTemplate() )
+                {
+                    template = true;
+                }
+                else
+                {
+                    buildDefs.add( bd );
+                }
+            }
+            if ( template )
+            {
+                try
+                {
+                    pg.setBuildDefinitions( buildDefs );
+                    updateProjectGroup( pg );
+                }
+                catch ( ContinuumStoreException e )
+                {
+                    // Do nothing
+                }
+            }
+
             removeObject( pg );
         }
     }
@@ -154,10 +190,10 @@
 
     public List<ProjectGroup> getAllProjectGroupsWithTheLot()
     {
-        List fetchGroups = Arrays.asList( new String[]{PROJECT_WITH_BUILDS_FETCH_GROUP,
-            PROJECTGROUP_PROJECTS_FETCH_GROUP, BUILD_RESULT_WITH_DETAILS_FETCH_GROUP,
-            PROJECT_WITH_CHECKOUT_RESULT_FETCH_GROUP, PROJECT_ALL_DETAILS_FETCH_GROUP,
-            PROJECT_BUILD_DETAILS_FETCH_GROUP} );
+        List fetchGroups = Arrays.asList(
+            new String[]{PROJECT_WITH_BUILDS_FETCH_GROUP, PROJECTGROUP_PROJECTS_FETCH_GROUP,
+                BUILD_RESULT_WITH_DETAILS_FETCH_GROUP, PROJECT_WITH_CHECKOUT_RESULT_FETCH_GROUP,
+                PROJECT_ALL_DETAILS_FETCH_GROUP, PROJECT_BUILD_DETAILS_FETCH_GROUP} );
         return PlexusJdoUtils.getAllObjectsDetached( getPersistenceManager(), ProjectGroup.class, "name ascending",
                                                      fetchGroups );
     }
@@ -186,7 +222,7 @@
 
             query.setFilter( "this.localRepository.id == repositoryId" );
 
-            List result = (List) query.execute( new Integer( repositoryId ) );
+            List result = (List) query.execute( repositoryId );
 
             return result == null ? Collections.EMPTY_LIST : (List) pm.detachCopyAll( result );
         }
diff --git a/continuum-store/src/main/java/org/apache/continuum/dao/ProjectScmRootDaoImpl.java b/continuum-store/src/main/java/org/apache/continuum/dao/ProjectScmRootDaoImpl.java
index e927fb5..b59e40e 100644
--- a/continuum-store/src/main/java/org/apache/continuum/dao/ProjectScmRootDaoImpl.java
+++ b/continuum-store/src/main/java/org/apache/continuum/dao/ProjectScmRootDaoImpl.java
@@ -19,24 +19,24 @@
  * under the License.
  */
 
-import java.util.Collection;
-import java.util.List;
-
-import javax.jdo.Extent;
-import javax.jdo.PersistenceManager;
-import javax.jdo.Query;
-import javax.jdo.Transaction;
-
 import org.apache.continuum.model.project.ProjectScmRoot;
 import org.apache.maven.continuum.store.ContinuumObjectNotFoundException;
 import org.apache.maven.continuum.store.ContinuumStoreException;
 import org.springframework.stereotype.Repository;
 
+import java.util.Collection;
+import java.util.List;
+import javax.jdo.Extent;
+import javax.jdo.PersistenceManager;
+import javax.jdo.Query;
+import javax.jdo.Transaction;
+
 /**
  * @author <a href="mailto:ctan@apache.org">Maria Catherine Tan</a>
  * @version $Id: $
+ * @plexus.component role="org.apache.continuum.dao.ProjectScmRootDao"
  */
-@Repository("projectScmRootDao")
+@Repository( "projectScmRootDao" )
 public class ProjectScmRootDaoImpl
     extends AbstractDao
     implements ProjectScmRootDao
@@ -51,7 +51,7 @@
     {
         return getAllObjectsDetached( ProjectScmRoot.class );
     }
-    
+
     public List<ProjectScmRoot> getProjectScmRootByProjectGroup( int projectGroupId )
     {
         PersistenceManager pm = getPersistenceManager();
@@ -116,7 +116,7 @@
             Object[] params = new Object[2];
             params[0] = projectGroupId;
             params[1] = scmRootAddress;
-            
+
             Collection result = (Collection) query.executeWithArray( params );
 
             if ( result.size() == 0 )
@@ -137,7 +137,7 @@
             rollback( tx );
         }
     }
-    
+
     public ProjectScmRoot getProjectScmRoot( int projectScmRootId )
         throws ContinuumObjectNotFoundException, ContinuumStoreException
     {
diff --git a/continuum-store/src/main/java/org/apache/continuum/dao/RepositoryPurgeConfigurationDaoImpl.java b/continuum-store/src/main/java/org/apache/continuum/dao/RepositoryPurgeConfigurationDaoImpl.java
index 1cd8e7f..7b88908 100644
--- a/continuum-store/src/main/java/org/apache/continuum/dao/RepositoryPurgeConfigurationDaoImpl.java
+++ b/continuum-store/src/main/java/org/apache/continuum/dao/RepositoryPurgeConfigurationDaoImpl.java
@@ -23,18 +23,19 @@
 import org.apache.maven.continuum.store.ContinuumStoreException;
 import org.springframework.stereotype.Repository;
 
+import java.util.Collections;
+import java.util.List;
 import javax.jdo.Extent;
 import javax.jdo.PersistenceManager;
 import javax.jdo.Query;
 import javax.jdo.Transaction;
-import java.util.Collections;
-import java.util.List;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
  * @version $Id$
+ * @plexus.component role="org.apache.continuum.dao.RepositoryPurgeConfigurationDao"
  */
-@Repository("repositoryPurgeConfigurationDao")
+@Repository( "repositoryPurgeConfigurationDao" )
 public class RepositoryPurgeConfigurationDaoImpl
     extends AbstractDao
     implements RepositoryPurgeConfigurationDao
@@ -62,7 +63,37 @@
 
             query.setFilter( "this.schedule.id == scheduleId" );
 
-            List result = (List) query.execute( new Integer( scheduleId ) );
+            List result = (List) query.execute( scheduleId );
+
+            return result == null ? Collections.EMPTY_LIST : (List) pm.detachCopyAll( result );
+        }
+        finally
+        {
+            tx.commit();
+
+            rollback( tx );
+        }
+    }
+
+    public List<RepositoryPurgeConfiguration> getEnableRepositoryPurgeConfigurationsBySchedule( int scheduleId )
+    {
+        PersistenceManager pm = getPersistenceManager();
+
+        Transaction tx = pm.currentTransaction();
+
+        try
+        {
+            tx.begin();
+
+            Extent extent = pm.getExtent( RepositoryPurgeConfiguration.class, true );
+
+            Query query = pm.newQuery( extent );
+
+            query.declareParameters( "int scheduleId" );
+
+            query.setFilter( "this.schedule.id == scheduleId  && this.enabled == true" );
+
+            List result = (List) query.execute( scheduleId );
 
             return result == null ? Collections.EMPTY_LIST : (List) pm.detachCopyAll( result );
         }
@@ -92,7 +123,7 @@
 
             query.setFilter( "this.repository.id == repositoryId" );
 
-            List result = (List) query.execute( new Integer( repositoryId ) );
+            List result = (List) query.execute( repositoryId );
 
             return result == null ? Collections.EMPTY_LIST : (List) pm.detachCopyAll( result );
         }
diff --git a/continuum-store/src/main/java/org/apache/continuum/dao/ScheduleDaoImpl.java b/continuum-store/src/main/java/org/apache/continuum/dao/ScheduleDaoImpl.java
index bf2dc48..81b5951 100644
--- a/continuum-store/src/main/java/org/apache/continuum/dao/ScheduleDaoImpl.java
+++ b/continuum-store/src/main/java/org/apache/continuum/dao/ScheduleDaoImpl.java
@@ -23,18 +23,19 @@
 import org.apache.maven.continuum.store.ContinuumStoreException;
 import org.springframework.stereotype.Repository;
 
+import java.util.Collection;
+import java.util.List;
 import javax.jdo.Extent;
 import javax.jdo.PersistenceManager;
 import javax.jdo.Query;
 import javax.jdo.Transaction;
-import java.util.Collection;
-import java.util.List;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
  * @version $Id$
+ * @plexus.component role="org.apache.continuum.dao.ScheduleDao"
  */
-@Repository("scheduleDao")
+@Repository( "scheduleDao" )
 public class ScheduleDaoImpl
     extends AbstractDao
     implements ScheduleDao
diff --git a/continuum-store/src/main/java/org/apache/continuum/dao/StoreUtilities.java b/continuum-store/src/main/java/org/apache/continuum/dao/StoreUtilities.java
index 64b912e..cc4f7b6 100644
--- a/continuum-store/src/main/java/org/apache/continuum/dao/StoreUtilities.java
+++ b/continuum-store/src/main/java/org/apache/continuum/dao/StoreUtilities.java
@@ -28,14 +28,15 @@
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
  * @version $Id$
+ * @plexus.component role="org.apache.continuum.dao.StoreUtilities"
  */
-@Service("storeUtilities")
+@Service( "storeUtilities" )
 public class StoreUtilities
 {
     /**
      * @plexus.requirement role-hint="continuum"
      */
-    @Resource(name="jdoFactory#continuum")
+    @Resource( name = "jdoFactory#continuum" )
     private JdoFactory continuumJdoFactory;
 
     private PersistenceManagerFactory continuumPersistenceManagerFactory;
diff --git a/continuum-store/src/main/java/org/apache/continuum/dao/SystemConfigurationDaoImpl.java b/continuum-store/src/main/java/org/apache/continuum/dao/SystemConfigurationDaoImpl.java
index d0a0822..834ff36 100644
--- a/continuum-store/src/main/java/org/apache/continuum/dao/SystemConfigurationDaoImpl.java
+++ b/continuum-store/src/main/java/org/apache/continuum/dao/SystemConfigurationDaoImpl.java
@@ -28,8 +28,9 @@
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
  * @version $Id$
+ * @plexus.component role="org.apache.continuum.dao.SystemConfigurationDao"
  */
-@Repository("systemConfigurationDao")
+@Repository( "systemConfigurationDao" )
 public class SystemConfigurationDaoImpl
     extends AbstractDao
     implements SystemConfigurationDao
diff --git a/continuum-store/src/main/resources/META-INF/spring-context.xml b/continuum-store/src/main/resources/META-INF/spring-context.xml
index 8476316..52a7478 100644
--- a/continuum-store/src/main/resources/META-INF/spring-context.xml
+++ b/continuum-store/src/main/resources/META-INF/spring-context.xml
@@ -18,6 +18,7 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
   -->
+
 <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
@@ -26,6 +27,6 @@
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-2.5.xsd">
 
-  <context:annotation-config />
+  <context:annotation-config/>
   <context:component-scan base-package="org.apache.continuum.dao"/>
 </beans>
\ No newline at end of file
diff --git a/continuum-store/src/test/java/org/apache/maven/continuum/store/AbstractContinuumStoreTestCase.java b/continuum-store/src/test/java/org/apache/maven/continuum/store/AbstractContinuumStoreTestCase.java
index a2c2c29..6fe56ba 100644
--- a/continuum-store/src/test/java/org/apache/maven/continuum/store/AbstractContinuumStoreTestCase.java
+++ b/continuum-store/src/test/java/org/apache/maven/continuum/store/AbstractContinuumStoreTestCase.java
@@ -19,6 +19,8 @@
  * under the License.
  */
 
+import org.apache.continuum.dao.BuildDefinitionTemplateDao;
+import org.apache.continuum.dao.BuildQueueDao;
 import org.apache.continuum.dao.ContinuumReleaseResultDao;
 import org.apache.continuum.dao.DaoUtils;
 import org.apache.continuum.dao.DirectoryPurgeConfigurationDao;
@@ -38,6 +40,8 @@
 import org.apache.continuum.model.repository.RepositoryPurgeConfiguration;
 import org.apache.maven.continuum.installation.InstallationService;
 import org.apache.maven.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.BuildDefinitionTemplate;
+import org.apache.maven.continuum.model.project.BuildQueue;
 import org.apache.maven.continuum.model.project.BuildResult;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.project.ProjectDependency;
@@ -56,6 +60,8 @@
 import org.codehaus.plexus.spring.PlexusInSpringTestCase;
 
 import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -91,6 +97,10 @@
 
     protected ContinuumReleaseResultDao releaseResultDao;
 
+    protected BuildQueueDao buildQueueDao;
+
+    protected BuildDefinitionTemplateDao buildDefinitionTemplateDao;
+
     protected ProjectGroup defaultProjectGroup;
 
     protected ProjectGroup testProjectGroup2;
@@ -111,12 +121,16 @@
 
     protected Profile testProfile3;
 
+    protected Profile testProfile4;
+
     protected Installation testInstallationJava13;
 
     protected Installation testInstallationJava14;
 
     protected Installation testInstallationMaven20a3;
 
+    protected Installation testInstallationEnvVar;
+
     protected BuildResult testBuildResult1;
 
     protected BuildResult testBuildResult2;
@@ -141,6 +155,16 @@
 
     protected ProjectScmRoot testProjectScmRoot;
 
+    protected ContinuumReleaseResult testContinuumReleaseResult;
+
+    protected BuildQueue testBuildQueue1;
+
+    protected BuildQueue testBuildQueue2;
+
+    protected BuildQueue testBuildQueue3;
+
+    protected long baseTime;
+
     private SystemConfiguration systemConfiguration;
 
     @Override
@@ -151,13 +175,13 @@
 
         createStore();
 
-        directoryPurgeConfigurationDao =
-            (DirectoryPurgeConfigurationDao) lookup( DirectoryPurgeConfigurationDao.class.getName() );
+        directoryPurgeConfigurationDao = (DirectoryPurgeConfigurationDao) lookup(
+            DirectoryPurgeConfigurationDao.class.getName() );
 
         localRepositoryDao = (LocalRepositoryDao) lookup( LocalRepositoryDao.class.getName() );
 
-        repositoryPurgeConfigurationDao =
-            (RepositoryPurgeConfigurationDao) lookup( RepositoryPurgeConfigurationDao.class.getName() );
+        repositoryPurgeConfigurationDao = (RepositoryPurgeConfigurationDao) lookup(
+            RepositoryPurgeConfigurationDao.class.getName() );
 
         installationDao = (InstallationDao) lookup( InstallationDao.class.getName() );
 
@@ -174,15 +198,19 @@
         projectScmRootDao = (ProjectScmRootDao) lookup( ProjectScmRootDao.class.getName() );
 
         releaseResultDao = (ContinuumReleaseResultDao) lookup( ContinuumReleaseResultDao.class.getName() );
+
+        buildQueueDao = (BuildQueueDao) lookup( BuildQueueDao.class.getName() );
+
+        buildDefinitionTemplateDao = (BuildDefinitionTemplateDao) lookup( BuildDefinitionTemplateDao.class.getName() );
     }
 
-    protected void createBuildDatabase()
+    protected void createBuildDatabase( boolean isTestFromDataManagementTool )
         throws Exception
     {
-        createBuildDatabase( true );
+        createBuildDatabase( true, isTestFromDataManagementTool );
     }
 
-    protected void createBuildDatabase( boolean addToStore )
+    protected void createBuildDatabase( boolean addToStore, boolean isTestFromDataManagementTool )
         throws Exception
     {
         // Setting up test data
@@ -228,11 +256,53 @@
             testLocalRepository3.setId( 3 );
         }
 
+        testBuildQueue1 = createTestBuildQueue( "build queue 1" );
+
+        BuildQueue buildQueue1 = createTestBuildQueue( testBuildQueue1 );
+        if ( addToStore )
+        {
+            buildQueue1 = buildQueueDao.addBuildQueue( buildQueue1 );
+            testBuildQueue1.setId( buildQueue1.getId() );
+        }
+        else
+        {
+            buildQueue1.setId( 1 );
+            testBuildQueue1.setId( 1 );
+        }
+
+        testBuildQueue2 = createTestBuildQueue( "build queue 2" );
+
+        BuildQueue buildQueue2 = createTestBuildQueue( testBuildQueue2 );
+        if ( addToStore )
+        {
+            buildQueue2 = buildQueueDao.addBuildQueue( buildQueue2 );
+            testBuildQueue2.setId( buildQueue2.getId() );
+        }
+        else
+        {
+            buildQueue2.setId( 2 );
+            testBuildQueue2.setId( 2 );
+        }
+
+        testBuildQueue3 = createTestBuildQueue( "build queue 3" );
+
+        BuildQueue buildQueue3 = createTestBuildQueue( testBuildQueue3 );
+        if ( addToStore )
+        {
+            buildQueue3 = buildQueueDao.addBuildQueue( buildQueue3 );
+            testBuildQueue3.setId( buildQueue3.getId() );
+        }
+        else
+        {
+            buildQueue3.setId( 3 );
+            testBuildQueue3.setId( 3 );
+        }
+
         defaultProjectGroup = createTestProjectGroup( "Default Group", "The Default Group",
                                                       "org.apache.maven.test.default", localRepository1 );
 
-        testProjectGroup2 =
-            createTestProjectGroup( "test group 2", "test group 2 desc", "test group 2 groupId", localRepository2 );
+        testProjectGroup2 = createTestProjectGroup( "test group 2", "test group 2 desc", "test group 2 groupId",
+                                                    localRepository2 );
 
         testProject1 = createTestProject( "artifactId1", 1, "description1", defaultProjectGroup.getGroupId(), "name1",
                                           "scmUrl1", 1, "url1", "version1", "workingDirectory1" );
@@ -242,15 +312,23 @@
                                           "scmUrl2", 1, "url2", "version2", "workingDirectory2" );
 
         testSchedule1 = createTestSchedule( "name1", "description1", 1, "cronExpression1", true );
+        testSchedule1.addBuildQueue( buildQueue1 );
+        testSchedule1.addBuildQueue( buildQueue2 );
+
         testSchedule2 = createTestSchedule( "name2", "description2", 2, "cronExpression2", true );
+        testSchedule2.addBuildQueue( buildQueue2 );
+        testSchedule2.addBuildQueue( buildQueue3 );
+
         testSchedule3 = createTestSchedule( "name3", "description3", 3, "cronExpression3", true );
 
-        testInstallationJava13 =
-            createTestInstallation( "JDK 1.3", InstallationService.JDK_TYPE, "JAVA_HOME", "/usr/local/java-1.3" );
-        testInstallationJava14 =
-            createTestInstallation( "JDK 1.4", InstallationService.JDK_TYPE, "JAVA_HOME", "/usr/local/java-1.4" );
+        testInstallationJava13 = createTestInstallation( "JDK 1.3", InstallationService.JDK_TYPE, "JAVA_HOME",
+                                                         "/usr/local/java-1.3" );
+        testInstallationJava14 = createTestInstallation( "JDK 1.4", InstallationService.JDK_TYPE, "JAVA_HOME",
+                                                         "/usr/local/java-1.4" );
         testInstallationMaven20a3 = createTestInstallation( "Maven 2.0 alpha 3", InstallationService.MAVEN2_TYPE,
                                                             "M2_HOME", "/usr/local/maven-2.0-alpha-3" );
+        testInstallationEnvVar = createTestInstallation( "Maven Heap Size", InstallationService.ENVVAR_TYPE,
+                                                         "MAVEN_OPTS", "-Xms256m -Xmx256m" );
 
         ProjectNotifier testGroupNotifier1 = createTestNotifier( 1, true, false, true, "type1" );
         ProjectNotifier testGroupNotifier2 = createTestNotifier( 2, false, true, false, "type2" );
@@ -269,8 +347,16 @@
         ProjectDependency testDependency3 = createTestDependency( "groupId3", "artifactId3", "version3" );
 
         // TODO: simplify by deep copying the relationships in createTest... ?
-        long baseTime = System.currentTimeMillis();
-        testBuildResult1 = createTestBuildResult( 1, true, 1, 1, "error1", 1, baseTime, baseTime + 1000 );
+        baseTime = System.currentTimeMillis();
+
+        Calendar cal = Calendar.getInstance();
+        cal.setTime( new Date( baseTime ) );
+        cal.add( Calendar.DAY_OF_MONTH, 1 );
+
+        long newTime = cal.getTimeInMillis();
+
+        // successful forced build
+        testBuildResult1 = createTestBuildResult( 1, true, 2, 1, "error1", 1, baseTime, baseTime + 1000, "user" );
         BuildResult buildResult1 = createTestBuildResult( testBuildResult1 );
         ScmResult scmResult = createTestScmResult( "commandOutput1", "providerMessage1", true, "1" );
         buildResult1.setScmResult( scmResult );
@@ -281,11 +367,16 @@
         testProject1.setCheckoutResult( checkoutResult1 );
         testProject1.addBuildResult( buildResult1 );
 
-        testBuildResult2 = createTestBuildResult( 2, false, 2, 2, "error2", 2, baseTime + 2000, baseTime + 3000 );
+        // failed scheduled build
+        testBuildResult2 = createTestBuildResult( 2, false, 3, 2, "error2", 2, newTime, newTime + 3000, "schedule" );
         BuildResult buildResult2 = createTestBuildResult( testBuildResult2 );
         testProject1.addBuildResult( buildResult2 );
 
-        testBuildResult3 = createTestBuildResult( 3, true, 3, 3, "error3", 3, baseTime + 4000, baseTime + 5000 );
+        cal.add( Calendar.DAY_OF_MONTH, 2 );
+        newTime = cal.getTimeInMillis();
+
+        // successful scheduled build
+        testBuildResult3 = createTestBuildResult( 2, true, 2, 3, "error3", 3, newTime, newTime + 5000, "schedule" );
         BuildResult buildResult3 = createTestBuildResult( testBuildResult3 );
         scmResult = createTestScmResult( "commandOutput3", "providerMessage3", true, "3" );
         buildResult3.setScmResult( scmResult );
@@ -359,12 +450,25 @@
             installationJava13.setInstallationId( 3 );
         }
 
-        testProfile1 =
-            createTestProfile( "name1", "description1", 1, true, true, installationJava13, installationMaven20a3 );
-        testProfile2 =
-            createTestProfile( "name2", "description2", 2, false, true, installationJava14, installationMaven20a3 );
-        testProfile3 =
-            createTestProfile( "name3", "description3", 3, true, false, installationJava14, installationMaven20a3 );
+        Installation installationEnvVar = createTestInstallation( testInstallationEnvVar );
+        if ( addToStore )
+        {
+            installationEnvVar = installationDao.addInstallation( installationEnvVar );
+        }
+        else
+        {
+            installationEnvVar.setInstallationId( 4 );
+        }
+
+        testProfile1 = createTestProfile( "name1", "description1", 1, true, true, installationJava13,
+                                          installationMaven20a3 );
+        testProfile2 = createTestProfile( "name2", "description2", 2, false, true, installationJava14,
+                                          installationMaven20a3 );
+        testProfile3 = createTestProfile( "name3", "description3", 3, true, false, installationJava14,
+                                          installationMaven20a3 );
+        testProfile4 = createTestProfile( "name4", "description4", 4, false, false, installationJava14,
+                                          installationMaven20a3 );
+        testProfile4.addEnvironmentVariable( installationEnvVar );
 
         Profile profile1 = createTestProfile( testProfile1 );
         if ( addToStore )
@@ -399,71 +503,94 @@
             profile3.setId( 3 );
         }
 
-        testRepoPurgeConfiguration1 =
-            createTestRepositoryPurgeConfiguration( true, 5, 50, false, schedule2, true, localRepository1 );
+        Profile profile4 = createTestProfile( testProfile4 );
         if ( addToStore )
         {
-            testRepoPurgeConfiguration1 =
-                repositoryPurgeConfigurationDao.addRepositoryPurgeConfiguration( testRepoPurgeConfiguration1 );
+            profile4 = profileDao.addProfile( profile4 );
+            testProfile4.setId( profile4.getId() );
+        }
+        else
+        {
+            profile4.setId( 4 );
+        }
+
+        testRepoPurgeConfiguration1 = createTestRepositoryPurgeConfiguration( true, 5, 50, false, schedule2, true,
+                                                                              localRepository1 );
+        if ( addToStore )
+        {
+            testRepoPurgeConfiguration1 = repositoryPurgeConfigurationDao.addRepositoryPurgeConfiguration(
+                testRepoPurgeConfiguration1 );
         }
         else
         {
             testRepoPurgeConfiguration1.setId( 1 );
         }
 
-        testRepoPurgeConfiguration2 =
-            createTestRepositoryPurgeConfiguration( false, 10, 200, true, schedule1, true, localRepository2 );
+        testRepoPurgeConfiguration2 = createTestRepositoryPurgeConfiguration( false, 10, 200, true, schedule1, true,
+                                                                              localRepository2 );
         if ( addToStore )
         {
-            testRepoPurgeConfiguration2 =
-                repositoryPurgeConfigurationDao.addRepositoryPurgeConfiguration( testRepoPurgeConfiguration2 );
+            testRepoPurgeConfiguration2 = repositoryPurgeConfigurationDao.addRepositoryPurgeConfiguration(
+                testRepoPurgeConfiguration2 );
         }
         else
         {
             testRepoPurgeConfiguration2.setId( 2 );
         }
 
-        testRepoPurgeConfiguration3 =
-            createTestRepositoryPurgeConfiguration( false, 10, 200, true, schedule2, true, localRepository1 );
+        testRepoPurgeConfiguration3 = createTestRepositoryPurgeConfiguration( false, 10, 200, true, schedule2, true,
+                                                                              localRepository1 );
         if ( addToStore )
         {
-            testRepoPurgeConfiguration3 =
-                repositoryPurgeConfigurationDao.addRepositoryPurgeConfiguration( testRepoPurgeConfiguration3 );
+            testRepoPurgeConfiguration3 = repositoryPurgeConfigurationDao.addRepositoryPurgeConfiguration(
+                testRepoPurgeConfiguration3 );
         }
         else
         {
             testRepoPurgeConfiguration3.setId( 3 );
         }
 
-        testDirectoryPurgeConfig =
-            createTestDirectoryPurgeConfiguration( "location1", "directoryType1", true, 10, 50, schedule2, true );
+        testDirectoryPurgeConfig = createTestDirectoryPurgeConfiguration( "location1", "directoryType1", true, 10, 50,
+                                                                          schedule2, true );
         if ( addToStore )
         {
-            testDirectoryPurgeConfig =
-                directoryPurgeConfigurationDao.addDirectoryPurgeConfiguration( testDirectoryPurgeConfig );
+            testDirectoryPurgeConfig = directoryPurgeConfigurationDao.addDirectoryPurgeConfiguration(
+                testDirectoryPurgeConfig );
         }
         else
         {
             testDirectoryPurgeConfig.setId( 1 );
         }
 
-        BuildDefinition testGroupBuildDefinition1 =
-            createTestBuildDefinition( "arguments1", "buildFile1", "goals1", profile1, schedule2, false, false );
-        BuildDefinition testGroupBuildDefinition2 =
-            createTestBuildDefinition( "arguments2", "buildFile2", "goals2", profile1, schedule1, false, false );
-        BuildDefinition testGroupBuildDefinition3 =
-            createTestBuildDefinition( "arguments3", "buildFile3", "goals3", profile2, schedule1, false, false );
-        BuildDefinition testGroupBuildDefinition4 =
-            createTestBuildDefinition( null, null, "deploy", null, null, false, false );
+        BuildDefinition testGroupBuildDefinition1 = createTestBuildDefinition( "arguments1", "buildFile1", "goals1",
+                                                                               profile1, schedule2, false, false );
+        BuildDefinition testGroupBuildDefinition2 = createTestBuildDefinition( "arguments2", "buildFile2", "goals2",
+                                                                               profile1, schedule1, false, false );
+        BuildDefinition testGroupBuildDefinition3 = createTestBuildDefinition( "arguments3", "buildFile3", "goals3",
+                                                                               profile2, schedule1, false, false );
+        BuildDefinition testGroupBuildDefinition4 = createTestBuildDefinition( null, null, "deploy", null, null, false,
+                                                                               false );
 
-        BuildDefinition testBuildDefinition1 =
-            createTestBuildDefinition( "arguments11", "buildFile11", "goals11", profile2, schedule1, false, false );
-        BuildDefinition testBuildDefinition2 =
-            createTestBuildDefinition( "arguments12", "buildFile12", "goals12", profile2, schedule2, false, false );
-        BuildDefinition testBuildDefinition3 =
-            createTestBuildDefinition( "arguments13", "buildFile13", "goals13", profile1, schedule2, false, false );
-        BuildDefinition testBuildDefinition4 =
-            createTestBuildDefinition( null, null, "deploy", null, null, false, false );
+        BuildDefinition testBuildDefinition1 = createTestBuildDefinition( "arguments11", "buildFile11", "goals11",
+                                                                          profile2, schedule1, false, false );
+        BuildDefinition testBuildDefinition2 = createTestBuildDefinition( "arguments12", "buildFile12", "goals12",
+                                                                          profile2, schedule2, false, false );
+        BuildDefinition testBuildDefinition3 = createTestBuildDefinition( "arguments13", "buildFile13", "goals13",
+                                                                          profile1, schedule2, false, false );
+        BuildDefinition testBuildDefinition4 = createTestBuildDefinition( null, null, "deploy", null, null, false,
+                                                                          false );
+        BuildDefinition testBuildDefinition5 = createTestBuildDefinition( "arguments14", "buildFile14", "goals14",
+                                                                          profile1, schedule1, false, false );
+        testBuildDefinition5.setTemplate( true );
+
+        BuildDefinitionTemplate testBuildDefinitionTemplate1 = createTestBuildDefinitionTemplate( "template2", "type2",
+                                                                                                  false );
+        testBuildDefinitionTemplate1.addBuildDefinition( testBuildDefinition5 );
+
+        if ( addToStore )
+        {
+            buildDefinitionTemplateDao.addBuildDefinitionTemplate( testBuildDefinitionTemplate1 );
+        }
 
         ProjectGroup group = createTestProjectGroup( defaultProjectGroup );
 
@@ -541,7 +668,7 @@
 
         if ( addToStore )
         {
-            projectGroupDao.addProjectGroup( group );
+            group = projectGroupDao.addProjectGroup( group );
             defaultProjectGroup.setId( group.getId() );
             testProject1.setId( project1.getId() );
             testProject2.setId( project2.getId() );
@@ -582,6 +709,7 @@
         }
         else
         {
+            group.setId( 2 );
             testProjectGroup2.setId( 2 ); // from expected.xml, continuum-data-management
         }
 
@@ -595,16 +723,66 @@
         systemConfiguration.setInitialized( true );
         systemConfiguration.setWorkingDirectory( "workingDirectory" );
 
-        if ( addToStore )
+        if ( addToStore && !isTestFromDataManagementTool )
         {
             systemConfiguration = systemConfigurationDao.addSystemConfiguration( systemConfiguration );
         }
-        
+        else
+        {
+            // hack for DataManagementTool test
+            // data-management-jdo has a dependency to continuum-commons where DefaultConfigurationService
+            //      is located. DefaultConfiguration loads the data and already adds a system configuration, causing
+            //      this to throw an exception
+            boolean isExisting = false;
+            try
+            {
+                systemConfigurationDao.getSystemConfiguration();
+            }
+            catch ( ContinuumStoreException e )
+            {
+                isExisting = true;
+            }
+
+            if ( !isExisting )
+            {
+                systemConfiguration = systemConfigurationDao.getSystemConfiguration();
+                systemConfiguration.setBaseUrl( "baseUrl" );
+                systemConfiguration.setBuildOutputDirectory( "buildOutputDirectory" );
+                systemConfiguration.setDefaultScheduleCronExpression( "* * * * *" );
+                systemConfiguration.setDefaultScheduleDescription( "Description" );
+                systemConfiguration.setDeploymentRepositoryDirectory( "deployment" );
+                systemConfiguration.setGuestAccountEnabled( false );
+                systemConfiguration.setInitialized( true );
+                systemConfiguration.setWorkingDirectory( "workingDirectory" );
+
+                systemConfigurationDao.updateSystemConfiguration( systemConfiguration );
+            }
+        }
+
         testProjectScmRoot = createTestProjectScmRoot( "scmRootAddress1", 1, 0, "error1", group );
-        
+        ProjectScmRoot scmRoot = createTestProjectScmRoot( testProjectScmRoot );
+
         if ( addToStore )
         {
-            projectScmRootDao.addProjectScmRoot( testProjectScmRoot );
+            scmRoot = projectScmRootDao.addProjectScmRoot( scmRoot );
+            testProjectScmRoot.setId( scmRoot.getId() );
+        }
+        else
+        {
+            testProjectScmRoot.setId( 1 );
+        }
+
+        testContinuumReleaseResult = createTestContinuumReleaseResult( group, null, "releaseGoal", 0, 0, 0 );
+        ContinuumReleaseResult releaseResult = createTestContinuumReleaseResult( testContinuumReleaseResult );
+
+        if ( addToStore )
+        {
+            releaseResult = releaseResultDao.addContinuumReleaseResult( releaseResult );
+            testContinuumReleaseResult.setId( releaseResult.getId() );
+        }
+        else
+        {
+            testContinuumReleaseResult.setId( 1 );
         }
     }
 
@@ -788,8 +966,31 @@
         store.addProjectGroup( group );
         testProjectGroup2.setId( group.getId() );
 */
-
         assertSystemConfiguration( systemConfiguration, systemConfigurationDao.getSystemConfiguration() );
+
+        assertLocalRepositoryEquals( testLocalRepository1, localRepositoryDao.getLocalRepository(
+            testLocalRepository1.getId() ) );
+        assertLocalRepositoryEquals( testLocalRepository2, localRepositoryDao.getLocalRepository(
+            testLocalRepository2.getId() ) );
+        assertLocalRepositoryEquals( testLocalRepository3, localRepositoryDao.getLocalRepository(
+            testLocalRepository3.getId() ) );
+
+/*
+        assertRepositoryPurgeConfigurationEquals( testRepoPurgeConfiguration1,
+                                                  repositoryPurgeConfigurationDao.getRepositoryPurgeConfiguration( testRepoPurgeConfiguration1.getId() ) );
+        assertRepositoryPurgeConfigurationEquals( testRepoPurgeConfiguration2,
+                                                  repositoryPurgeConfigurationDao.getRepositoryPurgeConfiguration( testRepoPurgeConfiguration2.getId() ) );
+        assertRepositoryPurgeConfigurationEquals( testRepoPurgeConfiguration3,
+                                                  repositoryPurgeConfigurationDao.getRepositoryPurgeConfiguration( testRepoPurgeConfiguration3.getId() ) );
+
+        assertDirectoryPurgeConfigurationEquals( testDirectoryPurgeConfig, 
+                                                 directoryPurgeConfigurationDao.getDirectoryPurgeConfiguration( testDirectoryPurgeConfig.getId() ) );
+*/
+        assertProjectScmRootEquals( testProjectScmRoot, projectScmRootDao.getProjectScmRoot(
+            testProjectScmRoot.getId() ) );
+
+        assertReleaseResultEquals( testContinuumReleaseResult, releaseResultDao.getContinuumReleaseResult(
+            testContinuumReleaseResult.getId() ) );
     }
 
     private void assertSystemConfiguration( SystemConfiguration expected, SystemConfiguration actual )
@@ -805,22 +1006,25 @@
         assertEquals( expected.getWorkingDirectory(), actual.getWorkingDirectory() );
     }
 
-    protected void assertEmpty()
+    protected void assertEmpty( boolean isTestFromDataManagementTool )
         throws ContinuumStoreException
     {
         assertEquals( 0, installationDao.getAllInstallations().size() );
         assertEquals( 0, profileDao.getAllProfilesByName().size() );
         assertEquals( 0, projectGroupDao.getAllProjectGroups().size() );
         assertEquals( 0, projectDao.getAllProjectsByName().size() );
-        assertNull( systemConfigurationDao.getSystemConfiguration() );
+        if ( !isTestFromDataManagementTool )
+        {
+            assertNull( systemConfigurationDao.getSystemConfiguration() );
+        }
     }
 
     protected static BuildDefinition createTestBuildDefinition( BuildDefinition buildDefinition )
     {
         return createTestBuildDefinition( buildDefinition.getArguments(), buildDefinition.getBuildFile(),
-                                          buildDefinition.getGoals(), buildDefinition.getProfile(), buildDefinition
-            .getSchedule(), buildDefinition.isDefaultForProject(), buildDefinition
-            .isBuildFresh() );
+                                          buildDefinition.getGoals(), buildDefinition.getProfile(),
+                                          buildDefinition.getSchedule(), buildDefinition.isDefaultForProject(),
+                                          buildDefinition.isBuildFresh() );
     }
 
     protected static BuildDefinition createTestBuildDefinition( String arguments, String buildFile, String goals,
@@ -909,11 +1113,12 @@
     {
         return createTestBuildResult( buildResult.getTrigger(), buildResult.isSuccess(), buildResult.getState(),
                                       buildResult.getExitCode(), buildResult.getError(), buildResult.getBuildNumber(),
-                                      buildResult.getStartTime(), buildResult.getEndTime() );
+                                      buildResult.getStartTime(), buildResult.getEndTime(), buildResult.getUsername() );
     }
 
     private static BuildResult createTestBuildResult( int trigger, boolean success, int state, int exitCode,
-                                                      String error, int buildNumber, long startTime, long endTime )
+                                                      String error, int buildNumber, long startTime, long endTime,
+                                                      String triggeredBy )
     {
         BuildResult result = new BuildResult();
         result.setBuildNumber( buildNumber );
@@ -924,6 +1129,7 @@
         result.setState( state );
         result.setSuccess( success );
         result.setTrigger( trigger );
+        result.setUsername( triggeredBy );
         return result;
     }
 
@@ -945,29 +1151,35 @@
 
     protected static Schedule createTestSchedule( Schedule schedule )
     {
-        return createTestSchedule( schedule.getName(), schedule.getDescription(), schedule.getDelay(), schedule
-            .getCronExpression(), schedule.isActive() );
+        return createTestSchedule( schedule.getName(), schedule.getDescription(), schedule.getDelay(),
+                                   schedule.getCronExpression(), schedule.isActive(), schedule.getBuildQueues() );
     }
 
     protected static Schedule createTestSchedule( String name, String description, int delay, String cronExpression,
                                                   boolean active )
     {
+        return createTestSchedule( name, description, delay, cronExpression, active, null );
+    }
+
+    protected static Schedule createTestSchedule( String name, String description, int delay, String cronExpression,
+                                                  boolean active, List<BuildQueue> buildQueues )
+    {
         Schedule schedule = new Schedule();
         schedule.setActive( active );
         schedule.setCronExpression( cronExpression );
         schedule.setDelay( delay );
         schedule.setDescription( description );
         schedule.setName( name );
+        schedule.setBuildQueues( buildQueues );
+
         return schedule;
     }
 
     protected static Profile createTestProfile( Profile profile )
     {
-        return createTestProfile( profile.getName(), profile.getDescription(), profile.getScmMode(), profile
-            .isBuildWithoutChanges(), profile.isActive(), profile.getJdk(), profile.getBuilder(),
-                                      profile.getEnvironmentVariables() );
-//                                  createTestInstallation( profile.getJdk() ),
-//                                  createTestInstallation( profile.getBuilder() ) );
+        return createTestProfile( profile.getName(), profile.getDescription(), profile.getScmMode(),
+                                  profile.isBuildWithoutChanges(), profile.isActive(), profile.getJdk(),
+                                  profile.getBuilder(), profile.getEnvironmentVariables() );
     }
 
     protected static Profile createTestProfile( String name, String description, int scmMode,
@@ -1012,14 +1224,14 @@
 
     protected static Project createTestProject( Project project )
     {
-        return createTestProject( project.getArtifactId(), project.getBuildNumber(), project.getDescription(), project
-            .getGroupId(), project.getName(), project.getScmUrl(), project.getState(), project.getUrl(), project
-            .getVersion(), project.getWorkingDirectory() );
+        return createTestProject( project.getArtifactId(), project.getBuildNumber(), project.getDescription(),
+                                  project.getGroupId(), project.getName(), project.getScmUrl(), project.getState(),
+                                  project.getUrl(), project.getVersion(), project.getWorkingDirectory() );
     }
 
-    private static Project createTestProject( String artifactId, int buildNumber, String description, String groupId,
-                                              String name, String scmUrl, int state, String url, String version,
-                                              String workingDirectory )
+    protected static Project createTestProject( String artifactId, int buildNumber, String description, String groupId,
+                                                String name, String scmUrl, int state, String url, String version,
+                                                String workingDirectory )
     {
         Project project = new Project();
         project.setArtifactId( artifactId );
@@ -1045,14 +1257,14 @@
         assertEquals( "compare expectedProject - groupId", expectedProject.getGroupId(), project.getGroupId() );
         assertEquals( "compare expectedProject - artifactId", expectedProject.getArtifactId(),
                       project.getArtifactId() );
-        assertEquals( "compare expectedProject - buildNumber", expectedProject.getBuildNumber(), project
-            .getBuildNumber() );
+        assertEquals( "compare expectedProject - buildNumber", expectedProject.getBuildNumber(),
+                      project.getBuildNumber() );
         assertEquals( "compare expectedProject - scmUrl", expectedProject.getScmUrl(), project.getScmUrl() );
         assertEquals( "compare expectedProject - state", expectedProject.getState(), project.getState() );
         assertEquals( "compare expectedProject - url", expectedProject.getUrl(), project.getUrl() );
         assertEquals( "compare expectedProject - version", expectedProject.getVersion(), project.getVersion() );
-        assertEquals( "compare expectedProject - workingDirectory", expectedProject.getWorkingDirectory(), project
-            .getWorkingDirectory() );
+        assertEquals( "compare expectedProject - workingDirectory", expectedProject.getWorkingDirectory(),
+                      project.getWorkingDirectory() );
     }
 
     protected static void assertProjectGroupEquals( ProjectGroup expectedGroup, ProjectGroup actualGroup )
@@ -1076,8 +1288,8 @@
             assertEquals( "compare schedule - desc", expectedSchedule.getDescription(),
                           actualSchedule.getDescription() );
             assertEquals( "compare schedule - delay", expectedSchedule.getDelay(), actualSchedule.getDelay() );
-            assertEquals( "compare schedule - cron", expectedSchedule.getCronExpression(), actualSchedule
-                .getCronExpression() );
+            assertEquals( "compare schedule - cron", expectedSchedule.getCronExpression(),
+                          actualSchedule.getCronExpression() );
             assertEquals( "compare schedule - active", expectedSchedule.isActive(), actualSchedule.isActive() );
         }
     }
@@ -1091,8 +1303,8 @@
             assertEquals( "compare profile - name", expectedProfile.getName(), actualProfile.getName() );
             assertEquals( "compare profile - desc", expectedProfile.getDescription(), actualProfile.getDescription() );
             assertEquals( "compare profile - scmMode", expectedProfile.getScmMode(), actualProfile.getScmMode() );
-            assertEquals( "compare profile - build w/o changes", expectedProfile.isBuildWithoutChanges(), actualProfile
-                .isBuildWithoutChanges() );
+            assertEquals( "compare profile - build w/o changes", expectedProfile.isBuildWithoutChanges(),
+                          actualProfile.isBuildWithoutChanges() );
             assertEquals( "compare profile - active", expectedProfile.isActive(), actualProfile.isActive() );
         }
     }
@@ -1124,8 +1336,8 @@
         assertEquals( "compare SCM result - changes size", actual.getChanges().size(), expected.getChanges().size() );
         for ( int i = 0; i < actual.getChanges().size(); i++ )
         {
-            assertChangeSetEquals( (ChangeSet) expected.getChanges().get( i ),
-                                   (ChangeSet) actual.getChanges().get( i ) );
+            assertChangeSetEquals( (ChangeSet) expected.getChanges().get( i ), (ChangeSet) actual.getChanges().get(
+                i ) );
         }
     }
 
@@ -1138,8 +1350,8 @@
         assertEquals( "compare change set result - files size", expected.getFiles().size(), actual.getFiles().size() );
         for ( int i = 0; i < actual.getFiles().size(); i++ )
         {
-            assertChangeFileEquals( (ChangeFile) expected.getFiles().get( i ),
-                                    (ChangeFile) actual.getFiles().get( i ) );
+            assertChangeFileEquals( (ChangeFile) expected.getFiles().get( i ), (ChangeFile) actual.getFiles().get(
+                i ) );
         }
     }
 
@@ -1187,8 +1399,8 @@
                       actualBuildDefinition.getArguments() );
         assertEquals( "compare build definition - build file", expectedBuildDefinition.getBuildFile(),
                       actualBuildDefinition.getBuildFile() );
-        assertEquals( "compare build definition - goals", expectedBuildDefinition.getGoals(), actualBuildDefinition
-            .getGoals() );
+        assertEquals( "compare build definition - goals", expectedBuildDefinition.getGoals(),
+                      actualBuildDefinition.getGoals() );
         assertEquals( "compare build definition - build fresh", expectedBuildDefinition.isBuildFresh(),
                       actualBuildDefinition.isBuildFresh() );
         assertEquals( "compare build definition - defaultForProject", expectedBuildDefinition.isDefaultForProject(),
@@ -1200,8 +1412,7 @@
     {
         for ( int i = 0; i < actualDevelopers.size(); i++ )
         {
-            assertDeveloperEquals( expectedDevelopers.get( i ), actualDevelopers
-                .get( i ) );
+            assertDeveloperEquals( expectedDevelopers.get( i ), actualDevelopers.get( i ) );
         }
     }
 
@@ -1210,8 +1421,8 @@
         assertEquals( "compare developer - name", expectedDeveloper.getName(), actualDeveloper.getName() );
         assertEquals( "compare developer - email", expectedDeveloper.getEmail(), actualDeveloper.getEmail() );
         assertEquals( "compare developer - scmId", expectedDeveloper.getScmId(), actualDeveloper.getScmId() );
-        assertEquals( "compare developer - continuumId", expectedDeveloper.getContinuumId(), actualDeveloper
-            .getContinuumId() );
+        assertEquals( "compare developer - continuumId", expectedDeveloper.getContinuumId(),
+                      actualDeveloper.getContinuumId() );
     }
 
     protected static void assertDependenciesEqual( List<ProjectDependency> expectedDependencies,
@@ -1227,8 +1438,8 @@
                                                   ProjectDependency actualDependency )
     {
         assertEquals( "compare dependency - groupId", expectedDependency.getGroupId(), actualDependency.getGroupId() );
-        assertEquals( "compare dependency - artifactId", expectedDependency.getArtifactId(), actualDependency
-            .getArtifactId() );
+        assertEquals( "compare dependency - artifactId", expectedDependency.getArtifactId(),
+                      actualDependency.getArtifactId() );
         assertEquals( "compare dependency - version", expectedDependency.getVersion(), actualDependency.getVersion() );
     }
 
@@ -1239,8 +1450,8 @@
 
     protected static ProjectDeveloper createTestDeveloper( ProjectDeveloper developer )
     {
-        return createTestDeveloper( developer.getContinuumId(), developer.getEmail(), developer.getName(), developer
-            .getScmId() );
+        return createTestDeveloper( developer.getContinuumId(), developer.getEmail(), developer.getName(),
+                                    developer.getScmId() );
     }
 
     protected static ProjectDependency createTestDependency( String groupId, String artifactId, String version )
@@ -1382,32 +1593,38 @@
         assertEquals( "compare directory purge configuration - enabled", expectedConfig.isEnabled(),
                       actualConfig.isEnabled() );
     }
-    
+
     protected static ProjectScmRoot createTestProjectScmRoot( String scmRootAddress, int state, int oldState,
                                                               String error, ProjectGroup group )
     {
         ProjectScmRoot projectScmRoot = new ProjectScmRoot();
-        
+
         projectScmRoot.setScmRootAddress( scmRootAddress );
         projectScmRoot.setState( state );
         projectScmRoot.setOldState( oldState );
         projectScmRoot.setError( error );
         projectScmRoot.setProjectGroup( group );
-        
+
         return projectScmRoot;
     }
 
+    protected static ProjectScmRoot createTestProjectScmRoot( ProjectScmRoot scmRoot )
+    {
+        return createTestProjectScmRoot( scmRoot.getScmRootAddress(), scmRoot.getState(), scmRoot.getOldState(),
+                                         scmRoot.getError(), scmRoot.getProjectGroup() );
+    }
+
     protected static void assertProjectScmRootEquals( ProjectScmRoot expectedConfig, ProjectScmRoot actualConfig )
     {
         assertEquals( "compare project scm root - id", expectedConfig.getId(), actualConfig.getId() );
-        assertEquals( "compare project scm root - scmUrl", expectedConfig.getScmRootAddress(), 
-                                                           actualConfig.getScmRootAddress() );
+        assertEquals( "compare project scm root - scmUrl", expectedConfig.getScmRootAddress(),
+                      actualConfig.getScmRootAddress() );
         assertEquals( "compare project scm root - state", expectedConfig.getState(), actualConfig.getState() );
         assertEquals( "compare project scm root - oldState", expectedConfig.getOldState(), actualConfig.getOldState() );
         assertEquals( "compare project scm root - error", expectedConfig.getError(), actualConfig.getError() );
     }
 
-    protected static ContinuumReleaseResult createTestContinuumReleaseResult( ProjectGroup group, Project project, 
+    protected static ContinuumReleaseResult createTestContinuumReleaseResult( ProjectGroup group, Project project,
                                                                               String releaseGoal, int resultCode,
                                                                               long startTime, long endTime )
     {
@@ -1418,24 +1635,61 @@
         releaseResult.setResultCode( resultCode );
         releaseResult.setStartTime( startTime );
         releaseResult.setEndTime( endTime );
-        
+
         return releaseResult;
     }
-    
-    protected static void assertReleaseResultEquals( ContinuumReleaseResult expectedConfig, 
+
+    protected static ContinuumReleaseResult createTestContinuumReleaseResult( ContinuumReleaseResult releaseResult )
+    {
+        return createTestContinuumReleaseResult( releaseResult.getProjectGroup(), releaseResult.getProject(),
+                                                 releaseResult.getReleaseGoal(), releaseResult.getResultCode(),
+                                                 releaseResult.getStartTime(), releaseResult.getEndTime() );
+    }
+
+    protected static void assertReleaseResultEquals( ContinuumReleaseResult expectedConfig,
                                                      ContinuumReleaseResult actualConfig )
     {
         assertEquals( "compare continuum release result - id", expectedConfig.getId(), actualConfig.getId() );
         assertEquals( "compare continuum release result - releaseGoal", expectedConfig.getReleaseGoal(),
                       actualConfig.getReleaseGoal() );
-        assertEquals( "compare continuum release result - resultCode", expectedConfig.getResultCode(), 
+        assertEquals( "compare continuum release result - resultCode", expectedConfig.getResultCode(),
                       actualConfig.getResultCode() );
-        assertEquals( "compare continuum release result - startTime", expectedConfig.getStartTime(), 
+        assertEquals( "compare continuum release result - startTime", expectedConfig.getStartTime(),
                       actualConfig.getStartTime() );
         assertEquals( "compare continuum release result - endTime", expectedConfig.getEndTime(),
                       actualConfig.getEndTime() );
     }
-    
+
+    protected static BuildQueue createTestBuildQueue( String name )
+    {
+        BuildQueue buildQueue = new BuildQueue();
+        buildQueue.setName( name );
+
+        return buildQueue;
+    }
+
+    protected static BuildQueue createTestBuildQueue( BuildQueue buildQueue )
+    {
+        return createTestBuildQueue( buildQueue.getName() );
+    }
+
+    protected static void assertBuildQueueEquals( BuildQueue expectedConfig, BuildQueue actualConfig )
+    {
+        assertEquals( "compare build queue - id", expectedConfig.getId(), actualConfig.getId() );
+        assertEquals( "compare build queue - name", expectedConfig.getName(), actualConfig.getName() );
+    }
+
+    protected static BuildDefinitionTemplate createTestBuildDefinitionTemplate( String name, String type,
+                                                                                boolean continuumDefault )
+    {
+        BuildDefinitionTemplate template = new BuildDefinitionTemplate();
+        template.setName( name );
+        template.setType( type );
+        template.setContinuumDefault( continuumDefault );
+
+        return template;
+    }
+
     /**
      * Setup JDO Factory
      *
@@ -1444,8 +1698,8 @@
     protected void createStore()
         throws Exception
     {
-        DefaultConfigurableJdoFactory jdoFactory =
-            (DefaultConfigurableJdoFactory) lookup( JdoFactory.ROLE, "continuum" );
+        DefaultConfigurableJdoFactory jdoFactory = (DefaultConfigurableJdoFactory) lookup( JdoFactory.ROLE,
+                                                                                           "continuum" );
 
         jdoFactory.setUrl( "jdbc:hsqldb:mem:" + getName() );
 
diff --git a/continuum-store/src/test/java/org/apache/maven/continuum/store/ContinuumStoreTest.java b/continuum-store/src/test/java/org/apache/maven/continuum/store/ContinuumStoreTest.java
index fa4fee6..a08617a 100644
--- a/continuum-store/src/test/java/org/apache/maven/continuum/store/ContinuumStoreTest.java
+++ b/continuum-store/src/test/java/org/apache/maven/continuum/store/ContinuumStoreTest.java
@@ -22,6 +22,7 @@
 import org.apache.continuum.dao.BuildDefinitionDao;
 import org.apache.continuum.dao.BuildDefinitionTemplateDao;
 import org.apache.continuum.dao.BuildResultDao;
+import org.apache.continuum.model.project.ProjectGroupSummary;
 import org.apache.continuum.model.project.ProjectScmRoot;
 import org.apache.continuum.model.release.ContinuumReleaseResult;
 import org.apache.continuum.model.repository.DirectoryPurgeConfiguration;
@@ -31,6 +32,7 @@
 import org.apache.maven.continuum.installation.InstallationService;
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.BuildDefinitionTemplate;
+import org.apache.maven.continuum.model.project.BuildQueue;
 import org.apache.maven.continuum.model.project.BuildResult;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.project.ProjectDependency;
@@ -41,12 +43,15 @@
 import org.apache.maven.continuum.model.system.Installation;
 import org.apache.maven.continuum.model.system.Profile;
 
-import javax.jdo.JDODetachedFieldAccessException;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Calendar;
 import java.util.Collection;
+import java.util.Date;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
+import javax.jdo.JDODetachedFieldAccessException;
 
 /**
  * @author <a href="mailto:brett@apache.org">Brett Porter</a>
@@ -96,20 +101,20 @@
         assertProjectGroupEquals( defaultProjectGroup, retrievedGroup );
         assertLocalRepositoryEquals( testLocalRepository1, retrievedGroup.getLocalRepository() );
 
-        List projects = retrievedGroup.getProjects();
+        List<Project> projects = retrievedGroup.getProjects();
         assertEquals( "Check number of projects", 2, projects.size() );
         assertTrue( "Check existence of project 1", projects.contains( testProject1 ) );
         assertTrue( "Check existence of project 2", projects.contains( testProject2 ) );
 
         checkProjectGroupDefaultFetchGroup( retrievedGroup );
 
-        Project project = (Project) projects.get( 0 );
+        Project project = projects.get( 0 );
         checkProjectDefaultFetchGroup( project );
         //assertSame( "Check project group reference matches", project.getProjectGroup(), retrievedGroup );
         assertEquals( project.getProjectGroup().getId(), retrievedGroup.getId() );
         assertProjectEquals( testProject1, project );
 
-        project = (Project) projects.get( 1 );
+        project = projects.get( 1 );
         checkProjectDefaultFetchGroup( project );
         //assertSame( "Check project group reference matches", project.getProjectGroup(), retrievedGroup );
         assertEquals( project.getProjectGroup().getId(), retrievedGroup.getId() );
@@ -170,16 +175,15 @@
 
     public void testGetAllProjectGroups()
     {
-        Collection groups = projectGroupDao.getAllProjectGroupsWithProjects();
+        Collection<ProjectGroup> groups = projectGroupDao.getAllProjectGroupsWithProjects();
 
         assertEquals( "check size", 2, groups.size() );
         assertTrue( groups.contains( defaultProjectGroup ) );
         assertTrue( groups.contains( testProjectGroup2 ) );
 
-        for ( Iterator i = groups.iterator(); i.hasNext(); )
+        for ( ProjectGroup group : groups )
         {
-            ProjectGroup group = (ProjectGroup) i.next();
-            List projects = group.getProjects();
+            List<Project> projects = group.getProjects();
             if ( group.getId() == testProjectGroup2.getId() )
             {
                 assertProjectGroupEquals( testProjectGroup2, group );
@@ -196,7 +200,7 @@
 
                 checkProjectGroupDefaultFetchGroup( group );
 
-                Project p = (Project) projects.get( 0 );
+                Project p = projects.get( 0 );
                 checkProjectDefaultFetchGroup( p );
                 assertSame( "Check project group reference matches", p.getProjectGroup(), group );
             }
@@ -287,83 +291,111 @@
 
     public void testGetAllProjects()
     {
-        List projects = projectDao.getAllProjectsByName();
-        assertEquals( "check items", Arrays.asList( new Project[]{testProject1, testProject2} ), projects );
+        List<Project> projects = projectDao.getAllProjectsByName();
+        assertEquals( "check items", Arrays.asList( testProject1, testProject2 ), projects );
 
-        Project project = (Project) projects.get( 1 );
+        Project project = projects.get( 1 );
         assertProjectEquals( testProject2, project );
         checkProjectDefaultFetchGroup( project );
         assertNotNull( "Check project group reference matches", project.getProjectGroup() );
     }
 
     public void testAddSchedule()
+        throws ContinuumStoreException
     {
+        BuildQueue buildQueue = buildQueueDao.getAllBuildQueues().get( 0 );
+
         Schedule newSchedule = createTestSchedule( "testAddSchedule", "testAddSchedule desc", 10, "cron test", false );
+        newSchedule.addBuildQueue( buildQueue );
+
         Schedule copy = createTestSchedule( newSchedule );
         scheduleDao.addSchedule( newSchedule );
         copy.setId( newSchedule.getId() );
 
-        List schedules = scheduleDao.getAllSchedulesByName();
-        Schedule retrievedSchedule = (Schedule) schedules.get( schedules.size() - 1 );
+        List<Schedule> schedules = scheduleDao.getAllSchedulesByName();
+        Schedule retrievedSchedule = schedules.get( schedules.size() - 1 );
         assertScheduleEquals( copy, retrievedSchedule );
+        assertEquals( "check size of build queues", 1, retrievedSchedule.getBuildQueues().size() );
+        assertBuildQueueEquals( buildQueue, retrievedSchedule.getBuildQueues().get( 0 ) );
     }
 
     public void testEditSchedule()
         throws ContinuumStoreException
     {
-        Schedule newSchedule = (Schedule) scheduleDao.getAllSchedulesByName().get( 0 );
+        Schedule newSchedule = scheduleDao.getAllSchedulesByName().get( 0 );
         newSchedule.setName( "name1.1" );
         newSchedule.setDescription( "testEditSchedule updated description" );
 
+        assertEquals( "check size of build queues", 2, newSchedule.getBuildQueues().size() );
+        BuildQueue buildQueue1 = newSchedule.getBuildQueues().get( 0 );
+        BuildQueue buildQueue2 = newSchedule.getBuildQueues().get( 1 );
+
         Schedule copy = createTestSchedule( newSchedule );
         copy.setId( newSchedule.getId() );
         scheduleDao.updateSchedule( newSchedule );
 
-        Schedule retrievedSchedule = (Schedule) scheduleDao.getAllSchedulesByName().get( 0 );
+        Schedule retrievedSchedule = scheduleDao.getAllSchedulesByName().get( 0 );
         assertScheduleEquals( copy, retrievedSchedule );
+        assertBuildQueueEquals( buildQueue1, retrievedSchedule.getBuildQueues().get( 0 ) );
+        assertBuildQueueEquals( buildQueue2, retrievedSchedule.getBuildQueues().get( 1 ) );
     }
 
     public void testRemoveSchedule()
     {
-        Schedule schedule = (Schedule) scheduleDao.getAllSchedulesByName().get( 2 );
+        Schedule schedule = scheduleDao.getAllSchedulesByName().get( 2 );
 
         // TODO: test if it has any attachments
-
+        assertEquals( "check size of build queues", 0, schedule.getBuildQueues().size() );
         scheduleDao.removeSchedule( schedule );
 
-        List schedules = scheduleDao.getAllSchedulesByName();
+        List<Schedule> schedules = scheduleDao.getAllSchedulesByName();
         assertEquals( "check size", 2, schedules.size() );
         assertFalse( "check not there", schedules.contains( schedule ) );
     }
 
     public void testGetAllSchedules()
+        throws ContinuumStoreException
     {
-        List schedules = scheduleDao.getAllSchedulesByName();
+        List<Schedule> schedules = scheduleDao.getAllSchedulesByName();
+        List<BuildQueue> buildQueues = buildQueueDao.getAllBuildQueues();
 
         assertEquals( "check item count", 3, schedules.size() );
+        assertEquals( "check build queues count", 3, buildQueues.size() );
+
+        BuildQueue buildQueue1 = buildQueues.get( 0 );
+        BuildQueue buildQueue2 = buildQueues.get( 1 );
+        BuildQueue buildQueue3 = buildQueues.get( 2 );
 
         // check equality and order
-        Schedule schedule = (Schedule) schedules.get( 0 );
+        Schedule schedule = schedules.get( 0 );
         assertScheduleEquals( testSchedule1, schedule );
-        schedule = (Schedule) schedules.get( 1 );
+        assertEquals( "check size of buildQueues", 2, schedule.getBuildQueues().size() );
+        assertBuildQueueEquals( buildQueue1, schedule.getBuildQueues().get( 0 ) );
+        assertBuildQueueEquals( buildQueue2, schedule.getBuildQueues().get( 1 ) );
+
+        schedule = schedules.get( 1 );
         assertScheduleEquals( testSchedule2, schedule );
-        schedule = (Schedule) schedules.get( 2 );
+        assertEquals( "check size of buildQueues", 2, schedule.getBuildQueues().size() );
+        assertBuildQueueEquals( buildQueue2, schedule.getBuildQueues().get( 0 ) );
+        assertBuildQueueEquals( buildQueue3, schedule.getBuildQueues().get( 1 ) );
+
+        schedule = schedules.get( 2 );
         assertScheduleEquals( testSchedule3, schedule );
+        assertEquals( "check size of buildQueues", 0, schedule.getBuildQueues().size() );
     }
 
     public void testAddProfile()
         throws Exception
     {
-        List installations = installationDao.getAllInstallations();
+        List<Installation> installations = installationDao.getAllInstallations();
         Profile newProfile = createTestProfile( "testAddProfile", "testAddProfile desc", 5, false, false,
-                                                (Installation) installations.get( 1 ), (Installation) installations
-            .get( 2 ) );
+                                                installations.get( 1 ), installations.get( 2 ) );
         Profile copy = createTestProfile( newProfile );
         profileDao.addProfile( newProfile );
         copy.setId( newProfile.getId() );
 
-        List profiles = profileDao.getAllProfilesByName();
-        Profile retrievedProfile = (Profile) profiles.get( profiles.size() - 1 );
+        List<Profile> profiles = profileDao.getAllProfilesByName();
+        Profile retrievedProfile = profiles.get( profiles.size() - 1 );
         assertProfileEquals( copy, retrievedProfile );
         assertInstallationEquals( testInstallationMaven20a3, retrievedProfile.getBuilder() );
         assertInstallationEquals( testInstallationJava14, retrievedProfile.getJdk() );
@@ -372,7 +404,7 @@
     public void testEditProfile()
         throws ContinuumStoreException
     {
-        Profile newProfile = (Profile) profileDao.getAllProfilesByName().get( 0 );
+        Profile newProfile = profileDao.getAllProfilesByName().get( 0 );
         newProfile.setName( "name1.1" );
         newProfile.setDescription( "testEditProfile updated description" );
 
@@ -380,7 +412,7 @@
         copy.setId( newProfile.getId() );
         profileDao.updateProfile( newProfile );
 
-        Profile retrievedProfile = (Profile) profileDao.getAllProfilesByName().get( 0 );
+        Profile retrievedProfile = profileDao.getAllProfilesByName().get( 0 );
         assertProfileEquals( copy, retrievedProfile );
         assertInstallationEquals( copy.getBuilder(), retrievedProfile.getBuilder() );
         assertInstallationEquals( copy.getJdk(), retrievedProfile.getJdk() );
@@ -389,36 +421,43 @@
 
     public void testRemoveProfile()
     {
-        Profile profile = (Profile) profileDao.getAllProfilesByName().get( 2 );
+        Profile profile = profileDao.getAllProfilesByName().get( 2 );
 
         // TODO: test if it has any attachments
 
         profileDao.removeProfile( profile );
 
-        List profiles = profileDao.getAllProfilesByName();
-        assertEquals( "check size", 2, profiles.size() );
+        List<Profile> profiles = profileDao.getAllProfilesByName();
+        assertEquals( "check size", 3, profiles.size() );
         assertFalse( "check not there", profiles.contains( profile ) );
     }
 
     public void testGetAllProfiles()
     {
-        List profiles = profileDao.getAllProfilesByName();
+        List<Profile> profiles = profileDao.getAllProfilesByName();
 
-        assertEquals( "check item count", 3, profiles.size() );
+        assertEquals( "check item count", 4, profiles.size() );
 
         // check equality and order
-        Profile profile = (Profile) profiles.get( 0 );
+        Profile profile = profiles.get( 0 );
         assertProfileEquals( testProfile1, profile );
         assertInstallationEquals( testProfile1.getBuilder(), profile.getBuilder() );
         assertInstallationEquals( testProfile1.getJdk(), profile.getJdk() );
-        profile = (Profile) profiles.get( 1 );
+        profile = profiles.get( 1 );
         assertProfileEquals( testProfile2, profile );
         assertInstallationEquals( testProfile2.getBuilder(), profile.getBuilder() );
         assertInstallationEquals( testProfile2.getJdk(), profile.getJdk() );
-        profile = (Profile) profiles.get( 2 );
+        profile = profiles.get( 2 );
         assertProfileEquals( testProfile3, profile );
         assertInstallationEquals( testProfile3.getBuilder(), profile.getBuilder() );
         assertInstallationEquals( testProfile3.getJdk(), profile.getJdk() );
+        profile = profiles.get( 3 );
+        assertProfileEquals( testProfile4, profile );
+        assertInstallationEquals( testProfile4.getBuilder(), profile.getBuilder() );
+        assertInstallationEquals( testProfile4.getJdk(), profile.getJdk() );
+        assertEquals( "check env var count", 1, profile.getEnvironmentVariables().size() );
+        assertInstallationEquals( testProfile4.getEnvironmentVariables().get( 0 ),
+                                  profile.getEnvironmentVariables().get( 0 ) );
     }
 
     /*
@@ -432,17 +471,19 @@
     public void testGetAllInstallations()
         throws Exception
     {
-        List installations = installationDao.getAllInstallations();
+        List<Installation> installations = installationDao.getAllInstallations();
 
-        assertEquals( "check item count", 3, installations.size() );
+        assertEquals( "check item count", 4, installations.size() );
 
         // check equality and order
-        Installation installation = (Installation) installations.get( 0 );
+        Installation installation = installations.get( 0 );
         assertInstallationEquals( testInstallationJava13, installation );
-        installation = (Installation) installations.get( 1 );
+        installation = installations.get( 1 );
         assertInstallationEquals( testInstallationJava14, installation );
-        installation = (Installation) installations.get( 2 );
+        installation = installations.get( 2 );
         assertInstallationEquals( testInstallationMaven20a3, installation );
+        installation = installations.get( 3 );
+        assertInstallationEquals( testInstallationEnvVar, installation );
     }
 
     public void testUpdateInstallation()
@@ -484,17 +525,17 @@
         String nameFirstEnvVar = "firstEnvVar";
         String nameSecondEnvVar = "secondEnvVar";
 
-        Installation testOne =
-            createTestInstallation( nameFirstInst, InstallationService.JDK_TYPE, "varName", "varValue" );
+        Installation testOne = createTestInstallation( nameFirstInst, InstallationService.JDK_TYPE, "varName",
+                                                       "varValue" );
 
-        Installation testTwo =
-            createTestInstallation( nameSecondInst, InstallationService.MAVEN2_TYPE, "varName", "varValue" );
+        Installation testTwo = createTestInstallation( nameSecondInst, InstallationService.MAVEN2_TYPE, "varName",
+                                                       "varValue" );
 
-        Installation firstEnvVar =
-            createTestInstallation( nameFirstEnvVar, InstallationService.MAVEN2_TYPE, "varName", "varValue" );
+        Installation firstEnvVar = createTestInstallation( nameFirstEnvVar, InstallationService.MAVEN2_TYPE, "varName",
+                                                           "varValue" );
 
-        Installation secondEnvVar =
-            createTestInstallation( nameSecondEnvVar, InstallationService.MAVEN2_TYPE, "varName", "varValue" );
+        Installation secondEnvVar = createTestInstallation( nameSecondEnvVar, InstallationService.MAVEN2_TYPE,
+                                                            "varName", "varValue" );
 
         testOne = installationDao.addInstallation( testOne );
         testTwo = installationDao.addInstallation( testTwo );
@@ -571,14 +612,14 @@
         assertNull( firstGetted.getJdk() );
         assertNull( firstGetted.getBuilder() );
         assertEquals( 1, firstGetted.getEnvironmentVariables().size() );
-        Installation env = (Installation) firstGetted.getEnvironmentVariables().get( 0 );
+        Installation env = firstGetted.getEnvironmentVariables().get( 0 );
         assertEquals( nameSecondEnvVar, env.getName() );
 
         assertNotNull( secondGetted );
         assertNull( secondGetted.getJdk() );
         assertNull( secondGetted.getBuilder() );
         assertEquals( 1, secondGetted.getEnvironmentVariables().size() );
-        env = (Installation) secondGetted.getEnvironmentVariables().get( 0 );
+        env = secondGetted.getEnvironmentVariables().get( 0 );
         assertEquals( nameSecondEnvVar, env.getName() );
 
         // removing secondEnvVar
@@ -605,7 +646,7 @@
 
         ProjectGroup projectGroup = projectGroupDao.getProjectGroupWithProjects( defaultProjectGroup.getId() );
         assertEquals( "check size is now 1", 1, projectGroup.getProjects().size() );
-        assertProjectEquals( testProject2, (Project) projectGroup.getProjects().get( 0 ) );
+        assertProjectEquals( testProject2, projectGroup.getProjects().get( 0 ) );
 
         confirmProjectDeletion( testProject1 );
     }
@@ -636,9 +677,9 @@
     {
         Project project = projectDao.getProjectWithBuilds( testProject1.getId() );
 
-        for ( Iterator i = project.getBuildResults().iterator(); i.hasNext(); )
+        for ( Iterator<BuildResult> i = project.getBuildResults().iterator(); i.hasNext(); )
         {
-            BuildResult result = (BuildResult) i.next();
+            BuildResult result = i.next();
             if ( result.getId() == testBuildResult1.getId() )
             {
                 i.remove();
@@ -648,11 +689,11 @@
 
         project = projectDao.getProjectWithBuilds( testProject1.getId() );
         assertEquals( "check size is now 1", 1, project.getBuildResults().size() );
-        assertBuildResultEquals( testBuildResult2, (BuildResult) project.getBuildResults().get( 0 ) );
+        assertBuildResultEquals( testBuildResult2, project.getBuildResults().get( 0 ) );
 
-        List results = buildResultDao.getAllBuildsForAProjectByDate( testProject1.getId() );
+        List<BuildResult> results = buildResultDao.getAllBuildsForAProjectByDate( testProject1.getId() );
         assertEquals( "check item count", 1, results.size() );
-        assertBuildResultEquals( testBuildResult2, (BuildResult) results.get( 0 ) );
+        assertBuildResultEquals( testBuildResult2, results.get( 0 ) );
 
         // !! These actually aren't happening !!
         // TODO: test the build result was physically deleted
@@ -676,16 +717,16 @@
 
     public void testGetAllBuildsForAProject()
     {
-        List results = buildResultDao.getAllBuildsForAProjectByDate( testProject1.getId() );
+        List<BuildResult> results = buildResultDao.getAllBuildsForAProjectByDate( testProject1.getId() );
 
         assertEquals( "check item count", 2, results.size() );
 
         // check equality and order
-        BuildResult buildResult = (BuildResult) results.get( 0 );
+        BuildResult buildResult = results.get( 0 );
         assertBuildResultEquals( testBuildResult2, buildResult );
         assertProjectEquals( testProject1, buildResult.getProject() );
         //checkBuildResultDefaultFetchGroup( buildResult );
-        buildResult = (BuildResult) results.get( 1 );
+        buildResult = results.get( 1 );
         assertBuildResultEquals( testBuildResult1, buildResult );
         assertProjectEquals( testProject1, buildResult.getProject() );
         //checkBuildResultDefaultFetchGroup( buildResult );
@@ -704,17 +745,16 @@
     public void testGetProjectGroupWithDetails()
         throws ContinuumStoreException
     {
-        ProjectGroup retrievedGroup =
-            projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId( defaultProjectGroup
-                .getId() );
+        ProjectGroup retrievedGroup = projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId(
+            defaultProjectGroup.getId() );
         assertProjectGroupEquals( defaultProjectGroup, retrievedGroup );
         assertNotifiersEqual( defaultProjectGroup.getNotifiers(), retrievedGroup.getNotifiers() );
         assertBuildDefinitionsEqual( retrievedGroup.getBuildDefinitions(), defaultProjectGroup.getBuildDefinitions() );
 
-        List projects = retrievedGroup.getProjects();
+        List<Project> projects = retrievedGroup.getProjects();
         assertEquals( "Check number of projects", 2, projects.size() );
 
-        Project project = (Project) projects.get( 0 );
+        Project project = projects.get( 0 );
         checkProjectFetchGroup( project, false, false, true, false );
         //assertSame( "Check project group reference matches", project.getProjectGroup(), retrievedGroup );
         assertEquals( project.getProjectGroup().getId(), retrievedGroup.getId() );
@@ -722,7 +762,7 @@
         assertNotifiersEqual( testProject1.getNotifiers(), project.getNotifiers() );
         assertBuildDefinitionsEqual( project.getBuildDefinitions(), testProject1.getBuildDefinitions() );
 
-        project = (Project) projects.get( 1 );
+        project = projects.get( 1 );
         checkProjectFetchGroup( project, false, false, true, false );
         //assertSame( "Check project group reference matches", project.getProjectGroup(), retrievedGroup );
         assertEquals( project.getProjectGroup().getId(), retrievedGroup.getId() );
@@ -733,27 +773,27 @@
 
     public void testGetAllProjectsGroupWithDetails()
     {
-        List projectGroups = projectGroupDao.getAllProjectGroupsWithBuildDetails();
-        ProjectGroup group1 = (ProjectGroup) projectGroups.get( 0 );
+        List<ProjectGroup> projectGroups = projectGroupDao.getAllProjectGroupsWithBuildDetails();
+        ProjectGroup group1 = projectGroups.get( 0 );
         assertProjectGroupEquals( defaultProjectGroup, group1 );
         assertNotifiersEqual( defaultProjectGroup.getNotifiers(), group1.getNotifiers() );
         assertBuildDefinitionsEqual( group1.getBuildDefinitions(), defaultProjectGroup.getBuildDefinitions() );
-        ProjectGroup group2 = (ProjectGroup) projectGroups.get( 1 );
+        ProjectGroup group2 = projectGroups.get( 1 );
         assertProjectGroupEquals( testProjectGroup2, group2 );
         assertNotifiersEqual( testProjectGroup2.getNotifiers(), group2.getNotifiers() );
         assertBuildDefinitionsEqual( group2.getBuildDefinitions(), testProjectGroup2.getBuildDefinitions() );
 
-        List projects = group1.getProjects();
+        List<Project> projects = group1.getProjects();
         assertEquals( "Check number of projects", 2, projects.size() );
 
-        Project project = (Project) projects.get( 0 );
+        Project project = projects.get( 0 );
         checkProjectFetchGroup( project, false, false, true, false );
         assertSame( "Check project group reference matches", project.getProjectGroup(), group1 );
         assertProjectEquals( testProject1, project );
         assertNotifiersEqual( testProject1.getNotifiers(), project.getNotifiers() );
         assertBuildDefinitionsEqual( project.getBuildDefinitions(), testProject1.getBuildDefinitions() );
 
-        project = (Project) projects.get( 1 );
+        project = projects.get( 1 );
         checkProjectFetchGroup( project, false, false, true, false );
         assertSame( "Check project group reference matches", project.getProjectGroup(), group1 );
         assertProjectEquals( testProject2, project );
@@ -776,7 +816,7 @@
 
         project = projectDao.getProjectWithAllDetails( testProject1.getId() );
         assertEquals( "check # devs", 2, project.getDevelopers().size() );
-        assertDeveloperEquals( copy, (ProjectDeveloper) project.getDevelopers().get( 1 ) );
+        assertDeveloperEquals( copy, project.getDevelopers().get( 1 ) );
     }
 
     public void testEditDeveloper()
@@ -784,7 +824,7 @@
     {
         Project project = projectDao.getProjectWithAllDetails( testProject1.getId() );
 
-        ProjectDeveloper newDeveloper = (ProjectDeveloper) project.getDevelopers().get( 0 );
+        ProjectDeveloper newDeveloper = project.getDevelopers().get( 0 );
         newDeveloper.setName( "name1.1" );
         newDeveloper.setEmail( "email1.1" );
 
@@ -793,7 +833,7 @@
 
         project = projectDao.getProjectWithAllDetails( testProject1.getId() );
         assertEquals( "check # devs", 1, project.getDevelopers().size() );
-        assertDeveloperEquals( copy, (ProjectDeveloper) project.getDevelopers().get( 0 ) );
+        assertDeveloperEquals( copy, project.getDevelopers().get( 0 ) );
     }
 
     public void testDeleteDeveloper()
@@ -822,7 +862,7 @@
 
         project = projectDao.getProjectWithAllDetails( testProject1.getId() );
         assertEquals( "check # deps", 3, project.getDependencies().size() );
-        assertDependencyEquals( copy, (ProjectDependency) project.getDependencies().get( 2 ) );
+        assertDependencyEquals( copy, project.getDependencies().get( 2 ) );
     }
 
     public void testEditDependency()
@@ -830,7 +870,7 @@
     {
         Project project = projectDao.getProjectWithAllDetails( testProject1.getId() );
 
-        ProjectDependency newDependency = (ProjectDependency) project.getDependencies().get( 0 );
+        ProjectDependency newDependency = project.getDependencies().get( 0 );
         newDependency.setGroupId( "groupId1.1" );
         newDependency.setArtifactId( "artifactId1.1" );
 
@@ -839,20 +879,20 @@
 
         project = projectDao.getProjectWithAllDetails( testProject1.getId() );
         assertEquals( "check # deps", 2, project.getDependencies().size() );
-        assertDependencyEquals( copy, (ProjectDependency) project.getDependencies().get( 0 ) );
+        assertDependencyEquals( copy, project.getDependencies().get( 0 ) );
     }
 
     public void testDeleteDependency()
         throws ContinuumStoreException
     {
         Project project = projectDao.getProjectWithAllDetails( testProject1.getId() );
-        ProjectDependency dependency = (ProjectDependency) project.getDependencies().get( 1 );
+        ProjectDependency dependency = project.getDependencies().get( 1 );
         project.getDependencies().remove( 0 );
         projectDao.updateProject( project );
 
         project = projectDao.getProjectWithAllDetails( testProject1.getId() );
         assertEquals( "check size is now 1", 1, project.getDependencies().size() );
-        assertDependencyEquals( dependency, (ProjectDependency) project.getDependencies().get( 0 ) );
+        assertDependencyEquals( dependency, project.getDependencies().get( 0 ) );
 
         // !! These actually aren't happening !!
         // TODO: test the dependency was physically deleted
@@ -870,7 +910,7 @@
 
         project = projectDao.getProjectWithAllDetails( testProject1.getId() );
         assertEquals( "check # notifiers", 2, project.getNotifiers().size() );
-        assertNotifierEquals( copy, (ProjectNotifier) project.getNotifiers().get( 1 ) );
+        assertNotifierEquals( copy, project.getNotifiers().get( 1 ) );
     }
 
     public void testEditNotifier()
@@ -878,7 +918,7 @@
     {
         Project project = projectDao.getProjectWithAllDetails( testProject1.getId() );
 
-        ProjectNotifier newNotifier = (ProjectNotifier) project.getNotifiers().get( 0 );
+        ProjectNotifier newNotifier = project.getNotifiers().get( 0 );
         // If we use "type1.1", jpox-rc2 store "type11", weird
         String type = "type11";
         newNotifier.setType( type );
@@ -888,7 +928,7 @@
 
         project = projectDao.getProjectWithAllDetails( testProject1.getId() );
         assertEquals( "check # notifiers", 1, project.getNotifiers().size() );
-        assertNotifierEquals( copy, (ProjectNotifier) project.getNotifiers().get( 0 ) );
+        assertNotifierEquals( copy, project.getNotifiers().get( 0 ) );
     }
 
     public void testDeleteNotifier()
@@ -920,7 +960,7 @@
 
         project = projectDao.getProjectWithAllDetails( testProject1.getId() );
         assertEquals( "check # build defs", 3, project.getBuildDefinitions().size() );
-        BuildDefinition retrievedBuildDefinition = (BuildDefinition) project.getBuildDefinitions().get( 2 );
+        BuildDefinition retrievedBuildDefinition = project.getBuildDefinitions().get( 2 );
         assertBuildDefinitionEquals( copy, retrievedBuildDefinition );
         assertScheduleEquals( testSchedule1, retrievedBuildDefinition.getSchedule() );
         assertProfileEquals( testProfile1, retrievedBuildDefinition.getProfile() );
@@ -931,18 +971,18 @@
     {
         Project project = projectDao.getProjectWithAllDetails( testProject1.getId() );
 
-        BuildDefinition newBuildDefinition = (BuildDefinition) project.getBuildDefinitions().get( 0 );
+        BuildDefinition newBuildDefinition = project.getBuildDefinitions().get( 0 );
         newBuildDefinition.setBuildFresh( true );
         new BuildDefinition().setDefaultForProject( true );
         String arguments = "arguments1.1";
         newBuildDefinition.setArguments( arguments );
-
         BuildDefinition copy = createTestBuildDefinition( newBuildDefinition );
         buildDefinitionDao.storeBuildDefinition( newBuildDefinition );
 
         project = projectDao.getProjectWithAllDetails( testProject1.getId() );
         assertEquals( "check # build defs", 2, project.getBuildDefinitions().size() );
-        BuildDefinition retrievedBuildDefinition = (BuildDefinition) project.getBuildDefinitions().get( 0 );
+        BuildDefinition retrievedBuildDefinition = project.getBuildDefinitions().get( 0 );
+
         assertBuildDefinitionEquals( copy, retrievedBuildDefinition );
         assertScheduleEquals( testSchedule1, retrievedBuildDefinition.getSchedule() );
         assertProfileEquals( testProfile2, retrievedBuildDefinition.getProfile() );
@@ -952,13 +992,13 @@
         throws ContinuumStoreException
     {
         Project project = projectDao.getProjectWithAllDetails( testProject1.getId() );
-        BuildDefinition buildDefinition = (BuildDefinition) project.getBuildDefinitions().get( 1 );
+        BuildDefinition buildDefinition = project.getBuildDefinitions().get( 1 );
         project.getBuildDefinitions().remove( 0 );
         projectDao.updateProject( project );
 
         project = projectDao.getProjectWithAllDetails( testProject1.getId() );
         assertEquals( "check size is now 1", 1, project.getBuildDefinitions().size() );
-        BuildDefinition retrievedBuildDefinition = (BuildDefinition) project.getBuildDefinitions().get( 0 );
+        BuildDefinition retrievedBuildDefinition = project.getBuildDefinitions().get( 0 );
         assertBuildDefinitionEquals( buildDefinition, retrievedBuildDefinition );
         assertScheduleEquals( testSchedule2, retrievedBuildDefinition.getSchedule() );
         assertProfileEquals( testProfile2, retrievedBuildDefinition.getProfile() );
@@ -971,8 +1011,8 @@
     public void testAddNotifierToProjectGroup()
         throws ContinuumStoreException
     {
-        ProjectGroup projectGroup =
-            projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId( defaultProjectGroup.getId() );
+        ProjectGroup projectGroup = projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId(
+            defaultProjectGroup.getId() );
 
         ProjectNotifier notifier = createTestNotifier( 14, true, false, true, "TADNTPG type" );
         ProjectNotifier copy = createTestNotifier( notifier );
@@ -981,16 +1021,16 @@
 
         projectGroup = projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId( defaultProjectGroup.getId() );
         assertEquals( "check # notifiers", 3, projectGroup.getNotifiers().size() );
-        assertNotifierEquals( copy, (ProjectNotifier) projectGroup.getNotifiers().get( 2 ) );
+        assertNotifierEquals( copy, projectGroup.getNotifiers().get( 2 ) );
     }
 
     public void testEditGroupNotifier()
         throws ContinuumStoreException
     {
-        ProjectGroup projectGroup =
-            projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId( defaultProjectGroup.getId() );
+        ProjectGroup projectGroup = projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId(
+            defaultProjectGroup.getId() );
 
-        ProjectNotifier newNotifier = (ProjectNotifier) projectGroup.getNotifiers().get( 0 );
+        ProjectNotifier newNotifier = projectGroup.getNotifiers().get( 0 );
         // If we use "type1.1", jpox-rc2 store "type1", weird
         String type = "type1";
         newNotifier.setType( type );
@@ -1000,21 +1040,21 @@
 
         projectGroup = projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId( defaultProjectGroup.getId() );
         assertEquals( "check # notifiers", 2, projectGroup.getNotifiers().size() );
-        assertNotifierEquals( copy, (ProjectNotifier) projectGroup.getNotifiers().get( 0 ) );
+        assertNotifierEquals( copy, projectGroup.getNotifiers().get( 0 ) );
     }
 
     public void testDeleteGroupNotifier()
         throws ContinuumStoreException
     {
-        ProjectGroup projectGroup =
-            projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId( defaultProjectGroup.getId() );
-        ProjectNotifier notifier = (ProjectNotifier) projectGroup.getNotifiers().get( 1 );
+        ProjectGroup projectGroup = projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId(
+            defaultProjectGroup.getId() );
+        ProjectNotifier notifier = projectGroup.getNotifiers().get( 1 );
         projectGroup.getNotifiers().remove( 0 );
         projectGroupDao.updateProjectGroup( projectGroup );
 
         projectGroup = projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId( defaultProjectGroup.getId() );
         assertEquals( "check size is now 1", 1, projectGroup.getNotifiers().size() );
-        assertNotifierEquals( notifier, (ProjectNotifier) projectGroup.getNotifiers().get( 0 ) );
+        assertNotifierEquals( notifier, projectGroup.getNotifiers().get( 0 ) );
 
         // !! These actually aren't happening !!
         // TODO: test the notifier was physically deleted
@@ -1023,8 +1063,8 @@
     public void testAddBuildDefinitionToProjectGroup()
         throws ContinuumStoreException
     {
-        ProjectGroup projectGroup =
-            projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId( defaultProjectGroup.getId() );
+        ProjectGroup projectGroup = projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId(
+            defaultProjectGroup.getId() );
 
         Profile profile = profileDao.getProfile( testProfile1.getId() );
         Schedule schedule = scheduleDao.getSchedule( testSchedule1.getId() );
@@ -1036,7 +1076,7 @@
 
         projectGroup = projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId( defaultProjectGroup.getId() );
         assertEquals( "check # build defs", 2, projectGroup.getBuildDefinitions().size() );
-        BuildDefinition retrievedBuildDefinition = (BuildDefinition) projectGroup.getBuildDefinitions().get( 1 );
+        BuildDefinition retrievedBuildDefinition = projectGroup.getBuildDefinitions().get( 1 );
         assertBuildDefinitionEquals( copy, retrievedBuildDefinition );
         assertScheduleEquals( testSchedule1, retrievedBuildDefinition.getSchedule() );
         assertProfileEquals( testProfile1, retrievedBuildDefinition.getProfile() );
@@ -1045,10 +1085,11 @@
     public void testEditGroupBuildDefinition()
         throws ContinuumStoreException
     {
-        ProjectGroup projectGroup =
-            projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId( defaultProjectGroup.getId() );
+        ProjectGroup projectGroup = projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId(
+            defaultProjectGroup.getId() );
 
-        BuildDefinition newBuildDefinition = (BuildDefinition) projectGroup.getBuildDefinitions().get( 0 );
+        BuildDefinition newBuildDefinition = projectGroup.getBuildDefinitions().get( 0 );
+
         // If we use "arguments1.1", jpox-rc2 store "arguments11", weird
         String arguments = "arguments1";
         newBuildDefinition.setArguments( arguments );
@@ -1058,7 +1099,7 @@
 
         projectGroup = projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId( defaultProjectGroup.getId() );
         assertEquals( "check # build defs", 1, projectGroup.getBuildDefinitions().size() );
-        BuildDefinition retrievedBuildDefinition = (BuildDefinition) projectGroup.getBuildDefinitions().get( 0 );
+        BuildDefinition retrievedBuildDefinition = projectGroup.getBuildDefinitions().get( 0 );
         assertBuildDefinitionEquals( copy, retrievedBuildDefinition );
         assertScheduleEquals( testSchedule2, retrievedBuildDefinition.getSchedule() );
         assertProfileEquals( testProfile1, retrievedBuildDefinition.getProfile() );
@@ -1067,8 +1108,8 @@
     public void testDeleteGroupBuildDefinition()
         throws ContinuumStoreException
     {
-        ProjectGroup projectGroup =
-            projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId( defaultProjectGroup.getId() );
+        ProjectGroup projectGroup = projectGroupDao.getProjectGroupWithBuildDetailsByProjectGroupId(
+            defaultProjectGroup.getId() );
         projectGroup.getBuildDefinitions().remove( 0 );
         projectGroupDao.updateProjectGroup( projectGroup );
 
@@ -1104,15 +1145,15 @@
         assertTrue( template.isContinuumDefault() );
         assertEquals( 1, template.getBuildDefinitions().size() );
         assertEquals( all + 1, buildDefinitionDao.getAllBuildDefinitions().size() );
-        assertEquals( 1, buildDefinitionTemplateDao.getAllBuildDefinitionTemplate().size() );
+        assertEquals( 2, buildDefinitionTemplateDao.getAllBuildDefinitionTemplate().size() );
 
-        template = buildDefinitionTemplateDao
-            .getContinuumBuildDefinitionTemplateWithType( ContinuumBuildExecutorConstants.MAVEN_TWO_BUILD_EXECUTOR );
+        template = buildDefinitionTemplateDao.getContinuumBuildDefinitionTemplateWithType(
+            ContinuumBuildExecutorConstants.MAVEN_TWO_BUILD_EXECUTOR );
 
         assertNotNull( template );
         assertEquals( 1, template.getBuildDefinitions().size() );
 
-        assertEquals( 1, buildDefinitionTemplateDao.getAllBuildDefinitionTemplate().size() );
+        assertEquals( 2, buildDefinitionTemplateDao.getAllBuildDefinitionTemplate().size() );
     }
 
     public void testAddLocalRepository()
@@ -1141,7 +1182,6 @@
         assertLocalRepositoryEquals( testLocalRepository2, projectGroup.getLocalRepository() );
         projectGroup.setLocalRepository( null );
 
-        ProjectGroup copy = createTestProjectGroup( projectGroup );
         projectGroupDao.updateProjectGroup( projectGroup );
 
         projectGroup = projectGroupDao.getProjectGroup( testProjectGroup2.getId() );
@@ -1176,15 +1216,15 @@
         LocalRepository repository = localRepositoryDao.getLocalRepository( testLocalRepository3.getId() );
         Schedule schedule = scheduleDao.getSchedule( testSchedule1.getId() );
 
-        RepositoryPurgeConfiguration repoPurge =
-            createTestRepositoryPurgeConfiguration( true, 2, 100, false, schedule, true, repository );
+        RepositoryPurgeConfiguration repoPurge = createTestRepositoryPurgeConfiguration( true, 2, 100, false, schedule,
+                                                                                         true, repository );
 
         RepositoryPurgeConfiguration copy = createTestRepositoryPurgeConfiguration( repoPurge );
         repositoryPurgeConfigurationDao.addRepositoryPurgeConfiguration( repoPurge );
         copy.setId( repoPurge.getId() );
 
-        RepositoryPurgeConfiguration retrieved =
-            repositoryPurgeConfigurationDao.getRepositoryPurgeConfiguration( repoPurge.getId() );
+        RepositoryPurgeConfiguration retrieved = repositoryPurgeConfigurationDao.getRepositoryPurgeConfiguration(
+            repoPurge.getId() );
         assertRepositoryPurgeConfigurationEquals( copy, retrieved );
         assertLocalRepositoryEquals( testLocalRepository3, retrieved.getRepository() );
         assertScheduleEquals( testSchedule1, retrieved.getSchedule() );
@@ -1193,8 +1233,8 @@
     public void testRemoveRepositoryPurgeConfiguration()
         throws Exception
     {
-        RepositoryPurgeConfiguration repoPurge =
-            repositoryPurgeConfigurationDao.getRepositoryPurgeConfiguration( testRepoPurgeConfiguration2.getId() );
+        RepositoryPurgeConfiguration repoPurge = repositoryPurgeConfigurationDao.getRepositoryPurgeConfiguration(
+            testRepoPurgeConfiguration2.getId() );
         repositoryPurgeConfigurationDao.removeRepositoryPurgeConfiguration( repoPurge );
 
         List<RepositoryPurgeConfiguration> repoPurgeList =
@@ -1210,15 +1250,15 @@
         String directoryType = "release";
 
         Schedule schedule = scheduleDao.getSchedule( testSchedule1.getId() );
-        DirectoryPurgeConfiguration dirPurge =
-            createTestDirectoryPurgeConfiguration( location, directoryType, false, 2, 100, schedule, true );
+        DirectoryPurgeConfiguration dirPurge = createTestDirectoryPurgeConfiguration( location, directoryType, false, 2,
+                                                                                      100, schedule, true );
 
         DirectoryPurgeConfiguration copy = createTestDirectoryPurgeConfiguration( dirPurge );
         directoryPurgeConfigurationDao.addDirectoryPurgeConfiguration( dirPurge );
         copy.setId( dirPurge.getId() );
 
-        DirectoryPurgeConfiguration retrieved =
-            directoryPurgeConfigurationDao.getDirectoryPurgeConfiguration( dirPurge.getId() );
+        DirectoryPurgeConfiguration retrieved = directoryPurgeConfigurationDao.getDirectoryPurgeConfiguration(
+            dirPurge.getId() );
         assertDirectoryPurgeConfigurationEquals( copy, retrieved );
         assertScheduleEquals( testSchedule1, retrieved.getSchedule() );
     }
@@ -1226,8 +1266,8 @@
     public void testRemoveDirectoryPurgeConfiguration()
         throws Exception
     {
-        DirectoryPurgeConfiguration dirPurge =
-            directoryPurgeConfigurationDao.getDirectoryPurgeConfiguration( testDirectoryPurgeConfig.getId() );
+        DirectoryPurgeConfiguration dirPurge = directoryPurgeConfigurationDao.getDirectoryPurgeConfiguration(
+            testDirectoryPurgeConfig.getId() );
         directoryPurgeConfigurationDao.removeDirectoryPurgeConfiguration( dirPurge );
 
         List<DirectoryPurgeConfiguration> dirPurgeList =
@@ -1256,17 +1296,17 @@
     {
         ProjectGroup projectGroup = projectGroupDao.getProjectGroup( testProjectGroup2.getId() );
         ProjectScmRoot projectScmRoot = createTestProjectScmRoot( "scmRootAddress", 1, 0, "", projectGroup );
-        
+
         projectScmRoot = projectScmRootDao.addProjectScmRoot( projectScmRoot );
-        
-        List<ProjectScmRoot> projectScmRoots = 
-            projectScmRootDao.getProjectScmRootByProjectGroup( projectGroup.getId() );
-        
+
+        List<ProjectScmRoot> projectScmRoots = projectScmRootDao.getProjectScmRootByProjectGroup(
+            projectGroup.getId() );
+
         assertEquals( "check # of project scm root", 2, projectScmRoots.size() );
-        
-        ProjectScmRoot retrievedProjectScmRoot = 
-            projectScmRootDao.getProjectScmRootByProjectGroupAndScmRootAddress( projectGroup.getId(), "scmRootAddress" );
-        
+
+        ProjectScmRoot retrievedProjectScmRoot = projectScmRootDao.getProjectScmRootByProjectGroupAndScmRootAddress(
+            projectGroup.getId(), "scmRootAddress" );
+
         assertProjectScmRootEquals( projectScmRoot, retrievedProjectScmRoot );
         assertProjectGroupEquals( projectScmRoot.getProjectGroup(), retrievedProjectScmRoot.getProjectGroup() );
     }
@@ -1275,44 +1315,129 @@
         throws Exception
     {
         ProjectGroup projectGroup = projectGroupDao.getProjectGroup( testProjectGroup2.getId() );
-        
-        List<ProjectScmRoot> projectScmRoots = 
-            projectScmRootDao.getProjectScmRootByProjectGroup( projectGroup.getId() );
-        
+
+        List<ProjectScmRoot> projectScmRoots = projectScmRootDao.getProjectScmRootByProjectGroup(
+            projectGroup.getId() );
+
         assertEquals( "check # of project scm root", 1, projectScmRoots.size() );
-        
+
         ProjectScmRoot projectScmRoot = projectScmRoots.get( 0 );
         projectScmRootDao.removeProjectScmRoot( projectScmRoot );
-        
-        projectScmRoots = 
-            projectScmRootDao.getProjectScmRootByProjectGroup( projectGroup.getId() );
-        
+
+        projectScmRoots = projectScmRootDao.getProjectScmRootByProjectGroup( projectGroup.getId() );
+
         assertEquals( "check # of project scm root", 0, projectScmRoots.size() );
     }
 
-	public void testRemoveProjectWithReleaseResult()
+    public void testRemoveProjectWithReleaseResult()
         throws Exception
     {
         Project project = projectDao.getProject( testProject1.getId() );
         ProjectGroup group = project.getProjectGroup();
-        
-        ContinuumReleaseResult releaseResult = createTestContinuumReleaseResult( group, project, "releaseGoal", 0, 0, 0 );
+
+        ContinuumReleaseResult releaseResult = createTestContinuumReleaseResult( group, project, "releaseGoal", 0, 0,
+                                                                                 0 );
         releaseResult = releaseResultDao.addContinuumReleaseResult( releaseResult );
-        
+
         List<ContinuumReleaseResult> releaseResults = releaseResultDao.getAllContinuumReleaseResults();
-        assertEquals( "check size of continuum release results", 1, releaseResults.size() );
-        
-        ContinuumReleaseResult retrievedResult = releaseResults.get( 0 );
+        assertEquals( "check size of continuum release results", 2, releaseResults.size() );
+
+        ContinuumReleaseResult retrievedResult = releaseResults.get( 1 );
         assertReleaseResultEquals( releaseResult, retrievedResult );
         assertProjectGroupEquals( group, retrievedResult.getProjectGroup() );
         assertProjectEquals( project, retrievedResult.getProject() );
-        
+
         releaseResultDao.removeContinuumReleaseResult( releaseResult );
         projectDao.removeProject( project );
         assertFalse( projectDao.getProjectsInGroup( group.getId() ).contains( project ) );
-        
+
         releaseResults = releaseResultDao.getAllContinuumReleaseResults();
-        assertEquals( "check size of continuum release results", 0, releaseResults.size() );
+        assertEquals( "check size of continuum release results", 1, releaseResults.size() );
+    }
+
+    public void testGetProjectSummaryByProjectGroup()
+        throws Exception
+    {
+        List<Project> projects = projectDao.getProjectsInGroup( defaultProjectGroup.getId() );
+        assertEquals( 2, projects.size() );
+
+        Project project = projects.get( 0 );
+        project.setState( 2 );
+        projectDao.updateProject( project );
+
+        project = projects.get( 1 );
+        project.setState( 2 );
+        projectDao.updateProject( project );
+
+        ProjectGroup newGroup = projectGroupDao.getProjectGroupWithProjects( testProjectGroup2.getId() );
+        Project project1 = createTestProject( testProject1 );
+        project1.setState( 4 );
+        newGroup.addProject( project1 );
+
+        Project project2 = createTestProject( testProject2 );
+        project2.setState( 1 );
+        newGroup.addProject( project2 );
+        projectGroupDao.updateProjectGroup( newGroup );
+
+        Map<Integer, ProjectGroupSummary> summaries = projectDao.getProjectsSummary();
+
+        assertNotNull( summaries );
+        assertEquals( "check size of project summaries", 2, summaries.size() );
+
+        ProjectGroupSummary summary = summaries.get( testProjectGroup2.getId() );
+        assertEquals( "check id of project group", testProjectGroup2.getId(), summary.getProjectGroupId() );
+        assertEquals( "check number of errors", 1, summary.getNumberOfErrors() );
+        assertEquals( "check number of successes", 0, summary.getNumberOfSuccesses() );
+        assertEquals( "check number of failures", 0, summary.getNumberOfFailures() );
+        assertEquals( "check number of projects", 2, summary.getNumberOfProjects() );
+
+        summary = summaries.get( defaultProjectGroup.getId() );
+        assertEquals( "check id of project group", defaultProjectGroup.getId(), summary.getProjectGroupId() );
+        assertEquals( "check number of errors", 0, summary.getNumberOfErrors() );
+        assertEquals( "check number of successes", 2, summary.getNumberOfSuccesses() );
+        assertEquals( "check number of failures", 0, summary.getNumberOfFailures() );
+        assertEquals( "check number of projects", 2, summary.getNumberOfProjects() );
+
+    }
+
+    public void testGetBuildResultsInRange()
+        throws Exception
+    {
+        List<BuildResult> results = buildResultDao.getBuildResultsInRange( null, null, 0, null, 0 );
+        assertEquals( "check number of build results returned", 3, results.size() );
+
+        results = buildResultDao.getBuildResultsInRange( null, null, 2, null, 0 );
+        assertEquals( "check number of build results returned with state == OK", 2, results.size() );
+
+        results = buildResultDao.getBuildResultsInRange( null, null, 0, "user", 0 );
+        assertEquals( "check number of build results returned with triggeredBy == user", 1, results.size() );
+
+        results = buildResultDao.getBuildResultsInRange( null, null, 0, "schedule", 0 );
+        assertEquals( "check number of build results returned with triggeredBy == schedule", 2, results.size() );
+
+        results = buildResultDao.getBuildResultsInRange( null, null, 2, "schedule", 0 );
+        assertEquals( "check number of build results returned with state == Ok and triggeredBy == schedule", 1,
+                      results.size() );
+
+        results = buildResultDao.getBuildResultsInRange( null, null, 3, "user", 0 );
+        assertEquals( "check number of build results returned with state == Failed and triggeredBy == user", 0,
+                      results.size() );
+
+        Calendar cal = Calendar.getInstance();
+        cal.setTime( new Date( baseTime ) );
+        cal.add( Calendar.DAY_OF_MONTH, 1 );
+
+        results = buildResultDao.getBuildResultsInRange( new Date( baseTime ), cal.getTime(), 0, null, 0 );
+        assertEquals( "check number of build results returned with startDate and endDate", 2, results.size() );
+
+        results = buildResultDao.getBuildResultsInRange( new Date( baseTime ), new Date( baseTime ), 0, null, 0 );
+        assertEquals( "check number of build results returned with the same startDate and endDate", 1, results.size() );
+
+        results = buildResultDao.getBuildResultsInRange( null, null, 0, null, 1 );
+        assertEquals( "check number of build results returned with an existing group id", 3, results.size() );
+
+        results = buildResultDao.getBuildResultsInRange( null, null, 0, null, 2 );
+        assertEquals( "check number of build results returned with non-existing group id", 0, results.size() );
     }
     // ----------------------------------------------------------------------
     //  HELPER METHODS
@@ -1381,7 +1506,7 @@
 
         buildResultDao = (BuildResultDao) lookup( BuildResultDao.class.getName() );
 
-        createBuildDatabase();
+        createBuildDatabase( false );
     }
 
     private static void checkProjectFetchGroup( Project project, boolean checkoutFetchGroup,
@@ -1467,21 +1592,21 @@
         }
     }
 
-    private static void checkBuildResultDefaultFetchGroup( BuildResult buildResult )
-    {
-        try
-        {
-            buildResult.getScmResult();
-
-            fail( "scmResult should not be in the default fetch group" );
-        }
-        catch ( JDODetachedFieldAccessException expected )
-        {
-            assertTrue( true );
-        }
-        // TODO: artifacts
-        // TODO: report
-        // TODO: long error data
-    }
+//    private static void checkBuildResultDefaultFetchGroup( BuildResult buildResult )
+//    {
+//        try
+//        {
+//            buildResult.getScmResult();
+//
+//            fail( "scmResult should not be in the default fetch group" );
+//        }
+//        catch ( JDODetachedFieldAccessException expected )
+//        {
+//            assertTrue( true );
+//        }
+//        // TODO: artifacts
+//        // TODO: report
+//        // TODO: long error data
+//    }
 
 }
diff --git a/continuum-store/src/test/resources/org/apache/maven/continuum/store/ContinuumStoreTest.xml b/continuum-store/src/test/resources/org/apache/maven/continuum/store/ContinuumStoreTest.xml
index ddf4483..d8d0064 100644
--- a/continuum-store/src/test/resources/org/apache/maven/continuum/store/ContinuumStoreTest.xml
+++ b/continuum-store/src/test/resources/org/apache/maven/continuum/store/ContinuumStoreTest.xml
@@ -60,12 +60,5 @@
         </otherProperties>
       </configuration>
     </component>
-
-    <component>
-      <role>org.codehaus.plexus.logging.LoggerManager</role>
-      <implementation>org.codehaus.plexus.logging.slf4j.Slf4jLoggerManager</implementation>
-      <lifecycle-handler>basic</lifecycle-handler>
-    </component>
-
   </components>
 </component-set>
diff --git a/continuum-test/pom.xml b/continuum-test/pom.xml
index 093ae10..057aca4 100644
--- a/continuum-test/pom.xml
+++ b/continuum-test/pom.xml
@@ -1,27 +1,28 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
+  ~ 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.
+  -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <artifactId>continuum</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>continuum-test</artifactId>
@@ -30,7 +31,10 @@
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
-      <version>3.8.1</version>
+    </dependency>
+    <dependency>
+      <groupId>javax.jdo</groupId>
+      <artifactId>jdo2-api</artifactId>
     </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
@@ -38,22 +42,19 @@
     </dependency>
     <dependency>
       <groupId>jpox</groupId>
-      <artifactId>jpox-enhancer</artifactId>
+      <artifactId>jpox</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-model</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.continuum</groupId>
       <artifactId>continuum-api</artifactId>
     </dependency>
     <dependency>
-      <groupId>org.codehaus.plexus</groupId>
+      <groupId>org.codehaus.redback</groupId>
       <artifactId>plexus-spring</artifactId>
-      <scope>compile</scope>
-    </dependency>    
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-log4j12</artifactId>
-      <version>1.5.0</version>
-      <scope>runtime</scope>
     </dependency>
   </dependencies>
 </project>
diff --git a/continuum-test/src/main/java/org/apache/maven/continuum/AbstractContinuumTest.java b/continuum-test/src/main/java/org/apache/maven/continuum/AbstractContinuumTest.java
index 329a08c..341cecd 100644
--- a/continuum-test/src/main/java/org/apache/maven/continuum/AbstractContinuumTest.java
+++ b/continuum-test/src/main/java/org/apache/maven/continuum/AbstractContinuumTest.java
@@ -22,10 +22,12 @@
 import org.apache.continuum.dao.DaoUtils;
 import org.apache.continuum.dao.ProjectDao;
 import org.apache.continuum.dao.ProjectGroupDao;
+import org.apache.continuum.dao.ProjectScmRootDao;
 import org.apache.continuum.dao.ScheduleDao;
 import org.apache.maven.continuum.configuration.ConfigurationService;
 import org.apache.maven.continuum.execution.ContinuumBuildExecutor;
 import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
+import org.apache.maven.continuum.initialization.ContinuumInitializer;
 import org.apache.maven.continuum.jdo.MemoryJdoFactory;
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.Project;
@@ -38,14 +40,14 @@
 import org.codehaus.plexus.spring.PlexusInSpringTestCase;
 import org.jpox.SchemaTool;
 
-import javax.jdo.PersistenceManager;
-import javax.jdo.PersistenceManagerFactory;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
+import javax.jdo.PersistenceManager;
+import javax.jdo.PersistenceManagerFactory;
 
 /**
  * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
@@ -62,6 +64,8 @@
 
     private ScheduleDao scheduleDao;
 
+    private ProjectScmRootDao projectScmRootDao;
+
     // ----------------------------------------------------------------------
     //
     // ----------------------------------------------------------------------
@@ -80,6 +84,8 @@
 
         getScheduleDao();
 
+        getProjectScmRootDao();
+
         setUpConfigurationService( (ConfigurationService) lookup( "configurationService" ) );
 
         Collection<ProjectGroup> projectGroups = projectGroupDao.getAllProjectGroupsWithProjects();
@@ -117,7 +123,7 @@
 
             group.setName( "Default Project Group" );
 
-            group.setGroupId( Continuum.DEFAULT_PROJECT_GROUP_GROUP_ID );
+            group.setGroupId( ContinuumInitializer.DEFAULT_PROJECT_GROUP_GROUP_ID );
 
             group.setDescription( "Contains all projects that do not have a group of their own" );
 
@@ -131,10 +137,8 @@
         configurationService.setBuildOutputDirectory( getTestFile( "target/build-output" ) );
 
         configurationService.setWorkingDirectory( getTestFile( "target/working-directory" ) );
-        
-        configurationService.setReleaseOutputDirectory( getTestFile( "target/release-outpur" ) );
 
-        configurationService.setReleaseOutputDirectory( getTestFile( "target/release-outpur" ) );
+        configurationService.setReleaseOutputDirectory( getTestFile( "target/release-output" ) );
 
         configurationService.store();
     }
@@ -142,7 +146,8 @@
     protected ProjectGroup getDefaultProjectGroup()
         throws ContinuumStoreException
     {
-        return projectGroupDao.getProjectGroupByGroupIdWithProjects( Continuum.DEFAULT_PROJECT_GROUP_GROUP_ID );
+        return projectGroupDao.getProjectGroupByGroupIdWithProjects(
+            ContinuumInitializer.DEFAULT_PROJECT_GROUP_GROUP_ID );
     }
 
     // ----------------------------------------------------------------------
@@ -207,8 +212,8 @@
             System.setProperty( (String) entry.getKey(), (String) entry.getValue() );
         }
 
-        SchemaTool.createSchemaTables( new URL[]{getClass().getResource( "/META-INF/package.jdo" )}, new URL[]{}, null,
-                                       false, null );
+        SchemaTool.createSchemaTables( new URL[]{getClass().getResource( "/package.jdo" )}, new URL[]{}, null, false,
+                                       null );
 
         // ----------------------------------------------------------------------
         //
@@ -244,6 +249,15 @@
         return scheduleDao;
     }
 
+    protected ProjectScmRootDao getProjectScmRootDao()
+    {
+        if ( projectScmRootDao == null )
+        {
+            projectScmRootDao = (ProjectScmRootDao) lookup( ProjectScmRootDao.class.getName() );
+        }
+        return projectScmRootDao;
+    }
+
     // ----------------------------------------------------------------------
     // Build Executor
     // ----------------------------------------------------------------------
@@ -405,9 +419,8 @@
 
                 assertEquals( "project.notifiers.notifier.type", notifier.getType(), actualNotifier.getType() );
 
-                assertEquals( "project.notifiers.notifier.configuration.address",
-                              notifier.getConfiguration().get( "address" ),
-                              actualNotifier.getConfiguration().get( "address" ) );
+                assertEquals( "project.notifiers.notifier.configuration.address", notifier.getConfiguration().get(
+                    "address" ), actualNotifier.getConfiguration().get( "address" ) );
             }
         }
 
diff --git a/continuum-test/src/main/java/org/apache/maven/continuum/configuration/ConfigurationServiceMock.java b/continuum-test/src/main/java/org/apache/maven/continuum/configuration/ConfigurationServiceMock.java
index b9119be..48ae7bb 100644
--- a/continuum-test/src/main/java/org/apache/maven/continuum/configuration/ConfigurationServiceMock.java
+++ b/continuum-test/src/main/java/org/apache/maven/continuum/configuration/ConfigurationServiceMock.java
@@ -19,7 +19,10 @@
  * under the License.
  */
 
+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;
 
@@ -35,7 +38,7 @@
 public class ConfigurationServiceMock
     implements ConfigurationService
 {
-    private String basedir;
+    private final String basedir;
 
     public ConfigurationServiceMock()
     {
@@ -175,6 +178,15 @@
         return null;
     }
 
+    public String getSharedSecretPassword()
+    {
+        return null;
+    }
+
+    public void setSharedSecretPassword( String sharedSecretPassword )
+    {
+    }
+
     public boolean isLoaded()
     {
         return false;
@@ -190,6 +202,12 @@
     {
     }
 
+    public BuildQueue getDefaultBuildQueue()
+        throws BuildQueueServiceException
+    {
+        return null;
+    }
+
     public Schedule getDefaultSchedule()
         throws ContinuumStoreException
     {
@@ -229,7 +247,7 @@
             throw new ConfigurationException(
                 "Could not make the release output directory: " + "'" + dir.getAbsolutePath() + "'." );
         }
-    
+
         return new File( dir, releaseName + ".log.txt" );
     }
 
@@ -242,9 +260,19 @@
         return null;
     }
 
+    public int getNumberOfBuildsInParallel()
+    {
+        return 1;
+    }
+
+    public void setNumberOfBuildsInParallel( int num )
+    {
+
+    }
+
     public void addBuildAgent( BuildAgentConfiguration buildAgent )
         throws ConfigurationException
-    {    
+    {
     }
 
     public List<BuildAgentConfiguration> getBuildAgents()
@@ -258,7 +286,7 @@
     }
 
     public void removeBuildAgent( BuildAgentConfiguration buildAgent )
-    {   
+    {
     }
 
     public void setDistributedBuildEnabled( boolean distributedBuildEnabled )
@@ -269,4 +297,48 @@
     {
     }
 
+    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;
+    }
 }
diff --git a/continuum-test/src/main/java/org/apache/maven/continuum/jdo/MemoryJdoFactory.java b/continuum-test/src/main/java/org/apache/maven/continuum/jdo/MemoryJdoFactory.java
index 14d9d7c..d134839 100644
--- a/continuum-test/src/main/java/org/apache/maven/continuum/jdo/MemoryJdoFactory.java
+++ b/continuum-test/src/main/java/org/apache/maven/continuum/jdo/MemoryJdoFactory.java
@@ -1,9 +1,28 @@
 package org.apache.maven.continuum.jdo;
 
-import java.util.Properties;
+/*
+ * 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 org.codehaus.plexus.jdo.DefaultConfigurableJdoFactory;
 
+import java.util.Properties;
+
 public class MemoryJdoFactory
     extends DefaultConfigurableJdoFactory
 {
diff --git a/continuum-test/src/main/resources/META-INF/plexus/components.xml b/continuum-test/src/main/resources/META-INF/plexus/components.xml
index a63811e..b5f2e00 100644
--- a/continuum-test/src/main/resources/META-INF/plexus/components.xml
+++ b/continuum-test/src/main/resources/META-INF/plexus/components.xml
@@ -19,57 +19,6 @@
 
 <component-set>
   <components>
-<!--
-    <component>
-      <role>org.codehaus.plexus.jdo.JdoFactory</role>
-      <role-hint>continuum</role-hint>
-      <implementation>org.apache.maven.continuum.jdo.MemoryJdoFactory</implementation>
-      <configuration>
-        <persistenceManagerFactoryClass>org.jpox.PersistenceManagerFactoryImpl</persistenceManagerFactoryClass>
-        <driverName>org.hsqldb.jdbcDriver</driverName>
-        <url>jdbc:hsqldb:${plexus.home}/database</url>
-        <userName>sa</userName>
-        <password></password>
-        <persistenceManagerFactoryClass>org.jpox.PersistenceManagerFactoryImpl</persistenceManagerFactoryClass>
-
-        <otherProperties>
-          <property>
-            <name>org.jpox.autoCreateSchema</name>
-            <value>true</value>
-          </property>
-          <property>
-            <name>org.jpox.validateTables</name>
-            <value>false</value>
-          </property>
-          <property>
-            <name>org.jpox.validateColumns</name>
-            <value>false</value>
-          </property>
-          <property>
-            <name>org.jpox.validateConstraints</name>
-            <value>false</value>
-          </property>
-
-          <property>
-            <name>org.jpox.autoStartMechanism</name>
-            <value>SchemaTable</value>
-          </property>
-          <property>
-            <name>org.jpox.autoStartMechanismMode</name>
-            <value>Ignored</value>
-          </property>
-          <property>
-            <name>org.jpox.transactionIsolation</name>
-            <value>READ_COMMITTED</value>
-          </property>
-          <property>
-            <name>org.jpox.poid.transactionIsolation</name>
-            <value>READ_COMMITTED</value>
-          </property>
-        </otherProperties>
-      </configuration>
-    </component>
--->
     <component>
       <role>org.codehaus.plexus.jdo.JdoFactory</role>
       <role-hint>users</role-hint>
@@ -77,7 +26,7 @@
       <configuration>
         <!-- Database Configuration -->
         <driverName>org.hsqldb.jdbcDriver</driverName>
-        <url>jdbc:hsqldb:${plexus.home}/database</url>
+        <url>jdbc:hsqldb:mem:userstest</url>
         <userName>sa</userName>
         <password></password>
         <persistenceManagerFactoryClass>org.jpox.PersistenceManagerFactoryImpl</persistenceManagerFactoryClass>
diff --git a/continuum-test/src/main/resources/META-INF/spring-context.xml b/continuum-test/src/main/resources/META-INF/spring-context.xml
index c5911e5..b6cdb03 100644
--- a/continuum-test/src/main/resources/META-INF/spring-context.xml
+++ b/continuum-test/src/main/resources/META-INF/spring-context.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
+
 <!--
   ~ Licensed to the Apache Software Foundation (ASF) under one
   ~ or more contributor license agreements.  See the NOTICE file
@@ -17,20 +18,15 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
   -->
+
 <beans xmlns="http://www.springframework.org/schema/beans"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xmlns:p="http://www.springframework.org/schema/p"
-	xmlns:aop="http://www.springframework.org/schema/aop"
-	xmlns:util="http://www.springframework.org/schema/util"
-	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
-		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:p="http://www.springframework.org/schema/p"
+       xmlns:util="http://www.springframework.org/schema/util"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+
 		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd">
 
-<!--
-  <bean id="jdoProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
-    <property name="location" value="classpath:jdo.properties"/>
-  </bean>
--->
   <util:properties id="jdoProperties" location="classpath:jdo.properties"/>
 
   <bean name="jdoFactory#continuum" depends-on="jdoProperties"
@@ -41,13 +37,7 @@
         p:password=""
         p:url="jdbc:hsqldb:mem:test">
 
-<!-- 
-        <property name="persistenceManagerFactoryClass" value="org.jpox.PersistenceManagerFactoryImpl"/>
--->
     <property name="otherProperties" ref="jdoProperties"/>
   </bean>
-<!--
-        p:url="jdbc:hsqldb:${plexus.home}/database"
--->
 
 </beans>
diff --git a/continuum-test/src/main/resources/jdo.properties b/continuum-test/src/main/resources/jdo.properties
index 5af17ae..d22ee9e 100644
--- a/continuum-test/src/main/resources/jdo.properties
+++ b/continuum-test/src/main/resources/jdo.properties
@@ -1,3 +1,22 @@
+#
+# 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.
+#
+
 org.jpox.autoCreateSchema=true
 org.jpox.autoCreateTables=true
 org.jpox.validateTables=false
diff --git a/continuum-webapp-test/Readme.txt b/continuum-webapp-test/Readme.txt
index 9f5d2e2..55b6559 100644
--- a/continuum-webapp-test/Readme.txt
+++ b/continuum-webapp-test/Readme.txt
@@ -6,26 +6,60 @@
  * in Selenium IDE, modify the Base URL if necessary (for example, http://localhost:8080/continuum)
  * in Selenium IDE, click the 'Play entire test suite' icon
 
-Test Continuum with Tomcat 5.x and firefox
-    'mvn clean install' or 'mvn clean install -Ptomcat5x,firefox'
+Run Selenium tests in src/test/testNG with Maven, TestNG and Cargo
+ * mvn clean install
 
-Test Continuum with Tomcat 5.x and Internet Explorer
-    'mvn clean install -Ptomcat5x,iexplore'
+Note that while tomcat7x is the default container, if you have activated any
+other profiles on the command line or in your settings.xml, you need to
+specify it explicitly:
 
-Test Continuum with Tomcat 5.x and a specific browser
-    'mvn clean install -Ptomcat5x,otherbrowser -DbrowserPath=PATH_TO_YOUR_BROWSER'
+ * mvn clean install -Ptomcat7x
 
-Test Continuum with Tomcat 5.x and firefox wherein your firefox executable is not in the default installation directory
-    'mvn clean install' or 'mvn clean install -Ptomcat5x,firefox -Dbrowser="*firefox <full path of firefox executable>'
+The tests require Ant and Maven to be on your PATH. If they are not, pass the plexus.system.path argument:
+ * mvn clean install -Dplexus.system.path=/path/to/apache-maven-3.0.4/bin:/path/to/apache-ant-1.8.1/bin
 
-Test Continuum with Tomcat 5.x and Internet Explorer wherein your Internet Explorer executable is not in the default installation directory
-    'mvn clean install' or 'mvn clean install -Ptomcat5x,firefox -Dbrowser="*iexplore <full path of Internet Explorer executable>'
+Run Selenium tests against an existing Continuum instance
+  * mvn clean install -DbaseUrl=http://localhost:9090 -DbuildAgentUrl=http://localhost:9191/xmlrpc \
+        -DappserverBase=$PWD/../continuum-webapp/target/appserver-base
 
-WARNING: If you specify your own custom browser, it's up to you to configure it correctly. At a minimum, you'll need to configure your browser to use the Selenium Server as a proxy, and disable all browser-specific prompting.
-http://release.openqa.org/selenium-remote-control/nightly/doc/java/com/thoughtworks/selenium/DefaultSelenium.html#DefaultSelenium(java.lang.String,%20int,%20java.lang.String,%20java.lang.String)
+  This skips the Cargo plugin configuration that starts a container with the
+  Continuum webapp deployed. Note that you will need to have set this on the
+  existing Continuum instance:
+  
+    -Dsvn.base.url=file://localhost${PWD}/../continuum-webapp-test/target/example-svn
+
+Run Selenium tests in an alternate browser
+  * mvn clean install -Ptomcat7x -Dbrowser=iexplore  (or -Dbrowser=safari or -Dbrowser=other -DbrowserPath=/path/to/browser)
+
+(Note that you must specify the container in this case, as the browser profile disables the default container profile)
+
+Change the port the embedded selenium runs on
+  * mvn clean install -DseleniumPort=4444
+
+Run Selenium tests in an running Selenium server or hub
+  * mvn clean install -DseleniumHost=localhost -DseleniumPort=4444
+
+ Note that this does not install anything, it simply runs through the lifecycle including the integration test phases.
+ More properly it would be 'mvn clean post-integration-test', but install is much shorter to type. :)
 
 If you'd like to run the tests from your IDE, you can start the container from Maven using:
 
-    mvn selenium:start-server cargo:start
+    mvn clean test-compile selenium:start-server cargo:run
 
 The server will run until you press Ctrl-C, and you can run the tests from the IDE.
+
+To attach a debugger to the same process, run:
+
+    mvn -Ptomcat7x,debug test-compile selenium:start-server cargo:run
+
+You can also run the Selenium server against your development instance, so
+that you can run the tests in your IDE:
+
+    mvn -Ptomcat7x,debug test-compile selenium:start-server cargo:run -DbaseUrl=http://localhost:9090
+
+The remaining properties appserverBase and buildAgentUrl need to be supplied to the running tests, along with the same
+baseUrl value.
+
+Note, the tests currently fail with "Illegal value" errors under newer
+versions of Selenium and Firefox. The tests run successfully with Selenium
+2.21.0 and Firefox 17.
diff --git a/continuum-webapp-test/pom.xml b/continuum-webapp-test/pom.xml
index ef8a003..abbf2f7 100644
--- a/continuum-webapp-test/pom.xml
+++ b/continuum-webapp-test/pom.xml
@@ -1,400 +1,49 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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
+  ~ 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.
+  -->
 
-  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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
     <groupId>org.apache.continuum</groupId>
     <artifactId>continuum</artifactId>
-    <version>1.3.0-SNAPSHOT</version>
+    <version>1.4.3-SNAPSHOT</version>
   </parent>
   <artifactId>continuum-webapp-test</artifactId>
-  <name>Continuum Webapp Test</name>
+  <name>Continuum :: Webapp Tests</name>
   <packaging>pom</packaging>
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-webapp</artifactId>
-      <type>war</type>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.shared</groupId>
-      <artifactId>maven-web-ui-tests</artifactId>
-      <version>1.0-SNAPSHOT</version>
-      <scope>test</scope>
-    </dependency>
-    
-    <!--
-       All dependencies defined below are the dependencies list of continuum-webapp
-       We need them because we need to add in WEB-INF-lib all jars that aren't in
-       the webapp because they are provided by appserver
-    -->
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-configuration</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.shared</groupId>
-      <artifactId>maven-app-configuration-model</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.shared</groupId>
-      <artifactId>maven-app-configuration-web</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-core</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-security</artifactId>
-    </dependency>
-    <dependency> <!-- added since depMgt doesn't override imported dependencies -->
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-utils</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-xwork-integration</artifactId>
-      <version>1.0-alpha-3</version>
-    </dependency>
-    <dependency>
-      <groupId>javax.servlet</groupId>
-      <artifactId>servlet-api</artifactId>
-      <version>2.4</version>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>javax.servlet</groupId>
-      <artifactId>jsp-api</artifactId>
-      <version>2.0</version>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>opensymphony</groupId>
-      <artifactId>sitemesh</artifactId>
-      <version>2.2.1</version>
-    </dependency>
-    <dependency>
-      <groupId>org.extremecomponents</groupId>
-      <artifactId>extremecomponents</artifactId>
-      <version>1.0.1</version>
-    </dependency>
-    <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-log4j-logging</artifactId>
-    </dependency>
-    <!--
-    <dependency>
-      <groupId>mysql</groupId>
-      <artifactId>mysql-connector-java</artifactId>
-    </dependency>
-    -->
-    <dependency>
-      <groupId>commons-fileupload</groupId>
-      <artifactId>commons-fileupload</artifactId>
-      <version>1.1</version>
-    </dependency>
-    <dependency>
-      <groupId>taglibs</groupId>
-      <artifactId>standard</artifactId>
-      <version>1.1.2</version>
-    </dependency>
-    <dependency>
-      <groupId>javax.servlet</groupId>
-      <artifactId>jstl</artifactId>
-      <version>1.1.2</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.scm</groupId>
-      <artifactId>maven-scm-provider-bazaar</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.scm</groupId>
-      <artifactId>maven-scm-provider-clearcase</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.scm</groupId>
-      <artifactId>maven-scm-provider-cvsexe</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.scm</groupId>
-      <artifactId>maven-scm-provider-local</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.scm</groupId>
-      <artifactId>maven-scm-provider-perforce</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.scm</groupId>
-      <artifactId>maven-scm-provider-starteam</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.scm</groupId>
-      <artifactId>maven-scm-provider-svnexe</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.scm</groupId>
-      <artifactId>maven-scm-provider-synergy</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.scm</groupId>
-      <artifactId>maven-scm-provider-vss</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-notifier-irc</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-notifier-jabber</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-notifier-msn</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-notifier-wagon</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-xmlrpc</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-xmlrpc</artifactId>
-      <version>1.0-beta-4</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.wagon</groupId>
-      <artifactId>wagon-provider-api</artifactId>
-      <scope>runtime</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.wagon</groupId>
-      <artifactId>wagon-file</artifactId>
-      <scope>runtime</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.wagon</groupId>
-      <artifactId>wagon-http-lightweight</artifactId>
-      <scope>runtime</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.wagon</groupId>
-      <artifactId>wagon-ssh</artifactId>
-      <scope>runtime</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.wagon</groupId>
-      <artifactId>wagon-ssh-external</artifactId>
-      <scope>runtime</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.wagon</groupId>
-      <artifactId>wagon-webdav</artifactId>
-      <scope>runtime</scope>
-    </dependency>
-    <!--
-      Plexus Security Dependencies
-      -->
-    <dependency>
-      <groupId>org.codehaus.plexus.security</groupId>
-      <artifactId>plexus-security-ui-web</artifactId>
-      <type>war</type>
-      <scope>runtime</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.codehaus.plexus.security</groupId>
-      <artifactId>plexus-security-ui-web-taglib</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-jdo2</artifactId>
-      <exclusions>
-        <exclusion>
-          <groupId>xerces</groupId>
-          <artifactId>xercesImpl</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>xerces</groupId>
-          <artifactId>xmlParserAPIs</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-utils</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.derby</groupId>
-      <artifactId>derby</artifactId>
-    </dependency>
-    <!--
-    <dependency>
-      <groupId>postgresql</groupId>
-      <artifactId>postgresql</artifactId>
-      <version>8.0-312.jdbc3</version>
-    </dependency>
-    -->
-    <dependency>
-      <groupId>jpox</groupId>
-      <artifactId>jpox</artifactId>
-      <exclusions>
-        <!-- targeting JDK 1.4 we don't need this -->
-        <exclusion>
-          <groupId>javax.sql</groupId>
-          <artifactId>jdbc-stdext</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>commons-lang</groupId>
-      <artifactId>commons-lang</artifactId>
-      <version>2.1</version>
-    </dependency>
-    <dependency>
-      <groupId>javax.mail</groupId>
-      <artifactId>mail</artifactId>
-      <version>1.4</version>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>javax.activation</groupId>
-      <artifactId>activation</artifactId>
-      <version>1.1</version>
-      <scope>provided</scope>
-    </dependency>
-  </dependencies>
 
   <build>
-    <testSourceDirectory>src/test/it</testSourceDirectory>
+    <testSourceDirectory>src/test/testng</testSourceDirectory>
+    <testResources>
+      <testResource>
+        <directory>src/test/resources</directory>
+        <filtering>true</filtering>
+        <includes>
+          <include>**/*</include>
+        </includes>
+      </testResource>
+    </testResources>
     <plugins>
       <plugin>
-        <groupId>org.codehaus.mojo</groupId>
-        <artifactId>dependency-maven-plugin</artifactId>
-        <executions>
-          <execution>
-            <id>unzip-continuum-webapp</id>
-            <phase>generate-resources</phase>
-            <goals>
-              <goal>unpack</goal>
-            </goals>
-            <configuration>
-              <artifactItems>
-                <artifactItem>
-                  <groupId>${project.groupId}</groupId>
-                  <artifactId>continuum-webapp</artifactId>
-                  <version>${project.version}</version>
-                  <type>war</type>
-                </artifactItem>
-              </artifactItems>
-              <outputDirectory>${project.build.directory}/${container.name}conf/webapps/continuum</outputDirectory>
-            </configuration>
-          </execution>
-          <execution>
-            <id>prepare-provided-dependencies</id>
-            <phase>generate-resources</phase>
-            <goals>
-              <goal>copy-dependencies</goal>
-            </goals>
-            <configuration>
-              <overWriteReleases>false</overWriteReleases>
-              <overWriteSnapshots>true</overWriteSnapshots>
-              <excludeTransitive>false</excludeTransitive>
-              <outputDirectory>${project.build.directory}/providedDependencies</outputDirectory>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-      <plugin>
-        <artifactId>maven-antrun-plugin</artifactId>
-        <executions>
-          <execution>
-            <id>copy-container-conf</id>
-            <phase>package</phase>
-            <configuration>
-              <tasks>
-                <copy todir="${project.build.directory}/${container.name}conf">
-                  <fileset dir="src/test/${container.name}"/>
-                </copy>
-                <copy todir="${project.build.directory}/installs/${container.name}/apache-tomcat-5.5.20/apache-tomcat-5.5.20/common/lib">
-                  <fileset dir="${project.build.directory}/providedDependencies">
-                    <include name="**/derby-*.jar"/>
-                  </fileset>
-                </copy>
-              </tasks>
-            </configuration>
-            <goals>
-              <goal>run</goal>
-            </goals>
-          </execution>
-          <execution>
-            <id>copy-provided-dependencies</id>
-            <phase>package</phase>
-            <configuration>
-              <tasks>
-                <copy todir="${project.build.directory}/${container.name}conf">
-                  <fileset dir="src/test/${container.name}"/>
-                </copy>
-                <copy todir="${project.build.directory}/${container.name}conf/webapps/continuum/WEB-INF/lib">
-                  <fileset dir="${project.build.directory}/providedDependencies">
-                    <include name="activation-*.jar"/>
-                    <include name="classworlds-*.jar"/>
-                    <include name="icu4j-*.jar"/>
-                    <include name="jpox-*.jar"/>
-                    <include name="velocity-dep-*.jar"/>
-                    <include name="xalan-*.jar"/>
-                    <include name="xercesImpl-*.jar"/>
-                    <include name="xml-apis-*.jar"/>
-                    <include name="xmlParserAPIs-*.jar"/>
-                    <include name="mail-*.jar"/>
-                    <include name="plexus-container-default-*.jar"/>
-                    <include name="jdo2-api-*.jar"/>
-                    <include name="connector-*.jar"/>
-                    <include name="nlog4j-*.jar"/>
-                    <include name="log4j-*.jar"/>
-                  </fileset>
-                </copy>
-              </tasks>
-            </configuration>
-            <goals>
-              <goal>run</goal>
-            </goals>
-          </execution>
-          <execution>
-            <id>check-continuum-loaded</id>
-            <phase>integration-test</phase>
-            <configuration>
-              <tasks>
-                <get src="http://localhost:9595/continuum/" dest="${project.build.directory}/index.html"/>
-                <delete file="${project.build.directory}/index.html"/>
-              </tasks>
-            </configuration>
-            <goals>
-              <goal>run</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
-      <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-compiler-plugin</artifactId>
         <executions>
@@ -406,9 +55,76 @@
         </executions>
       </plugin>
       <plugin>
+        <artifactId>maven-resources-plugin</artifactId>
+        <version>2.5</version>
+        <executions>
+          <execution>
+            <goals>
+              <goal>testResources</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <version>1.3</version>
+        <executions>
+          <execution>
+            <phase>generate-resources</phase>
+            <goals>
+              <goal>run</goal>
+            </goals>
+            <configuration>
+              <tasks>
+                <copy todir="${project.build.directory}" overwrite="true">
+                  <filterchain>
+                    <expandproperties />
+                  </filterchain>
+                  <fileset dir="src/appserver-base"/>
+                </copy>
+                <delete dir="${project.build.directory}/example-svn"/>
+                <copy todir="${project.build.directory}/example-svn">
+                  <fileset dir="src/test/example-svn"/>
+                </copy>
+                <!-- This doesn't work, SVN doesn't like the file:/ URL it gives
+                <makeurl file="${project.build.directory}/example-svn" property="svn.base.url"/>
+                -->
+                <path id="svn.repo.dir">
+                  <pathelement location="${project.build.directory}/example-svn"/>
+                </path>
+                <pathconvert refid="svn.repo.dir" targetos="unix" property="svn.base.url"/>
+                <echo file="${project.build.directory}/filter.properties">
+                  svn.base.url=file://localhost${svn.base.url}
+                  continuum.port=${continuum.port}
+                  baseUrl=${baseUrl}
+                </echo>
+              </tasks>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>properties-maven-plugin</artifactId>
+        <version>1.0-alpha-2</version>
+        <executions>
+          <execution>
+            <phase>generate-resources</phase>
+            <goals>
+              <goal>read-project-properties</goal>
+            </goals>
+            <configuration>
+              <files>
+                <file>${project.build.directory}/filter.properties</file>
+              </files>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>selenium-maven-plugin</artifactId>
-        <version>1.0-SNAPSHOT</version>
+        <version>2.3</version>
         <executions>
           <execution>
             <id>start-selenium</id>
@@ -417,14 +133,114 @@
               <goal>start-server</goal>
             </goals>
           </execution>
+          <execution>
+            <id>stop-selenium</id>
+            <phase>post-integration-test</phase>
+            <goals>
+              <goal>stop-server</goal>
+            </goals>
+          </execution>
         </executions>
-        <configuration>
-          <background>true</background>
-        </configuration>
+        <dependencies>
+          <dependency>
+            <groupId>org.seleniumhq.selenium</groupId>
+            <artifactId>selenium-server</artifactId>
+            <version>${selenium.version}</version>
+          </dependency>
+          <dependency>
+            <groupId>org.seleniumhq.selenium</groupId>
+            <artifactId>selenium-remote-driver</artifactId>
+            <version>${selenium.version}</version>
+          </dependency>
+          <dependency>
+            <groupId>org.seleniumhq.selenium</groupId>
+            <artifactId>selenium-api</artifactId>
+            <version>${selenium.version}</version>
+          </dependency>
+        </dependencies>
       </plugin>
       <plugin>
         <groupId>org.codehaus.cargo</groupId>
         <artifactId>cargo-maven2-plugin</artifactId>
+        <version>1.2.3</version>
+        <configuration>
+          <container>
+            <containerId>${container.name}</containerId>
+            <log>${project.build.directory}/logs/${container.name}.log</log>
+            <output>${project.build.directory}/logs/${container.name}.out</output>
+            <timeout>180000</timeout>
+            <systemProperties>
+              <appserver.base>${project.build.directory}</appserver.base>
+              <derby.system.home>${project.build.directory}</derby.system.home>
+              <svn.base.url>${svn.base.url}</svn.base.url>
+              <continuum.port>${contiuum.port}</continuum.port>
+              <baseUrl>${baseUrl}</baseUrl>
+              <plexus.system.path>${plexus.system.path}</plexus.system.path>
+            </systemProperties>
+            <dependencies>
+              <dependency>
+                <groupId>org.apache.derby</groupId>
+                <artifactId>derby</artifactId>
+              </dependency>
+              <dependency>
+                <groupId>javax.mail</groupId>
+                <artifactId>mail</artifactId>
+              </dependency>
+              <dependency>
+                <groupId>javax.activation</groupId>
+                <artifactId>activation</artifactId>
+              </dependency>
+            </dependencies>
+          </container>
+          <configuration>
+            <properties>
+              <cargo.servlet.port>${continuum.port}</cargo.servlet.port>
+              <cargo.jvmargs>${cargo.jvmargs}</cargo.jvmargs>
+              <cargo.datasource.datasource.users>
+                cargo.datasource.driver=org.apache.derby.jdbc.EmbeddedDriver|
+                cargo.datasource.url=jdbc:derby:${project.build.directory}/databases/${container.name}/users;create=true|
+                cargo.datasource.jndi=jdbc/users|
+                cargo.datasource.username=sa
+              </cargo.datasource.datasource.users>
+              <cargo.datasource.datasource.builds>
+                cargo.datasource.driver=org.apache.derby.jdbc.EmbeddedDriver|
+                cargo.datasource.url=jdbc:derby:${project.build.directory}/databases/${container.name}/builds;create=true|
+                cargo.datasource.jndi=jdbc/continuum|
+                cargo.datasource.username=sa
+              </cargo.datasource.datasource.builds>
+              <cargo.resource.resource.mail>
+                cargo.resource.name=mail/Session|
+                cargo.resource.type=javax.mail.Session|
+                cargo.resource.factory=org.apache.naming.factory.MailSessionFactory|
+                cargo.resource.parameters=mail.smtp.host=localhost
+              </cargo.resource.resource.mail>
+            </properties>
+          </configuration>
+          <deployables>
+            <deployable>
+              <artifactId>continuum-webapp</artifactId>
+              <type>war</type>
+              <properties>
+                <context>continuum</context>
+              </properties>
+            </deployable>
+            <deployable>
+              <artifactId>continuum-buildagent-webapp</artifactId>
+              <type>war</type>
+              <properties>
+                <context>continuum-buildagent</context>
+              </properties>
+            </deployable>
+            <!-- Test resources -->
+            <deployable>
+              <location>${basedir}/src/test/example-projects</location>
+              <type>war</type>
+              <properties>
+                <context>example-projects</context>
+              </properties>
+            </deployable>
+          </deployables>
+        </configuration>
         <executions>
           <execution>
             <id>start-container</id>
@@ -432,93 +248,374 @@
             <goals>
               <goal>start</goal>
             </goals>
-            <configuration>
-              <wait>false</wait>
-            </configuration>
           </execution>
           <execution>
             <id>stop-container</id>
             <phase>post-integration-test</phase>
             <goals>
-                <goal>stop</goal>
+              <goal>stop</goal>
             </goals>
           </execution>
         </executions>
-        <configuration>
-          <container>
-            <containerId>${container.name}</containerId>
-            <zipUrlInstaller>
-              <url>${container.url}</url>
-              <installDir>${project.build.directory}/installs/${container.name}</installDir>
-            </zipUrlInstaller>
-            <log>${project.build.directory}/logs/${container.name}.log</log>
-            <output>${project.build.directory}/logs/${container.name}.out</output>
-            <timeout>600000</timeout>
-          </container>
-          <configuration>
-            <home>${project.build.directory}/${container.name}conf</home>
-            <type>existing</type>
-            <properties>
-              <cargo.servlet.port>9595</cargo.servlet.port>
-            </properties>
-          </configuration>
-        </configuration>
       </plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-surefire-plugin</artifactId>
+        <artifactId>maven-failsafe-plugin</artifactId>
+        <configuration>
+          <!-- Better to be able to see the results output from the listener as we go -->
+          <redirectTestOutputToFile>false</redirectTestOutputToFile>
+          <suiteXmlFiles>
+            <suiteXmlFile>src/test/testng/config/testng.xml</suiteXmlFile>
+          </suiteXmlFiles>
+        </configuration>
         <executions>
           <execution>
+            <id>integration-tests</id>
             <phase>integration-test</phase>
             <goals>
-              <goal>test</goal>
+              <goal>integration-test</goal>
+            </goals>
+            <configuration>
+              <systemProperties>
+                <property>
+                  <name>baseUrl</name>
+                  <value>${baseUrl}</value>
+                </property>
+                <property>
+                  <name>buildAgentUrl</name>
+                  <value>${buildAgentUrl}</value>
+                </property>
+                <property>
+                  <name>appserverBase</name>
+                  <value>${appserverBase}</value>
+                </property>
+                <property>
+                  <name>browser</name>
+                  <value>${browser}</value>
+                </property>
+                <property>
+                  <name>seleniumHost</name>
+                  <value>${seleniumHost}</value>
+                </property>
+                <property>
+                  <name>seleniumPort</name>
+                  <value>${seleniumPort}</value>
+                </property>
+              </systemProperties>
+            </configuration>
+          </execution>
+          <execution>
+            <id>verify-integration-tests</id>
+            <goals>
+              <goal>verify</goal>
             </goals>
           </execution>
         </executions>
-        <configuration>
-          <systemProperties>
-            <property>
-              <name>browser</name>
-              <value>${browser}</value>
-            </property>
-          </systemProperties>
-        </configuration>
       </plugin>
     </plugins>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.codehaus.mojo</groupId>
+          <artifactId>selenium-maven-plugin</artifactId>
+          <version>2.3</version>
+          <configuration>
+            <port>${seleniumPort}</port>
+            <background>true</background>
+            <logOutput>true</logOutput>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
   </build>
-  
+
+  <dependencies>
+    <dependency>
+      <groupId>org.testng</groupId>
+      <artifactId>testng</artifactId>
+      <version>6.2.1</version>
+      <scope>test</scope>
+    </dependency>
+
+    <!-- deployables -->
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-webapp</artifactId>
+      <type>war</type>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-buildagent-webapp</artifactId>
+      <type>war</type>
+    </dependency>
+
+    <!-- container dependencies -->
+    <dependency>
+      <groupId>org.apache.derby</groupId>
+      <artifactId>derby</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>javax.mail</groupId>
+      <artifactId>mail</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>javax.activation</groupId>
+      <artifactId>activation</artifactId>
+    </dependency>
+
+    <!-- dependencies below are for code in src/test/it -->
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-utils</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.seleniumhq.selenium.server</groupId>
+      <artifactId>selenium-server</artifactId>
+      <version>1.0.1</version>
+      <exclusions>
+        <exclusion>
+          <groupId>commons-logging</groupId>
+          <artifactId>commons-logging</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.seleniumhq.selenium.client-drivers</groupId>
+      <artifactId>selenium-java-client-driver</artifactId>
+      <version>1.0.1</version>
+      <scope>test</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>commons-logging</groupId>
+          <artifactId>commons-logging</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+  </dependencies>
+
   <profiles>
     <profile>
-      <id>tomcat5x</id>
+      <id>disable-cargo</id>
       <activation>
-        <activeByDefault>true</activeByDefault>
+        <property>
+          <name>baseUrl</name>
+        </property>
       </activation>
-      <properties>
-        <container.name>tomcat5x</container.name>
-        <container.url>http://apache.multidist.com/tomcat/tomcat-5/v5.5.20/bin/apache-tomcat-5.5.20.zip</container.url>
-      </properties>
+      <build>
+        <pluginManagement>
+          <plugins>
+            <plugin>
+              <groupId>org.codehaus.cargo</groupId>
+              <artifactId>cargo-maven2-plugin</artifactId>
+              <configuration>
+                <deployables>
+                  <!-- Skip all but test resources -->
+                  <deployable>
+                    <location>${basedir}/src/test/example-projects</location>
+                    <type>war</type>
+                    <properties>
+                      <context>example-projects</context>
+                    </properties>
+                  </deployable>
+                </deployables>
+              </configuration>
+            </plugin>
+          </plugins>
+        </pluginManagement>
+      </build>
     </profile>
-
+    <profile>
+      <id>disable-selenium-server</id>
+      <activation>
+        <property>
+          <name>seleniumHost</name>
+        </property>
+      </activation>
+      <build>
+        <pluginManagement>
+          <plugins>
+            <plugin>
+              <groupId>org.codehaus.mojo</groupId>
+              <artifactId>selenium-maven-plugin</artifactId>
+              <configuration>
+                <skip>true</skip>
+              </configuration>
+            </plugin>
+          </plugins>
+        </pluginManagement>
+      </build>
+    </profile>
     <profile>
       <id>firefox</id>
-      <activation>
-        <activeByDefault>true</activeByDefault>
-      </activation>
       <properties>
         <browser>*firefox</browser>
       </properties>
     </profile>
     <profile>
       <id>iexplore</id>
+      <activation>
+        <property>
+          <name>browser</name>
+          <value>iexplore</value>
+        </property>
+      </activation>
       <properties>
         <browser>*iexplore</browser>
       </properties>
     </profile>
     <profile>
+      <id>safari</id>
+      <activation>
+        <property>
+          <name>browser</name>
+          <value>safari</value>
+        </property>
+      </activation>
+      <properties>
+        <browser>*safari</browser>
+      </properties>
+    </profile>
+    <profile>
       <id>otherbrowser</id>
+      <activation>
+        <property>
+          <name>browser</name>
+          <value>other</value>
+        </property>
+      </activation>
       <properties>
         <browser>*custom ${browserPath}</browser>
       </properties>
     </profile>
+    <profile>
+      <id>headless</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>selenium-maven-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>xvfb</id>
+                <phase>validate</phase>
+                <goals>
+                  <goal>xvfb</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+    <profile>
+      <id>reporting</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-surefire-report-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>report-only</id>
+                <phase>integration-test</phase>
+                <goals>
+                  <goal>report-only</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+    <profile>
+      <id>tomcat7x</id>
+      <activation>
+        <activeByDefault>true</activeByDefault>
+        <!-- -DseleniumHost profile cancels this, so we need to trigger on that as well -->
+        <property>
+          <name>seleniumHost</name>
+        </property>
+      </activation>
+      <build>
+        <pluginManagement>
+          <plugins>
+            <plugin>
+              <groupId>org.codehaus.cargo</groupId>
+              <artifactId>cargo-maven2-plugin</artifactId>
+              <configuration>
+                <container>
+                  <zipUrlInstaller>
+                    <url>
+                      http://archive.apache.org/dist/tomcat/tomcat-7/v${tomcat7x.version}/bin/apache-tomcat-${tomcat7x.version}.zip
+                    </url>
+                    <downloadDir>${user.home}/.cargo</downloadDir>
+                  </zipUrlInstaller>
+                </container>
+              </configuration>
+            </plugin>
+          </plugins>
+        </pluginManagement>
+      </build>
+      <properties>
+        <container.name>tomcat7x</container.name>
+        <tomcat7x.version>7.0.29</tomcat7x.version>
+      </properties>
+    </profile>
+    <profile>
+      <id>jetty7x</id>
+      <build>
+        <pluginManagement>
+          <plugins>
+            <plugin>
+              <groupId>org.codehaus.cargo</groupId>
+              <artifactId>cargo-maven2-plugin</artifactId>
+              <configuration>
+                <container>
+                  <artifactInstaller>
+                    <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>jetty-distribution</artifactId>
+                    <version>${jetty7x.version}</version>
+                  </artifactInstaller>
+                </container>
+              </configuration>
+            </plugin>
+          </plugins>
+        </pluginManagement>
+      </build>
+      <properties>
+        <container.name>jetty7x</container.name>
+        <jetty7x.version>7.6.5.v20120716</jetty7x.version>
+      </properties>
+    </profile>
+    <profile>
+      <id>debug</id>
+      <properties>
+        <cargo.jvmargs>
+          -Xmx512m
+          -XX:MaxPermSize=128m
+          -Xdebug
+          -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005
+          -Xnoagent
+          -Djava.compiler=NONE
+        </cargo.jvmargs>
+      </properties>
+    </profile>
   </profiles>
+  <properties>
+    <seleniumHost>localhost</seleniumHost>
+    <seleniumPort>4444</seleniumPort>
+    <continuum.port>9595</continuum.port>
+    <baseUrl>http://localhost:${continuum.port}/continuum</baseUrl>
+    <buildAgentUrl>http://localhost:${continuum.port}/continuum-buildagent/xmlrpc</buildAgentUrl>
+    <appserverBase>${project.build.directory}</appserverBase>
+    <browser>*firefox</browser>
+    <browserPath/>
+    <cargo.jvmargs>-Xmx512m -XX:MaxPermSize=128m</cargo.jvmargs>
+    <plexus.system.path/>
+    <selenium.version>2.41.0</selenium.version>
+  </properties>
 </project>
diff --git a/continuum-webapp-test/src/appserver-base/conf/continuum-buildagent.xml b/continuum-webapp-test/src/appserver-base/conf/continuum-buildagent.xml
new file mode 100644
index 0000000..4dd5b87
--- /dev/null
+++ b/continuum-webapp-test/src/appserver-base/conf/continuum-buildagent.xml
@@ -0,0 +1,26 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+  ~ 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.
+  -->
+
+<continuum-buildagent-configuration>
+  <continuumServerUrl>${baseUrl}/master-xmlrpc</continuumServerUrl>
+  <buildOutputDirectory>target/data/build-agent/build-output-directory</buildOutputDirectory>
+  <workingDirectory>target/data/build-agent/working-directory</workingDirectory>
+  <sharedSecretPassword>continuum1234</sharedSecretPassword>
+</continuum-buildagent-configuration>
diff --git a/continuum-webapp-test/src/site/apt/index.apt b/continuum-webapp-test/src/site/apt/index.apt
new file mode 100644
index 0000000..5580ac7
--- /dev/null
+++ b/continuum-webapp-test/src/site/apt/index.apt
@@ -0,0 +1,503 @@
+  ----
+  Continuum Webapp Test
+  ----
+
+~~ 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.
+
+~~ NOTE: For help with the syntax of this file, see:
+~~ http://maven.apache.org/doxia/references/apt-format.html
+
+
+Continuum Webapp Test
+ 
+* Contents
+
+	* {{{About_the_Continuum_Webapp_Tests}About the Continuum Webapp Tests}}
+	
+	* {{Pre-requisites}}
+	
+	* {{{Getting_the_Source_from_the_Repository} Getting the Source from the Repository}}
+	
+	* {{{Running_the_Tests} Running the Tests}}
+	
+	* {{{Viewing_the_Test_Results} Viewing the Test Results}}
+	
+	* {{{Test_Coverage}Test Coverage}}
+	
+	* {{{Adding_New_Tests} Adding New Tests}}
+	
+	* {{{Improving_the_Existing_Tests} Improving the Existing Tests}}
+	
+	* {{{Creating_Patches} Creating Patches}}
+	
+	* {{{Submitting_Patches} Submitting Patches}}	
+	
+
+* {About the Continuum Webapp Tests}
+
+	{{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp-test}Continuum web app tests}} depends on {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp} continuum-webapp}} module of Continuum. It depends on a successful build result in {{{https://svn.apache.org/repos/asf/continuum/trunk} continuum-trunk}}. 
+
+** Automation Tool
+	
+	The module makes use of the latest {{{http://seleniumhq.org/projects/remote-control/} Selenium Remote Control}} release (1.0.1)
+	
+		* {{{http://release.seleniumhq.org/selenium-remote-control/1.0-beta-2/doc/java/} selenium-java-client-driver}}
+		
+		* {{{http://release.seleniumhq.org/selenium-remote-control/1.0-beta-2/doc/server/} selenium-server}}
+		
+		<Note: Documents for 1.0.1 are not yet available for both selenium java client driver and selenium server. The above links direct to 1.0-beta-2 docs.>
+		
+** Maven Plugins
+	
+	The module makes use of the following maven plugins:
+	
+		* {{{http://cargo.codehaus.org/Maven2+plugin} cargo-maven2-plugin}} who is in-charge on the start-up of the container {{{http://apache.mirrors.redwire.net/tomcat/tomcat-5/v5.5.27/bin/apache-tomcat-5.5.27.zip]} tomcat5x}}, deployment of the application to the container and stopping the container. 
+		
+		* {{{http://mojo.codehaus.org/selenium-maven-plugin/} selenium-maven-plugin}} who is in-charge on starting/stopping the selenium server, running a suite of HTML Selenese tests and starting an Xvfb instance suitable for handling X11 displays for headless systems.
+		
+		*{{{http://maven.apache.org/plugins/maven-surefire-plugin/} maven-surefire-plugin}} and {{{http://maven.apache.org/plugins/maven-surefire-report-plugin/} maven-surefire-report-plugin}} for reporting.
+		
+** Testing Framework
+
+	Continuum web app tests module uses TestNG for the following reasons:
+
+		* flexibility (coding convention), 
+		
+		* dependency testing (skipping not failing), 
+		
+		* fail and rerun (handy in large test suite) and 
+		
+		* parametric testing ( reusing generic test) features. 
+		
+		More on TestNG {{{http://testng.org/doc/documentation-main.html}here}}.
+
+	View the module's pom.xml {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp-test/pom.xml}here}}
+
+* {Pre-requisites}
+
+		* {{{http://java.sun.com/javase/downloads/index.jsp}JDK 1.5 or higher}}
+
+		* {{{http://maven.apache.org/download.html}Maven 2.0.9 or higher}}
+
+		* {{{http://subversion.tigris.org/}Subversion}}
+
+	Installation instructions for Windows and Unix-based systems can be found {{{http://maven.apache.org/download.html}here}}
+
+* {Getting the Source from the Repository}
+
+	Checkout continuum trunk {{{https://svn.apache.org/repos/asf/continuum/trunk}here}}.
+
++-----------------------------------------------------------------------------+
+svn co https://svn.apache.org/repos/asf/continuum/trunk continuum-trunk
+or
+svn co http://svn.apache.org/repos/asf/continuum/trunk continuum-trunk
++-----------------------------------------------------------------------------+
+
+* {Running the Tests}
+
+	Getting started with the tests:
+
+	After getting the source from the repository, execute the following:
+	
++-----------------------------------------------------------------------------+
+cd /path/to/continuum-trunk/
+mvn clean install
++-----------------------------------------------------------------------------+
+
+
+	<<Reminder: Continuum-trunk must have a successful build or else there's no way to run continuum-webapp-test successfully.>>	
+
+	
++-----------------------------------------------------------------------------+
+cd /path/to/continuum-trunk/continuum-webapp-test/
++-----------------------------------------------------------------------------+
+
+	Default configuration (i.e. App's Base URL, Selenium Host, Selenium Port's values, etc.) are stored in a property file that can be found in <</path/to/continuum-trunk/continuum-webapp-test/src/test/resources/testng.properties>> (or {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp-test/src/test/resources/testng.properties}here}}). You may change the values in it before executing the next command.
+
++-----------------------------------------------------------------------------+
+mvn clean install
++-----------------------------------------------------------------------------+
+
+	This command will:
+
+		* build the application from source
+	
+		* deploy the packaged application to a container and start it
+	
+		*  start the selenium server
+
+		*  start the selenium tests by launching the selenium test runner and the application under test (AUT)
+		
+		For every test failure encountered, {{{http://testng.org/doc/documentation-main.html#logging-listeners}TestNG Listeners}} will call selenium's windowMaximize and captureEntirePageScreenshot commands. This will maximize the application-under-test (AUT) browser then do a screen capture of the page and saves it as an image file with .png extension.
+		
+		View the code {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/listener/CaptureScreenShotsListener.java}here}} 
+		
+		* kill the selenium server after the tests are done
+		
+		* stop the app server (container)
+		
+		* return the results of the build (summary, reports, screen shots)
+
+[]
+
+** {Running selected tests by editing testng.xml}
+
+	Continuum web app tests is invoked with a {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp-test/src/test/testng/config/testng.xml}testng.xml}} file. The contents of that xml file is displayed below and/or this could be found in <</path/to/continuum-trunk/continuum-webapp-test/src/test/testng/config/>> directory.
+
++---------------------------------------------------------+
+<suite name="ContinuumTest" verbose="1">
+   <test name="BasicTest" enabled="true">
+     <groups>
+	<run>
+	   <include name="about" />
+	</run>
+     </groups>
+     <packages>
+	<package name="org.apache.continuum.web.test" />
+     </packages>
+   </test>
+   <test name="AdminTest" enabled="true">
+     <groups>
+	<run>
+	   <include name="login" />
+	   <include name="mavenTwoProject"/>								
+	   <include name="projectGroup" />				
+      	   <include name="mavenOneProject" />
+      	   <include name="antProject" />
+      	   <include name="shellProject" />
+           <include name="buildDefinition" />
+           <include name="notifier" />
+	   <include name="schedule" />
+	   <include name="myAccount" />
+	   <include name="queue" />
+	   <include name="purge" />
+	   <include name="repository" />
+	   <include name="configuration" />
+	   <include name="installation" />
+	   <include name="buildEnvironment" />
+	   <include name="buildDefinitionTemplate" />
+	   <include name="userroles"/>
+	   <include name="agent"/>
+	</run>
+     </groups>
+     <packages>
+	<package name="org.apache.continuum.web.test" />
+     </packages>
+   </test>
+</suite>
++---------------------------------------------------------+
+
+	The order of the build when running the tests is defined in the annotations of each test. Groups are divided into unit tests. If want to run a specific test, you may edit the testng.xml file and exclude the undesired tests to be ran.
+
++---------------------------------------------------------+
+Example:
+
+<test name="AdminTest" enabled="true">
+     <groups>
+	<run>
+	   <include name="login" />
+	   <exclude name="mavenTwoProject"/>								
+	   <exclude name="projectGroup" />				
+      	   <exclude name="mavenOneProject" />
+      	   <include name="antProject" />
+      	   <exclude name="shellProject" />
+           ...
+           ...
+           ...
+	</run>
+     </groups>
+     <packages>
+	<package name="org.apache.continuum.web.test" />
+     </packages>
+   </test>
++---------------------------------------------------------+
+
+	More information about testng.xml {{{http://testng.org/doc/documentation-main.html#testng-xml}here}}.
+
+
+** Running the tests with different container and/or browsers
+
+*** Running Selenium tests in an alternate browser
+
+	Modify src/test/resources/testng.properties as needed then execute:
+	
++---------------------------------------------------------+
+mvn clean install -Dbrowser=iexplore  (or -Dbrowser=safari or -Dbrowser=other -DbrowserPath=/path/to/browser)
++---------------------------------------------------------+
+
+*** Running Selenium tests against an existing Continuum instance
+
+	Modify src/test/resources/testng.properties as needed, then execute:
+	
++---------------------------------------------------------+
+mvn clean install -Dexisting-container
++---------------------------------------------------------+
+
+	(This skips the Cargo plugin configuration that starts a container with the Continuum webapp deployed)
+
+*** Test with Firefox and Selenium IDE
+
+	continuum-webapp-test also has Selenium IDE scripts. Here's how you should run it:
+
+		* Start Continuum
+		
+		* Open Firefox and navigate to Continuum (it should be on the "Create Admin User" page.)
+		
+		* in Firefox, Tools -> Selenium IDE 
+		
+		* in Selenium IDE, File -> Open Test Suite and choose src/test/selenium-ide/continuum_test_suite.html
+		
+		* in Selenium IDE, modify the Base URL if necessary (for example, http://localhost:8080/continuum)
+		
+		* in Selenium IDE, click the 'Play entire test suite' icon
+
+* {Viewing the Test Results}
+
+** Surefire-reports
+
+	After running the continuum webapp tests, cd to <</path/to/continuum-trunk/continuum-webapp-test/target/surefire-reports/>> and open the index.html file.
+	
+	Click the 'ContinuumTest' suite link
+	
+	Click the 'Results' link to view the summary of the tests. (Passed/Failed/Skipped)
+	
+** Screenshots
+
+	If there are test failures, cd to <</path/to/continuum-trunk/continuum-webapp-test/target/screenshots/>> to view the captured image files.
+	
+	Screen shots are saved with the format "methodName(className.java_lineNumber)-time.png" in order to easily debug the error encountered.
+
+* {Test Coverage}
+
+	Test scripts available {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/}here}} automate the various {{{http://continuum.apache.org/features.html}features}} of Continuum. Listed below are the existing scripts with which you can help improve the testing process or you may contribute on any areas you see not covered.
+
+	* {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/AboutTest.java}About}}
+
+	* {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/LoginTest.java}Login}}
+
+	* {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/MyAccountTest.java}My Account}}
+
+	* {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/ProjectGroupTest.java}Project Groups}}
+	
+	* {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/MavenOneProjectTest.java}Maven 1.x Projects}}
+	
+	* {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/MavenTwoProjectTest.java}Maven Projects}}
+	
+	* {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/AntProjectTest.java}Ant Projects}}
+	
+	* {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/ShellProjectTest.java}Shell Projects}}
+	
+	* {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/LocalRepositoriesTest.java}Local Repository}}
+	
+	* {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/InstallationTest.java}Installation}}
+	
+	* {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/PurgeTest.java}Purge Configurations}}
+	
+	* {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/ScheduleTest.java}Schedules}}
+	
+	* {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/ConfigurationTest.java}Configurations}}
+	
+	* {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/UserRolesManagementTest.java}User Roles Management}}
+	
+	* {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/BuildEnvironmentTest.java}Build Environments}}
+	
+	* {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/QueueTest.java}Queues}}
+	
+	* {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/BuildDefinitionTest.java}Build Definition}}
+	
+	* {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/BuildDefinitionTemplateTest.java}Build Definition Templates}}
+	
+	* {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/BuildAgentsTest.java}Distributed Builds}}
+	
+	* {{{https://svn.apache.org/repos/asf/continuum/trunk/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/NotifierTest.java}Build Notification}}
+	
+	[]
+
+** Continuum Feature/s for development:
+
+	* Release Projects
+	
+[]
+	
+	If you would like to be involved, start by reading the Continuum {{{http://continuum.apache.org/docs/}documentation}} to familiarize yourself with the features of the application. 
+
+
+* {Adding New Tests}
+
+	This section will guide you on how to contribute new script/s to run with the existing ones.
+
+	You can find out what features already have tests by looking at the source code of the scripts on the {{{Test_Coverage} Test Coverage}} section. If you look at the scripts, you can see which features have lots of tests and which need more. But note that even if the coverage looks good, there may be more interesting tests to write.
+
+** Directory where to add new tests
+
+	Once you have written a good test scenario, the script must be placed in this directory:
+
++---------------------------------------------------------+
+/path/to/continuum-trunk/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/
++---------------------------------------------------------+
+
+	Put your abstract classes in this directory:
+	
++---------------------------------------------------------+
+/path/to/continuum-trunk/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/parent/
++---------------------------------------------------------+
+
+~~** Order where to put the new class
+** Editing the testng.xml file to include the new class / group
+
+	* Edit the testng.xml (refer to {{{Running_selected_tests_by_editing_testng.xml} Editing testng.xml}}) to include the newly created script. 
+	
+	* Run the test suite (refer to {{{Running_the_Tests} Running the Tests}}) to check if it will build successfully. 
+
+	[]
+	Once you have a successful build in continuum-webapp-test, you are now ready to create a patch and submit your work to the community. Just follow the guidelines on the {{{Creating_Patches} Creating Patches}} and {{{Submitting_Patches} Submitting Patches}} section.
+
+* {Improving the Existing Tests}
+
+	The listed items on continuum-webapp-test Test Coverage are not yet complete. Releasing Projects is one of the features listed for development but basically, the existing scripts still have missing scenarios that need to be completed, such as:
+
+	[[1]] Functions of Continuum Features to Projects
+	
+	* Wide use of Continuum features to different projects (i.e. the use of different build definitions, schedules, queues, agent, etc. ) --ant, shell, maven1, maven2.
+	
+	
+	[]
+	
+	[[2]] User Roles Test
+	
+	* User roles tests only have scripts for assertion of elements on the specific roles. Tests for user roles should include its specific function on Continuum.
+	
+	[]
+	
+	[[3]]Logo / Headers / Footers
+	
+	* Assertion of Logo / Headers / Footers on each page (or scenarios) are not yet implemented.
+	
+	[]
+	
+	[[4]]Optimization of the Automation Tool and Test Framework
+	
+	* Selenium and TestNG have lots of capabilities that will help improve the existing tests. Discussed below are the items that are not yet implemented on the existing tests:
+For reporting, the generated report of surefire for TestNG has a text and html file. Improving the html file that would link to the screenshots of the failed tests would help a lot.
+	
+	* The wide use of TestNG, i.e. The use or @Parameters for values to be used on that specific test class. It will help developers not to be confused with regards to values that are placed in the property files (lots of values on that file) and those values will also be placed on the TestNG report. 
+
+[]
+
+	As listed above, those are just examples on how to improve Continuum's existing tests. As you go along with the scripts, you may encounter scenarios that need to be modified so that it will be easily read by fellow developers. Tests contributions are welcome in this community. See {{{Adding_New_Tests} Adding New Tests}} section on how.
+
+
+
+* {Creating Patches}
+
+	After adding new tests or improving existing tests, the next step is to create a patch.
+
+	Below are the steps needed for creating patches:
+
+	* Update the version of the project's source. 
+	
++---------------------------------------------------------+
+svn up
++---------------------------------------------------------+
+
+	* Ensure that the project will build successfully (from trunk) and that your modification will not break anything
+	
++---------------------------------------------------------+
+mvn clean install
++---------------------------------------------------------+
+	
+	* Go to the directory where the modifications are done. Verify if the module's build is working. (i.e. /path/to/continuum-trunk/continuum-webapp-test/)
+	
++---------------------------------------------------------+
+mvn clean install
++---------------------------------------------------------+
+
+	* After a successful build, add the new tests to version control.
+	
+
+		Directory:
+	
++---------------------------------------------------------+
+svn add /path/to/the/new_module/
++---------------------------------------------------------+
+
+		
+		File:
+	
++---------------------------------------------------------+
+svn add /path/to/the/new_module/file.extension
++---------------------------------------------------------+
+
+	Note: If the modifications are made to the existing files which are already under version control, there is no need to do "svn add".
+	
+	* Create the patch from the trunk
+	
++---------------------------------------------------------+
+cd /path/to/continuum-trunk/
++---------------------------------------------------------+
+
++---------------------------------------------------------+
+svn diff > PatchName.patch
++---------------------------------------------------------+
+
+	* Verify the content of the generated patch by viewing the file using any text editor. It should display all the intended changes.
+
+* {Submitting Patches}
+
+	After creating the patch, the next step is to contribute by sending the patch to the community!
+	
+	* If you don't have a codehaus jira account yet, sign up {{{http://jira.codehaus.org/secure/Signup!default.jspa} here}}
+	
+	* Login using your account
+	
+	* Go to {{{http://jira.codehaus.org/browse/CONTINUUM}Continuum}} project
+	
+	* Create a new issue with the appropriate issue type (bug, improvement, feature, test, etc)
+	
+	* Provide a good summary
+	
++---------------------------------------------------------+
+New Tests for X Feature
+or 
+Improve Tests for an Existing X Feature
++---------------------------------------------------------+
+
+	* Provide the environment details
+	
++---------------------------------------------------------+
+Windows/Linux/Mac
+Maven version
+Java version
++---------------------------------------------------------+
+
+	* Provide the description
+	
++---------------------------------------------------------+
+Describe what the patch is for. (changes made to the existing version)
+Post the results of the build (test runs, failures, errors etc)
++---------------------------------------------------------+
+
+	* Don't forget to add your patch as an attachment. Tick the 'Patch Submitted' box then click the 'Create' button.
+
+
+	<<If nothing happens in a few days, write to the {{{mailto:dev@continuum.apache.org}dev list}} and nudge the developers to review your patch.>>
+
+		
+
+
+
diff --git a/continuum-webapp-test/src/test/example-projects/ant/build.xml b/continuum-webapp-test/src/test/example-projects/ant/build.xml
new file mode 100644
index 0000000..9d19f47
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-projects/ant/build.xml
@@ -0,0 +1,6 @@
+<project name="ant-project" default="build">
+  <target name="build">
+    <echo>Hello, Ant!</echo>
+  </target>
+</project>
+
diff --git a/continuum-webapp-test/src/test/example-projects/continuum-2437-example/pom.xml b/continuum-webapp-test/src/test/example-projects/continuum-2437-example/pom.xml
new file mode 100644
index 0000000..023a110
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-projects/continuum-2437-example/pom.xml
@@ -0,0 +1,24 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.continuum.examples</groupId>
+  <artifactId>continuum-2437-example</artifactId>
+  <packaging>jar</packaging>
+  <version>1.1-SNAPSHOT</version>
+  <name>Continuum 2437 Example Project</name>
+  <url>http://continuum.apache.org</url>
+
+  <scm>
+    <connection>scm:svn:${svn.base.url}/trunk/continuum-2437-example</connection>
+    <developerConnection>scm:svn:${svn.base.url}/trunk/continuum-2437-example</developerConnection>
+    <tag>${svn.base.url}/tags/continuum-2437-example-1.0</tag>
+  </scm>
+
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.2</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/continuum-webapp-test/src/test/example-projects/continuum-2437-example/src/main/java/org/apache/continuum/examples/App.java b/continuum-webapp-test/src/test/example-projects/continuum-2437-example/src/main/java/org/apache/continuum/examples/App.java
new file mode 100644
index 0000000..82e058d
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-projects/continuum-2437-example/src/main/java/org/apache/continuum/examples/App.java
@@ -0,0 +1,13 @@
+package org.apache.continuum.examples;
+
+/**
+ * Hello world!
+ *
+ */
+public class App 
+{
+    public static void main( String[] args )
+    {
+        System.out.println( "Hello World!" );
+    }
+}
diff --git a/continuum-webapp-test/src/test/example-projects/continuum-2437-example/src/test/java/org/apache/continuum/examples/AppTest.java b/continuum-webapp-test/src/test/example-projects/continuum-2437-example/src/test/java/org/apache/continuum/examples/AppTest.java
new file mode 100644
index 0000000..e521181
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-projects/continuum-2437-example/src/test/java/org/apache/continuum/examples/AppTest.java
@@ -0,0 +1,38 @@
+package org.apache.continuum.examples;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Unit test for simple App.
+ */
+public class AppTest 
+    extends TestCase
+{
+    /**
+     * Create the test case
+     *
+     * @param testName name of the test case
+     */
+    public AppTest( String testName )
+    {
+        super( testName );
+    }
+
+    /**
+     * @return the suite of tests being tested
+     */
+    public static Test suite()
+    {
+        return new TestSuite( AppTest.class );
+    }
+
+    /**
+     * Rigourous Test :-)
+     */
+    public void testApp()
+    {
+        assertTrue( true );
+    }
+}
diff --git a/continuum-webapp-test/src/test/example-projects/continuum-build-queue-test-data/pom.xml b/continuum-webapp-test/src/test/example-projects/continuum-build-queue-test-data/pom.xml
new file mode 100644
index 0000000..5e6b59c
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-projects/continuum-build-queue-test-data/pom.xml
@@ -0,0 +1,87 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.continuum</groupId>
+  <artifactId>continuum-build-queue-test-data</artifactId>
+  <packaging>pom</packaging>
+  <version>1.0-SNAPSHOT</version>
+  <name>ContinuumBuildQueueTestData</name>
+  <description>Project for testing continuum build queue</description>  
+  <dependencies>
+    <dependency>
+      <groupId>org.testng</groupId>
+      <artifactId>testng</artifactId>
+      <version>5.8</version>
+      <scope>test</scope>
+      <classifier>jdk15</classifier>
+    </dependency>
+  </dependencies>
+  
+  <scm>
+    <connection>scm:svn:${svn.base.url}/trunk/continuum-build-queue-test-data</connection>
+    <developerConnection>scm:svn:${svn.base.url}/trunk/continuum-build-queue-test-data</developerConnection>
+    <url>${svn.base.url}/trunk/continuum-build-queue-test-data</url>
+  </scm>
+
+  <build>
+    <plugins>   	
+        <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-compiler-plugin</artifactId>
+            <version>2.0.2</version>
+            <configuration>
+               <source>1.5</source>
+               <target>1.5</target>
+               <encoding>UTF-8</encoding>
+            </configuration>      
+			<executions>
+			 <execution>
+            <goals>
+              <goal>testCompile</goal>
+            </goals>
+            </execution>
+			</executions>
+		</plugin>
+       <plugin>
+        <artifactId>maven-resources-plugin</artifactId>
+        <executions>
+          <execution>
+            <goals>
+              <goal>testResources</goal>
+            </goals>
+          </execution>
+        </executions>
+		</plugin>
+	 <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <suiteXmlFiles>
+            <suiteXmlFile>src/test/java/config/testng.xml</suiteXmlFile>
+          </suiteXmlFiles>
+        </configuration>
+        <executions>
+          <execution>
+            <id>integration-tests</id>
+            <phase>integration-test</phase>
+            <goals>
+              <goal>test</goal>
+            </goals>
+          </execution>
+        </executions>
+       </plugin>   
+     </plugins>
+   </build>
+	  
+      
+   
+   <developers>
+      <developer>
+        <id>blago</id>
+        <name>Bernard Lago</name>
+        <roles>
+          <role>QA Engineer</role>
+        </roles>
+        <timezone>+8</timezone>
+      </developer>
+   </developers> 
+</project>
diff --git a/continuum-webapp-test/src/test/example-projects/continuum-build-queue-test-data/src/test/java/config/testng.xml b/continuum-webapp-test/src/test/example-projects/continuum-build-queue-test-data/src/test/java/config/testng.xml
new file mode 100644
index 0000000..8ae8fba
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-projects/continuum-build-queue-test-data/src/test/java/config/testng.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
+<!--
+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.
+-->
+
+<suite name="MaestroProjectServerTest" verbose="1">
+	<test name="BasicTest" enabled="true">
+
+		<packages>
+			<package name="org.apache.continuum.examples" />
+		</packages>
+	</test>
+</suite>
diff --git a/continuum-webapp-test/src/test/example-projects/continuum-build-queue-test-data/src/test/java/org/apache/continuum/examples/BasicThreadTest.java b/continuum-webapp-test/src/test/example-projects/continuum-build-queue-test-data/src/test/java/org/apache/continuum/examples/BasicThreadTest.java
new file mode 100644
index 0000000..b6ecf65
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-projects/continuum-build-queue-test-data/src/test/java/org/apache/continuum/examples/BasicThreadTest.java
@@ -0,0 +1,16 @@
+package org.apache.continuum.examples;
+
+import org.testng.annotations.Test;
+
+public class BasicThreadTest {
+	
+	@Test
+	public void testThread() {
+	    try {
+	        long numMillisecondsToSleep = 60000; // 1 * 60 seconds
+	        Thread.sleep(numMillisecondsToSleep);
+	    } catch (InterruptedException e) {
+	    }
+	}
+
+}
diff --git a/continuum-webapp-test/src/test/example-projects/continuum-failing-project/pom.xml b/continuum-webapp-test/src/test/example-projects/continuum-failing-project/pom.xml
new file mode 100644
index 0000000..d2da023
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-projects/continuum-failing-project/pom.xml
@@ -0,0 +1,32 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.continuum.failing.project</groupId>
+  <artifactId>continuum-failing-project</artifactId>
+  <version>1.0-SNAPSHOT</version>
+  <packaging>jar</packaging>
+
+  <name>Continuum Sample Failing Project</name>
+  <description>Sample project that has a build failure</description>
+  <url>http://maven.apache.org</url>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <scm>
+    <connection>scm:svn:${svn.base.url}/trunk/continuum-failing-project</connection>
+    <developerConnection>scm:svn:${svn.base.url}/trunk/continuum-failing-project</developerConnection>
+    <url>${svn.base.url}/trunk/continuum-failing-project</url>
+  </scm>
+
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.1</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/continuum-webapp-test/src/test/example-projects/continuum-failing-project/src/main/java/org/apache/continuum/App.java b/continuum-webapp-test/src/test/example-projects/continuum-failing-project/src/main/java/org/apache/continuum/App.java
new file mode 100644
index 0000000..b57685a
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-projects/continuum-failing-project/src/main/java/org/apache/continuum/App.java
@@ -0,0 +1,13 @@
+package org.apache.continuum;
+
+/**
+ * Hello world!
+ *
+ */
+public class App 
+{
+    public static void main( String[] args )
+    {
+        System.out.println( "Hello World!" )
+    }
+}
diff --git a/continuum-webapp-test/src/test/example-projects/continuum-failing-project/src/test/java/org/apache/continuum/AppTest.java b/continuum-webapp-test/src/test/example-projects/continuum-failing-project/src/test/java/org/apache/continuum/AppTest.java
new file mode 100644
index 0000000..db7acbe
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-projects/continuum-failing-project/src/test/java/org/apache/continuum/AppTest.java
@@ -0,0 +1,38 @@
+package org.apache.continuum;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Unit test for simple App.
+ */
+public class AppTest 
+    extends TestCase
+{
+    /**
+     * Create the test case
+     *
+     * @param testName name of the test case
+     */
+    public AppTest( String testName )
+    {
+        super( testName );
+    }
+
+    /**
+     * @return the suite of tests being tested
+     */
+    public static Test suite()
+    {
+        return new TestSuite( AppTest.class );
+    }
+
+    /**
+     * Rigourous Test :-)
+     */
+    public void testApp()
+    {
+        assertTrue( true );
+    }
+}
diff --git a/continuum-webapp-test/src/test/example-projects/flat-example/flat-core/pom.xml b/continuum-webapp-test/src/test/example-projects/flat-example/flat-core/pom.xml
new file mode 100644
index 0000000..eefc524
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-projects/flat-example/flat-core/pom.xml
@@ -0,0 +1,24 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.example.flat</groupId>
+    <artifactId>flat-parent</artifactId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>flat-core</artifactId>
+  <packaging>jar</packaging>
+  <name>flat-core</name>
+  <url>http://maven.apache.org</url>
+
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.1</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/continuum-webapp-test/src/test/example-projects/flat-example/flat-core/src/main/java/com/example/flat/App.java b/continuum-webapp-test/src/test/example-projects/flat-example/flat-core/src/main/java/com/example/flat/App.java
new file mode 100644
index 0000000..bdcf5a4
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-projects/flat-example/flat-core/src/main/java/com/example/flat/App.java
@@ -0,0 +1,13 @@
+package com.example.flat;
+
+/**
+ * Hello world!
+ *
+ */
+public class App 
+{
+    public static void main( String[] args )
+    {
+        System.out.println( "Hello World!" );
+    }
+}
diff --git a/continuum-webapp-test/src/test/example-projects/flat-example/flat-core/src/test/java/com/example/flat/AppTest.java b/continuum-webapp-test/src/test/example-projects/flat-example/flat-core/src/test/java/com/example/flat/AppTest.java
new file mode 100644
index 0000000..d35ea33
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-projects/flat-example/flat-core/src/test/java/com/example/flat/AppTest.java
@@ -0,0 +1,38 @@
+package com.example.flat;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Unit test for simple App.
+ */
+public class AppTest 
+    extends TestCase
+{
+    /**
+     * Create the test case
+     *
+     * @param testName name of the test case
+     */
+    public AppTest( String testName )
+    {
+        super( testName );
+    }
+
+    /**
+     * @return the suite of tests being tested
+     */
+    public static Test suite()
+    {
+        return new TestSuite( AppTest.class );
+    }
+
+    /**
+     * Rigourous Test :-)
+     */
+    public void testApp()
+    {
+        assertTrue( true );
+    }
+}
diff --git a/continuum-webapp-test/src/test/example-projects/flat-example/flat-parent/pom.xml b/continuum-webapp-test/src/test/example-projects/flat-example/flat-parent/pom.xml
new file mode 100644
index 0000000..64c6855
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-projects/flat-example/flat-parent/pom.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>com.example.flat</groupId>
+  <artifactId>flat-parent</artifactId>
+  <version>1.0-SNAPSHOT</version>
+  <packaging>pom</packaging>
+  <name>Flat Example</name>
+
+  <scm>
+    <connection>scm:svn:${svn.base.url}/trunk/flat-example/flat-parent</connection>
+    <developerConnection>scm:svn:${svn.base.url}/trunk/flat-example/flat-parent</developerConnection>
+  </scm>
+
+  <modules>
+    <module>../flat-webapp</module>
+    <module>../flat-core</module>
+  </modules>
+
+</project>
diff --git a/continuum-webapp-test/src/test/example-projects/flat-example/flat-webapp/pom.xml b/continuum-webapp-test/src/test/example-projects/flat-example/flat-webapp/pom.xml
new file mode 100644
index 0000000..a08265f
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-projects/flat-example/flat-webapp/pom.xml
@@ -0,0 +1,32 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.example.flat</groupId>
+    <artifactId>flat-parent</artifactId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>flat-webapp</artifactId>
+  <packaging>war</packaging>
+  <name>flat-webapp Maven Webapp</name>
+  <url>http://maven.apache.org</url>
+
+  <dependencies>
+    <dependency>
+      <groupId>com.example.flat</groupId>
+      <artifactId>flat-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.1</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+  <build>
+    <finalName>flat-webapp</finalName>
+  </build>
+</project>
diff --git a/continuum-webapp-test/src/test/example-projects/flat-example/flat-webapp/src/main/webapp/WEB-INF/web.xml b/continuum-webapp-test/src/test/example-projects/flat-example/flat-webapp/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..9f88c1f
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-projects/flat-example/flat-webapp/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,7 @@
+<!DOCTYPE web-app PUBLIC
+ "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+ "http://java.sun.com/dtd/web-app_2_3.dtd" >
+
+<web-app>
+  <display-name>Archetype Created Web Application</display-name>
+</web-app>
diff --git a/continuum-distributed-build/continuum-buildagent/continuum-buildagent-webapp/src/main/webapp/index.jsp b/continuum-webapp-test/src/test/example-projects/flat-example/flat-webapp/src/main/webapp/index.jsp
similarity index 100%
rename from continuum-distributed-build/continuum-buildagent/continuum-buildagent-webapp/src/main/webapp/index.jsp
rename to continuum-webapp-test/src/test/example-projects/flat-example/flat-webapp/src/main/webapp/index.jsp
diff --git a/continuum-webapp-test/src/test/resources/unit/maven-one-projects/extend-element-project.xml b/continuum-webapp-test/src/test/example-projects/maven-one-projects/extend-element-project.xml
similarity index 100%
rename from continuum-webapp-test/src/test/resources/unit/maven-one-projects/extend-element-project.xml
rename to continuum-webapp-test/src/test/example-projects/maven-one-projects/extend-element-project.xml
diff --git a/continuum-webapp-test/src/test/resources/unit/maven-one-projects/missing-repository-element-project.xml b/continuum-webapp-test/src/test/example-projects/maven-one-projects/missing-repository-element-project.xml
similarity index 100%
rename from continuum-webapp-test/src/test/resources/unit/maven-one-projects/missing-repository-element-project.xml
rename to continuum-webapp-test/src/test/example-projects/maven-one-projects/missing-repository-element-project.xml
diff --git a/continuum-webapp-test/src/test/resources/unit/maven-one-projects/unparseable-content-project.xml b/continuum-webapp-test/src/test/example-projects/maven-one-projects/unparseable-content-project.xml
similarity index 100%
rename from continuum-webapp-test/src/test/resources/unit/maven-one-projects/unparseable-content-project.xml
rename to continuum-webapp-test/src/test/example-projects/maven-one-projects/unparseable-content-project.xml
diff --git a/continuum-webapp-test/src/test/resources/unit/maven-one-projects/valid-project.xml b/continuum-webapp-test/src/test/example-projects/maven-one-projects/valid-project.xml
similarity index 100%
rename from continuum-webapp-test/src/test/resources/unit/maven-one-projects/valid-project.xml
rename to continuum-webapp-test/src/test/example-projects/maven-one-projects/valid-project.xml
diff --git a/continuum-webapp-test/src/test/resources/unit/maven-two-projects/missing-connection-element-pom.xml b/continuum-webapp-test/src/test/example-projects/maven-two-projects/missing-connection-element-pom.xml
similarity index 100%
rename from continuum-webapp-test/src/test/resources/unit/maven-two-projects/missing-connection-element-pom.xml
rename to continuum-webapp-test/src/test/example-projects/maven-two-projects/missing-connection-element-pom.xml
diff --git a/continuum-webapp-test/src/test/resources/unit/maven-two-projects/missing-modules-pom.xml b/continuum-webapp-test/src/test/example-projects/maven-two-projects/missing-modules-pom.xml
similarity index 100%
rename from continuum-webapp-test/src/test/resources/unit/maven-two-projects/missing-modules-pom.xml
rename to continuum-webapp-test/src/test/example-projects/maven-two-projects/missing-modules-pom.xml
diff --git a/continuum-webapp-test/src/test/resources/unit/maven-two-projects/missing-parent-pom.xml b/continuum-webapp-test/src/test/example-projects/maven-two-projects/missing-parent-pom.xml
similarity index 100%
rename from continuum-webapp-test/src/test/resources/unit/maven-two-projects/missing-parent-pom.xml
rename to continuum-webapp-test/src/test/example-projects/maven-two-projects/missing-parent-pom.xml
diff --git a/continuum-webapp-test/src/test/resources/unit/maven-two-projects/missing-scm-element-pom.xml b/continuum-webapp-test/src/test/example-projects/maven-two-projects/missing-scm-element-pom.xml
similarity index 100%
rename from continuum-webapp-test/src/test/resources/unit/maven-two-projects/missing-scm-element-pom.xml
rename to continuum-webapp-test/src/test/example-projects/maven-two-projects/missing-scm-element-pom.xml
diff --git a/continuum-webapp-test/src/test/resources/unit/maven-two-projects/missing-type-element-pom.xml b/continuum-webapp-test/src/test/example-projects/maven-two-projects/missing-type-element-pom.xml
similarity index 100%
rename from continuum-webapp-test/src/test/resources/unit/maven-two-projects/missing-type-element-pom.xml
rename to continuum-webapp-test/src/test/example-projects/maven-two-projects/missing-type-element-pom.xml
diff --git a/continuum-webapp-test/src/test/resources/unit/maven-two-projects/multi-module-maven-project/maven-two-multi-module-project-module1/pom.xml b/continuum-webapp-test/src/test/example-projects/maven-two-projects/multi-module-maven-project/maven-two-multi-module-project-module1/pom.xml
similarity index 100%
rename from continuum-webapp-test/src/test/resources/unit/maven-two-projects/multi-module-maven-project/maven-two-multi-module-project-module1/pom.xml
rename to continuum-webapp-test/src/test/example-projects/maven-two-projects/multi-module-maven-project/maven-two-multi-module-project-module1/pom.xml
diff --git a/continuum-webapp-test/src/test/resources/unit/maven-two-projects/multi-module-maven-project/maven-two-multi-module-project-module2/pom.xml b/continuum-webapp-test/src/test/example-projects/maven-two-projects/multi-module-maven-project/maven-two-multi-module-project-module2/pom.xml
similarity index 100%
rename from continuum-webapp-test/src/test/resources/unit/maven-two-projects/multi-module-maven-project/maven-two-multi-module-project-module2/pom.xml
rename to continuum-webapp-test/src/test/example-projects/maven-two-projects/multi-module-maven-project/maven-two-multi-module-project-module2/pom.xml
diff --git a/continuum-webapp-test/src/test/resources/unit/maven-two-projects/multi-module-maven-project/pom.xml b/continuum-webapp-test/src/test/example-projects/maven-two-projects/multi-module-maven-project/pom.xml
similarity index 100%
rename from continuum-webapp-test/src/test/resources/unit/maven-two-projects/multi-module-maven-project/pom.xml
rename to continuum-webapp-test/src/test/example-projects/maven-two-projects/multi-module-maven-project/pom.xml
diff --git a/continuum-webapp-test/src/test/resources/unit/maven-two-projects/specified-notifiers-pom.xml b/continuum-webapp-test/src/test/example-projects/maven-two-projects/specified-notifiers-pom.xml
similarity index 100%
rename from continuum-webapp-test/src/test/resources/unit/maven-two-projects/specified-notifiers-pom.xml
rename to continuum-webapp-test/src/test/example-projects/maven-two-projects/specified-notifiers-pom.xml
diff --git a/continuum-webapp-test/src/test/resources/unit/maven-two-projects/valid-pom.xml b/continuum-webapp-test/src/test/example-projects/maven-two-projects/valid-pom.xml
similarity index 100%
rename from continuum-webapp-test/src/test/resources/unit/maven-two-projects/valid-pom.xml
rename to continuum-webapp-test/src/test/example-projects/maven-two-projects/valid-pom.xml
diff --git a/continuum-webapp-test/src/test/example-projects/shell/bad-build.sh b/continuum-webapp-test/src/test/example-projects/shell/bad-build.sh
new file mode 100755
index 0000000..fb8d38c
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-projects/shell/bad-build.sh
@@ -0,0 +1,5 @@
+
+
+echo "Build script..."
+echo "FAILURE!"
+exit 1
diff --git a/continuum-webapp-test/src/test/example-projects/shell/build.bat b/continuum-webapp-test/src/test/example-projects/shell/build.bat
new file mode 100755
index 0000000..fa882dd
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-projects/shell/build.bat
@@ -0,0 +1,6 @@
+

+

+@echo off

+echo Build script...

+

+exit 0
\ No newline at end of file
diff --git a/continuum-webapp-test/src/test/example-projects/shell/build.sh b/continuum-webapp-test/src/test/example-projects/shell/build.sh
new file mode 100755
index 0000000..f4cd72b
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-projects/shell/build.sh
@@ -0,0 +1,5 @@
+
+
+echo "Build script..."
+
+exit 0
diff --git a/continuum-webapp-test/src/test/example-projects/simple-example/pom.xml b/continuum-webapp-test/src/test/example-projects/simple-example/pom.xml
new file mode 100644
index 0000000..a77fad5
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-projects/simple-example/pom.xml
@@ -0,0 +1,24 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.continuum.examples.simple</groupId>
+  <artifactId>simple-example</artifactId>
+  <packaging>jar</packaging>
+  <version>1.0-SNAPSHOT</version>
+  <name>Continuum Simple Example Project</name>
+  <url>http://continuum.apache.org</url>
+
+  <scm>
+    <connection>scm:svn:${svn.base.url}/trunk/simple-example</connection>
+   <developerConnection>scm:svn:${svn.base.url}/trunk/simple-example</developerConnection>
+  </scm>
+
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.2</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/continuum-webapp-test/src/test/example-projects/simple-example/src/main/java/org/apache/continuum/examples/App.java b/continuum-webapp-test/src/test/example-projects/simple-example/src/main/java/org/apache/continuum/examples/App.java
new file mode 100644
index 0000000..82e058d
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-projects/simple-example/src/main/java/org/apache/continuum/examples/App.java
@@ -0,0 +1,13 @@
+package org.apache.continuum.examples;
+
+/**
+ * Hello world!
+ *
+ */
+public class App 
+{
+    public static void main( String[] args )
+    {
+        System.out.println( "Hello World!" );
+    }
+}
diff --git a/continuum-webapp-test/src/test/example-projects/simple-example/src/test/java/org/apache/continuum/examples/AppTest.java b/continuum-webapp-test/src/test/example-projects/simple-example/src/test/java/org/apache/continuum/examples/AppTest.java
new file mode 100644
index 0000000..e521181
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-projects/simple-example/src/test/java/org/apache/continuum/examples/AppTest.java
@@ -0,0 +1,38 @@
+package org.apache.continuum.examples;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Unit test for simple App.
+ */
+public class AppTest 
+    extends TestCase
+{
+    /**
+     * Create the test case
+     *
+     * @param testName name of the test case
+     */
+    public AppTest( String testName )
+    {
+        super( testName );
+    }
+
+    /**
+     * @return the suite of tests being tested
+     */
+    public static Test suite()
+    {
+        return new TestSuite( AppTest.class );
+    }
+
+    /**
+     * Rigourous Test :-)
+     */
+    public void testApp()
+    {
+        assertTrue( true );
+    }
+}
diff --git a/continuum-webapp-test/src/test/example-svn/README.txt b/continuum-webapp-test/src/test/example-svn/README.txt
new file mode 100644
index 0000000..3bf5a57
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/README.txt
@@ -0,0 +1,5 @@
+This is a Subversion repository; use the 'svnadmin' tool to examine
+it.  Do not add, delete, or modify files here unless you know how
+to avoid corrupting the repository.
+
+Visit http://subversion.tigris.org/ for more information.
diff --git a/continuum-webapp-test/src/test/example-svn/conf/authz b/continuum-webapp-test/src/test/example-svn/conf/authz
new file mode 100644
index 0000000..0b9a410
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/conf/authz
@@ -0,0 +1,32 @@
+### This file is an example authorization file for svnserve.
+### Its format is identical to that of mod_authz_svn authorization
+### files.
+### As shown below each section defines authorizations for the path and
+### (optional) repository specified by the section name.
+### The authorizations follow. An authorization line can refer to:
+###  - a single user,
+###  - a group of users defined in a special [groups] section,
+###  - an alias defined in a special [aliases] section,
+###  - all authenticated users, using the '$authenticated' token,
+###  - only anonymous users, using the '$anonymous' token,
+###  - anyone, using the '*' wildcard.
+###
+### A match can be inverted by prefixing the rule with '~'. Rules can
+### grant read ('r') access, read-write ('rw') access, or no access
+### ('').
+
+[aliases]
+# joe = /C=XZ/ST=Dessert/L=Snake City/O=Snake Oil, Ltd./OU=Research Institute/CN=Joe Average
+
+[groups]
+# harry_and_sally = harry,sally
+# harry_sally_and_joe = harry,sally,&joe
+
+# [/foo/bar]
+# harry = rw
+# &joe = r
+# * =
+
+# [repository:/baz/fuz]
+# @harry_and_sally = rw
+# * = r
diff --git a/continuum-webapp-test/src/test/example-svn/conf/passwd b/continuum-webapp-test/src/test/example-svn/conf/passwd
new file mode 100644
index 0000000..ecaa08d
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/conf/passwd
@@ -0,0 +1,8 @@
+### This file is an example password file for svnserve.
+### Its format is similar to that of svnserve.conf. As shown in the
+### example below it contains one section labelled [users].
+### The name and password for each user follow, one account per line.
+
+[users]
+# harry = harryssecret
+# sally = sallyssecret
diff --git a/continuum-webapp-test/src/test/example-svn/conf/svnserve.conf b/continuum-webapp-test/src/test/example-svn/conf/svnserve.conf
new file mode 100644
index 0000000..e62a01e
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/conf/svnserve.conf
@@ -0,0 +1,47 @@
+### This file controls the configuration of the svnserve daemon, if you
+### use it to allow access to this repository.  (If you only allow
+### access through http: and/or file: URLs, then this file is
+### irrelevant.)
+
+### Visit http://subversion.tigris.org/ for more information.
+
+[general]
+### These options control access to the repository for unauthenticated
+### and authenticated users.  Valid values are "write", "read",
+### and "none".  The sample settings below are the defaults.
+# anon-access = read
+# auth-access = write
+### The password-db option controls the location of the password
+### database file.  Unless you specify a path starting with a /,
+### the file's location is relative to the directory containing
+### this configuration file.
+### If SASL is enabled (see below), this file will NOT be used.
+### Uncomment the line below to use the default password file.
+# password-db = passwd
+### The authz-db option controls the location of the authorization
+### rules for path-based access control.  Unless you specify a path
+### starting with a /, the file's location is relative to the the
+### directory containing this file.  If you don't specify an
+### authz-db, no path-based access control is done.
+### Uncomment the line below to use the default authorization file.
+# authz-db = authz
+### This option specifies the authentication realm of the repository.
+### If two repositories have the same authentication realm, they should
+### have the same password database, and vice versa.  The default realm
+### is repository's uuid.
+# realm = My First Repository
+
+[sasl]
+### This option specifies whether you want to use the Cyrus SASL
+### library for authentication. Default is false.
+### This section will be ignored if svnserve is not built with Cyrus
+### SASL support; to check, run 'svnserve --version' and look for a line
+### reading 'Cyrus SASL authentication is available.'
+# use-sasl = true
+### These options specify the desired strength of the security layer
+### that you want SASL to provide. 0 means no encryption, 1 means
+### integrity-checking only, values larger than 1 are correlated
+### to the effective key length for encryption (e.g. 128 means 128-bit
+### encryption). The values below are the defaults.
+# min-encryption = 0
+# max-encryption = 256
diff --git a/continuum-webapp/src/main/resources/template/default/empty.ftl b/continuum-webapp-test/src/test/example-svn/dav/.gitignore
similarity index 100%
rename from continuum-webapp/src/main/resources/template/default/empty.ftl
rename to continuum-webapp-test/src/test/example-svn/dav/.gitignore
diff --git a/continuum-webapp-test/src/test/example-svn/db/current b/continuum-webapp-test/src/test/example-svn/db/current
new file mode 100644
index 0000000..cd9daee
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/db/current
@@ -0,0 +1 @@
+4 7j 1
diff --git a/continuum-webapp-test/src/test/example-svn/db/format b/continuum-webapp-test/src/test/example-svn/db/format
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/db/format
@@ -0,0 +1 @@
+1
diff --git a/continuum-webapp-test/src/test/example-svn/db/fs-type b/continuum-webapp-test/src/test/example-svn/db/fs-type
new file mode 100644
index 0000000..4fdd953
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/db/fs-type
@@ -0,0 +1 @@
+fsfs
diff --git a/continuum-webapp-test/src/test/example-svn/db/fsfs.conf b/continuum-webapp-test/src/test/example-svn/db/fsfs.conf
new file mode 100644
index 0000000..0a5f1fe
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/db/fsfs.conf
@@ -0,0 +1,37 @@
+### This file controls the configuration of the FSFS filesystem.
+
+[memcached-servers]
+### These options name memcached servers used to cache internal FSFS
+### data.  See http://www.danga.com/memcached/ for more information on
+### memcached.  To use memcached with FSFS, run one or more memcached
+### servers, and specify each of them as an option like so:
+# first-server = 127.0.0.1:11211
+# remote-memcached = mymemcached.corp.example.com:11212
+### The option name is ignored; the value is of the form HOST:PORT.
+### memcached servers can be shared between multiple repositories;
+### however, if you do this, you *must* ensure that repositories have
+### distinct UUIDs and paths, or else cached data from one repository
+### might be used by another accidentally.  Note also that memcached has
+### no authentication for reads or writes, so you must ensure that your
+### memcached servers are only accessible by trusted users.
+
+[caches]
+### When a cache-related error occurs, normally Subversion ignores it
+### and continues, logging an error if the server is appropriately
+### configured (and ignoring it with file:// access).  To make
+### Subversion never ignore cache errors, uncomment this line.
+# fail-stop = true
+
+[rep-sharing]
+### To conserve space, the filesystem can optionally avoid storing
+### duplicate representations.  This comes at a slight cost in performace,
+### as maintaining a database of shared representations can increase
+### commit times.  The space savings are dependent upon the size of the
+### repository, the number of objects it contains and the amount of
+### duplication between them, usually a function of the branching and
+### merging process.
+###
+### The following parameter enables rep-sharing in the repository.  It can
+### be switched on and off at will, but for best space-saving results
+### should be enabled consistently over the life of the repository.
+# enable-rep-sharing = false
diff --git a/continuum-webapp-test/src/test/example-svn/db/revprops/0 b/continuum-webapp-test/src/test/example-svn/db/revprops/0
new file mode 100644
index 0000000..077f5b5
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/db/revprops/0
@@ -0,0 +1,5 @@
+K 8
+svn:date
+V 27
+2010-03-16T11:03:29.911752Z
+END
diff --git a/continuum-webapp-test/src/test/example-svn/db/revprops/1 b/continuum-webapp-test/src/test/example-svn/db/revprops/1
new file mode 100644
index 0000000..8c9ce1f
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/db/revprops/1
@@ -0,0 +1,13 @@
+K 10
+svn:author
+V 5
+brett
+K 8
+svn:date
+V 27
+2010-03-16T11:03:38.252804Z
+K 7
+svn:log
+V 13
+test projects
+END
diff --git a/continuum-webapp-test/src/test/example-svn/db/revprops/2 b/continuum-webapp-test/src/test/example-svn/db/revprops/2
new file mode 100644
index 0000000..dc4b881
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/db/revprops/2
@@ -0,0 +1,13 @@
+K 10
+svn:author
+V 5
+brett
+K 8
+svn:date
+V 27
+2010-03-16T11:03:40.848036Z
+K 7
+svn:log
+V 13
+test projects
+END
diff --git a/continuum-webapp-test/src/test/example-svn/db/revprops/3 b/continuum-webapp-test/src/test/example-svn/db/revprops/3
new file mode 100644
index 0000000..2e17614
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/db/revprops/3
@@ -0,0 +1,13 @@
+K 10
+svn:author
+V 6
+marica
+K 8
+svn:date
+V 27
+2010-06-03T23:55:26.242482Z
+K 7
+svn:log
+V 28
+added sample failing project
+END
diff --git a/continuum-webapp-test/src/test/example-svn/db/revprops/4 b/continuum-webapp-test/src/test/example-svn/db/revprops/4
new file mode 100644
index 0000000..59a5d26
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/db/revprops/4
@@ -0,0 +1,13 @@
+K 10
+svn:author
+V 5
+brent
+K 8
+svn:date
+V 27
+2012-08-23T04:48:10.024103Z
+K 7
+svn:log
+V 39
+Adding script for windows shell builds.
+END
diff --git a/continuum-webapp-test/src/test/example-svn/db/revs/0 b/continuum-webapp-test/src/test/example-svn/db/revs/0
new file mode 100644
index 0000000..10f5c45
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/db/revs/0
@@ -0,0 +1,11 @@
+PLAIN
+END
+ENDREP
+id: 0.0.r0/17
+type: dir
+count: 0
+text: 0 0 4 4 2d2977d1c96f487abe4a1e202dd03b4e
+cpath: /
+
+
+17 107
diff --git a/continuum-webapp-test/src/test/example-svn/db/revs/1 b/continuum-webapp-test/src/test/example-svn/db/revs/1
new file mode 100644
index 0000000..1e036ce
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/db/revs/1
Binary files differ
diff --git a/continuum-webapp-test/src/test/example-svn/db/revs/2 b/continuum-webapp-test/src/test/example-svn/db/revs/2
new file mode 100644
index 0000000..49d84a8
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/db/revs/2
Binary files differ
diff --git a/continuum-webapp-test/src/test/example-svn/db/revs/3 b/continuum-webapp-test/src/test/example-svn/db/revs/3
new file mode 100644
index 0000000..01c4ab7
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/db/revs/3
Binary files differ
diff --git a/continuum-webapp-test/src/test/example-svn/db/revs/4 b/continuum-webapp-test/src/test/example-svn/db/revs/4
new file mode 100644
index 0000000..0d2831c
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/db/revs/4
Binary files differ
diff --git a/continuum-webapp/src/main/resources/template/default/empty.ftl b/continuum-webapp-test/src/test/example-svn/db/transactions/.gitignore
similarity index 100%
copy from continuum-webapp/src/main/resources/template/default/empty.ftl
copy to continuum-webapp-test/src/test/example-svn/db/transactions/.gitignore
diff --git a/continuum-webapp-test/src/test/example-svn/db/uuid b/continuum-webapp-test/src/test/example-svn/db/uuid
new file mode 100644
index 0000000..709f8f8
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/db/uuid
@@ -0,0 +1 @@
+4e8e9111-6a64-48cb-a7ec-3c42aae7d8c6
diff --git a/continuum-webapp/src/main/resources/template/default/empty.ftl b/continuum-webapp-test/src/test/example-svn/db/write-lock
similarity index 100%
copy from continuum-webapp/src/main/resources/template/default/empty.ftl
copy to continuum-webapp-test/src/test/example-svn/db/write-lock
diff --git a/continuum-webapp-test/src/test/example-svn/format b/continuum-webapp-test/src/test/example-svn/format
new file mode 100644
index 0000000..00750ed
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/format
@@ -0,0 +1 @@
+3
diff --git a/continuum-webapp-test/src/test/example-svn/hooks/post-commit.tmpl b/continuum-webapp-test/src/test/example-svn/hooks/post-commit.tmpl
new file mode 100644
index 0000000..38ae6b7
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/hooks/post-commit.tmpl
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+# POST-COMMIT HOOK
+#
+# The post-commit hook is invoked after a commit.  Subversion runs
+# this hook by invoking a program (script, executable, binary, etc.)
+# named 'post-commit' (for which this file is a template) with the 
+# following ordered arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] REV          (the number of the revision just committed)
+#
+# The default working directory for the invocation is undefined, so
+# the program should set one explicitly if it cares.
+#
+# Because the commit has already completed and cannot be undone,
+# the exit code of the hook program is ignored.  The hook program
+# can use the 'svnlook' utility to help it examine the
+# newly-committed tree.
+#
+# On a Unix system, the normal procedure is to have 'post-commit'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+# Note that 'post-commit' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'post-commit.bat' or 'post-commit.exe',
+# but the basic idea is the same.
+# 
+# The hook program typically does not inherit the environment of
+# its parent process.  For example, a common problem is for the
+# PATH environment variable to not be set to its usual value, so
+# that subprograms fail to launch unless invoked via absolute path.
+# If you're having unexpected problems with a hook program, the
+# culprit may be unusual (or missing) environment variables.
+# 
+# Here is an example hook script, for a Unix /bin/sh interpreter.
+# For more examples and pre-written hooks, see those in
+# the Subversion repository at
+# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
+# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
+
+
+REPOS="$1"
+REV="$2"
+
+mailer.py commit "$REPOS" "$REV" /path/to/mailer.conf
diff --git a/continuum-webapp-test/src/test/example-svn/hooks/post-lock.tmpl b/continuum-webapp-test/src/test/example-svn/hooks/post-lock.tmpl
new file mode 100644
index 0000000..c779f11
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/hooks/post-lock.tmpl
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+# POST-LOCK HOOK
+#
+# The post-lock hook is run after a path is locked.  Subversion runs
+# this hook by invoking a program (script, executable, binary, etc.)
+# named 'post-lock' (for which this file is a template) with the 
+# following ordered arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] USER         (the user who created the lock)
+#
+# The paths that were just locked are passed to the hook via STDIN (as
+# of Subversion 1.2, only one path is passed per invocation, but the
+# plan is to pass all locked paths at once, so the hook program
+# should be written accordingly).
+#
+# The default working directory for the invocation is undefined, so
+# the program should set one explicitly if it cares.
+#
+# Because the lock has already been created and cannot be undone,
+# the exit code of the hook program is ignored.  The hook program
+# can use the 'svnlook' utility to help it examine the
+# newly-created lock.
+#
+# On a Unix system, the normal procedure is to have 'post-lock'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+# Note that 'post-lock' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'post-lock.bat' or 'post-lock.exe',
+# but the basic idea is the same.
+# 
+# Here is an example hook script, for a Unix /bin/sh interpreter:
+
+REPOS="$1"
+USER="$2"
+
+# Send email to interested parties, let them know a lock was created:
+mailer.py lock "$REPOS" "$USER" /path/to/mailer.conf
diff --git a/continuum-webapp-test/src/test/example-svn/hooks/post-revprop-change.tmpl b/continuum-webapp-test/src/test/example-svn/hooks/post-revprop-change.tmpl
new file mode 100644
index 0000000..ea3db33
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/hooks/post-revprop-change.tmpl
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+# POST-REVPROP-CHANGE HOOK
+#
+# The post-revprop-change hook is invoked after a revision property
+# has been added, modified or deleted.  Subversion runs this hook by
+# invoking a program (script, executable, binary, etc.) named
+# 'post-revprop-change' (for which this file is a template), with the
+# following ordered arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] REV          (the revision that was tweaked)
+#   [3] USER         (the username of the person tweaking the property)
+#   [4] PROPNAME     (the property that was changed)
+#   [5] ACTION       (the property was 'A'dded, 'M'odified, or 'D'eleted)
+#
+#   [STDIN] PROPVAL  ** the old property value is passed via STDIN.
+#
+# Because the propchange has already completed and cannot be undone,
+# the exit code of the hook program is ignored.  The hook program
+# can use the 'svnlook' utility to help it examine the
+# new property value.
+#
+# On a Unix system, the normal procedure is to have 'post-revprop-change'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+# Note that 'post-revprop-change' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'post-revprop-change.bat' or 'post-revprop-change.exe',
+# but the basic idea is the same.
+# 
+# The hook program typically does not inherit the environment of
+# its parent process.  For example, a common problem is for the
+# PATH environment variable to not be set to its usual value, so
+# that subprograms fail to launch unless invoked via absolute path.
+# If you're having unexpected problems with a hook program, the
+# culprit may be unusual (or missing) environment variables.
+# 
+# Here is an example hook script, for a Unix /bin/sh interpreter.
+# For more examples and pre-written hooks, see those in
+# the Subversion repository at
+# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
+# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
+
+
+REPOS="$1"
+REV="$2"
+USER="$3"
+PROPNAME="$4"
+ACTION="$5"
+
+mailer.py propchange2 "$REPOS" "$REV" "$USER" "$PROPNAME" "$ACTION" /path/to/mailer.conf
diff --git a/continuum-webapp-test/src/test/example-svn/hooks/post-unlock.tmpl b/continuum-webapp-test/src/test/example-svn/hooks/post-unlock.tmpl
new file mode 100644
index 0000000..ae95c4b
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/hooks/post-unlock.tmpl
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+# POST-UNLOCK HOOK
+#
+# The post-unlock hook runs after a path is unlocked.  Subversion runs
+# this hook by invoking a program (script, executable, binary, etc.)
+# named 'post-unlock' (for which this file is a template) with the 
+# following ordered arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] USER         (the user who destroyed the lock)
+#
+# The paths that were just unlocked are passed to the hook via STDIN
+# (as of Subversion 1.2, only one path is passed per invocation, but
+# the plan is to pass all unlocked paths at once, so the hook program
+# should be written accordingly).
+#
+# The default working directory for the invocation is undefined, so
+# the program should set one explicitly if it cares.
+#
+# Because the lock has already been destroyed and cannot be undone,
+# the exit code of the hook program is ignored.
+#
+# On a Unix system, the normal procedure is to have 'post-unlock'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+# Note that 'post-unlock' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'post-unlock.bat' or 'post-unlock.exe',
+# but the basic idea is the same.
+# 
+# Here is an example hook script, for a Unix /bin/sh interpreter:
+
+REPOS="$1"
+USER="$2"
+
+# Send email to interested parties, let them know a lock was removed:
+mailer.py unlock "$REPOS" "$USER" /path/to/mailer.conf
diff --git a/continuum-webapp-test/src/test/example-svn/hooks/pre-commit.tmpl b/continuum-webapp-test/src/test/example-svn/hooks/pre-commit.tmpl
new file mode 100644
index 0000000..066d84f
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/hooks/pre-commit.tmpl
@@ -0,0 +1,81 @@
+#!/bin/sh
+
+# PRE-COMMIT HOOK
+#
+# The pre-commit hook is invoked before a Subversion txn is
+# committed.  Subversion runs this hook by invoking a program
+# (script, executable, binary, etc.) named 'pre-commit' (for which
+# this file is a template), with the following ordered arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] TXN-NAME     (the name of the txn about to be committed)
+#
+#   [STDIN] LOCK-TOKENS ** the lock tokens are passed via STDIN.
+#
+#   If STDIN contains the line "LOCK-TOKENS:\n" (the "\n" denotes a
+#   single newline), the lines following it are the lock tokens for
+#   this commit.  The end of the list is marked by a line containing
+#   only a newline character.
+#
+#   Each lock token line consists of a URI-escaped path, followed
+#   by the separator character '|', followed by the lock token string,
+#   followed by a newline.
+#
+# The default working directory for the invocation is undefined, so
+# the program should set one explicitly if it cares.
+#
+# If the hook program exits with success, the txn is committed; but
+# if it exits with failure (non-zero), the txn is aborted, no commit
+# takes place, and STDERR is returned to the client.   The hook
+# program can use the 'svnlook' utility to help it examine the txn.
+#
+# On a Unix system, the normal procedure is to have 'pre-commit'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+#   ***  NOTE: THE HOOK PROGRAM MUST NOT MODIFY THE TXN, EXCEPT  ***
+#   ***  FOR REVISION PROPERTIES (like svn:log or svn:author).   ***
+#
+#   This is why we recommend using the read-only 'svnlook' utility.
+#   In the future, Subversion may enforce the rule that pre-commit
+#   hooks should not modify the versioned data in txns, or else come
+#   up with a mechanism to make it safe to do so (by informing the
+#   committing client of the changes).  However, right now neither
+#   mechanism is implemented, so hook writers just have to be careful.
+#
+# Note that 'pre-commit' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'pre-commit.bat' or 'pre-commit.exe',
+# but the basic idea is the same.
+#
+# The hook program typically does not inherit the environment of
+# its parent process.  For example, a common problem is for the
+# PATH environment variable to not be set to its usual value, so
+# that subprograms fail to launch unless invoked via absolute path.
+# If you're having unexpected problems with a hook program, the
+# culprit may be unusual (or missing) environment variables.
+# 
+# Here is an example hook script, for a Unix /bin/sh interpreter.
+# For more examples and pre-written hooks, see those in
+# the Subversion repository at
+# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
+# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
+
+
+REPOS="$1"
+TXN="$2"
+
+# Make sure that the log message contains some text.
+SVNLOOK=/usr/bin/svnlook
+$SVNLOOK log -t "$TXN" "$REPOS" | \
+   grep "[a-zA-Z0-9]" > /dev/null || exit 1
+
+# Check that the author of this commit has the rights to perform
+# the commit on the files and directories being modified.
+commit-access-control.pl "$REPOS" "$TXN" commit-access-control.cfg || exit 1
+
+# All checks passed, so allow the commit.
+exit 0
diff --git a/continuum-webapp-test/src/test/example-svn/hooks/pre-lock.tmpl b/continuum-webapp-test/src/test/example-svn/hooks/pre-lock.tmpl
new file mode 100644
index 0000000..13827fb
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/hooks/pre-lock.tmpl
@@ -0,0 +1,71 @@
+#!/bin/sh
+
+# PRE-LOCK HOOK
+#
+# The pre-lock hook is invoked before an exclusive lock is
+# created.  Subversion runs this hook by invoking a program 
+# (script, executable, binary, etc.) named 'pre-lock' (for which
+# this file is a template), with the following ordered arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] PATH         (the path in the repository about to be locked)
+#   [3] USER         (the user creating the lock)
+#   [4] COMMENT      (the comment of the lock)
+#   [5] STEAL-LOCK   (1 if the user is trying to steal the lock, else 0)
+#
+# If the hook program outputs anything on stdout, the output string will
+# be used as the lock token for this lock operation.  If you choose to use
+# this feature, you must guarantee the tokens generated are unique across
+# the repository each time.
+#
+# The default working directory for the invocation is undefined, so
+# the program should set one explicitly if it cares.
+#
+# If the hook program exits with success, the lock is created; but
+# if it exits with failure (non-zero), the lock action is aborted
+# and STDERR is returned to the client.
+
+# On a Unix system, the normal procedure is to have 'pre-lock'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+# Note that 'pre-lock' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'pre-lock.bat' or 'pre-lock.exe',
+# but the basic idea is the same.
+#
+# Here is an example hook script, for a Unix /bin/sh interpreter:
+
+REPOS="$1"
+PATH="$2"
+USER="$3"
+
+# If a lock exists and is owned by a different person, don't allow it
+# to be stolen (e.g., with 'svn lock --force ...').
+
+# (Maybe this script could send email to the lock owner?)
+SVNLOOK=/usr/bin/svnlook
+GREP=/bin/grep
+SED=/bin/sed
+
+LOCK_OWNER=`$SVNLOOK lock "$REPOS" "$PATH" | \
+            $GREP '^Owner: ' | $SED 's/Owner: //'`
+
+# If we get no result from svnlook, there's no lock, allow the lock to
+# happen:
+if [ "$LOCK_OWNER" = "" ]; then
+  exit 0
+fi
+
+# If the person locking matches the lock's owner, allow the lock to
+# happen:
+if [ "$LOCK_OWNER" = "$USER" ]; then
+  exit 0
+fi
+
+# Otherwise, we've got an owner mismatch, so return failure:
+echo "Error: $PATH already locked by ${LOCK_OWNER}." 1>&2
+exit 1
diff --git a/continuum-webapp-test/src/test/example-svn/hooks/pre-revprop-change.tmpl b/continuum-webapp-test/src/test/example-svn/hooks/pre-revprop-change.tmpl
new file mode 100644
index 0000000..2f2de98
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/hooks/pre-revprop-change.tmpl
@@ -0,0 +1,66 @@
+#!/bin/sh
+
+# PRE-REVPROP-CHANGE HOOK
+#
+# The pre-revprop-change hook is invoked before a revision property
+# is added, modified or deleted.  Subversion runs this hook by invoking
+# a program (script, executable, binary, etc.) named 'pre-revprop-change'
+# (for which this file is a template), with the following ordered
+# arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] REVISION     (the revision being tweaked)
+#   [3] USER         (the username of the person tweaking the property)
+#   [4] PROPNAME     (the property being set on the revision)
+#   [5] ACTION       (the property is being 'A'dded, 'M'odified, or 'D'eleted)
+#
+#   [STDIN] PROPVAL  ** the new property value is passed via STDIN.
+#
+# If the hook program exits with success, the propchange happens; but
+# if it exits with failure (non-zero), the propchange doesn't happen.
+# The hook program can use the 'svnlook' utility to examine the 
+# existing value of the revision property.
+#
+# WARNING: unlike other hooks, this hook MUST exist for revision
+# properties to be changed.  If the hook does not exist, Subversion 
+# will behave as if the hook were present, but failed.  The reason
+# for this is that revision properties are UNVERSIONED, meaning that
+# a successful propchange is destructive;  the old value is gone
+# forever.  We recommend the hook back up the old value somewhere.
+#
+# On a Unix system, the normal procedure is to have 'pre-revprop-change'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+# Note that 'pre-revprop-change' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'pre-revprop-change.bat' or 'pre-revprop-change.exe',
+# but the basic idea is the same.
+#
+# The hook program typically does not inherit the environment of
+# its parent process.  For example, a common problem is for the
+# PATH environment variable to not be set to its usual value, so
+# that subprograms fail to launch unless invoked via absolute path.
+# If you're having unexpected problems with a hook program, the
+# culprit may be unusual (or missing) environment variables.
+# 
+# Here is an example hook script, for a Unix /bin/sh interpreter.
+# For more examples and pre-written hooks, see those in
+# the Subversion repository at
+# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
+# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
+
+
+REPOS="$1"
+REV="$2"
+USER="$3"
+PROPNAME="$4"
+ACTION="$5"
+
+if [ "$ACTION" = "M" -a "$PROPNAME" = "svn:log" ]; then exit 0; fi
+
+echo "Changing revision properties other than svn:log is prohibited" >&2
+exit 1
diff --git a/continuum-webapp-test/src/test/example-svn/hooks/pre-unlock.tmpl b/continuum-webapp-test/src/test/example-svn/hooks/pre-unlock.tmpl
new file mode 100644
index 0000000..d1aa858
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/hooks/pre-unlock.tmpl
@@ -0,0 +1,63 @@
+#!/bin/sh
+
+# PRE-UNLOCK HOOK
+#
+# The pre-unlock hook is invoked before an exclusive lock is
+# destroyed.  Subversion runs this hook by invoking a program 
+# (script, executable, binary, etc.) named 'pre-unlock' (for which
+# this file is a template), with the following ordered arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] PATH         (the path in the repository about to be unlocked)
+#   [3] USER         (the user destroying the lock)
+#   [4] TOKEN        (the lock token to be destroyed)
+#   [5] BREAK-UNLOCK (1 if the user is breaking the lock, else 0)
+#
+# The default working directory for the invocation is undefined, so
+# the program should set one explicitly if it cares.
+#
+# If the hook program exits with success, the lock is destroyed; but
+# if it exits with failure (non-zero), the unlock action is aborted
+# and STDERR is returned to the client.
+
+# On a Unix system, the normal procedure is to have 'pre-unlock'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+# Note that 'pre-unlock' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'pre-unlock.bat' or 'pre-unlock.exe',
+# but the basic idea is the same.
+#
+# Here is an example hook script, for a Unix /bin/sh interpreter:
+
+REPOS="$1"
+PATH="$2"
+USER="$3"
+
+# If a lock is owned by a different person, don't allow it be broken.
+# (Maybe this script could send email to the lock owner?)
+
+SVNLOOK=/usr/bin/svnlook
+GREP=/bin/grep
+SED=/bin/sed
+
+LOCK_OWNER=`$SVNLOOK lock "$REPOS" "$PATH" | \
+            $GREP '^Owner: ' | $SED 's/Owner: //'`
+
+# If we get no result from svnlook, there's no lock, return success:
+if [ "$LOCK_OWNER" = "" ]; then
+  exit 0
+fi
+
+# If the person unlocking matches the lock's owner, return success:
+if [ "$LOCK_OWNER" = "$USER" ]; then
+  exit 0
+fi
+
+# Otherwise, we've got an owner mismatch, so return failure:
+echo "Error: $PATH locked by ${LOCK_OWNER}." 1>&2
+exit 1
diff --git a/continuum-webapp-test/src/test/example-svn/hooks/start-commit.tmpl b/continuum-webapp-test/src/test/example-svn/hooks/start-commit.tmpl
new file mode 100644
index 0000000..7597f58
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/hooks/start-commit.tmpl
@@ -0,0 +1,65 @@
+#!/bin/sh
+
+# START-COMMIT HOOK
+#
+# The start-commit hook is invoked before a Subversion txn is created
+# in the process of doing a commit.  Subversion runs this hook
+# by invoking a program (script, executable, binary, etc.) named
+# 'start-commit' (for which this file is a template)
+# with the following ordered arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] USER         (the authenticated user attempting to commit)
+#   [3] CAPABILITIES (a colon-separated list of capabilities reported
+#                     by the client; see note below)
+#
+# Note: The CAPABILITIES parameter is new in Subversion 1.5, and 1.5
+# clients will typically report at least the "mergeinfo" capability.
+# If there are other capabilities, then the list is colon-separated,
+# e.g.: "mergeinfo:some-other-capability" (the order is undefined).
+#
+# The list is self-reported by the client.  Therefore, you should not
+# make security assumptions based on the capabilities list, nor should
+# you assume that clients reliably report every capability they have.
+#
+# The working directory for this hook program's invocation is undefined,
+# so the program should set one explicitly if it cares.
+#
+# If the hook program exits with success, the commit continues; but
+# if it exits with failure (non-zero), the commit is stopped before
+# a Subversion txn is created, and STDERR is returned to the client.
+#
+# On a Unix system, the normal procedure is to have 'start-commit'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+# Note that 'start-commit' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'start-commit.bat' or 'start-commit.exe',
+# but the basic idea is the same.
+# 
+# The hook program typically does not inherit the environment of
+# its parent process.  For example, a common problem is for the
+# PATH environment variable to not be set to its usual value, so
+# that subprograms fail to launch unless invoked via absolute path.
+# If you're having unexpected problems with a hook program, the
+# culprit may be unusual (or missing) environment variables.
+# 
+# Here is an example hook script, for a Unix /bin/sh interpreter.
+# For more examples and pre-written hooks, see those in
+# the Subversion repository at
+# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
+# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
+
+
+REPOS="$1"
+USER="$2"
+
+commit-allower.pl --repository "$REPOS" --user "$USER" || exit 1
+special-auth-check.py --user "$USER" --auth-level 3 || exit 1
+
+# All checks passed, so allow the commit.
+exit 0
diff --git a/continuum-webapp-test/src/test/example-svn/locks/db-logs.lock b/continuum-webapp-test/src/test/example-svn/locks/db-logs.lock
new file mode 100644
index 0000000..20dd636
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/locks/db-logs.lock
@@ -0,0 +1,3 @@
+This file is not used by Subversion 1.3.x or later.
+However, its existence is required for compatibility with
+Subversion 1.2.x or earlier.
diff --git a/continuum-webapp-test/src/test/example-svn/locks/db.lock b/continuum-webapp-test/src/test/example-svn/locks/db.lock
new file mode 100644
index 0000000..20dd636
--- /dev/null
+++ b/continuum-webapp-test/src/test/example-svn/locks/db.lock
@@ -0,0 +1,3 @@
+This file is not used by Subversion 1.3.x or later.
+However, its existence is required for compatibility with
+Subversion 1.2.x or earlier.
diff --git a/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/AbstractAuthenticatedAccessTestCase.java b/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/AbstractAuthenticatedAccessTestCase.java
deleted file mode 100644
index e3e454a..0000000
--- a/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/AbstractAuthenticatedAccessTestCase.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.apache.continuum.web.test;
-
-/*
- * Copyright 2005-2006 The Apache Software Foundation.
- *
- * Licensed 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.
- */
-
-/**
- * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
- * @version $Id$
- */
-public abstract class AbstractAuthenticatedAccessTestCase
-    extends AbstractGuestAccessTestCase
-{
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-        login( getUsername(), getPassword() );
-    }
-
-    public abstract String getUsername();
-
-    public abstract String getPassword();
-}
diff --git a/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/AbstractAuthenticatedAdminAccessTestCase.java b/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/AbstractAuthenticatedAdminAccessTestCase.java
deleted file mode 100644
index 79e83ce..0000000
--- a/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/AbstractAuthenticatedAdminAccessTestCase.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- *
- */
-package org.apache.continuum.web.test;
-
-/*
- * Copyright 2005-2006 The Apache Software Foundation.
- *
- * Licensed 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.
- */
-
-/**
- *
- */
-public abstract class AbstractAuthenticatedAdminAccessTestCase
-    extends AbstractAuthenticatedAccessTestCase
-{
-    /**
-     * @see org.apache.continuum.web.test.AbstractAuthenticatedAccessTestCase#getPassword()
-     */
-    public String getPassword()
-    {
-        return adminPassword;
-    }
-
-    /**
-     * @see org.apache.continuum.web.test.AbstractAuthenticatedAccessTestCase#getUsername()
-     */
-    public String getUsername()
-    {
-        return adminUsername;
-    }
-}
diff --git a/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/AbstractContinuumTestCase.java b/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/AbstractContinuumTestCase.java
deleted file mode 100644
index 7787640..0000000
--- a/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/AbstractContinuumTestCase.java
+++ /dev/null
@@ -1,1004 +0,0 @@
-package org.apache.continuum.web.test;
-
-/*
- * Copyright 2005-2006 The Apache Software Foundation.
- *
- * Licensed 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 org.apache.maven.shared.web.test.AbstractSeleniumTestCase;
-
-/**
- * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
- * @version $Id$
- */
-public abstract class AbstractContinuumTestCase
-    extends AbstractSeleniumTestCase
-{
-    private String baseUrl = "http://localhost:9595/continuum";
-
-    public final static String DEFAULT_PROJ_GRP_NAME = "Default Project Group";
-
-    public final static String DEFAULT_PROJ_GRP_ID = "default";
-
-    public final static String DEFAULT_PROJ_GRP_DESCRIPTION =
-        "Contains all projects that do not have a group of their own";
-
-    public final static String TEST_PROJ_GRP_NAME = "Test Project Group Name";
-
-    public final static String TEST_PROJ_GRP_ID = "Test Project Group Id";
-
-    public final static String TEST_PROJ_GRP_DESCRIPTION = "Test Project Group Description";
-
-    public final static String TEST_POM_URL = "http://svn.apache.org/repos/asf/maven/pom/trunk/maven/pom.xml";
-
-    public final static String TEST_POM_USERNAME = "dummy";
-
-    public final static String TEST_POM_PASSWORD = "dummy";
-
-    public static final String TEST_PROJECT_GROUP_NAME = "Apache Maven";
-
-    public static final String TEST_PROJECT_NAME = "Apache Maven";
-
-    protected void postAdminUserCreation()
-    {
-        assertEditConfigurationPage();
-        submitConfigurationPage( baseUrl, null, null, null );
-    }
-
-    //////////////////////////////////////
-    // Overriden AbstractSeleniumTestCase methods
-    //////////////////////////////////////
-    protected String getApplicationName()
-    {
-        return "Continuum";
-    }
-
-    protected String getInceptionYear()
-    {
-        return "2005";
-    }
-
-    public void assertHeader()
-    {
-        //TODO
-    }
-
-    public String getBaseUrl()
-    {
-        return baseUrl;
-    }
-
-    //////////////////////////////////////
-    // About
-    //////////////////////////////////////
-    public void goToAboutPage()
-    {
-        clickLinkWithText( "About" );
-
-        assertAboutPage();
-    }
-
-    public void assertAboutPage()
-    {
-        assertPage( "Continuum - About" );
-        assertTextPresent( "About Continuum" );
-        assertTextPresent( "Version:" );
-        assertTextPresent( "1.1-SNAPSHOT" );
-    }
-
-    //////////////////////////////////////
-    // Configuration
-    //////////////////////////////////////
-    public void assertEditConfigurationPage()
-    {
-        assertPage( "Continuum - Configuration" );
-        assertTextPresent( "Working Directory" );
-        assertElementPresent( "workingDirectory" );
-        assertTextPresent( "Build Output Directory" );
-        assertElementPresent( "buildOutputDirectory" );
-        assertTextPresent( "Deployment Repository Directory" );
-        assertElementPresent( "deploymentRepositoryDirectory" );
-        assertTextPresent( "Base URL" );
-        assertElementPresent( "baseUrl" );
-    }
-
-    public void submitConfigurationPage( String baseUrl, String companyName, String companyLogo, String companyUrl )
-    {
-        setFieldValue( "baseUrl", baseUrl );
-        if ( companyName != null )
-        {
-            setFieldValue( "companyName", companyName );
-        }
-        if ( companyLogo != null )
-        {
-            setFieldValue( "companyLogo", companyLogo );
-        }
-        if ( companyUrl != null )
-        {
-            setFieldValue( "companyUrl", companyUrl );
-        }
-        submit();
-        waitPage();
-    }
-
-    //////////////////////////////////////
-    // ANT/SHELL Projects
-    //////////////////////////////////////
-    public void assertAddProjectPage( String type )
-    {
-        String title = type.substring( 0, 1 ).toUpperCase() + type.substring( 1 ).toLowerCase();
-        assertPage( "Continuum - Add " + title + " Project" );
-        assertTextPresent( "Add " + title + " Project" );
-        assertTextPresent( "Project Name" );
-        assertElementPresent( "projectName" );
-        assertTextPresent( "Version" );
-        assertElementPresent( "projectVersion" );
-        assertTextPresent( "Scm Url" );
-        assertElementPresent( "projectScmUrl" );
-        assertTextPresent( "Scm Username" );
-        assertElementPresent( "projectScmUsername" );
-        assertTextPresent( "Scm Password" );
-        assertElementPresent( "projectScmPassword" );
-        assertTextPresent( "Scm Branch/Tag" );
-        assertElementPresent( "projectScmTag" );
-        assertLinkPresent( "Maven SCM URL" );
-    }
-
-    public void assertAddAntProjectPage()
-    {
-        assertAddProjectPage( "ant" );
-    }
-
-    public void assertAddShellProjectPage()
-    {
-        assertAddProjectPage( "shell" );
-    }
-
-    //////////////////////////////////////
-    // Project Groups
-    //////////////////////////////////////
-    public void goToProjectGroupsSummaryPage()
-        throws Exception
-    {
-        clickLinkWithText( "Show Project Groups" );
-
-        assertProjectGroupsSummaryPage();
-    }
-
-    public void assertProjectGroupsSummaryPage()
-    {
-        assertPage( "Continuum - Group Summary" );
-        assertTextPresent( "Project Groups" );
-
-        if ( isTextPresent( "Project Groups list is empty." ) )
-        {
-            assertTextNotPresent( "Name" );
-            assertTextNotPresent( "Group Id" );
-            assertTextNotPresent( "Projects" );
-            assertTextNotPresent( "Build Status" );
-        }
-        else
-        {
-            assertTextPresent( "Name" );
-            assertTextPresent( "Group Id" );
-            assertTextPresent( "Projects" );
-            assertTextPresent( "Build Status" );
-        }
-    }
-
-    //////////////////////////////////////
-    // Project Group
-    //////////////////////////////////////
-    public void showProjectGroup( String name, String groupId, String description )
-        throws Exception
-    {
-        goToProjectGroupsSummaryPage();
-
-        // Checks the link to the created Project Group
-        assertLinkPresent( name );
-        clickLinkWithText( name );
-
-        assertProjectGroupSummaryPage( name, groupId, description);
-    }
-
-    public void assertProjectGroupSummaryPage( String name, String groupId, String description )
-    {
-        assertTextPresent( "Project Group Name" );
-        assertTextPresent( name );
-        assertTextPresent( "Group Id" );
-        assertTextPresent( groupId );
-        assertTextPresent( "Description" );
-        assertTextPresent( description );
-
-        // Assert the available Project Group Actions
-        assertTextPresent( "Project Group Actions" );
-        assertElementPresent( "build" );
-        assertElementPresent( "edit" );
-        assertElementPresent( "remove" );
-
-        if ( isTextPresent( "Projects" ) )
-        {
-            assertTextPresent( "Project Name" );
-            assertTextPresent( "Version" );
-            assertTextPresent( "Build" );
-        }
-        else
-        {
-            assertTextNotPresent( "Project Name" );
-        }
-    }
-
-    public void addProjectGroup( String name, String groupId, String description )
-        throws Exception
-    {
-        goToProjectGroupsSummaryPage();
-
-        // Go to Add Project Group Page
-        clickButtonWithValue( "Add Project Group" );
-        assertAddProjectGroupPage();
-
-        // Enter values into Add Project Group fields, and submit  
-        setFieldValue( "name", name );
-        setFieldValue( "groupId", groupId );
-        setFieldValue( "description", description );
-
-        submit();
-        waitPage();
-
-        //TODO: Check the result Page
-    }
-
-    public void assertAddProjectGroupPage()
-    {
-        assertPage( "Continuum - Add Project Group" );
-
-        assertTextPresent( "Add Project Group" );
-        assertTextPresent( "Project Group Name" );
-        assertElementPresent( "name" );
-        assertTextPresent( "Project Group Id" );
-        assertElementPresent( "groupId" );
-        assertTextPresent( "Description" );
-        assertElementPresent( "description" );
-    }
-
-    public void removeProjectGroup( String name, String groupId, String description )
-        throws Exception
-    {
-        showProjectGroup( name, groupId, description );
-
-        // Remove
-        clickSubmitWithLocator( "remove" );
-
-        // Assert Confirmation
-        assertElementPresent( "removeProjectGroup_0" );
-        assertElementPresent( "Cancel" );
-
-        // Confirm Project Group deletion
-        clickSubmitWithLocator( "removeProjectGroup_0" );
-    }
-
-    public void editProjectGroup( String name, String groupId, String description, String newName, String newDescription )
-        throws Exception
-    {
-        showProjectGroup( name, groupId, description );
-        clickButtonWithValue( "Edit" );
-        assertEditGroupPage( groupId );
-        setFieldValue( "saveProjectGroup_name", newName );
-        setFieldValue( "saveProjectGroup_description", newDescription );
-        clickButtonWithValue( "Save" );
-    }
-
-    public void assertEditGroupPage( String groupId ) throws Exception
-    {
-        assertPage( "Continuum - Update Project Group" );
-        assertTextPresent( "Update Project Group" );
-        assertTextPresent( "Project Group Name" );
-        assertElementPresent( "saveProjectGroup_name" );
-        assertTextPresent( "Project Group Id" );
-        assertTextPresent( groupId );
-        assertTextPresent( "Description" );
-        assertElementPresent( "saveProjectGroup_description" );
-
-        // Assert Projects actions
-        assertTextPresent( "Projects" );
-        assertTextPresent( "Project Name" );
-        assertTextPresent( "Move to Group" );
-
-        assertElementPresent( "saveProjectGroup_0" );
-        assertElementPresent( "Cancel" );
-    }
-
-    public void buildProjectGroup( String projectGroupName, String groupId, String description ) throws Exception
-    {
-        int tries = 0, maxTries = 100;
-
-        showProjectGroup( projectGroupName, groupId, description );
-        clickButtonWithValue( "Build" );
-
-        // make sure build will be completed
-        while ( isElementPresent( "//img[@alt='Updating sources']" ) )
-        {
-            Thread.sleep( 5000 );
-            showProjectGroup( projectGroupName, groupId, description );
-
-            if ( tries++ >= maxTries )
-            {
-                assertTrue( "Max tries waiting for the project to build reached.", false );
-            }
-        }
-        // test if successfully built, then return to the original page
-        clickLinkWithText( "Apache Maven" );
-        clickLinkWithText( "Builds" );
-        clickLinkWithText( "Result" );
-        assertTextPresent( "BUILD SUCCESSFUL" );
-        clickLinkWithText( "Project Group Summary" );
-    }
-
-    public void assertReleaseSuccess()
-    {
-        assertTextPresent( "Choose Release Goal for Apache Maven" );
-    }
-
-    public void assertReleaseEmpty()
-    {
-        assertTextPresent( "Cannot release an empty group" );
-    }
-
-    public void addValidM2ProjectFromProjectGroup( String projectGroupName, String groupId, String description,
-                                                   String m2PomUrl ) throws Exception
-    {
-        showProjectGroup( projectGroupName, groupId, description );
-        selectValue( "projectTypes", "Add M2 Project" );
-        clickButtonWithValue( "Add" );
-        assertAddMavenTwoProjectPage();
-
-        setFieldValue( "m2PomUrl", m2PomUrl );
-        clickButtonWithValue( "Add" );
-
-        // if success redirect to summary page
-        assertProjectGroupsSummaryPage();
-    }
-
-    public void goToBuildDefinitionPage( String projectGroupName, String groupId, String description ) throws Exception
-    {
-        showProjectGroup( projectGroupName, groupId, description );
-        clickLinkWithText( "Build Definitions" );
-        assertTextPresent( "Project Group Build Definitions of " + projectGroupName + " group" );
-
-        assertBuildDefinitionPage( projectGroupName );
-
-    }
-
-    public void assertBuildDefinitionPage( String projectGroupName )
-    {
-
-        assertTextPresent( "Project Group Build Definitions of " + projectGroupName + " group" );
-        assertElementPresent( "buildDefinition_0" );
-    }
-
-    public void assertNotifierPage( String projectGroupName )
-    {
-        assertTextPresent( "Project Group Notifiers of " + projectGroupName + " group" );
-    }
-
-    public void assertAddNotifierPage()
-    {
-        assertPage( "Continuum - Add Notifier" );
-        assertTextPresent( "Add Notifier" );
-        assertTextPresent( "Type" );
-        assertElementPresent( "notifierType" );
-        assertElementPresent( "Cancel" );
-    }
-
-    public void assertAddEditMailNotifierPage()
-    {
-        assertPage( "Continuum - Add/Edit Mail Notifier" );
-        assertTextPresent( "Add/Edit Mail Notifier" );
-        assertTextPresent( "Mail Recipient Address" );
-        assertTextPresent( "Send on Success" );
-        assertTextPresent( "Send on Failure" );
-        assertTextPresent( "Send on Error" );
-        assertTextPresent( "Send on Warning" );
-        assertElementPresent( "address" );
-        assertElementPresent( "Cancel" );
-    }
-
-    public void assertAddEditIrcNotifierPage()
-    {
-        assertPage( "Continuum - Add/Edit IRC Notifier" );
-
-        assertTextPresent( "IRC Host" );
-        assertElementPresent( "host" );
-
-        assertTextPresent( "IRC port" );
-        assertElementPresent( "port" );
-
-        assertTextPresent( "IRC channel" );
-        assertElementPresent( "channel" );
-
-        assertTextPresent( "Nick Name" );
-        assertElementPresent( "nick" );
-
-        assertTextPresent( "Full Name" );
-        assertElementPresent( "fullName" );
-
-        assertTextPresent( "Password" );
-        assertElementPresent( "password" );
-
-        assertTextPresent( "Send on Success" );
-        assertTextPresent( "Send on Failure" );
-        assertTextPresent( "Send on Error" );
-        assertTextPresent( "Send on Warning" );
-    }
-
-    public void assertAddEditJabberPage()
-    {
-        assertPage( "Continuum - Add/Edit Jabber Notifier" );
-
-        assertTextPresent( "Jabber Host" );
-        assertElementPresent( "host" );
-        assertTextPresent( "Jabber port" );
-        assertElementPresent( "port" );
-        assertTextPresent( "Jabber login" );
-        assertElementPresent( "login" );
-        assertTextPresent( "Jabber Password" );
-        assertElementPresent( "password" );
-        assertTextPresent( "Jabber Domain Name" );
-        assertElementPresent( "domainName" );
-        assertTextPresent( "Jabber Recipient Address" );
-        assertElementPresent( "address" );
-
-        assertTextPresent( "Is it a SSL connection?" );
-        assertTextPresent( "Is it a Jabber group?" );
-        assertTextPresent( "Send on Success" );
-        assertTextPresent( "Send on Failure" );
-        assertTextPresent( "Send on Error" );
-        assertTextPresent( "Send on Warning" );
-    }
-
-    public void assertAddEditMsnPage()
-    {
-        assertPage( "Continuum - Add/Edit MSN Notifier" );
-
-        assertTextPresent( "MSN login" );
-        assertElementPresent( "login" );
-        assertTextPresent( "MSN Password" );
-        assertElementPresent( "password" );
-        assertTextPresent( "MSN Recipient Address" );
-        assertElementPresent( "address" );
-
-        assertTextPresent( "Send on Success" );
-        assertTextPresent( "Send on Failure" );
-        assertTextPresent( "Send on Error" );
-        assertTextPresent( "Send on Warning" );
-    }
-
-    public void assertAddEditWagonPage()
-    {
-        assertPage( "Continuum - Add/Edit Wagon Notifier" );
-
-        assertTextPresent( "Project Site URL" );
-        assertElementPresent( "url" );
-
-        assertTextPresent( "Send on Success" );
-        assertTextPresent( "Send on Failure" );
-        assertTextPresent( "Send on Error" );
-        assertTextPresent( "Send on Warning" );
-    }
-
-    public void addMailNotifier( String projectGroupName, String projectGroupId, String projectGroupDescription,
-                                 String email, boolean isValid ) throws Exception
-    {
-
-        showProjectGroup( projectGroupName, projectGroupId, projectGroupDescription );
-        clickLinkWithText( "Notifiers" );
-        assertNotifierPage( projectGroupName );
-
-        clickButtonWithValue( "Add" );
-        assertAddNotifierPage();
-        selectValue( "addProjectGroupNotifier_notifierType", "Mail" );
-        clickButtonWithValue( "Submit" );
-        assertAddEditMailNotifierPage();
-        setFieldValue( "address", email );
-        clickButtonWithValue( "Save" );
-
-        if ( isValid )
-        {
-            assertNotifierPage( projectGroupName );
-        }
-        else
-        {
-            assertTextPresent( "Address is invalid" );
-        }
-    }
-
-    public void addIrcNotifier( String projectGroupName, String projectGroupId, String projectGroupDescription,
-                                String host, String channel, boolean isValid ) throws Exception
-    {
-        showProjectGroup( projectGroupName, projectGroupId, projectGroupDescription );
-
-        clickLinkWithText( "Notifiers" );
-        assertNotifierPage( projectGroupName );
-
-        clickButtonWithValue( "Add" );
-        assertAddNotifierPage();
-        selectValue( "addProjectGroupNotifier_notifierType", "IRC" );
-
-        clickButtonWithValue( "Submit" );
-        assertAddEditIrcNotifierPage();
-        setFieldValue( "host", host );
-        setFieldValue( "channel", channel );
-
-        clickButtonWithValue( "Save" );
-        if ( isValid )
-        {
-            assertNotifierPage( projectGroupName );
-        }
-        else
-        {
-            assertTextPresent( "Host is required" );
-            assertTextPresent( "Channel is required" );
-        }
-    }
-
-    public void addJabberNotifier( String projectGroupName, String projectGroupId, String projectGroupDescription,
-                                   String host, String login, String password, String address, boolean isValid )
-        throws Exception
-    {
-        showProjectGroup( projectGroupName, projectGroupId, projectGroupDescription );
-
-        clickLinkWithText( "Notifiers" );
-        assertNotifierPage( projectGroupName );
-
-        clickButtonWithValue( "Add" );
-        assertAddNotifierPage();
-        selectValue( "addProjectGroupNotifier_notifierType", "Jabber" );
-        clickButtonWithValue( "Submit" );
-
-        assertAddEditJabberPage();
-        setFieldValue( "host", host );
-        setFieldValue( "login", login );
-        setFieldValue( "password", password );
-        setFieldValue( "address", address );
-        clickButtonWithValue( "Save" );
-
-        if ( isValid )
-        {
-            assertNotifierPage( projectGroupName );
-        }
-        else
-        {
-            assertTextPresent( "Host is required" );
-            assertTextPresent( "Login is required" );
-            assertTextPresent( "Password is required" );
-            assertTextPresent( "Address is required" );
-        }
-    }
-
-    public void addMsnNotifierPage( String projectGroupName, String projectGroupId, String projectGroupDescription,
-                                    String login, String password, String recipientAddress, boolean isValid )
-        throws Exception
-    {
-        showProjectGroup( projectGroupName, projectGroupId, projectGroupDescription );
-
-        clickLinkWithText( "Notifiers" );
-        assertNotifierPage( projectGroupName );
-
-        clickButtonWithValue( "Add" );
-        assertAddNotifierPage();
-        selectValue( "addProjectGroupNotifier_notifierType", "MSN" );
-        clickButtonWithValue( "Submit" );
-        assertAddEditMsnPage();
-        setFieldValue( "login", login );
-        setFieldValue( "password", password );
-        setFieldValue( "address", recipientAddress );
-        clickButtonWithValue( "Save" );
-
-        if ( isValid )
-        {
-            assertNotifierPage( projectGroupName );
-        }
-        else
-        {
-            assertTextPresent( "Login is required" );
-            assertTextPresent( "Password is required" );
-            assertTextPresent( "Address is required" );
-        }
-    }
-
-    public void addWagonNotifierPage( String projectGroupName, String projectGroupId, String projectGroupDescription,
-                                      String siteUrl, boolean isValid ) throws Exception
-    {
-        showProjectGroup( projectGroupName, projectGroupId, projectGroupDescription );
-
-        clickLinkWithText( "Notifiers" );
-        assertNotifierPage( projectGroupName );
-
-        clickButtonWithValue( "Add" );
-        assertAddNotifierPage();
-        selectValue( "addProjectGroupNotifier_notifierType", "Wagon" );
-        clickButtonWithValue( "Submit" );
-        assertAddEditWagonPage();
-        setFieldValue( "url", siteUrl );
-        clickButtonWithValue( "Save" );
-
-        if ( isValid )
-        {
-            assertNotifierPage( projectGroupName );
-        }
-        else
-        {
-            assertTextPresent( "Destination URL is required" );
-        }
-    }
-
-    //////////////////////////////////////
-    // General Project Pages
-    //////////////////////////////////////
-    public void goToEditProjectPage( String projectGroupName, String projectName )
-    {
-        clickLinkWithText( "Show Project Groups" );
-        clickLinkWithText( projectGroupName );
-        clickLinkWithText( projectName );
-        clickButtonWithValue( "Edit" );
-
-        assertEditProjectPage();
-    }
-
-    public void assertEditProjectPage()
-    {
-        assertTextPresent( "Update Continuum Project" );
-        assertTextPresent( "Project Name*:" );
-        assertElementPresent( "name" );
-        assertTextPresent( "Version*:" );
-        assertElementPresent( "version" );
-        assertTextPresent( "SCM Url*:" );
-        assertElementPresent( "scmUrl" );
-        assertTextPresent( "Use SCM Credentials Cache, if available" );
-        assertElementPresent( "scmUseCache" );
-        assertTextPresent( "SCM Username:" );
-        assertElementPresent( "scmUsername" );
-        assertTextPresent( "SCM Password:" );
-        assertElementPresent( "scmPassword" );
-        assertTextPresent( "SCM Branch/Tag:" );
-        assertElementPresent( "scmTag" );
-    }
-
-    public void goToAddBuildDefinitionPage( String projectGroupName, String projectName )
-    {
-        clickLinkWithText( "Show Project Groups" );
-        clickLinkWithText( projectGroupName );
-        clickLinkWithText( projectName );
-        clickButtonWithValue( "Add" );
-
-        assertAddBuildDefinitionPage();
-    }
-
-    public void assertAddBuildDefinitionPage()
-    {
-        assertTextPresent( "Add/Edit Build Definition" );
-        assertTextPresent( "POM filename*:" );
-        assertElementPresent( "buildFile" );
-        assertTextPresent( "Goals:" );
-        assertElementPresent( "goals" );
-        assertTextPresent( "Arguments:" );
-        assertElementPresent( "arguments" );
-        assertTextPresent( "Build Fresh" );
-        assertElementPresent( "buildFresh" );
-        assertTextPresent( "Is it default?" );
-        assertElementPresent( "defaultBuildDefinition" );
-        assertTextPresent( "Schedule:" );
-        assertElementPresent( "scheduleId" );
-    }
-
-    public void addBuildDefinition( String projectGroupName, String projectName, String buildFile, String goals,
-                                    String arguments, boolean buildFresh, boolean isDefault )
-    {
-        goToAddBuildDefinitionPage( projectGroupName, projectName );
-
-        // Enter values into Add Build Definition fields, and submit
-        setFieldValue( "buildFile", buildFile );
-        setFieldValue( "goals", goals );
-        setFieldValue( "arguments", arguments );
-        if ( buildFresh )
-        {
-            checkField( "buildFresh" );
-        }
-        if ( isDefault )
-        {
-            checkField( "defaultBuildDefinition" );
-        }
-
-        submit();
-
-        assertProjectInformationPage();
-    }
-
-    public void goToAddNotifierPage( String projectGroupName, String projectName )
-    {
-        clickLinkWithText( "Show Project Groups" );
-        clickLinkWithText( projectGroupName );
-        clickLinkWithText( projectName );
-        getSelenium().click( "addProjectNotifier" );
-        clickLinkWithXPath( "//input[@id='addProjectNotifier_0']" );
-
-        assertNotifierPage();
-    }
-
-    public void assertNotifierPage()
-    {
-        assertPage( "Continuum - Add Notifier" );
-        assertTextPresent( "Add Notifier" );
-        assertTextPresent( "Type:" );
-        assertElementPresent( "notifierType" );
-    }
-
-    public void addMailNotifier( String projectGroupName, String projectName, String email, boolean success,
-                                 boolean failure, boolean error, boolean warning )
-    {
-        goToAddNotifierPage( projectGroupName, projectName );
-        clickButtonWithValue( "Submit" );
-
-        // Enter values into Add Notifier fields, and submit
-        setFieldValue( "address", email );
-        if ( success )
-        {
-            checkField( "sendOnSuccess" );
-        }
-        if ( failure )
-        {
-            checkField( "sendOnFailure" );
-        }
-        if ( error )
-        {
-            checkField( "sendOnError" );
-        }
-        if ( warning )
-        {
-            checkField( "sendOnWarning" );
-        }
-
-        submit();
-        assertProjectInformationPage();
-    }
-
-    public void goToProjectInformationPage( String projectGroupName, String projectName )
-    {
-        clickLinkWithText( "Show Project Groups" );
-        clickLinkWithText( projectGroupName );
-        clickLinkWithText( projectName );
-
-        assertProjectInformationPage();
-    }
-
-    public void assertProjectInformationPage()
-    {
-        assertTextPresent( "Project Group Summary" );
-        assertTextPresent( "Project Information" );
-        assertTextPresent( "Builds" );
-        assertTextPresent( "Working Copy" );
-        assertTextPresent( "Build Definitions" );
-        assertTextPresent( "Notifiers" );
-        assertTextPresent( "Dependencies" );
-        assertTextPresent( "Developers" );
-    }
-
-    //////////////////////////////////////
-    // Maven 2.0.x Project
-    //////////////////////////////////////
-    public void goToAddMavenTwoProjectPage()
-    {
-        clickLinkWithText( "Maven 2.0.x Project" );
-
-        assertAddMavenTwoProjectPage();
-    }
-
-    public void assertAddMavenTwoProjectPage()
-    {
-        assertTextPresent( "POM Url" );
-        assertElementPresent( "m2PomUrl" );
-        assertTextPresent( "Username" );
-        assertElementPresent( "scmUsername" );
-        assertTextPresent( "Password" );
-        assertElementPresent( "scmPassword" );
-        assertTextPresent( "Upload POM" );
-        assertElementPresent( "m2PomFile" );
-        assertTextPresent( "Project Group" );
-        assertElementPresent( "selectedProjectGroup" );
-    }
-
-    public void addMavenTwoProject( String pomUrl, String username, String password, String projectGroup, boolean validProject )
-    {
-        goToAddMavenTwoProjectPage();
-
-        // Enter values into Add Maven Two Project fields, and submit  
-        setFieldValue( "m2PomUrl", pomUrl );
-        setFieldValue( "scmUsername", username );
-        setFieldValue( "scmPassword", password );
-
-        if ( projectGroup != null )
-        {
-            selectValue( "addMavenTwoProject_selectedProjectGroup", projectGroup );
-        }
-
-        submit();
-
-        if ( validProject )
-        {
-            assertProjectGroupsSummaryPage();
-        }
-        else
-        {
-            assertAddMavenTwoProjectPage();
-        }
-    }
-
-    //TODO: problem with input type="file", selenium.type(..) does not work,
-    // TODO: refer to http://forums.openqa.org/thread.jspa?messageID=1365&#1365 for workaround
-    /*
-    public void addMavenTwoProject( String pomFile, String projectGroup, boolean validProject )
-        throws Exception
-    {
-        goToAddMavenTwoProjectPage();
-
-        // Enter values into Add Maven Two Project fields, and submit  
-        setFieldValue( "m2PomFile", pomFile );
-
-        if ( projectGroup != null )
-        {
-            selectValue( "addMavenTwoProject_selectedProjectGroup", projectGroup );
-        }
-
-        submit();
-
-        if ( validProject )
-        {
-            assertProjectGroupsSummaryPage();
-        }
-        else
-        {
-            assertAddMavenTwoProjectPage();
-        }
-    }
-    */
-
-    //////////////////////////////////////
-    // Maven 1.x Project
-    //////////////////////////////////////
-    public void goToAddMavenOneProjectPage()
-    {
-        clickLinkWithText( "Maven 1.x Project" );
-
-        assertAddMavenOneProjectPage();
-    }
-
-    public void assertAddMavenOneProjectPage()
-    {
-        assertTextPresent( "POM Url" );
-        assertElementPresent( "m1PomUrl" );
-        assertTextPresent( "Username" );
-        assertElementPresent( "scmUsername" );
-        assertTextPresent( "Password" );
-        assertElementPresent( "scmPassword" );
-        assertTextPresent( "Upload POM" );
-        assertElementPresent( "m1PomFile" );
-        assertTextPresent( "Project Group" );
-        assertElementPresent( "selectedProjectGroup" );
-    }
-
-    public void addMavenOneProject( String pomUrl, String username, String password, String projectGroup, boolean validProject )
-    {
-        goToAddMavenOneProjectPage();
-
-        // Enter values into Add Maven One Project fields, and submit  
-        setFieldValue( "m1PomUrl", pomUrl );
-        setFieldValue( "scmUsername", username );
-        setFieldValue( "scmPassword", password );
-
-        if ( projectGroup != null )
-        {
-            selectValue( "addMavenOneProject_selectedProjectGroup", projectGroup );
-        }
-
-        submit();
-
-        if ( validProject )
-        {
-            assertProjectGroupsSummaryPage();
-        }
-        else
-        {
-            assertAddMavenOneProjectPage();
-        }
-    }
-
-    //TODO: problem with input type="file", selenium.type(..) does not work,
-    // TODO: refer to http://forums.openqa.org/thread.jspa?messageID=1365&#1365 for workaround
-    /*
-    public void addMavenOneProject( String pomFile, String projectGroup, boolean validProject )
-        throws Exception
-    {
-        goToAddMavenOneProjectPage();
-
-        // Enter values into Add Maven One Project fields, and submit  
-        setFieldValue( "m1PomFile", pomFile );
-
-        if ( projectGroup != null )
-        {
-            selectValue( "addMavenOneProject_selectedProjectGroup", projectGroup );
-        }
-
-        submit();
-
-        if ( validProject )
-        {
-            assertProjectGroupsSummaryPage();
-        }
-        else
-        {
-            assertAddMavenOneProjectPage();
-        }
-    }
-    */
-
-    public void moveProjectToProjectGroup( String name, String groupId, String description, String newProjectGroup )
-        throws Exception
-    {
-        showProjectGroup( name, groupId, description );
-
-        assertElementPresent( "edit" );
-        clickButtonWithValue( "Edit" );
-
-        assertTextPresent( "Move to Group" );
-        selectValue( "//select", newProjectGroup );
-
-        assertElementPresent( "saveProjectGroup_0" );
-        clickButtonWithValue( "Save" );
-    }
-
-    public void tearDown()
-        throws Exception
-    {
-        login( adminUsername, adminPassword );
-
-        goToProjectGroupsSummaryPage();
-
-        if ( isLinkPresent( TEST_PROJ_GRP_NAME ) )
-        {
-            removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-        }
-        // TODO: clean this up
-        if ( isLinkPresent( "Apache Maven" ) )
-        {
-            removeProjectGroup( "Apache Maven", "org.apache.maven", "Maven is a software project management and comprehension tool. Based on the concept of a project object model (POM), Maven can manage a project's build, reporting and documentation from a central piece of information." );
-        }
-        if ( isLinkPresent( "Maven One Project" ) )
-        {
-            removeProjectGroup( "Maven One Project", "maven-one-project", "This is a sample Maven One Project." );
-        }
-        if ( isLinkPresent( DEFAULT_PROJ_GRP_NAME ) &&
-            "0".equals( getCellValueFromTable( "ec_table", 1, 2 ) ) == false )
-        {
-            removeProjectGroup( DEFAULT_PROJ_GRP_NAME, DEFAULT_PROJ_GRP_ID, DEFAULT_PROJ_GRP_DESCRIPTION );
-            addProjectGroup( DEFAULT_PROJ_GRP_NAME, DEFAULT_PROJ_GRP_ID, DEFAULT_PROJ_GRP_DESCRIPTION );
-        }
-
-        super.tearDown();
-    }
-
-    protected String getWebContext()
-    {
-        return "/continuum";
-    }
-}
diff --git a/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/AbstractGuestAccessTestCase.java b/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/AbstractGuestAccessTestCase.java
deleted file mode 100644
index e95f0d9..0000000
--- a/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/AbstractGuestAccessTestCase.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.apache.continuum.web.test;
-
-/*
- * Copyright 2005-2006 The Apache Software Foundation.
- *
- * Licensed 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.
- */
-
-/**
- * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
- * @version $Id$
- */
-public abstract class AbstractGuestAccessTestCase
-    extends AbstractContinuumTestCase
-{
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-        assertFalse( "User was authenticated.", isAuthenticated() );
-    }
-}
diff --git a/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/AccountSecurityTest.java b/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/AccountSecurityTest.java
deleted file mode 100644
index 5e6de52..0000000
--- a/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/AccountSecurityTest.java
+++ /dev/null
@@ -1,327 +0,0 @@
-package org.apache.continuum.web.test;
-
-/*
- * Copyright 2005-2006 The Apache Software Foundation.
- *
- * Licensed 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 org.apache.maven.shared.web.test.XPathExpressionUtil;
-
-public class AccountSecurityTest
-    extends AbstractAuthenticatedAccessTestCase
-{
-    public final String SIMPLE_POM = getBasedir() + "/target/test-classes/unit/simple-project/pom.xml";
-
-    // create user fields
-    public static final String CREATE_FORM_USERNAME_FIELD = "userCreateForm_user_username";
-
-    public static final String CREATE_FORM_FULLNAME_FIELD = "userCreateForm_user_fullName";
-
-    public static final String CREATE_FORM_EMAILADD_FIELD = "userCreateForm_user_email";
-
-    public static final String CREATE_FORM_PASSWORD_FIELD = "userCreateForm_user_password";
-
-    public static final String CREATE_FORM_CONFIRM_PASSWORD_FIELD = "userCreateForm_user_confirmPassword";
-
-    public static final String PASSWORD_FIELD = "user.password";
-
-    public static final String CONFIRM_PASSWORD_FIELD = "user.confirmPassword";
-
-    // user account 1
-    public static final String CUSTOM_USERNAME = "custom1";
-
-    public static final String CUSTOM_USERNAME2 = "custom2";
-
-    public static final String CUSTOM_USERNAME3 = "custom3";
-
-    public static final String CUSTOM_USERNAME4 = "custom4";
-
-    public static final String CUSTOM_USERNAME5 = "custom5";
-
-    public static final String CUSTOM_FULLNAME = "custom fullname";
-
-    public static final String CUSTOM_EMAILADD = "custom@custom.com";
-
-    public static final String CUSTOM_PASSWORD = "custompassword";
-
-    public String getUsername()
-    {
-        return super.adminUsername;
-    }
-
-    public String getPassword()
-    {
-        return super.adminPassword;
-    }
-
-    public void tearDown()
-        throws Exception
-    {
-        login( adminUsername, adminPassword );
-
-        clickLinkWithText( "Users" );
-
-        String[] users = {CUSTOM_USERNAME, CUSTOM_USERNAME2, CUSTOM_USERNAME3, CUSTOM_USERNAME4, CUSTOM_USERNAME5};
-
-        for ( int i = 0; i < users.length; i++ )
-        {
-            String[] columns = new String[]{users[i], CUSTOM_FULLNAME, CUSTOM_EMAILADD};
-            if ( isElementPresent( XPathExpressionUtil.getTableRow( columns ) ) )
-            {
-                if ( i == 4 )
-                {
-                    // TODO! this is due to a bug where roles are not removed with the user, so remove them by hand [CONTINUUM-1095]
-                    clickLinkWithText( CUSTOM_USERNAME5 );
-                    clickLinkWithText( "Edit Roles" );
-                    checkField( "removeRolesFromUser_removeSelectedRolesSystem Administrator" );
-                    clickButtonWithValue( "Remove Selected Roles" );
-                }
-
-                deleteUser( users[i], CUSTOM_FULLNAME, CUSTOM_EMAILADD );
-            }
-        }
-
-        logout();
-
-        super.tearDown();
-    }
-
-    public void testBasicUserAddDelete()
-    {
-        createUser( CUSTOM_USERNAME, CUSTOM_FULLNAME, CUSTOM_EMAILADD, CUSTOM_PASSWORD, true );
-
-        // delete custom user
-        deleteUser( CUSTOM_USERNAME, CUSTOM_FULLNAME, CUSTOM_EMAILADD );
-    }
-
-    public void testPasswordConfirmation()
-        throws Exception
-    {
-        // initial user account creation ignores the password creation checks
-        createUser( CUSTOM_USERNAME2, CUSTOM_FULLNAME, CUSTOM_EMAILADD, CUSTOM_PASSWORD, true );
-        logout();
-
-        // start password creation validation test
-        login( CUSTOM_USERNAME2, CUSTOM_PASSWORD );
-
-        // Edit user informations
-        goToMyAccount();
-
-        //TODO: verify account details page
-        assertPage( "Account Details" );
-
-        // test password confirmation
-        setFieldValue( PASSWORD_FIELD, CUSTOM_PASSWORD );
-        setFieldValue( CONFIRM_PASSWORD_FIELD, CUSTOM_PASSWORD + "error" );
-        clickButtonWithValue( "Submit" );
-
-        // we should still be in Account Details
-        assertPage( "Account Details" );
-        isTextPresent( "Password confirmation failed.  Passwords do not match" );
-
-        logout();
-
-        // house keeping
-        login( getUsername(), getPassword() );
-        deleteUser( CUSTOM_USERNAME2, CUSTOM_FULLNAME, CUSTOM_EMAILADD );
-        logout();
-    }
-
-    public void testPasswordCreationValidation()
-        throws Exception
-    {
-        // initial user account creation ignores the password creation checks
-        createUser( CUSTOM_USERNAME3, CUSTOM_FULLNAME, CUSTOM_EMAILADD, CUSTOM_PASSWORD, true );
-        logout();
-
-        // start password creation validation test
-        login( CUSTOM_USERNAME3, CUSTOM_PASSWORD );
-
-        // password test
-        String alphaTest = "abcdef";
-        String numericalTest = "123456";
-        String characterLengthTest = "aaaaaaa12";
-        String validPassword = "abc123";
-
-        // select profile
-        clickLinkWithText( "Edit Details" );
-
-        //TODO: verify account details page
-        assertPage( "Account Details" );
-
-        // test all alpha
-        setFieldValue( PASSWORD_FIELD, alphaTest );
-        setFieldValue( CONFIRM_PASSWORD_FIELD, alphaTest );
-        clickButtonWithValue( "Submit" );
-
-        // we should still be in Account Details
-        assertPage( "Account Details" );
-        isTextPresent( "You must provide a password containing at least 1 numeric character(s)." );
-
-        setFieldValue( PASSWORD_FIELD, numericalTest );
-        setFieldValue( CONFIRM_PASSWORD_FIELD, numericalTest );
-        clickButtonWithValue( "Submit" );
-
-        // we should still be in Account Details
-        assertPage( "Account Details" );
-        isTextPresent( "You must provide a password containing at least 1 alphabetic character(s)." );
-
-        setFieldValue( PASSWORD_FIELD, characterLengthTest );
-        setFieldValue( CONFIRM_PASSWORD_FIELD, characterLengthTest );
-        clickButtonWithValue( "Submit" );
-
-        // we should still be in Account Details
-        assertPage( "Account Details" );
-        isTextPresent( "You must provide a password between 1 and 8 characters in length." );
-
-        // we should still be in Account Details
-        assertPage( "Account Details" );
-        isTextPresent( "You must provide a password containing at least 1 alphabetic character(s)." );
-
-        setFieldValue( PASSWORD_FIELD, validPassword );
-        setFieldValue( CONFIRM_PASSWORD_FIELD, validPassword );
-        clickButtonWithValue( "Submit" );
-
-        // we should still be in Account Details
-        assertPage( "Continuum - Group Summary" );
-
-        logout();
-
-        // house keeping
-        login( getUsername(), getPassword() );
-        deleteUser( CUSTOM_USERNAME3, CUSTOM_FULLNAME, CUSTOM_EMAILADD );
-        logout();
-    }
-
-
-    public void testThreeStrikeRule()
-        throws Exception
-    {
-        createUser( CUSTOM_USERNAME4, CUSTOM_FULLNAME, CUSTOM_EMAILADD, CUSTOM_PASSWORD, true );
-        logout();
-
-        int numberOfTries = 3;
-
-        for ( int nIndex = 0; nIndex < numberOfTries; nIndex++ )
-        {
-            if ( nIndex < 2 )
-            {
-                login( this.CUSTOM_USERNAME4, this.CUSTOM_PASSWORD + "error", false, "Login Page" );
-                // login should fail
-                assertTextPresent( "You have entered an incorrect username and/or password" );
-                assertFalse( "user is authenticated using wrong password", isAuthenticated() );
-            }
-            else
-            {
-                // on the 3rd try, account is locked and we are returned to the Group Summary Page
-                login( this.CUSTOM_USERNAME4, this.CUSTOM_PASSWORD + "error", false, "Continuum - Group Summary" );
-                assertTextPresent( "Account Locked" );
-            }
-        }
-
-        // house keeping
-        login( getUsername(), getPassword() );
-        deleteUser( CUSTOM_USERNAME4, CUSTOM_FULLNAME, CUSTOM_EMAILADD, false, true );
-        logout();
-    }
-
-    public void testDefaultRolesOfNewSystemAdministrator()
-        throws Exception
-    {
-        // initialize
-        createUser( CUSTOM_USERNAME5, CUSTOM_FULLNAME, CUSTOM_EMAILADD, CUSTOM_PASSWORD, true );
-
-        // upgrade the role of the user to system administrator
-        assertUserRolesPage();
-        checkField( "addRolesToUser_addSelectedRolesSystem Administrator" );
-        clickButtonWithValue( "Add Selected Roles" );
-
-        // after adding roles, we are returned to the list of users
-        //TODO: check Permanent/validated/locked columns
-        clickLinkWithText( CUSTOM_USERNAME5 );
-
-        // verify roles
-        String[] roleList = {"System Administrator", "User Administrator", 
-            "Continuum Group Project Administrator", "Project Developer - Default Project Group",
-            "Project User - Default Project Group"};
-Thread.sleep( 20000 );
-        assertElementPresent( XPathExpressionUtil.getList( roleList ) );
-        deleteUser( CUSTOM_USERNAME5, CUSTOM_FULLNAME, CUSTOM_EMAILADD );
-    }
-
-    private void createUser( String userName, String fullName, String emailAdd, String password, boolean valid )
-    {
-        createUser( userName, fullName, emailAdd, password, password, valid );
-    }
-
-    private void createUser( String userName, String fullName, String emailAdd, String password, String confirmPassword,
-                             boolean valid )
-    {
-        clickLinkWithText( "Users" );
-        assertUsersListPage();
-
-        // create user
-        clickButtonWithValue( "Create New User" );
-        assertCreateUserPage();
-        setFieldValue( CREATE_FORM_USERNAME_FIELD, userName );
-        setFieldValue( CREATE_FORM_FULLNAME_FIELD, fullName );
-        setFieldValue( CREATE_FORM_EMAILADD_FIELD, emailAdd );
-        setFieldValue( CREATE_FORM_PASSWORD_FIELD, password );
-        setFieldValue( CREATE_FORM_CONFIRM_PASSWORD_FIELD, confirmPassword );
-        submit();
-
-        // click past second page without adding any roles
-        assertUserRolesPage();
-        clickButtonWithValue( "Add Selected Roles" );
-
-        if ( valid )
-        {
-            assertUsersListPage();
-
-            String[] columnValues = {userName, fullName, emailAdd};
-
-            // check if custom user is created
-            assertElementPresent( XPathExpressionUtil.getTableRow( columnValues ) );
-            //TODO: check Permanent/validated/locked columns
-        }
-        else
-        {
-            assertCreateUserPage();
-        }
-    }
-
-    private void deleteUser( String userName, String fullName, String emailAdd )
-    {
-        deleteUser( userName, fullName, emailAdd, false, false );
-    }
-
-    private void deleteUser( String userName, String fullName, String emailAdd, boolean validated, boolean locked )
-    {
-        //TODO: Add permanent/validated/locked values
-        String[] columnValues = {userName, fullName, emailAdd};
-
-        clickLinkWithText( "Users" );
-
-        // delete user
-        clickLinkWithXPath(
-            XPathExpressionUtil.getImgColumnElement( XPathExpressionUtil.ANCHOR, 7, "delete.gif", columnValues ) );
-
-        // confirm
-        assertDeleteUserPage( userName );
-        submit();
-
-        // check if account is successfuly deleted
-        assertElementNotPresent( XPathExpressionUtil.getTableRow( columnValues ) );
-    }
-}
diff --git a/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/AddMavenOneProjectTestCase.java b/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/AddMavenOneProjectTestCase.java
deleted file mode 100644
index 7629c10..0000000
--- a/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/AddMavenOneProjectTestCase.java
+++ /dev/null
@@ -1,144 +0,0 @@
-package org.apache.continuum.web.test;
-
-/*
- * Copyright 2005-2006 The Apache Software Foundation.
- *
- * Licensed 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.io.File;
-
-/**
- * Class for testing add maven one project UI page.
- */
-public class AddMavenOneProjectTestCase
-    extends AbstractAuthenticatedAccessTestCase
-{
-    public String getUsername()
-    {
-        return adminUsername;
-    }
-
-    public String getPassword()
-    {
-        return adminPassword;
-    }
-
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-    }
-
-    /**
-     * submit the page
-     *
-     * @param m1PomUrl
-     * @param validPom
-     */
-    public void submitAddMavenOneProjectPage( String m1PomUrl, boolean validPom )
-    {
-        addMavenOneProject( m1PomUrl, "", "", null, validPom );
-
-        if ( validPom )
-        {
-            assertTextPresent( "Default Project Group" );
-            //TODO: Add more tests
-        }
-    }
-
-    /**
-     * test with valid pom url
-     */
-    public void testValidPomUrl()
-        throws Exception
-    {
-        String pomUrl = "http://svn.apache.org/repos/asf/maven/continuum/trunk/continuum-webapp-test/src/test/resources/unit/maven-one-projects/valid-project.xml";
-        submitAddMavenOneProjectPage( pomUrl, true );
-        //Test the group is created
-        assertTextPresent( "Maven One Project" );
-        //TODO: add more tests
-        removeProjectGroup( "Maven One Project", "maven-one-project", "This is a sample Maven One Project." );
-    }
-
-    /**
-     * test with no pom file or pom url specified
-     */
-    public void testNoPomSpecified()
-    {
-        submitAddMavenOneProjectPage( "", false );
-        assertTextPresent( "Either POM URL or Upload POM is required." );
-    }
-
-    /**
-     * test with missing <repository> element in the pom file
-     */
-    public void testMissingElementInPom()
-    {
-        String pomUrl = "http://svn.apache.org/repos/asf/maven/continuum/trunk/continuum-webapp-test/src/test/resources/unit/maven-one-projects/missing-repository-element-project.xml";
-        submitAddMavenOneProjectPage( pomUrl, false );
-        assertTextPresent( "Missing 'repository' element in the POM." );
-    }
-
-
-    /**
-     * test with <extend> element present in pom file
-     */
-    public void testWithExtendElementPom()
-    {
-        String pomUrl = "http://svn.apache.org/repos/asf/maven/continuum/trunk/continuum-webapp-test/src/test/resources/unit/maven-one-projects/extend-element-project.xml";
-        submitAddMavenOneProjectPage( pomUrl, false );
-        assertTextPresent( "Cannot use a POM with an 'extend' element." );
-    }
-
-    /**
-     * test with unparseable xml content for pom file
-     */
-    public void testUnparseableXmlContent()
-    {
-        String pomUrl = "http://svn.apache.org/repos/asf/maven/continuum/trunk/continuum-webapp-test/src/test/resources/unit/maven-one-projects/unparseable-content-project.xml";
-        submitAddMavenOneProjectPage( pomUrl, false );
-        assertTextPresent( "The XML content of the POM can not be parsed." );
-    }
-
-    /**
-     * test with a malformed pom url
-     */
-    public void testMalformedPomUrl()
-    {
-        String pomUrl = "aaa";
-        submitAddMavenOneProjectPage( pomUrl, false );
-        assertTextPresent(
-            "The specified resource cannot be accessed. Please try again later or contact your administrator." );
-    }
-
-    /**
-     * test with an inaccessible pom url
-     */
-    public void testInaccessiblePomUrl()
-    {
-        String pomUrl = "http://www.google.com";
-        submitAddMavenOneProjectPage( pomUrl, false );
-        assertTextPresent( "POM file does not exist. Either the POM you specified or one of its modules does not exist." );
-    }
-
-    /**
-     * test unallowed file protocol
-     */
-    public void testNotAllowedProtocol()
-    {
-        String pomUrl = "file:///project.xml";
-        submitAddMavenOneProjectPage( pomUrl, false );
-        assertTextPresent( "The specified resource isn't a file or the protocol used isn't allowed." );
-    }
-}
diff --git a/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/AddMavenTwoProjectTest.java b/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/AddMavenTwoProjectTest.java
deleted file mode 100644
index e6c4196..0000000
--- a/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/AddMavenTwoProjectTest.java
+++ /dev/null
@@ -1,166 +0,0 @@
-package org.apache.continuum.web.test;
-
-/*
- * Copyright 2005-2006 The Apache Software Foundation.
- *
- * Licensed 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.
- */
-
-public class AddMavenTwoProjectTest
-    extends AbstractAuthenticatedAdminAccessTestCase
-{
-    public void testAddMavenTwoProjectFromRemoteSource()
-        throws Exception
-    {
-        // Enter values into Add Maven Two Project fields, and submit
-        addMavenTwoProject( TEST_POM_URL, TEST_POM_USERNAME, TEST_POM_PASSWORD, null, true );
-
-        clickLinkWithText( DEFAULT_PROJ_GRP_NAME );
-
-        removeProjectGroup( "Apache Maven", "org.apache.maven", "Maven is a software project management and comprehension tool. Based on the concept of a project object model (POM), Maven can manage a project's build, reporting and documentation from a central piece of information." );
-    }
-
-    public void testAddMavenTwoProjectFromRemoteSourceToNonDefaultProjectGroup()
-        throws Exception
-    {
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        addMavenTwoProject( TEST_POM_URL, TEST_POM_USERNAME, TEST_POM_PASSWORD, TEST_PROJ_GRP_NAME, true );
-
-        assertCellValueFromTable( TEST_PROJ_GRP_NAME, "ec_table", 2, 0 );
-        assertCellValueFromTable( TEST_PROJ_GRP_ID, "ec_table", 2, 1 );
-        assertCellValueFromTable( "1", "ec_table", 2, 2 );
-
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-    }
-
-    /**
-     * submit the page
-     *
-     * @param m2PomUrl
-     * @param validPom
-     */
-    public void submitAddMavenTwoProjectPage( String m2PomUrl, boolean validPom )
-    {
-        addMavenTwoProject( m2PomUrl, "", "", null, validPom );
-
-        if ( validPom )
-        {
-            assertTextPresent( "Default Project Group" );
-            //TODO: Add more tests
-        }
-    }
-
-    /**
-     * Test invalid pom url
-     */
-    public void testNoPomSpecified()
-    {
-        submitAddMavenTwoProjectPage( "", false );
-        assertTextPresent( "Either POM URL or Upload POM is required." );
-    }
-
-    /**
-     * Test when scm element is missing from pom
-     */
-    public void testMissingScmElementPom()
-    {
-        String pomUrl = "http://svn.apache.org/repos/asf/maven/continuum/trunk/continuum-webapp-test/src/test/resources/unit/maven-two-projects/missing-scm-element-pom.xml";
-        submitAddMavenTwoProjectPage( pomUrl, false );
-        assertTextPresent( "Missing 'scm' element in the POM." );
-    }
-
-    /**
-     * Test when the specified pom url is invalid
-     */
-    public void testCannotAccessResource()
-    {
-        String pomUrl = "http://svn.apache.org/asf/maven/continuum/trunk/bad_url/pom.xml";
-        submitAddMavenTwoProjectPage( pomUrl, false );
-        assertTextPresent(
-            "POM file does not exist. Either the POM you specified or one of its modules does not exist." );
-    }
-
-    /**
-     * test with a malformed pom url
-     */
-    public void testMalformedPomUrl()
-    {
-        String pomUrl = "aaa";
-        submitAddMavenTwoProjectPage( pomUrl, false );
-        assertTextPresent(
-            "The specified resource cannot be accessed. Please try again later or contact your administrator." );
-    }
-
-    /**
-     * Test when the connection element is missing from the scm tag
-     */
-    public void testMissingConnectionElement()
-    {
-        String pomUrl = "http://svn.apache.org/repos/asf/maven/continuum/trunk/continuum-webapp-test/src/test/resources/unit/maven-two-projects/missing-connection-element-pom.xml";
-        submitAddMavenTwoProjectPage( pomUrl, false );
-        assertTextPresent( "Missing 'connection' sub-element in the 'scm' element in the POM." );
-    }
-
-    /**
-     * Test when the parent pom is missing or not yet added in continuum
-     */
-    public void testMissingParentPom()
-    {
-        String pomUrl = "http://svn.apache.org/repos/asf/maven/continuum/trunk/continuum-webapp-test/src/test/resources/unit/maven-two-projects/missing-parent-pom.xml";
-        submitAddMavenTwoProjectPage( pomUrl, false );
-        assertTextPresent(
-            "Missing artifact trying to build the POM. Check that its parent POM is available or add it first in Continuum." );
-    }
-
-    /**
-     * Test when the modules/subprojects specified in the pom are not found
-     */
-    public void testMissingModules()
-    {
-        String pomUrl= "http://svn.apache.org/repos/asf/maven/continuum/trunk/continuum-webapp-test/src/test/resources/unit/maven-two-projects/missing-modules-pom.xml";
-        submitAddMavenTwoProjectPage( pomUrl, false );
-        assertTextPresent( "Unknown error trying to build POM." );
-    }
-
-    /**
-     * test with an inaccessible pom url
-     */
-    public void testInaccessiblePomUrl()
-    {
-        String pomUrl = "http://www.google.com";
-        submitAddMavenTwoProjectPage( pomUrl, false );
-        assertTextPresent( "POM file does not exist. Either the POM you specified or one of its modules does not exist." );
-    }
-
-    /**
-     * test unallowed file protocol
-     */
-    public void testNotAllowedProtocol()
-    {
-        String pomUrl = "file:///pom.xml";
-        submitAddMavenTwoProjectPage( pomUrl, false );
-        assertTextPresent( "The specified resource isn't a file or the protocol used isn't allowed." );
-    }
-
-    /**
-     * test cancel button
-     */
-    public void testCancelButton()
-    {
-        goToAboutPage();
-        goToAddMavenTwoProjectPage();
-        clickButtonWithValue( "Cancel" );
-        assertAboutPage();
-    }
-}
diff --git a/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/AntTest.java b/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/AntTest.java
deleted file mode 100644
index 7c17166..0000000
--- a/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/AntTest.java
+++ /dev/null
@@ -1,112 +0,0 @@
-package org.apache.continuum.web.test;
-
-/*
- * Copyright 2005-2006 The Apache Software Foundation.
- *
- * Licensed 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.
- */
-
-/**
- * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
- * @version $Id$
- */
-public class AntTest
-    extends AbstractAuthenticatedAdminAccessTestCase
-{
-    public void testAddAntProject()
-        throws Exception
-    {
-        goToAddAntPage();
-        setFieldValue( "projectName", "Foo" );
-        setFieldValue( "projectVersion", "1.0-SNAPSHOT" );
-        setFieldValue( "projectScmUrl",
-                       "https://svn.apache.org/repos/asf/maven/continuum/trunk/continuum-test-projects/ant/" );
-        clickButtonWithValue( "Add" );
-
-        assertProjectGroupsSummaryPage();
-        assertTextPresent( "Default Project Group" );
-        clickLinkWithText( "Default Project Group" );
-        assertTextPresent( "Foo" );
-
-        //TODO Add more tests (values in Default Project Group, values in project view, notifiers, build defintions, delete, build,...)
-    }
-
-    public void testSubmitEmptyForm()
-    {
-        goToAddAntPage();
-        clickButtonWithValue( "Add", false );
-        assertAddAntProjectPage();
-        assertTextPresent( "Name is required" );
-        assertTextPresent( "Version is required" );
-        assertTextPresent( "SCM Url is required" );
-    }
-
-    public void testSubmitEmptyProjectName()
-    {
-        goToAddAntPage();
-        clickButtonWithValue( "Add", false );
-        assertAddAntProjectPage();
-        assertTextPresent( "Name is required" );
-    }
-
-    public void testSubmitEmptyVersion()
-    {
-        goToAddAntPage();
-        clickButtonWithValue( "Add", false );
-        assertAddAntProjectPage();
-        assertTextPresent( "Version is required" );
-    }
-
-    public void testSubmitEmptyScmUrl()
-    {
-        goToAddAntPage();
-        clickButtonWithValue( "Add", false );
-        assertAddAntProjectPage();
-        assertTextPresent( "SCM Url is required" );
-    }
-
-    public void testSubmitDoubleErrorMessages()
-    {
-        goToAddAntPage();
-        clickButtonWithValue( "Add", false );
-        clickButtonWithValue( "Add", false );
-        assertAddAntProjectPage();
-        if ( "Name is required".equals( getSelenium().getText( "//td/span" ) ) )
-        {
-            assertFalse( "Double Error Messages", "Name is required".equals( getSelenium().getText( "//tr[2]/td/span" ) ) );
-        }
-        if ( "Version is required".equals( getSelenium().getText( "//tr[4]/td/span" ) ) )
-        {
-            assertFalse( "Double Error Messages", "Version is required".equals( getSelenium().getText( "//tr[5]/td/span" ) ) );
-        }
-        if ( "SCM Url is required".equals( getSelenium().getText( "//tr[7]/td/span" ) ) )
-        {
-            assertFalse( "Double Error Messages", "SCM Url is required".equals( getSelenium().getText( "//tr[8]/td/span" ) ) );
-        }
-    }
-
-    public void testCancelButton()
-    {
-        goToAboutPage();
-        goToAddAntPage();
-        clickButtonWithValue( "Cancel" );
-        assertAboutPage();
-    }
-
-    private void goToAddAntPage()
-    {
-        clickLinkWithText( "Ant Project" );
-        assertAddAntProjectPage();
-    }
-
-}
diff --git a/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/LoginTest.java b/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/LoginTest.java
deleted file mode 100644
index 9252ab0..0000000
--- a/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/LoginTest.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package org.apache.continuum.web.test;
-
-/*
- * Copyright 2005-2006 The Apache Software Foundation.
- *
- * Licensed 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.
- */
-
-/**
- * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
- * @version $Id$
- */
-public class LoginTest
-    extends AbstractGuestAccessTestCase
-{
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-        clickLinkWithText( "Login" );
-        assertLoginPage();
-    }
-
-    public void testWithBadUsername()
-    {
-        submitLoginPage( "badUsername", "badPassword", false );
-        assertLoginPage();
-        assertTextPresent( "You have entered an incorrect username and/or password" );
-    }
-
-    public void testWithBadPassword()
-    {
-        submitLoginPage( adminUsername, "badPassword", false );
-        assertLoginPage();
-        assertTextPresent( "You have entered an incorrect username and/or password" );
-    }
-
-    public void testWithEmptyUsername()
-    {
-        submitLoginPage( "", "badPassword", false );
-        assertLoginPage();
-        assertTextPresent( "Username cannot be empty." );
-    }
-
-    public void testWithEmptyPassword()
-    {
-        submitLoginPage( adminUsername, "", false );
-        assertLoginPage();
-        assertTextPresent( "You have entered an incorrect username and/or password" );
-    }
-
-    public void testWithCorrectUsernamePassword()
-    {
-        submitLoginPage( adminUsername, adminPassword );
-        logout();
-    }
-
-}
diff --git a/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/MyAccountTest.java b/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/MyAccountTest.java
deleted file mode 100644
index efd8673..0000000
--- a/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/MyAccountTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.apache.continuum.web.test;
-
-/*
- * Copyright 2005-2006 The Apache Software Foundation.
- *
- * Licensed 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.
- */
-
-/**
- * Test update or edit account of the current user.
- */
-public class MyAccountTest
-    extends AbstractAuthenticatedAdminAccessTestCase
-{
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-    }
-
-    public void testMyAccountEdit()
-        throws Exception
-    {
-        String newFullName = "Continuum Admin _ new";
-        String newEmail = "admin_new@localhost.localdomain.com";
-        String newPassword = "admin1_new";
-        String newConfirmationPassword = newPassword;
-
-        goToMyAccount();
-
-        // check current account details
-        assertMyAccountDetails( adminUsername, adminFullName, adminEmail );
-
-        // change account details
-        editMyUserInfo( newFullName, newEmail, newPassword, newConfirmationPassword );
-        assertMyAccountDetails( adminUsername, newFullName, newEmail );
-
-        // revert to original account details
-        editMyUserInfo( adminFullName, adminEmail, adminPassword, adminPassword );
-        assertMyAccountDetails( adminUsername, adminFullName, adminEmail );
-    }
-
-}
diff --git a/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/ProjectGroupTest.java b/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/ProjectGroupTest.java
deleted file mode 100644
index dd70411..0000000
--- a/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/ProjectGroupTest.java
+++ /dev/null
@@ -1,475 +0,0 @@
-package org.apache.continuum.web.test;
-
-/*
- * Copyright 2005-2006 The Apache Software Foundation.
- *
- * Licensed 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.
- */
-
-/**
- * Test case for project groups.
- */
-public class ProjectGroupTest
-    extends AbstractAuthenticatedAdminAccessTestCase
-{
-    public void testAddRemoveProjectGroup()
-        throws Exception
-    {
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        showProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-    }
-
-    public void testDefaultBuildDefinition()
-        throws Exception
-    {
-        goToProjectGroupsSummaryPage();
-
-        showProjectGroup( DEFAULT_PROJ_GRP_NAME, DEFAULT_PROJ_GRP_ID, DEFAULT_PROJ_GRP_DESCRIPTION );
-
-        clickLinkWithText( "Build Definitions" );
-
-        String tableElement = "ec_table";
-        assertCellValueFromTable( "Goals", tableElement, 0, 0 );
-        assertCellValueFromTable( "Arguments", tableElement, 0, 1 );
-        assertCellValueFromTable( "Build File", tableElement, 0, 2 );
-        assertCellValueFromTable( "Schedule", tableElement, 0, 3 );
-        assertCellValueFromTable( "From", tableElement, 0, 4 );
-        assertCellValueFromTable( "Build Fresh", tableElement, 0, 5 );
-        assertCellValueFromTable( "Default", tableElement, 0, 6 );
-        assertCellValueFromTable( "", tableElement, 0, 7 );
-        assertCellValueFromTable( "", tableElement, 0, 8 );
-
-        assertCellValueFromTable( "clean install", tableElement, 1, 0 );
-        assertCellValueFromTable( "--batch-mode --non-recursive", tableElement, 1, 1 );
-        assertCellValueFromTable( "pom.xml", tableElement, 1, 2 );
-        assertCellValueFromTable( "DEFAULT_SCHEDULE", tableElement, 1, 3 );
-        assertCellValueFromTable( "GROUP", tableElement, 1, 4 );
-        assertCellValueFromTable( "false", tableElement, 1, 5 );
-        assertCellValueFromTable( "true", tableElement, 1, 6 );
-        assertImgWithAlt( "Edit" );
-        assertImgWithAlt( "Delete" );
-    }
-
-    public void testMoveProject()
-        throws Exception
-    {
-        // Add a project group and a project to it
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-        addMavenTwoProject( TEST_POM_URL, TEST_POM_USERNAME, TEST_POM_PASSWORD, TEST_PROJ_GRP_NAME, true );
-
-        // assert that the default project group has 0 projects while the test project group has 1
-        assertCellValueFromTable( "0", "ec_table", 1, 2 );
-        assertCellValueFromTable( "1", "ec_table", 2, 2 );
-
-        // move the project of the test project group to the default project group
-        moveProjectToProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION,
-                                   DEFAULT_PROJ_GRP_NAME );
-
-        // assert that the default project group now has 1 while the test project group has 0
-        goToProjectGroupsSummaryPage();
-        assertCellValueFromTable( "1", "ec_table", 1, 2 );
-        assertCellValueFromTable( "0", "ec_table", 2, 2 );
-
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-    }
-
-    public void testAddBuildDefinitionWithEmptyStrings() throws Exception
-    {
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-        showProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        clickLinkWithText( "Build Definitions" );
-        clickButtonWithValue( "Add" );
-        clickButtonWithValue( "Save" );
-
-        assertTextPresent( "POM is required." );
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-    }
-
-    public void testAddBuildDefinitionWithSpaces() throws Exception
-    {
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-        showProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        clickLinkWithText( "Build Definitions" );
-        clickButtonWithValue( "Add" );
-        setFieldValue( "buildFile", "" );
-        clickButtonWithValue( "Save" );
-
-        assertTextPresent( "POM is invalid." );
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-    }
-
-    public void testCancelAddProjectGroup() throws Exception
-    {
-        clickLinkWithText( "Show Project Groups" );
-        clickButtonWithValue( "Add Project Group" );
-        clickButtonWithValue( "Cancel" );
-
-        assertPage( "Continuum - Group Summary" );
-        assertTextPresent( "Project Groups" );
-        assertButtonWithValuePresent( "Add Project Group" );
-    }
-
-    public void testCancelEditProjectGroup() throws Exception
-    {
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-        showProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        clickButtonWithValue( "Edit" );
-        clickButtonWithValue( "Cancel" );
-
-        assertProjectGroupSummaryPage( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-    }
-
-    public void testCancelDeleteProjectGroup() throws Exception
-    {
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-        showProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        clickButtonWithValue( "Delete" );
-        clickButtonWithValue( "Cancel" );
-
-        assertProjectGroupSummaryPage( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-    }
-
-    public void testCancelAddBuildDefinition() throws Exception
-    {
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-        showProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        clickLinkWithText( "Build Definitions" );
-        clickButtonWithValue( "Add" );
-        clickButtonWithValue( "Cancel" );
-
-        assertTextPresent( "Project Group Build Definitions of " + TEST_PROJ_GRP_NAME );
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-    }
-
-    public void testCancelDeleteBuildDefinition() throws Exception
-    {
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-        showProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        clickLinkWithText( "Build Definitions" );
-        clickLinkWithXPath( "//img[@alt='Delete']" );
-        clickButtonWithValue( "Cancel" );
-
-        assertTextPresent( "Project Group Build Definitions of " + TEST_PROJ_GRP_NAME );
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-    }
-
-    public void testCancelAddNotifier() throws Exception
-    {
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-        showProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        clickLinkWithText( "Notifiers" );
-        clickButtonWithValue( "Add" );
-        clickButtonWithValue( "Cancel" );
-
-        assertTextPresent( "Project Group Notifiers of " + TEST_PROJ_GRP_NAME );
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-    }
-
-    public void testCancelDeleteNotifier() throws Exception
-    {
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-        showProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        clickLinkWithText( "Notifiers" );
-        clickButtonWithValue( "Add" );
-        clickButtonWithValue( "Submit" );
-        setFieldValue( "address", "email@domain.com" );
-        submit();
-        clickLinkWithXPath( "//img[@alt='Delete']" );
-        clickButtonWithValue( "Cancel" );
-
-        assertTextPresent( "Project Group Notifiers of " + TEST_PROJ_GRP_NAME );
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-    }
-
-    public void testAddProjectGroupWithEmptyString() throws Exception
-    {
-        addProjectGroup( "", "", "" );
-        assertTextPresent( "Project Group Name required." );
-        assertTextPresent( "Project Group ID required." );
-    }
-
-    public void testAddProjectGroupWithWhitespaceString() throws Exception
-    {
-        addProjectGroup( " ", " ", " " );
-        assertTextPresent( "Project Group Name required." );
-        assertTextPresent( "Project Group ID required." );
-    }
-
-    public void testEditProjectGroupWithInvalidValues() throws Exception
-    {
-
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-        editProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION, "",
-                          TEST_PROJ_GRP_DESCRIPTION + "_2" );
-
-        assertTextPresent( "Project Group Name required." );
-
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-    }
-
-    public void testEditProjectGroupWithValidValues() throws Exception
-    {
-        final String sNewProjectName = TEST_PROJ_GRP_NAME + "_2";
-        final String sNewProjectDescription = TEST_PROJ_GRP_DESCRIPTION + "_2";
-
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-        editProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION, sNewProjectName,
-                          sNewProjectDescription );
-
-        assertProjectGroupSummaryPage( sNewProjectName, TEST_PROJ_GRP_ID, sNewProjectDescription );
-
-        removeProjectGroup( sNewProjectName, TEST_PROJ_GRP_ID, sNewProjectDescription );
-    }
-
-    public void testProjectGroupAllBuildSuccess() throws Exception
-    {
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        addValidM2ProjectFromProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION,
-                                           TEST_POM_URL );
-
-        showProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        buildProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        clickButtonWithValue( "Release" );
-
-        assertReleaseSuccess();
-
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-    }
-
-    public void testProjectGroupNoProject() throws Exception
-    {
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-        showProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        clickButtonWithValue( "Release" );
-        assertReleaseEmpty();
-
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-    }
-
-    public void testAddGroupProjectAnt() throws Exception
-    {
-        clickLinkWithText( "Ant Project" );
-        assertAddAntProjectPage();
-        setFieldValue( "projectName", "Foo" );
-        setFieldValue( "projectVersion", "1.0-SNAPSHOT" );
-        // TODO change to invalid url
-        setFieldValue( "projectScmUrl",
-                       "https://svn.apache.org/repos/asf/maven/continuum/trunk/continuum-test-projects/ant/" );
-
-        // selectValue( "projectTypes", "Add M2 Project" );
-        // setselectedProjectGroup
-        clickButtonWithValue( "Add" );
-
-        assertProjectGroupsSummaryPage();
-        assertTextPresent( "Default Project Group" );
-        clickLinkWithText( "Default Project Group" );
-        assertTextPresent( "Foo" );
-
-    }
-
-    public void testfromGroupBuildDefinition() throws Exception
-    {
-        final String projectGroupName2 = TEST_PROJ_GRP_NAME + "_2";
-        final String projectgroupId2 = TEST_PROJ_GRP_ID + "_2";
-        final String projectGroupDescription2 = TEST_PROJ_GRP_DESCRIPTION + "_2";
-
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-        addProjectGroup( projectGroupName2, projectgroupId2, projectGroupDescription2 );
-
-        addMavenTwoProject( TEST_POM_URL, "", "", TEST_PROJ_GRP_NAME, true );
-
-        addMavenTwoProject( TEST_POM_URL, "", "", projectGroupName2, true );
-
-        goToBuildDefinitionPage( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-        clickImgWithAlt( "Build" );
-
-        assertProjectGroupsSummaryPage();
-
-        removeProjectGroup( projectGroupName2, projectgroupId2, projectGroupDescription2 );
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-    }
-
-    public void testBuildFromProjectGroupSummary() throws Exception
-    {
-        final String projectGroupName2 = TEST_PROJ_GRP_NAME + "_2";
-        final String projectgroupId2 = TEST_PROJ_GRP_ID + "_2";
-        final String projectGroupDescription2 = TEST_PROJ_GRP_DESCRIPTION + "_2";
-
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-        addProjectGroup( projectGroupName2, projectgroupId2, projectGroupDescription2 );
-
-        addMavenTwoProject( TEST_POM_URL, "", "", TEST_PROJ_GRP_NAME, true );
-
-        addMavenTwoProject( TEST_POM_URL, "", "", projectGroupName2, true );
-
-        showProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-        clickButtonWithValue( "Build" );
-
-        assertProjectGroupSummaryPage( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        removeProjectGroup( projectGroupName2, projectgroupId2, projectGroupDescription2 );
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-    }
-
-    public void testDeleteProjectGroupBuild() throws Exception
-    {
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        addMavenTwoProject( TEST_POM_URL, "", "", TEST_PROJ_GRP_NAME, true );
-
-        showProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-        clickImgWithAlt( "Delete" );
-        assertElementPresent( "deleteProject_0" );
-        assertElementPresent( "Cancel" );
-
-        clickSubmitWithLocator( "deleteProject_0" );
-
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-    }
-
-    public void testAddValidMailNotifier() throws Exception
-    {
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        addMailNotifier( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION, "test@test.com", true );
-
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-    }
-
-    public void testAddInvalidMailNotifier() throws Exception
-    {
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        addMailNotifier( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION, "invalid_email_add", false );
-
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-    }
-
-    public void testAddValidIrcNotifier() throws Exception
-    {
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        addIrcNotifier( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION, "test.com", "test_channel",
-                        true );
-
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-    }
-
-    public void testAddInvalidIrcNotifier() throws Exception
-    {
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        addIrcNotifier( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION, "", "", false );
-
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-    }
-
-    public void testAddValidJabberNotifier() throws Exception
-    {
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        addJabberNotifier( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION, "test", "test_login",
-                           "hello", "test@address.com", true );
-
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-    }
-
-    public void testAddInvalidJabberNotifier() throws Exception
-    {
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        addJabberNotifier( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION, "", "", "", "", false );
-
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-    }
-
-    public void testAddValidMsnNotifier() throws Exception
-    {
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        addMsnNotifierPage( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION, "test", "hello",
-                            "test@address.com", true );
-
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-    }
-
-    public void testAddInvalidMsnNotifier() throws Exception
-    {
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        addMsnNotifierPage( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION, "", "", "", false );
-
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-    }
-
-    public void testAddValidWagonNotifier() throws Exception
-    {
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        addWagonNotifierPage( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION, TEST_POM_URL, true );
-
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-    }
-
-    public void testAddInvalidWagonNotifier() throws Exception
-    {
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        addWagonNotifierPage( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION, "", false );
-
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-    }
-
-    public void testDeleteNotifier() throws Exception
-    {
-        addProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-        showProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-
-        clickLinkWithText( "Notifiers" );
-        assertNotifierPage( TEST_PROJ_GRP_NAME );
-
-        clickButtonWithValue( "Add" );
-        assertAddNotifierPage();
-        selectValue( "addProjectGroupNotifier_notifierType", "Wagon" );
-        clickButtonWithValue( "Submit" );
-        assertAddEditWagonPage();
-        setFieldValue( "url", TEST_POM_URL );
-        clickButtonWithValue( "Save" );
-
-        assertNotifierPage( TEST_PROJ_GRP_NAME );
-
-        clickImgWithAlt( "Delete" );
-        clickSubmitWithLocator( "deleteProjectGroupNotifier_0" );
-        assertNotifierPage( TEST_PROJ_GRP_NAME );
-
-        removeProjectGroup( TEST_PROJ_GRP_NAME, TEST_PROJ_GRP_ID, TEST_PROJ_GRP_DESCRIPTION );
-    }
-}
diff --git a/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/SchedulesPageTest.java b/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/SchedulesPageTest.java
deleted file mode 100644
index 72f13e1..0000000
--- a/continuum-webapp-test/src/test/it/org/apache/continuum/web/test/SchedulesPageTest.java
+++ /dev/null
@@ -1,452 +0,0 @@
-package org.apache.continuum.web.test;
-
-/*
- * Copyright 2005-2006 The Apache Software Foundation.
- *
- * Licensed 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 org.apache.maven.shared.web.test.XPathExpressionUtil;
-
-import java.util.HashMap;
-
-/**
- *
- *
- *
- */
-public class SchedulesPageTest
-    extends AbstractAuthenticatedAccessTestCase
-{
-    // Add Edit Page fields
-    final public static String FIELD_NAME = "name";
-
-    final public static String FIELD_DESCRIPTION = "description";
-
-    final public static String FIELD_SECOND = "second";
-
-    final public static String FIELD_MINUTE = "minute";
-
-    final public static String FIELD_HOUR = "hour";
-
-    final public static String FIELD_DAYOFMONTH = "dayOfMonth";
-
-    final public static String FIELD_MONTH = "month";
-
-    final public static String FIELD_DAYOFWEEK = "dayOfWeek";
-
-    final public static String FIELD_YEAR = "year";
-
-    final public static String FIELD_MAXJOBEXECUTIONTIME = "maxJobExecutionTime";
-
-    final public static String FIELD_DELAY = "delay";
-
-
-    // field values
-    final public static String SCHEDULES_PAGE_TITLE = "Continuum - Schedules";
-
-    final public static String DEFAULT_SCHEDULE = "DEFAULT_SCHEDULE";
-
-    final public static String DEFAULT_SCHEDULE_DESCRIPTION = "Run hourly";
-
-    final public static String DEFAULT_CRONVALUE = "0 0 * * * ?";
-
-    final public static String DEFAULT_DELAY = "0";
-
-    final public static String DEFAULT_MAXJOBEXECUTIONTIME = "0";
-
-    final public static String EDIT_SCHEDULE_PAGE_TITLE = "Continuum - Edit Schedule";
-
-    final public static String SCHEDULE_NAME = "Test Schedule";
-
-    final public static String SCHEDULE_NAME_EDIT = "Test Schedule Edit";
-
-    final public static String SCHEDULE_DESCRIPTION = "Test Description";
-
-    final public static String SECOND = "1";
-
-    final public static String MINUTE = "2";
-
-    final public static String HOUR = "3";
-
-    final public static String DAYOFMONTH = "?";
-
-    final public static String MONTH = "4";
-
-    final public static String DAYOFWEEK = "5";
-
-    final public static String YEAR = "2020";
-
-    final public static String MAXJOBEXECUTIONTIME = "6";
-
-    final public static String DELAY = "7";
-
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-
-        clickLinkWithText( "Schedules" );
-
-        assertSchedulesPage();
-    }
-
-    public String getUsername()
-    {
-        return this.adminUsername;
-    }
-
-    public String getPassword()
-    {
-        return this.adminPassword;
-    }
-
-    public void testBasicScheduleAddAndDelete()
-        throws Exception
-    {
-        // add schedule
-        clickButtonWithValue( "Add" );
-
-        assertEditSchedulePage();
-
-        inputSchedule( SCHEDULE_NAME, SCHEDULE_DESCRIPTION, SECOND, MINUTE, HOUR, DAYOFMONTH, MONTH, DAYOFWEEK, YEAR,
-                       MAXJOBEXECUTIONTIME, DELAY, true );
-
-        String cronSchedule = SECOND;
-        cronSchedule += " " + MINUTE;
-        cronSchedule += " " + HOUR;
-        cronSchedule += " " + DAYOFMONTH;
-        cronSchedule += " " + MONTH;
-        cronSchedule += " " + DAYOFWEEK;
-        cronSchedule += " " + YEAR;
-
-        String[] columnValues = {SCHEDULE_NAME, SCHEDULE_DESCRIPTION, DELAY, cronSchedule, MAXJOBEXECUTIONTIME};
-
-        assertTrue( "Can not add schedule",
-                    getSelenium().isElementPresent( XPathExpressionUtil.getTableRow( columnValues ) ) );
-
-        // delete schedule after adding
-        deleteSchedule( SCHEDULE_NAME );
-
-        assertFalse( "Can not delete schedule",
-                     getSelenium().isElementPresent( XPathExpressionUtil.getTableRow( columnValues ) ) );
-    }
-
-    public void testEditSchedule()
-        throws Exception
-    {
-        clickButtonWithValue( "Add" );
-
-        assertEditSchedulePage();
-
-        inputSchedule( SCHEDULE_NAME_EDIT, SCHEDULE_DESCRIPTION, SECOND, MINUTE, HOUR, DAYOFMONTH, MONTH, DAYOFWEEK,
-                       YEAR, MAXJOBEXECUTIONTIME, DELAY, true );
-
-        String cronSchedule = SECOND;
-        cronSchedule += " " + MINUTE;
-        cronSchedule += " " + HOUR;
-        cronSchedule += " " + DAYOFMONTH;
-        cronSchedule += " " + MONTH;
-        cronSchedule += " " + DAYOFWEEK;
-        cronSchedule += " " + YEAR;
-
-        String[] columnValues = {SCHEDULE_NAME, SCHEDULE_DESCRIPTION, DELAY, cronSchedule, MAXJOBEXECUTIONTIME};
-
-        // edit the schedule        
-        clickLinkWithXPath(
-            XPathExpressionUtil.getImgColumnElement( XPathExpressionUtil.ANCHOR, 5, "edit.gif", columnValues ) );
-
-        inputSchedule( SCHEDULE_NAME_EDIT + "modified", SCHEDULE_DESCRIPTION + "updated", "2", "3", "4", "?", "6", "7",
-                       "2021", "8", "9", false );
-
-        cronSchedule = "2 3 4 ? 6 7 2021";
-
-        String[] editedColumnValues =
-            {SCHEDULE_NAME_EDIT + "modified", SCHEDULE_DESCRIPTION + "updated", "9", cronSchedule, "8"};
-
-        assertTrue( "Can not edit schedule",
-                    getSelenium().isElementPresent( XPathExpressionUtil.getTableRow( editedColumnValues ) ) );
-
-        // check if the active state has been saved
-        clickLinkWithXPath(
-            XPathExpressionUtil.getImgColumnElement( XPathExpressionUtil.ANCHOR, 5, "edit.gif", editedColumnValues ) );
-
-        assertEquals( "Can disable the schedule", CHECKBOX_UNCHECK, getFieldValue( "active" ) );
-
-        //house keeping
-        clickLinkWithText( "Schedules" );
-        deleteSchedule( SCHEDULE_NAME_EDIT + "modified" );
-    }
-
-    public void testScheduleAddEditPageInputValidation()
-    {
-        clickButtonWithValue( "Add" );
-
-        assertEditSchedulePage();
-
-        HashMap fields = new HashMap();
-        fields.put( FIELD_MAXJOBEXECUTIONTIME, "" );
-        boolean valid = false;
-        boolean wait = false;
-
-        // test saving without editing anything from the initial edit page except for Max Job Execution Time
-        inputSchedule( fields, wait, valid );
-
-        assertTrue( "Name field not validated",
-                    getSelenium().isElementPresent( "//tr/td[span='schedule.name.required']" ) );
-        assertTrue( "Description field not validated",
-                    getSelenium().isElementPresent( "//tr/td[span='schedule.version.required']" ) );
-        assertTrue( "Max Job Execution Time field not validated",
-                    getSelenium().isElementPresent( "//tr/td[span='schedule.maxJobExecutionTime.required']" ) );
-
-        // go back to the schedules page
-        clickLinkWithText( "Schedules" );
-
-        // start new schedule add session
-        clickButtonWithValue( "Add" );
-
-        // test saving using spaces for name and description
-        fields.put( FIELD_NAME, " " );
-        fields.put( FIELD_DESCRIPTION, " " );
-
-        inputSchedule( fields, wait, valid );
-
-        //TODO: Fix text validation, we need real text and not a property in the screen
-        assertTrue( "Name field not validated",
-                     getSelenium().isElementPresent( "//tr/td[span='schedule.name.required']" ) );
-        assertTrue( "Description field not validated",
-                     getSelenium().isElementPresent( "//tr/td[span='schedule.version.required']" ) );
-
-        // go back to the schedules page
-        clickLinkWithText( "Schedules" );
-
-        // start new schedule add session
-        clickButtonWithValue( "Add" );
-
-        // test saving using alpha characters for the maxjobexecution and delay
-        // with valid name and description  
-        fields.put( FIELD_NAME, SCHEDULE_NAME );
-        fields.put( FIELD_DESCRIPTION, SCHEDULE_DESCRIPTION );
-        fields.put( FIELD_MAXJOBEXECUTIONTIME, "abcde" );
-        fields.put( FIELD_DELAY, "abcde" );
-
-        inputSchedule( fields, wait, valid );
-
-        //TODO: Fix text validation, we need real text and not a property in the screen
-        assertFalse( "Name field improperly validated",
-                     getSelenium().isElementPresent( "//tr/td[span='schedule.name.required']" ) );
-        assertFalse( "Description field improperly validated",
-                     getSelenium().isElementPresent( "//tr/td[span='schedule.version.required']" ) );
-        assertFalse( "Max Job Execution Time field improperly validated",
-                    getSelenium().isElementPresent( "//tr/td[span='schedule.maxJobExecutionTime.required']" ) );
-        assertTrue( "MaxJobExecutionTime not validated", isTextPresent( "schedule.maxJobExecutionTime.invalid" ) );
-        assertTrue( "Delay not validated", isTextPresent( "schedule.delay.invalid" ) );
-
-        assertEditSchedulePage();
-    }
-
-
-    public void testScheduleAddEditPageDoubleErrorMessages()
-    {
-        clickButtonWithValue( "Add" );
-
-        assertEditSchedulePage();
-
-        HashMap fields = new HashMap();
-        boolean valid = false;
-        boolean wait = false;
-
-        // test double error messages issue of webworks
-        inputSchedule( fields, wait, valid );
-        clickButtonWithValue( "Save", false );
-
-        if ( "schedule.name.required".equals( getSelenium().getText( "//td/span" ) ) )
-        {
-            assertFalse( "Double Error Messages", "schedule.name.required".equals( getSelenium().getText( "//tr[2]/td/span" ) ) );
-        }
-        if ( "schedule.version.required".equals( getSelenium().getText( "//tr[4]/td/span" ) ) )
-        {
-            assertFalse( "Double Error Messages", "schedule.version.required".equals( getSelenium().getText( "//tr[5]/td/span" ) ) );
-        }
-
-        assertEditSchedulePage();
-    }
-
-    public void testCancelAddSchedule()
-    {
-        clickButtonWithValue( "Add" );
-        clickButtonWithValue( "Cancel" );
-        assertSchedulesPage();
-    }
-
-    public void testCancelEditSchedule()
-    {
-        clickLinkWithXPath( "//img[@alt='Edit']" );
-        clickButtonWithValue( "Cancel" );
-        assertSchedulesPage();
-    }
-
-    public void testCancelDeleteSchedule()
-    {
-        clickLinkWithXPath( "//img[@alt='Delete']" );
-        clickButtonWithValue( "Cancel" );
-        assertSchedulesPage();
-    }
-
-    public void assertSchedulesPage()
-    {
-        assertPage( SCHEDULES_PAGE_TITLE );
-
-        assertDefaultSchedule();
-    }
-
-    public void assertDefaultSchedule()
-    {
-        String[] columnValues = {DEFAULT_SCHEDULE, DEFAULT_SCHEDULE_DESCRIPTION, DEFAULT_DELAY, DEFAULT_CRONVALUE,
-            DEFAULT_MAXJOBEXECUTIONTIME};
-
-        assertTrue( "Default schedule not found",
-                    getSelenium().isElementPresent( XPathExpressionUtil.getTableRow( columnValues ) ) );
-    }
-
-    public void assertEditSchedulePage()
-    {
-        assertPage( EDIT_SCHEDULE_PAGE_TITLE );
-
-        //TODO: assert error messages
-
-        assertEditSchedulePageInputFields();
-    }
-
-    public void assertEditSchedulePageInputFields()
-    {
-        //TODO: assert content
-
-        assertElementPresent( "saveSchedule_id" );
-        assertElementPresent( "id" );
-        assertElementPresent( "saveSchedule_name" );
-        assertElementPresent( "name" );
-        assertElementPresent( "saveSchedule_description" );
-        assertElementPresent( "description" );
-        assertElementPresent( "saveSchedule_second" );
-        assertElementPresent( "second" );
-        assertElementPresent( "saveSchedule_minute" );
-        assertElementPresent( "minute" );
-        assertElementPresent( "saveSchedule_hour" );
-        assertElementPresent( "hour" );
-        assertElementPresent( "saveSchedule_dayOfMonth" );
-        assertElementPresent( "dayOfMonth" );
-        assertElementPresent( "saveSchedule_month" );
-        assertElementPresent( "month" );
-        assertElementPresent( "saveSchedule_dayOfWeek" );
-        assertElementPresent( "dayOfWeek" );
-        assertElementPresent( "saveSchedule_year" );
-        assertElementPresent( "year" );
-        assertElementPresent( "saveSchedule_maxJobExecutionTime" );
-        assertElementPresent( "maxJobExecutionTime" );
-        assertElementPresent( "saveSchedule_delay" );
-        assertElementPresent( "delay" );
-        assertElementPresent( "saveSchedule_active" );
-        assertElementPresent( "active" );
-    }
-
-    public void deleteSchedule( String scheduleName )
-    {
-        // after we save the schedule we should be brought back to the schedules page
-        assertSchedulesPage();
-
-        String[] columnValues = {scheduleName};
-
-        clickLinkWithXPath(
-            XPathExpressionUtil.getImgColumnElement( XPathExpressionUtil.ANCHOR, 5, "delete.gif", columnValues ) );
-
-        // deletion confirmation page
-        assertPage( "Schedule Removal" );
-        //TODO: assert content
-        //TODO: assert schedule name is in deletion confirmation
-
-        clickButtonWithValue( "Delete" );
-
-        // after we confirm the deletion we should be brought back to the schedules page
-        assertSchedulesPage();
-    }
-
-
-    public void inputSchedule( String scheduleName, String scheduleDescription, String second, String minute,
-                               String hour, String dayOfMonth, String month, String dayOfWeek, String year,
-                               String maxJobExecutionTime, String delay, boolean active )
-    {
-        inputSchedule( scheduleName, scheduleDescription, second, minute, hour, dayOfMonth, month, dayOfWeek, year,
-                       maxJobExecutionTime, delay, active, true );
-    }
-
-
-    public void inputSchedule( String scheduleName, String schedule_description, String second, String minute,
-                               String hour, String dayOfMonth, String month, String dayOfWeek, String year,
-                               String maxJobExecutionTime, String delay, boolean active, boolean wait )
-    {
-        assertEditSchedulePage();
-
-        HashMap inputFields = new HashMap();
-
-        inputFields.put( "name", scheduleName );
-        inputFields.put( "description", schedule_description );
-        inputFields.put( "second", second );
-        inputFields.put( "minute", minute );
-        inputFields.put( "hour", hour );
-        inputFields.put( "dayOfMonth", dayOfMonth );
-        inputFields.put( "month", month );
-        inputFields.put( "dayOfWeek", dayOfWeek );
-        inputFields.put( "year", year );
-        inputFields.put( "maxJobExecutionTime", maxJobExecutionTime );
-        inputFields.put( "delay", delay );
-
-        if ( !active )
-        {
-            uncheckField( "active" );
-        }
-
-        inputSchedule( inputFields, wait, true );
-    }
-
-    public void inputSchedule( HashMap fields )
-    {
-        inputSchedule( fields, true, true );
-    }
-
-    public void inputSchedule( HashMap fields, boolean wait, boolean valid )
-    {
-        setFieldValues( fields );
-
-        clickButtonWithValue( "Save", wait );
-
-        if ( valid )
-        {
-            // after we save the schedule we should be brought back to the schedules page        
-            assertSchedulesPage();
-        }
-        else
-        {
-            assertEditSchedulePage();
-        }
-    }
-
-    public void tearDown()
-        throws Exception
-    {
-        logout();
-
-        super.tearDown();
-    }
-}
diff --git a/continuum-webapp-test/src/test/resources/testng.properties b/continuum-webapp-test/src/test/resources/testng.properties
new file mode 100644
index 0000000..1310de2
--- /dev/null
+++ b/continuum-webapp-test/src/test/resources/testng.properties
@@ -0,0 +1,409 @@
+#
+# 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.
+#
+
+# General properties
+
+MAX_WAIT_TIME_IN_MS=60000
+MAX_PROJECT_WAIT_TIME_IN_MS=120000
+
+WAIT_TRIES=80
+
+# Users
+
+ADMIN_USERNAME=admin
+ADMIN_FULLNAME=admin
+ADMIN_PASSWORD=admin123
+ADMIN_MAIL=admin@mail.com
+
+# Maven 2 projects to load
+
+MAVEN2_POM_URL=http://localhost:${continuum.port}/example-projects/simple-example/pom.xml
+MAVEN2_POM_USERNAME=
+MAVEN2_POM_PASSWORD=
+MAVEN2_POM_PROJECT_NAME=Continuum Simple Example Project
+# values used for "Defined by POM" - tests should clean up this group afterwards if added
+MAVEN2_POM_PROJECT_GROUP_NAME=Continuum Simple Example Project
+MAVEN2_POM_PROJECT_GROUP_ID=org.apache.continuum.examples.simple
+MAVEN2_POM_PROJECT_GROUP_DESCRIPTION=
+MAVEN2_POM_PROJECT_GROUP_SCM_ROOT_URL=scm:svn:${svn.base.url}/trunk/simple-example
+
+MAVEN2_PROJECT_WITH_TAG_POM_URL=http://localhost:${continuum.port}/example-projects/continuum-2437-example/pom.xml
+MAVEN2_PROJECT_WITH_TAG_POM_PROJECT_NAME=Continuum 2437 Example Project
+# values used for "Defined by POM" - tests should clean up this group afterwards if added
+MAVEN2_PROJECT_WITH_TAG_POM_PROJECT_GROUP_NAME=Continuum 2437 Example Project
+MAVEN2_PROJECT_WITH_TAG_POM_PROJECT_GROUP_ID=org.apache.continuum.examples
+MAVEN2_PROJECT_WITH_TAG_POM_PROJECT_GROUP_DESCRIPTION=
+
+MAVEN2_FAILING_PROJECT_POM_URL=http://localhost:${continuum.port}/example-projects/continuum-failing-project/pom.xml
+# values used for "Defined by POM" - tests should clean up this group afterwards if added
+MAVEN2_FAILING_PROJECT_POM_PROJECT_GROUP_NAME=Continuum Sample Failing Project
+MAVEN2_FAILING_PROJECT_POM_PROJECT_GROUP_ID=org.apache.continuum.failing.project
+MAVEN2_FAILING_PROJECT_POM_PROJECT_GROUP_DESCRIPTION=Sample project that has a build failure
+
+MAVEN2_QUEUE_TEST_POM_URL=http://localhost:${continuum.port}/example-projects/continuum-build-queue-test-data/pom.xml
+MAVEN2_QUEUE_TEST_POM_USERNAME=
+MAVEN2_QUEUE_TEST_POM_PASSWORD=
+# values used for "Defined by POM" - tests should clean up this group afterwards if added
+MAVEN2_QUEUE_TEST_POM_PROJECT_GROUP_NAME=ContinuumBuildQueueTestData
+MAVEN2_QUEUE_TEST_POM_PROJECT_GROUP_ID=org.apache.continuum
+MAVEN2_QUEUE_TEST_POM_PROJECT_GROUP_DESCRIPTION=Project for testing continuum build queue
+
+# Ant projects to load
+
+ANT_NAME=Sample Ant Project
+ANT_DESCRIPTION=This is a sample Ant Project used for testing
+ANT_VERSION=1.0.0-SNAPSHOT
+ANT_TAG=
+ANT_SCM_URL=http://localhost:${continuum.port}/example-projects/ant/
+ANT_SCM_USERNAME=
+ANT_SCM_PASSWORD=
+
+# Maven 1 projects to load
+
+MAVEN1_POM_URL=http://localhost:${continuum.port}/example-projects/maven-one-projects/valid-project.xml
+MAVEN1_POM_USERNAME=
+MAVEN1_POM_PASSWORD=
+
+# Shell projects to load
+
+SHELL_PROJECT_NAME=Test Shell Project
+SHELL_PROJECT_DESCRIPTION=This is a sample Shell Project used for testing
+SHELL_PROJECT_VERSION=1.0.0-SNAPSHOT
+SHELL_PROJECT_TAG=
+SHELL_PROJECT_SCM_URL=scm:svn:${svn.base.url}/trunk/shell/
+SHELL_PROJECT_SCM_USERNAME=
+SHELL_PROJECT_SCM_PASSWORD=
+
+# Default project group
+
+DEFAULT_PROJECT_GROUP_NAME=Default Project Group
+DEFAULT_PROJECT_GROUP_ID=default
+DEFAULT_PROJECT_GROUP_DESCRIPTION=Contains all projects that do not have a group of their own
+
+# Schedule detail data
+SCHEDULE_DESCRIPTION=schedule_description
+SCHEDULE_EXPR_SECOND=10
+SCHEDULE_EXPR_MINUTE=10
+SCHEDULE_EXPR_HOUR=20
+SCHEDULE_EXPR_DAY_MONTH=*
+SCHEDULE_EXPR_MONTH=*
+SCHEDULE_EXPR_DAY_WEEK=?
+SCHEDULE_EXPR_YEAR=2009
+SCHEDULE_MAX_TIME=60000
+SCHEDULE_PERIOD=36000
+
+### The following properties should not be shared across groups ###
+
+# Notifier test properties
+
+NOTIFIER_PROJECT_GROUP_NAME=Notifier Project Group
+NOTIFIER_PROJECT_GROUP_ID=com.example.notifiers
+NOTIFIER_PROJECT_GROUP_DESCRIPTION=Sample projects for testing notifiers
+MAIL_NOTIFIER_ADDRESS=test@test.com
+IRC_NOTIFIER_HOST=test.com
+IRC_NOTIFIER_CHANNEL=test_channel
+JABBER_NOTIFIER_HOST=test
+JABBER_NOTIFIER_LOGIN=test_login
+JABBER_NOTIFIER_PASSWORD=hello
+JABBER_NOTIFIER_ADDRESS=test@address.com
+MSN_NOTIFIER_ADDRESS=test@address.com
+MSN_NOTIFIER_LOGIN=test
+MSN_NOTIFIER_PASSWORD=hello
+WAGON_NOTIFIER_URL=http://svn.apache.org/repos/asf/maven/pom/trunk/maven/pom.xml
+WAGON_SERVER_ID=wagoId
+
+# Maven 1 test properties
+
+MAVEN1_PROJECT_GROUP_NAME=Maven One Project
+MAVEN1_PROJECT_GROUP_ID=maven-one-project
+MAVEN1_PROJECT_GROUP_DESCRIPTION=This is a sample Maven One Project
+
+MAVEN1_MISSING_REPO_POM_URL=http://localhost:${continuum.port}/example-projects/maven-one-projects/missing-repository-element-project.xml
+MAVEN1_EXTENDED_POM_URL=http://localhost:${continuum.port}/example-projects/maven-one-projects/extend-element-project.xml
+MAVEN1_UNPARSEABLE_POM_URL=http://localhost:${continuum.port}/example-projects/maven-one-projects/unparseable-content-project.xml
+
+# Maven 2 test properties
+
+MAVEN2_SAME_LETTER_FLAT_POM_URL=http://localhost:${continuum.port}/example-projects/flat-example/flat-parent/pom.xml
+MAVEN2_SAME_LETTER_FLAT_PROJECT_GROUP_NAME=Flat Example
+MAVEN2_SAME_LETTER_FLAT_PROJECT_GROUP_ID=com.example.flat
+MAVEN2_SAME_LETTER_FLAT_PROJECT_GROUP_DESCRIPTION=
+MAVEN2_SAME_LETTER_FLAT_PROJECT_GROUP_SCM_ROOT_URL=scm:svn:${svn.base.url}/trunk/flat-example
+
+MAVEN2_NON_DEFAULT_PROJECT_GROUP_NAME=Maven Non-Default Project Group Name
+MAVEN2_NON_DEFAULT_PROJECT_GROUP_ID=org.apache.continuum.examples.maven2.nondefaultgroup
+MAVEN2_NON_DEFAULT_PROJECT_GROUP_DESCRIPTION=
+
+MAVEN2_MOVE_PROJECT_TARGET_PROJECT_GROUP_NAME=Maven Move Project Target Group Name
+MAVEN2_MOVE_PROJECT_TARGET_PROJECT_GROUP_ID=org.apache.continuum.examples.maven2.moveproject
+MAVEN2_MOVE_PROJECT_TARGET_PROJECT_GROUP_DESCRIPTION=
+
+# SCM element is missing from pom
+MAVEN2_NO_SCM_POM_URL=http://localhost:${continuum.port}/example-projects/maven-two-projects/missing-scm-element-pom.xml
+MAVEN2_MISS_CONNECTION_POM_URL=http://localhost:${continuum.port}/example-projects/maven-two-projects/missing-connection-element-pom.xml
+MAVEN2_MISS_PARENT_POM_URL=http://localhost:${continuum.port}/example-projects/maven-two-projects/missing-parent-pom.xml
+MAVEN2_MISS_SUBPRO_POM_URL=http://localhost:${continuum.port}/example-projects/maven-two-projects/missing-modules-pom.xml
+
+# Ant test properties
+
+ANT_PROJECT_GROUP_NAME=Ant Project Group
+ANT_PROJECT_GROUP_ID=com.example.ant
+ANT_PROJECT_GROUP_DESCRIPTION=Group for Ant test projects
+
+# Distributed build properties
+
+DISTRIBUTED_PROJECT_GROUP_NAME=Distributed Build Test Project Group
+DISTRIBUTED_PROJECT_GROUP_ID=org.apache.continuum.examples.distributed
+DISTRIBUTED_PROJECT_GROUP_DESCRIPTION=
+
+DISTRIBUTED_BUILD_ENV_NAME=Distributed Build Env
+DISTRIBUTED_BUILD_AGENT_GROUP_NAME=Distributed Build Agent Group
+DISTRIBUTED_DUPLICATE_BUILD_ENV=Distributed Duplicate Build Env
+
+# Distributed Release test properties
+
+DIST_RELEASE_PROJECT_GROUP_NAME=Distributed Release Test Project Group
+DIST_RELEASE_PROJECT_GROUP_ID=com.example.release
+DIST_RELEASE_PROJECT_TAGBASE=${svn.base.url}/tags
+DIST_RELEASE_PROJECT_TAG=simple-example-1.0
+DIST_RELEASE_PROJECT_VERSION=1.0
+DIST_RELEASE_PROJECT_DEVELOPMENT_VERSION=1.1-SNAPSHOT
+DIST_RELEASE_PROJECT_SCM_URL=scm:svn:${svn.base.url}/trunk/simple-example
+
+DIST_RELEASE_BUILD_ENV=RELEASE_BUILD_ENV
+DIST_RELEASE_BUILD_AGENT_GROUP=RELEASE_BUILDAGENT_GROUP
+DIST_RELEASE_NO_AGENT_MESSAGE=Unable to prepare release because build agent
+
+# Release test properties
+
+RELEASE_PROJECT_GROUP_NAME=Release Test Project Group
+RELEASE_PROJECT_GROUP_ID=com.example.release.local
+RELEASE_PROJECT_TAGBASE=${svn.base.url}/tags
+RELEASE_PROJECT_TAG=simple-example-10.0
+RELEASE_PROJECT_VERSION=10.0
+RELEASE_PROJECT_DEVELOPMENT_VERSION=10.1-SNAPSHOT
+RELEASE_PROJECT_SCM_URL=scm:svn:${svn.base.url}/trunk/simple-example
+
+# Report test properties
+
+REPORT_PROJECT_GROUP_NAME=Report Test Project Group
+REPORT_PROJECT_GROUP_ID=org.apache.continuum.examples.report
+REPORT_PROJECT_GROUP_DESCRIPTION=
+
+# Build definition tests
+
+BUILD_DEFINITION_PROJECT_GROUP_NAME=Build Definition Test Project Group
+BUILD_DEFINITION_PROJECT_GROUP_ID=org.apache.continuum.examples.builddefinition
+BUILD_DEFINITION_PROJECT_GROUP_DESCRIPTION=Test project group for the build definition project group tests
+
+BUILD_DEFINITION_POM_NAME=pom.xml
+BUILD_DEFINITION_GOALS=test
+BUILD_DEFINITION_ARGUMENTS=--batch-mode --non-recursive -P!dev
+BUILD_DEFINITION_DESCRIPTION=Maven Build Definition Description
+
+BUILD_DEFINITION_ANT_PROJECT_NAME=Build Definition Test Ant Project
+
+# Build queue tests
+
+BUILD_QUEUE_NAME=name_build_queue
+QUEUE_SCHEDULE_NAME=queue_schedule
+
+# Build result tests
+
+BUILD_RESULT_PROJECT_GROUP_NAME=Build Result Test Project Group
+BUILD_RESULT_PROJECT_GROUP_ID=org.apache.continuum.examples.buildresult
+BUILD_RESULT_PROJECT_GROUP_DESCRIPTION=Test project group for the build result project group tests
+
+#####
+
+DEFAULT_PROJ_GRP_NAME=Default Project Group
+DEFAULT_PROJ_GRP_ID=default
+DEFAULT_PROJ_GRP_DESCRIPTION=Contains all projects that do not have a group of their own
+
+########################
+# mavenTwoProject group 
+########################
+
+# Properties for testAddMavenTwoProject
+M2_POM_URL=http://localhost:${continuum.port}/example-projects/continuum-build-queue-test-data/pom.xml
+M2_POM_USERNAME=
+M2_POM_PASSWORD=
+
+# Properties for testDeleteMavenTwoProject
+M2_DELETE_POM_URL=http://localhost:${continuum.port}/example-projects/simple-example/pom.xml
+M2_DELETE_PROJ_GRP_NAME=Continuum Simple Example Project
+M2_DELETE_PROJ_GRP_ID=org.apache.continuum.examples.simple
+
+########################
+# shellProject group 
+########################
+
+SHELL_NAME=Shell Project
+SHELL_DESCRIPTION=This is a sample Shell Project used for testing
+SHELL_VERSION=1.0.0-SNAPSHOT
+SHELL_TAG=
+SHELL_SCM_URL=http://localhost:${continuum.port}/example-projects/shell/
+SHELL_SCM_USERNAME=
+SHELL_SCM_PASSWORD=
+
+SHELL_PROJECT_GROUP_NAME=Shell Test Project Group
+SHELL_PROJECT_GROUP_ID=shell.group
+SHELL_PROJECT_GROUP_DESCRIPTION=She sells seashells by the seashore
+
+########################
+# projectGroup group 
+########################
+TEST_PROJ_GRP_NAME=Test Project Group Name
+TEST_PROJ_GRP_ID=Test Project Group Id
+TEST_PROJ_GRP_DESCRIPTION=Test Project Group Description
+
+# Test properties for testDeleteProjectGroup
+TEST_DELETE_GRP_NAME=Add then Delete Project Group
+TEST_DELETE_GRP_ID=test.delete.project.group
+TEST_DELETE_GRP_DESCRIPTION=Test Delete Project Group Description
+
+# Test properties for testProjectGroupMembers
+TEST_PROJ_GRP_NAME_ONE=Group
+TEST_PROJ_GRP_ID_ONE=Group Id
+TEST_PROJ_GRP_DESCRIPTION_ONE=First project group for members test
+TEST_PROJ_GRP_NAME_TWO=Group My
+TEST_PROJ_GRP_ID_TWO=Group Id My
+TEST_PROJ_GRP_DESCRIPTION_TWO=Second project group for members test
+TEST_PROJ_GRP_NAME_THREE = My Group
+TEST_PROJ_GRP_ID_THREE=My Group Id
+TEST_PROJ_GRP_DESCRIPTION_THREE=Third project group for members test
+
+########################
+# purge group 
+########################
+PURGE_REPOSITORY_DESCRIPTION=repository_description
+PURGE_REPOSITORY_DAYS=100
+PURGE_REPOSITORY_RETETION=3
+PURGE_DIRECTORY_DESCRIPTION=directory_description
+PURGE_DIRECTORY_DAYS=90
+PURGE_DIRECTORY_RETETION=4
+
+########################
+# local repository group 
+########################
+LOCAL_REPOSITORY_NAME=repository_name
+LOCAL_REPOSITORY_LOCATION=/usr/m2/repository
+
+########################
+# schedules group 
+########################
+SCHEDULE_NAME=schedule_name
+
+########################
+# installations group 
+########################
+# Correct location for JDK
+INSTALL_TOOL_JDK_NAME=JDK6
+INSTALL_TOOL_JDK_PATH=${java.home}
+# Correct location for maven 2
+INSTALL_TOOL_MAVEN_NAME=M9_HOME
+INSTALL_TOOL_MAVEN_PATH=${maven.home}
+# Not neccesary correct location
+INSTALL_VAR_NAME=JDK5
+INSTALL_VAR_VARIABLE_NAME=JAVA5_HOME
+INSTALL_VAR_PATH=/usr/lib/jvm/java-5-sun-1.5.0.12
+
+########################
+# buildEnvironment group 
+########################
+BUILD_ENV_NAME=APPLICATION_JDK4
+
+########################
+# buildTemplate group 
+########################
+TEMPLATE_NAME=PROJECT_MAVEN_TEMPLATE
+TEMPLATE_BUILD_POM_NAME=pom.xml
+TEMPLATE_BUILD_GOALS=test
+TEMPLATE_BUILD_ARGUMENTS=--batch-mode --non-recursive
+TEMPLATE_BUILD_DESCRIPTION=Template Maven Test
+
+########################
+# userRoles group
+########################
+# General
+USERROLE_EMAIL=user@localhost.localdomain
+USERROLE_PASSWORD=pass123
+NEW_USERROLE_PASSWORD=pass12345
+# Guest Role
+GUEST_USERNAME=guest1
+GUEST_FULLNAME=Guest
+# Registered User Role
+REGISTERED_USERNAME=reg_user
+REGISTERED_FULLNAME=Registered User
+# System Administrator
+SYSAD_USERNAME=sys_admin
+SYSAD_FULLNAME=System Administrator
+# User Administrator
+USERADMIN_USERNAME=user_admin
+USERADMIN_FULLNAME=User Administrator
+# Continuum Group Project Administrator
+GROUPPROJECTADMIN_USERNAME=groupprojectadmin
+GROUPPROJECTADMIN_FULLNAME=Continuum Group Project Administrator
+# Continuum Group Project Developer
+GROUPPROJECTDEVELOPER_USERNAME=groupprojectdev
+GROUPPROJECTDEVELOPER_FULLNAME=Continuum Group Project Developer
+# Continuum Group Project User
+GROUPPROJECTUSER_USERNAME=groupprojectuser
+GROUPPROJECTUSER_FULLNAME=Continuum Group Project User
+# Continuum Manage Build Environment
+MANAGEBUILDENVIRONMENT_USERNAME=managebuildenv
+MANAGEBUILDENVIRONMENT_FULLNAME=Continuum Manage Build Environments
+# Continuum Manage Build Templates
+MANAGEBUILDTEMPLATES_USERNAME=managebuildtemp
+MANAGEBUILDTEMPLATES_FULLNAME=Continuum Manage Build Templates
+# Continuum Manage Installations
+MANAGEINSTALLATIONS_USERNAME=manageinstallations
+MANAGEINSTALLATIONS_FULLNAME=Continuum Manage Installations
+# Continuum Manage Local Repositories
+MANAGELOCALREPOS_USERNAME=managelocalrepo
+MANAGELOCALREPOS_FULLNAME=Continuum Manage Local Repositories
+# Continuum Manage Purging
+MANAGEPURGING_USERNAME=managepurging
+MANAGEPURGING_FULLNAME=Continuum Manage Purging
+# Continuum Manage Queues
+MANAGEQUEUES_USERNAME=managequeues
+MANAGEQUEUES_FULLNAME=Continuum Manage Queues
+# Continuum Manage Scheduling
+MANAGESCHEDULING_USERNAME=manageschedule
+MANAGESCHEDULING_FULLNAME=Continuum Manage Scheduling
+# Project Administrator
+PROJECTADMINISTRATOR_DEFAULTPROJECTGROUP_USERNAME=projectadmin
+PROJECTADMINISTRATOR_DEFAULTPROJECTGROUP_FULLNAME=Project Administrator - Default Project Group
+# Project Developer
+PROJECTDEVELOPER_DEFAULTPROJECTGROUP_USERNAME=projectdev
+PROJECTDEVELOPER_DEFAULTPROJECTGROUP_FULLNAME=Project Developer - Default Project Group
+# Project User
+PROJECTUSER_DEFAULTPROJECTGROUP_USERNAME=projectuser
+PROJECTUSER_DEFAULTPROJECTGROUP_FULLNAME=Project User - Default Project Group
+
+########################
+# buildAgents group 
+########################
+BUILD_AGENT_DESCRIPTION=Agent_description
+BUILD_AGENT_GROUPNAME=agent_groupname
+
+########################
+# appearance
+########################
+APPEARANCE_SAVE_FOOTER_URL=${baseUrl}/admin/saveFooter.action
diff --git a/continuum-webapp-test/src/test/selenium-ide/add_and_build_project.html b/continuum-webapp-test/src/test/selenium-ide/add_and_build_project.html
index 01a5cf6..77be105 100644
--- a/continuum-webapp-test/src/test/selenium-ide/add_and_build_project.html
+++ b/continuum-webapp-test/src/test/selenium-ide/add_and_build_project.html
@@ -3,6 +3,7 @@
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head profile="http://selenium-ide.openqa.org/profiles/test-case">
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
 <title>add_and_build_project.html</title>
 </head>
 <body>
@@ -144,7 +145,7 @@
 </tr>
 <tr>
 	<td>clickAndWait</td>
-	<td>removeProjectGroup_0</td>
+	<td>removeProjectGroup_</td>
 	<td></td>
 </tr>
 <tr>
diff --git a/continuum-webapp-test/src/test/selenium-ide/add_and_delete_local_repo.html b/continuum-webapp-test/src/test/selenium-ide/add_and_delete_local_repo.html
index faf18e3..10c3a7d 100644
--- a/continuum-webapp-test/src/test/selenium-ide/add_and_delete_local_repo.html
+++ b/continuum-webapp-test/src/test/selenium-ide/add_and_delete_local_repo.html
@@ -48,7 +48,7 @@
 </tr>
 <tr>
 	<td>clickAndWait</td>
-	<td>saveRepository_0</td>
+	<td>saveRepository_</td>
 	<td></td>
 </tr>
 <tr>
@@ -63,7 +63,7 @@
 </tr>
 <tr>
 	<td>clickAndWait</td>
-	<td>removeRepository_0</td>
+	<td>removeRepository_</td>
 	<td></td>
 </tr>
 <tr>
diff --git a/continuum-webapp-test/src/test/selenium-ide/add_and_delete_project_group.html b/continuum-webapp-test/src/test/selenium-ide/add_and_delete_project_group.html
index d734d63..10c9abe 100644
--- a/continuum-webapp-test/src/test/selenium-ide/add_and_delete_project_group.html
+++ b/continuum-webapp-test/src/test/selenium-ide/add_and_delete_project_group.html
@@ -53,7 +53,7 @@
 </tr>
 <tr>
 	<td>clickAndWait</td>
-	<td>//table[@id='ec_table']/tbody/tr[2]/td[6]/a/img</td>
+	<td>//table[@id='ec_table']/tbody/tr[2]/td[5]/a/img</td>
 	<td></td>
 </tr>
 <tr>
diff --git a/continuum-webapp-test/src/test/selenium-ide/add_and_edit_project_level_build_definition.html b/continuum-webapp-test/src/test/selenium-ide/add_and_edit_project_level_build_definition.html
new file mode 100644
index 0000000..212dfa3
--- /dev/null
+++ b/continuum-webapp-test/src/test/selenium-ide/add_and_edit_project_level_build_definition.html
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title>add_and_edit_project_level_build_definition</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">add_and_edit_project_level_build_definition</td></tr>
+</thead><tbody>
+<tr>
+	<td>open</td>
+	<td>/continuum/groupSummary.action</td>
+	<td></td>
+</tr>
+<!--Add a project-->
+<tr>
+	<td>clickAndWait</td>
+	<td>link=Maven Project</td>
+	<td></td>
+</tr>
+<tr>
+	<td>type</td>
+	<td>addMavenTwoProject_m2PomUrl</td>
+	<td>http://svn.apache.org/repos/asf/continuum/sandbox/simple-example/pom.xml</td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>//input[@id='addMavenTwoProject_']</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForTextNotPresent</td>
+	<td>in progress</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForTextPresent</td>
+	<td>Project Group Information</td>
+	<td></td>
+</tr>
+<!--Select the project from the group-->
+<tr>
+	<td>clickAndWait</td>
+	<td>link=Continuum Simple Example Project</td>
+	<td></td>
+</tr>
+<!--Add a build definition-->
+<tr>
+	<td>clickAndWait</td>
+	<td>buildDefinition_0</td>
+	<td></td>
+</tr>
+<tr>
+	<td>type</td>
+	<td>saveBuildDefinition_goals</td>
+	<td>clean install</td>
+</tr>
+<tr>
+	<td>type</td>
+	<td>saveBuildDefinition_description</td>
+	<td>Project level build definition for testing</td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>saveBuildDefinition_</td>
+	<td></td>
+</tr>
+<!--Now try to edit the build definition-->
+<tr>
+	<td>clickAndWait</td>
+	<td>//table[@id='ec_table']/tbody/tr[2]/td[12]/a/img</td>
+	<td></td>
+</tr>
+<tr>
+	<td>type</td>
+	<td>saveBuildDefinition_description</td>
+	<td>Project level build definition for testing (edited)</td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>saveBuildDefinition_</td>
+	<td></td>
+</tr>
+<!--error occurs at this point-->
+<tr>
+	<td>assertTextPresent</td>
+	<td>TBD</td>
+	<td></td>
+</tr>
+<!--Delete the project group-->
+<tr>
+	<td>clickAndWait</td>
+	<td>link=Show Project Groups</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>//img[@alt='Delete Group']</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>removeProjectGroup_</td>
+	<td></td>
+</tr>
+<!---->
+
+</tbody></table>
+</body>
+</html>
diff --git a/continuum-webapp-test/src/test/selenium-ide/check_menu_options.html b/continuum-webapp-test/src/test/selenium-ide/check_menu_options.html
index c4c174c..0d0fae4 100644
--- a/continuum-webapp-test/src/test/selenium-ide/check_menu_options.html
+++ b/continuum-webapp-test/src/test/selenium-ide/check_menu_options.html
@@ -38,12 +38,12 @@
 </tr>
 <tr>
 	<td>clickAndWait</td>
-	<td>link=Maven 2.0.x Project</td>
+	<td>link=Maven Project</td>
 	<td></td>
 </tr>
 <tr>
 	<td>assertTextPresent</td>
-	<td>Add Maven 2</td>
+	<td>Add Maven</td>
 	<td></td>
 </tr>
 <tr>
@@ -153,7 +153,7 @@
 </tr>
 <tr>
 	<td>clickAndWait</td>
-	<td>link=Build Definitions Templates</td>
+	<td>link=Build Definition Templates</td>
 	<td></td>
 </tr>
 <tr>
diff --git a/continuum-webapp-test/src/test/selenium-ide/continuum_failing_test_suite.html b/continuum-webapp-test/src/test/selenium-ide/continuum_failing_test_suite.html
index 260c812..2450b62 100644
--- a/continuum-webapp-test/src/test/selenium-ide/continuum_failing_test_suite.html
+++ b/continuum-webapp-test/src/test/selenium-ide/continuum_failing_test_suite.html
@@ -8,7 +8,9 @@
 <body>
 <table id="suiteTable" cellpadding="1" cellspacing="1" border="1" class="selenium"><tbody>
 <tr><td><b>Test Suite</b></td></tr>
-<tr><td><a href="test_build_definition_templates.html">test_build_definition_templates.html</a></td></tr>
+<tr><td><a href="add_and_edit_project_level_build_definition.html">add_and_edit_project_level_build_definition.html</a></td></tr>
+<tr><td><a href="test_project_group_homepage_url.html">test_project_group_homepage_url</a></td></tr>
+<tr><td><a href="test_shell_project.html">test_shell_project</a></td></tr>
 </tbody></table>
 </body>
 </html>
diff --git a/continuum-webapp-test/src/test/selenium-ide/continuum_online_test_suite.html b/continuum-webapp-test/src/test/selenium-ide/continuum_online_test_suite.html
index b376c6d..f3db0d7 100644
--- a/continuum-webapp-test/src/test/selenium-ide/continuum_online_test_suite.html
+++ b/continuum-webapp-test/src/test/selenium-ide/continuum_online_test_suite.html
@@ -9,6 +9,8 @@
 <table id="suiteTable" cellpadding="1" cellspacing="1" border="1" class="selenium"><tbody>
 <tr><td><b>Test Suite</b></td></tr>
 <tr><td><a href="add_and_build_project.html">add_and_build_project.html</a></td></tr>
+<tr><td><a href="test_build_definition_templates.html">test_build_definition_templates.html</a></td></tr>
+<tr><td><a href="test_release_plugin_configuration.html">test_release_plugin_configuration.html</a></td></tr>
 </tbody></table>
 </body>
 </html>
diff --git a/continuum-webapp-test/src/test/selenium-ide/create_admin_user_and_general_configuration.html b/continuum-webapp-test/src/test/selenium-ide/create_admin_user_and_general_configuration.html
index 1fa81ec..214510e 100644
--- a/continuum-webapp-test/src/test/selenium-ide/create_admin_user_and_general_configuration.html
+++ b/continuum-webapp-test/src/test/selenium-ide/create_admin_user_and_general_configuration.html
@@ -67,7 +67,7 @@
 </tr>
 <tr>
 	<td>clickAndWait</td>
-	<td>configuration_</td>
+	<td>configuration_null</td>
 	<td></td>
 </tr>
 
diff --git a/continuum-webapp-test/src/test/selenium-ide/edit_project_group.html b/continuum-webapp-test/src/test/selenium-ide/edit_project_group.html
index 8b6d1d8..d903394 100644
--- a/continuum-webapp-test/src/test/selenium-ide/edit_project_group.html
+++ b/continuum-webapp-test/src/test/selenium-ide/edit_project_group.html
@@ -37,7 +37,7 @@
 </tr>
 <tr>
 	<td>clickAndWait</td>
-	<td>saveProjectGroup_</td>
+	<td>saveProjectGroup_null</td>
 	<td></td>
 </tr>
 <tr>
diff --git a/continuum-webapp-test/src/test/selenium-ide/test_build_definition_templates.html b/continuum-webapp-test/src/test/selenium-ide/test_build_definition_templates.html
index d600b56..d44d8a3 100644
--- a/continuum-webapp-test/src/test/selenium-ide/test_build_definition_templates.html
+++ b/continuum-webapp-test/src/test/selenium-ide/test_build_definition_templates.html
@@ -3,6 +3,7 @@
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head profile="http://selenium-ide.openqa.org/profiles/test-case">
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
 <title>test_build_definition_templates</title>
 </head>
 <body>
@@ -17,7 +18,7 @@
 </tr>
 <tr>
 	<td>clickAndWait</td>
-	<td>link=Build Definitions Templates</td>
+	<td>link=Build Definition Templates</td>
 	<td></td>
 </tr>
 <!--Add a build definition-->
@@ -39,12 +40,12 @@
 <tr>
 	<td>type</td>
 	<td>saveBuildDefinitionAsTemplate_buildDefinition_description</td>
-	<td>Maven 2 package only</td>
+	<td>Maven package only</td>
 </tr>
 <!--Add another build definition-->
 <tr>
 	<td>clickAndWait</td>
-	<td>saveBuildDefinitionAsTemplate_0</td>
+	<td>saveBuildDefinitionAsTemplate_</td>
 	<td></td>
 </tr>
 <tr>
@@ -65,11 +66,11 @@
 <tr>
 	<td>type</td>
 	<td>saveBuildDefinitionAsTemplate_buildDefinition_description</td>
-	<td>Maven 2 site only</td>
+	<td>Maven site only</td>
 </tr>
 <tr>
 	<td>clickAndWait</td>
-	<td>saveBuildDefinitionAsTemplate_0</td>
+	<td>saveBuildDefinitionAsTemplate_</td>
 	<td></td>
 </tr>
 <!--Add a new template and associate the two build definitions-->
@@ -86,7 +87,7 @@
 <tr>
 	<td>addSelection</td>
 	<td>saveBuildDefinitionTemplate_buildDefinitionIds</td>
-	<td>label=Maven 2 package only</td>
+	<td>label=Maven package only</td>
 </tr>
 <tr>
 	<td>click</td>
@@ -96,7 +97,7 @@
 <tr>
 	<td>addSelection</td>
 	<td>saveBuildDefinitionTemplate_buildDefinitionIds</td>
-	<td>label=Maven 2 site only</td>
+	<td>label=Maven site only</td>
 </tr>
 <tr>
 	<td>click</td>
@@ -105,7 +106,7 @@
 </tr>
 <tr>
 	<td>clickAndWait</td>
-	<td>saveBuildDefinitionTemplate_0</td>
+	<td>saveBuildDefinitionTemplate_</td>
 	<td></td>
 </tr>
 <!--Add a new project group-->
@@ -136,7 +137,7 @@
 </tr>
 <tr>
 	<td>clickAndWait</td>
-	<td>addProjectGroup_0</td>
+	<td>addProjectGroup_</td>
 	<td></td>
 </tr>
 <!--Open the new project group and add a project using the template-->
@@ -162,7 +163,7 @@
 </tr>
 <tr>
 	<td>clickAndWait</td>
-	<td>addMavenTwoProject_0</td>
+	<td>//input[@id='addMavenTwoProject_']</td>
 	<td></td>
 </tr>
 <!--Verify that both build definitions from the template were used-->
@@ -183,12 +184,48 @@
 </tr>
 <tr>
 	<td>assertTextPresent</td>
-	<td>Maven 2 package only</td>
+	<td>Maven package only</td>
 	<td></td>
 </tr>
 <tr>
 	<td>assertTextPresent</td>
-	<td>Maven 2 site only</td>
+	<td>Maven site only</td>
+	<td></td>
+</tr>
+<!--Remove the project group, template, and build defs-->
+<tr>
+	<td>clickAndWait</td>
+	<td>link=Project Group Summary</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>remove</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>removeProjectGroup_</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>link=Build Definitions Templates</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>//img[@alt='Delete']</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>//img[@alt='Delete']</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>//img[@alt='Delete']</td>
 	<td></td>
 </tr>
 
diff --git a/continuum-webapp-test/src/test/selenium-ide/test_project_group_homepage_url.html b/continuum-webapp-test/src/test/selenium-ide/test_project_group_homepage_url.html
new file mode 100644
index 0000000..16f31dc
--- /dev/null
+++ b/continuum-webapp-test/src/test/selenium-ide/test_project_group_homepage_url.html
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title>test_project_group_homepage_url</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">test_project_group_homepage_url</td></tr>
+</thead><tbody>
+<!--assumptions:  general config complete, admin user is logged in-->
+<tr>
+	<td>open</td>
+	<td>/groupSummary.action</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>link=Show Project Groups</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>link=Default Project Group</td>
+	<td></td>
+</tr>
+<!--Add a homepage url to the Default project group-->
+<tr>
+	<td>clickAndWait</td>
+	<td>edit</td>
+	<td></td>
+</tr>
+<tr>
+	<td>type</td>
+	<td>saveProjectGroup_url</td>
+	<td>http://example.com</td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>saveProjectGroup_null</td>
+	<td></td>
+</tr>
+<!--check that the url is displayed after we save the form-->
+<tr>
+	<td>assertTextPresent</td>
+	<td>http://example.com</td>
+	<td></td>
+</tr>
+<!--Now view the project group again-->
+<tr>
+	<td>clickAndWait</td>
+	<td>link=Show Project Groups</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>link=Default Project Group</td>
+	<td></td>
+</tr>
+<!--The url should be displayed, but it isn't-->
+<tr>
+	<td>assertTextPresent</td>
+	<td>http://example.com</td>
+	<td></td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
diff --git a/continuum-webapp-test/src/test/selenium-ide/test_release_plugin_configuration.html b/continuum-webapp-test/src/test/selenium-ide/test_release_plugin_configuration.html
new file mode 100644
index 0000000..d18b5ec
--- /dev/null
+++ b/continuum-webapp-test/src/test/selenium-ide/test_release_plugin_configuration.html
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:9090/" />
+<title>test_release_plugin_configuration</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">test_release_plugin_configuration</td></tr>
+</thead><tbody>
+<tr>
+	<td>open</td>
+	<td>/continuum/groupSummary.action</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>link=Maven Project</td>
+	<td></td>
+</tr>
+<tr>
+	<td>type</td>
+	<td>addMavenTwoProject_m2PomUrl</td>
+	<td>http://svn.apache.org/repos/asf/continuum/sandbox/examples/mm-example/pom.xml</td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>//input[@id='addMavenTwoProject_']</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForTextNotPresent</td>
+	<td>in progress</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForTextPresent</td>
+	<td>Project Group Information</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>build</td>
+	<td></td>
+</tr>
+<!--Wait for build success-->
+<tr>
+	<td>assertTextPresent</td>
+	<td>Success : 2</td>
+	<td></td>
+</tr>
+<!--Begin the release process-->
+<tr>
+	<td>clickAndWait</td>
+	<td>release</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>goal</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>releaseProject_0</td>
+	<td></td>
+</tr>
+<!--Verify that the SCM Comment Prefix was pre-populated with the value from the pom-->
+<tr>
+	<td>assertTextPresent</td>
+	<td>MME-455</td>
+	<td></td>
+</tr>
+<!--Verify that it does not prompt for a version for the sub-module, since autoVersionSubmodules is true-->
+<tr>
+	<td>assertTextNotPresent</td>
+	<td>Multi Module Example :: Core</td>
+	<td></td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
diff --git a/continuum-webapp-test/src/test/selenium-ide/test_shell_project.html b/continuum-webapp-test/src/test/selenium-ide/test_shell_project.html
new file mode 100644
index 0000000..00bc462
--- /dev/null
+++ b/continuum-webapp-test/src/test/selenium-ide/test_shell_project.html
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
+<title>test_shell_project</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">test_shell_project</td></tr>
+</thead><tbody>
+<tr>
+	<td>open</td>
+	<td>/continuum/groupSummary.action</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>link=Show Project Groups</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>addProjectGroup</td>
+	<td></td>
+</tr>
+<tr>
+	<td>type</td>
+	<td>addProjectGroup_name</td>
+	<td>Shell Test</td>
+</tr>
+<tr>
+	<td>type</td>
+	<td>addProjectGroup_groupId</td>
+	<td>shell-test</td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>addProjectGroup_</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>link=Shell Test</td>
+	<td></td>
+</tr>
+<tr>
+	<td>select</td>
+	<td>preferredExecutor</td>
+	<td>label=Add Shell Project</td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>//input[@value='Add']</td>
+	<td></td>
+</tr>
+<tr>
+	<td>type</td>
+	<td>addProject_projectName</td>
+	<td>Good Shell Project</td>
+</tr>
+<tr>
+	<td>type</td>
+	<td>addProject_projectVersion</td>
+	<td>1.0</td>
+</tr>
+<tr>
+	<td>type</td>
+	<td>addProject_projectScmUrl</td>
+	<td>https://svn.apache.org/repos/asf/continuum/sandbox/examples/shell</td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>addProject_</td>
+	<td></td>
+</tr>
+<!--Either the project was not added, OR you get-->
+<!--Error - "Project name already exist" (however, project is added)-->
+<tr>
+	<td>clickAndWait</td>
+	<td>link=Show Project Groups</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>link=Shell Test</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>//img[@alt='Build Now']</td>
+	<td></td>
+</tr>
+<!--Error - java.lang.NullPointerException-->
+<tr>
+	<td>clickAndWait</td>
+	<td>link=Show Project Groups</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>link=Shell Test</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>remove</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>removeProjectGroup_</td>
+	<td></td>
+</tr>
+<!--Error - java.lang.NullPointerException on first delete attempt (second seems to work) -->
+<tr>
+	<td>assertTextNotPresent</td>
+	<td>Shell Test</td>
+	<td></td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
diff --git a/continuum-webapp-test/src/test/testng/config/testng-multienvironment.xml b/continuum-webapp-test/src/test/testng/config/testng-multienvironment.xml
new file mode 100644
index 0000000..a31a38d
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/config/testng-multienvironment.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
+
+<suite name="ContinuumTestMultiEnvironment" verbose="1" parallel="tests" thread-count="2">
+  <listeners>
+    <listener class-name="org.apache.continuum.web.test.listener.CaptureScreenShotsListener"/>
+  </listeners>
+  <test name="safari4Windows">
+    <parameter name="browser" value="Safari 4 on Windows"/>
+    <groups>
+      <run>
+        <include name="login"/>
+      </run>
+    </groups>
+    <packages>
+      <package name="org.apache.continuum.web.test"/>
+    </packages>
+  </test>
+  <test name="firefox3Linux">
+    <parameter name="browser" value="Firefox 3 on Linux"/>
+    <groups>
+      <run>
+        <include name="login"/>
+      </run>
+    </groups>
+    <packages>
+      <package name="org.apache.continuum.web.test"/>
+    </packages>
+  </test>
+</suite>
diff --git a/continuum-webapp-test/src/test/testng/config/testng.xml b/continuum-webapp-test/src/test/testng/config/testng.xml
new file mode 100644
index 0000000..b884f7d
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/config/testng.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
+
+<suite name="ContinuumTest" verbose="1">
+  <listeners>
+    <listener class-name="org.apache.continuum.web.test.listener.CaptureScreenShotsListener"/>
+  </listeners>
+  <test name="BasicTest" enabled="true">
+    <!--
+       Groups are divided into the unit tests. The order will be described
+       in the annotations of each type of test.
+     -->
+    <groups>
+      <run>
+        <include name="about"/>
+      </run>
+    </groups>
+    <packages>
+      <package name="org.apache.continuum.web.test"/>
+    </packages>
+  </test>
+  <test name="AdminTest" enabled="true">
+    <groups>
+      <run>
+        <include name="login"/>
+        <include name="projectGroup"/>
+        <include name="mavenTwoProject"/>
+        <include name="mavenOneProject"/>
+        <include name="antProject"/>
+        <include name="shellProject"/>
+        <include name="report"/>
+        <include name="agent"/>
+        <include name="release"/>
+        <include name="distributedRelease"/>
+        <include name="buildDefinition"/>
+        <include name="notifier"/>
+        <include name="myAccount"/>
+        <include name="schedule"/>
+        <include name="queue"/>
+        <include name="purge"/>
+        <include name="repository"/>
+        <include name="configuration"/>
+        <include name="installation"/>
+        <include name="buildEnvironment"/>
+        <include name="buildDefinitionTemplate"/>
+        <include name="userroles"/>
+        <include name="appearance"/>
+        <include name="csrf"/>
+        <include name="distributed"/>
+        <include name="buildResult"/>
+      </run>
+    </groups>
+    <packages>
+      <package name="org.apache.continuum.web.test"/>
+    </packages>
+  </test>
+</suite>
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/AboutTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/AboutTest.java
new file mode 100644
index 0000000..d503554
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/AboutTest.java
@@ -0,0 +1,40 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 org.apache.continuum.web.test.parent.AbstractContinuumTest;
+import org.testng.annotations.Test;
+
+/**
+ * Based on AboutTest of Wendy Smoak test.
+ *
+ * @author José Morales Martínez
+ * @version $Id$
+ */
+@Test( groups = {"about"}, alwaysRun = true )
+public class AboutTest
+    extends AbstractContinuumTest
+{
+    public void displayAboutPage()
+    {
+        goToAboutPage();
+    }
+
+}
\ No newline at end of file
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/AbstractReleaseTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/AbstractReleaseTest.java
new file mode 100644
index 0000000..2c6b5f1
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/AbstractReleaseTest.java
@@ -0,0 +1,147 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 org.apache.continuum.web.test.parent.AbstractAdminTest;
+
+import java.util.Arrays;
+
+public abstract class AbstractReleaseTest
+    extends AbstractAdminTest
+{
+    protected static final String RELEASE_BUTTON_TEXT = "Release";
+
+    protected static final String PROVIDE_RELEASE_PARAMETERS_TEXT = "Provide Release Parameters";
+
+    protected void releasePrepareProject( String username, String password, String tagBase, String tag,
+                                          String releaseVersion, String developmentVersion, String buildEnv )
+    {
+        goToReleasePreparePage();
+        setFieldValue( "scmUsername", username );
+        setFieldValue( "scmPassword", password );
+        setFieldValue( "scmTag", tag );
+        setFieldValue( "scmTagBase", tagBase );
+        setFieldValue( "prepareGoals", "clean" );
+        selectValue( "profileId", buildEnv );
+        setFieldValue( "relVersions", releaseVersion );
+        setFieldValue( "devVersions", developmentVersion );
+        submit();
+
+        waitForRelease();
+    }
+
+    protected void releasePerformProjectWithProvideParameters( String username, String password, String tagBase,
+                                                               String tag, String scmUrl, String buildEnv )
+    {
+        goToReleasePerformProvideParametersPage();
+        setFieldValue( "scmUrl", scmUrl );
+        setFieldValue( "scmUsername", username );
+        setFieldValue( "scmPassword", password );
+        setFieldValue( "scmTag", tag );
+        setFieldValue( "scmTagBase", tagBase );
+        setFieldValue( "goals", "clean deploy" );
+        selectValue( "profileId", buildEnv );
+        submit();
+
+        waitForRelease();
+
+        assertReleasePhaseError();
+    }
+
+    private void goToReleasePreparePage()
+    {
+        clickLinkWithLocator( "goal", false );
+        submit();
+        assertReleasePreparePage();
+    }
+
+    private void goToReleasePerformProvideParametersPage()
+    {
+        selectValue( "preparedReleaseId", PROVIDE_RELEASE_PARAMETERS_TEXT );
+        selectPerformAndSubmit();
+        assertReleasePerformProvideParametersPage();
+    }
+
+    protected void selectPerformAndSubmit()
+    {
+        clickLinkWithLocator( "//input[@name='goal' and @value='perform']", false );
+        submit();
+    }
+
+    void assertReleasePreparePage()
+    {
+        assertPage( "Continuum - Release Project" );
+        assertTextPresent( "Prepare Project for Release" );
+        assertTextPresent( "Release Prepare Parameters" );
+        assertTextPresent( "SCM Username" );
+        assertTextPresent( "SCM Password" );
+        assertTextPresent( "SCM Tag" );
+        assertTextPresent( "SCM Tag Base" );
+        assertTextPresent( "SCM Comment Prefix" );
+        assertTextPresent( "Preparation Goals" );
+        assertTextPresent( "Arguments" );
+        assertTextPresent( "Build Environment" );
+        assertTextPresent( "Release Version" );
+        assertTextPresent( "Next Development Version" );
+        assertButtonWithValuePresent( "Submit" );
+    }
+
+    void assertReleasePerformProvideParametersPage()
+    {
+        assertPage( "Continuum - Perform Project Release" );
+        assertTextPresent( "Perform Project Release" );
+        assertTextPresent( "Release Perform Parameters" );
+        assertTextPresent( "SCM Connection URL" );
+        assertTextPresent( "SCM Username" );
+        assertTextPresent( "SCM Password" );
+        assertTextPresent( "SCM Tag" );
+        assertTextPresent( "SCM Tag Base" );
+        assertTextPresent( "Perform Goals" );
+        assertTextPresent( "Arguments" );
+        assertTextPresent( "Build Environment" );
+        assertButtonWithValuePresent( "Submit" );
+    }
+
+    void assertReleaseError()
+    {
+        assertTextPresent( "Release Error" );
+    }
+
+    protected void assertReleasePhaseError()
+    {
+        assertButtonWithValuePresent( "Rollback changes" );
+        assertImgWithAlt( "Error" );
+    }
+
+    protected void assertReleasePhaseSuccess()
+    {
+        assertButtonWithValuePresent( "Rollback changes" );
+        assertElementNotPresent( "//img[@alt='Error']" );
+    }
+
+    protected void waitForRelease()
+    {
+        String doneButtonLocator = "//input[@id='releaseCleanup_0']";
+        String errorTextLocator = "//h3[text()='Release Error']";
+
+        // condition for release is complete; "Done" button or "Release Error" in page is present
+        waitForOneOfElementsPresent( Arrays.asList( doneButtonLocator, errorTextLocator ), true );
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/AntProjectTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/AntProjectTest.java
new file mode 100644
index 0000000..af1d709
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/AntProjectTest.java
@@ -0,0 +1,129 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 org.apache.continuum.web.test.parent.AbstractAdminTest;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * Based on AddAntProjectTestCase of Emmanuel Venisse.
+ *
+ * @author José Morales Martínez
+ * @version $Id$
+ */
+@Test( groups = {"antProject"} )
+public class AntProjectTest
+    extends AbstractAdminTest
+{
+    private String projectName;
+
+    private String projectDescription;
+
+    private String projectVersion;
+
+    private String projectTag;
+
+    private String scmUrl;
+
+    private String scmUsername;
+
+    private String scmPassword;
+
+    private String projectGroupName;
+
+    private String projectGroupId;
+
+    private String projectGroupDescription;
+
+    @BeforeMethod
+    protected void setUp()
+        throws Exception
+    {
+        projectName = getProperty( "ANT_NAME" );
+        projectDescription = getProperty( "ANT_DESCRIPTION" );
+        projectVersion = getProperty( "ANT_VERSION" );
+        projectTag = getProperty( "ANT_TAG" );
+        scmUrl = getProperty( "ANT_SCM_URL" );
+        scmUsername = getProperty( "ANT_SCM_USERNAME" );
+        scmPassword = getProperty( "ANT_SCM_PASSWORD" );
+
+        projectGroupName = getProperty( "ANT_PROJECT_GROUP_NAME" );
+        projectGroupId = getProperty( "ANT_PROJECT_GROUP_ID" );
+        projectGroupDescription = getProperty( "ANT_PROJECT_GROUP_DESCRIPTION" );
+
+        // create project group, if it doesn't exist
+        addProjectGroup( projectGroupName, projectGroupId, projectGroupDescription, true, false );
+    }
+
+    @AfterMethod
+    public void tearDown()
+        throws Throwable
+    {
+        removeProjectGroup( projectGroupName, false );
+    }
+
+    public void testAddAntProject()
+        throws Exception
+    {
+        goToAddAntProjectPage();
+        addProject( projectName, projectDescription, projectVersion, scmUrl, scmUsername, scmPassword, projectTag,
+                    projectGroupName, true, "ant" );
+        assertProjectGroupSummaryPage( projectGroupName, projectGroupId, projectGroupDescription );
+    }
+
+    public void testAddAntProjectWithInvalidValues()
+        throws Exception
+    {
+        String name = "!@#$<>?etc";
+        String description = "![]<>'^&etc";
+        String version = "<>whitespaces!#etc";
+        String tag = "!<>*%etc";
+        String scmUrl = "!<>*%etc";
+        goToAddAntProjectPage();
+        addProject( name, description, version, scmUrl, scmUsername, scmPassword, tag, projectGroupName, false, "ant" );
+        assertTextPresent( "Name contains invalid characters." );
+        assertTextPresent( "Version contains invalid characters." );
+        assertTextPresent( "SCM Url contains invalid characters." );
+        assertTextPresent( "SCM Tag contains invalid characters." );
+    }
+
+    public void testSubmitEmptyForm()
+    {
+        goToAddAntProjectPage();
+        submit();
+        assertAddProjectPage( "ant" );
+        assertTextPresent( "Name is required and cannot contain null or spaces only" );
+        assertTextPresent( "Version is required and cannot contain null or spaces only" );
+        assertTextPresent( "SCM Url is required and cannot contain null or spaces only" );
+    }
+
+    public void testAddDuplicateAntProject()
+        throws Exception
+    {
+        testAddAntProject();
+
+        goToAddAntProjectPage();
+        addProject( projectName, projectDescription, projectVersion, scmUrl, scmUsername, scmPassword, projectTag, null,
+                    false, "ant" );
+        assertTextPresent( "Project name already exist" );
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/AppearanceTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/AppearanceTest.java
new file mode 100644
index 0000000..57007ad
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/AppearanceTest.java
@@ -0,0 +1,49 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 org.apache.continuum.web.test.parent.AbstractAdminTest;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+@Test(groups = { "appearance" })
+public class AppearanceTest
+    extends AbstractAdminTest
+{
+
+    public void testAppearancePage()
+    {
+        goToAppearancePage();
+    }
+
+    @Test(dependsOnMethods = { "testAppearancePage" })
+    public void testSaveFooter()
+    {
+        goToAppearancePage();
+        getSelenium().type( "saveFooter_footer",
+                            "<div class=\"xright\">Continuum Test Footer</div> <div class=\"clear\"><hr/></div>" );
+        clickButtonWithValue( "Save" );
+
+        assertTextPresent( "Successfully saved footer content." );
+
+        String SAVE_FOOTER_URL = getProperty( "APPEARANCE_SAVE_FOOTER_URL" );
+        Assert.assertEquals( getSelenium().getLocation(), SAVE_FOOTER_URL );
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/BuildAgentsTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/BuildAgentsTest.java
new file mode 100644
index 0000000..9849c86
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/BuildAgentsTest.java
@@ -0,0 +1,250 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 org.apache.continuum.web.test.parent.AbstractAdminTest;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.io.UnsupportedEncodingException;
+
+@Test( groups = {"agent"} )
+public class BuildAgentsTest
+    extends AbstractAdminTest
+{
+    private String buildAgentGroup;
+
+    private String buildAgentDescription;
+
+    private String badAgentUrl;
+
+    @BeforeMethod
+    public void setUp()
+    {
+        enableDistributedBuilds();
+
+        buildAgentGroup = getProperty( "BUILD_AGENT_GROUPNAME" );
+
+        buildAgentDescription = getProperty( "BUILD_AGENT_DESCRIPTION" );
+        badAgentUrl = "http://localhost:8585/bad-continuum-buildagent/xmlrpc";
+    }
+
+    @AfterMethod
+    public void tearDown()
+        throws Exception
+    {
+        removeBuildAgentGroup( buildAgentGroup, false );
+
+        removeBuildAgent( buildAgentUrl, false );
+        removeBuildAgent( badAgentUrl, false );
+
+        disableDistributedBuilds();
+    }
+
+    public void testAddBuildAgent()
+    {
+        goToAddBuildAgent();
+        addBuildAgent( buildAgentUrl, buildAgentDescription, true, true, true );
+    }
+
+    public void testAddBuildAgentWithXSS()
+    {
+        String invalidUrl = "http://sampleagent/<script>alert('gotcha')</script>";
+        String invalidDescription = "blah blah <script>alert('gotcha')</script> blah blah";
+        goToAddBuildAgent();
+        addBuildAgent( invalidUrl, invalidDescription, false, true, false );
+
+        assertTextPresent( "Build agent url is invalid." );
+    }
+
+    public void testViewBuildAgentInstallationXSS()
+    {
+        String url = baseUrl +
+            "/security/viewBuildAgent.action?buildAgent.url=test%3Cscript%3Ealert%28%27xss%27%29%3C/script%3E";
+        getSelenium().open( url );
+        Assert.assertFalse( getSelenium().isAlertPresent() );
+        assertTextPresent( "<script>alert('xss')</script>" );
+    }
+
+    public void testEditBuildAgentXSS()
+    {
+        String url = baseUrl +
+            "/security/editBuildAgent.action?buildAgent.url=test%3Cscript%3Ealert%28%27xss%27%29%3C/script%3E";
+        getSelenium().open( url );
+        Assert.assertFalse( getSelenium().isAlertPresent() );
+    }
+
+    public void testAddAnExistingBuildAgent()
+    {
+        addBuildAgent( buildAgentUrl );
+
+        goToAddBuildAgent();
+        addBuildAgent( buildAgentUrl, buildAgentDescription, false, false, true );
+        assertTextPresent( "Build agent already exists" );
+    }
+
+    public void testEditBuildAgent()
+        throws Exception
+    {
+        // reset agent to expected state
+        addBuildAgent( buildAgentUrl, buildAgentDescription );
+
+        String new_agentDescription = "new_agentDescription";
+
+        goToEditBuildAgent( buildAgentUrl, buildAgentDescription );
+        addEditBuildAgent( buildAgentUrl, new_agentDescription );
+        goToEditBuildAgent( buildAgentUrl, new_agentDescription );
+        addEditBuildAgent( buildAgentUrl, buildAgentDescription );
+    }
+
+    public void testAddBadBuildAgent()
+        throws Exception
+    {
+        String description = "down agent";
+        goToAddBuildAgent();
+        addBuildAgent( badAgentUrl, description, true, true, false );
+
+        goToBuildAgentPage();
+        assertLinkNotPresent( badAgentUrl );
+    }
+
+    public void testEnableBadBuildAgent()
+        throws Exception
+    {
+        // Note: relying on behaviour of being able to add a disabled agent without a test, if that changes in future we
+        // might need to force its configuration
+        String description = "down agent";
+        goToAddBuildAgent();
+        addBuildAgent( badAgentUrl, description, true, false, true );
+
+        goToEditBuildAgent( badAgentUrl, description );
+        addBuildAgent( badAgentUrl, description, true, true, false );
+
+        goToBuildAgentPage();
+        assertLinkPresent( badAgentUrl );
+    }
+
+    public void testDeleteBuildAgent()
+        throws Exception
+    {
+        addBuildAgent( buildAgentUrl, buildAgentDescription );
+
+        goToBuildAgentPage();
+        removeBuildAgent( buildAgentUrl );
+        assertTextNotPresent( buildAgentUrl );
+    }
+
+    public void testAddEmptyBuildAgent()
+    {
+        goToAddBuildAgent();
+        addBuildAgent( "", buildAgentDescription, false, false, false );
+        assertTextPresent( "Build agent url is required." );
+    }
+
+    //TESTS FOR BUILD AGENT GROUPS
+
+    public void testAddBuildAgentGroupXSS()
+        throws Exception
+    {
+        addBuildAgent( buildAgentUrl );
+
+        goToAddBuildAgentGroup();
+        addEditBuildAgentGroup( "%3Cscript%3Ealert%28%27xss%27%29%3C/script%3E", new String[]{}, new String[]{},
+                                false );
+        assertTextPresent( "Build agent group name contains invalid characters" );
+    }
+
+    public void testEditBuildAgentGroupXSS()
+    {
+        String url = baseUrl +
+            "/security/editBuildAgentGroup.action?buildAgentGroup.name=test%3Cscript%3Ealert%28%27xss%27%29%3C/script%3E";
+        getSelenium().open( url );
+        Assert.assertFalse( getSelenium().isAlertPresent() );
+    }
+
+    public void testAddBuildAgentGroup()
+        throws Exception
+    {
+        addBuildAgent( buildAgentUrl );
+
+        goToAddBuildAgentGroup();
+        addEditBuildAgentGroup( buildAgentGroup, new String[]{buildAgentUrl}, new String[]{}, true );
+    }
+
+    public void testEditBuildAgentGroup()
+        throws Exception
+    {
+        addBuildAgent( buildAgentUrl );
+
+        goToAddBuildAgentGroup();
+        addEditBuildAgentGroup( buildAgentGroup, new String[]{buildAgentUrl}, new String[]{}, true );
+
+        String newName = "new_agentgroupname";
+        goToEditBuildAgentGroup( buildAgentGroup, new String[]{buildAgentUrl} );
+        addEditBuildAgentGroup( newName, new String[]{}, new String[]{buildAgentUrl}, true );
+        goToEditBuildAgentGroup( newName, new String[]{} );
+        addEditBuildAgentGroup( buildAgentGroup, new String[]{buildAgentUrl}, new String[]{}, true );
+    }
+
+    public void testAddAnExistingBuildAgentGroup()
+        throws Exception
+    {
+        addBuildAgent( buildAgentUrl );
+
+        goToAddBuildAgentGroup();
+        addEditBuildAgentGroup( buildAgentGroup, new String[]{buildAgentUrl}, new String[]{}, true );
+
+        goToAddBuildAgentGroup();
+        addEditBuildAgentGroup( buildAgentGroup, new String[]{buildAgentUrl}, new String[]{}, false );
+        assertTextPresent( "Build agent group already exists." );
+    }
+
+    public void testAddEmptyBuildAgentGroupName()
+        throws Exception
+    {
+        addBuildAgent( buildAgentUrl );
+
+        goToAddBuildAgentGroup();
+        addEditBuildAgentGroup( "", new String[]{}, new String[]{}, false );
+        assertTextPresent( "Build agent group name is required." );
+    }
+
+    public void testDeleteBuildAgentGroup()
+        throws UnsupportedEncodingException
+    {
+        addBuildAgent( buildAgentUrl );
+
+        goToAddBuildAgentGroup();
+        addEditBuildAgentGroup( buildAgentGroup, new String[]{buildAgentUrl}, new String[]{}, true );
+
+        removeBuildAgentGroup( buildAgentGroup );
+    }
+
+    public void testAddBuildAgentGroupWithEmptyBuildAgent()
+        throws Exception
+    {
+        addBuildAgent( buildAgentUrl );
+
+        goToAddBuildAgentGroup();
+        addEditBuildAgentGroup( buildAgentGroup, new String[]{}, new String[]{}, true );
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/BuildDefinitionTemplateTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/BuildDefinitionTemplateTest.java
new file mode 100644
index 0000000..bbc13a3
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/BuildDefinitionTemplateTest.java
@@ -0,0 +1,154 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 org.apache.continuum.web.test.parent.AbstractBuildDefinitionTemplateTest;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/**
+ * @author José Morales Martínez
+ * @version $Id$
+ */
+@Test( groups = {"buildDefinitionTemplate"} )
+public class BuildDefinitionTemplateTest
+    extends AbstractBuildDefinitionTemplateTest
+{
+    private String templateName;
+
+    @BeforeClass
+    public void setUp()
+    {
+        templateName = getProperty( "TEMPLATE_NAME" );
+    }
+
+    public void testAddTemplate()
+        throws Exception
+    {
+        goToAddTemplate();
+        addEditTemplate( templateName,
+                         new String[]{"Default Maven Build Definition", "Default Maven 1 Build Definition"},
+                         new String[]{}, true );
+    }
+
+    public void testAddInvalidTemplate()
+        throws Exception
+    {
+        goToAddTemplate();
+        addEditTemplate( "", new String[] { "Default Maven Build Definition" }, new String[] {}, false );
+        assertTextPresent( "Name is required" );
+    }
+
+    public void testAddTemplateWithXSS()
+        throws Exception
+    {
+        goToAddTemplate();
+        addEditTemplate( "Name <script>alert('gotcha')</script>", new String[]{ "Default Maven Build Definition" }, new String[]{}, false );
+        assertTextPresent( "Name contains invalid characters" );
+    }
+
+    @Test( dependsOnMethods = {"testAddTemplate"} )
+    public void testEditTemplate()
+        throws Exception
+    {
+        String newName = "new_name";
+        goToEditTemplate( templateName,
+                          new String[]{"Default Maven Build Definition", "Default Maven 1 Build Definition"} );
+        addEditTemplate( newName, new String[]{"Default Shell Build Definition"},
+                         new String[]{"Default Maven Build Definition"}, true );
+        goToEditTemplate( newName, new String[]{"Default Maven 1 Build Definition", "Default Shell Build Definition"} );
+        addEditTemplate( templateName, new String[]{"Default Maven Build Definition"},
+                         new String[]{"Default Shell Build Definition"}, true );
+    }
+
+    @Test( dependsOnMethods = {"testEditTemplate"} )
+    public void testDeleteTemplate()
+    {
+        removeTemplate( templateName );
+    }
+
+    public void testAddBuildDefinitionTemplate()
+        throws Exception
+    {
+        String TEMPLATE_BUILD_POM_NAME = getProperty( "TEMPLATE_BUILD_POM_NAME" );
+        String TEMPLATE_BUILD_GOALS = getProperty( "TEMPLATE_BUILD_GOALS" );
+        String TEMPLATE_BUILD_ARGUMENTS = getProperty( "TEMPLATE_BUILD_ARGUMENTS" );
+        String TEMPLATE_BUILD_DESCRIPTION = getProperty( "TEMPLATE_BUILD_DESCRIPTION" );
+        goToAddBuildDefinitionTemplate();
+        addEditBuildDefinitionTemplate( TEMPLATE_BUILD_POM_NAME, TEMPLATE_BUILD_GOALS, TEMPLATE_BUILD_ARGUMENTS,
+                                        TEMPLATE_BUILD_DESCRIPTION, true, true, true, true );
+    }
+
+    public void testAddInvalidBuildDefinitionTemplate()
+        throws Exception
+    {
+        goToAddBuildDefinitionTemplate();
+        addEditBuildDefinitionTemplate( "", "", "", "", true, true, true, false );
+        assertTextPresent( "BuildFile is required" );
+        assertTextPresent( "Goals are required" );
+        assertTextPresent( "Description is required" );
+    }
+
+    public void testAddBuildDefinitionTemplateWithXSS()
+        throws Exception
+    {
+        String invalidString = "<script>alert('gotcha')</script>";
+        goToAddBuildDefinitionTemplate();
+        addEditBuildDefinitionTemplate( invalidString, invalidString, invalidString, invalidString, true, true, true,
+                                        false );
+        assertTextPresent( "BuildFile contains invalid characters" );
+        assertTextPresent( "Goals contain invalid characters" );
+        assertTextPresent( "Arguments contain invalid characters" );
+    }
+
+    @Test( dependsOnMethods = {"testAddBuildDefinitionTemplate"} )
+    public void testEditBuildDefinitionTemplate()
+        throws Exception
+    {
+        String TEMPLATE_BUILD_POM_NAME = getProperty( "TEMPLATE_BUILD_POM_NAME" );
+        String TEMPLATE_BUILD_GOALS = getProperty( "TEMPLATE_BUILD_GOALS" );
+        String TEMPLATE_BUILD_ARGUMENTS = getProperty( "TEMPLATE_BUILD_ARGUMENTS" );
+        String TEMPLATE_BUILD_DESCRIPTION = getProperty( "TEMPLATE_BUILD_DESCRIPTION" );
+        goToEditBuildDefinitionTemplate( TEMPLATE_BUILD_DESCRIPTION );
+        addEditBuildDefinitionTemplate( TEMPLATE_BUILD_POM_NAME, TEMPLATE_BUILD_GOALS, TEMPLATE_BUILD_ARGUMENTS,
+                                        TEMPLATE_BUILD_DESCRIPTION, false, false, false, true );
+    }
+
+    @Test( dependsOnMethods = {"testEditBuildDefinitionTemplate"} )
+    public void testDeleteBuildDefinitionTemplate()
+    {
+        String TEMPLATE_BUILD_DESCRIPTION = getProperty( "TEMPLATE_BUILD_DESCRIPTION" );
+        removeBuildDefinitionTemplate( TEMPLATE_BUILD_DESCRIPTION );
+    }
+
+    public void testAddTemplateWithEmptyBuildDefinitions()
+        throws Exception
+    {
+        goToAddTemplate();
+        addEditTemplate( templateName, new String[] {}, new String[] {}, false );
+    }
+
+    @AfterClass
+    public void tearDown()
+    {
+        removeTemplate( templateName, false );
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/BuildDefinitionTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/BuildDefinitionTest.java
new file mode 100644
index 0000000..1e6c201
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/BuildDefinitionTest.java
@@ -0,0 +1,345 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 junit.framework.Assert;
+import org.apache.continuum.web.test.parent.AbstractAdminTest;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author José Morales Martínez
+ * @version $Id$
+ */
+@Test( groups = {"buildDefinition"} )
+public class BuildDefinitionTest
+    extends AbstractAdminTest
+{
+    private String defaultProjectGroupName;
+
+    private String defaultProjectGroupId;
+
+    private String defaultProjectGroupDescription;
+
+    private String projectGroupName;
+
+    private String projectGroupId;
+
+    private String projectGroupDescription;
+
+    private String buildDefinitionPomName;
+
+    private String buildDefinitionGoals;
+
+    private String buildDefinitionArguments;
+
+    private String buildDefinitionDescription;
+
+    private String projectName;
+
+    private String antProjectName;
+
+    private String buildDefinitionId;
+
+    @BeforeClass
+    public void createProject()
+    {
+        projectGroupName = getProperty( "BUILD_DEFINITION_PROJECT_GROUP_NAME" );
+        projectGroupId = getProperty( "BUILD_DEFINITION_PROJECT_GROUP_ID" );
+        projectGroupDescription = getProperty( "BUILD_DEFINITION_PROJECT_GROUP_DESCRIPTION" );
+
+        projectName = getProperty( "MAVEN2_POM_PROJECT_NAME" );
+        String projectPomUrl = getProperty( "MAVEN2_POM_URL" );
+        String pomUsername = getProperty( "MAVEN2_POM_USERNAME" );
+        String pomPassword = getProperty( "MAVEN2_POM_PASSWORD" );
+
+        antProjectName = getProperty( "BUILD_DEFINITION_ANT_PROJECT_NAME" );
+        String antProjectDescription = getProperty( "ANT_DESCRIPTION" );
+        String antProjectVersion = getProperty( "ANT_VERSION" );
+        String antProjectTag = getProperty( "ANT_TAG" );
+        String antScmUrl = getProperty( "ANT_SCM_URL" );
+        String antScmUsername = getProperty( "ANT_SCM_USERNAME" );
+        String antScmPassword = getProperty( "ANT_SCM_PASSWORD" );
+
+        loginAsAdmin();
+        addProjectGroup( projectGroupName, projectGroupId, projectGroupDescription, true, false );
+        clickLinkWithText( projectGroupName );
+        if ( !isLinkPresent( projectName ) )
+        {
+            addMavenTwoProject( projectPomUrl, pomUsername, pomPassword, projectGroupName, true );
+        }
+        if ( !isLinkPresent( antProjectName ) )
+        {
+            goToAddAntProjectPage();
+            addProject( antProjectName, antProjectDescription, antProjectVersion, antScmUrl, antScmUsername,
+                        antScmPassword, antProjectTag, projectGroupName, true, "ant" );
+        }
+    }
+
+    @BeforeMethod
+    protected void setUp()
+        throws Exception
+    {
+        defaultProjectGroupName = getProperty( "DEFAULT_PROJECT_GROUP_NAME" );
+        defaultProjectGroupId = getProperty( "DEFAULT_PROJECT_GROUP_ID" );
+        defaultProjectGroupDescription = getProperty( "DEFAULT_PROJECT_GROUP_DESCRIPTION" );
+
+        buildDefinitionPomName = getProperty( "BUILD_DEFINITION_POM_NAME" );
+        buildDefinitionGoals = getProperty( "BUILD_DEFINITION_GOALS" );
+        buildDefinitionArguments = getProperty( "BUILD_DEFINITION_ARGUMENTS" );
+        buildDefinitionDescription = getProperty( "BUILD_DEFINITION_DESCRIPTION" );
+    }
+
+    public void testDefaultGroupBuildDefinition()
+        throws Exception
+    {
+        goToGroupBuildDefinitionPage( defaultProjectGroupName, defaultProjectGroupId, defaultProjectGroupDescription );
+        String tableElement = "ec_table";
+        assertCellValueFromTable( "Goals", tableElement, 0, 0 );
+        assertCellValueFromTable( "Arguments", tableElement, 0, 1 );
+        assertCellValueFromTable( "Build File", tableElement, 0, 2 );
+        assertCellValueFromTable( "Schedule", tableElement, 0, 3 );
+        assertCellValueFromTable( "Build Environment", tableElement, 0, 4 );
+        assertCellValueFromTable( "From", tableElement, 0, 5 );
+        assertCellValueFromTable( "Build Fresh", tableElement, 0, 6 );
+        assertCellValueFromTable( "Default", tableElement, 0, 7 );
+        assertCellValueFromTable( "Description", tableElement, 0, 8 );
+        assertCellValueFromTable( "Type", tableElement, 0, 9 );
+        assertCellValueFromTable( "Always Build", tableElement, 0, 10 );
+
+        assertCellValueFromTable( "clean install", tableElement, 1, 0 );
+        assertCellValueFromTable( "--batch-mode --non-recursive", tableElement, 1, 1 );
+        assertCellValueFromTable( "pom.xml", tableElement, 1, 2 );
+        assertCellValueFromTable( "DEFAULT_SCHEDULE", tableElement, 1, 3 );
+        assertCellValueFromTable( "GROUP", tableElement, 1, 5 );
+        assertCellValueFromTable( "false", tableElement, 1, 6 );
+        assertCellValueFromTable( "true", tableElement, 1, 7 );
+        assertCellValueFromTable( "Default Maven Build Definition", tableElement, 1, 8 );
+        assertCellValueFromTable( "maven2", tableElement, 1, 9 );
+        assertCellValueFromTable( "false", tableElement, 1, 10 );
+        assertImgWithAlt( "Edit" );
+        assertImgWithAlt( "Delete" );
+        assertImgWithAlt( "Build" );
+    }
+
+    public void testAddInvalidGroupBuildDefinition()
+        throws Exception
+    {
+        goToGroupBuildDefinitionPage( projectGroupName, projectGroupId, projectGroupDescription );
+        clickButtonWithValue( "Add" );
+        setFieldValue( "buildFile", "" );
+        setFieldValue( "goals", "" );
+        clickButtonWithValue( "Save" );
+        assertTextPresent( "Build file is required and cannot contain spaces only" );
+        assertTextPresent( "Goals are required" );
+    }
+
+    public void testAddGroupBuildDefinitionWithXSS()
+        throws Exception
+    {
+        goToGroupBuildDefinitionPage( projectGroupName, projectGroupId, projectGroupDescription );
+        clickButtonWithValue( "Add" );
+        setFieldValue( "buildFile", "<script>alert('xss')</script>" );
+        setFieldValue( "description", "<script>alert('xss')</script>" );
+        clickButtonWithValue( "Save" );
+        assertTextPresent( "Build file contains invalid characters." );
+    }
+
+    public void testBuildFromGroupBuildDefinition()
+        throws Exception
+    {
+        goToGroupBuildDefinitionPage( projectGroupName, projectGroupId, projectGroupDescription );
+        clickImgWithAlt( "Build" );
+        assertProjectGroupSummaryPage( projectGroupName, projectGroupId, projectGroupDescription );
+    }
+
+    public void testAddDefaultGroupBuildDefinition()
+        throws Exception
+    {
+        goToGroupBuildDefinitionPage( projectGroupName, projectGroupId, projectGroupDescription );
+        clickButtonWithValue( "Add" );
+        addEditGroupBuildDefinition( projectGroupName, buildDefinitionPomName, buildDefinitionGoals,
+                                     buildDefinitionArguments, buildDefinitionDescription, true, false, true,
+                                     MAVEN_PROJECT_TYPE, true );
+    }
+
+    public void testAddNotDefaultGroupBuildDefinition()
+        throws Exception
+    {
+        goToGroupBuildDefinitionPage( projectGroupName, projectGroupId, projectGroupDescription );
+        clickButtonWithValue( "Add" );
+        addEditGroupBuildDefinition( projectGroupName, buildDefinitionPomName, buildDefinitionGoals,
+                                     buildDefinitionArguments, buildDefinitionDescription, false, false, false,
+                                     MAVEN_PROJECT_TYPE, true );
+    }
+
+    @Test( dependsOnMethods = {"testAddNotDefaultGroupBuildDefinition"} )
+    public void testEditGroupBuildDefinition()
+        throws Exception
+    {
+        String newPom = "newpom.xml";
+        String newGoals = "new goals";
+        String newArguments = "new arguments";
+        String newDescription = "new description";
+        goToGroupBuildDefinitionPage( projectGroupName, projectGroupId, projectGroupDescription );
+        clickImgWithAlt( "Edit" );
+        addEditGroupBuildDefinition( projectGroupName, newPom, newGoals, newArguments, newDescription, false, false,
+                                     false, MAVEN_PROJECT_TYPE, true );
+        clickImgWithAlt( "Edit" );
+        addEditGroupBuildDefinition( projectGroupName, buildDefinitionPomName, buildDefinitionGoals,
+                                     buildDefinitionArguments, buildDefinitionDescription, true, true, false,
+                                     MAVEN_PROJECT_TYPE, true );
+        clickImgWithAlt( "Edit" );
+        addEditGroupBuildDefinition( projectGroupName, buildDefinitionPomName, buildDefinitionGoals,
+                                     buildDefinitionArguments, buildDefinitionDescription, false, true, false,
+                                     MAVEN_PROJECT_TYPE, true );
+    }
+
+    @Test( dependsOnMethods = {"testEditGroupBuildDefinition"} )
+    public void testDeleteGroupBuildDefinition()
+        throws Exception
+    {
+        goToGroupBuildDefinitionPage( projectGroupName, projectGroupId, projectGroupDescription );
+        // Click in Delete Image
+        clickLinkWithXPath( "(//a[contains(@href,'removeGroupBuildDefinition')])//img" );
+        assertDeleteBuildDefinitionPage( buildDefinitionDescription, buildDefinitionGoals );
+        clickButtonWithValue( "Delete" );
+        assertGroupBuildDefinitionPage( projectGroupName );
+    }
+
+    public void testAddNotDefaultProjectBuildDefinition()
+        throws Exception
+    {
+        goToProjectInformationPage( projectGroupName, projectName );
+        clickLinkWithXPath( "//input[contains(@id,'buildDefinition')]" );
+        addEditGroupBuildDefinition( null, buildDefinitionPomName, buildDefinitionGoals, buildDefinitionArguments,
+                                     buildDefinitionDescription, false, false, false, MAVEN_PROJECT_TYPE, true );
+        String value = getSelenium().getAttribute(
+            "xpath=(//a[contains(@href,'removeProjectBuildDefinition')])[last()]/@href" );
+        Matcher m = Pattern.compile( "^.*buildDefinitionId=([0-9]+).*$" ).matcher( value );
+        Assert.assertTrue( m.matches() );
+        buildDefinitionId = m.group( 1 );
+    }
+
+    public void testAddNotDefaultProjectBuildDefinitionWithLongMavenGoal()
+        throws Exception
+    {
+        goToProjectInformationPage( projectGroupName, projectName );
+        clickLinkWithXPath( "//input[contains(@id,'buildDefinition')]" );
+        addEditGroupBuildDefinition( null, buildDefinitionPomName,
+                                     "clean org.apache.maven.plugins:maven-compile-plugin:2.4:compile",
+                                     buildDefinitionArguments, buildDefinitionDescription, false, false, false,
+                                     MAVEN_PROJECT_TYPE, true );
+    }
+
+    @Test( dependsOnMethods = {"testAddNotDefaultProjectBuildDefinition"} )
+    public void testDeleteProjectBuildDefinition()
+        throws Exception
+    {
+        goToProjectInformationPage( projectGroupName, projectName );
+        // Click in Delete Image
+        String locator = "id=remove-build-definition-" + buildDefinitionId;
+        assertElementPresent( locator );
+        clickLinkWithLocator( locator );
+        assertDeleteBuildDefinitionPage( buildDefinitionDescription, buildDefinitionGoals );
+        clickButtonWithValue( "Delete" );
+        assertProjectInformationPage();
+
+        assertElementNotPresent( locator );
+    }
+
+    public void testAddNotDefaultProjectBuildDefinitionAnt()
+        throws Exception
+    {
+        goToProjectInformationPage( projectGroupName, antProjectName );
+        clickLinkWithXPath( "//input[contains(@id,'buildDefinition')]" );
+        addEditGroupBuildDefinition( null, "build-other.xml", "package", "", "other build file", false, false, false,
+                                     ANT_PROJECT_TYPE, true );
+    }
+
+    public void testAddNotDefaultProjectBuildDefinitionAntWithPathBuildFile()
+        throws Exception
+    {
+        goToProjectInformationPage( projectGroupName, antProjectName );
+        clickLinkWithXPath( "//input[contains(@id,'buildDefinition')]" );
+        addEditGroupBuildDefinition( null, "Quartz/path\\build.xml", "package", "", "build file with path", false,
+                                     false, false, ANT_PROJECT_TYPE, true );
+    }
+
+    public void testAddNotDefaultProjectBuildDefinitionAntWithInvalidBuildFile()
+        throws Exception
+    {
+        goToProjectInformationPage( projectGroupName, antProjectName );
+        clickLinkWithXPath( "//input[contains(@id,'buildDefinition')]" );
+        addEditGroupBuildDefinition( null, "<script>alert('xss');</script>", "package", "", "invalid build file",
+                                     false, false, false, ANT_PROJECT_TYPE, false );
+
+        assertTextPresent( "Build file contains invalid characters" );
+
+        // confirm error page contains the right fields still
+        assertTextPresent( "Ant build filename*:" );
+        assertTextPresent( "Targets:" );
+    }
+
+    public void testEditBuildDefinitionFromSummary()
+        throws Exception
+    {
+        goToProjectInformationPage( projectGroupName, projectName );
+        clickLinkWithLocator( "buildDefinition_0" ); // Add button for project build definition
+        String description = "testEditBuildDefinitionFromSummary";
+        addEditGroupBuildDefinition( null, buildDefinitionPomName, buildDefinitionGoals,
+                                     buildDefinitionArguments, description, false, false,
+                                     false, MAVEN_PROJECT_TYPE, true );
+
+        assertProjectInformationPage();
+        String xPath = "//preceding::td[text()='" + description + "']//following::img[@alt='Edit']";
+        clickLinkWithXPath( xPath );
+
+        addEditGroupBuildDefinition( null, buildDefinitionPomName, "new goals", buildDefinitionArguments,
+                                     description, false, false, false, MAVEN_PROJECT_TYPE, true );
+
+        assertProjectInformationPage();
+        assertTextPresent( "new goals" );
+    }
+
+    public void testEditGroupBuildDefinitionFromSummary()
+        throws Exception
+    {
+        goToGroupBuildDefinitionPage( projectGroupName, projectGroupId, projectGroupDescription );
+        clickButtonWithValue( "Add" );
+        String description = "testEditGroupBuildDefinitionFromSummary";
+        addEditGroupBuildDefinition( projectGroupName, buildDefinitionPomName, buildDefinitionGoals,
+                                     buildDefinitionArguments, description, false, false,
+                                     false, MAVEN_PROJECT_TYPE, true );
+
+        goToProjectInformationPage( projectGroupName, projectName );
+        String xPath = "//preceding::td[text()='" + description + "']//following::img[@alt='Edit']";
+        clickLinkWithXPath( xPath );
+
+        addEditGroupBuildDefinition( projectGroupName, buildDefinitionPomName, "new goals", buildDefinitionArguments,
+                                     description, false, false, false, MAVEN_PROJECT_TYPE, true );
+
+        assertTextPresent( "new goals" );
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/BuildEnvironmentTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/BuildEnvironmentTest.java
new file mode 100644
index 0000000..a93d71c
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/BuildEnvironmentTest.java
@@ -0,0 +1,181 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 org.apache.continuum.web.test.parent.AbstractInstallationTest;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/**
+ * @author José Morales Martínez
+ * @version $Id$
+ */
+@Test( groups = { "buildEnvironment" } )
+public class BuildEnvironmentTest
+    extends AbstractInstallationTest
+{
+
+    public static final String INSTALLATION_NAME = "varForBuildEnv";
+
+    private static final String INSTALLATION_BUILD_ENV = "installationBuildEnv";
+
+    private static final String NEW_BUILD_ENV = "NEW_BUILD_ENV";
+
+    private String buildEnvName;
+
+    @BeforeClass(alwaysRun = true)
+    public void setUp()
+    {
+        buildEnvName = getProperty( "BUILD_ENV_NAME" );
+    }
+
+    public void testAddBuildEnvironment()
+    {
+        goToAddBuildEnvironment();
+        addBuildEnvironment( buildEnvName, new String[]{ }, true );
+    }
+
+    public void testAddInvalidBuildEnvironment()
+    {
+        goToAddBuildEnvironment();
+        addBuildEnvironment( "", new String[]{ }, false );
+        assertTextPresent( "You must define a name" );
+    }
+
+    public void testAddBuildEnvironmentWithXSS()
+    {
+        goToAddBuildEnvironment();
+        addBuildEnvironment( "<script>alert('gotcha')</script>", new String[]{ }, false );
+        assertTextPresent( "Build environment name contains invalid characters." );
+    }
+
+    @Test( dependsOnMethods = { "testAddBuildEnvironment" } )
+    public void testEditInvalidBuildEnvironment()
+    {
+        goToEditBuildEnvironment( buildEnvName );
+        editBuildEnvironment( "", new String[]{ }, false );
+        assertTextPresent( "You must define a name" );
+    }
+
+    @Test( dependsOnMethods = { "testAddBuildEnvironment" } )
+    public void testAddDuplicatedBuildEnvironment()
+    {
+        goToAddBuildEnvironment();
+        addBuildEnvironment( buildEnvName, new String[]{ }, false );
+        assertTextPresent( "A Build Environment with the same name already exists" );
+    }
+
+    @Test( dependsOnMethods = { "testAddBuildEnvironment" } )
+    public void testEditBuildEnvironment()
+    {
+        String newName = "new_name";
+        goToEditBuildEnvironment( buildEnvName );
+        editBuildEnvironment( newName, new String[]{ }, true );
+        goToEditBuildEnvironment( newName );
+        editBuildEnvironment( buildEnvName, new String[]{ }, true );
+    }
+
+    @Test( dependsOnMethods = { "testAddBuildEnvironment" })
+    public void testAddInstallationToBuildEnvironment()
+    {
+        addBuildEnvironment( INSTALLATION_BUILD_ENV, new String[]{ }, true );
+
+        goToInstallationPage();
+        if ( !isTextPresent( INSTALLATION_NAME ) )
+        {
+            goToAddInstallationVariable();
+            addInstallation( INSTALLATION_NAME, "VAR_BUILD_ENV", "var_value", false, false, true );
+        }
+
+        goToEditBuildEnvironment( INSTALLATION_BUILD_ENV );
+        editBuildEnvironment( INSTALLATION_BUILD_ENV, new String[] { INSTALLATION_NAME }, true );
+    }
+
+    @Test( dependsOnMethods = { "testAddInstallationToBuildEnvironment" })
+    public void testEditInstallationOnBuildEnvironment()
+    {
+        goToEditBuildEnvironment( INSTALLATION_BUILD_ENV );
+        clickLinkWithText( INSTALLATION_NAME );
+        assertEditInstallationVariablePage();
+        assert INSTALLATION_NAME.equals( getFieldValue( "installation.name" ) );
+    }
+
+    @Test( dependsOnMethods = { "testEditInstallationOnBuildEnvironment" })
+    public void testRemoveInstallationOnBuildEnvironment()
+    {
+        goToEditBuildEnvironment( INSTALLATION_BUILD_ENV );
+        assertLinkPresent( INSTALLATION_NAME );
+        clickImgWithAlt( "Delete" );
+        assertEditBuildEnvironmentPage( INSTALLATION_BUILD_ENV );
+        assertLinkNotPresent( INSTALLATION_NAME );
+    }
+
+    @Test( dependsOnMethods = { "testEditInvalidBuildEnvironment", "testEditBuildEnvironment",
+        "testAddDuplicatedBuildEnvironment", "testEditInvalidBuildEnvironment" } )
+    public void testDeleteBuildEnvironment()
+    {
+        removeBuildEnvironment( buildEnvName );
+    }
+
+    @Test( dependsOnMethods = { "testAddBuildEnvironment" } )
+    public void testEditDuplicatedBuildEnvironmentParallelBuilds()
+    {
+        goToAddBuildEnvironment();
+        addBuildEnvironment( NEW_BUILD_ENV, new String[]{ }, true );
+        goToEditBuildEnvironment( NEW_BUILD_ENV );
+        editBuildEnvironment( buildEnvName, new String[]{ }, false );
+        assertTextPresent( "A Build Environment with the same name already exists" );
+    }
+
+    protected void addBuildEnvironment( String name, String[] installations, boolean success )
+    {
+        setFieldValue( "profile.name", name );
+        submit();
+        editBuildEnvironment( name, installations, success );
+    }
+
+    protected void editBuildEnvironment( String name, String[] installations, boolean success )
+    {
+        setFieldValue( "profile.name", name );
+        for ( String i : installations )
+        {
+            selectValue( "installationId", i );
+            clickButtonWithValue( "Add" );
+        }
+        submit();
+        if ( success )
+        {
+            assertBuildEnvironmentPage();
+        }
+        else
+        {
+            assertAddBuildEnvironmentPage();
+        }
+    }
+
+    @AfterClass(alwaysRun = true)
+    public void tearDown()
+    {
+        removeBuildEnvironment( buildEnvName, false );
+        removeBuildEnvironment( INSTALLATION_BUILD_ENV, false );
+        removeBuildEnvironment( NEW_BUILD_ENV, false );
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/BuildResultTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/BuildResultTest.java
new file mode 100644
index 0000000..bcd8e59
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/BuildResultTest.java
@@ -0,0 +1,81 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 org.apache.continuum.web.test.parent.AbstractAdminTest;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+@Test( groups = { "buildResult" } )
+public class BuildResultTest
+    extends AbstractAdminTest
+{
+    private String projectGroupName;
+
+    private String projectGroupId;
+
+    private String projectGroupDescription;
+
+    private String projectName;
+
+    @BeforeClass
+    public void createProject()
+    {
+        projectGroupName = getProperty( "BUILD_RESULT_PROJECT_GROUP_NAME" );
+        projectGroupId = getProperty( "BUILD_RESULT_PROJECT_GROUP_ID" );
+        projectGroupDescription = getProperty( "BUILD_RESULT_PROJECT_GROUP_DESCRIPTION" );
+
+        projectName = getProperty( "MAVEN2_POM_PROJECT_NAME" );
+        String projectPomUrl = getProperty( "MAVEN2_POM_URL" );
+        String pomUsername = getProperty( "MAVEN2_POM_USERNAME" );
+        String pomPassword = getProperty( "MAVEN2_POM_PASSWORD" );
+
+        loginAsAdmin();
+        addProjectGroup( projectGroupName, projectGroupId, projectGroupDescription, true, false );
+        clickLinkWithText( projectGroupName );
+        if ( !isLinkPresent( projectName ) )
+        {
+            addMavenTwoProject( projectPomUrl, pomUsername, pomPassword, projectGroupName, true );
+        }
+    }
+
+    public void testDeleteBuildResult()
+    {
+        buildProjectGroup( projectGroupName, projectGroupId, projectGroupDescription, projectName, true );
+
+        // go to build results page
+        clickAndWait( "css=img[title='Build History']" );
+
+        assertPage( "Continuum - Build results" );
+        assertElementPresent( "css=tbody.tableBody tr" );
+
+        assertElementPresent( "selectedBuildResults_selector" );
+        getSelenium().click( "selectedBuildResults_selector" );
+        clickButtonWithValue( "Delete" );
+
+        assertPage( "Continuum - Delete Build Results" );
+
+        clickButtonWithValue( "Delete" );
+
+        assertPage( "Continuum - Build results" );
+        assertElementNotPresent( "css=tbody.tableBody tr" );
+    }
+
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/CSRFSecurityTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/CSRFSecurityTest.java
new file mode 100644
index 0000000..48e4fa1
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/CSRFSecurityTest.java
@@ -0,0 +1,174 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 org.apache.continuum.web.test.parent.AbstractAdminTest;
+import org.testng.annotations.Test;
+
+/**
+ * Test actions that are vulnerable to CSRF.
+ */
+@Test( groups = {"csrf"} )
+public class CSRFSecurityTest
+    extends AbstractAdminTest
+{
+    public void testCSRFDeleteProject()
+    {
+        getSelenium().open( baseUrl );
+        getSelenium().open( baseUrl + "/deleteProject_default.action?projectGroupId=2&projectId=2" );
+        assertTextPresent( "Security Alert - Invalid Token Found" );
+        assertTextPresent( "Possible CSRF attack detected! Invalid token found in the request." );
+    }
+
+    public void testCSRFRemoveProjectBuildDefinition()
+    {
+        getSelenium().open( baseUrl );
+        getSelenium().open(
+            baseUrl + "/removeProjectBuildDefinition.action?projectId=1&buildDefinitionId=9&confirmed=true" );
+        assertTextPresent( "Security Alert - Invalid Token Found" );
+        assertTextPresent( "Possible CSRF attack detected! Invalid token found in the request." );
+    }
+
+    public void testCSRFRemoveGroupBuildDefinition()
+    {
+        getSelenium().open( baseUrl );
+        getSelenium().open(
+            baseUrl + "/removeGroupBuildDefinition.action?projectGroupId=2&buildDefinitionId=8&confirmed=true" );
+        assertTextPresent( "Security Alert - Invalid Token Found" );
+        assertTextPresent( "Possible CSRF attack detected! Invalid token found in the request." );
+    }
+
+    public void testCSRFRemoveProjectGroup()
+    {
+        getSelenium().open( baseUrl );
+        getSelenium().open( baseUrl + "/removeProjectGroup.action?projectGroupId=2" );
+        assertTextPresent( "Security Alert - Invalid Token Found" );
+        assertTextPresent( "Possible CSRF attack detected! Invalid token found in the request." );
+    }
+
+    public void testCSRFRemoveBuildResult()
+    {
+        getSelenium().open( baseUrl );
+        getSelenium().open( baseUrl + "/removeBuildResult.action?projectId=1&buildId=1&confirmed=true" );
+        assertTextPresent( "Security Alert - Invalid Token Found" );
+        assertTextPresent( "Possible CSRF attack detected! Invalid token found in the request." );
+    }
+
+    public void testCSRFRemoveSchedule()
+    {
+        getSelenium().open( baseUrl );
+        getSelenium().open( baseUrl + "/removeSchedule.action?id=1&name=DEFAULT_SCHEDULE" );
+        assertTextPresent( "Security Alert - Invalid Token Found" );
+        assertTextPresent( "Possible CSRF attack detected! Invalid token found in the request." );
+    }
+
+    public void testCSRFRemoveReleaseResults()
+    {
+        getSelenium().open( baseUrl );
+        getSelenium().open(
+            baseUrl + "/removeReleaseResults.action?projectGroupId=2&selectedReleaseResults=1&confirmed=true" );
+        assertTextPresent( "Security Alert - Invalid Token Found" );
+        assertTextPresent( "Possible CSRF attack detected! Invalid token found in the request." );
+    }
+
+    public void testCSRFSaveFooter()
+    {
+        getSelenium().open( baseUrl );
+        getSelenium().open( baseUrl + "/admin/saveFooter.action?footer=testValue" );
+        assertTextPresent( "Security Alert - Invalid Token Found" );
+        assertTextPresent( "Possible CSRF attack detected! Invalid token found in the request." );
+    }
+
+    public void testCSRFSaveCompanyPOM()
+    {
+        getSelenium().open( baseUrl );
+        getSelenium().open( baseUrl + "/admin/saveCompanyPom.action" );
+        assertTextPresent( "Security Alert - Invalid Token Found" );
+        assertTextPresent( "Possible CSRF attack detected! Invalid token found in the request." );
+    }
+
+    public void testCSRFDeleteBuildEnvironment()
+    {
+        getSelenium().open( baseUrl );
+        getSelenium().open( baseUrl + "/deleteBuildEnv.action?profile.id=1" );
+        assertTextPresent( "Security Alert - Invalid Token Found" );
+        assertTextPresent( "Possible CSRF attack detected! Invalid token found in the request." );
+    }
+
+    public void testCSRFDeleteBuildDefinitionTemplate()
+    {
+        getSelenium().open( baseUrl );
+        getSelenium().open( baseUrl +
+                                "/deleteDefinitionTemplate.action?buildDefinitionTemplate.id=5&buildDefinitionTemplate.name=Test+Template" );
+        assertTextPresent( "Security Alert - Invalid Token Found" );
+        assertTextPresent( "Possible CSRF attack detected! Invalid token found in the request." );
+    }
+
+    public void testCSRFDeleteBuildQueue()
+    {
+        getSelenium().open( baseUrl );
+        getSelenium().open( baseUrl + "/deleteBuildQueue.action?buildQueue.id=3&buildQueue.name=TEST_BUILD_QUEUE" );
+        assertTextPresent( "Security Alert - Invalid Token Found" );
+        assertTextPresent( "Possible CSRF attack detected! Invalid token found in the request." );
+    }
+
+    public void testCSRFRemoveLocalRepository()
+    {
+        getSelenium().open( baseUrl );
+        getSelenium().open( baseUrl + "/removeRepository.action?repository.id=2" );
+        assertTextPresent( "Security Alert - Invalid Token Found" );
+        assertTextPresent( "Possible CSRF attack detected! Invalid token found in the request." );
+    }
+
+    public void testCSRFRemovePurgeConfiguration()
+    {
+        getSelenium().open( baseUrl );
+        getSelenium().open( baseUrl + "/removePurgeConfig.action?purgeConfigId=2&confirmed=true" );
+        assertTextPresent( "Security Alert - Invalid Token Found" );
+        assertTextPresent( "Possible CSRF attack detected! Invalid token found in the request." );
+    }
+
+    public void testCSRFDeleteBuildAgent()
+    {
+        getSelenium().open( baseUrl );
+        getSelenium().open( baseUrl +
+                                "/security/deleteBuildAgent.action?buildAgent.url=http%3A%2F%2Flocalhost%3A8181%2Fcontinuum-buildagent%2Fxmlrpc&confirmed=true" );
+        assertTextPresent( "Security Alert - Invalid Token Found" );
+        assertTextPresent( "Possible CSRF attack detected! Invalid token found in the request." );
+    }
+
+    public void testCSRFDeleteBuildAgentGroup()
+    {
+        getSelenium().open( baseUrl );
+        getSelenium().open(
+            baseUrl + "/security/deleteBuildAgentGroup.action?buildAgentGroup.name=Test+Agent+Group&confirmed=true" );
+        assertTextPresent( "Security Alert - Invalid Token Found" );
+        assertTextPresent( "Possible CSRF attack detected! Invalid token found in the request." );
+    }
+
+    public void testCSRFDeleteProjectGroupNotifier()
+    {
+        getSelenium().open( baseUrl );
+        getSelenium().open(
+            baseUrl + "/deleteProjectGroupNotifier.action?projectGroupId=2&notifierId=1&notifierType=mail" );
+        assertTextPresent( "Security Alert - Invalid Token Found" );
+        assertTextPresent( "Possible CSRF attack detected! Invalid token found in the request." );
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/ConfigurationTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/ConfigurationTest.java
new file mode 100644
index 0000000..d8fe5d2
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/ConfigurationTest.java
@@ -0,0 +1,234 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 org.apache.continuum.web.test.parent.AbstractAdminTest;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * @author José Morales Martínez
+ * @version $Id$
+ */
+@Test( groups = { "configuration" } )
+public class ConfigurationTest
+    extends AbstractAdminTest
+{
+    private String WORKING_DIRECTORY;
+
+    private String BASE_URL;
+
+    private String BUILD_OUTPUT_DIRECTORY;
+
+    private String RELEASE_OUTPUT_DIRECTORY;
+
+    private String DEPLOYMENT_REPOSITORY_DIRECTORY;
+
+    private String NUMBER_ALLOWED_PARALLEL;
+
+    public void defaultConfiguration()
+    {
+        goToConfigurationPage();
+        WORKING_DIRECTORY = getFieldValue( "workingDirectory" );
+        BASE_URL = getFieldValue( "baseUrl" );
+        BUILD_OUTPUT_DIRECTORY = getFieldValue( "buildOutputDirectory" );
+        RELEASE_OUTPUT_DIRECTORY = getFieldValue( "releaseOutputDirectory" );
+        DEPLOYMENT_REPOSITORY_DIRECTORY = getFieldValue( "deploymentRepositoryDirectory" );
+        NUMBER_ALLOWED_PARALLEL = getFieldValue( "numberOfAllowedBuildsinParallel" );
+    }
+
+    @Test( dependsOnMethods = { "defaultConfiguration" } )
+    public void editConfiguration()
+    {
+        String newWorking = "newWorking";
+        String newUrl = "http://localhost:8181";
+        String newBuildOutput = "newBuildOutput";
+        String newReleaseOutput = "newReleaseOutput";
+        String newDeployRepository = "newDeployRepository";
+        String newNumberParallel = "9";
+        goToConfigurationPage();
+        submitConfiguration( newWorking, newBuildOutput, newReleaseOutput, newDeployRepository, newUrl,
+                             newNumberParallel, true, true );
+        clickButtonWithValue( "Edit" );
+        submitConfiguration( WORKING_DIRECTORY, BUILD_OUTPUT_DIRECTORY, RELEASE_OUTPUT_DIRECTORY,
+                             DEPLOYMENT_REPOSITORY_DIRECTORY, BASE_URL, NUMBER_ALLOWED_PARALLEL, false, true );
+    }
+
+    public void setInvalidConfiguration()
+    {
+        goToConfigurationPage();
+        submitConfiguration( "", "", "", "", "", "", true, false );
+        assertTextPresent( "You must define a working directory" );
+        assertTextPresent( "You must define a build output directory" );
+        assertTextPresent( "You must define a URL" );
+    }
+
+    public void setZeroParallelBuilds()
+    {
+        setMaxBuildQueue( 0 );
+        assertTextPresent( "Number of Allowed Builds in Parallel must be greater than zero" );
+    }
+
+    public void testSetConfigurationWithXSS()
+    {
+        String invalidString = "<script>alert('gotcha')</script>";
+        goToConfigurationPage();
+        submitConfiguration( invalidString, invalidString, invalidString, invalidString, invalidString, invalidString,
+                             true, false );
+        assertTextPresent( "Working directory contains invalid characters." );
+        assertTextPresent( "Build output directory contains invalid characters." );
+        assertTextPresent( "Release output directory contains invalid characters." );
+        assertTextPresent( "Deployment repository directory contains invalid characters." );
+        assertTextPresent( "You must define a valid URL." );
+    }
+
+    public void testSetFooterXSS()
+    {
+        goToAppearancePage();
+        setFieldValue( "saveFooter_footer",
+                       "Copyright <SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT> 2005-2011&nbsp;The Apache Software Foundation" );
+        submit();
+        Assert.assertFalse( getSelenium().isAlertPresent() );
+        assertTextPresent( "Copyright 2005-2011 The Apache Software Foundation" );
+
+        setFieldValue( "saveFooter_footer",
+                       "Copyright <SCRIPT SRC=http://ha.ckers.org/xss.js></SCRIPT> 2005-2011&nbsp;The Apache Software Foundation" );
+        submit();
+        Assert.assertFalse( getSelenium().isAlertPresent() );
+        assertTextPresent( "Copyright 2005-2011 The Apache Software Foundation" );
+
+        setFieldValue( "saveFooter_footer",
+                       "Copyright <IMG SRC=\"javascript:alert('XSS');\"> 2005-2011&nbsp;The Apache Software Foundation" );
+        submit();
+        Assert.assertFalse( getSelenium().isAlertPresent() );
+        assertTextPresent( "Copyright 2005-2011 The Apache Software Foundation" );
+
+        setFieldValue( "saveFooter_footer",
+                       "Copyright <IMG SRC=JaVaScRiPt:alert('XSS')> 2005-2011&nbsp;The Apache Software Foundation" );
+        submit();
+        Assert.assertFalse( getSelenium().isAlertPresent() );
+        assertTextPresent( "Copyright 2005-2011 The Apache Software Foundation" );
+
+        setFieldValue( "saveFooter_footer",
+                       "Copyright <IMG SRC=javascript:alert(&quot;XSS&quot;)> 2005-2011&nbsp;The Apache Software Foundation" );
+        submit();
+        Assert.assertFalse( getSelenium().isAlertPresent() );
+        assertTextPresent( "Copyright 2005-2011 The Apache Software Foundation" );
+
+        // unicode
+        setFieldValue( "saveFooter_footer",
+                       "Copyright <IMG SRC=&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41;> 2005-2011&nbsp;The Apache Software Foundation" );
+        submit();
+        Assert.assertFalse( getSelenium().isAlertPresent() );
+        assertTextPresent( "Copyright 2005-2011 The Apache Software Foundation" );
+
+        // utf-8
+        setFieldValue( "saveFooter_footer",
+                       "Copyright <IMG SRC=&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041> 2005-2011&nbsp;The Apache Software Foundation" );
+        submit();
+        Assert.assertFalse( getSelenium().isAlertPresent() );
+        assertTextPresent( "Copyright 2005-2011 The Apache Software Foundation" );
+
+        // hex encoding
+        setFieldValue( "saveFooter_footer",
+                       "Copyright <IMG SRC=&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29> 2005-2011&nbsp;The Apache Software Foundation" );
+        submit();
+        Assert.assertFalse( getSelenium().isAlertPresent() );
+        assertTextPresent( "Copyright 2005-2011 The Apache Software Foundation" );
+
+        setFieldValue( "saveFooter_footer",
+                       "Copyright <IMG SRC=\"jav    ascript:alert('XSS');\"> 2005-2011&nbsp;The Apache Software Foundation" );
+        submit();
+        Assert.assertFalse( getSelenium().isAlertPresent() );
+        assertTextPresent( "Copyright 2005-2011 The Apache Software Foundation" );
+
+        setFieldValue( "saveFooter_footer",
+                       "Copyright <IMG SRC=\"jav&#x09;ascript:alert('XSS');\"> 2005-2011&nbsp;The Apache Software Foundation" );
+        submit();
+        Assert.assertFalse( getSelenium().isAlertPresent() );
+        assertTextPresent( "Copyright 2005-2011 The Apache Software Foundation" );
+
+        setFieldValue( "saveFooter_footer",
+                       "Copyright <STYLE>@import'http://ha.ckers.org/xss.css';</STYLE> 2005-2011&nbsp;The Apache Software Foundation" );
+        submit();
+        Assert.assertFalse( getSelenium().isAlertPresent() );
+        assertTextPresent( "Copyright 2005-2011 The Apache Software Foundation" );
+    }
+
+    void assertEditedConfigurationPage( String working, String buildOutput, String releaseOutput,
+                                        String deploymentRepository, String baseUrl, String numberBuildParallel )
+    {
+        assertPage( "Continuum - Configuration" );
+        assertTextPresent( "General Configuration " );
+        assertTextPresent( "Working Directory" );
+        assertElementNotPresent( "workingDirectory" );
+        assertTextPresent( working );
+        assertTextPresent( "Build Output Directory" );
+        assertElementNotPresent( "buildOutputDirectory" );
+        assertTextPresent( buildOutput );
+        assertTextPresent( "Release Output Directory" );
+        assertElementNotPresent( "releaseOutputDirectory" );
+        assertTextPresent( releaseOutput );
+        assertTextPresent( "Deployment Repository Directory" );
+        assertElementNotPresent( "deploymentRepositoryDirectory" );
+        assertTextPresent( deploymentRepository );
+        assertTextPresent( "Base URL" );
+        assertElementNotPresent( "baseUrl" );
+        assertTextPresent( baseUrl );
+        assertTextPresent( "Number of Allowed Builds in Parallel" );
+        assertElementNotPresent( "numberOfAllowedBuildsinParallel" );
+        assertTextPresent( numberBuildParallel );
+        assertTextPresent( "Enable Distributed Builds" );
+        assertElementNotPresent( "distributedBuildEnabled" );
+        assertButtonWithValuePresent( "Edit" );
+
+    }
+
+    protected void submitConfiguration( String working, String buildOutput, String releaseOutput,
+                                        String deploymentRepository, String baseUrl, String numberBuildParallel,
+                                        boolean distributed, boolean success )
+    {
+        setFieldValue( "workingDirectory", working );
+        setFieldValue( "buildOutputDirectory", buildOutput );
+        setFieldValue( "releaseOutputDirectory", releaseOutput );
+        setFieldValue( "deploymentRepositoryDirectory", deploymentRepository );
+        setFieldValue( "baseUrl", baseUrl );
+        setFieldValue( "numberOfAllowedBuildsinParallel", numberBuildParallel );
+        setFieldValue( "sharedSecretPassword", SHARED_SECRET );
+        if ( distributed )
+        {
+            checkField( "distributedBuildEnabled" );
+        }
+        else
+        {
+            uncheckField( "distributedBuildEnabled" );
+        }
+        submit();
+        if ( success )
+        {
+            assertEditedConfigurationPage( working, buildOutput, releaseOutput, deploymentRepository, baseUrl,
+                                           numberBuildParallel );
+        }
+        else
+        {
+            assertEditConfigurationPage();
+        }
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/DistributedBuildTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/DistributedBuildTest.java
new file mode 100644
index 0000000..2400f60
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/DistributedBuildTest.java
@@ -0,0 +1,257 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 org.apache.continuum.web.test.parent.AbstractAdminTest;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * Based on AddMavenTwoProjectTest of Emmanuel Venisse test.
+ *
+ * @author José Morales Martínez
+ * @version $Id$
+ */
+@Test( groups = {"distributed"} )
+public class DistributedBuildTest
+    extends AbstractAdminTest
+{
+    private String projectGroupName;
+
+    private String projectGroupId;
+
+    private String projectGroupDescription;
+
+    private String pomUrl;
+
+    private String pomUsername;
+
+    private String pomPassword;
+
+    private String projectName;
+
+    private String buildEnvName;
+
+    private String buildAgentGroupName;
+
+    private String newBuildEnv;
+
+    @BeforeMethod
+    public void setUp()
+    {
+        enableDistributedBuilds();
+
+        addBuildAgent( buildAgentUrl );
+
+        projectGroupName = getProperty( "DISTRIBUTED_PROJECT_GROUP_NAME" );
+        projectGroupId = getProperty( "DISTRIBUTED_PROJECT_GROUP_ID" );
+        projectGroupDescription = getProperty( "DISTRIBUTED_PROJECT_GROUP_DESCRIPTION" );
+
+        addProjectGroup( projectGroupName, projectGroupId, projectGroupDescription, true, false );
+
+        pomUrl = getProperty( "MAVEN2_POM_URL" );
+        pomUsername = getProperty( "MAVEN2_POM_USERNAME" );
+        pomPassword = getProperty( "MAVEN2_POM_PASSWORD" );
+        projectName = getProperty( "MAVEN2_POM_PROJECT_NAME" );
+
+        buildAgentGroupName = getProperty( "DISTRIBUTED_BUILD_AGENT_GROUP_NAME" );
+        buildEnvName = getProperty( "DISTRIBUTED_BUILD_ENV_NAME" );
+        newBuildEnv = getProperty( "DISTRIBUTED_DUPLICATE_BUILD_ENV" );
+    }
+
+    @AfterMethod
+    public void tearDown()
+        throws Throwable
+    {
+        removeProjectGroup( projectGroupName, false );
+
+        removeBuildEnvironment( buildEnvName, false );
+
+        removeBuildEnvironment( newBuildEnv, false );
+
+        removeBuildAgentGroup( buildAgentGroupName, false );
+
+        disableDistributedBuilds();
+    }
+
+    public void testBuildProjectGroupNoBuildAgentConfigured()
+        throws Exception
+    {
+        goToBuildAgentPage();
+        removeBuildAgent( buildAgentUrl, false );
+
+        addMavenTwoProject( pomUrl, pomUsername, pomPassword, projectGroupName, true );
+        goToProjectGroupsSummaryPage();
+        assertLinkPresent( projectGroupName );
+        clickLinkWithText( projectGroupName );
+
+        assertPage( "Continuum - Project Group" );
+
+        clickButtonWithValue( "Build all projects" );
+
+        assertTextPresent( "Unable to build projects because no build agent is configured" );
+    }
+
+    public void testProjectGroupAllBuildSuccessWithDistributedBuilds()
+        throws Exception
+    {
+        addMavenTwoProject( pomUrl, pomUsername, pomPassword, projectGroupName, true );
+
+        buildProjectGroup( projectGroupName, projectGroupId, projectGroupDescription, projectName, true );
+    }
+
+    public void testBuildMaven2ProjectWithTagDistributedBuild()
+        throws Exception
+    {
+        String pomUrl = getProperty( "MAVEN2_PROJECT_WITH_TAG_POM_URL" );
+        String pomUsername = "";
+        String pomPassword = "";
+        String projectName = getProperty( "MAVEN2_PROJECT_WITH_TAG_POM_PROJECT_NAME" );
+
+        addMavenTwoProject( pomUrl, pomUsername, pomPassword, projectGroupName, true );
+        assertProjectGroupSummaryPage( projectGroupName, projectGroupId, projectGroupDescription );
+
+        buildProjectGroup( projectGroupName, projectGroupId, projectGroupDescription, projectName, true );
+    }
+
+    public void testBuildShellProjectWithDistributedBuildsEnabled()
+        throws Exception
+    {
+        String projectName = getProperty( "SHELL_PROJECT_NAME" );
+        String projectDescription = getProperty( "SHELL_PROJECT_DESCRIPTION" );
+        String projectVersion = getProperty( "SHELL_PROJECT_VERSION" );
+        String projectTag = getProperty( "SHELL_PROJECT_TAG" );
+        String projectScmUrl = getProperty( "SHELL_PROJECT_SCM_URL" );
+        String projectScmUsername = getProperty( "SHELL_PROJECT_SCM_USERNAME" );
+        String projectScmPassword = getProperty( "SHELL_PROJECT_SCM_PASSWORD" );
+
+        goToAddShellProjectPage();
+        addProject( projectName, projectDescription, projectVersion, projectScmUrl, projectScmUsername,
+                    projectScmPassword, projectTag, projectGroupName, true, "shell" );
+        assertProjectGroupSummaryPage( projectGroupName, projectGroupId, projectGroupDescription );
+
+        goToProjectGroupsSummaryPage();
+        clickLinkWithText( projectGroupName );
+        clickLinkWithText( "Build Definitions" );
+        clickLinkWithXPath( "//table[@id='ec_table']/tbody/tr/td[14]/a/img" );
+
+        editBuildDefinitionShellType();
+
+        buildProjectGroup( projectGroupName, projectGroupId, projectGroupDescription, projectName, true );
+    }
+
+    public void testQueuePageWithProjectCurrentlyBuildingInDistributedBuilds()
+        throws Exception
+    {
+        String pomUrl = getProperty( "MAVEN2_QUEUE_TEST_POM_URL" );
+        String pomUsername = getProperty( "MAVEN2_QUEUE_TEST_POM_USERNAME" );
+        String pomPassword = getProperty( "MAVEN2_QUEUE_TEST_POM_PASSWORD" );
+
+        goToAddMavenTwoProjectPage();
+        addMavenTwoProject( pomUrl, pomUsername, pomPassword, projectGroupName, true );
+
+        buildProjectForQueuePageTest( projectGroupName, projectGroupId, projectGroupDescription );
+
+        //check queue page while building
+        getSelenium().open( baseUrl + "/admin/displayQueues.action" );
+        assertPage( "Continuum - View Distributed Builds" );
+        assertTextPresent( "Current Build" );
+        assertTextPresent( "Build Queue" );
+        assertTextPresent( "Current Prepare Build" );
+        assertTextPresent( "Prepare Build Queue" );
+        assertTextPresent( projectGroupName );
+        assertTextPresent( "Build Agent URL" );
+    }
+
+    public void testAddBuildEnvironmentWithBuildAgentGroup()
+    {
+        addBuildAgentGroupAndEnvironment( new String[]{buildAgentUrl} );
+    }
+
+    public void testProjectGroupNoBuildAgentConfiguredInBuildAgentGroup()
+        throws Exception
+    {
+        addBuildAgentGroupAndEnvironment( new String[]{} );
+
+        addMavenTwoProject( pomUrl, pomUsername, pomPassword, projectGroupName, true );
+
+        goToGroupBuildDefinitionPage( projectGroupName, projectGroupId, projectGroupDescription );
+        clickImgWithAlt( "Edit" );
+        assertAddEditBuildDefinitionPage( MAVEN_PROJECT_TYPE );
+        selectValue( "profileId", buildEnvName );
+        submit();
+        assertGroupBuildDefinitionPage( projectGroupName );
+
+        clickLinkWithText( "Project Group Summary" );
+        clickButtonWithValue( "Build all projects" );
+
+        assertTextPresent( "Unable to build projects because no build agent is configured in the build agent group" );
+    }
+
+    public void testEditDuplicatedBuildEnvironmentDistributedBuilds()
+    {
+        addBuildAgentGroupAndEnvironment( new String[]{buildAgentUrl} );
+
+        goToAddBuildEnvironment();
+        addBuildEnvironmentWithBuildAgentGroup( newBuildEnv, new String[]{}, buildAgentGroupName );
+
+        goToEditBuildEnvironment( newBuildEnv );
+        editBuildEnvironmentWithBuildAgentGroup( buildEnvName, new String[]{}, buildAgentGroupName, false );
+        assertTextPresent( "A Build Environment with the same name already exists" );
+    }
+
+    @Test( enabled = false )
+    public void testBuildSuccessWithDistributedBuildsAfterDisableEnableOfBuildAgent()
+        throws Exception
+    {
+        addMavenTwoProject( pomUrl, pomUsername, pomPassword, projectGroupName, true );
+
+        // disable then enable build agent
+        goToBuildAgentPage();
+        clickImgWithAlt( "Edit" );
+        enableDisableBuildAgent( buildAgentUrl, false );
+        clickImgWithAlt( "Edit" );
+        enableDisableBuildAgent( buildAgentUrl, true );
+
+        buildProjectGroup( projectGroupName, projectGroupId, projectGroupDescription, projectName, true );
+    }
+
+    private void addBuildAgentGroupAndEnvironment( String[] buildAgents )
+    {
+        // create build agent group
+        goToAddBuildAgentGroup();
+        addEditBuildAgentGroup( buildAgentGroupName, buildAgents, new String[]{}, true );
+
+        goToAddBuildEnvironment();
+        addBuildEnvironmentWithBuildAgentGroup( buildEnvName, new String[]{}, buildAgentGroupName );
+    }
+
+    private void editBuildDefinitionShellType()
+    {
+        setFieldValue( "buildFile", isWindows() ? "build.bat" : "build.sh" );
+        setFieldValue( "arguments", "" );
+        setFieldValue( "description", "description" );
+        setFieldValue( "buildDefinitionType", "shell" );
+        checkField( "alwaysBuild" );
+
+        submit();
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/DistributedReleaseTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/DistributedReleaseTest.java
new file mode 100644
index 0000000..8517e1a
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/DistributedReleaseTest.java
@@ -0,0 +1,461 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 org.apache.commons.io.IOUtils;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Optional;
+import org.testng.annotations.Parameters;
+import org.testng.annotations.Test;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.Arrays;
+
+@Test( groups = {"distributedRelease"} )
+public class DistributedReleaseTest
+    extends AbstractReleaseTest
+{
+    private static final String RELEASE_BUTTON_TEXT = "Release";
+
+    private static final String PROVIDE_RELEASE_PARAMETERS_TEXT = "Provide Release Parameters";
+
+    private String appserverBase;
+
+    private String projectGroupName;
+
+    private String projectGroupId;
+
+    private String releaseBuildEnvironment;
+
+    private String releaseBuildAgentGroup;
+
+    private String tagBase;
+
+    private String tag;
+
+    private String releaseVersion;
+
+    private String developmentVersion;
+
+    private String errorMessageNoAgent;
+
+    private String releaseProjectScmUrl;
+
+    @BeforeClass
+    @Parameters( { "appserverBase" } )
+    public void createAndBuildProject( @Optional( "target" ) String appserverBase )
+    {
+        this.appserverBase = appserverBase;
+
+        projectGroupName = getProperty( "DIST_RELEASE_PROJECT_GROUP_NAME" );
+        projectGroupId = getProperty( "DIST_RELEASE_PROJECT_GROUP_ID" );
+        String description = "Distributed Release test projects";
+
+        loginAsAdmin();
+
+        enableDistributedBuilds();
+
+        addBuildAgent( buildAgentUrl );
+
+        String pomUrl = getProperty( "MAVEN2_POM_URL" );
+        String pomUsername = getProperty( "MAVEN2_POM_USERNAME" );
+        String pomPassword = getProperty( "MAVEN2_POM_PASSWORD" );
+        String projectName = getProperty( "MAVEN2_POM_PROJECT_NAME" );
+
+        removeProjectGroup( projectGroupName, false );
+
+        addProjectGroup( projectGroupName, projectGroupId, description, true );
+        clickLinkWithText( projectGroupName );
+
+        if ( !isLinkPresent( projectName ) )
+        {
+            addMavenTwoProject( pomUrl, pomUsername, pomPassword, projectGroupName, true );
+
+            buildProjectGroup( projectGroupName, projectGroupId, "", projectName, true );
+        }
+    }
+
+    @BeforeMethod
+    public void setUp()
+        throws IOException
+    {
+        releaseBuildEnvironment = getProperty( "DIST_RELEASE_BUILD_ENV" );
+        releaseBuildAgentGroup = getProperty( "DIST_RELEASE_BUILD_AGENT_GROUP" );
+        errorMessageNoAgent = getProperty( "DIST_RELEASE_NO_AGENT_MESSAGE" );
+
+        tagBase = getProperty( "DIST_RELEASE_PROJECT_TAGBASE" );
+        tag = getProperty( "DIST_RELEASE_PROJECT_TAG" );
+        releaseVersion = getProperty( "DIST_RELEASE_PROJECT_VERSION" );
+        developmentVersion = getProperty( "DIST_RELEASE_PROJECT_DEVELOPMENT_VERSION" );
+        releaseProjectScmUrl = getProperty( "DIST_RELEASE_PROJECT_SCM_URL" );
+
+        File file = getPreparedReleasesFile();
+
+        if ( file.exists() && !file.delete() )
+        {
+            throw new IOException( "Unable to delete existing prepared-releases.xml file" );
+        }
+
+        enableDistributedBuilds();
+
+        addBuildAgent( buildAgentUrl );
+
+        createBuildEnvAndBuildagentGroup( releaseBuildEnvironment, releaseBuildAgentGroup );
+    }
+
+    @AfterMethod
+    public void tearDown()
+        throws Exception
+    {
+        removeBuildagentGroupFromBuildEnv( releaseBuildAgentGroup );
+
+        removeBuildAgentGroup( releaseBuildAgentGroup );
+
+        // enable agent if disabled
+        goToBuildAgentPage();
+        clickImgWithAlt( "Edit" );
+        enableDisableBuildAgent( buildAgentUrl, true );
+
+        disableDistributedBuilds();
+    }
+
+    public void testDistributedReleasePrepareWithoutInterveningPerform()
+        throws IOException
+    {
+        // CONTINUUM-2687
+        showProjectGroup( projectGroupName, projectGroupId, "" );
+        clickButtonWithValue( RELEASE_BUTTON_TEXT );
+        assertReleaseChoicePage();
+
+        // first attempt
+        releasePrepareProject( "", "", tagBase, "simple-example-1.1", "1.1", "1.2-SNAPSHOT", releaseBuildEnvironment );
+        assertReleasePhaseSuccess();
+        clickButtonWithValue( "Done" );
+
+        // second attempt
+        releasePrepareProject( "", "", tagBase, "simple-example-1.2", "1.2", "1.3-SNAPSHOT", releaseBuildEnvironment );
+        assertReleasePhaseSuccess();
+        clickButtonWithValue( "Done" );
+
+        // check prepared releases content (timestamp version)
+        String str = getPreparedReleasesContent();
+        Assert.assertTrue( str.contains( "<releaseId>org.apache.continuum.examples.simple:simple-example:" ) );
+
+        // check that two versions are present
+        Assert.assertEquals( Arrays.asList( getSelenium().getSelectOptions( "preparedReleaseId" ) ), Arrays.asList(
+            "1.1", "1.2", PROVIDE_RELEASE_PARAMETERS_TEXT ) );
+
+        // check that 1.2 is selected by default
+        Assert.assertEquals( getSelenium().getSelectedLabel( "preparedReleaseId" ), "1.2" );
+
+        // test perform on 1.2
+        selectPerformAndSubmit();
+
+        setFieldValue( "goals", "clean validate" );
+        submit();
+
+        waitForRelease();
+
+        assertReleasePhaseSuccess();
+        clickButtonWithValue( "Done" );
+
+        // verify that it is removed from the list again
+        showProjectGroup( projectGroupName, projectGroupId, "" );
+        clickButtonWithValue( RELEASE_BUTTON_TEXT );
+        assertReleaseChoicePage();
+        Assert.assertEquals( Arrays.asList( getSelenium().getSelectOptions( "preparedReleaseId" ) ), Arrays.asList(
+            "1.1", PROVIDE_RELEASE_PARAMETERS_TEXT ) );
+        Assert.assertEquals( getSelenium().getSelectedLabel( "preparedReleaseId" ), "1.1" );
+    }
+
+    public void testReleasePrepareWhenAgentGoesDown()
+        throws IOException
+    {
+        // CONTINUUM-2686
+        showProjectGroup( projectGroupName, projectGroupId, "" );
+        clickButtonWithValue( RELEASE_BUTTON_TEXT );
+        assertReleaseChoicePage();
+
+        releasePrepareProject( "", "", tagBase, "simple-example-2.0", "2.0", "2.1-SNAPSHOT", releaseBuildEnvironment );
+        assertReleasePhaseSuccess();
+
+        // disable agent
+        goToBuildAgentPage();
+        clickImgWithAlt( "Edit" );
+        enableDisableBuildAgent( buildAgentUrl, false );
+
+        // check prepared releases content
+        String str = getPreparedReleasesContent();
+        Assert.assertTrue( str.contains( "<releaseId>org.apache.continuum.examples.simple:simple-example" ) );
+
+        // go back to release page
+        showProjectGroup( projectGroupName, projectGroupId, "" );
+        clickButtonWithValue( RELEASE_BUTTON_TEXT );
+        assertReleaseChoicePage();
+
+        // check that the version is present
+        Assert.assertEquals( Arrays.asList( getSelenium().getSelectOptions( "preparedReleaseId" ) ), Arrays.asList(
+            "2.0", PROVIDE_RELEASE_PARAMETERS_TEXT ) );
+    }
+
+    // can't test u/p locally and don't have a suitable SVN server to test against
+    @Test( enabled = false )
+    public void testReleasePrepareProjectWithInvalidUsernamePasswordInDistributedBuilds()
+        throws Exception
+    {
+        String releaseUsername = "invalid";
+        String releasePassword = "invalid";
+
+        showProjectGroup( projectGroupName, projectGroupId, "" );
+        clickButtonWithValue( RELEASE_BUTTON_TEXT );
+        assertReleaseChoicePage();
+        releasePrepareProject( releaseUsername, releasePassword, tagBase, "simple-example-3.0", "3.0", "3.1-SNAPSHOT",
+                               releaseBuildEnvironment );
+        assertReleasePhaseError();
+        assertPreparedReleasesFileContainsBuildAgent();
+    }
+
+    /*
+     * Test release prepare with no build agent configured in the selected build environment.
+     */
+    public void testReleasePrepareProjectWithNoBuildagentInBuildEnvironment()
+        throws Exception
+    {
+        detachBuildagentFromGroup( releaseBuildAgentGroup );
+
+        showProjectGroup( projectGroupName, projectGroupId, projectGroupId );
+
+        clickButtonWithValue( RELEASE_BUTTON_TEXT );
+        assertReleaseChoicePage();
+        releasePrepareProject( "", "", tagBase, tag, releaseVersion, developmentVersion, releaseBuildEnvironment );
+
+        assertReleaseError();
+
+        assertTextPresent( errorMessageNoAgent );
+    }
+
+    /*
+    * Test release prepare with no build agent group in the selected build environment.
+    */
+    public void testReleasePrepareProjectWithNoBuildagentGroupInBuildEnvironment()
+        throws Exception
+    {
+        removeBuildagentGroupFromBuildEnv( releaseBuildEnvironment );
+
+        showProjectGroup( projectGroupName, projectGroupId, projectGroupId );
+
+        clickButtonWithValue( RELEASE_BUTTON_TEXT );
+        assertReleaseChoicePage();
+        releasePrepareProject( "", "", tagBase, tag, releaseVersion, developmentVersion, releaseBuildEnvironment );
+
+        assertReleaseError();
+
+        assertTextPresent( errorMessageNoAgent );
+    }
+
+    /*
+    * Test release prepare with no build environment selected.
+    */
+    public void testReleasePrepareProjectWithNoBuildEnvironment()
+        throws Exception
+    {
+        showProjectGroup( projectGroupName, projectGroupId, projectGroupId );
+
+        clickButtonWithValue( RELEASE_BUTTON_TEXT );
+        assertReleaseChoicePage();
+        releasePrepareProject( "", "", tagBase, tag, releaseVersion, developmentVersion, "" );
+
+        assertReleasePhaseSuccess();
+        clickButtonWithValue( "Done" );
+
+        assertPreparedReleasesFileContainsBuildAgent();
+
+        // test subsequent perform
+        selectPerformAndSubmit();
+
+        setFieldValue( "goals", "clean validate" );
+        submit();
+
+        waitForRelease();
+
+        assertReleasePhaseSuccess();
+    }
+
+    @Test( dependsOnMethods = {"testReleasePrepareProjectWithNoBuildEnvironment"} )
+    public void testReleasePerformUsingProvidedParametersWithDistributedBuilds()
+        throws Exception
+    {
+        String releaseUsername = "invalid";
+        String releasePassword = "invalid";
+
+        showProjectGroup( projectGroupName, projectGroupId, "" );
+        clickButtonWithValue( RELEASE_BUTTON_TEXT );
+        assertReleaseChoicePage();
+        releasePerformProjectWithProvideParameters( releaseUsername, releasePassword, tagBase, tag,
+                                                    releaseProjectScmUrl, releaseBuildEnvironment );
+        assertPreparedReleasesFileContainsBuildAgent();
+    }
+
+    @Test( dependsOnMethods = {"testReleasePrepareProjectWithNoBuildEnvironment"} )
+    public void testReleasePerformUsingProvidedParametersWithNoBuildEnvironment()
+        throws Exception
+    {
+        String releaseUsername = "invalid";
+        String releasePassword = "invalid";
+
+        showProjectGroup( projectGroupName, projectGroupId, "" );
+        clickButtonWithValue( RELEASE_BUTTON_TEXT );
+        assertReleaseChoicePage();
+        releasePerformProjectWithProvideParameters( releaseUsername, releasePassword, tagBase, tag,
+                                                    releaseProjectScmUrl, "" );
+        assertPreparedReleasesFileContainsBuildAgent();
+    }
+
+    private void createBuildEnvAndBuildagentGroup( String projectBuildEnv, String projectAgentGroup )
+    {
+        // add build agent group no agents
+        goToBuildAgentPage();
+        if ( !isTextPresent( projectAgentGroup ) )
+        {
+            clickAndWait( "//input[@id='editBuildAgentGroup_0']" );
+            setFieldValue( "saveBuildAgentGroup_buildAgentGroup_name", projectAgentGroup );
+            clickButtonWithValue( "Save" );
+        }
+
+        // add build environment with build agent group
+        clickLinkWithText( "Build Environments" );
+        if ( !isTextPresent( projectBuildEnv ) )
+        {
+            clickAndWait( "//input[@id='addBuildEnv_0']" );
+            setFieldValue( "saveBuildEnv_profile_name", projectBuildEnv );
+            clickButtonWithValue( "Save" );
+        }
+
+        attachBuildagentGroupToBuildEnv( releaseBuildEnvironment, releaseBuildAgentGroup );
+
+        // attach build agent in build agent group created
+        attachBuildagentInGroup( releaseBuildAgentGroup );
+    }
+
+    private void attachBuildagentGroupToBuildEnv( String projectBuildEnv, String projectAgentGroup )
+    {
+        clickLinkWithText( "Build Environments" );
+        String xPath = "//preceding::td[text()='" + projectBuildEnv + "']//following::img[@alt='Edit']";
+        clickLinkWithXPath( xPath );
+        selectValue( "profile.buildAgentGroup", projectAgentGroup );
+        clickButtonWithValue( "Save" );
+    }
+
+    private void removeBuildagentGroupFromBuildEnv( String projectBuildEnv )
+    {
+        clickLinkWithText( "Build Environments" );
+        String xPath = "//preceding::td[text()='" + projectBuildEnv + "']//following::img[@alt='Edit']";
+        if ( isElementPresent( "xpath=" + xPath ) )
+        {
+            clickLinkWithXPath( xPath );
+            selectValue( "profile.buildAgentGroup", "" );
+            clickButtonWithValue( "Save" );
+        }
+    }
+
+    private void attachBuildagentInGroup( String projectAgentGroup )
+    {
+        String buildAgent = buildAgentUrl;
+
+        clickLinkWithText( "Build Agents" );
+        String xPath = "//preceding::td[text()='" + projectAgentGroup + "']//following::img[@alt='Edit']";
+        clickLinkWithXPath( xPath );
+
+        if ( isElementPresent(
+            "xpath=//select[@id='saveBuildAgentGroup_buildAgentIds']/option[@value='" + buildAgent + "']" ) )
+        {
+            selectValue( "buildAgentIds", buildAgent );
+            clickLinkWithXPath( "//input[@value='->']", false );
+            submit();
+        }
+    }
+
+    private void detachBuildagentFromGroup( String projectAgentGroup )
+    {
+        String buildAgent = buildAgentUrl;
+
+        clickLinkWithText( "Build Agents" );
+        String xPath = "//preceding::td[text()='" + projectAgentGroup + "']//following::img[@alt='Edit']";
+        clickLinkWithXPath( xPath );
+
+        if ( isElementPresent(
+            "xpath=//select[@id='saveBuildAgentGroup_selectedBuildAgentIds']/option[@value='" + buildAgent + "']" ) )
+        {
+            selectValue( "selectedBuildAgentIds", buildAgent );
+            clickLinkWithXPath( "//input[@value='<-']", false );
+            submit();
+        }
+    }
+
+    private void assertPreparedReleasesFileContainsBuildAgent()
+        throws Exception
+    {
+        String str = getPreparedReleasesContent();
+
+        Assert.assertTrue( str.contains( "<buildAgentUrl>" + buildAgentUrl + "</buildAgentUrl>" ),
+                           "prepared-releases.xml was not populated" );
+    }
+
+    private String getPreparedReleasesContent()
+        throws IOException
+    {
+        File file = getPreparedReleasesFile();
+        Assert.assertTrue( file.exists(), "prepared-releases.xml was not created" );
+
+        FileInputStream fis = null;
+        BufferedReader reader = null;
+
+        try
+        {
+            fis = new FileInputStream( file );
+            reader = new BufferedReader( new InputStreamReader( fis ) );
+
+            String strLine;
+            StringBuilder str = new StringBuilder();
+            while ( ( strLine = reader.readLine() ) != null )
+            {
+                str.append( strLine );
+            }
+            return str.toString();
+        }
+        finally
+        {
+            IOUtils.closeQuietly( reader );
+            IOUtils.closeQuietly( fis );
+        }
+    }
+
+    private File getPreparedReleasesFile()
+    {
+        return new File( appserverBase, "conf/prepared-releases.xml" );
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/InstallationTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/InstallationTest.java
new file mode 100644
index 0000000..632c3db
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/InstallationTest.java
@@ -0,0 +1,223 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 org.apache.continuum.web.test.parent.AbstractInstallationTest;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.util.Arrays;
+
+/**
+ * @author José Morales Martínez
+ * @version $Id$
+ */
+@Test( groups = {"installation"} )
+public class InstallationTest
+    extends AbstractInstallationTest
+{
+    private static final String JDK_VAR_NAME = "JDK";
+
+    private static final String MAVEN_VAR_NAME = "Maven";
+
+    private String jdkName;
+
+    private String jdkPath;
+
+    private String varName;
+
+    private String varVariableName;
+
+    private String varPath;
+
+    private String mavenName;
+
+    private String mavenPath;
+
+    private String varNameNoBE;
+
+    private String varNameOptions;
+
+    @BeforeMethod
+    protected void setUp()
+        throws Exception
+    {
+        jdkName = getProperty( "INSTALL_TOOL_JDK_NAME" );
+        jdkPath = getProperty( "INSTALL_TOOL_JDK_PATH" );
+        varName = getProperty( "INSTALL_VAR_NAME" );
+        varVariableName = getProperty( "INSTALL_VAR_VARIABLE_NAME" );
+        varPath = getProperty( "INSTALL_VAR_PATH" );
+        mavenName = getProperty( "INSTALL_TOOL_MAVEN_NAME" );
+        mavenPath = getProperty( "INSTALL_TOOL_MAVEN_PATH" );
+        varNameNoBE = "var_without_build_environment";
+        varNameOptions = "var_with_options";
+    }
+
+    @AfterClass
+    public void cleanup()
+    {
+        for ( String installation : Arrays.asList( jdkName, varName, mavenName, varNameNoBE, varNameOptions ) )
+        {
+            removeInstallation( installation, false );
+            removeBuildEnvironment( installation, false );
+        }
+    }
+
+    public void testAddJdkToolWithoutBuildEnvironment()
+    {
+        goToAddInstallationTool();
+        addInstallation( jdkName, JDK_VAR_NAME, jdkPath, false, true, true );
+    }
+
+    public void testAddJdkToolWithoutBuildEnvironmentWithInvalidValues()
+    {
+        String jdkName = "!@#$<>?etc";
+        String jdkPath = "!@#$<>?etc";
+        goToAddInstallationTool();
+        addInstallation( jdkName, JDK_VAR_NAME, jdkPath, false, true, false );
+        assertTextPresent( "Installation name contains invalid characters." );
+        assertTextPresent( "Installation value contains invalid characters." );
+    }
+
+    public void testAddMavenToolWithBuildEnvironment()
+    {
+        goToAddInstallationTool();
+        addInstallation( mavenName, MAVEN_VAR_NAME, mavenPath, true, true, true );
+        // TODO: Validate build environment
+
+    }
+
+    public void testAddInstallationVariableWithBuildEnvironment()
+    {
+        goToAddInstallationVariable();
+        addInstallation( varName, varVariableName, varPath, true, false, true );
+        // TODO: Validate build environment
+    }
+
+    public void testAddInstallationVariableWithoutBuildEnvironment()
+    {
+        String varVariableName = "var_name";
+        String varPath = "path";
+        goToAddInstallationVariable();
+        addInstallation( varNameNoBE, varVariableName, varPath, false, false, true );
+    }
+
+    public void testAddInstallationVariableWithOtherOptions()
+    {
+        String varVariableName = "JAVA_OPTS";
+        String varPath = "-XX:+CompressedOops";
+        goToAddInstallationVariable();
+        addInstallation( varNameOptions, varVariableName, varPath, false, false, true );
+    }
+
+    public void testAddInstallationVariableWithoutBuildEnvironmentWithInvalidValues()
+    {
+        String varName = "!@#$<>?etc";
+        String varVariableName = "!@#$<>?etc";
+        String varPath = "!@#$<>?etc";
+        goToAddInstallationVariable();
+        addInstallation( varName, varVariableName, varPath, false, false, false );
+        assertTextPresent( "Installation name contains invalid characters." );
+        assertTextPresent( "Environment variable name contains invalid characters." );
+        assertTextPresent( "Installation value contains invalid characters." );
+    }
+
+    public void testAddInvalidInstallationTool()
+    {
+        goToAddInstallationTool();
+        addInstallation( "", JDK_VAR_NAME, "", false, true, false );
+        assertTextPresent( "You must define a name" );
+        assertTextPresent( "You must define a value" );
+    }
+
+    public void testAddInvalidPathInstallationTool()
+    {
+        goToAddInstallationTool();
+        addInstallation( "name", JDK_VAR_NAME, "invalid_path", false, true, false );
+        assertTextPresent( "Failed to validate installation, check server log" );
+    }
+
+    public void testAddInvalidInstallationVariable()
+    {
+        goToAddInstallationVariable();
+        addInstallation( "", "", "", false, false, false );
+        assertTextPresent( "You must define a name" );
+        assertTextPresent( "You must define a value" );
+    }
+
+    public void testAddInvalidVarNameInstallationVariable()
+    {
+        goToAddInstallationVariable();
+        addInstallation( "name", "", "path", false, false, false );
+        assertTextPresent( "You must define an environment variable" );
+    }
+
+    @Test( dependsOnMethods = {"testAddJdkToolWithoutBuildEnvironment"} )
+    public void testAddDuplicatedInstallationTool()
+    {
+        goToAddInstallationTool();
+        addInstallation( jdkName, JDK_VAR_NAME, jdkPath, false, true, false );
+        assertTextPresent( "Installation name already exists" );
+
+    }
+
+    @Test( dependsOnMethods = {"testAddInstallationVariableWithBuildEnvironment"} )
+    public void testAddDuplicatedInstallationVariable()
+    {
+        goToAddInstallationVariable();
+        addInstallation( varName, varVariableName, varPath, false, false, false );
+        assertTextPresent( "Installation name already exists" );
+    }
+
+    @Test( dependsOnMethods = {"testAddJdkToolWithoutBuildEnvironment"} )
+    public void testEditInstallationTool()
+    {
+        String newName = "new_name";
+        goToEditInstallation( jdkName, JDK_VAR_NAME, jdkPath, true );
+        editInstallation( newName, JDK_VAR_NAME, jdkPath, true, true );
+        goToEditInstallation( newName, JDK_VAR_NAME, jdkPath, true );
+        editInstallation( jdkName, JDK_VAR_NAME, jdkPath, true, true );
+    }
+
+    @Test( dependsOnMethods = {"testAddInstallationVariableWithBuildEnvironment"} )
+    public void testEditInstallationVariable()
+    {
+        String newName = "new_name";
+        String newVarName = "new_var_name";
+        String newPath = "new_path";
+        goToEditInstallation( varName, varVariableName, varPath, false );
+        editInstallation( newName, newVarName, newPath, false, true );
+        goToEditInstallation( newName, newVarName, newPath, false );
+        editInstallation( varName, varVariableName, varPath, false, true );
+    }
+
+    @Test( dependsOnMethods = {"testEditInstallationTool", "testAddDuplicatedInstallationTool"} )
+    public void testDeleteInstallationTool()
+    {
+        removeInstallation( jdkName, true );
+    }
+
+    @Test( dependsOnMethods = {"testEditInstallationVariable", "testAddDuplicatedInstallationVariable"} )
+    public void testDeleteInstallationVariable()
+    {
+        removeInstallation( varName, true );
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/LocalRepositoriesTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/LocalRepositoriesTest.java
new file mode 100644
index 0000000..f63ef11
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/LocalRepositoriesTest.java
@@ -0,0 +1,107 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 org.apache.continuum.web.test.parent.AbstractLocalRepositoryTest;
+import org.testng.annotations.Test;
+
+/**
+ * @author José Morales Martínez
+ * @version $Id$
+ */
+@Test( groups = {"repository"} )
+public class LocalRepositoriesTest
+    extends AbstractLocalRepositoryTest
+{
+    public void testAddLocalRepository()
+    {
+        String LOCAL_REPOSITORY_NAME = getProperty( "LOCAL_REPOSITORY_NAME" );
+        String LOCAL_REPOSITORY_LOCATION = getProperty( "LOCAL_REPOSITORY_LOCATION" );
+        goToAddLocalRepository();
+        addEditLocalRepository( LOCAL_REPOSITORY_NAME, LOCAL_REPOSITORY_LOCATION, true );
+    }
+
+    public void testAddInvalidLocalRepository()
+    {
+        goToAddLocalRepository();
+        addEditLocalRepository( "", "", false );
+        assertTextPresent( "You must define a name." );
+        assertTextPresent( "You must define a local repository directory." );
+    }
+
+    public void testAddLocalRepositoryWithXSS()
+    {
+        String invalidName = "Repo <script>alert('gotcha')</script> name";
+        String invalidLocation = "/Users/continuum/<script>alert('gotcha')</script>/dir";
+
+        goToAddLocalRepository();
+        addEditLocalRepository( invalidName, invalidLocation, false );
+        assertTextPresent( "Local repository name contains invalid characters." );
+        assertTextPresent( "Local repository location contains invalid characters." );
+    }
+
+    @Test( dependsOnMethods = {"testAddLocalRepository"} )
+    public void testAddDuplicatedLocalRepository()
+    {
+        String LOCAL_REPOSITORY_NAME = getProperty( "LOCAL_REPOSITORY_NAME" );
+        String LOCAL_REPOSITORY_LOCATION = getProperty( "LOCAL_REPOSITORY_LOCATION" );
+        goToAddLocalRepository();
+        addEditLocalRepository( LOCAL_REPOSITORY_NAME, LOCAL_REPOSITORY_LOCATION, false );
+        assertTextPresent( "Local repository name must be unique" );
+        assertTextPresent( "Local repository location must be unique" );
+    }
+
+    @Test( dependsOnMethods = {"testAddDuplicatedLocalRepository"} )
+    public void testAddDuplicateLocalRepositoryWithTrailingWhitespaces()
+    {
+        String duplicateRepositoryName = addTrailingWhitespace( getProperty( "LOCAL_REPOSITORY_NAME" ) );
+        String duplicateRepositoryLocation = addTrailingWhitespace( getProperty( "LOCAL_REPOSITORY_LOCATION" ) );
+        goToAddLocalRepository();
+        addEditLocalRepository( duplicateRepositoryName, duplicateRepositoryLocation, false );
+        assertTextPresent( "Local repository name must be unique" );
+        assertTextPresent( "Local repository location must be unique" );
+    }
+
+    @Test( dependsOnMethods = {"testAddDuplicateLocalRepositoryWithTrailingWhitespaces"} )
+    public void testEditLocalRepository()
+    {
+        String LOCAL_REPOSITORY_NAME = getProperty( "LOCAL_REPOSITORY_NAME" );
+        String LOCAL_REPOSITORY_LOCATION = getProperty( "LOCAL_REPOSITORY_LOCATION" );
+        String newName = "new_name";
+        String newLocation = "new_location";
+        goToEditLocalRepository( LOCAL_REPOSITORY_NAME, LOCAL_REPOSITORY_LOCATION );
+        addEditLocalRepository( newName, newLocation, true );
+        goToEditLocalRepository( newName, newLocation );
+        addEditLocalRepository( LOCAL_REPOSITORY_NAME, LOCAL_REPOSITORY_LOCATION, true );
+    }
+
+    @Test( dependsOnMethods = {"testEditLocalRepository"} )
+    public void testDeleteLocalRepository()
+    {
+        String LOCAL_REPOSITORY_NAME = getProperty( "LOCAL_REPOSITORY_NAME" );
+        removeLocalRepository( LOCAL_REPOSITORY_NAME );
+    }
+
+    private String addTrailingWhitespace( String str )
+    {
+        String WHITESPACE = "    ";
+        return WHITESPACE.concat( str.concat( WHITESPACE ) );
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/LoginTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/LoginTest.java
new file mode 100644
index 0000000..abebdf4
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/LoginTest.java
@@ -0,0 +1,85 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 org.apache.continuum.web.test.parent.AbstractContinuumTest;
+import org.testng.annotations.Test;
+
+/*
+ * Bug in TestNG. TESTNG-285: @Test(sequential=true) works incorrectly for classes with inheritance
+ * http://code.google.com/p/testng/source/browse/trunk/CHANGES.txt
+ * Waiting 5.9 release. It's comming soon.
+ */
+
+/**
+ * Based on LoginTest of Emmanuel Venisse test.
+ *
+ * @author José Morales Martínez
+ * @version $Id$
+ */
+@Test( groups = {"login"} )
+public class LoginTest
+    extends AbstractContinuumTest
+{
+    public void testWithBadUsername()
+    {
+        goToLoginPage();
+        getSelenium().type( "loginForm_username", "badUsername" );
+        getSelenium().type( "loginForm_username", getProperty( "ADMIN_PASSWORD" ) );
+        getSelenium().click( "//input[@value='Login']" );
+        getSelenium().waitForPageToLoad( maxWaitTimeInMs );
+        assertTextPresent( "You have entered an incorrect username and/or password" );
+    }
+
+    public void testWithBadPassword()
+    {
+        login( getProperty( "ADMIN_USERNAME" ), "badPassword" );
+        assertTextPresent( "You have entered an incorrect username and/or password" );
+    }
+
+    public void testWithEmptyUsername()
+    {
+        goToLoginPage();
+        getSelenium().type( "loginForm_password", "password" );
+        getSelenium().click( "//input[@value='Login']" );
+        getSelenium().waitForPageToLoad( maxWaitTimeInMs );
+        assertTextPresent( "User Name is required" );
+    }
+
+    public void testWithEmptyPassword()
+    {
+        goToLoginPage();
+        getSelenium().type( "loginForm_username", getProperty( "ADMIN_USERNAME" ) );
+        getSelenium().click( "//input[@value='Login']" );
+        getSelenium().waitForPageToLoad( maxWaitTimeInMs );
+        assertTextPresent( "You have entered an incorrect username and/or password" );
+    }
+
+    public void testWithCorrectUsernamePassword()
+    {
+        String username = getProperty( "ADMIN_USERNAME" );
+        String password = getProperty( "ADMIN_PASSWORD" );
+        login( username, password );
+        assertTextPresent( "Edit Details" );
+        assertTextPresent( "Logout" );
+        assertTextPresent( username );
+    }
+
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/MavenOneProjectTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/MavenOneProjectTest.java
new file mode 100644
index 0000000..2ab55d3
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/MavenOneProjectTest.java
@@ -0,0 +1,241 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 org.apache.continuum.web.test.parent.AbstractAdminTest;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * Based on AddMavenOneProjectTestCase of Emmanuel Venisse.
+ *
+ * @author José Morales Martínez
+ * @version $Id$
+ */
+@Test( groups = {"mavenOneProject"} )
+public class MavenOneProjectTest
+    extends AbstractAdminTest
+{
+    private String pomUrl;
+
+    private String pomUsername;
+
+    private String projectGroupId;
+
+    private String projectGroupDescription;
+
+    private String projectGroupName;
+
+    private String pomPassword;
+
+    private String pomUrlMissingElement;
+
+    private String pomUrlWithExtend;
+
+    private String pomUrlUnparseableContent;
+
+    private String malformedPomUrl;
+
+    private String inaccessiblePomUrl;
+
+    @BeforeMethod
+    protected void setUp()
+        throws Exception
+    {
+        pomUrl = getProperty( "MAVEN1_POM_URL" );
+        pomUsername = getProperty( "MAVEN1_POM_USERNAME" );
+        pomPassword = getProperty( "MAVEN1_POM_PASSWORD" );
+        projectGroupName = getProperty( "MAVEN1_PROJECT_GROUP_NAME" );
+        projectGroupId = getProperty( "MAVEN1_PROJECT_GROUP_ID" );
+        projectGroupDescription = getProperty( "MAVEN1_PROJECT_GROUP_DESCRIPTION" );
+
+        pomUrlMissingElement = getProperty( "MAVEN1_MISSING_REPO_POM_URL" );
+        pomUrlWithExtend = getProperty( "MAVEN1_EXTENDED_POM_URL" );
+        pomUrlUnparseableContent = getProperty( "MAVEN1_UNPARSEABLE_POM_URL" );
+
+        malformedPomUrl = "aaa";
+        inaccessiblePomUrl = baseUrl + "/inaccessible-pom/";
+    }
+
+    @AfterMethod
+    protected void tearDown()
+    {
+        removeProjectGroup( projectGroupName, false );
+    }
+
+    public void testAddMavenOneProjectToProjectGroup()
+        throws Exception
+    {
+        goToProjectGroupsSummaryPage();
+        String defaultProjectGroupName = getProperty( "DEFAULT_PROJECT_GROUP_NAME" );
+        clickLinkWithText( defaultProjectGroupName );
+        selectValue( "preferredExecutor", "Add M1 Project" );
+        clickButtonWithValue( "Add" );
+        assertAddMavenOneProjectPage( defaultProjectGroupName );
+        // rest is tested by other methods
+    }
+
+    public void testAddMavenOneProjectWithNoDefaultBuildDefinitionFromTemplate()
+        throws Exception
+    {
+        removeDefaultBuildDefinitionFromTemplate( "maven1" );
+
+        goToAddMavenOneProjectPage();
+        addMavenOneProject( pomUrl, pomUsername, pomPassword, null, true );
+        assertProjectGroupSummaryPage( projectGroupName, projectGroupId, projectGroupDescription );
+
+        // Re-add default build definition of template
+        addDefaultBuildDefinitionFromTemplate( "maven1" );
+    }
+
+    /**
+     * test with valid pom url
+     */
+    public void testValidPomUrl()
+        throws Exception
+    {
+        // Enter values into Add Maven Two Project fields, and submit
+        goToAddMavenOneProjectPage();
+        addMavenOneProject( pomUrl, pomUsername, pomPassword, null, true );
+        assertProjectGroupSummaryPage( projectGroupName, projectGroupId, projectGroupDescription );
+    }
+
+    /**
+     * test with no pom file or pom url specified
+     */
+    public void testNoPomSpecified()
+        throws Exception
+    {
+        goToAddMavenOneProjectPage();
+        addMavenOneProject( "", "", "", null, false );
+        assertTextPresent( "Either POM URL or Upload POM is required." );
+    }
+
+    /**
+     * test with missing <repository> element in the pom file
+     */
+    public void testMissingElementInPom()
+        throws Exception
+    {
+        goToAddMavenOneProjectPage();
+        addMavenOneProject( pomUrlMissingElement, pomUsername, pomPassword, null, false );
+        assertTextPresent( "Missing 'repository' element in the POM." );
+    }
+
+    /**
+     * test with <extend> element present in pom file
+     */
+    public void testWithExtendElementPom()
+        throws Exception
+    {
+        goToAddMavenOneProjectPage();
+        addMavenOneProject( pomUrlWithExtend, pomUsername, pomPassword, null, false );
+        assertTextPresent( "Cannot use a POM with an 'extend' element" );
+    }
+
+    /**
+     * test with unparseable xml content for pom file
+     */
+    public void testUnparseableXmlContent()
+        throws Exception
+    {
+        goToAddMavenOneProjectPage();
+        addMavenOneProject( pomUrlUnparseableContent, pomUsername, pomPassword, null, false );
+        assertTextPresent( "The XML content of the POM can not be parsed." );
+    }
+
+    /**
+     * test with a malformed pom url
+     */
+    public void testMalformedPomUrl()
+        throws Exception
+    {
+        goToAddMavenOneProjectPage();
+        addMavenOneProject( malformedPomUrl, "", "", null, false );
+        assertTextPresent(
+            "The specified resource cannot be accessed. Please try again later or contact your administrator." );
+    }
+
+    /**
+     * test with an inaccessible pom url
+     */
+    public void testInaccessiblePomUrl()
+        throws Exception
+    {
+        goToAddMavenOneProjectPage();
+        addMavenOneProject( inaccessiblePomUrl, "", "", null, false );
+        assertTextPresent(
+            "POM file does not exist. Either the POM you specified or one of its modules does not exist." );
+    }
+
+    /**
+     * test cancel button
+     */
+    public void testCancelButton()
+    {
+        goToAboutPage();
+        goToAddMavenOneProjectPage();
+        clickButtonWithValue( "Cancel" );
+        assertAboutPage();
+    }
+
+    public void testDeleteMavenOneProject()
+        throws Exception
+    {
+        // setup
+        goToProjectGroupsSummaryPage();
+        addMaven1Project( projectGroupName, pomUrl, pomUsername, pomPassword );
+
+        // delete project - delete icon
+        clickLinkWithText( projectGroupName );
+        clickLinkWithXPath( "//tbody/tr['0']/td['10']/a/img[@alt='Delete']" );
+        assertTextPresent( "Delete Continuum Project" );
+        clickButtonWithValue( "Delete" );
+        assertPage( "Continuum - Project Group" );
+        assertLinkNotPresent( projectGroupName );
+    }
+
+    public void testDeleteMavenOneProjects()
+        throws Exception
+    {
+        // setup
+        goToProjectGroupsSummaryPage();
+        addMaven1Project( projectGroupName, pomUrl, pomUsername, pomPassword );
+
+        // delete project - "Delete Project(s)" button
+        clickLinkWithText( projectGroupName );
+        checkField( "//tbody/tr['0']/td['0']/input[@name='selectedProjects']" );
+        clickButtonWithValue( "Delete Project(s)" );
+        assertTextPresent( "Delete Continuum Projects" );
+        clickButtonWithValue( "Delete" );
+        assertPage( "Continuum - Project Group" );
+        assertLinkNotPresent( projectGroupName );
+    }
+
+    private void addMaven1Project( String groupName, String pomUrl, String pomUsername, String pomPassword )
+    {
+        assertLinkNotPresent( groupName );
+        goToAddMavenOneProjectPage();
+        addMavenOneProject( pomUrl, pomUsername, pomPassword, null, true );
+        goToProjectGroupsSummaryPage();
+        assertLinkPresent( groupName );
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/MavenTwoProjectTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/MavenTwoProjectTest.java
new file mode 100644
index 0000000..4de7a14
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/MavenTwoProjectTest.java
@@ -0,0 +1,342 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 org.apache.continuum.web.test.parent.AbstractAdminTest;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * Based on AddMavenTwoProjectTest of Emmanuel Venisse test.
+ *
+ * @author José Morales Martínez
+ * @version $Id$
+ */
+@Test( groups = { "mavenTwoProject" } )
+public class MavenTwoProjectTest
+    extends AbstractAdminTest
+{
+    private String pomUrl;
+
+    private String pomUsername;
+
+    private String pomPassword;
+
+    private String projectGroupName;
+
+    private String projectGroupId;
+
+    private String projectGroupDescription;
+
+    private String projectGroupScmRootUrl;
+
+    private String projectName;
+
+    @BeforeMethod
+    protected void setUp()
+        throws Exception
+    {
+        pomUrl = getProperty( "MAVEN2_POM_URL" );
+        pomUsername = getProperty( "MAVEN2_POM_USERNAME" );
+        pomPassword = getProperty( "MAVEN2_POM_PASSWORD" );
+
+        projectName = getProperty( "MAVEN2_POM_PROJECT_NAME" );
+        projectGroupName = getProperty( "MAVEN2_POM_PROJECT_GROUP_NAME" );
+        projectGroupId = getProperty( "MAVEN2_POM_PROJECT_GROUP_ID" );
+        projectGroupDescription = getProperty( "MAVEN2_POM_PROJECT_GROUP_DESCRIPTION" );
+        projectGroupScmRootUrl = getProperty( "MAVEN2_POM_PROJECT_GROUP_SCM_ROOT_URL" );
+    }
+
+    @AfterMethod
+    public void tearDown()
+    {
+        removeProjectGroup( projectGroupName, false );
+    }
+
+    public void testAddMavenTwoProject()
+        throws Exception
+    {
+        // Enter values into Add Maven Two Project fields, and submit
+        addMavenTwoProject( pomUrl, pomUsername, pomPassword, null, true );
+
+        // Wait Struts Listener
+        assertProjectGroupSummaryPage( projectGroupName, projectGroupId, projectGroupDescription );
+
+        assertTextPresent( projectGroupScmRootUrl );
+    }
+
+    @Test( dependsOnMethods = { "testAddMavenTwoProject" } )
+    public void testEditProjectName()
+         throws Exception
+    {
+        // Create a project to use
+        testAddMavenTwoProject();
+
+        // Navigate to project's edit page
+        clickLinkWithText(projectName);
+        clickButtonWithValue("Edit");
+        assertPage("Continuum - Update Continuum Project");
+
+        // Edit the name of the project and save it
+        String newName = "New Name";
+        setFieldValue("projectSave_name", newName);
+        clickButtonWithValue("Save");
+
+        // Verify that the save succeeded
+        assertPage("Continuum - Continuum Project");
+        assertTextPresent(String.format("Continuum Project \"%s\"", newName));
+    }
+
+    /**
+     * Test flat multi module project with names that start with the same letter
+     */
+    public void testAddMavenTwoProjectModuleNameWithSameLetter()
+        throws Exception
+    {
+        pomUrl = getProperty( "MAVEN2_SAME_LETTER_FLAT_POM_URL" );
+        pomUsername = "";
+        pomPassword = "";
+
+        projectGroupName = getProperty( "MAVEN2_SAME_LETTER_FLAT_PROJECT_GROUP_NAME" );
+        projectGroupId = getProperty( "MAVEN2_SAME_LETTER_FLAT_PROJECT_GROUP_ID" );
+        projectGroupDescription = getProperty( "MAVEN2_SAME_LETTER_FLAT_PROJECT_GROUP_DESCRIPTION" );
+        projectGroupScmRootUrl = getProperty( "MAVEN2_SAME_LETTER_FLAT_PROJECT_GROUP_SCM_ROOT_URL" );
+
+        addMavenTwoProject( pomUrl, pomUsername, pomPassword, null, true );
+
+        assertProjectGroupSummaryPage( projectGroupName, projectGroupId, projectGroupDescription );
+
+        assertTextPresent( projectGroupScmRootUrl );
+    }
+
+    public void testAddMavenTwoProjectFromRemoteSourceToNonDefaultProjectGroup()
+        throws Exception
+    {
+        projectGroupName = getProperty( "MAVEN2_NON_DEFAULT_PROJECT_GROUP_NAME" );
+        projectGroupId = getProperty( "MAVEN2_NON_DEFAULT_PROJECT_GROUP_ID" );
+        projectGroupDescription = getProperty( "MAVEN2_NON_DEFAULT_PROJECT_GROUP_DESCRIPTION" );
+
+        addProjectGroup( projectGroupName, projectGroupId, projectGroupDescription, true );
+
+        addMavenTwoProject( pomUrl, pomUsername, pomPassword, projectGroupName, true );
+
+        assertProjectGroupSummaryPage( projectGroupName, projectGroupId, projectGroupDescription );
+
+        assertTextPresent( projectGroupScmRootUrl );
+    }
+
+    public void testMoveProject()
+        throws Exception
+    {
+        addMavenTwoProject( pomUrl, pomUsername, pomPassword, null, true );
+        assertProjectGroupSummaryPage( projectGroupName, projectGroupId, projectGroupDescription );
+        assertTextPresent( projectGroupScmRootUrl );
+
+        String targetGroupName = getProperty( "MAVEN2_MOVE_PROJECT_TARGET_PROJECT_GROUP_NAME" );
+        String targetGroupId = getProperty( "MAVEN2_MOVE_PROJECT_TARGET_PROJECT_GROUP_ID" );
+        String targetGroupDescription = getProperty( "MAVEN2_MOVE_PROJECT_TARGET_PROJECT_GROUP_DESCRIPTION" );
+        addProjectGroup( targetGroupName, targetGroupId, targetGroupDescription, true );
+
+        try {
+            // Move the project
+            moveProjectToProjectGroup( projectGroupName, projectGroupId, projectGroupDescription, projectName,
+                                       targetGroupName );
+            showProjectGroup( targetGroupName, targetGroupId, targetGroupDescription );
+            assertTextPresent( "Member Projects" );
+            assertTextPresent( projectName );
+
+            showProjectGroup( projectGroupName, projectGroupId, projectGroupDescription );
+            assertTextNotPresent( "Member Projects" );
+        } finally {
+            removeProjectGroup( targetGroupName, false );
+        }
+    }
+
+    /**
+     * Test invalid pom url
+     */
+    public void testNoPomSpecified()
+        throws Exception
+    {
+        submitAddMavenTwoProjectPage( "" );
+        assertTextPresent( "Either POM URL or Upload POM is required." );
+    }
+
+    /**
+     * Test when scm element is missing from pom
+     */
+    public void testMissingScmElementPom()
+        throws Exception
+    {
+        String pomUrl = getProperty( "MAVEN2_NO_SCM_POM_URL" );
+        submitAddMavenTwoProjectPage( pomUrl );
+        assertTextPresent( "Missing ''scm'' element in the POM, project Maven Two Project" );
+    }
+
+    /**
+     * test with a malformed pom url
+     */
+    public void testMalformedPomUrl()
+        throws Exception
+    {
+        String pomUrl = "aaa";
+        submitAddMavenTwoProjectPage( pomUrl );
+        assertTextPresent(
+            "The specified resource cannot be accessed. Please try again later or contact your administrator." );
+    }
+
+    /**
+     * Test when the connection element is missing from the scm tag
+     */
+    public void testMissingConnectionElement()
+        throws Exception
+    {
+        String pomUrl = getProperty( "MAVEN2_MISS_CONNECTION_POM_URL" );
+        submitAddMavenTwoProjectPage( pomUrl );
+        assertTextPresent( "Missing 'connection' sub-element in the 'scm' element in the POM." );
+    }
+
+    /**
+     * test unallowed file protocol
+     */
+    public void testNotAllowedProtocol()
+        throws Exception
+    {
+        String pomUrl = "file:///pom.xml";
+        submitAddMavenTwoProjectPage( pomUrl );
+        assertTextPresent( "The specified resource isn't a file or the protocol used isn't allowed." );
+    }
+
+    /**
+     * Test when the parent pom is missing or not yet added in continuum
+     */
+    public void testMissingParentPom()
+        throws Exception
+    {
+        String pomUrl = getProperty( "MAVEN2_MISS_PARENT_POM_URL" );
+        submitAddMavenTwoProjectPage( pomUrl );
+        assertTextPresent(
+            "Missing artifact trying to build the POM. Check that its parent POM is available or add it first in Continuum." );
+    }
+
+    /**
+     * Test when the modules/subprojects specified in the pom are not found
+     */
+    public void testMissingModules()
+        throws Exception
+    {
+        String pomUrl = getProperty( "MAVEN2_MISS_SUBPRO_POM_URL" );
+        submitAddMavenTwoProjectPage( pomUrl );
+        assertTextPresent( "Unknown error trying to build POM." );
+    }
+
+    /**
+     * test with an inaccessible pom url
+     */
+    public void testInaccessiblePomUrl()
+        throws Exception
+    {
+        String pomUrl = baseUrl + "/inaccessible-pom/";
+        submitAddMavenTwoProjectPage( pomUrl );
+        assertTextPresent(
+            "POM file does not exist. Either the POM you specified or one of its modules does not exist." );
+    }
+
+    /**
+     * test cancel button
+     */
+    public void testCancelButton()
+    {
+        goToAboutPage();
+        goToAddMavenTwoProjectPage();
+        clickButtonWithValue( "Cancel" );
+        assertAboutPage();
+    }
+
+    public void testDeleteMavenTwoProject()
+        throws Exception
+    {
+        goToProjectGroupsSummaryPage();
+
+        addMavenTwoProject( pomUrl, pomUsername, pomPassword, null, true );
+        goToProjectGroupsSummaryPage();
+        assertLinkPresent( projectGroupName );
+        clickLinkWithText( projectGroupName );
+
+        assertPage( "Continuum - Project Group" );
+        assertTextPresent( projectGroupScmRootUrl );
+
+        // wait for project to finish checkout
+        waitForProjectCheckout();
+        waitPage();
+
+        clickLinkWithXPath( "//tbody/tr['0']/td['10']/a/img[@alt='Delete']" );
+        assertTextPresent( "Delete Continuum Project" );
+        clickButtonWithValue( "Delete" );
+        assertPage( "Continuum - Project Group" );
+        assertTextNotPresent( "Unable to delete project" );
+        assertLinkNotPresent( projectGroupName );
+        assertTextNotPresent( projectGroupScmRootUrl );
+    }
+
+    public void testDeleteMavenTwoProjects()
+        throws Exception
+    {
+        goToProjectGroupsSummaryPage();
+
+        addMavenTwoProject( pomUrl, pomUsername, pomPassword, null, true );
+        goToProjectGroupsSummaryPage();
+        assertLinkPresent( projectGroupName );
+        clickLinkWithText( projectGroupName );
+
+        assertPage( "Continuum - Project Group" );
+
+        //wait for project to finish checkout
+        waitForProjectCheckout();
+        waitPage();
+
+        checkField( "//tbody/tr['0']/td['0']/input[@name='selectedProjects']" );
+        clickButtonWithValue( "Delete Project(s)" );
+        assertTextPresent( "Delete Continuum Projects" );
+        clickButtonWithValue( "Delete" );
+        assertPage( "Continuum - Project Group" );
+        assertTextNotPresent( "Unable to delete project" );
+        assertLinkNotPresent( projectGroupName );
+        assertTextNotPresent( projectGroupScmRootUrl );
+    }
+
+    public void testBuildMaven2ProjectWithTag()
+        throws Exception
+    {
+        pomUrl = getProperty( "MAVEN2_PROJECT_WITH_TAG_POM_URL" );
+        pomUsername = "";
+        pomPassword = "";
+
+        projectGroupName = getProperty( "MAVEN2_PROJECT_WITH_TAG_POM_PROJECT_GROUP_NAME" );
+        projectGroupId = getProperty( "MAVEN2_PROJECT_WITH_TAG_POM_PROJECT_GROUP_ID" );
+        projectGroupDescription = getProperty( "MAVEN2_PROJECT_WITH_TAG_POM_PROJECT_GROUP_DESCRIPTION" );
+
+        addMavenTwoProject( pomUrl, pomUsername, pomPassword, null, true );
+        assertProjectGroupSummaryPage( projectGroupName, projectGroupId, projectGroupDescription );
+
+        buildProjectGroup( projectGroupName, projectGroupId, projectGroupDescription, projectGroupName, true );
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/MyAccountTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/MyAccountTest.java
new file mode 100644
index 0000000..8db61fe
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/MyAccountTest.java
@@ -0,0 +1,62 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 org.apache.continuum.web.test.parent.AbstractAdminTest;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * Based on MyAccountTest of Emmanuel Venisse test.
+ *
+ * @author José Morales Martínez
+ * @version $Id$
+ */
+@Test( groups = {"myAccount"} )
+public class MyAccountTest
+    extends AbstractAdminTest
+{
+
+    private static final String NEW_FULL_NAME = "Admin_FullName";
+
+    private static final String NEW_EMAIL = "new_admin@mail.com";
+
+    public void testMyAccountEdit()
+        throws Exception
+    {
+        clickLinkWithText( "Edit Details" );
+        String email = getFieldValue( "user.email" );
+        String fullName = getFieldValue( "user.fullName" );
+        setFieldValue( "user.fullName", NEW_FULL_NAME );
+        setFieldValue( "user.email", NEW_EMAIL );
+        submit();
+        getSelenium().waitForPageToLoad( maxWaitTimeInMs );
+        Assert.assertEquals( "Continuum - Group Summary", getTitle() );
+        clickLinkWithText( "Edit Details" );
+        assertFieldValue( NEW_FULL_NAME, "user.fullName" );
+        assertFieldValue( NEW_EMAIL, "user.email" );
+        setFieldValue( "user.fullName", fullName );
+        setFieldValue( "user.email", email );
+        submit();
+        clickLinkWithText( "Edit Details" );
+        assertFieldValue( fullName, "user.fullName" );
+        assertFieldValue( email, "user.email" );
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/NotifierTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/NotifierTest.java
new file mode 100644
index 0000000..07a983a
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/NotifierTest.java
@@ -0,0 +1,1021 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 org.apache.continuum.web.test.parent.AbstractAdminTest;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * @author José Morales Martínez
+ * @version $Id$
+ */
+@Test( groups = { "notifier" } )
+public class NotifierTest
+    extends AbstractAdminTest
+{
+    private String projectGroupName;
+
+    private String projectGroupId;
+
+    private String projectGroupDescription;
+
+    private String projectName;
+
+    private String mailNotifierAddress;
+
+    private String ircNotifierHost;
+
+    private String ircNotifierChannel;
+
+    private String jabberNotifierHost;
+
+    private String jabberNotifierLogin;
+
+    private String jabberNotifierPassword;
+
+    private String jabberNotifierAddress;
+
+    private String msnNotifierAddress;
+
+    private String msnNotifierLogin;
+
+    private String msnNotifierPassword;
+
+    private String wagonNotifierUrl;
+
+    private String wagonServerId;
+
+    @BeforeClass
+    public void createProject()
+    {
+        projectGroupName = getProperty( "NOTIFIER_PROJECT_GROUP_NAME" );
+        projectGroupId = getProperty( "NOTIFIER_PROJECT_GROUP_ID" );
+        projectGroupDescription = getProperty( "NOTIFIER_PROJECT_GROUP_DESCRIPTION" );
+
+        projectName = getProperty( "MAVEN2_POM_PROJECT_NAME" );
+        String projectPomUrl = getProperty( "MAVEN2_POM_URL" );
+        String pomUsername = getProperty( "MAVEN2_POM_USERNAME" );
+        String pomPassword = getProperty( "MAVEN2_POM_PASSWORD" );
+
+        loginAsAdmin();
+
+        removeProjectGroup( projectGroupName, false );
+
+        addProjectGroup( projectGroupName, projectGroupId, projectGroupDescription, true, true );
+        clickLinkWithText( projectGroupName );
+
+        addMavenTwoProject( projectPomUrl, pomUsername, pomPassword, projectGroupName, true );
+    }
+
+    @BeforeMethod
+    protected void setUp()
+        throws Exception
+    {
+        mailNotifierAddress = getProperty( "MAIL_NOTIFIER_ADDRESS" );
+        ircNotifierHost = getProperty( "IRC_NOTIFIER_HOST" );
+        ircNotifierChannel = getProperty( "IRC_NOTIFIER_CHANNEL" );
+        jabberNotifierHost = getProperty( "JABBER_NOTIFIER_HOST" );
+        jabberNotifierLogin = getProperty( "JABBER_NOTIFIER_LOGIN" );
+        jabberNotifierPassword = getProperty( "JABBER_NOTIFIER_PASSWORD" );
+        jabberNotifierAddress = getProperty( "JABBER_NOTIFIER_ADDRESS" );
+        msnNotifierAddress = getProperty( "MSN_NOTIFIER_ADDRESS" );
+        msnNotifierLogin = getProperty( "MSN_NOTIFIER_LOGIN" );
+        msnNotifierPassword = getProperty( "MSN_NOTIFIER_PASSWORD" );
+        wagonNotifierUrl = getProperty( "WAGON_NOTIFIER_URL" );
+        wagonServerId = getProperty( "WAGON_SERVER_ID" );
+    }
+
+    public void testAddValidMailProjectNotifier()
+        throws Exception
+    {
+        goToProjectNotifier( projectGroupName, projectName );
+        addMailNotifier( projectGroupName, projectName, mailNotifierAddress, true );
+    }
+
+    public void testAddValidMailProjectNotifierWithInvalidValue()
+        throws Exception
+    {
+        String mailNotifierAddress = "<script>alert('xss')</script>";
+        goToProjectNotifier( projectGroupName, projectName );
+        addMailNotifier( projectGroupName, projectName, mailNotifierAddress, false );
+        assertTextPresent( "Address is invalid" );
+    }
+
+    @Test( dependsOnMethods = { "testAddValidMailProjectNotifier" } )
+    public void testEditValidMailProjectNotifier()
+        throws Exception
+    {
+        String newMail = "newmail@mail.com";
+        goToProjectInformationPage( projectGroupName, projectName );
+        editMailNotifier( projectGroupName, projectName, mailNotifierAddress, newMail, true );
+        editMailNotifier( projectGroupName, projectName, newMail, mailNotifierAddress, true );
+    }
+
+    @Test( dependsOnMethods = { "testAddValidMailProjectNotifier" } )
+    public void testEditInvalidMailProjectNotifier()
+        throws Exception
+    {
+        goToProjectInformationPage( projectGroupName, projectName );
+        editMailNotifier( projectGroupName, projectName, mailNotifierAddress, "invalid_email_add", false );
+    }
+
+    public void testAddInvalidMailProjectNotifier()
+        throws Exception
+    {
+        goToProjectNotifier( projectGroupName, projectName );
+        addMailNotifier( projectGroupName, projectName, "invalid_email_add", false );
+    }
+
+    public void testAddValidMailGroupNotifier()
+        throws Exception
+    {
+        goToGroupNotifier( projectGroupName, projectGroupId, projectGroupDescription );
+        addMailNotifier( projectGroupName, null, mailNotifierAddress, true );
+    }
+
+    @Test( dependsOnMethods = { "testAddValidMailGroupNotifier" } )
+    public void testEditValidMailGroupNotifier()
+        throws Exception
+    {
+        String newMail = "newmail@mail.com";
+        showProjectGroup( projectGroupName, projectGroupId, projectGroupDescription );
+        clickLinkWithText( "Notifiers" );
+        assertGroupNotifierPage( projectGroupName );
+        editMailNotifier( projectGroupName, null, mailNotifierAddress, newMail, true );
+        editMailNotifier( projectGroupName, null, newMail, mailNotifierAddress, true );
+    }
+
+    @Test( dependsOnMethods = { "testAddValidMailGroupNotifier" } )
+    public void testEditInvalidMailGroupNotifier()
+        throws Exception
+    {
+        showProjectGroup( projectGroupName, projectGroupId, projectGroupDescription );
+        clickLinkWithText( "Notifiers" );
+        assertGroupNotifierPage( projectGroupName );
+        editMailNotifier( projectGroupName, null, mailNotifierAddress, "invalid_email_add", false );
+    }
+
+    public void testAddInvalidMailGroupNotifier()
+        throws Exception
+    {
+        goToGroupNotifier( projectGroupName, projectGroupId, projectGroupDescription );
+        addMailNotifier( projectGroupName, null, "invalid_email_add", false );
+    }
+
+    public void testAddValidIrcProjectNotifier()
+        throws Exception
+    {
+        goToProjectNotifier( projectGroupName, projectName );
+        addIrcNotifier( projectGroupName, projectName, ircNotifierHost, ircNotifierChannel, true );
+    }
+
+    public void testAddProjectNotifierWithInvalidValues()
+        throws Exception
+    {
+        String ircNotifierHost = "!@#$<>?etc";
+        String ircNotifierChannel = "!@#$<>?etc";
+        goToProjectNotifier( projectGroupName, projectName );
+        addIrcNotifier( projectGroupName, projectName, ircNotifierHost, ircNotifierChannel, false );
+        assertTextPresent( "Host contains invalid character" );
+        assertTextPresent( "Channel contains invalid character" );
+    }
+
+    @Test( dependsOnMethods = { "testAddValidIrcProjectNotifier" } )
+    public void testEditValidIrcProjectNotifier()
+        throws Exception
+    {
+        String newHost = "new.test.com";
+        String newChannel = "new_test_channel";
+        goToProjectInformationPage( projectGroupName, projectName );
+        editIrcNotifier( projectGroupName, projectName, ircNotifierHost, ircNotifierChannel, newHost, newChannel, true );
+        editIrcNotifier( projectGroupName, projectName, newHost, newChannel, ircNotifierHost, ircNotifierChannel, true );
+    }
+
+    @Test( dependsOnMethods = { "testAddValidIrcProjectNotifier" } )
+    public void testEditInvalidIrcProjectNotifier()
+        throws Exception
+    {
+        goToProjectInformationPage( projectGroupName, projectName );
+        editIrcNotifier( projectGroupName, projectName, ircNotifierHost, ircNotifierChannel, "", "", false );
+    }
+
+    public void testAddInvalidIrcProjectNotifier()
+        throws Exception
+    {
+        goToProjectNotifier( projectGroupName, projectName );
+        addIrcNotifier( projectGroupName, projectName, "", "", false );
+        assertTextPresent( "Host is required" );
+        assertTextPresent( "Channel is required" );
+    }
+
+    public void testAddValidIrcGroupNotifier()
+        throws Exception
+    {
+        goToGroupNotifier( projectGroupName, projectGroupId, projectGroupDescription );
+        addIrcNotifier( projectGroupName, null, ircNotifierHost, ircNotifierChannel, true );
+    }
+
+    @Test( dependsOnMethods = { "testAddValidIrcGroupNotifier" } )
+    public void testEditValidIrcGroupNotifier()
+        throws Exception
+    {
+        String newHost = "new.test.com";
+        String newChannel = "new_test_channel";
+        showProjectGroup( projectGroupName, projectGroupId, projectGroupDescription );
+        clickLinkWithText( "Notifiers" );
+        assertGroupNotifierPage( projectGroupName );
+        editIrcNotifier( projectGroupName, null, ircNotifierHost, ircNotifierChannel, newHost, newChannel, true );
+        editIrcNotifier( projectGroupName, null, newHost, newChannel, ircNotifierHost, ircNotifierChannel, true );
+    }
+
+    @Test( dependsOnMethods = { "testAddValidIrcGroupNotifier" } )
+    public void testEditInvalidIrcGroupNotifier()
+        throws Exception
+    {
+        showProjectGroup( projectGroupName, projectGroupId, projectGroupDescription );
+        clickLinkWithText( "Notifiers" );
+        assertGroupNotifierPage( projectGroupName );
+        editIrcNotifier( projectGroupName, null, ircNotifierHost, ircNotifierChannel, "", "", false );
+    }
+
+    public void testAddInvalidIrcGroupNotifier()
+        throws Exception
+    {
+        goToGroupNotifier( projectGroupName, projectGroupId, projectGroupDescription );
+        addIrcNotifier( projectGroupName, null, "", "", false );
+        assertTextPresent( "Host is required" );
+        assertTextPresent( "Channel is required" );
+    }
+
+    public void testAddValidJabberProjectNotifier()
+        throws Exception
+    {
+        goToProjectNotifier( projectGroupName, projectName );
+        addJabberNotifier( projectGroupName, projectName, jabberNotifierHost, jabberNotifierLogin,
+                           jabberNotifierPassword, jabberNotifierAddress, true );
+    }
+
+    public void testAddJabberProjectNotifierWithInvalidValues()
+        throws Exception
+    {
+        String jabberNotifierHost = "!@#$<>?etc";
+        String jabberNotifierAddress = "!@#$<>?etc";
+        goToProjectNotifier( projectGroupName, projectName );
+        addJabberNotifier( projectGroupName, projectName, jabberNotifierHost, jabberNotifierLogin,
+                           jabberNotifierPassword, jabberNotifierAddress, false );
+        assertTextPresent( "Host contains invalid characters" );
+        assertTextPresent( "Address is invalid" );
+    }
+
+    @Test( dependsOnMethods = { "testAddValidJabberProjectNotifier" } )
+    public void testEditValidJabberProjectNotifier()
+        throws Exception
+    {
+        String newHost = "new_test";
+        String newLogin = "new_test_login";
+        String newPassword = "new_password";
+        String newAddress = "new.test@mail.com";
+        goToProjectInformationPage( projectGroupName, projectName );
+        editJabberNotifier( projectGroupName, projectName, jabberNotifierHost, jabberNotifierLogin,
+                            jabberNotifierAddress, newHost, newLogin, newPassword, newAddress, true );
+        editJabberNotifier( projectGroupName, projectName, newHost, newLogin, newAddress, jabberNotifierHost,
+                            jabberNotifierLogin, jabberNotifierPassword, jabberNotifierAddress, true );
+    }
+
+    @Test( dependsOnMethods = { "testAddValidJabberProjectNotifier" } )
+    public void testEditInvalidJabberProjectNotifier()
+        throws Exception
+    {
+        goToProjectInformationPage( projectGroupName, projectName );
+        editJabberNotifier( projectGroupName, projectName, jabberNotifierHost, jabberNotifierLogin,
+                            jabberNotifierAddress, "", "", "", "", false );
+    }
+
+    public void testAddInvalidJabberProjectNotifier()
+        throws Exception
+    {
+        goToProjectNotifier( projectGroupName, projectName );
+        addJabberNotifier( projectGroupName, projectName, "", "", "", "", false );
+        assertTextPresent( "Host is required" );
+        assertTextPresent( "Login is required" );
+        assertTextPresent( "Password is required" );
+        assertTextPresent( "Address is required" );
+    }
+
+    public void testAddValidJabberGroupNotifier()
+        throws Exception
+    {
+        goToGroupNotifier( projectGroupName, projectGroupId, projectGroupDescription );
+        addJabberNotifier( projectGroupName, null, jabberNotifierHost, jabberNotifierLogin, jabberNotifierPassword,
+                           jabberNotifierAddress, true );
+    }
+
+    @Test( dependsOnMethods = { "testAddValidJabberGroupNotifier" } )
+    public void testEditValidJabberGroupNotifier()
+        throws Exception
+    {
+        String newHost = "new_test";
+        String newLogin = "new_test_login";
+        String newPassword = "new_password";
+        String newAddress = "new.test@mail.com";
+        showProjectGroup( projectGroupName, projectGroupId, projectGroupDescription );
+        clickLinkWithText( "Notifiers" );
+        assertGroupNotifierPage( projectGroupName );
+        editJabberNotifier( projectGroupName, null, jabberNotifierHost, jabberNotifierLogin, jabberNotifierAddress,
+                            newHost, newLogin, newPassword, newAddress, true );
+        editJabberNotifier( projectGroupName, null, newHost, newLogin, newAddress, jabberNotifierHost,
+                            jabberNotifierLogin, jabberNotifierPassword, jabberNotifierAddress, true );
+    }
+
+    @Test( dependsOnMethods = { "testAddValidJabberGroupNotifier" } )
+    public void testEditInvalidJabberGroupNotifier()
+        throws Exception
+    {
+        showProjectGroup( projectGroupName, projectGroupId, projectGroupDescription );
+        clickLinkWithText( "Notifiers" );
+        assertGroupNotifierPage( projectGroupName );
+        editJabberNotifier( projectGroupName, null, jabberNotifierHost, jabberNotifierLogin, jabberNotifierAddress, "",
+                            "", "", "", false );
+    }
+
+    public void testAddInvalidJabberGroupNotifier()
+        throws Exception
+    {
+        goToGroupNotifier( projectGroupName, projectGroupId, projectGroupDescription );
+        addJabberNotifier( projectGroupName, null, "", "", "", "", false );
+        assertTextPresent( "Host is required" );
+        assertTextPresent( "Login is required" );
+        assertTextPresent( "Password is required" );
+        assertTextPresent( "Address is required" );
+    }
+
+    public void testAddValidMsnProjectNotifier()
+        throws Exception
+    {
+        goToProjectNotifier( projectGroupName, projectName );
+        addMsnNotifier( projectGroupName, projectName, msnNotifierLogin, msnNotifierPassword, msnNotifierAddress, true );
+    }
+
+    public void testAddMsnProjectNotifierWithInvalidValues()
+        throws Exception
+    {
+        String msnNotifierAddress = "!@#$<>?etc";
+        goToProjectNotifier( projectGroupName, projectName );
+        addMsnNotifier( projectGroupName, projectName, msnNotifierLogin, msnNotifierPassword, msnNotifierAddress,
+                        false );
+        assertTextPresent( "Address is invalid" );
+    }
+
+    @Test( dependsOnMethods = { "testAddValidMsnProjectNotifier" } )
+    public void testEditValidMsnProjectNotifier()
+        throws Exception
+    {
+        String newLogin = "new_test_login";
+        String newPassword = "new_password";
+        String newAddress = "new.test@mail.com";
+        goToProjectInformationPage( projectGroupName, projectName );
+        editMsnNotifier( projectGroupName, projectName, msnNotifierLogin, msnNotifierAddress, newLogin, newPassword,
+                         newAddress, true );
+        editMsnNotifier( projectGroupName, projectName, newLogin, newAddress, msnNotifierLogin, msnNotifierPassword,
+                         msnNotifierAddress, true );
+    }
+
+    @Test( dependsOnMethods = { "testAddValidMsnProjectNotifier" } )
+    public void testEditInvalidMsnProjectNotifier()
+        throws Exception
+    {
+        goToProjectInformationPage( projectGroupName, projectName );
+        editMsnNotifier( projectGroupName, projectName, msnNotifierLogin, msnNotifierAddress, "", "", "", false );
+    }
+
+    public void testAddInvalidMsnProjectNotifier()
+        throws Exception
+    {
+        goToProjectNotifier( projectGroupName, projectName );
+        addMsnNotifier( projectGroupName, projectName, "", "", "", false );
+        assertTextPresent( "Login is required" );
+        assertTextPresent( "Password is required" );
+        assertTextPresent( "Address is required" );
+    }
+
+    public void testAddValidMsnGroupNotifier()
+        throws Exception
+    {
+        goToGroupNotifier( projectGroupName, projectGroupId, projectGroupDescription );
+        addMsnNotifier( projectGroupName, null, msnNotifierLogin, msnNotifierPassword, msnNotifierAddress, true );
+    }
+
+    @Test( dependsOnMethods = { "testAddValidMsnGroupNotifier" } )
+    public void testEditValidMsnGroupNotifier()
+        throws Exception
+    {
+        String newLogin = "new_test_login";
+        String newPassword = "new_password";
+        String newAddress = "new.test@mail.com";
+        showProjectGroup( projectGroupName, projectGroupId, projectGroupDescription );
+        clickLinkWithText( "Notifiers" );
+        assertGroupNotifierPage( projectGroupName );
+        editMsnNotifier( projectGroupName, null, msnNotifierLogin, msnNotifierAddress, newLogin, newPassword,
+                         newAddress, true );
+        editMsnNotifier( projectGroupName, null, newLogin, newAddress, msnNotifierLogin, msnNotifierPassword,
+                         msnNotifierAddress, true );
+    }
+
+    @Test( dependsOnMethods = { "testAddValidMsnGroupNotifier" } )
+    public void testEditInvalidMsnGroupNotifier()
+        throws Exception
+    {
+        showProjectGroup( projectGroupName, projectGroupId, projectGroupDescription );
+        clickLinkWithText( "Notifiers" );
+        assertGroupNotifierPage( projectGroupName );
+        editMsnNotifier( projectGroupName, null, msnNotifierLogin, msnNotifierAddress, "", "", "", false );
+    }
+
+    public void testAddInvalidMsnGroupNotifier()
+        throws Exception
+    {
+        goToGroupNotifier( projectGroupName, projectGroupId, projectGroupDescription );
+        addMsnNotifier( projectGroupName, null, "", "", "", false );
+        assertTextPresent( "Login is required" );
+        assertTextPresent( "Password is required" );
+        assertTextPresent( "Address is required" );
+    }
+
+    public void testAddValidWagonProjectNotifier()
+        throws Exception
+    {
+        goToProjectNotifier( projectGroupName, projectName );
+        addWagonNotifierPage( projectGroupName, projectName, wagonNotifierUrl, wagonServerId, true );
+    }
+
+    public void testAddInvalidURLWagonProjectNotifier()
+        throws Exception
+    {
+        String wagonNotifierUrl = "!@#$<>?etc";
+        goToProjectNotifier( projectGroupName, projectName );
+        addWagonNotifierPage( projectGroupName, projectName, wagonNotifierUrl, wagonServerId, false );
+        assertTextPresent( "Destination URL is invalid" );
+    }
+
+    @Test( dependsOnMethods = { "testAddValidWagonProjectNotifier" } )
+    public void testEditValidWagonProjectNotifier()
+        throws Exception
+    {
+        String newId = "newId";
+        goToProjectInformationPage( projectGroupName, projectName );
+        editWagonNotifier( projectGroupName, projectName, wagonNotifierUrl, wagonServerId, wagonNotifierUrl, newId,
+                           true );
+        editWagonNotifier( projectGroupName, projectName, wagonNotifierUrl, newId, wagonNotifierUrl, wagonServerId,
+                           true );
+    }
+
+    @Test( dependsOnMethods = { "testAddValidWagonProjectNotifier" } )
+    public void testEditInvalidWagonProjectNotifier()
+        throws Exception
+    {
+        goToProjectInformationPage( projectGroupName, projectName );
+        editWagonNotifier( projectGroupName, projectName, wagonNotifierUrl, wagonServerId, "", "", false );
+    }
+
+    public void testAddInvalidWagonProjectNotifier()
+        throws Exception
+    {
+        goToProjectNotifier( projectGroupName, projectName );
+        addWagonNotifierPage( projectGroupName, projectName, "", "", false );
+        assertTextPresent( "Destination URL is required" );
+        assertTextPresent( "Server Id is required" );
+    }
+
+    public void testAddValidWagonGroupNotifier()
+        throws Exception
+    {
+        goToGroupNotifier( projectGroupName, projectGroupId, projectGroupDescription );
+        addWagonNotifierPage( projectGroupName, null, wagonNotifierUrl, wagonServerId, true );
+    }
+
+    @Test( dependsOnMethods = { "testAddValidWagonGroupNotifier" } )
+    public void testEditValidWagonGroupNotifier()
+        throws Exception
+    {
+        String newId = "newId";
+        showProjectGroup( projectGroupName, projectGroupId, projectGroupDescription );
+        clickLinkWithText( "Notifiers" );
+        assertGroupNotifierPage( projectGroupName );
+        editWagonNotifier( projectGroupName, null, wagonNotifierUrl, wagonServerId, wagonNotifierUrl, newId, true );
+        editWagonNotifier( projectGroupName, null, wagonNotifierUrl, newId, wagonNotifierUrl, wagonServerId, true );
+    }
+
+    @Test( dependsOnMethods = { "testAddValidWagonGroupNotifier" } )
+    public void testEditInvalidWagonGroupNotifier()
+        throws Exception
+    {
+        showProjectGroup( projectGroupName, projectGroupId, projectGroupDescription );
+        clickLinkWithText( "Notifiers" );
+        assertGroupNotifierPage( projectGroupName );
+        editWagonNotifier( projectGroupName, null, wagonNotifierUrl, wagonServerId, "", "", false );
+    }
+
+    public void testAddInvalidWagonGroupNotifier()
+        throws Exception
+    {
+        goToGroupNotifier( projectGroupName, projectGroupId, projectGroupDescription );
+        addWagonNotifierPage( projectGroupName, null, "", "", false );
+        assertTextPresent( "Destination URL is required" );
+        assertTextPresent( "Server Id is required" );
+    }
+
+    @Test( dependsOnMethods = { "testEditValidMailGroupNotifier", "testEditInvalidMailGroupNotifier" } )
+    public void testDeleteGroupNotifier()
+        throws Exception
+    {
+        showProjectGroup( projectGroupName, projectGroupId, projectGroupDescription );
+        clickLinkWithText( "Notifiers" );
+        assertGroupNotifierPage( projectGroupName );
+        clickLinkWithXPath( "(//a[contains(@href,'deleteProjectGroupNotifier') and contains(@href,'mail')])//img" );
+        assertButtonWithValuePresent( "Delete" );
+        assertButtonWithValuePresent( "Cancel" );
+        clickButtonWithValue( "Delete" );
+        assertGroupNotifierPage( projectGroupName );
+    }
+
+    @Test( dependsOnMethods = { "testEditValidMailProjectNotifier", "testEditInvalidMailProjectNotifier" } )
+    public void testDeleteProjectNotifier()
+        throws Exception
+    {
+        goToProjectInformationPage( projectGroupName, projectName );
+        // Delete
+        clickLinkWithXPath( "(//a[contains(@href,'deleteProjectNotifier') and contains(@href,'mail')])//img" );
+        assertButtonWithValuePresent( "Delete" );
+        assertButtonWithValuePresent( "Cancel" );
+        clickButtonWithValue( "Delete" );
+        assertProjectInformationPage();
+    }
+
+    public void testDeleteProjectNotifierFromGroupNotifierPage()
+        throws Exception
+    {
+        String mailNotifierAddress = "testDeleteProjectNotifierFromGroupNotifierPage@test.com";
+
+        goToProjectGroupsSummaryPage();
+        goToProjectNotifier( projectGroupName, projectName );
+        addMailNotifier( projectGroupName, projectName, mailNotifierAddress, true );
+
+        showProjectGroup( projectGroupName, projectGroupId, projectGroupDescription );
+        clickLinkWithText( "Notifiers" );
+        assertGroupNotifierPage( projectGroupName );
+
+        // Delete
+        clickLinkWithXPath( "//preceding::td[text()='" + mailNotifierAddress + "']//following::img[@alt='Delete']" );
+        assertButtonWithValuePresent( "Delete" );
+        assertButtonWithValuePresent( "Cancel" );
+        clickButtonWithValue( "Delete" );
+        assertGroupNotifierPage( projectGroupName );
+
+        assertTextNotPresent( mailNotifierAddress );
+    }
+
+    protected void assertGroupNotifierPage( String projectGroupName )
+    {
+        assertTextPresent( "Project Group Notifiers of group " + projectGroupName );
+    }
+
+    void assertAddNotifierPage()
+    {
+        assertPage( "Continuum - Add Notifier" );
+        assertTextPresent( "Add Notifier" );
+        assertTextPresent( "Type" );
+        assertElementPresent( "notifierType" );
+        assertElementPresent( "Cancel" );
+    }
+
+    void assertAddEditMailNotifierPage()
+    {
+        assertPage( "Continuum - Add/Edit Mail Notifier" );
+        assertTextPresent( "Add/Edit Mail Notifier" );
+        assertTextPresent( "Mail Recipient Address" );
+        assertTextPresent( "Send a mail to latest committers" );
+        assertTextPresent( "Send on Success" );
+        assertTextPresent( "Send on Failure" );
+        assertTextPresent( "Send on Error" );
+        assertTextPresent( "Send on Warning" );
+        assertTextPresent( "Send on SCM Failure" );
+        assertElementPresent( "address" );
+        assertElementPresent( "Cancel" );
+    }
+
+    void assertAddEditIrcNotifierPage()
+    {
+        assertPage( "Continuum - Add/Edit IRC Notifier" );
+
+        assertTextPresent( "IRC Host" );
+        assertElementPresent( "host" );
+
+        assertTextPresent( "IRC port" );
+        assertElementPresent( "port" );
+
+        assertTextPresent( "IRC channel" );
+        assertElementPresent( "channel" );
+
+        assertTextPresent( "Nick Name" );
+        assertElementPresent( "nick" );
+
+        assertTextPresent( "Alternate Nick Name" );
+        assertElementPresent( "alternateNick" );
+
+        assertTextPresent( "User Name" );
+        assertElementPresent( "username" );
+
+        assertTextPresent( "Full Name" );
+        assertElementPresent( "fullName" );
+
+        assertTextPresent( "Password" );
+        assertElementPresent( "password" );
+
+        assertTextPresent( "SSL" );
+        assertTextPresent( "Send on Success" );
+        assertTextPresent( "Send on Failure" );
+        assertTextPresent( "Send on Error" );
+        assertTextPresent( "Send on Warning" );
+        assertTextPresent( "Send on SCM Failure" );
+    }
+
+    void assertAddEditJabberPage()
+    {
+        assertPage( "Continuum - Add/Edit Jabber Notifier" );
+
+        assertTextPresent( "Jabber Host" );
+        assertElementPresent( "host" );
+        assertTextPresent( "Jabber port" );
+        assertElementPresent( "port" );
+        assertTextPresent( "Jabber login" );
+        assertElementPresent( "login" );
+        assertTextPresent( "Jabber Password" );
+        assertElementPresent( "password" );
+        assertTextPresent( "Jabber Domain Name" );
+        assertElementPresent( "domainName" );
+        assertTextPresent( "Jabber Recipient Address" );
+        assertElementPresent( "address" );
+
+        assertTextPresent( "Is it a SSL connection?" );
+        assertTextPresent( "Is it a Jabber group?" );
+        assertTextPresent( "Send on Success" );
+        assertTextPresent( "Send on Failure" );
+        assertTextPresent( "Send on Error" );
+        assertTextPresent( "Send on Warning" );
+        assertTextPresent( "Send on SCM Failure" );
+    }
+
+    void assertAddEditMsnPage()
+    {
+        assertPage( "Continuum - Add/Edit MSN Notifier" );
+
+        assertTextPresent( "MSN login" );
+        assertElementPresent( "login" );
+        assertTextPresent( "MSN Password" );
+        assertElementPresent( "password" );
+        assertTextPresent( "MSN Recipient Address" );
+        assertElementPresent( "address" );
+
+        assertTextPresent( "Send on Success" );
+        assertTextPresent( "Send on Failure" );
+        assertTextPresent( "Send on Error" );
+        assertTextPresent( "Send on Warning" );
+        assertTextPresent( "Send on SCM Failure" );
+    }
+
+    void assertAddEditWagonPage()
+    {
+        assertPage( "Continuum - Add/Edit Wagon Notifier" );
+
+        assertTextPresent( "Project Site URL" );
+        assertTextPresent( "Server Id (defined in your settings.xml for authentication)" );
+        assertElementPresent( "url" );
+        assertElementPresent( "id" );
+        assertTextPresent( "Send on Success" );
+        assertTextPresent( "Send on Failure" );
+        assertTextPresent( "Send on Error" );
+        assertTextPresent( "Send on Warning" );
+    }
+
+    protected void goToGroupNotifier( String projectGroupName, String projectGroupId, String projectGroupDescription )
+    {
+        showProjectGroup( projectGroupName, projectGroupId, projectGroupDescription );
+        clickLinkWithText( "Notifiers" );
+        assertGroupNotifierPage( projectGroupName );
+        clickButtonWithValue( "Add" );
+        assertAddNotifierPage();
+    }
+
+    protected void goToProjectNotifier( String projectGroupName, String projectName )
+    {
+        goToProjectInformationPage( projectGroupName, projectName );
+        clickLinkWithXPath( "//input[contains(@id,'addProjectNotifier') and @type='submit']" );
+        assertAddNotifierPage();
+    }
+
+    protected void addMailNotifier( String projectGroupName, String projectName, String email, boolean isValid )
+    {
+        selectValue( "//select", "Mail" );
+        clickButtonWithValue( "Submit" );
+        assertAddEditMailNotifierPage();
+        setFieldValue( "address", email );
+        clickButtonWithValue( "Save" );
+
+        if ( !isValid )
+        {
+            assertTextPresent( "Address is invalid" );
+        }
+        else if ( projectName != null )
+        {
+            assertProjectInformationPage();
+        }
+        else
+        {
+            assertGroupNotifierPage( projectGroupName );
+        }
+    }
+
+    protected void editMailNotifier( String projectGroupName, String projectName, String oldMail, String newMail,
+                                     boolean isValid )
+    {
+        if ( projectName == null )
+        {
+            clickLinkWithXPath( "(//a[contains(@href,'editProjectGroupNotifier') and contains(@href,'mail')])//img" );
+        }
+        else
+        {
+            clickLinkWithXPath( "(//a[contains(@href,'editProjectNotifier') and contains(@href,'mail')])//img" );
+        }
+        assertAddEditMailNotifierPage();
+        assertFieldValue( oldMail, "address" );
+        setFieldValue( "address", newMail );
+        clickButtonWithValue( "Save" );
+
+        if ( !isValid )
+        {
+            assertTextPresent( "Address is invalid" );
+        }
+        else if ( projectName != null )
+        {
+            assertProjectInformationPage();
+        }
+        else
+        {
+            assertGroupNotifierPage( projectGroupName );
+        }
+    }
+
+    protected void addIrcNotifier( String projectGroupName, String projectName, String host, String channel,
+                                   boolean isValid )
+    {
+        selectValue( "//select", "IRC" );
+        clickButtonWithValue( "Submit" );
+        assertAddEditIrcNotifierPage();
+        setFieldValue( "host", host );
+        setFieldValue( "channel", channel );
+
+        clickButtonWithValue( "Save" );
+        if ( isValid )
+        {
+            if ( projectName != null )
+            {
+                assertProjectInformationPage();
+            }
+            else
+            {
+                assertGroupNotifierPage( projectGroupName );
+            }
+        }
+    }
+
+    protected void editIrcNotifier( String projectGroupName, String projectName, String oldHost, String oldChannel,
+                                    String newHost, String newChannel, boolean isValid )
+    {
+        if ( projectName == null )
+        {
+            clickLinkWithXPath( "(//a[contains(@href,'editProjectGroupNotifier') and contains(@href,'irc')])//img" );
+        }
+        else
+        {
+            clickLinkWithXPath( "(//a[contains(@href,'editProjectNotifier') and contains(@href,'irc')])//img" );
+        }
+        assertAddEditIrcNotifierPage();
+        assertFieldValue( oldHost, "host" );
+        assertFieldValue( oldChannel, "channel" );
+        setFieldValue( "host", newHost );
+        setFieldValue( "channel", newChannel );
+        clickButtonWithValue( "Save" );
+
+        if ( !isValid )
+        {
+            assertTextPresent( "Host is required" );
+            assertTextPresent( "Channel is required" );
+        }
+        else if ( projectName != null )
+        {
+            assertProjectInformationPage();
+        }
+        else
+        {
+            assertGroupNotifierPage( projectGroupName );
+        }
+    }
+
+    protected void addJabberNotifier( String projectGroupName, String projectName, String host, String login,
+                                      String password, String address, boolean isValid )
+    {
+        selectValue( "//select", "Jabber" );
+        clickButtonWithValue( "Submit" );
+        assertAddEditJabberPage();
+        setFieldValue( "host", host );
+        setFieldValue( "login", login );
+        setFieldValue( "password", password );
+        setFieldValue( "address", address );
+        clickButtonWithValue( "Save" );
+
+        if ( isValid )
+        {
+            if ( projectName != null )
+            {
+                assertProjectInformationPage();
+            }
+            else
+            {
+                assertGroupNotifierPage( projectGroupName );
+            }
+        }
+    }
+
+    protected void editJabberNotifier( String projectGroupName, String projectName, String oldHost, String oldLogin,
+                                       String oldAddress, String newHost, String newLogin, String newPassword,
+                                       String newAddress, boolean isValid )
+    {
+        if ( projectName == null )
+        {
+            clickLinkWithXPath( "(//a[contains(@href,'editProjectGroupNotifier') and contains(@href,'jabber')])//img" );
+        }
+        else
+        {
+            clickLinkWithXPath( "(//a[contains(@href,'editProjectNotifier') and contains(@href,'jabber')])//img" );
+        }
+        assertAddEditJabberPage();
+        assertFieldValue( oldHost, "host" );
+        assertFieldValue( oldLogin, "login" );
+        assertFieldValue( oldAddress, "address" );
+        setFieldValue( "host", newHost );
+        setFieldValue( "login", newLogin );
+        setFieldValue( "password", newPassword );
+        setFieldValue( "address", newAddress );
+        clickButtonWithValue( "Save" );
+
+        if ( !isValid )
+        {
+            assertTextPresent( "Host is required" );
+            assertTextPresent( "Login is required" );
+            assertTextPresent( "Password is required" );
+            assertTextPresent( "Address is required" );
+        }
+        else if ( projectName != null )
+        {
+            assertProjectInformationPage();
+        }
+        else
+        {
+            assertGroupNotifierPage( projectGroupName );
+        }
+    }
+
+    protected void addMsnNotifier( String projectGroupName, String projectName, String login, String password,
+                                   String recipientAddress, boolean isValid )
+    {
+        selectValue( "//select", "MSN" );
+        clickButtonWithValue( "Submit" );
+        assertAddEditMsnPage();
+        setFieldValue( "login", login );
+        setFieldValue( "password", password );
+        setFieldValue( "address", recipientAddress );
+        clickButtonWithValue( "Save" );
+
+        if ( isValid )
+        {
+            if ( projectName != null )
+            {
+                assertProjectInformationPage();
+            }
+            else
+            {
+                assertGroupNotifierPage( projectGroupName );
+            }
+        }
+    }
+
+    protected void editMsnNotifier( String projectGroupName, String projectName, String oldLogin, String oldAddress,
+                                    String newLogin, String newPassword, String newAddress, boolean isValid )
+    {
+        if ( projectName == null )
+        {
+            clickLinkWithXPath( "(//a[contains(@href,'editProjectGroupNotifier') and contains(@href,'msn')])//img" );
+        }
+        else
+        {
+            clickLinkWithXPath( "(//a[contains(@href,'editProjectNotifier') and contains(@href,'msn')])//img" );
+        }
+        assertAddEditMsnPage();
+        assertFieldValue( oldLogin, "login" );
+        assertFieldValue( oldAddress, "address" );
+        setFieldValue( "login", newLogin );
+        setFieldValue( "password", newPassword );
+        setFieldValue( "address", newAddress );
+        clickButtonWithValue( "Save" );
+
+        if ( !isValid )
+        {
+            assertTextPresent( "Login is required" );
+            assertTextPresent( "Password is required" );
+            assertTextPresent( "Address is required" );
+        }
+        else if ( projectName != null )
+        {
+            assertProjectInformationPage();
+        }
+        else
+        {
+            assertGroupNotifierPage( projectGroupName );
+        }
+    }
+
+    protected void addWagonNotifierPage( String projectGroupName, String projectName, String siteUrl, String serverId,
+                                         boolean isValid )
+    {
+        selectValue( "//select", "Wagon" );
+        clickButtonWithValue( "Submit" );
+        assertAddEditWagonPage();
+        setFieldValue( "url", siteUrl );
+        setFieldValue( "id", serverId );
+        clickButtonWithValue( "Save" );
+
+        if ( isValid )
+        {
+            if ( projectName != null )
+            {
+                assertProjectInformationPage();
+            }
+            else
+            {
+                assertGroupNotifierPage( projectGroupName );
+            }
+        }
+    }
+
+    protected void editWagonNotifier( String projectGroupName, String projectName, String oldUrl, String oldId,
+                                      String newUrl, String newId, boolean isValid )
+    {
+        if ( projectName == null )
+        {
+            clickLinkWithXPath( "(//a[contains(@href,'editProjectGroupNotifier') and contains(@href,'wagon')])//img" );
+        }
+        else
+        {
+            clickLinkWithXPath( "(//a[contains(@href,'editProjectNotifier') and contains(@href,'wagon')])//img" );
+        }
+        assertAddEditWagonPage();
+        assertFieldValue( oldUrl, "url" );
+        assertFieldValue( oldId, "id" );
+        setFieldValue( "url", newUrl );
+        setFieldValue( "id", newId );
+        clickButtonWithValue( "Save" );
+
+        if ( !isValid )
+        {
+            assertTextPresent( "Destination URL is required" );
+            assertTextPresent( "Server Id is required" );
+        }
+        else if ( projectName != null )
+        {
+            assertProjectInformationPage();
+        }
+        else
+        {
+            assertGroupNotifierPage( projectGroupName );
+        }
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/ProjectGroupTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/ProjectGroupTest.java
new file mode 100644
index 0000000..a9b5cec
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/ProjectGroupTest.java
@@ -0,0 +1,261 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 org.apache.continuum.web.test.parent.AbstractAdminTest;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * Based on ProjectGroupTest of Emmanuel Venisse test.
+ *
+ * @author José Morales Martínez
+ * @version $Id$
+ */
+@Test( groups = {"projectGroup"} )
+public class ProjectGroupTest
+    extends AbstractAdminTest
+{
+
+    public static final String TEST_PROJECT_NAME = "ContinuumBuildQueueTestData";
+
+    private String projectGroupName;
+
+    private String projectGroupId;
+
+    private String projectGroupDescription;
+
+    @BeforeMethod
+    protected void setUp()
+        throws Exception
+    {
+        projectGroupName = getProperty( "TEST_PROJ_GRP_NAME" );
+        projectGroupId = getProperty( "TEST_PROJ_GRP_ID" );
+        projectGroupDescription = getProperty( "TEST_PROJ_GRP_DESCRIPTION" );
+    }
+
+    @AfterClass
+    public void tearDown()
+    {
+        removeProjectGroup( projectGroupName, false );
+    }
+
+    public void testAddProjectGroup()
+        throws Exception
+    {
+        addProjectGroup( projectGroupName, projectGroupId, projectGroupDescription, true );
+        showProjectGroup( projectGroupName, projectGroupId, projectGroupDescription );
+    }
+
+    public void testAddProjectGroupWithInvalidValues()
+        throws Exception
+    {
+        String name = "!@#$<>?etch";
+        String groupId = "-!@#<>etc";
+        String description = "![]<>'^&etc";
+
+        addProjectGroup( name, groupId, description, false );
+        assertTextPresent( "Name contains invalid characters." );
+        assertTextPresent( "Id contains invalid characters." );
+    }
+
+    public void testAddProjectGroupWithDashedGroupId()
+        throws Exception
+    {
+        String name = "Test Project Group with Dashes";
+        String groupId = "com.example.this-is-a-long-group-id";
+        String description = "";
+
+        try {
+            addProjectGroup( name, groupId, description, true );
+        } finally {
+            removeProjectGroup( name, false );
+        }
+    }
+
+    public void testAddProjectGroupWithPunctuation()
+        throws Exception
+    {
+        String name = "Test :: Test Project Group (with Punctuation)";
+        String groupId = "com.example.test";
+        String description = "";
+
+        try {
+            addProjectGroup( name, groupId, description, true );
+        } finally {
+            removeProjectGroup( name, false );
+        }
+    }
+
+    public void testAddProjectGroupWithEmptyString()
+        throws Exception
+    {
+        addProjectGroup( "", "", "", false );
+        assertTextPresent( "Project Group Name is required" );
+        assertTextPresent( "Project Group ID is required" );
+    }
+
+    public void testAddProjectGroupWithWhitespaceString()
+        throws Exception
+    {
+        addProjectGroup( " ", " ", " ", false );
+        assertTextPresent( "Project Group Name is required" );
+        assertTextPresent( "Project Group ID is required" );
+    }
+
+    @Test( dependsOnMethods = {"testAddProjectGroup"} )
+    public void testEditProjectGroupWithValidValues()
+        throws Exception
+    {
+        final String newName = "Test :: New Project Group Name (with valid values)";
+        final String newDescription = "New Project Group Description";
+
+        editProjectGroup( projectGroupName, projectGroupId, projectGroupDescription, newName, newDescription );
+        assertProjectGroupSummaryPage( newName, projectGroupId, newDescription );
+
+        editProjectGroup( newName, projectGroupId, newDescription, projectGroupName, projectGroupDescription );
+        assertProjectGroupSummaryPage( projectGroupName, projectGroupId, projectGroupDescription );
+    }
+
+    @Test( dependsOnMethods = {"testAddProjectGroup"} )
+    public void testEditProjectGroupWithInvalidValues()
+        throws Exception
+    {
+        editProjectGroup( projectGroupName, projectGroupId, projectGroupDescription, " ", projectGroupDescription );
+        assertTextPresent( "Project Group Name is required" );
+    }
+
+    @Test( dependsOnMethods = {"testAddProjectGroup"} )
+    public void testEditProjectGroupWithXSS()
+        throws Exception
+    {
+        String newName = "<script>alert('XSS')</script>";
+        String newDescription = "<script>alert('XSS')</script>";
+        editProjectGroup( projectGroupName, projectGroupId, projectGroupDescription, newName, newDescription );
+        assertTextPresent( "Name contains invalid characters." );
+    }
+
+    public void testDeleteProjectGroup()
+        throws Exception
+    {
+        String name = getProperty( "TEST_DELETE_GRP_NAME" );
+        String groupId = getProperty( "TEST_DELETE_GRP_ID" );
+        String description = getProperty( "TEST_DELETE_GRP_DESCRIPTION" );
+
+        // delete group - delete icon
+        addProjectGroup( name, groupId, description, true );
+        assertLinkPresent( name );
+        clickLinkWithXPath( "//tbody/tr['0']/td['4']/a/img[@alt='Delete Group']" );
+        assertTextPresent( "Project Group Removal" );
+        clickButtonWithValue( "Delete" );
+        assertProjectGroupsSummaryPage();
+        assertLinkNotPresent( name );
+
+        // delete group - "Delete Group" button
+        addProjectGroup( name, groupId, description, true );
+        assertLinkPresent( name );
+        removeProjectGroup( name );
+        assertLinkNotPresent( name );
+        assertProjectGroupsSummaryPage();
+        assertLinkNotPresent( name );
+    }
+
+    public void testProjectGroupMembers()
+        throws Exception
+    {
+        String name1 = getProperty( "TEST_PROJ_GRP_NAME_ONE" );
+        String groupId1 = getProperty( "TEST_PROJ_GRP_ID_ONE" );
+        String description1 = getProperty( "TEST_PROJ_GRP_DESCRIPTION_ONE" );
+        String name2 = getProperty( "TEST_PROJ_GRP_NAME_TWO" );
+        String groupId2 = getProperty( "TEST_PROJ_GRP_ID_TWO" );
+        String description2 = getProperty( "TEST_PROJ_GRP_DESCRIPTION_TWO" );
+        String name3 = getProperty( "TEST_PROJ_GRP_NAME_THREE" );
+        String groupId3 = getProperty( "TEST_PROJ_GRP_ID_THREE" );
+        String description3 = getProperty( "TEST_PROJ_GRP_DESCRIPTION_THREE" );
+
+        addProjectGroup( name1, groupId1, description1, true, false );
+        assertLinkPresent( name1 );
+
+        addProjectGroup( name2, groupId2, description2, true, false );
+        assertLinkPresent( name2 );
+
+        addProjectGroup( name3, groupId3, description3, true, false );
+        assertLinkPresent( name3 );
+
+        createAndAddUserAsDeveloperToGroup( "username1", "user1", "user1@something.com", name1 );
+        createAndAddUserAsDeveloperToGroup( "username2", "user2", "user2@something.com", name1 );
+        createAndAddUserAsDeveloperToGroup( "username3", "user3", "user3@something.com", name2 );
+        createAndAddUserAsDeveloperToGroup( "username4", "user4", "user4@something.com", name3 );
+
+        showMembers( name1, groupId1, description1 );
+        assertUserPresent( "username1", "user1", "user1@something.com" );
+        assertUserPresent( "username2", "user2", "user2@something.com" );
+        assertUserNotPresent( "username3", "user3", "user3@something.com" );
+        assertUserNotPresent( "username4", "user4", "user4@something.com" );
+
+        showMembers( name2, groupId2, description2 );
+        assertUserNotPresent( "username1", "user1", "user1@something.com" );
+        assertUserNotPresent( "username2", "user2", "user2@something.com" );
+        assertUserPresent( "username3", "user3", "user3@something.com" );
+        assertUserNotPresent( "username4", "user4", "user4@something.com" );
+
+        showMembers( name3, groupId3, description3 );
+        assertUserNotPresent( "username1", "user1", "user1@something.com" );
+        assertUserNotPresent( "username2", "user2", "user2@something.com" );
+        assertUserNotPresent( "username3", "user3", "user3@something.com" );
+        assertUserPresent( "username4", "user4", "user4@something.com" );
+
+        removeProjectGroup( name1 );
+        assertLinkNotPresent( name1 );
+        removeProjectGroup( name2 );
+        assertLinkNotPresent( name2 );
+        removeProjectGroup( name3 );
+        assertLinkNotPresent( name3 );
+    }
+
+    public void testRemoveProjectFromMembers()
+    {
+        goToProjectGroupsSummaryPage();
+        addProjectGroup( projectGroupName, projectGroupId, projectGroupDescription, true, false );
+        showProjectGroup( projectGroupName, projectGroupId, projectGroupDescription );
+
+        if ( !isLinkPresent( TEST_PROJECT_NAME ) )
+        {
+            clickButtonWithValue( "Add" );
+            assertAddMavenTwoProjectPage();
+            setFieldValue( "m2PomUrl", getProperty( "M2_POM_URL" ) );
+            clickButtonWithValue( "Add" );
+            waitAddProject( "Continuum - Project Group" );
+            assertTextPresent( TEST_PROJECT_NAME );
+            waitForProjectCheckout();
+        }
+
+        clickLinkWithText( "Members" );
+        assertTextPresent( TEST_PROJECT_NAME );
+        clickImgWithAlt( "Delete" );
+
+        assertTextPresent( "Delete Continuum Project" );
+        clickButtonWithValue( "Delete" );
+
+        assertProjectGroupSummaryPage( projectGroupName, projectGroupId, projectGroupDescription );
+        assertTextNotPresent( TEST_PROJECT_NAME );
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/PurgeTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/PurgeTest.java
new file mode 100644
index 0000000..db3362f
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/PurgeTest.java
@@ -0,0 +1,110 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 org.apache.continuum.web.test.parent.AbstractPurgeTest;
+import org.testng.annotations.Test;
+
+/**
+ * @author José Morales Martínez
+ * @version $Id$
+ */
+@Test( groups = {"purge"} )
+public class PurgeTest
+    extends AbstractPurgeTest
+{
+    public void testAddRepositoryPurge()
+    {
+        String PURGE_REPOSITORY_DESCRIPTION = getProperty( "PURGE_REPOSITORY_DESCRIPTION" );
+        String PURGE_REPOSITORY_DAYS = getProperty( "PURGE_REPOSITORY_DAYS" );
+        String PURGE_REPOSITORY_RETETION = getProperty( "PURGE_REPOSITORY_RETETION" );
+        goToAddRepositoryPurge();
+        addEditRepositoryPurge( PURGE_REPOSITORY_DAYS, PURGE_REPOSITORY_RETETION, PURGE_REPOSITORY_DESCRIPTION, true );
+    }
+
+    public void testAddInvalidRepositoryPurge()
+    {
+        String PURGE_REPOSITORY_DESCRIPTION = getProperty( "PURGE_REPOSITORY_DESCRIPTION" );
+        goToAddRepositoryPurge();
+        addEditRepositoryPurge( "", "", PURGE_REPOSITORY_DESCRIPTION, false );
+        assertTextPresent( "Retention Count must be greater than 0." );
+    }
+
+    @Test( dependsOnMethods = {"testAddRepositoryPurge"} )
+    public void testEditRepositoryPurge()
+    {
+        String PURGE_REPOSITORY_DESCRIPTION = getProperty( "PURGE_REPOSITORY_DESCRIPTION" );
+        String PURGE_REPOSITORY_DAYS = getProperty( "PURGE_REPOSITORY_DAYS" );
+        String PURGE_REPOSITORY_RETETION = getProperty( "PURGE_REPOSITORY_RETETION" );
+        String newDescription = "new_description";
+        String newDays = "45";
+        String newRetention = "4";
+        goToEditRepositoryPurge( PURGE_REPOSITORY_DAYS, PURGE_REPOSITORY_RETETION, PURGE_REPOSITORY_DESCRIPTION );
+        addEditRepositoryPurge( newDays, newRetention, newDescription, true );
+        goToEditRepositoryPurge( newDays, newRetention, newDescription );
+        addEditRepositoryPurge( PURGE_REPOSITORY_DAYS, PURGE_REPOSITORY_RETETION, PURGE_REPOSITORY_DESCRIPTION, true );
+    }
+
+    @Test( dependsOnMethods = {"testEditRepositoryPurge"} )
+    public void testDeleteRepositoryPurge()
+    {
+        String PURGE_REPOSITORY_DESCRIPTION = getProperty( "PURGE_REPOSITORY_DESCRIPTION" );
+        removeRepositoryPurge( PURGE_REPOSITORY_DESCRIPTION );
+    }
+
+    public void testAddDirectoryPurge()
+    {
+        String PURGE_DIRECTORY_DESCRIPTION = getProperty( "PURGE_DIRECTORY_DESCRIPTION" );
+        String PURGE_DIRECTORY_DAYS = getProperty( "PURGE_DIRECTORY_DAYS" );
+        String PURGE_DIRECTORY_RETETION = getProperty( "PURGE_DIRECTORY_RETETION" );
+        goToAddDirectoryPurge();
+        addEditDirectoryPurge( PURGE_DIRECTORY_DAYS, PURGE_DIRECTORY_RETETION, PURGE_DIRECTORY_DESCRIPTION, true );
+    }
+
+    public void testAddInvalidDirectoryPurge()
+    {
+        String PURGE_DIRECTORY_DESCRIPTION = getProperty( "PURGE_DIRECTORY_DESCRIPTION" );
+        goToAddDirectoryPurge();
+        addEditDirectoryPurge( "", "", PURGE_DIRECTORY_DESCRIPTION, false );
+        assertTextPresent( "Retention Count must be greater than 0." );
+    }
+
+    @Test( dependsOnMethods = {"testAddDirectoryPurge"} )
+    public void testEditDirectoryPurge()
+    {
+        String PURGE_DIRECTORY_DESCRIPTION = getProperty( "PURGE_DIRECTORY_DESCRIPTION" );
+        String PURGE_DIRECTORY_DAYS = getProperty( "PURGE_DIRECTORY_DAYS" );
+        String PURGE_DIRECTORY_RETETION = getProperty( "PURGE_DIRECTORY_RETETION" );
+        String newDescription = "new_description";
+        String newDays = "45";
+        String newRetention = "4";
+        goToEditDirectoryPurge( PURGE_DIRECTORY_DAYS, PURGE_DIRECTORY_RETETION, PURGE_DIRECTORY_DESCRIPTION );
+        addEditDirectoryPurge( newDays, newRetention, newDescription, true );
+        goToEditDirectoryPurge( newDays, newRetention, newDescription );
+        addEditDirectoryPurge( PURGE_DIRECTORY_DAYS, PURGE_DIRECTORY_RETETION, PURGE_DIRECTORY_DESCRIPTION, true );
+    }
+
+    @Test( dependsOnMethods = {"testEditDirectoryPurge"} )
+    public void testDeleteDirectoryPurge()
+    {
+        String PURGE_DIRECTORY_DESCRIPTION = getProperty( "PURGE_DIRECTORY_DESCRIPTION" );
+        removeDirectoryPurge( PURGE_DIRECTORY_DESCRIPTION );
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/QueueTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/QueueTest.java
new file mode 100644
index 0000000..af41fc6
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/QueueTest.java
@@ -0,0 +1,243 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 org.apache.continuum.web.test.parent.AbstractAdminTest;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+
+/**
+ * @author José Morales Martínez
+ * @version $Id$
+ */
+@Test( groups = { "queue" } )
+public class QueueTest
+    extends AbstractAdminTest
+{
+    private String buildQueueName;
+
+    @BeforeMethod
+    protected void setUp()
+        throws Exception
+    {
+        buildQueueName = getProperty( "BUILD_QUEUE_NAME" );
+    }
+
+    @AfterClass
+    protected void tearDown()
+    {
+        goToBuildQueuePage();
+        removeBuildQueue( buildQueueName );
+    }
+
+    public void testAddBuildQueue()
+    {
+        setMaxBuildQueue( 2 );
+        addBuildQueue( buildQueueName );
+    }
+
+    public void testQueuePageWithoutBuild()
+    {
+        clickAndWait( "link=Queues" );
+        assertPage( "Continuum - Build Queue" );
+        assertTextPresent( "Nothing is building" );
+        assertTextNotPresent( "Project Name* Build Definition" );
+        assertTextPresent( "Current Build" );
+        assertTextPresent( "Build Queue" );
+        assertTextPresent( "Current Checkout" );
+        assertTextPresent( "Checkout Queue " );
+        assertTextPresent( "Current Prepare Build" );
+        assertTextPresent( "Prepare Build Queue" );
+    }
+
+    @Test( dependsOnMethods = { "testAddBuildQueue" } )
+    public void testAddBuildQueueToSchedule()
+    {
+        String scheduleName = getProperty( "QUEUE_SCHEDULE_NAME" );
+        String scheduleDescription = getProperty( "SCHEDULE_DESCRIPTION" );
+        String second = getProperty( "SCHEDULE_EXPR_SECOND" );
+        String minute = getProperty( "SCHEDULE_EXPR_MINUTE" );
+        String hour = getProperty( "SCHEDULE_EXPR_HOUR" );
+        String dayOfMonth = getProperty( "SCHEDULE_EXPR_DAY_MONTH" );
+        String month = getProperty( "SCHEDULE_EXPR_MONTH" );
+        String dayOfWeek = getProperty( "SCHEDULE_EXPR_DAY_WEEK" );
+        String year = getProperty( "SCHEDULE_EXPR_YEAR" );
+        String maxTime = getProperty( "SCHEDULE_MAX_TIME" );
+        String period = getProperty( "SCHEDULE_PERIOD" );
+
+        goToAddSchedule();
+        addEditSchedule( scheduleName, scheduleDescription, second, minute, hour, dayOfMonth, month, dayOfWeek, year,
+                         maxTime, period, true, true );
+        try {
+            goToEditSchedule( scheduleName, scheduleDescription, second, minute, hour, dayOfMonth, month, dayOfWeek, year,
+                              maxTime, period );
+
+            getSelenium().addSelection( "saveSchedule_availableBuildQueuesIds", "label=" + buildQueueName );
+            getSelenium().click( "//input[@value='->']" );
+            submit();
+        } finally {
+            removeSchedule( scheduleName );
+        }
+    }
+
+    @Test( dependsOnMethods = { "testAddBuildQueue" } )
+    public void testAddNotAllowedBuildQueue()
+    {
+        setMaxBuildQueue( 1 );
+        String secondQueue = "second_queue_name";
+        addBuildQueue( secondQueue, false );
+        assertTextPresent( "You are only allowed 1 number of builds in parallel." );
+    }
+
+    @Test( dependsOnMethods = { "testAddBuildQueue" } )
+    public void testAddAlreadyExistBuildQueue()
+    {
+        setMaxBuildQueue( 3 );
+        addBuildQueue( buildQueueName, false );
+        assertTextPresent( "Build queue name already exists." );
+    }
+
+    public void testAddEmptyBuildQueue()
+    {
+        setMaxBuildQueue( 3 );
+        addBuildQueue( "", false, false );
+        assertTextPresent( "You must define a name" );
+    }
+
+    public void testDeleteBuildQueue()
+    {
+        setMaxBuildQueue( 3 );
+        goToBuildQueuePage();
+        String testBuildQueue = "test_build_queue";
+        addBuildQueue( testBuildQueue );
+
+        removeBuildQueue( testBuildQueue );
+        assertTextNotPresent( testBuildQueue );
+    }
+
+    @Test( dependsOnMethods = { "testQueuePageWithoutBuild" } )
+    public void testQueuePageWithProjectCurrentlyBuilding()
+        throws Exception
+    {
+        String pomUrl = getProperty( "MAVEN2_QUEUE_TEST_POM_URL" );
+        String pomUsername = getProperty( "MAVEN2_QUEUE_TEST_POM_USERNAME" );
+        String pomPassword = getProperty( "MAVEN2_QUEUE_TEST_POM_PASSWORD" );
+
+        String projectGroupName = getProperty( "MAVEN2_QUEUE_TEST_POM_PROJECT_GROUP_NAME" );
+        String projectGroupId = getProperty( "MAVEN2_QUEUE_TEST_POM_PROJECT_GROUP_ID" );
+        String projectGroupDescription = getProperty( "MAVEN2_QUEUE_TEST_POM_PROJECT_GROUP_DESCRIPTION" );
+
+        goToProjectGroupsSummaryPage();
+        if ( !isLinkPresent( projectGroupName ) )
+        {
+            //build a project
+            goToAddMavenTwoProjectPage();
+            addMavenTwoProject( pomUrl, pomUsername, pomPassword, null, true );
+        }
+
+        buildProjectForQueuePageTest( projectGroupName, projectGroupId, projectGroupDescription );
+        String location = getSelenium().getLocation();
+
+        //check queue page while building
+        getSelenium().open( baseUrl + "/admin/displayQueues.action" );
+        assertPage( "Continuum - Build Queue" );
+        assertTextPresent( "Current Build" );
+        assertTextPresent( "Build Queue" );
+        assertTextPresent( "Current Checkout" );
+        assertTextPresent( "Checkout Queue " );
+        assertTextPresent( "Current Prepare Build" );
+        assertTextPresent( "Prepare Build Queue" );
+        assertElementPresent( "//table[@id='ec_table']/tbody/tr/td[4]" );
+        assertTextPresent( projectGroupName );
+        getSelenium().open( location );
+        waitPage();
+        waitForElementPresent( "//img[@alt='Success']" );
+    }
+
+    protected void goToBuildQueuePage()
+    {
+        clickLinkWithText( "Build Queue" );
+
+        assertBuildQueuePage();
+    }
+
+    void assertBuildQueuePage()
+    {
+        assertPage( "Continumm - Parallel Build Queue" );
+        assertTextPresent( "Parallel Build Queue" );
+        assertTextPresent( "Name" );
+        assertTextPresent( "DEFAULT_BUILD_QUEUE" );
+        assertButtonWithValuePresent( "Add" );
+    }
+
+    protected void removeBuildQueue( String queueName )
+    {
+        clickLinkWithXPath(
+            "(//a[contains(@href,'deleteBuildQueue.action') and contains(@href, '" + queueName + "')])//img" );
+        assertTextPresent( "Delete Parallel Build Queue" );
+        assertTextPresent( "Are you sure you want to delete the build queue \"" + queueName + "\"?" );
+        assertButtonWithValuePresent( "Delete" );
+        assertButtonWithValuePresent( "Cancel" );
+        clickButtonWithValue( "Delete" );
+        assertBuildQueuePage();
+    }
+
+    void assertAddBuildQueuePage()
+    {
+        assertPage( "Continuum - Add/Edit Parallel Build Queue" );
+        assertTextPresent( "Add/Edit Parallel Build Queue" );
+        assertTextPresent( "Name*" );
+        assertElementPresent( "name" );
+        assertButtonWithValuePresent( "Save" );
+        assertButtonWithValuePresent( "Cancel" );
+    }
+
+    protected void addBuildQueue( String name )
+    {
+        addBuildQueue( name, true );
+    }
+
+    protected void addBuildQueue( String name, boolean success )
+    {
+        addBuildQueue( name, success, true );
+    }
+
+    protected void addBuildQueue( String name, boolean success, boolean waitForError )
+    {
+        goToBuildQueuePage();
+        assertBuildQueuePage();
+        submit();
+        assertAddBuildQueuePage();
+        setFieldValue( "name", name );
+        if ( success )
+        {
+            submit();
+            assertBuildQueuePage();
+            assertTextPresent( name );
+        }
+        else
+        {
+            submit( waitForError );
+            assertAddBuildQueuePage();
+        }
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/ReleaseTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/ReleaseTest.java
new file mode 100644
index 0000000..badc8a3
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/ReleaseTest.java
@@ -0,0 +1,180 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+@Test( groups = {"release"} )
+public class ReleaseTest
+    extends AbstractReleaseTest
+{
+    private String projectGroupName;
+
+    private String projectGroupId;
+
+    private String tagBase;
+
+    private String tag;
+
+    private String releaseVersion;
+
+    private String developmentVersion;
+
+    private String releaseProjectScmUrl;
+
+    @BeforeClass
+    public void createAndBuildProject()
+    {
+        projectGroupName = getProperty( "RELEASE_PROJECT_GROUP_NAME" );
+        projectGroupId = getProperty( "RELEASE_PROJECT_GROUP_ID" );
+        String description = "Release test projects";
+
+        loginAsAdmin();
+
+        String pomUrl = getProperty( "MAVEN2_POM_URL" );
+        String pomUsername = getProperty( "MAVEN2_POM_USERNAME" );
+        String pomPassword = getProperty( "MAVEN2_POM_PASSWORD" );
+        String projectName = getProperty( "MAVEN2_POM_PROJECT_NAME" );
+
+        addProjectGroup( projectGroupName, projectGroupId, description, true, false );
+        clickLinkWithText( projectGroupName );
+
+        if ( !isLinkPresent( projectName ) )
+        {
+            addMavenTwoProject( pomUrl, pomUsername, pomPassword, projectGroupName, true );
+
+            buildProjectGroup( projectGroupName, projectGroupId, "", projectName, true );
+        }
+    }
+
+    @BeforeMethod
+    public void setUp()
+        throws IOException
+    {
+        tagBase = getProperty( "RELEASE_PROJECT_TAGBASE" );
+        tag = getProperty( "RELEASE_PROJECT_TAG" );
+        releaseVersion = getProperty( "RELEASE_PROJECT_VERSION" );
+        developmentVersion = getProperty( "RELEASE_PROJECT_DEVELOPMENT_VERSION" );
+        releaseProjectScmUrl = getProperty( "RELEASE_PROJECT_SCM_URL" );
+    }
+
+    @AfterMethod
+    public void tearDown()
+        throws Exception
+    {
+    }
+
+    // can't test u/p locally and don't have a suitable SVN server to test against
+    @Test( enabled = false )
+    public void testReleasePrepareProjectWithInvalidUsernamePassword()
+        throws Exception
+    {
+        String releaseUsername = "invalid";
+        String releasePassword = "invalid";
+
+        showProjectGroup( projectGroupName, projectGroupId, "" );
+        clickButtonWithValue( RELEASE_BUTTON_TEXT );
+        assertReleaseChoicePage();
+        releasePrepareProject( releaseUsername, releasePassword, tagBase, "simple-example-13.0", "13.0",
+                               "13.1-SNAPSHOT", null );
+        assertReleasePhaseError();
+    }
+
+    public void testReleasePrepareProject()
+        throws Exception
+    {
+        showProjectGroup( projectGroupName, projectGroupId, projectGroupId );
+
+        clickButtonWithValue( RELEASE_BUTTON_TEXT );
+        assertReleaseChoicePage();
+        releasePrepareProject( "", "", tagBase, tag, releaseVersion, developmentVersion, "" );
+
+        assertReleasePhaseSuccess();
+    }
+
+    @Test( dependsOnMethods = {"testReleasePrepareProject"} )
+    public void testReleasePerformUsingProvidedParameters()
+        throws Exception
+    {
+        String releaseUsername = "invalid";
+        String releasePassword = "invalid";
+
+        showProjectGroup( projectGroupName, projectGroupId, "" );
+        clickButtonWithValue( RELEASE_BUTTON_TEXT );
+        assertReleaseChoicePage();
+        releasePerformProjectWithProvideParameters( releaseUsername, releasePassword, tagBase, tag,
+                                                    releaseProjectScmUrl, "" );
+    }
+
+    // avoid the above test running between these so that the list of prepared releases is correct
+    @Test( dependsOnMethods = {"testReleasePrepareProject"} )
+    public void testReleasePrepareWithoutInterveningPerform()
+        throws IOException
+    {
+        // CONTINUUM-2687
+        showProjectGroup( projectGroupName, projectGroupId, "" );
+        clickButtonWithValue( RELEASE_BUTTON_TEXT );
+        assertReleaseChoicePage();
+
+        // first attempt
+        releasePrepareProject( "", "", tagBase, "simple-example-10.1", "10.1", "10.2-SNAPSHOT", "" );
+        assertReleasePhaseSuccess();
+        clickButtonWithValue( "Done" );
+
+        // second attempt
+        releasePrepareProject( "", "", tagBase, "simple-example-10.2", "10.2", "10.3-SNAPSHOT", "" );
+        assertReleasePhaseSuccess();
+        clickButtonWithValue( "Done" );
+
+        // check that two versions are present
+        Assert.assertEquals( Arrays.asList( getSelenium().getSelectOptions( "preparedReleaseId" ) ), Arrays.asList(
+            "10.0", "10.1", "10.2", PROVIDE_RELEASE_PARAMETERS_TEXT ) );
+
+        // check that 10.2 is selected by default
+        Assert.assertEquals( getSelenium().getSelectedLabel( "preparedReleaseId" ), "10.2" );
+
+        // test perform on 10.2
+        selectPerformAndSubmit();
+
+        setFieldValue( "goals", "clean validate" );
+        submit();
+
+        waitForRelease();
+
+        assertReleasePhaseSuccess();
+        clickButtonWithValue( "Done" );
+
+        // verify that it is removed from the list again
+        showProjectGroup( projectGroupName, projectGroupId, "" );
+        clickButtonWithValue( RELEASE_BUTTON_TEXT );
+        assertReleaseChoicePage();
+        Assert.assertEquals( Arrays.asList( getSelenium().getSelectOptions( "preparedReleaseId" ) ), Arrays.asList(
+            "10.0", "10.1", PROVIDE_RELEASE_PARAMETERS_TEXT ) );
+        Assert.assertEquals( getSelenium().getSelectedLabel( "preparedReleaseId" ), "10.1" );
+    }
+
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/ReportTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/ReportTest.java
new file mode 100644
index 0000000..40c3ede
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/ReportTest.java
@@ -0,0 +1,178 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 org.apache.continuum.web.test.parent.AbstractAdminTest;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+@Test( groups = { "report" } )
+public class ReportTest
+    extends AbstractAdminTest
+{
+    private String projectGroupName;
+
+    private String failedProjectGroupName;
+
+    @BeforeClass
+    public void createProject()
+    {
+        projectGroupName = getProperty( "REPORT_PROJECT_GROUP_NAME" );
+        String projectGroupId = getProperty( "REPORT_PROJECT_GROUP_ID" );
+        String projectGroupDescription = getProperty( "REPORT_PROJECT_GROUP_DESCRIPTION" );
+
+        String projectName = getProperty( "MAVEN2_POM_PROJECT_NAME" );
+        String projectPomUrl = getProperty( "MAVEN2_POM_URL" );
+        String pomUsername = getProperty( "MAVEN2_POM_USERNAME" );
+        String pomPassword = getProperty( "MAVEN2_POM_PASSWORD" );
+
+        loginAsAdmin();
+        addProjectGroup( projectGroupName, projectGroupId, projectGroupDescription, true, false );
+        clickLinkWithText( projectGroupName );
+        if ( !isLinkPresent( projectName ) )
+        {
+            addMavenTwoProject( projectPomUrl, pomUsername, pomPassword, projectGroupName, true );
+
+            buildProjectGroup( projectGroupName, projectGroupId, projectGroupDescription, projectName, true );
+        }
+    }
+
+    @BeforeMethod
+    protected void setUp()
+        throws Exception
+    {
+        failedProjectGroupName = getProperty( "MAVEN2_FAILING_PROJECT_POM_PROJECT_GROUP_NAME" );
+    }
+
+    @AfterMethod
+    public void tearDown()
+    {
+        removeProjectGroup( failedProjectGroupName, false );
+    }
+
+    public void testViewBuildsReportWithSuccessfulBuild()
+        throws Exception
+    {
+        goToProjectBuildsReport();
+        selectValue( "buildStatus", "Ok" );
+        clickButtonWithValue( "View Report" );
+
+        assertProjectBuildReportWithResult();
+        assertTextPresent( projectGroupName );
+        assertImgWithAlt( "Success" );
+    }
+
+    /*@Test( dependsOnMethods = { "testProjectGroupAllBuildSuccess" } )
+    public void testBuildsReportPagination()
+        throws Exception
+    {
+        String M2_PROJ_GRP_NAME = getProperty( "M2_PROJ_GRP_NAME" );
+        String M2_PROJ_GRP_ID = getProperty( "M2_PROJ_GRP_ID" );
+        String M2_PROJ_GRP_DESCRIPTION = getProperty( "M2_PROJ_GRP_DESCRIPTION" );
+
+        for ( int ctr = 0; ctr < 10; ctr++ )
+        {
+            buildProjectGroup( M2_PROJ_GRP_NAME, M2_PROJ_GRP_ID, M2_PROJ_GRP_DESCRIPTION, M2_PROJ_GRP_NAME, true );
+            clickButtonWithValue( "Release" );
+            assertReleaseSuccess();
+        }
+
+        goToProjectBuildsReport();
+        setFieldValue( "rowCount", "10" );
+        clickButtonWithValue( "View Report" );
+
+        assertProjectBuildReportWithResult();
+        assertLinkNotPresent( "Prev" );
+        assertLinkNotPresent( "1" );
+        assertLinkPresent( "2" );
+        assertLinkPresent( "Next" );
+
+        clickLinkWithText( "2" );
+        assertProjectBuildReportWithResult();
+        assertLinkNotPresent( "Next" );
+        assertLinkNotPresent( "2" );
+        assertLinkPresent( "1" );
+        assertLinkPresent( "Prev" );
+
+        clickLinkWithText( "Prev" );
+        assertProjectBuildReportWithResult();
+        assertLinkNotPresent( "Prev" );
+        assertLinkNotPresent( "1" );
+        assertLinkPresent( "2" );
+        assertLinkPresent( "Next" );
+    }*/
+
+    public void testBuildsReportWithInvalidRowCount()
+    {
+        goToProjectBuildsReport();
+        setFieldValue( "rowCount", "1" );
+        clickButtonWithValue( "View Report" );
+
+        assertProjectBuildReportWithFieldError();
+        assertTextPresent( "Row count should be at least 10." );
+    }
+
+    public void testBuildsReportWithInvalidDates()
+    {
+        goToProjectBuildsReport();
+        setFieldValue( "startDate", "05/25/2010" );
+        setFieldValue( "endDate", "05/24/2010" );
+        clickButtonWithValue( "View Report" );
+
+        assertProjectBuildReportWithFieldError();
+        assertTextPresent( "Start Date must be earlier than the End Date" );
+    }
+
+    public void testViewBuildsReportWithFailedBuild()
+        throws Exception
+    {
+        String pomUrl = getProperty( "MAVEN2_FAILING_PROJECT_POM_URL" );
+        String pomUsername = "";
+        String pomPassword = "";
+
+        String failedProjectGroupId = getProperty( "MAVEN2_FAILING_PROJECT_POM_PROJECT_GROUP_ID" );
+        String failedProjectGroupDescription = getProperty( "MAVEN2_FAILING_PROJECT_POM_PROJECT_GROUP_DESCRIPTION" );
+
+        addMavenTwoProject( pomUrl, pomUsername, pomPassword, null, true );
+        assertProjectGroupSummaryPage( failedProjectGroupName, failedProjectGroupId, failedProjectGroupDescription );
+
+        buildProjectGroup( failedProjectGroupName, failedProjectGroupId, failedProjectGroupDescription,
+                           failedProjectGroupName, false );
+
+        goToProjectBuildsReport();
+        selectValue( "buildStatus", "Failed" );
+        clickButtonWithValue( "View Report" );
+
+        assertProjectBuildReportWithResult();
+        assertImgWithAlt( "Failed" );
+        assertTextPresent( failedProjectGroupName );
+    }
+
+    public void testViewBuildsReportWithErrorBuild()
+    {
+        goToProjectBuildsReport();
+        selectValue( "buildStatus", "Error" );
+        clickButtonWithValue( "View Report" );
+
+        assertProjectBuildReportWithNoResult();
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/ScheduleTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/ScheduleTest.java
new file mode 100644
index 0000000..86a24c7
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/ScheduleTest.java
@@ -0,0 +1,166 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 org.apache.continuum.web.test.parent.AbstractAdminTest;
+import org.testng.annotations.Test;
+
+/**
+ * @author José Morales Martínez
+ * @version $Id$
+ */
+@Test( groups = { "schedule" } )
+public class ScheduleTest
+    extends AbstractAdminTest
+{
+    public void testAddScheduleNoBuildQueueToBeUsed()
+    {
+        String SCHEDULE_NAME = getProperty( "SCHEDULE_NAME" );
+        String SCHEDULE_DESCRIPTION = getProperty( "SCHEDULE_DESCRIPTION" );
+        String SCHEDULE_EXPR_SECOND = getProperty( "SCHEDULE_EXPR_SECOND" );
+        String SCHEDULE_EXPR_MINUTE = getProperty( "SCHEDULE_EXPR_MINUTE" );
+        String SCHEDULE_EXPR_HOUR = getProperty( "SCHEDULE_EXPR_HOUR" );
+        String SCHEDULE_EXPR_DAY_MONTH = getProperty( "SCHEDULE_EXPR_DAY_MONTH" );
+        String SCHEDULE_EXPR_MONTH = getProperty( "SCHEDULE_EXPR_MONTH" );
+        String SCHEDULE_EXPR_DAY_WEEK = getProperty( "SCHEDULE_EXPR_DAY_WEEK" );
+        String SCHEDULE_EXPR_YEAR = getProperty( "SCHEDULE_EXPR_YEAR" );
+        String SCHEDULE_MAX_TIME = getProperty( "SCHEDULE_MAX_TIME" );
+        String SCHEDULE_PERIOD = getProperty( "SCHEDULE_PERIOD" );
+        goToAddSchedule();
+        addEditSchedule( SCHEDULE_NAME, SCHEDULE_DESCRIPTION, SCHEDULE_EXPR_SECOND, SCHEDULE_EXPR_MINUTE,
+                         SCHEDULE_EXPR_HOUR, SCHEDULE_EXPR_DAY_MONTH, SCHEDULE_EXPR_MONTH, SCHEDULE_EXPR_DAY_WEEK,
+                         SCHEDULE_EXPR_YEAR, SCHEDULE_MAX_TIME, SCHEDULE_PERIOD, false, false );
+        assertTextPresent( "Used Build Queues cannot be empty" );
+    }
+
+    @Test( dependsOnMethods = { "testAddScheduleNoBuildQueueToBeUsed" } )
+    public void testAddSchedule()
+    {
+        String SCHEDULE_NAME = getProperty( "SCHEDULE_NAME" );
+        String SCHEDULE_DESCRIPTION = getProperty( "SCHEDULE_DESCRIPTION" );
+        String SCHEDULE_EXPR_SECOND = getProperty( "SCHEDULE_EXPR_SECOND" );
+        String SCHEDULE_EXPR_MINUTE = getProperty( "SCHEDULE_EXPR_MINUTE" );
+        String SCHEDULE_EXPR_HOUR = getProperty( "SCHEDULE_EXPR_HOUR" );
+        String SCHEDULE_EXPR_DAY_MONTH = getProperty( "SCHEDULE_EXPR_DAY_MONTH" );
+        String SCHEDULE_EXPR_MONTH = getProperty( "SCHEDULE_EXPR_MONTH" );
+        String SCHEDULE_EXPR_DAY_WEEK = getProperty( "SCHEDULE_EXPR_DAY_WEEK" );
+        String SCHEDULE_EXPR_YEAR = getProperty( "SCHEDULE_EXPR_YEAR" );
+        String SCHEDULE_MAX_TIME = getProperty( "SCHEDULE_MAX_TIME" );
+        String SCHEDULE_PERIOD = getProperty( "SCHEDULE_PERIOD" );
+        goToAddSchedule();
+        addEditSchedule( SCHEDULE_NAME, SCHEDULE_DESCRIPTION, SCHEDULE_EXPR_SECOND, SCHEDULE_EXPR_MINUTE,
+                         SCHEDULE_EXPR_HOUR, SCHEDULE_EXPR_DAY_MONTH, SCHEDULE_EXPR_MONTH, SCHEDULE_EXPR_DAY_WEEK,
+                         SCHEDULE_EXPR_YEAR, SCHEDULE_MAX_TIME, SCHEDULE_PERIOD, true, true );
+    }
+
+    @Test( dependsOnMethods = { "testAddScheduleNoBuildQueueToBeUsed" } )
+    public void testAddScheduleWithInvalidValues()
+    {
+        String SCHEDULE_NAME = "!@#$<>?etc";
+        String SCHEDULE_DESCRIPTION = "![]<>'^&etc";
+        String SCHEDULE_EXPR_SECOND = getProperty( "SCHEDULE_EXPR_SECOND" );
+        String SCHEDULE_EXPR_MINUTE = getProperty( "SCHEDULE_EXPR_MINUTE" );
+        String SCHEDULE_EXPR_HOUR = getProperty( "SCHEDULE_EXPR_HOUR" );
+        String SCHEDULE_EXPR_DAY_MONTH = getProperty( "SCHEDULE_EXPR_DAY_MONTH" );
+        String SCHEDULE_EXPR_MONTH = getProperty( "SCHEDULE_EXPR_MONTH" );
+        String SCHEDULE_EXPR_DAY_WEEK = getProperty( "SCHEDULE_EXPR_DAY_WEEK" );
+        String SCHEDULE_EXPR_YEAR = getProperty( "SCHEDULE_EXPR_YEAR" );
+        String SCHEDULE_MAX_TIME = getProperty( "SCHEDULE_MAX_TIME" );
+        String SCHEDULE_PERIOD = getProperty( "SCHEDULE_PERIOD" );
+        goToAddSchedule();
+        addEditSchedule( SCHEDULE_NAME, SCHEDULE_DESCRIPTION, SCHEDULE_EXPR_SECOND, SCHEDULE_EXPR_MINUTE,
+                         SCHEDULE_EXPR_HOUR, SCHEDULE_EXPR_DAY_MONTH, SCHEDULE_EXPR_MONTH, SCHEDULE_EXPR_DAY_WEEK,
+                         SCHEDULE_EXPR_YEAR, SCHEDULE_MAX_TIME, SCHEDULE_PERIOD, true, false );
+        assertTextPresent( "Name contains invalid characters." );
+    }
+
+    public void testAddInvalidSchedule()
+    {
+        goToAddSchedule();
+        addEditSchedule( "", "", "", "", "", "", "", "", "", "", "", true, false );
+        assertTextPresent( "Invalid cron expression value(s)" );
+        assertTextPresent( "Name is required and cannot contain spaces only" );
+        assertTextPresent( "Description is required and cannot contain spaces only" );
+    }
+
+    @Test( dependsOnMethods = { "testAddSchedule" } )
+    public void testAddDuplicatedSchedule()
+    {
+        String SCHEDULE_NAME = getProperty( "SCHEDULE_NAME" );
+        String SCHEDULE_DESCRIPTION = getProperty( "SCHEDULE_DESCRIPTION" );
+        String SCHEDULE_EXPR_SECOND = getProperty( "SCHEDULE_EXPR_SECOND" );
+        String SCHEDULE_EXPR_MINUTE = getProperty( "SCHEDULE_EXPR_MINUTE" );
+        String SCHEDULE_EXPR_HOUR = getProperty( "SCHEDULE_EXPR_HOUR" );
+        String SCHEDULE_EXPR_DAY_MONTH = getProperty( "SCHEDULE_EXPR_DAY_MONTH" );
+        String SCHEDULE_EXPR_MONTH = getProperty( "SCHEDULE_EXPR_MONTH" );
+        String SCHEDULE_EXPR_DAY_WEEK = getProperty( "SCHEDULE_EXPR_DAY_WEEK" );
+        String SCHEDULE_EXPR_YEAR = getProperty( "SCHEDULE_EXPR_YEAR" );
+        String SCHEDULE_MAX_TIME = getProperty( "SCHEDULE_MAX_TIME" );
+        String SCHEDULE_PERIOD = getProperty( "SCHEDULE_PERIOD" );
+        goToAddSchedule();
+        addEditSchedule( SCHEDULE_NAME, SCHEDULE_DESCRIPTION, SCHEDULE_EXPR_SECOND, SCHEDULE_EXPR_MINUTE,
+                         SCHEDULE_EXPR_HOUR, SCHEDULE_EXPR_DAY_MONTH, SCHEDULE_EXPR_MONTH, SCHEDULE_EXPR_DAY_WEEK,
+                         SCHEDULE_EXPR_YEAR, SCHEDULE_MAX_TIME, SCHEDULE_PERIOD, true, false );
+        assertTextPresent( "A Schedule with the same name already exists" );
+    }
+
+    @Test( dependsOnMethods = { "testAddDuplicatedSchedule" } )
+    public void testEditSchedule()
+    {
+        String SCHEDULE_NAME = getProperty( "SCHEDULE_NAME" );
+        String SCHEDULE_DESCRIPTION = getProperty( "SCHEDULE_DESCRIPTION" );
+        String SCHEDULE_EXPR_SECOND = getProperty( "SCHEDULE_EXPR_SECOND" );
+        String SCHEDULE_EXPR_MINUTE = getProperty( "SCHEDULE_EXPR_MINUTE" );
+        String SCHEDULE_EXPR_HOUR = getProperty( "SCHEDULE_EXPR_HOUR" );
+        String SCHEDULE_EXPR_DAY_MONTH = getProperty( "SCHEDULE_EXPR_DAY_MONTH" );
+        String SCHEDULE_EXPR_MONTH = getProperty( "SCHEDULE_EXPR_MONTH" );
+        String SCHEDULE_EXPR_DAY_WEEK = getProperty( "SCHEDULE_EXPR_DAY_WEEK" );
+        String SCHEDULE_EXPR_YEAR = getProperty( "SCHEDULE_EXPR_YEAR" );
+        String SCHEDULE_MAX_TIME = getProperty( "SCHEDULE_MAX_TIME" );
+        String SCHEDULE_PERIOD = getProperty( "SCHEDULE_PERIOD" );
+        String name = "new_name";
+        String description = "new_description";
+        String second = "1";
+        String minute = "20";
+        String hour = "15";
+        String dayMonth = "20";
+        String month = "9";
+        String dayWeek = "?";
+        String year = "";
+        String maxTime = "9000";
+        String period = "0";
+        goToEditSchedule( SCHEDULE_NAME, SCHEDULE_DESCRIPTION, SCHEDULE_EXPR_SECOND, SCHEDULE_EXPR_MINUTE,
+                          SCHEDULE_EXPR_HOUR, SCHEDULE_EXPR_DAY_MONTH, SCHEDULE_EXPR_MONTH, SCHEDULE_EXPR_DAY_WEEK,
+                          SCHEDULE_EXPR_YEAR, SCHEDULE_MAX_TIME, SCHEDULE_PERIOD );
+        addEditSchedule( name, description, second, minute, hour, dayMonth, month, dayWeek, year, maxTime, period,
+                         false, true );
+        goToEditSchedule( name, description, second, minute, hour, dayMonth, month, dayWeek, year, maxTime, period );
+        addEditSchedule( SCHEDULE_NAME, SCHEDULE_DESCRIPTION, SCHEDULE_EXPR_SECOND, SCHEDULE_EXPR_MINUTE,
+                         SCHEDULE_EXPR_HOUR, SCHEDULE_EXPR_DAY_MONTH, SCHEDULE_EXPR_MONTH, SCHEDULE_EXPR_DAY_WEEK,
+                         SCHEDULE_EXPR_YEAR, SCHEDULE_MAX_TIME, SCHEDULE_PERIOD, false, true );
+    }
+
+    @Test( dependsOnMethods = { "testEditSchedule" } )
+    public void testDeleteSchedule()
+    {
+        String SCHEDULE_NAME = getProperty( "SCHEDULE_NAME" );
+        removeSchedule( SCHEDULE_NAME );
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/ShellProjectTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/ShellProjectTest.java
new file mode 100644
index 0000000..0b1cda9
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/ShellProjectTest.java
@@ -0,0 +1,126 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 org.apache.continuum.web.test.parent.AbstractAdminTest;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * Based on AddShellProjectTestCase of Emmanuel Venisse.
+ *
+ * @author José Morales Martínez
+ * @version $Id$
+ */
+@Test( groups = {"shellProject"} )
+public class ShellProjectTest
+    extends AbstractAdminTest
+{
+    private String projectGroupId;
+
+    private String projectGroupName;
+
+    private String projectGroupDescription;
+
+    private String scmPassword;
+
+    private String scmUsername;
+
+    private String scmUrl;
+
+    private String scmTag;
+
+    private String projectVersion;
+
+    private String projectDescription;
+
+    private String projectName;
+
+    @BeforeMethod
+    public void setUp()
+    {
+        projectGroupId = getProperty( "SHELL_PROJECT_GROUP_ID" );
+        projectGroupName = getProperty( "SHELL_PROJECT_GROUP_NAME" );
+        projectGroupDescription = getProperty( "SHELL_PROJECT_GROUP_DESCRIPTION" );
+        projectName = getProperty( "SHELL_NAME" );
+        projectDescription = getProperty( "SHELL_DESCRIPTION" );
+        projectVersion = getProperty( "SHELL_VERSION" );
+        scmUrl = getProperty( "SHELL_SCM_URL" );
+        scmUsername = getProperty( "SHELL_SCM_USERNAME" );
+        scmPassword = getProperty( "SHELL_SCM_PASSWORD" );
+        scmTag = getProperty( "SHELL_TAG" );
+
+        addProjectGroup( projectGroupName, projectGroupId, projectGroupDescription, true, false );
+    }
+
+    @AfterClass
+    public void cleanup()
+    {
+        removeProjectGroup( projectGroupName );
+    }
+
+    public void testAddShellProject()
+        throws Exception
+    {
+        goToAddShellProjectPage();
+        addProject( projectName, projectDescription, projectVersion, scmUrl, scmUsername, scmPassword, scmTag,
+                    projectGroupName, true, "shell" );
+        assertProjectGroupSummaryPage( projectGroupName, projectGroupId, projectGroupDescription );
+    }
+
+    public void testAddShellProjectWithInvalidValues()
+        throws Exception
+    {
+        String projectName = "!@#$<>?etc";
+        String description = "![]<>'^&etc";
+        String version = "<>whitespaces!#etc";
+        String tag = "!<>*%etc";
+        String scmUrl = "!<>*%etc";
+        goToAddShellProjectPage();
+        addProject( projectName, description, version, scmUrl, scmUsername, scmPassword, tag, projectGroupName, false,
+                    "shell" );
+        assertTextPresent( "Name contains invalid characters." );
+        assertTextPresent( "Version contains invalid characters." );
+        assertTextPresent( "SCM Url contains invalid characters." );
+        assertTextPresent( "SCM Tag contains invalid characters." );
+    }
+
+    public void testSubmitEmptyForm()
+    {
+        goToAddShellProjectPage();
+        submit();
+        assertAddProjectPage( "shell" );
+        assertTextPresent( "Name is required and cannot contain null or spaces only" );
+        assertTextPresent( "Version is required and cannot contain null or spaces only" );
+        assertTextPresent( "SCM Url is required and cannot contain null or spaces only" );
+    }
+
+    @Test( dependsOnMethods = {"testAddShellProject"} )
+    public void testAddDuplicateShellProject()
+        throws Exception
+    {
+        goToAddShellProjectPage();
+        addProject( projectName, projectDescription, projectVersion, scmUrl, scmUsername, scmPassword, scmTag, null,
+                    false, "shell" );
+        assertTextPresent( "Project name already exist" );
+    }
+
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/UserRolesManagementTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/UserRolesManagementTest.java
new file mode 100644
index 0000000..b38d4cd
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/UserRolesManagementTest.java
@@ -0,0 +1,656 @@
+package org.apache.continuum.web.test;
+
+/*
+ * 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 org.apache.continuum.web.test.parent.AbstractUserRolesManagementTest;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Test( groups = {"userroles"}, sequential = true )
+public class UserRolesManagementTest
+    extends AbstractUserRolesManagementTest
+{
+
+    public static final String TEST_GROUP = "UserRoles Test Group";
+
+    private List<String> usernames = new ArrayList<String>();
+
+    public void testBasicAddDeleteUser()
+    {
+        username = getProperty( "GUEST_USERNAME" );
+        fullname = getProperty( "GUEST_FULLNAME" );
+
+        createUser( username, fullname, getUserEmail(), getUserRolePassword() );
+        deleteUser( username );
+        clickLinkWithText( "Logout" );
+    }
+
+    /*
+     * GUEST USER ROLE
+     * Guest Role could only view the About Page. Project Groups should not be shown when clicking
+     * Show Project Group link.
+    */
+    @Test( dependsOnMethods = {"testBasicAddDeleteUser"} )
+    public void testAddUserWithGuestRole()
+    {
+        username = getProperty( "GUEST_USERNAME" );
+        fullname = getProperty( "GUEST_FULLNAME" );
+
+        createUser( username, fullname, getUserEmail(), getUserRolePassword() );
+        assertCreatedUserInfo( username );
+        //checkUserRoleWithValue( fullname );
+        clickLinkWithLocator( "addRolesToUser_addNDSelectedRoles", false );
+        clickButtonWithValue( "Submit" );
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRolePassword() );
+        changePassword( getUserRolePassword(), getUserRoleNewPassword() );
+        //assertTextPresent( "Password successfully changed" );        
+        clickLinkWithText( "Logout" );
+    }
+
+    @Test( dependsOnMethods = {"testAddUserWithGuestRole"} )
+    public void testGuestUserRoleFunction()
+    {
+        username = getProperty( "GUEST_USERNAME" );
+        fullname = getProperty( "GUEST_FULLNAME" );
+        loginAs( username, getUserRoleNewPassword() );
+        assertLeftNavMenuWithRole( fullname );
+        goToAboutPage();
+        clickLinkWithText( "Show Project Groups" );
+        assertTextPresent( "Project Groups list is empty" );
+        clickLinkWithText( "Logout" );
+    }
+
+
+    /*
+     * REGISTERED USER ROLE
+     * Registered User Role could only view the About Page. Project Groups should not be shown when clicking
+     * Show Project Group link.
+    */
+    @Test( dependsOnMethods = {"testBasicAddDeleteUser", "testGuestUserRoleFunction"} )
+    public void testAddUserWithRegisteredUserRole()
+    {
+        username = getProperty( "REGISTERED_USERNAME" );
+        fullname = getProperty( "REGISTERED_FULLNAME" );
+
+        createUser( username, fullname, getUserEmail(), getUserRolePassword() );
+        assertCreatedUserInfo( username );
+        checkUserRoleWithValue( fullname );
+        clickButtonWithValue( "Submit" );
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRolePassword() );
+        changePassword( getUserRolePassword(), getUserRoleNewPassword() );
+        assertTextPresent( "Password successfully changed" );
+
+        clickLinkWithText( "Logout" );
+        // assertTextPresent("You are already logged in.");
+    }
+
+    @Test( dependsOnMethods = {"testAddUserWithRegisteredUserRole"} )
+    public void testRegisteredRoleFunction()
+    {
+        username = getProperty( "REGISTERED_USERNAME" );
+        fullname = getProperty( "REGISTERED_FULLNAME" );
+        login( username, getUserRoleNewPassword() );
+        assertLeftNavMenuWithRole( fullname );
+        goToAboutPage();
+        clickLinkWithText( "Show Project Groups" );
+        assertTextPresent( "Project Groups list is empty." );
+        clickLinkWithText( "Logout" );
+    }
+
+    /*
+     * SYSTEM ADMINISTRATOR ROLE
+     * Has access to all functions in the application.
+     *
+     * The following tests only asserts elements that could be shown 
+     * when system admin user is logged in since the user that is used 
+     * to test the other functionalities is a system admin user.
+     */
+    @Test( dependsOnMethods = {"testBasicAddDeleteUser", "testRegisteredRoleFunction"} )
+    public void testAddUserWithSystemAdminRole()
+    {
+        username = getProperty( "SYSAD_USERNAME" );
+        fullname = getProperty( "SYSAD_FULLNAME" );
+
+        createUser( username, fullname, getUserEmail(), getUserRolePassword() );
+        assertCreatedUserInfo( username );
+        checkUserRoleWithValue( fullname );
+        clickButtonWithValue( "Submit" );
+
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRolePassword() );
+        changePassword( getUserRolePassword(), getUserRoleNewPassword() );
+        assertTextPresent( "Password successfully changed" );
+
+        clickLinkWithText( "Logout" );
+    }
+
+    @Test( dependsOnMethods = {"testAddUserWithSystemAdminRole"} )
+    public void testSystemAdminRoleFunction()
+    {
+        username = getProperty( "SYSAD_USERNAME" );
+        fullname = getProperty( "SYSAD_FULLNAME" );
+        login( username, getUserRoleNewPassword() );
+        assertLeftNavMenuWithRole( fullname );
+        clickLinkWithText( "Show Project Groups" );
+        assertTextNotPresent( "Project Groups list is empty." );
+        assertLinkPresent( "Default Project Group" );
+
+        clickLinkWithText( "Logout" );
+    }
+
+    /* 
+     * USER ADMIN ROLE
+     * User Admin role could only add/edit/delete users and can view user Roles. Cannot view Project Groups
+     * but can assign a User to a project.
+     *
+     */
+    @Test( dependsOnMethods = {"testBasicAddDeleteUser", "testSystemAdminRoleFunction"} )
+    public void testAddUserWithUserAdminRole()
+    {
+        username = getProperty( "USERADMIN_USERNAME" );
+        fullname = getProperty( "USERADMIN_FULLNAME" );
+
+        createUser( username, fullname, getUserEmail(), getUserRolePassword() );
+        assertCreatedUserInfo( username );
+        checkUserRoleWithValue( fullname );
+        clickButtonWithValue( "Submit" );
+
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRolePassword() );
+        changePassword( getUserRolePassword(), getUserRoleNewPassword() );
+        assertTextPresent( "Password successfully changed" );
+
+        clickLinkWithText( "Logout" );
+    }
+
+    @Test( dependsOnMethods = {"testAddUserWithUserAdminRole"} )
+    public void testUserAdminFunction()
+    {
+        username = getProperty( "USERADMIN_USERNAME" );
+        fullname = getProperty( "USERADMIN_FULLNAME" );
+        login( username, getUserRoleNewPassword() );
+        assertLeftNavMenuWithRole( fullname );
+        clickLinkWithText( "Show Project Groups" );
+        assertTextPresent( "Project Groups list is empty." );
+        // add user
+        clickLinkWithText( "Users" );
+        clickButtonWithValue( "Create New User" );
+        assertCreateUserPage();
+        setFieldValue( "user.username", "guest0" );
+        setFieldValue( "user.fullName", "guest0" );
+        setFieldValue( "user.email", "guest0@guest0.com" );
+        setFieldValue( "user.password", "pass" );
+        setFieldValue( "user.confirmPassword", "pass" );
+        submit();
+        assertUserRolesPage();
+        clickButtonWithValue( "Submit" );
+        selectValue( "name=ec_rd", "50" );
+        waitPage();
+        // delete user	
+        deleteUser( "guest0" );
+        // TODO edit user
+
+        clickLinkWithText( "Logout" );
+    }
+
+    /*
+     * CONTINUUM GROUP PROJECT ADMIN
+     * - Can Add/Edit/Delete Project Group, can Add/Edit/Delete projects, can assign Users
+     *    roles to existing projects, can add/edit/delete schedules, can view existing roles for the
+     *    projects, can build/release projects
+     * - Cannot add users, --- --- ---
+     */
+    @Test( dependsOnMethods = {"testBasicAddDeleteUser", "testUserAdminFunction"} )
+    public void testAddUserWithContinuumGroupProjectAdminRole()
+    {
+        username = getProperty( "GROUPPROJECTADMIN_USERNAME" );
+        fullname = getProperty( "GROUPPROJECTADMIN_FULLNAME" );
+
+        createUser( username, fullname, getUserEmail(), getUserRolePassword() );
+        assertCreatedUserInfo( username );
+        checkUserRoleWithValue( fullname );
+        clickButtonWithValue( "Submit" );
+
+        // enable distributed build
+        clickLinkWithText( "Configuration" );
+        checkField( "distributedBuildEnabled" );
+        clickButtonWithValue( "Save" );
+
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRolePassword() );
+        changePassword( getUserRolePassword(), getUserRoleNewPassword() );
+        assertTextPresent( "Password successfully changed" );
+
+        assertProjectAdministratorAccess();
+
+        clickLinkWithText( "Logout" );
+
+        loginAsAdmin();
+        // disable distributed build
+        clickLinkWithText( "Configuration" );
+        uncheckField( "distributedBuildEnabled" );
+        clickButtonWithValue( "Save" );
+
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRoleNewPassword() );
+        assertProjectAdministratorAccess();
+
+        clickLinkWithText( "Logout" );
+    }
+
+    @Test( dependsOnMethods = {"testAddUserWithContinuumGroupProjectAdminRole"} )
+    public void testContinuumGroupProjectAdmin_AddProjectGroup()
+        throws Exception
+    {
+        username = getProperty( "GROUPPROJECTADMIN_USERNAME" );
+        fullname = getProperty( "GROUPPROJECTADMIN_FULLNAME" );
+        login( username, getUserRoleNewPassword() );
+        assertLeftNavMenuWithRole( fullname );
+        clickLinkWithText( "Show Project Groups" );
+        assertTextNotPresent( "Project Groups list is empty." );
+        // test add project group
+        clickButtonWithValue( "Add Project Group" );
+        setFieldValue( "name", TEST_GROUP );
+        setFieldValue( "groupId", TEST_GROUP );
+        setFieldValue( "description", "testing project group" );
+        submit();
+    }
+
+    @Test( dependsOnMethods = {"testContinuumGroupProjectAdmin_AddProjectGroup"} )
+    public void testContinuumGroupProjectAdmin_AddProjectToProjectGroup()
+        throws Exception
+    {
+        clickLinkWithText( TEST_GROUP );
+        clickButtonWithValue( "Add" );
+        assertAddMavenTwoProjectPage();
+        setFieldValue( "m2PomUrl", getProperty( "M2_POM_URL" ) );
+        clickButtonWithValue( "Add" );
+        waitAddProject( "Continuum - Project Group" );
+        assertTextPresent( "ContinuumBuildQueueTestData" );
+        waitForProjectCheckout();
+    }
+
+    @Test( dependsOnMethods = {"testContinuumGroupProjectAdmin_AddProjectToProjectGroup"} )
+    public void testContinuumGroupProjectAdmin_BuildProject()
+        throws Exception
+    {
+        buildProjectGroup( TEST_GROUP, TEST_GROUP, "testing project group", "ContinuumBuildQueueTestData", true );
+    }
+
+    @Test( dependsOnMethods = {"testContinuumGroupProjectAdmin_BuildProject"} )
+    public void testContinuumGroupProjectAdmin_AssignUserToAGroup()
+    {
+        clickLinkWithText( "Users" );
+        clickLinkWithText( "guest1" );
+        clickLinkWithText( "Edit Roles" );
+        checkUserRoleWithValue( "Guest" );
+        checkResourceRoleWithValue( "Project Developer - " + TEST_GROUP );
+        submit();
+        clickLinkWithText( "Logout" );
+    }
+
+    /*
+     * Uncomment the lines below to release a Project provided that you add
+     * the values under RELEASE A PROJECT in testng.properties file (project's pom url, access to project to be released.)
+    	
+    @Test( dependsOnMethods = { "testContinuumGroupProjectAdmin_AssignUserToAGroup" } )
+    public void testContinuumGroupProjectAdmin_ReleaseProject() throws Exception
+    {
+	String projectUrl = getProperty( "PROJECT_URL_TO_BE_RELEASED" );
+	String projectName = getProperty( "PROJECT_NAME_TO_BE_RELEASED" );
+	String projectUsername = getProperty( "PROJECT_USERNAME" );
+	String projectPassword = getProperty( "PROJECT_USERNAME" );
+	// add a project group
+	clickLinkWithText( "Show Project Groups" );
+	clickButtonWithValue( "Add Project Group" );
+	setFieldValue( "name", "Project Group" );
+        setFieldValue( "groupId", "Project Group" );
+        setFieldValue( "description", "project group for projects to be released" );
+	submit();
+	// add a project to a project group
+	clickLinkWithText( "Project Group" );
+	clickButtonWithValue( "Add" );
+	assertAddMavenTwoProjectPage();
+	setFieldValue( "m2PomUrl", projectUrl );
+	// set username and password here
+	setFieldValue( "scmUsername", projectUsername );
+	setFieldValue( "scmPassword", projectPassword );
+	clickButtonWithValue( "Add" );
+	String title;
+	boolean success = true;
+	if ( success )
+        {
+            title = "Continuum - Project Group";
+        }
+        else
+        {
+            title = "Continuum - Add Maven Project";
+        }
+        waitAddProject( title );
+	// build the project added in the project group
+	buildProjectGroup( "Project Group", "Project Group", "project group for projects to be released", projectName );
+	// release the project
+	clickButtonWithValue( "Release" );
+	clickLinkWithText( "Logout" );
+        login( getAdminUsername(), getAdminPassword() );
+    }
+    */
+
+    @Test( dependsOnMethods = {"testContinuumGroupProjectAdmin_AssignUserToAGroup"} )
+    public void testUserWithContinuumGroupProjectDeveloperRole()
+    {
+        username = getProperty( "GROUPPROJECTDEVELOPER_USERNAME" );
+        fullname = getProperty( "GROUPPROJECTDEVELOPER_FULLNAME" );
+
+        createUser( username, fullname, getUserEmail(), getUserRolePassword() );
+        assertCreatedUserInfo( username );
+        checkUserRoleWithValue( fullname );
+        clickButtonWithValue( "Submit" );
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRolePassword() );
+        changePassword( getUserRolePassword(), getUserRoleNewPassword() );
+        assertTextPresent( "Password successfully changed" );
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRoleNewPassword() );
+        assertLeftNavMenuWithRole( fullname );
+        clickLinkWithText( "Logout" );
+    }
+
+    @Test( dependsOnMethods = {"testUserWithContinuumGroupProjectDeveloperRole"} )
+    public void testUserWithContinuumGroupProjectUserRole()
+    {
+        username = getProperty( "GROUPPROJECTUSER_USERNAME" );
+        fullname = getProperty( "GROUPPROJECTUSER_FULLNAME" );
+
+        createUser( username, fullname, getUserEmail(), getUserRolePassword() );
+        assertCreatedUserInfo( username );
+        checkUserRoleWithValue( fullname );
+        clickButtonWithValue( "Submit" );
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRolePassword() );
+        changePassword( getUserRolePassword(), getUserRoleNewPassword() );
+        assertTextPresent( "Password successfully changed" );
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRoleNewPassword() );
+        assertLeftNavMenuWithRole( fullname );
+        clickLinkWithText( "Logout" );
+    }
+
+    @Test( dependsOnMethods = {"testUserWithContinuumGroupProjectUserRole"} )
+    public void testUserWithContinuumManageBuildEnvironmentRole()
+    {
+        username = getProperty( "MANAGEBUILDENVIRONMENT_USERNAME" );
+        fullname = getProperty( "MANAGEBUILDENVIRONMENT_FULLNAME" );
+
+        createUser( username, fullname, getUserEmail(), getUserRolePassword() );
+        assertCreatedUserInfo( username );
+        checkUserRoleWithValue( fullname );
+        clickButtonWithValue( "Submit" );
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRolePassword() );
+        changePassword( getUserRolePassword(), getUserRoleNewPassword() );
+        assertTextPresent( "Password successfully changed" );
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRoleNewPassword() );
+        assertLeftNavMenuWithRole( fullname );
+        clickLinkWithText( "Logout" );
+    }
+
+    @Test( dependsOnMethods = {"testUserWithContinuumManageBuildEnvironmentRole"} )
+    public void testUserWithContinuumManageBuildTemplatesRole()
+    {
+        username = getProperty( "MANAGEBUILDTEMPLATES_USERNAME" );
+        fullname = getProperty( "MANAGEBUILDTEMPLATES_FULLNAME" );
+
+        createUser( username, fullname, getUserEmail(), getUserRolePassword() );
+        assertCreatedUserInfo( username );
+        checkUserRoleWithValue( fullname );
+        clickButtonWithValue( "Submit" );
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRolePassword() );
+        changePassword( getUserRolePassword(), getUserRoleNewPassword() );
+        assertTextPresent( "Password successfully changed" );
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRoleNewPassword() );
+        assertLeftNavMenuWithRole( fullname );
+        clickLinkWithText( "Logout" );
+    }
+
+    @Test( dependsOnMethods = {"testUserWithContinuumManageBuildTemplatesRole"} )
+    public void testUserWithContinuumManageInstallationsRole()
+    {
+        username = getProperty( "MANAGEINSTALLATIONS_USERNAME" );
+        fullname = getProperty( "MANAGEINSTALLATIONS_FULLNAME" );
+
+        createUser( username, fullname, getUserEmail(), getUserRolePassword() );
+        assertCreatedUserInfo( username );
+        checkUserRoleWithValue( fullname );
+        clickButtonWithValue( "Submit" );
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRolePassword() );
+        changePassword( getUserRolePassword(), getUserRoleNewPassword() );
+        assertTextPresent( "Password successfully changed" );
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRoleNewPassword() );
+        assertLeftNavMenuWithRole( fullname );
+        clickLinkWithText( "Logout" );
+    }
+
+    @Test( dependsOnMethods = {"testUserWithContinuumManageInstallationsRole"} )
+    public void testUserWithContinuumManageLocalRepoRole()
+    {
+        username = getProperty( "MANAGELOCALREPOS_USERNAME" );
+        fullname = getProperty( "MANAGELOCALREPOS_FULLNAME" );
+
+        createUser( username, fullname, getUserEmail(), getUserRolePassword() );
+        assertCreatedUserInfo( username );
+        checkUserRoleWithValue( fullname );
+        clickButtonWithValue( "Submit" );
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRolePassword() );
+        changePassword( getUserRolePassword(), getUserRoleNewPassword() );
+        assertTextPresent( "Password successfully changed" );
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRoleNewPassword() );
+        assertLeftNavMenuWithRole( fullname );
+        clickLinkWithText( "Logout" );
+    }
+
+    @Test( dependsOnMethods = {"testUserWithContinuumManageLocalRepoRole"} )
+    public void testUserWithContinuumManagePurgingRole()
+    {
+        username = getProperty( "MANAGEPURGING_USERNAME" );
+        fullname = getProperty( "MANAGEPURGING_FULLNAME" );
+
+        createUser( username, fullname, getUserEmail(), getUserRolePassword() );
+        assertCreatedUserInfo( username );
+        checkUserRoleWithValue( fullname );
+        clickButtonWithValue( "Submit" );
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRolePassword() );
+        changePassword( getUserRolePassword(), getUserRoleNewPassword() );
+        assertTextPresent( "Password successfully changed" );
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRoleNewPassword() );
+        assertLeftNavMenuWithRole( fullname );
+        clickLinkWithText( "Logout" );
+    }
+
+    @Test( dependsOnMethods = {"testUserWithContinuumManagePurgingRole"} )
+    public void testUserWithContinuumManageQueuesRole()
+    {
+        username = getProperty( "MANAGEQUEUES_USERNAME" );
+        fullname = getProperty( "MANAGEQUEUES_FULLNAME" );
+
+        createUser( username, fullname, getUserEmail(), getUserRolePassword() );
+        assertCreatedUserInfo( username );
+        checkUserRoleWithValue( fullname );
+        clickButtonWithValue( "Submit" );
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRolePassword() );
+        changePassword( getUserRolePassword(), getUserRoleNewPassword() );
+        assertTextPresent( "Password successfully changed" );
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRoleNewPassword() );
+        assertLeftNavMenuWithRole( fullname );
+        clickLinkWithText( "Logout" );
+    }
+
+    @Test( dependsOnMethods = {"testUserWithContinuumManageQueuesRole"} )
+    public void testUserWithContinuumManageSchedulingRole()
+    {
+        username = getProperty( "MANAGESCHEDULING_USERNAME" );
+        fullname = getProperty( "MANAGESCHEDULING_FULLNAME" );
+
+        createUser( username, fullname, getUserEmail(), getUserRolePassword() );
+        assertCreatedUserInfo( username );
+        checkUserRoleWithValue( fullname );
+        clickButtonWithValue( "Submit" );
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRolePassword() );
+        changePassword( getUserRolePassword(), getUserRoleNewPassword() );
+        assertTextPresent( "Password successfully changed" );
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRoleNewPassword() );
+        assertLeftNavMenuWithRole( fullname );
+        clickLinkWithText( "Logout" );
+    }
+
+    @Test( dependsOnMethods = {"testUserWithContinuumManageSchedulingRole"} )
+    public void testUserWithProjectAdminDefaultProjectGroup()
+    {
+        username = getProperty( "PROJECTADMINISTRATOR_DEFAULTPROJECTGROUP_USERNAME" );
+        fullname = getProperty( "PROJECTADMINISTRATOR_DEFAULTPROJECTGROUP_FULLNAME" );
+
+        createUser( username, fullname, getUserEmail(), getUserRolePassword() );
+        assertCreatedUserInfo( username );
+        checkResourceRoleWithValue( fullname );
+        clickButtonWithValue( "Submit" );
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRolePassword() );
+        changePassword( getUserRolePassword(), getUserRoleNewPassword() );
+        assertTextPresent( "Password successfully changed" );
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRoleNewPassword() );
+        assertLeftNavMenuWithRole( fullname );
+        clickLinkWithText( "Logout" );
+    }
+
+    @Test( dependsOnMethods = {"testUserWithProjectAdminDefaultProjectGroup"} )
+    public void testUserWithProjectDevDefaultProjectGroup()
+    {
+        username = getProperty( "PROJECTDEVELOPER_DEFAULTPROJECTGROUP_USERNAME" );
+        fullname = getProperty( "PROJECTDEVELOPER_DEFAULTPROJECTGROUP_FULLNAME" );
+
+        createUser( username, fullname, getUserEmail(), getUserRolePassword() );
+        assertCreatedUserInfo( username );
+        checkResourceRoleWithValue( fullname );
+        clickButtonWithValue( "Submit" );
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRolePassword() );
+        changePassword( getUserRolePassword(), getUserRoleNewPassword() );
+        assertTextPresent( "Password successfully changed" );
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRoleNewPassword() );
+        assertLeftNavMenuWithRole( fullname );
+        clickLinkWithText( "Logout" );
+    }
+
+    @Test( dependsOnMethods = {"testUserWithProjectDevDefaultProjectGroup"} )
+    public void testUserWithProjectUserDefaultProjectGroup()
+    {
+        username = getProperty( "PROJECTUSER_DEFAULTPROJECTGROUP_USERNAME" );
+        fullname = getProperty( "PROJECTUSER_DEFAULTPROJECTGROUP_FULLNAME" );
+
+        createUser( username, fullname, getUserEmail(), getUserRolePassword() );
+        assertCreatedUserInfo( username );
+        checkResourceRoleWithValue( fullname );
+        clickButtonWithValue( "Submit" );
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRolePassword() );
+        changePassword( getUserRolePassword(), getUserRoleNewPassword() );
+        assertTextPresent( "Password successfully changed" );
+        clickLinkWithText( "Logout" );
+
+        login( username, getUserRoleNewPassword() );
+        assertLeftNavMenuWithRole( fullname );
+        clickLinkWithText( "Logout" );
+    }
+
+    @AfterMethod
+    public void trackUserToDelete()
+    {
+        // record to delete at end, as some are used across dependent tests
+        // TODO: refactor!
+        usernames.add( username );
+    }
+
+    @AfterClass
+    public void cleanup()
+    {
+        loginAsAdmin();
+        if ( !isTextPresent( "List of Users" ) )
+        {
+            clickLinkWithText( "Users" );
+        }
+
+        for ( String username : usernames )
+        {
+            deleteUser( username, false );
+        }
+
+        removeProjectGroup( TEST_GROUP, false );
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/listener/CaptureScreenShotsListener.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/listener/CaptureScreenShotsListener.java
new file mode 100644
index 0000000..6aa5a7c
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/listener/CaptureScreenShotsListener.java
@@ -0,0 +1,162 @@
+package org.apache.continuum.web.test.listener;
+
+/*
+ * 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 com.thoughtworks.selenium.Selenium;
+import org.apache.commons.io.FileUtils;
+import org.apache.continuum.web.test.parent.AbstractSeleniumTest;
+import org.testng.ITestResult;
+import org.testng.TestListenerAdapter;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.regex.Pattern;
+
+public class CaptureScreenShotsListener
+    extends TestListenerAdapter
+{
+    @Override
+    public void onTestStart( ITestResult tr )
+    {
+        System.out.print( "Test " + tr.getName() + "... " );
+        super.onTestStart( tr );
+    }
+
+    @Override
+    public void onTestSkipped( ITestResult tr )
+    {
+        System.out.println( "Skipped" );
+        super.onTestSkipped( tr );
+    }
+
+    @Override
+    public void onTestFailure( ITestResult tr )
+    {
+        captureError( tr );
+        System.out.println( "Failed" );
+        super.onTestFailure( tr );
+    }
+
+    @Override
+    public void onTestSuccess( ITestResult tr )
+    {
+        System.out.println( "Success" );
+        super.onTestFailure( tr );
+    }
+
+    private void captureError( ITestResult tr )
+    {
+        captureScreenshotAndSource( tr.getTestClass().getName(), tr.getThrowable() );
+    }
+
+    public static void captureScreenshotAndSource( String cName, Throwable throwable )
+    {
+        Selenium selenium = AbstractSeleniumTest.getSelenium();
+        if ( selenium == null )
+        {
+            // avoid swallowing exception
+            System.err.println( "Not capturing screenshot as Selenium is not initialised" );
+            return;
+        }
+
+        String locator = "link=Show/hide Stack Trace";
+        if ( selenium.isElementPresent( locator ) )
+        {
+            selenium.click( locator );
+        }
+
+        SimpleDateFormat sdf = new SimpleDateFormat( "yyyy.MM.dd-HH_mm_ss" );
+        String time = sdf.format( new Date() );
+        File targetPath = new File( "target", "screenshots" );
+        StackTraceElement trace = getStackTraceOfCallingClass( cName, throwable.getStackTrace() );
+        String methodName;
+        int lNumber;
+        if ( trace == null )
+        {
+            System.err.println( "Unable to determine the calling method from class " + cName );
+            throwable.printStackTrace();
+            methodName = "unknown";
+            lNumber = 0;
+        }
+        else
+        {
+            methodName = trace.getMethodName();
+            lNumber = trace.getLineNumber();
+        }
+        String lineNumber = Integer.toString( lNumber );
+        String className = cName.substring( cName.lastIndexOf( '.' ) + 1 );
+        if ( !targetPath.exists() && !targetPath.mkdirs() )
+        {
+            System.out.println( "Unable to create screenshots directory" );
+            return;
+        }
+        String fileBaseName = methodName + "_" + className + ".java_" + lineNumber + "-" + time;
+
+        System.out.println( "Capturing screenshot at " + fileBaseName + ".png" );
+
+        try
+        {
+            selenium.windowMaximize();
+            File fileName = getFileName( targetPath, fileBaseName, ".png" );
+            selenium.captureEntirePageScreenshot( fileName.getAbsolutePath(), "" );
+        }
+        catch ( RuntimeException e )
+        {
+            System.out.println( "Error when take screenshot of error: " + e.getMessage() );
+        }
+        try
+        {
+            File fileName = getFileName( targetPath, fileBaseName, ".html" );
+            FileUtils.writeStringToFile( fileName, selenium.getHtmlSource() );
+        }
+        catch ( IOException ioe )
+        {
+            System.out.println( "Error writing HTML of error: " + ioe.getMessage() );
+        }
+    }
+
+    private static File getFileName( File targetPath, String fileBaseName, String ext )
+    {
+        File fileName = new File( targetPath, fileBaseName + ext );
+        int count = 0;
+        while ( fileName.exists() )
+        {
+            count++;
+            fileName = new File( targetPath, fileBaseName + "_" + count + ext );
+        }
+        return fileName;
+    }
+
+    private static StackTraceElement getStackTraceOfCallingClass( String nameOfClass, StackTraceElement stackTrace[] )
+    {
+        StackTraceElement lastMatch = null;
+        for ( StackTraceElement el : stackTrace )
+        {
+            String className = el.getClassName();
+            if ( Pattern.matches( nameOfClass, className ) )
+            {
+                lastMatch = el;
+            }
+        }
+        return lastMatch;
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/parent/AbstractAdminTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/parent/AbstractAdminTest.java
new file mode 100644
index 0000000..a50554b
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/parent/AbstractAdminTest.java
@@ -0,0 +1,371 @@
+package org.apache.continuum.web.test.parent;
+
+/*
+ * 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 org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Optional;
+import org.testng.annotations.Parameters;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+
+public abstract class AbstractAdminTest
+    extends AbstractContinuumTest
+{
+    protected String buildAgentUrl;
+
+    @BeforeMethod( alwaysRun = true )
+    public void loginAsAdmin()
+    {
+        loginAs( getProperty( "ADMIN_USERNAME" ), getProperty( "ADMIN_PASSWORD" ) );
+    }
+
+    protected void loginAs( String username, String password )
+    {
+        if ( !getSelenium().isElementPresent( "//span[@class='username' and text()='" + username + "']" ) )
+        {
+            login( username, password );
+
+            assertElementPresent( "//span[@class='username' and text()='" + username + "']" );
+        }
+    }
+
+    public void goToConfigurationPage()
+    {
+        clickLinkWithText( "Configuration" );
+        assertEditConfigurationPage();
+    }
+
+    protected void enableDisableBuildAgent( String agentName, boolean enable )
+    {
+        assertFieldValue( agentName, "saveBuildAgent_buildAgent_url" );
+
+        if ( enable )
+        {
+            checkField( "saveBuildAgent_buildAgent_enabled" );
+        }
+        else
+        {
+            uncheckField( "saveBuildAgent_buildAgent_enabled" );
+        }
+        submit();
+        assertBuildAgentPage();
+        assertTextPresent( Boolean.toString( enable ) );
+    }
+
+    protected void goToAddBuildAgentGroup()
+    {
+        goToBuildAgentPage();
+        clickAndWait( "editBuildAgentGroup_0" ); //add button
+        String[] options = new String[]{"--- Available Build Agents ---"};
+        assertAddEditBuildAgentGroupPage( options, null );
+    }
+
+    protected void addEditBuildAgentGroup( String name, String[] addBuildAgents, String[] removeBuildAgents,
+                                           boolean success )
+    {
+        setFieldValue( "saveBuildAgentGroup_buildAgentGroup_name", name );
+        if ( addBuildAgents != null && addBuildAgents.length > 0 )
+        {
+            for ( String ba : addBuildAgents )
+            {
+                selectValue( "buildAgentIds", ba );
+                clickButtonWithValue( "->", false );
+            }
+        }
+        if ( removeBuildAgents != null && removeBuildAgents.length > 0 )
+        {
+            for ( String ba : removeBuildAgents )
+            {
+                selectValue( "selectedBuildAgentIds", ba );
+                clickButtonWithValue( "<-", false );
+            }
+        }
+        submit();
+        if ( success )
+        {
+            assertBuildAgentPage();
+        }
+        else
+        {
+            assertAddEditBuildAgentGroupPage( null, null );
+        }
+    }
+
+    void assertAddEditBuildAgentGroupPage( String[] availableBuildAgents, String[] usedBuildAgents )
+    {
+        assertPage( "Continuum - Add/Edit Build Agent Group" );
+        assertTextPresent( "Add/Edit Build Agent Group" );
+        assertTextPresent( "Name*:" );
+        assertTextPresent( "Configure the used Build Agents:" );
+        assertElementPresent( "buildAgentGroup.name" );
+        if ( availableBuildAgents != null && availableBuildAgents.length > 0 )
+        {
+            assertOptionPresent( "buildAgentIds", availableBuildAgents );
+        }
+        if ( usedBuildAgents != null && usedBuildAgents.length > 0 )
+        {
+            assertOptionPresent( "selectedBuildAgentIds", usedBuildAgents );
+        }
+
+        assertButtonWithValuePresent( "Save" );
+        assertButtonWithValuePresent( "Cancel" );
+    }
+
+    protected void goToEditBuildAgentGroup( String name, String[] buildAgents )
+    {
+        goToBuildAgentPage();
+        String xPath = "//preceding::td[text()='" + name + "']//following::img[@alt='Edit']";
+        clickLinkWithXPath( xPath );
+        assertAddEditBuildAgentGroupPage( null, buildAgents );
+        assertFieldValue( name, "buildAgentGroup.name" );
+    }
+
+    protected void removeBuildAgentGroup( String name )
+        throws UnsupportedEncodingException
+    {
+        removeBuildAgentGroup( name, true );
+    }
+
+    protected void removeBuildAgentGroup( String name, boolean failIfMissing )
+        throws UnsupportedEncodingException
+    {
+        goToBuildAgentPage();
+        if ( isTextPresent( name ) || failIfMissing )
+        {
+            clickLinkWithXPath(
+                "(//a[contains(@href,'deleteBuildAgentGroup.action') and contains(@href, '" + URLEncoder.encode( name,
+                                                                                                                 "UTF-8" ) +
+                    "')])//img" );
+            assertPage( "Continuum - Delete Build Agent Group" );
+            assertTextPresent( "Delete Build Agent" );
+            assertTextPresent( "Are you sure you want to delete build agent group " + name + " ?" );
+            assertButtonWithValuePresent( "Delete" );
+            assertButtonWithValuePresent( "Cancel" );
+            clickButtonWithValue( "Delete" );
+            assertBuildAgentPage();
+            assertTextNotPresent( name );
+        }
+    }
+
+    protected void addBuildAgent( String buildAgentUrl )
+    {
+        addBuildAgent( buildAgentUrl, "Default description" );
+    }
+
+    protected void addBuildAgent( String buildAgentUrl, String description )
+    {
+        goToBuildAgentPage();
+        assertBuildAgentPage();
+
+        if ( !isElementPresent( "link=" + buildAgentUrl ) )
+        {
+
+            clickAndWait( "editBuildAgent_0" ); //add button
+            assertAddEditBuildAgentPage( true );
+
+            setFieldValue( "saveBuildAgent_buildAgent_url", buildAgentUrl );
+            setFieldValue( "saveBuildAgent_buildAgent_description", description );
+            checkField( "saveBuildAgent_buildAgent_enabled" );
+
+            submit();
+
+            assertBuildAgentPage();
+            assertElementPresent( "link=" + buildAgentUrl );
+        }
+    }
+
+    protected void goToAddBuildAgent()
+    {
+        goToBuildAgentPage();
+        assertBuildAgentPage();
+        clickAndWait( "editBuildAgent_0" ); //add button
+        assertAddEditBuildAgentPage( true );
+    }
+
+    void assertAddEditBuildAgentPage( boolean isChecked )
+    {
+        assertPage( "Continuum - Add/Edit Build Agent" );
+        assertTextPresent( "Add/Edit Build Agent" );
+        assertTextPresent( "Build Agent URL*:" );
+        assertTextPresent( "Description:" );
+        assertTextPresent( "Enabled" );
+        assertElementPresent( "saveBuildAgent_buildAgent_url" );
+        assertElementPresent( "saveBuildAgent_buildAgent_description" );
+
+        if ( isChecked )
+        {
+            assertIsChecked( "saveBuildAgent_buildAgent_enabled" );
+        }
+
+        assertButtonWithValuePresent( "Save" );
+        assertButtonWithValuePresent( "Cancel" );
+    }
+
+    @BeforeClass( alwaysRun = true )
+    @Parameters( { "buildAgentUrl" } )
+    public void initializeBuildAgent(
+        @Optional( "http://localhost:9595/continuum-buildagent/xmlrpc" ) String buildAgentUrl )
+    {
+        this.buildAgentUrl = buildAgentUrl;
+    }
+
+    protected void enableDistributedBuilds()
+    {
+        goToConfigurationPage();
+        setFieldValue( "numberOfAllowedBuildsinParallel", "2" );
+        if ( !isChecked( "distributedBuildEnabled" ) )
+        {
+            // must use click here so the JavaScript enabling the shared secret gets triggered
+            click( "distributedBuildEnabled" );
+        }
+        setFieldValue( "sharedSecretPassword", SHARED_SECRET );
+        clickAndWait( "css=input[value='Save']" );
+        assertTextPresent( "true" );
+        assertTextPresent( "Distributed Builds" );
+        assertElementPresent( "link=Build Agents" );
+    }
+
+    protected void disableDistributedBuilds()
+    {
+        goToConfigurationPage();
+        setFieldValue( "numberOfAllowedBuildsinParallel", "2" );
+        if ( isChecked( "distributedBuildEnabled" ) )
+        {
+            uncheckField( "distributedBuildEnabled" );
+        }
+        submit();
+        assertTextPresent( "false" );
+        assertElementNotPresent( "link=Build Agents" );
+    }
+
+    protected void goToBuildAgentPage()
+    {
+        clickAndWait( "link=Build Agents" );
+        assertPage( "Continuum - Build Agents" );
+    }
+
+    void assertBuildAgentPage()
+    {
+        assertPage( "Continuum - Build Agents" );
+        assertTextPresent( "Build Agents" );
+        assertTextPresent( "Build Agent Groups" );
+        assertButtonWithValuePresent( "Add" );
+    }
+
+    protected void removeBuildAgent( String agentName )
+        throws Exception
+    {
+        removeBuildAgent( agentName, true );
+    }
+
+    protected void removeBuildAgent( String agentName, boolean failIfMissing )
+        throws Exception
+    {
+        String deleteButton = "//a[contains(@href,'deleteBuildAgent.action') and contains(@href, '" + URLEncoder.encode(
+            agentName, "UTF-8" ) + "')]/img";
+        if ( failIfMissing || isElementPresent( deleteButton ) )
+        {
+            clickLinkWithXPath( deleteButton );
+            assertPage( "Continuum - Delete Build Agent" );
+            assertTextPresent( "Delete Build Agent" );
+            assertTextPresent( "Are you sure you want to delete build agent " + agentName + " ?" );
+            assertButtonWithValuePresent( "Delete" );
+            assertButtonWithValuePresent( "Cancel" );
+            clickButtonWithValue( "Delete" );
+            assertBuildAgentPage();
+            assertElementNotPresent( deleteButton );
+        }
+    }
+
+    protected void addBuildAgent( String agentURL, String description, boolean success, boolean enabled,
+                                  boolean pingOk )
+    {
+        setFieldValue( "saveBuildAgent_buildAgent_url", agentURL );
+        setFieldValue( "saveBuildAgent_buildAgent_description", description );
+
+        if ( enabled )
+        {
+            checkField( "saveBuildAgent_buildAgent_enabled" );
+        }
+        else
+        {
+            uncheckField( "saveBuildAgent_buildAgent_enabled" );
+        }
+
+        submit();
+
+        if ( success )
+        {
+            if ( pingOk )
+            {
+                assertBuildAgentPage();
+                assertElementPresent( "link=" + agentURL );
+                clickLinkWithText( agentURL );
+
+                if ( enabled )
+                {
+                    assertTextPresent( "true" );
+                }
+            }
+            else
+            {
+                assertTextPresent( "Unable to ping" );
+                assertAddEditBuildAgentPage( true );
+            }
+        }
+        else
+        {
+            assertAddEditBuildAgentPage( enabled );
+        }
+    }
+
+    protected void goToEditBuildAgent( String name, String description )
+    {
+        goToBuildAgentPage();
+        clickImgWithAlt( "Edit" );
+        assertAddEditBuildAgentPage( false );
+        assertFieldValue( name, "saveBuildAgent_buildAgent_url" );
+        assertFieldValue( description, "saveBuildAgent_buildAgent_description" );
+    }
+
+    protected void addEditBuildAgent( String agentName, String newDesc )
+    {
+        assertFieldValue( agentName, "saveBuildAgent_buildAgent_url" );
+        setFieldValue( "saveBuildAgent_buildAgent_description", newDesc );
+        submit();
+        assertBuildAgentPage();
+        assertTextPresent( newDesc );
+    }
+
+    protected void removeSchedule( String name )
+    {
+        goToSchedulePage();
+        clickLinkWithXPath( "(//a[contains(@href,'removeSchedule.action') and contains(@href, '" + name + "')])//img" );
+        assertPage( "Continuum - Delete Schedule" );
+        assertTextPresent( "Delete Schedule" );
+        assertTextPresent( "Are you sure you want to delete the schedule \"" + name + "\"?" );
+        assertButtonWithValuePresent( "Delete" );
+        assertButtonWithValuePresent( "Cancel" );
+        clickButtonWithValue( "Delete" );
+        assertSchedulePage();
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/parent/AbstractBuildDefinitionTemplateTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/parent/AbstractBuildDefinitionTemplateTest.java
new file mode 100644
index 0000000..cd2da9b
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/parent/AbstractBuildDefinitionTemplateTest.java
@@ -0,0 +1,247 @@
+package org.apache.continuum.web.test.parent;
+
+/*
+ * 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.
+ */
+
+/**
+ * @author José Morales Martínez
+ * @version $Id$
+ */
+public abstract class AbstractBuildDefinitionTemplateTest
+    extends AbstractAdminTest
+{
+    void goToBuildDefinitionTemplatePage()
+    {
+        clickLinkWithText( "Build Definition Templates" );
+        assertBuildDefinitionTemplatePage();
+    }
+
+    void assertBuildDefinitionTemplatePage()
+    {
+        assertPage( "Continuum - Build Definition Templates" );
+        assertTextPresent( "Available Templates" );
+        assertTextPresent( "Available Build Definitions" );
+        assertButtonWithIdPresent( "buildDefinitionTemplate_0" );
+        assertButtonWithIdPresent( "buildDefinitionAsTemplate_input_0" );
+    }
+
+    protected void goToAddTemplate()
+    {
+        goToBuildDefinitionTemplatePage();
+        clickSubmitWithLocator( "buildDefinitionTemplate_0" );
+        String[] options = new String[]{"--- Available Build Definitions ---", "Default Ant Build Definition",
+            "Default Maven 1 Build Definition", "Default Maven Build Definition", "Default Shell Build Definition"};
+        assertAddEditTemplatePage( options, null );
+    }
+
+    void assertAddEditTemplatePage( String[] pendingSelectBuild, String[] selectedBuild )
+    {
+        assertPage( "Continuum - Build Definition Template" );
+        assertTextPresent( "Build Definition Template" );
+        assertTextPresent( "Name" );
+        assertElementPresent( "buildDefinitionTemplate.name" );
+        assertTextPresent( "Configure the used Build Definitions" );
+        if ( pendingSelectBuild != null && pendingSelectBuild.length > 0 )
+        {
+            assertOptionPresent( "buildDefinitionIds", pendingSelectBuild );
+        }
+        if ( selectedBuild != null && selectedBuild.length > 0 )
+        {
+            assertOptionPresent( "selectedBuildDefinitionIds", selectedBuild );
+        }
+        assertButtonWithValuePresent( "Save" );
+        assertButtonWithValuePresent( "Cancel" );
+    }
+
+    protected void addEditTemplate( String name, String[] addBuildDefinitions, String[] removeBuildDefinitions,
+                                    boolean success )
+    {
+        boolean empty = false;
+
+        setFieldValue( "buildDefinitionTemplate.name", name );
+        if ( addBuildDefinitions != null && addBuildDefinitions.length > 0 )
+        {
+            for ( String bd : addBuildDefinitions )
+            {
+                selectValue( "buildDefinitionIds", bd );
+                clickButtonWithValue( "->", false );
+            }
+        }
+        else
+        {
+            empty = true;
+        }
+
+        if ( removeBuildDefinitions != null && removeBuildDefinitions.length > 0 )
+        {
+            for ( String bd : removeBuildDefinitions )
+            {
+                selectValue( "selectedBuildDefinitionIds", bd );
+                clickButtonWithValue( "<-", false );
+            }
+        }
+        submit();
+        if ( success )
+        {
+            assertBuildDefinitionTemplatePage();
+        }
+        else
+        {
+            if ( empty )
+            {
+                assertTextPresent( "Template requires at least one build definition" );
+            }
+            else
+            {
+                assertAddEditTemplatePage( null, null );
+            }
+        }
+    }
+
+    protected void goToEditTemplate( String name, String[] buildDefinitions )
+    {
+        goToBuildDefinitionTemplatePage();
+        String xPath = "//preceding::td[text()='" + name + "']//following::img[@alt='Edit']";
+        clickLinkWithXPath( xPath );
+        assertAddEditTemplatePage( null, buildDefinitions );
+        assertFieldValue( name, "buildDefinitionTemplate.name" );
+    }
+
+    protected void removeTemplate( String name )
+    {
+        removeTemplate( name, true );
+    }
+
+    protected void removeTemplate( String name, boolean failIfMissing )
+    {
+        goToBuildDefinitionTemplatePage();
+        String xpath = "(//a[contains(@href,'deleteDefinitionTemplate') and contains(@href, '" + name + "')])//img";
+        if ( failIfMissing || isElementPresent( "xpath=" + xpath ) )
+        {
+            clickLinkWithXPath( xpath );
+            assertPage( "Continuum - Delete Build Definition Template" );
+            assertTextPresent( "Delete Build Definition Template" );
+            assertTextPresent( "Are you sure you want to delete build definition template \"" + name + "\"?" );
+            assertButtonWithValuePresent( "Delete" );
+            assertButtonWithValuePresent( "Cancel" );
+            clickButtonWithValue( "Delete" );
+            assertBuildDefinitionTemplatePage();
+        }
+    }
+
+    protected void goToAddBuildDefinitionTemplate()
+    {
+        goToBuildDefinitionTemplatePage();
+        clickSubmitWithLocator( "buildDefinitionAsTemplate_input_0" );
+        assertAddEditBuildDefinitionTemplatePage();
+    }
+
+    protected void goToEditBuildDefinitionTemplate( String description )
+    {
+        goToBuildDefinitionTemplatePage();
+        String xPath = "//preceding::td[text()='" + description + "']//following::img[@alt='Edit']";
+        clickLinkWithXPath( xPath );
+        assertAddEditBuildDefinitionTemplatePage();
+    }
+
+    void assertAddEditBuildDefinitionTemplatePage()
+    {
+        assertPage( "Continuum - Build Definition Template" );
+        assertTextPresent( "Build Definition Template" );
+        assertTextPresent( "POM filename*:" );
+        assertElementPresent( "buildDefinition.buildFile" );
+        assertTextPresent( "Goals*:" );
+        assertElementPresent( "buildDefinition.goals" );
+        assertTextPresent( "Arguments:" );
+        assertElementPresent( "buildDefinition.arguments" );
+        assertTextPresent( "Build Fresh" );
+        assertElementPresent( "buildDefinition.buildFresh" );
+        assertTextPresent( "Always Build" );
+        assertElementPresent( "buildDefinition.alwaysBuild" );
+        assertTextPresent( "Is it default?" );
+        assertTextPresent( "Schedule:" );
+        assertElementPresent( "buildDefinition.schedule.id" );
+        assertTextPresent( "Description" );
+        assertElementPresent( "buildDefinition.description" );
+        assertTextPresent( "Type" );
+        assertElementPresent( "buildDefinition.type" );
+        assertTextPresent( "Build Environment" );
+        assertElementPresent( "buildDefinition.profile.id" );
+        assertButtonWithValuePresent( "Save" );
+        assertButtonWithValuePresent( "Cancel" );
+    }
+
+    protected void addEditBuildDefinitionTemplate( String buildFile, String goals, String arguments, String description,
+                                                   boolean buildFresh, boolean alwaysBuild, boolean isDefault,
+                                                   boolean success )
+    {
+        // Enter values into Add Build Definition fields, and submit
+        setFieldValue( "buildDefinition.buildFile", buildFile );
+        setFieldValue( "buildDefinition.goals", goals );
+        setFieldValue( "buildDefinition.arguments", arguments );
+        setFieldValue( "buildDefinition.description", description );
+        if ( buildFresh )
+        {
+            checkField( "buildDefinition.buildFresh" );
+        }
+        else
+        {
+            uncheckField( "buildDefinition.buildFresh" );
+        }
+        if ( isDefault )
+        {
+            checkField( "buildDefinition.defaultForProject" );
+        }
+        else
+        {
+            uncheckField( "buildDefinition.defaultForProject" );
+        }
+        if ( alwaysBuild )
+        {
+            checkField( "buildDefinition.alwaysBuild" );
+        }
+        else
+        {
+            uncheckField( "buildDefinition.alwaysBuild" );
+        }
+        submit();
+        if ( success )
+        {
+            assertBuildDefinitionTemplatePage();
+        }
+        else
+        {
+            assertAddEditBuildDefinitionTemplatePage();
+        }
+    }
+
+    protected void removeBuildDefinitionTemplate( String description )
+    {
+        goToBuildDefinitionTemplatePage();
+        String xPath = "//preceding::td[text()='" + description + "']//following::img[@alt='Delete']";
+        clickLinkWithXPath( xPath );
+        assertPage( "Continuum - Delete Build Definition Template" );
+        assertTextPresent( "Delete Build Definition Template" );
+        assertTextPresent( "Are you sure you want to delete build definition template \"" + description + "\"?" );
+        assertButtonWithValuePresent( "Delete" );
+        assertButtonWithValuePresent( "Cancel" );
+        clickButtonWithValue( "Delete" );
+        assertBuildDefinitionTemplatePage();
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/parent/AbstractContinuumTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/parent/AbstractContinuumTest.java
new file mode 100644
index 0000000..c781b6f
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/parent/AbstractContinuumTest.java
@@ -0,0 +1,1331 @@
+package org.apache.continuum.web.test.parent;
+
+/*
+ * 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 org.testng.Assert;
+import org.testng.annotations.BeforeSuite;
+import org.testng.annotations.Optional;
+import org.testng.annotations.Parameters;
+
+import static org.testng.Assert.assertEquals;
+
+/**
+ * Based on AbstractContinuumTestCase of Emmanuel Venisse test.
+ *
+ * @author José Morales Martínez
+ * @version $Id$
+ */
+public abstract class AbstractContinuumTest
+    extends AbstractSeleniumTest
+{
+    protected static final String SHARED_SECRET = "continuum1234";
+
+    protected static final String ANT_PROJECT_TYPE = "ant";
+
+    protected static final String MAVEN_PROJECT_TYPE = "maven";
+
+    // ////////////////////////////////////
+    // Create Admin User
+    // ////////////////////////////////////
+    void assertCreateAdmin()
+    {
+        assertPage( "Create Admin User" );
+        assertTextPresent( "Username" );
+        assertFieldValue( "admin", "user.username" );
+        assertTextPresent( "Full Name*" );
+        assertElementPresent( "user.fullName" );
+        assertTextPresent( "Email Address*" );
+        assertElementPresent( "user.email" );
+        assertTextPresent( "Password*" );
+        assertElementPresent( "user.password" );
+        assertTextPresent( "Confirm Password*" );
+        assertElementPresent( "user.confirmPassword" );
+        assertButtonWithValuePresent( "Create Admin" );
+    }
+
+    void submitAdminData( String fullname, String email, String password )
+    {
+        setFieldValue( "user.fullName", fullname );
+        setFieldValue( "user.email", email );
+        setFieldValue( "user.password", password );
+        setFieldValue( "user.confirmPassword", password );
+        submit();
+    }
+
+    // ////////////////////////////////////
+    // About
+    // ////////////////////////////////////
+    protected void goToAboutPage()
+    {
+        getSelenium().open( baseUrl );
+        clickLinkWithText( "About" );
+        assertAboutPage();
+    }
+
+    protected void assertAboutPage()
+    {
+        assertPage( "Continuum - About" );
+        assertTextPresent( "About Continuum" );
+        assertTextPresent( "Version:" );
+    }
+
+    // ////////////////////////////////////
+    // Login
+    // ////////////////////////////////////
+
+    protected void goToLoginPage()
+    {
+        getSelenium().deleteAllVisibleCookies();
+        getSelenium().open( baseUrl );
+        clickLinkWithText( "Login" );
+        assertLoginPage();
+    }
+
+    void assertLoginPage()
+    {
+        assertPage( "Login Page" );
+        assertTextPresent( "Login" );
+        assertTextPresent( "Register" );
+        assertTextPresent( "Username" );
+        assertElementPresent( "username" );
+        assertTextPresent( "Password" );
+        assertElementPresent( "password" );
+        assertTextPresent( "Remember Me" );
+        assertElementPresent( "rememberMe" );
+        assertButtonWithValuePresent( "Login" );
+        assertButtonWithValuePresent( "Cancel" );
+        assertTextPresent( "Need an Account? Register!" );
+        assertTextPresent( "Forgot your Password? Request a password reset." );
+    }
+
+    void assertAutenticatedPage( String username )
+    {
+        assertTextPresent( "Current User" );
+        assertTextPresent( "Edit Details" );
+        assertTextPresent( "Logout" );
+        assertTextNotPresent( "Login" );
+        assertTextPresent( username );
+    }
+
+    // ////////////////////////////////////
+    // Configuration
+    // ////////////////////////////////////
+
+    protected void assertEditConfigurationPage()
+    {
+        assertPage( "Continuum - Configuration" );
+        assertTextPresent( "General Configuration " );
+        assertTextPresent( "Working Directory" );
+        assertElementPresent( "workingDirectory" );
+        assertTextPresent( "Build Output Directory" );
+        assertElementPresent( "buildOutputDirectory" );
+        assertTextPresent( "Release Output Directory" );
+        assertElementPresent( "releaseOutputDirectory" );
+        assertTextPresent( "Deployment Repository Directory" );
+        assertElementPresent( "deploymentRepositoryDirectory" );
+        assertTextPresent( "Base URL" );
+        assertElementPresent( "baseUrl" );
+        assertTextPresent( "Number of Allowed Builds in Parallel" );
+        assertElementPresent( "numberOfAllowedBuildsinParallel" );
+        assertTextPresent( "Enable Distributed Builds" );
+        assertElementPresent( "distributedBuildEnabled" );
+        assertButtonWithValuePresent( "Save" );
+        assertButtonWithValuePresent( "Cancel" );
+    }
+
+    // ////////////////////////////////////
+    // Build Queue
+    // ////////////////////////////////////
+
+    protected void setMaxBuildQueue( int maxBuildQueue )
+    {
+        clickLinkWithText( "Configuration" );
+        setFieldValue( "numberOfAllowedBuildsinParallel", String.valueOf( maxBuildQueue ) );
+        submit();
+    }
+
+    // ////////////////////////////////////
+    // Project Groups
+    // ////////////////////////////////////
+    protected void goToProjectGroupsSummaryPage()
+    {
+        getSelenium().open( baseUrl + "/groupSummary.action" );
+        waitPage();
+
+        assertProjectGroupsSummaryPage();
+    }
+
+    protected void assertProjectGroupsSummaryPage()
+    {
+        assertPage( "Continuum - Group Summary" );
+        assertTextPresent( "Project Groups" );
+
+        if ( isTextPresent( "Project Groups list is empty." ) )
+        {
+            assertTextNotPresent( "Name" );
+            assertTextNotPresent( "Group Id" );
+        }
+        else
+        {
+            assertTextPresent( "Name" );
+            assertTextPresent( "Group Id" );
+        }
+    }
+
+    // ////////////////////////////////////
+    // Project Group
+    // ////////////////////////////////////
+    protected void showProjectGroup( String name, String groupId, String description )
+    {
+        goToProjectGroupsSummaryPage();
+
+        // Checks the link to the created Project Group
+        assertLinkPresent( name );
+        clickLinkWithText( name );
+
+        assertProjectGroupSummaryPage( name, groupId, description );
+    }
+
+    protected void assertProjectGroupSummaryPage( String name, String groupId, String description )
+    {
+        assertPage( "Continuum - Project Group" );
+        assertTextPresent( "Project Group Name" );
+        assertTextPresent( name );
+        assertTextPresent( "Project Group Id" );
+        assertTextPresent( groupId );
+        assertTextPresent( "Description" );
+        assertTextPresent( description );
+
+        // Assert the available Project Group Actions
+        assertTextPresent( "Group Actions" );
+        assertElementPresent( "build" );
+        assertElementPresent( "edit" );
+        // assertElementPresent( "remove" );
+
+        assertTextPresent( "Project Group Scm Root" );
+        assertTextPresent( "Scm Root URL" );
+
+        if ( isTextPresent( "Member Projects" ) )
+        {
+            assertTextPresent( "Project Name" );
+            assertTextPresent( "Version" );
+            assertTextPresent( "Build" );
+        }
+        else
+        {
+            assertTextNotPresent( "Project Name" );
+        }
+    }
+
+    protected void addProjectGroup( String name, String groupId, String description, boolean success )
+    {
+        addProjectGroup( name, groupId, description, success, true );
+    }
+
+    protected void addProjectGroup( String name, String groupId, String description, boolean success,
+                                    boolean failIfExists )
+    {
+        goToProjectGroupsSummaryPage();
+        if ( failIfExists )
+        {
+            assertLinkNotPresent( name );
+        }
+        else
+        {
+            if ( isLinkPresent( name ) )
+            {
+                return;
+            }
+        }
+
+        // Go to Add Project Group Page
+        clickButtonWithValue( "Add Project Group" );
+        assertAddProjectGroupPage();
+
+        // Enter values into Add Project Group fields, and submit
+        setFieldValue( "name", name );
+        setFieldValue( "groupId", groupId );
+        setFieldValue( "description", description );
+
+        submit();
+        if ( success )
+        {
+            assertProjectGroupsSummaryPage();
+        }
+        else
+        {
+            assertAddProjectGroupPage();
+        }
+    }
+
+    void assertAddProjectGroupPage()
+    {
+        assertPage( "Continuum - Add Project Group" );
+        assertTextPresent( "Add Project Group" );
+        assertTextPresent( "Project Group Name" );
+        assertElementPresent( "name" );
+        assertTextPresent( "Project Group Id" );
+        assertElementPresent( "groupId" );
+        assertTextPresent( "Description" );
+        assertElementPresent( "description" );
+    }
+
+    protected void removeProjectGroup( String groupName )
+    {
+        removeProjectGroup( groupName, true );
+    }
+
+    protected void removeProjectGroup( String groupName, boolean failIfMissing )
+    {
+        goToProjectGroupsSummaryPage();
+        if ( failIfMissing || isLinkPresent( groupName ) )
+        {
+            clickLinkWithText( groupName );
+            clickButtonWithValue( "Delete Group" );
+            assertTextPresent( "Project Group Removal" );
+            clickButtonWithValue( "Delete" );
+            assertProjectGroupsSummaryPage();
+        }
+    }
+
+    protected void editProjectGroup( String name, String groupId, String description, String newName,
+                                     String newDescription )
+    {
+        showProjectGroup( name, groupId, description );
+        clickButtonWithValue( "Edit" );
+        assertEditGroupPage( groupId );
+        setFieldValue( "name", newName );
+        setFieldValue( "description", newDescription );
+        clickButtonWithValue( "Save" );
+    }
+
+    void assertEditGroupPage( String groupId )
+    {
+        assertPage( "Continuum - Update Project Group" );
+        assertTextPresent( "Update Project Group" );
+        assertTextPresent( "Project Group Name" );
+        assertTextPresent( "Project Group Id" );
+        assertFieldValue( groupId, "projectGroup.groupId" );
+        assertTextPresent( "Description" );
+        assertTextPresent( "Homepage Url" );
+        assertTextPresent( "Local Repository" );
+        assertElementPresent( "css=input[value='Save']" );
+        assertElementPresent( "Cancel" );
+    }
+
+    protected void buildProjectGroup( String projectGroupName, String groupId, String description, String projectName,
+                                      boolean success )
+    {
+        showProjectGroup( projectGroupName, groupId, description );
+        waitForProjectUpdate();
+        clickButtonWithValue( "Build all projects" );
+
+        // wait for project to finish building
+        waitForProjectBuild();
+
+        // wait for the success status of project
+        if ( success )
+        {
+            if ( !isElementPresent( "//a/img[@alt='Success']" ) )
+            {
+                waitForElementPresent( "//a/img[@alt='Success']" );
+            }
+        }
+        else
+        {
+            if ( !isElementPresent( "//a/img[@alt='Failed']" ) )
+            {
+                waitForElementPresent( "//a/img[@alt='Failed']" );
+            }
+        }
+
+        // wait for the projectName link
+        if ( !isLinkPresent( projectName ) )
+        {
+            waitForElementPresent( "link=" + projectName );
+        }
+
+        clickLinkWithText( projectName );
+        waitForElementPresent( "link=Builds" );
+        clickLinkWithText( "Builds" );
+        clickLinkWithText( "Result" );
+
+        assertPage( "Continuum - Build result" );
+        assertTextPresent( "Build result for " + projectName );
+
+        if ( success )
+        {
+            assertImgWithAlt( "Success" );
+        }
+        else
+        {
+            assertImgWithAlt( "Failed" );
+        }
+
+        clickLinkWithText( "Project Group Summary" );
+    }
+
+    protected void assertReleaseChoicePage()
+    {
+        assertTextPresent( "Choose Release Goal for " );
+        assertTextPresent( "Prepare project for release " );
+        assertTextPresent( "Perform project release" );
+        assertElementPresent( "goal" );
+        assertElementPresent( "preparedReleaseId" );
+        assertButtonWithValuePresent( "Submit" );
+    }
+
+    protected void goToGroupBuildDefinitionPage( String projectGroupName, String groupId, String description )
+    {
+        showProjectGroup( projectGroupName, groupId, description );
+        clickLinkWithText( "Build Definitions" );
+        assertGroupBuildDefinitionPage( projectGroupName );
+    }
+
+    protected void assertGroupBuildDefinitionPage( String projectGroupName )
+    {
+        assertTextPresent( "Project Group Build Definitions of " + projectGroupName + " group" );
+    }
+
+    protected void assertDeleteBuildDefinitionPage( String description, String goals )
+    {
+        assertTextPresent(
+            "Are you sure you want to delete the build definition with description \"" + description + "\", goals \"" +
+                goals + "\" and id" );
+        isButtonWithValuePresent( "Cancel" );
+        isButtonWithValuePresent( "Delete" );
+    }
+
+    protected void assertAddEditBuildDefinitionPage( String type )
+    {
+        assertTextPresent( "Add/Edit Build Definition" );
+        if ( MAVEN_PROJECT_TYPE.equals( type ) )
+        {
+            assertTextPresent( "POM filename*:" );
+            assertTextPresent( "Goals*:" );
+        }
+        else if ( ANT_PROJECT_TYPE.equals( type ) )
+        {
+            assertTextPresent( "Ant build filename*:" );
+            assertTextPresent( "Targets:" );
+        }
+        else
+        {
+            throw new UnsupportedOperationException( "check not implemented for type: " + type );
+        }
+        assertElementPresent( "buildFile" );
+        assertElementPresent( "goals" );
+        assertTextPresent( "Arguments:" );
+        assertElementPresent( "arguments" );
+        assertTextPresent( "Build Fresh" );
+        assertElementPresent( "buildFresh" );
+        assertTextPresent( "Always Build" );
+        assertElementPresent( "alwaysBuild" );
+        assertTextPresent( "Is it default?" );
+        assertTextPresent( "Schedule:" );
+        assertElementPresent( "scheduleId" );
+        assertTextPresent( "Description" );
+        assertElementPresent( "description" );
+        assertTextPresent( "Type" );
+        assertElementPresent( "buildDefinitionType" );
+        assertTextPresent( "Build Environment" );
+        assertElementPresent( "profileId" );
+        assertEnabled();
+    }
+
+    protected void addEditGroupBuildDefinition( String groupName, String buildFile, String goals, String arguments,
+                                                String description, boolean buildFresh, boolean alwaysBuild,
+                                                boolean isDefault, String type, boolean success )
+    {
+        assertAddEditBuildDefinitionPage( type );
+
+        // Enter values into Add Build Definition fields, and submit
+        setFieldValue( "buildFile", buildFile );
+        setFieldValue( "goals", goals );
+        setFieldValue( "arguments", arguments );
+        setFieldValue( "description", description );
+
+        if ( buildFresh )
+        {
+            if ( isChecked( "buildFresh" ) )
+            {
+                uncheckField( "buildFresh" );
+            }
+
+            // need to do this for the onclick event
+            click( "buildFresh" );
+        }
+        else
+        {
+            if ( !isChecked( "buildFresh" ) )
+            {
+                checkField( "buildFresh" );
+            }
+
+            // need to do this for the onclick event
+            click( "buildFresh" );
+        }
+
+        assertEnabled();
+        if ( isElementPresent( "defaultBuildDefinition" ) )
+        {
+            if ( isDefault )
+            {
+                checkField( "defaultBuildDefinition" );
+            }
+            else
+            {
+                uncheckField( "defaultBuildDefinition" );
+            }
+        }
+        if ( alwaysBuild )
+        {
+            checkField( "alwaysBuild" );
+        }
+        else
+        {
+            uncheckField( "alwaysBuild" );
+        }
+
+        selectValue( "scheduleId", "DEFAULT_SCHEDULE" );
+
+        submit();
+
+        if ( !success )
+        {
+            assertAddEditBuildDefinitionPage( type );
+        }
+        else
+        {
+            if ( groupName != null )
+            {
+                assertGroupBuildDefinitionPage( groupName );
+            }
+            else
+            {
+                assertProjectInformationPage();
+            }
+        }
+    }
+
+    protected void goToProjectInformationPage( String projectGroupName, String projectName )
+    {
+        clickLinkWithText( "Show Project Groups" );
+        clickLinkWithText( projectGroupName );
+        clickLinkWithText( projectName );
+
+        assertProjectInformationPage();
+    }
+
+    protected void assertProjectInformationPage()
+    {
+        assertTextPresent( "Project Group Summary" );
+        assertTextPresent( "Project Information" );
+        assertTextPresent( "Builds" );
+        assertTextPresent( "Working Copy" );
+        assertTextPresent( "Build Definitions" );
+        assertTextPresent( "Notifiers" );
+        assertTextPresent( "Dependencies" );
+        assertTextPresent( "Developers" );
+    }
+
+    protected void moveProjectToProjectGroup( String groupName, String groupId, String groupDescription,
+                                              String projectName, String newProjectGroup )
+    {
+        showProjectGroup( groupName, groupId, groupDescription );
+
+        // wait for project not being used
+        waitForProjectBuild();
+
+        String id = getFieldValue( "name=projectGroupId" );
+        String url = baseUrl + "/editProjectGroup.action?projectGroupId=" + id;
+        getSelenium().open( url );
+        waitPage();
+
+        assertTextPresent( "Move to Group" );
+        String xPath = "//preceding::td/label[contains(text(),'" + projectName + "')]//following::select";
+        selectValue( xPath, newProjectGroup );
+        clickButtonWithValue( "Save" );
+        assertProjectGroupSummaryPage( groupName, groupId, groupDescription );
+    }
+
+    // ////////////////////////////////////
+    // Maven 2.0+ Project
+    // ////////////////////////////////////
+    protected void goToAddMavenTwoProjectPage()
+    {
+        clickLinkWithText( "Maven Project" );
+
+        assertAddMavenTwoProjectPage();
+    }
+
+    protected void assertAddMavenTwoProjectPage()
+    {
+        assertTextPresent( "POM Url" );
+        assertElementPresent( "m2PomUrl" );
+        assertTextPresent( "Username" );
+        assertElementPresent( "scmUsername" );
+        assertTextPresent( "Password" );
+        assertElementPresent( "scmPassword" );
+        assertTextPresent( "Upload POM" );
+        assertElementPresent( "m2PomFile" );
+        assertTextPresent( "Project Group" );
+        assertElementPresent( "selectedProjectGroup" );
+    }
+
+    protected void addMavenTwoProject( String pomUrl, String username, String password, String projectGroup,
+                                       boolean success )
+    {
+        goToAddMavenTwoProjectPage();
+
+        // Enter values into Add Maven Two Project fields, and submit
+        setFieldValue( "m2PomUrl", pomUrl );
+        setFieldValue( "scmUsername", username );
+        setFieldValue( "scmPassword", password );
+
+        if ( projectGroup != null )
+        {
+            selectValue( "addMavenTwoProject_selectedProjectGroup", projectGroup );
+        }
+        submit();
+        String title;
+        if ( success )
+        {
+            title = "Continuum - Project Group";
+        }
+        else
+        {
+            title = "Continuum - Add Maven Project";
+        }
+        waitAddProject( title );
+    }
+
+    protected void submitAddMavenTwoProjectPage( String m2PomUrl )
+    {
+        addMavenTwoProject( m2PomUrl, "", "", null, false );
+    }
+
+    // ////////////////////////////////////
+    // Maven 1.x Project
+    // ////////////////////////////////////
+    protected void goToAddMavenOneProjectPage()
+    {
+        clickLinkWithText( "Maven 1.x Project" );
+        assertAddMavenOneProjectPage();
+    }
+
+    protected void assertAddMavenOneProjectPage()
+    {
+        assertAddMavenOneProjectPage( null );
+    }
+
+    protected void assertAddMavenOneProjectPage( String existingProjectGroup )
+    {
+        assertPage( "Continuum - Add Maven 1 Project" );
+        assertTextPresent( "Add Maven 1.x Project" );
+        assertTextPresent( "M1 POM Url" );
+        assertElementPresent( "m1PomUrl" );
+        assertTextPresent( "Username" );
+        assertElementPresent( "scmUsername" );
+        assertTextPresent( "Password" );
+        assertElementPresent( "scmPassword" );
+        assertTextPresent( "OR" );
+        assertTextPresent( "Upload POM" );
+        assertElementPresent( "m1PomFile" );
+        assertTextPresent( "Project Group" );
+        assertElementPresent( "selectedProjectGroup" );
+        if ( existingProjectGroup == null )
+        {
+            assertOptionPresent( "selectedProjectGroup", new String[]{"Defined by POM", "Default Project Group"} );
+        }
+        else
+        {
+            assert existingProjectGroup.equals( getFieldValue( "projectGroupName" ) );
+        }
+        assertTextPresent( "Build Definition Template" );
+        assertElementPresent( "buildDefinitionTemplateId" );
+        assertOptionPresent( "buildDefinitionTemplateId",
+                             new String[]{"Default", "Default Ant Template", "Default Maven 1 Template",
+                                 "Default Maven Template", "Default Shell Template"} );
+        assertButtonWithValuePresent( "Add" );
+        assertButtonWithValuePresent( "Cancel" );
+    }
+
+    protected void addMavenOneProject( String pomUrl, String username, String password, String projectGroup,
+                                       boolean success )
+    {
+        setFieldValue( "m1PomUrl", pomUrl );
+        setFieldValue( "scmUsername", username );
+        setFieldValue( "scmPassword", password );
+
+        if ( projectGroup != null )
+        {
+            selectValue( "selectedProjectGroup", projectGroup );
+        }
+        submit();
+        String title;
+        if ( success )
+        {
+            title = "Continuum - Project Group";
+        }
+        else
+        {
+            title = "Continuum - Add Maven 1 Project";
+        }
+        waitAddProject( title );
+    }
+
+    // ////////////////////////////////////
+    // ANT/SHELL Projects
+    // ////////////////////////////////////
+
+    protected void goToAddAntProjectPage()
+    {
+        clickLinkWithText( "Ant Project" );
+        assertAddProjectPage( "ant" );
+    }
+
+    protected void goToAddShellProjectPage()
+    {
+        clickLinkWithText( "Shell Project" );
+        assertAddProjectPage( "shell" );
+    }
+
+    protected void assertAddProjectPage( String type )
+    {
+        String title = type.substring( 0, 1 ).toUpperCase() + type.substring( 1 ).toLowerCase();
+        assertPage( "Continuum - Add " + title + " Project" );
+        assertTextPresent( "Add " + title + " Project" );
+        assertTextPresent( "Project Name" );
+        assertElementPresent( "projectName" );
+        assertTextPresent( "Description" );
+        assertElementPresent( "projectDescription" );
+        assertTextPresent( "Version" );
+        assertElementPresent( "projectVersion" );
+        assertTextPresent( "Scm Url" );
+        assertElementPresent( "projectScmUrl" );
+        assertLinkPresent( "Maven SCM URL" );
+        assertTextPresent( "Scm Username" );
+        assertElementPresent( "projectScmUsername" );
+        assertTextPresent( "Scm Password" );
+        assertElementPresent( "projectScmPassword" );
+        assertTextPresent( "Scm Branch/Tag" );
+        assertElementPresent( "projectScmTag" );
+        assertTextPresent( "Use SCM Credentials Cache, if available" );
+        assertElementPresent( "projectScmUseCache" );
+        assertTextPresent( "Project Group" );
+        assertElementPresent( "selectedProjectGroup" );
+        assertOptionPresent( "selectedProjectGroup", new String[]{"Default Project Group"} );
+        assertTextPresent( "Build Definition Template" );
+        assertElementPresent( "buildDefinitionTemplateId" );
+        assertOptionPresent( "buildDefinitionTemplateId",
+                             new String[]{"Default", "Default Ant Template", "Default Maven 1 Template",
+                                 "Default Maven Template", "Default Shell Template"} );
+        assertButtonWithValuePresent( "Add" );
+        assertButtonWithValuePresent( "Cancel" );
+    }
+
+    protected void addProject( String name, String description, String version, String scmUrl, String scmUser,
+                               String scmPassword, String scmTag, String projectGroup, boolean success, String type )
+    {
+        setFieldValue( "projectName", name );
+        setFieldValue( "projectDescription", description );
+        setFieldValue( "projectVersion", version );
+        setFieldValue( "projectScmUrl", scmUrl );
+        setFieldValue( "projectScmUsername", scmUser );
+        setFieldValue( "projectScmPassword", scmPassword );
+        setFieldValue( "projectScmTag", scmTag );
+        if ( projectGroup != null )
+        {
+            selectValue( "selectedProjectGroup", projectGroup );
+        }
+        submit();
+        String title;
+        type = type.substring( 0, 1 ).toUpperCase() + type.substring( 1 ).toLowerCase();
+        if ( success )
+        {
+            title = "Continuum - Project Group";
+        }
+        else
+        {
+            title = "Continuum - Add " + type + " Project";
+        }
+        waitAddProject( title );
+
+        if ( success )
+        {
+            assertLinkPresent( name );
+        }
+    }
+
+    protected void waitAddProject( String title )
+    {
+        // the "adding project" interstitial page has an empty title, so we wait for a real title to appear
+
+        int currentIt = 1;
+        int maxIt = 12;
+
+        while ( getTitle().equals( "" ) && currentIt <= maxIt )
+        {
+            getSelenium().waitForPageToLoad( "10000" ); // 10s
+            currentIt++;
+        }
+
+        assertEquals( getTitle(), title );
+    }
+
+    protected void createAndAddUserAsDeveloperToGroup( String username, String name, String email, String groupName )
+    {
+        clickLinkWithText( "Users" );
+        assertPage( "[Admin] User List" );
+        selectValue( "xpath=//select[@name='ec_rd']", "100" );
+        waitPage();
+        if ( !isLinkPresent( username ) )
+        {
+            clickButtonWithValue( "Create New User" );
+            assertPage( "[Admin] User Create" );
+            setFieldValue( "user.fullName", name );
+            setFieldValue( "user.username", username );
+            setFieldValue( "user.email", email );
+            setFieldValue( "user.password", "password123" );
+            setFieldValue( "user.confirmPassword", "password123" );
+            clickButtonWithValue( "Create User" );
+            assertPage( "[Admin] User Edit" );
+            assignContinuumResourceRoleToUser( groupName );
+            clickButtonWithValue( "Submit" );
+            assertPage( "[Admin] User List" );
+            assertTextPresent( username );
+            assertTextPresent( name );
+            assertTextPresent( email );
+        }
+    }
+
+    protected void showMembers( String name, String groupId, String description )
+    {
+        showProjectGroup( name, groupId, description );
+        clickLinkWithText( "Members" );
+        assertTextPresent( "Member Projects of " + name + " group" );
+        assertTextPresent( "Users" );
+    }
+
+    protected void assertUserPresent( String username, String name, String email )
+    {
+        assertTextPresent( username );
+        assertTextPresent( name );
+        assertTextPresent( email );
+    }
+
+    protected void assertUserNotPresent( String username, String name, String email )
+    {
+        assertTextNotPresent( username );
+        assertTextNotPresent( name );
+        assertTextNotPresent( email );
+    }
+
+    protected void waitForProjectCheckout()
+    {
+        // wait for project to finish checking out
+        waitForElementPresent( "//img[@alt='Checking Out']", false );
+    }
+
+    void waitForProjectUpdate()
+    {
+        if ( isElementPresent( "//img[@alt='Checking Out']" ) )
+        {
+            waitForProjectCheckout();
+        }
+
+        // wait for project to finish updating
+        waitForElementPresent( "//img[@alt='Updating']", false );
+    }
+
+    void waitForProjectBuild()
+    {
+        if ( isElementPresent( "//img[@alt='Checking Out']" ) || isElementPresent( "//img[@alt='Updating']" ) )
+        {
+            waitForProjectUpdate();
+        }
+
+        // wait for project to finish building
+        waitForElementPresent( "//img[@alt='Building']", false );
+    }
+
+    void assignContinuumResourceRoleToUser( String groupName )
+    {
+        clickLinkWithXPath(
+            "//input[@name='addDSelectedRoles' and @value='" + "Project Developer" + " - " + groupName + "']", false );
+    }
+
+    protected void removeDefaultBuildDefinitionFromTemplate( String type )
+    {
+        goToEditBuildDefinitionTemplate( type );
+        clickLinkWithXPath( "//input[@value='<-']", false );
+        submit();
+    }
+
+    protected void addDefaultBuildDefinitionFromTemplate( String type )
+    {
+        goToEditBuildDefinitionTemplate( type );
+
+        if ( "maven2".equals( type ) )
+        {
+            getSelenium().addSelection( "saveBuildDefinitionTemplate_buildDefinitionIds",
+                                        "label=" + "Default Maven Build Definition" );
+        }
+
+        clickLinkWithXPath( "//input[@value='->']", false );
+        submit();
+    }
+
+    void goToEditBuildDefinitionTemplate( String type )
+    {
+        clickLinkWithText( "Build Definition Templates" );
+
+        assertBuildDefinitionTemplatesPage();
+
+        if ( "maven2".equals( type ) )
+        {
+            clickLinkWithXPath( "//table[@id='ec_table']/tbody/tr[3]/td[2]/a/img", true );
+        }
+        else if ( "maven1".equals( type ) )
+        {
+            clickLinkWithXPath( "//table[@id='ec_table']/tbody/tr[2]/td[2]/a/img", true );
+        }
+        else if ( "ant".equals( type ) )
+        {
+            clickLinkWithXPath( "//img[@alt='Edit']", true );
+        }
+        else
+        {
+            clickLinkWithXPath( "//table[@id='ec_table']/tbody/tr[4]/td[2]/a/img", true );
+        }
+
+        assertPage( "Continuum - Build Definition Template" );
+    }
+
+    void assertBuildDefinitionTemplatesPage()
+    {
+        assertPage( "Continuum - Build Definition Templates" );
+        assertTextPresent( "Default Ant Template" );
+        assertTextPresent( "Default Maven 1 Template" );
+        assertTextPresent( "Default Maven Template" );
+        assertTextPresent( "Default Shell Template" );
+        assertTextPresent( "Available Build Definitions" );
+        assertTextPresent( "Default Ant Build Definition" );
+        assertTextPresent( "Default Maven 1 Build Definition" );
+        assertTextPresent( "Default Maven Build Definition" );
+        assertTextPresent( "Default Shell Build Definition" );
+    }
+
+    // ////////////////////////////////////
+    // Reports
+    // ////////////////////////////////////
+
+    protected void goToProjectBuildsReport()
+    {
+        clickLinkWithText( "Project Builds" );
+        assertViewBuildsReportPage();
+    }
+
+    void assertViewBuildsReportPage()
+    {
+        assertPage( "Continuum - Project Builds Report" );
+        assertTextPresent( "Project Group" );
+        assertElementPresent( "projectGroupId" );
+        assertTextPresent( "Start Date" );
+        assertElementPresent( "startDate" );
+        assertTextPresent( "End Date" );
+        assertElementPresent( "endDate" );
+        assertTextPresent( "Triggered By" );
+        assertElementPresent( "triggeredBy" );
+        assertTextPresent( "Build Status" );
+        assertElementPresent( "buildStatus" );
+        assertTextPresent( "Row Count" );
+        assertElementPresent( "rowCount" );
+        assertButtonWithValuePresent( "View Report" );
+        assertTextNotPresent( "Results" );
+        assertTextNotPresent( "No Results Found" );
+        assertTextNotPresent( "Export to CSV" );
+    }
+
+    protected void assertProjectBuildReportWithResult()
+    {
+        assertTextPresent( "Results" );
+        assertTextPresent( "Project Group" );
+        assertTextPresent( "Project Name" );
+        assertTextPresent( "Build Date" );
+        assertTextPresent( "Triggered By" );
+        assertTextPresent( "Build Status" );
+        assertTextPresent( "Prev" );
+        assertTextPresent( "Next" );
+        assertTextPresent( "Export to CSV" );
+    }
+
+    protected void assertProjectBuildReportWithNoResult()
+    {
+        assertTextNotPresent( "Build Date" );
+        assertTextNotPresent( "Prev" );
+        assertTextNotPresent( "Next" );
+        assertTextNotPresent( "Export to CSV" );
+        assertTextPresent( "Results" );
+        assertTextPresent( "No Results Found" );
+    }
+
+    protected void assertProjectBuildReportWithFieldError()
+    {
+        assertTextNotPresent( "Build Date" );
+        assertTextNotPresent( "Prev" );
+        assertTextNotPresent( "Next" );
+        assertTextNotPresent( "Export to CSV" );
+        assertTextNotPresent( "Results" );
+        assertTextNotPresent( "No Results Found" );
+    }
+
+    @BeforeSuite( alwaysRun = true )
+    @Parameters( {"baseUrl", "browser", "seleniumHost", "seleniumPort"} )
+    public void initializeContinuum( @Optional( "http://localhost:9595/continuum" ) String baseUrl,
+                                     @Optional( "*firefox" ) String browser,
+                                     @Optional( "localhost" ) String seleniumHost,
+                                     @Optional( "4444" ) int seleniumPort )
+        throws Exception
+    {
+        super.open( baseUrl, browser, seleniumHost, seleniumPort );
+        Assert.assertNotNull( getSelenium(), "Selenium is not initialized" );
+        getSelenium().open( baseUrl );
+        String title = getSelenium().getTitle();
+        if ( title.equals( "Create Admin User" ) )
+        {
+            assertCreateAdmin();
+            String fullname = getProperty( "ADMIN_FULLNAME" );
+            String username = getProperty( "ADMIN_USERNAME" );
+            String mail = getProperty( "ADMIN_MAIL" );
+            String password = getProperty( "ADMIN_PASSWORD" );
+            submitAdminData( fullname, mail, password );
+            assertAutenticatedPage( username );
+            assertEditConfigurationPage();
+            postAdminUserCreation();
+            disableDefaultSchedule();
+            clickLinkWithText( "Logout" );
+        }
+    }
+
+    private void postAdminUserCreation()
+    {
+        if ( getTitle().endsWith( "Continuum - Configuration" ) )
+        {
+            String workingDir = getFieldValue( "workingDirectory" );
+            String buildOutputDir = getFieldValue( "buildOutputDirectory" );
+            String releaseOutputDir = getFieldValue( "releaseOutputDirectory" );
+            String locationDir = "target/data";
+            String data = "data";
+            setFieldValue( "workingDirectory", workingDir.replaceFirst( data, locationDir ) );
+            setFieldValue( "buildOutputDirectory", buildOutputDir.replaceFirst( data, locationDir ) );
+            setFieldValue( "releaseOutputDirectory", releaseOutputDir.replaceFirst( data, locationDir ) );
+            setFieldValue( "baseUrl", baseUrl );
+            submit();
+        }
+    }
+
+    private void disableDefaultSchedule()
+    {
+        clickLinkWithText( "Schedules" );
+        String xPath = "//preceding::td[text()='DEFAULT_SCHEDULE']//following::img[@alt='Edit']";
+        clickLinkWithXPath( xPath );
+        if ( isChecked( "saveSchedule_active" ) )
+        {
+            uncheckField( "saveSchedule_active" );
+        }
+        clickButtonWithValue( "Save" );
+    }
+
+    protected void login( String username, String password )
+    {
+        goToLoginPage();
+        getSelenium().type( "loginForm_username", username );
+        getSelenium().type( "loginForm_password", password );
+        getSelenium().click( "//input[@value='Login']" );
+        getSelenium().waitForPageToLoad( maxWaitTimeInMs );
+    }
+
+    protected void goToSchedulePage()
+    {
+        clickLinkWithText( "Schedules" );
+
+        assertSchedulePage();
+    }
+
+    protected void assertSchedulePage()
+    {
+        assertPage( "Continuum - Schedules" );
+        assertTextPresent( "Schedules" );
+        assertTextPresent( "Name" );
+        assertTextPresent( "Description" );
+        assertTextPresent( "Quiet Period" );
+        assertTextPresent( "Cron Expression" );
+        assertTextPresent( "Max Job Time" );
+        assertTextPresent( "Active" );
+        assertTextPresent( "DEFAULT_SCHEDULE" );
+        assertImgWithAlt( "Edit" );
+        assertImgWithAlt( "Delete" );
+        assertButtonWithValuePresent( "Add" );
+    }
+
+    protected void assertAddSchedulePage()
+    {
+        assertPage( "Continuum - Edit Schedule" );
+        assertTextPresent( "Edit Schedule" );
+        assertTextPresent( "Name" );
+        assertElementPresent( "name" );
+        assertTextPresent( "Description" );
+        assertElementPresent( "description" );
+        assertTextPresent( "Cron Expression" );
+        assertTextPresent( "Second" );
+        assertElementPresent( "second" );
+        assertTextPresent( "Minute" );
+        assertElementPresent( "minute" );
+        assertTextPresent( "Hour" );
+        assertElementPresent( "hour" );
+        assertTextPresent( "Day of Month" );
+        assertElementPresent( "dayOfMonth" );
+        assertTextPresent( "Month" );
+        assertElementPresent( "month" );
+        assertTextPresent( "Day of Week" );
+        assertElementPresent( "dayOfWeek" );
+        assertTextPresent( "Year [optional]" );
+        assertElementPresent( "year" );
+        assertTextPresent( "Maximum job execution time" );
+        assertElementPresent( "maxJobExecutionTime" );
+        assertTextPresent( "Quiet Period (seconds):" );
+        assertElementPresent( "delay" );
+        assertTextPresent( "Add Build Queue" );
+        assertElementPresent( "availableBuildQueuesIds" );
+        assertElementPresent( "selectedBuildQueuesIds" );
+        assertElementPresent( "active" );
+        assertTextPresent( "Enable/Disable the schedule" );
+        assertButtonWithValuePresent( "Save" );
+        assertButtonWithValuePresent( "Cancel" );
+    }
+
+    public void goToEditSchedule( String name, String description, String second, String minute, String hour,
+                                  String dayMonth, String month, String dayWeek, String year, String maxTime,
+                                  String period )
+    {
+        goToSchedulePage();
+        String xPath = "//preceding::td[text()='" + name + "']//following::img[@alt='Edit']";
+        clickLinkWithXPath( xPath );
+        assertAddSchedulePage();
+        assertFieldValue( name, "name" );
+        assertFieldValue( description, "description" );
+        assertFieldValue( second, "second" );
+        assertFieldValue( minute, "minute" );
+        assertFieldValue( hour, "hour" );
+        assertFieldValue( dayMonth, "dayOfMonth" );
+        assertFieldValue( month, "month" );
+        assertFieldValue( dayWeek, "dayOfWeek" );
+        assertFieldValue( year, "year" );
+        assertFieldValue( maxTime, "maxJobExecutionTime" );
+        assertFieldValue( period, "delay" );
+    }
+
+    protected void buildProjectForQueuePageTest( String projectGroupName, String groupId, String description )
+    {
+        showProjectGroup( projectGroupName, groupId, description );
+        clickButtonWithValue( "Build all projects" );
+        waitForElementPresent( "//img[@alt='Building']" );
+    }
+
+    protected void goToAddSchedule()
+    {
+        goToSchedulePage();
+        clickButtonWithValue( "Add" );
+        assertAddSchedulePage();
+    }
+
+    protected void addEditSchedule( String name, String description, String second, String minute, String hour,
+                                    String dayMonth, String month, String dayWeek, String year, String maxTime,
+                                    String period, boolean buildQueue, boolean success )
+    {
+        if ( buildQueue )
+        {
+            setFieldValue( "name", name );
+            setFieldValue( "description", description );
+            setFieldValue( "second", second );
+            setFieldValue( "minute", minute );
+            setFieldValue( "hour", hour );
+            setFieldValue( "dayOfMonth", dayMonth );
+            setFieldValue( "month", month );
+            setFieldValue( "dayOfWeek", dayWeek );
+            setFieldValue( "year", year );
+            setFieldValue( "maxJobExecutionTime", maxTime );
+            setFieldValue( "delay", period );
+            getSelenium().addSelection( "saveSchedule_availableBuildQueuesIds", "label=DEFAULT_BUILD_QUEUE" );
+            getSelenium().click( "//input[@value='->']" );
+            submit();
+        }
+        else
+        {
+            setFieldValue( "name", name );
+            setFieldValue( "description", description );
+            setFieldValue( "second", second );
+            setFieldValue( "minute", minute );
+            setFieldValue( "hour", hour );
+            setFieldValue( "dayOfMonth", dayMonth );
+            setFieldValue( "month", month );
+            setFieldValue( "dayOfWeek", dayWeek );
+            setFieldValue( "year", year );
+            setFieldValue( "maxJobExecutionTime", maxTime );
+            setFieldValue( "delay", period );
+            submit();
+        }
+
+        if ( success )
+        {
+            assertSchedulePage();
+        }
+        else
+        {
+            assertAddSchedulePage();
+        }
+    }
+
+    protected void goToBuildEnvironmentPage()
+    {
+        clickLinkWithText( "Build Environments" );
+        assertBuildEnvironmentPage();
+    }
+
+    protected void assertBuildEnvironmentPage()
+    {
+        assertPage( "Continuum - Build Environments" );
+        assertTextPresent( "Build Environments" );
+        assertButtonWithValuePresent( "Add" );
+    }
+
+    protected void goToAddBuildEnvironment()
+    {
+        goToBuildEnvironmentPage();
+        clickButtonWithValue( "Add" );
+        assertAddBuildEnvironmentPage();
+    }
+
+    protected void assertAddBuildEnvironmentPage()
+    {
+        assertPage( "Continuum - Build Environment" );
+        assertTextPresent( "Build Environment" );
+        assertTextPresent( "Build Environment Name" );
+        assertElementPresent( "profile.name" );
+        assertButtonWithValuePresent( "Save" );
+        assertButtonWithValuePresent( "Cancel" );
+    }
+
+    protected void addBuildEnvironmentWithBuildAgentGroup( String name, String[] installations,
+                                                           String buildAgentGroupName )
+    {
+        setFieldValue( "profile.name", name );
+        submit();
+        editBuildEnvironmentWithBuildAgentGroup( name, installations, buildAgentGroupName, true );
+    }
+
+    protected void editBuildEnvironmentWithBuildAgentGroup( String name, String[] installations,
+                                                            String buildAgentGroupName, boolean success )
+    {
+        setFieldValue( "profile.name", name );
+        selectValue( "profile.buildAgentGroup", buildAgentGroupName );
+        for ( String i : installations )
+        {
+            selectValue( "installationId", i );
+            clickButtonWithValue( "Add" );
+        }
+        submit();
+        if ( success )
+        {
+            assertBuildEnvironmentPage();
+        }
+        else
+        {
+            assertAddBuildEnvironmentPage();
+        }
+    }
+
+    protected void assertEditBuildEnvironmentPage( String name )
+    {
+        assertAddBuildEnvironmentPage();
+        assertTextPresent( "Installation Name" );
+        assertTextPresent( "Type" );
+        assertFieldValue( name, "profile.name" );
+    }
+
+    protected void goToEditBuildEnvironment( String name )
+    {
+        goToBuildEnvironmentPage();
+        String xPath = "//preceding::td[text()='" + name + "']//following::img[@alt='Edit']";
+        clickLinkWithXPath( xPath );
+        assertEditBuildEnvironmentPage( name );
+    }
+
+    protected void removeBuildEnvironment( String name )
+    {
+        removeBuildEnvironment( name, true );
+    }
+
+    protected void removeBuildEnvironment( String name, boolean failIfMissing )
+    {
+        goToBuildEnvironmentPage();
+        String xPath = "//preceding::td[text()='" + name + "']//following::img[@alt='Delete']";
+        if ( failIfMissing || isElementPresent( "xpath=" + xPath ) )
+        {
+            clickLinkWithXPath( xPath );
+            assertPage( "Continuum - Delete Build Environment" );
+            assertTextPresent( "Delete Build Environment" );
+            assertTextPresent( "Are you sure you want to delete Build Environment \"" + name + "\" ?" );
+            assertButtonWithValuePresent( "Delete" );
+            assertButtonWithValuePresent( "Cancel" );
+            clickButtonWithValue( "Delete" );
+            assertBuildEnvironmentPage();
+            assertElementNotPresent( "xpath=" + xPath );
+        }
+    }
+
+    public static boolean isWindows()
+    {
+        String os = System.getProperty( "os.name" ).toLowerCase();
+        //windows
+        return os.contains( "win" );
+    }
+
+    // ////////////////////////////////////
+    // Appearance
+    // ////////////////////////////////////
+
+    protected void goToAppearancePage()
+    {
+        clickLinkWithText( "Appearance" );
+        assertAppearancePage();
+    }
+
+    protected void assertAppearancePage()
+    {
+        assertPage("Configure Appearance");
+        assertTextPresent("Appearance");
+        assertTextPresent("Company Details");
+        assertTextPresent("Footer Content");
+        assertButtonWithValuePresent( "Save" );
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/parent/AbstractInstallationTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/parent/AbstractInstallationTest.java
new file mode 100644
index 0000000..ad795de
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/parent/AbstractInstallationTest.java
@@ -0,0 +1,190 @@
+package org.apache.continuum.web.test.parent;
+
+/*
+ * 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.
+ */
+
+/**
+ * @author José Morales Martínez
+ * @version $Id$
+ */
+public abstract class AbstractInstallationTest
+    extends AbstractAdminTest
+{
+    protected void goToInstallationPage()
+    {
+        clickLinkWithText( "Installations" );
+        assertInstallationPage();
+    }
+
+    void assertInstallationPage()
+    {
+        assertPage( "Continuum - Installations" );
+        assertTextPresent( "Installations" );
+        assertButtonWithValuePresent( "Add" );
+    }
+
+    protected void goToAddInstallationTool()
+    {
+        goToInstallationPage();
+        clickButtonWithValue( "Add" );
+        assertAddChoiceTypeInstallation();
+        selectValue( "installationType", "Tool" );
+        clickButtonWithValue( "Add" );
+        assertAddInstallationToolPage();
+    }
+
+    protected void goToAddInstallationVariable()
+    {
+        goToInstallationPage();
+        clickButtonWithValue( "Add" );
+        assertAddChoiceTypeInstallation();
+        selectValue( "installationType", "Environment Variable" );
+        clickButtonWithValue( "Add" );
+        assertAddInstallationVariablePage();
+    }
+
+    void assertAddChoiceTypeInstallation()
+    {
+        assertPage( "Continuum - Installation Type Choice" );
+        assertTextPresent( "Installation Type Choice" );
+        assertTextPresent( "Installation Type" );
+        assertOptionPresent( "installationType", new String[]{"Tool", "Environment Variable"} );
+        assertButtonWithValuePresent( "Add" );
+        assertButtonWithValuePresent( "Cancel" );
+    }
+
+    void assertAddInstallationToolPage()
+    {
+        assertEditInstallationToolPage();
+        assertElementPresent( "automaticProfile" );
+        assertTextPresent( "Create a Build Environment with the Installation name" );
+    }
+
+    void assertEditInstallationToolPage()
+    {
+        assertPage( "Continuum - Installation" );
+        assertTextPresent( "Installation" );
+        assertTextPresent( "Name" );
+        assertElementPresent( "installation.name" );
+        assertTextPresent( "Type" );
+        assertOptionPresent( "installation.type", new String[]{"JDK", "Maven", "Maven 1", "ANT"} );
+        assertTextPresent( "Value/Path" );
+        assertElementPresent( "installation.varValue" );
+        assertButtonWithValuePresent( "Save" );
+        assertButtonWithValuePresent( "Cancel" );
+    }
+
+    void assertAddInstallationVariablePage()
+    {
+        assertEditInstallationVariablePage();
+        assertElementPresent( "automaticProfile" );
+        assertTextPresent( "Create a Build Environment with the Installation name" );
+    }
+
+    protected void assertEditInstallationVariablePage()
+    {
+        assertPage( "Continuum - Installation" );
+        assertTextPresent( "Installation" );
+        assertTextPresent( "Name" );
+        assertElementPresent( "installation.name" );
+        assertTextPresent( "Environment Variable Name" );
+        assertElementPresent( "installation.varName" );
+        assertTextPresent( "Value/Path" );
+        assertElementPresent( "installation.varValue" );
+        assertButtonWithValuePresent( "Save" );
+        assertButtonWithValuePresent( "Cancel" );
+    }
+
+    protected void addInstallation( String name, String var, String path, boolean createBuildEnv, boolean tool,
+                                    boolean success )
+    {
+        if ( createBuildEnv )
+        {
+            checkField( "automaticProfile" );
+        }
+        else
+        {
+            uncheckField( "automaticProfile" );
+        }
+        editInstallation( name, var, path, tool, success );
+    }
+
+    protected void editInstallation( String name, String var, String path, boolean tool, boolean success )
+    {
+        setFieldValue( "installation.name", name );
+        setFieldValue( "installation.varValue", path );
+        if ( tool )
+        {
+            selectValue( "installation.type", var );
+        }
+        else
+        {
+            setFieldValue( "installation.varName", var );
+        }
+        submit();
+        if ( success )
+        {
+            assertInstallationPage();
+        }
+        else if ( tool )
+        {
+            assertAddInstallationToolPage();
+        }
+        else
+        {
+            assertAddInstallationVariablePage();
+        }
+    }
+
+    protected void goToEditInstallation( String name, String var, String path, boolean tool )
+    {
+        goToInstallationPage();
+        String xPath = "//preceding::td[text()='" + name + "']//following::img[@alt='Edit']";
+        clickLinkWithXPath( xPath );
+        if ( tool )
+        {
+            assertEditInstallationToolPage();
+        }
+        else
+        {
+            assertEditInstallationVariablePage();
+            assertFieldValue( var, "installation.varName" );
+        }
+        assertFieldValue( name, "installation.name" );
+        assertFieldValue( path, "installation.varValue" );
+    }
+
+    protected void removeInstallation( String name, boolean failIfMissing )
+    {
+        goToInstallationPage();
+        String xpath = "(//a[contains(@href,'deleteInstallation') and contains(@href, '" + name + "')])//img";
+        if ( isElementPresent( "xpath=" + xpath ) || failIfMissing )
+        {
+            clickLinkWithXPath( xpath );
+            assertPage( "Continuum - Delete Installation" );
+            assertTextPresent( "Delete Installation" );
+            assertTextPresent( "Are you sure you want to delete \"" + name + "\" installation ?" );
+            assertButtonWithValuePresent( "Delete" );
+            assertButtonWithValuePresent( "Cancel" );
+            clickButtonWithValue( "Delete" );
+            assertInstallationPage();
+        }
+    }
+
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/parent/AbstractLocalRepositoryTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/parent/AbstractLocalRepositoryTest.java
new file mode 100644
index 0000000..1f35009
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/parent/AbstractLocalRepositoryTest.java
@@ -0,0 +1,107 @@
+package org.apache.continuum.web.test.parent;
+
+/*
+ * 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.
+ */
+
+/**
+ * @author José Morales Martínez
+ * @version $Id$
+ */
+public abstract class AbstractLocalRepositoryTest
+    extends AbstractAdminTest
+{
+    void goToLocalRepositoryPage()
+    {
+        clickLinkWithText( "Local Repositories" );
+
+        assertLocalRepositoryPage();
+    }
+
+    void assertLocalRepositoryPage()
+    {
+        assertPage( "Continuum - Local Repositories" );
+        assertTextPresent( "Local Repositories" );
+        assertTextPresent( "Name" );
+        assertTextPresent( "Location" );
+        assertTextPresent( "Layout" );
+        assertImgWithAlt( "Edit" );
+        assertImgWithAlt( "Purge" );
+        assertImgWithAlt( "Delete" );
+        assertButtonWithValuePresent( "Add" );
+    }
+
+    void assertAddLocalRepositoryPage()
+    {
+        assertPage( "Continuum - Add/Edit Local Repository" );
+        assertTextPresent( "Add/Edit Local Repository" );
+        assertTextPresent( "Name" );
+        assertElementPresent( "repository.name" );
+        assertTextPresent( "Location" );
+        assertElementPresent( "repository.location" );
+        assertTextPresent( "Layout" );
+        assertElementPresent( "repository.layout" );
+        assertButtonWithValuePresent( "Save" );
+        assertButtonWithValuePresent( "Cancel" );
+    }
+
+    protected void removeLocalRepository( String name )
+    {
+        goToLocalRepositoryPage();
+        String xPath = "//preceding::td[text()='" + name + "']//following::img[@alt='Delete']";
+        clickLinkWithXPath( xPath );
+        assertTextPresent( "Delete Local Repository" );
+        assertTextPresent( "Are you sure you want to delete Local Repository \"" + name + "\" ?" );
+        assertButtonWithValuePresent( "Delete" );
+        assertButtonWithValuePresent( "Cancel" );
+        clickButtonWithValue( "Delete" );
+        assertLocalRepositoryPage();
+    }
+
+    protected void goToAddLocalRepository()
+    {
+        goToLocalRepositoryPage();
+        clickButtonWithValue( "Add" );
+        assertAddLocalRepositoryPage();
+    }
+
+    protected void goToEditLocalRepository( String name, String location )
+    {
+        goToLocalRepositoryPage();
+        String xPath = "//preceding::td[text()='" + name + "']//following::img[@alt='Edit']";
+        clickLinkWithXPath( xPath );
+        assertAddLocalRepositoryPage();
+        assertFieldValue( name, "repository.name" );
+        assertFieldValue( location, "repository.location" );
+    }
+
+    protected void addEditLocalRepository( String name, String location, boolean success )
+    {
+        setFieldValue( "repository.name", name );
+        setFieldValue( "repository.location", location );
+        submit();
+        if ( success )
+        {
+            assertLocalRepositoryPage();
+        }
+        else
+        {
+            assertAddLocalRepositoryPage();
+        }
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/parent/AbstractPurgeTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/parent/AbstractPurgeTest.java
new file mode 100644
index 0000000..ff1767f
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/parent/AbstractPurgeTest.java
@@ -0,0 +1,178 @@
+package org.apache.continuum.web.test.parent;
+
+/*
+ * 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.
+ */
+
+/**
+ * @author José Morales Martínez
+ * @version $Id$
+ */
+public abstract class AbstractPurgeTest
+    extends AbstractAdminTest
+{
+    void goToGeneralPurgePage()
+    {
+        clickLinkWithText( "Purge Configurations" );
+        assertGeneralPurgePage();
+    }
+
+    void assertGeneralPurgePage()
+    {
+        assertPage( "Continuum - Purge Configurations" );
+        assertTextPresent( "Repository Purge Configurations" );
+        assertTextPresent( "Directory Purge Configurations" );
+        assertButtonWithValuePresent( "Add" );
+    }
+
+    protected void removeRepositoryPurge( String purgeDescription )
+    {
+        goToGeneralPurgePage();
+        clickLinkWithXPath(
+            "(//a[contains(@href,'removePurgeConfig.action') and contains(@href, '" + purgeDescription + "')])//img" );
+        assertTextPresent( "Delete Purge Configuration" );
+        assertTextPresent( "Are you sure you want to delete Purge Configuration \"" + purgeDescription + "\"?" );
+        assertButtonWithValuePresent( "Delete" );
+        assertButtonWithValuePresent( "Cancel" );
+        clickButtonWithValue( "Delete" );
+        assertGeneralPurgePage();
+    }
+
+    protected void removeDirectoryPurge( String purgeDescription )
+    {
+        goToGeneralPurgePage();
+        clickLinkWithXPath(
+            "(//a[contains(@href,'removePurgeConfig.action') and contains(@href, '" + purgeDescription + "')])//img" );
+        assertTextPresent( "Delete Purge Configuration" );
+        assertTextPresent( "Are you sure you want to delete Purge Configuration \"" + purgeDescription + "\"?" );
+        assertButtonWithValuePresent( "Delete" );
+        assertButtonWithValuePresent( "Cancel" );
+        clickButtonWithValue( "Delete" );
+        assertGeneralPurgePage();
+    }
+
+    void assertAddRepositoryPurgePage()
+    {
+        assertPage( "Continuum - Add/Edit Purge Configuration" );
+        assertTextPresent( "Add/Edit Purge Configuration" );
+        assertTextPresent( "Repository" );
+        assertElementPresent( "repositoryId" );
+        assertTextPresent( "Days Older" );
+        assertElementPresent( "daysOlder" );
+        assertTextPresent( "Retention Count" );
+        assertElementPresent( "retentionCount" );
+        assertElementPresent( "deleteAll" );
+        assertElementPresent( "deleteReleasedSnapshots" );
+        assertElementPresent( "defaultPurgeConfiguration" );
+        assertTextPresent( "Schedule" );
+        assertElementPresent( "scheduleId" );
+        assertTextPresent( "Description" );
+        assertElementPresent( "description" );
+        assertButtonWithValuePresent( "Save" );
+        assertButtonWithValuePresent( "Cancel" );
+    }
+
+    void assertAddEditDirectoryPurgePage()
+    {
+        assertPage( "Continuum - Add/Edit Purge Configuration" );
+        assertTextPresent( "Add/Edit Purge Configuration" );
+        assertTextPresent( "Directory Type" );
+        assertElementPresent( "directoryType" );
+        assertTextPresent( "Days Older" );
+        assertElementPresent( "daysOlder" );
+        assertTextPresent( "Retention Count" );
+        assertElementPresent( "retentionCount" );
+        assertElementPresent( "deleteAll" );
+        assertElementPresent( "defaultPurgeConfiguration" );
+        assertTextPresent( "Schedule" );
+        assertElementPresent( "scheduleId" );
+        assertTextPresent( "Description" );
+        assertElementPresent( "description" );
+        assertButtonWithValuePresent( "Save" );
+        assertButtonWithValuePresent( "Cancel" );
+    }
+
+    protected void goToAddRepositoryPurge()
+    {
+        goToGeneralPurgePage();
+        clickLinkWithXPath( "//form[@name='addRepoPurgeConfig']/input[@type='submit']" );
+        assertAddRepositoryPurgePage();
+    }
+
+    protected void goToEditRepositoryPurge( String daysOlder, String retentionCount, String description )
+    {
+        goToGeneralPurgePage();
+        String xPath = "//preceding::td[text()='" + description + "']//following::img[@alt='Edit']";
+        clickLinkWithXPath( xPath );
+        assertAddRepositoryPurgePage();
+        assertFieldValue( daysOlder, "daysOlder" );
+        assertFieldValue( retentionCount, "retentionCount" );
+        assertFieldValue( description, "description" );
+    }
+
+    protected void goToEditDirectoryPurge( String daysOlder, String retentionCount, String description )
+    {
+        goToGeneralPurgePage();
+        String xPath = "//preceding::td[text()='" + description + "']//following::img[@alt='Edit']";
+        clickLinkWithXPath( xPath );
+        assertAddEditDirectoryPurgePage();
+        assertFieldValue( daysOlder, "daysOlder" );
+        assertFieldValue( retentionCount, "retentionCount" );
+        assertFieldValue( description, "description" );
+    }
+
+    protected void addEditRepositoryPurge( String daysOlder, String retentionCount, String description,
+                                           boolean success )
+    {
+        setFieldValue( "daysOlder", daysOlder );
+        setFieldValue( "retentionCount", retentionCount );
+        setFieldValue( "description", description );
+        submit();
+        if ( success )
+        {
+            assertGeneralPurgePage();
+        }
+        else
+        {
+            assertAddRepositoryPurgePage();
+        }
+    }
+
+    protected void goToAddDirectoryPurge()
+    {
+        goToGeneralPurgePage();
+        clickLinkWithXPath( "//form[@name='addDirPurgeConfig']/input[@type='submit']" );
+        assertAddEditDirectoryPurgePage();
+    }
+
+    protected void addEditDirectoryPurge( String daysOlder, String retentionCount, String description, boolean success )
+    {
+        setFieldValue( "daysOlder", daysOlder );
+        setFieldValue( "retentionCount", retentionCount );
+        setFieldValue( "description", description );
+        submit();
+        if ( success )
+        {
+            assertGeneralPurgePage();
+        }
+        else
+        {
+            assertAddEditDirectoryPurgePage();
+        }
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/parent/AbstractSeleniumTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/parent/AbstractSeleniumTest.java
new file mode 100644
index 0000000..134a944
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/parent/AbstractSeleniumTest.java
@@ -0,0 +1,414 @@
+package org.apache.continuum.web.test.parent;
+
+/*
+ * 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 com.thoughtworks.selenium.DefaultSelenium;
+import com.thoughtworks.selenium.Selenium;
+import org.apache.commons.io.IOUtils;
+import org.testng.Assert;
+import org.testng.annotations.AfterSuite;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * Based on AbstractSeleniumTestCase of Emmanuel Venisse test.
+ *
+ * @author José Morales Martínez
+ * @version $Id$
+ */
+public abstract class AbstractSeleniumTest
+{
+    protected static String baseUrl;
+
+    static String browser;
+
+    protected static String maxWaitTimeInMs;
+
+    private static final ThreadLocal<Selenium> selenium = new ThreadLocal<Selenium>();
+
+    private static Properties p;
+
+    private final static String PROPERTIES_SEPARATOR = "=";
+
+    private static String maxProjectWaitTimeInMs;
+
+    /**
+     * Initialize selenium
+     */
+    void open( String baseUrl, String browser, String seleniumHost, int seleniumPort )
+        throws Exception
+    {
+        InputStream input = this.getClass().getClassLoader().getResourceAsStream( "testng.properties" );
+        p = new Properties();
+        p.load( input );
+
+        // for running in the IDE
+        String svnBaseUrl = "file://localhost/" + new File( "target/example-svn" ).getAbsolutePath();
+        for ( String key : p.stringPropertyNames() )
+        {
+            String value = p.getProperty( key );
+            String newValue = value.replace( "${svn.base.url}", svnBaseUrl );
+            newValue = newValue.replace( "${maven.home}", System.getProperty( "maven.home", "/usr/share/maven" ) );
+            p.setProperty( key, newValue );
+        }
+
+        maxWaitTimeInMs = getProperty( "MAX_WAIT_TIME_IN_MS" );
+        maxProjectWaitTimeInMs = getProperty( "MAX_PROJECT_WAIT_TIME_IN_MS" );
+
+        AbstractSeleniumTest.baseUrl = baseUrl;
+
+        AbstractSeleniumTest.browser = browser;
+
+        if ( getSelenium() == null )
+        {
+            DefaultSelenium s = new DefaultSelenium( seleniumHost, seleniumPort, browser, baseUrl );
+            s.start();
+            s.setTimeout( maxWaitTimeInMs );
+            selenium.set( s );
+        }
+    }
+
+    public static Selenium getSelenium()
+    {
+        return selenium == null ? null : selenium.get();
+    }
+
+    protected String getProperty( String key )
+    {
+        return p.getProperty( key );
+    }
+
+    // TODO: look into removing this, as the issue should be fixed by upgrading the resources plugin to v2.4+
+    protected String getEscapeProperty( String key )
+    {
+        InputStream input = this.getClass().getClassLoader().getResourceAsStream( "testng.properties" );
+        String value = null;
+        List<String> lines;
+        try
+        {
+            lines = IOUtils.readLines( input );
+        }
+        catch ( IOException e )
+        {
+            lines = new ArrayList<String>();
+        }
+        for ( String l : lines )
+        {
+            if ( l != null && l.startsWith( key ) )
+            {
+                int indexSeparator = l.indexOf( PROPERTIES_SEPARATOR );
+                value = l.substring( indexSeparator + 1 ).trim();
+                break;
+            }
+        }
+        return value;
+    }
+
+    /**
+     * Close selenium session. Called from AfterSuite method of sub-class
+     */
+    @AfterSuite( alwaysRun = true )
+    public void close()
+        throws Exception
+    {
+        if ( getSelenium() != null )
+        {
+            getSelenium().stop();
+            selenium.set( null );
+        }
+    }
+
+    // *******************************************************
+    // Auxiliar methods. This method help us and simplify test.
+    // *******************************************************
+
+    protected void assertFieldValue( String fieldValue, String fieldName )
+    {
+        assertElementPresent( fieldName );
+        Assert.assertEquals( fieldValue, getSelenium().getValue( fieldName ) );
+    }
+
+    protected void assertPage( String title )
+    {
+        Assert.assertEquals( getTitle(), title );
+    }
+
+    protected String getTitle()
+    {
+        return getSelenium().getTitle();
+    }
+
+    protected void assertTextPresent( String text )
+    {
+        Assert.assertTrue( getSelenium().isTextPresent( text ), "'" + text + "' isn't present." );
+    }
+
+    protected void assertTextNotPresent( String text )
+    {
+        Assert.assertFalse( getSelenium().isTextPresent( text ), "'" + text + "' is present." );
+    }
+
+    protected void assertElementPresent( String elementLocator )
+    {
+        Assert.assertTrue( isElementPresent( elementLocator ), "'" + elementLocator + "' isn't present." );
+    }
+
+    protected void assertElementNotPresent( String elementLocator )
+    {
+        Assert.assertFalse( isElementPresent( elementLocator ), "'" + elementLocator + "' is present." );
+    }
+
+    protected void assertLinkPresent( String text )
+    {
+        Assert.assertTrue( isElementPresent( "link=" + text ), "The link '" + text + "' isn't present." );
+    }
+
+    protected void assertLinkNotPresent( String text )
+    {
+        Assert.assertFalse( isElementPresent( "link=" + text ), "The link '" + text + "' is present." );
+    }
+
+    protected void assertImgWithAlt( String alt )
+    {
+        assertElementPresent( "//img[@alt='" + alt + "']" );
+    }
+
+    protected void assertCellValueFromTable( String expected, String tableElement, int row, int column )
+    {
+        Assert.assertEquals( expected, getCellValueFromTable( tableElement, row, column ) );
+    }
+
+    protected boolean isTextPresent( String text )
+    {
+        return getSelenium().isTextPresent( text );
+    }
+
+    protected boolean isLinkPresent( String text )
+    {
+        return isElementPresent( "link=" + text );
+    }
+
+    protected boolean isElementPresent( String locator )
+    {
+        return getSelenium().isElementPresent( locator );
+    }
+
+    protected void waitPage()
+    {
+        getSelenium().waitForPageToLoad( maxWaitTimeInMs );
+    }
+
+    protected String getFieldValue( String fieldName )
+    {
+        return getSelenium().getValue( fieldName );
+    }
+
+    String getCellValueFromTable( String tableElement, int row, int column )
+    {
+        return getSelenium().getTable( tableElement + "." + row + "." + column );
+    }
+
+    protected void selectValue( String locator, String value )
+    {
+        getSelenium().select( locator, "label=" + value );
+    }
+
+    void assertOptionPresent( String selectField, String[] options )
+    {
+        assertElementPresent( selectField );
+        String[] optionsPresent = getSelenium().getSelectOptions( selectField );
+        List<String> expected = Arrays.asList( options );
+        List<String> present = Arrays.asList( optionsPresent );
+
+        Assert.assertTrue( present.containsAll( expected ), "Options expected are not included in present options" );
+    }
+
+    protected void submit()
+    {
+        submit( true );
+    }
+
+    protected void submit( boolean wait )
+    {
+        clickLinkWithXPath( "//input[@type='submit']", wait );
+    }
+
+    protected void assertButtonWithValuePresent( String text )
+    {
+        Assert.assertTrue( isButtonWithValuePresent( text ), "'" + text + "' button isn't present" );
+    }
+
+    void assertButtonWithIdPresent( String id )
+    {
+        Assert.assertTrue( isButtonWithIdPresent( id ), "'Button with id =" + id + "' isn't present" );
+    }
+
+    boolean isButtonWithValuePresent( String text )
+    {
+        return isElementPresent( "//button[@value='" + text + "']" ) || isElementPresent(
+            "//input[@value='" + text + "']" );
+    }
+
+    boolean isButtonWithIdPresent( String text )
+    {
+        return isElementPresent( "//button[@id='" + text + "']" ) || isElementPresent( "//input[@id='" + text + "']" );
+    }
+
+    protected void clickButtonWithValue( String text )
+    {
+        clickButtonWithValue( text, true );
+    }
+
+    void clickButtonWithValue( String text, boolean wait )
+    {
+        assertButtonWithValuePresent( text );
+
+        if ( isElementPresent( "//button[@value='" + text + "']" ) )
+        {
+            clickLinkWithXPath( "//button[@value='" + text + "']", wait );
+        }
+        else
+        {
+            clickLinkWithXPath( "//input[@value='" + text + "']", wait );
+        }
+    }
+
+    void clickSubmitWithLocator( String locator )
+    {
+        clickLinkWithLocator( locator );
+    }
+
+    protected void clickImgWithAlt( String alt )
+    {
+        clickLinkWithLocator( "//img[@alt='" + alt + "']" );
+    }
+
+    protected void clickLinkWithText( String text )
+    {
+        clickLinkWithLocator( "link=" + text, true );
+    }
+
+    protected void clickLinkWithXPath( String xpath )
+    {
+        clickLinkWithXPath( xpath, true );
+    }
+
+    protected void clickLinkWithXPath( String xpath, boolean wait )
+    {
+        clickLinkWithLocator( "xpath=" + xpath, wait );
+    }
+
+    protected void clickLinkWithLocator( String locator )
+    {
+        clickLinkWithLocator( locator, true );
+    }
+
+    protected void clickLinkWithLocator( String locator, boolean wait )
+    {
+        getSelenium().click( locator );
+        if ( wait )
+        {
+            waitPage();
+        }
+    }
+
+    protected void setFieldValue( String fieldName, String value )
+    {
+        getSelenium().type( fieldName, value );
+    }
+
+    protected void checkField( String locator )
+    {
+        getSelenium().check( locator );
+    }
+
+    protected void uncheckField( String locator )
+    {
+        getSelenium().uncheck( locator );
+    }
+
+    boolean isChecked( String locator )
+    {
+        return getSelenium().isChecked( locator );
+    }
+
+    void assertIsChecked( String locator )
+    {
+        Assert.assertTrue( isChecked( locator ) );
+    }
+
+    void click( String locator )
+    {
+        getSelenium().click( locator );
+    }
+
+    protected void clickAndWait( String locator )
+    {
+        getSelenium().click( locator );
+        getSelenium().waitForPageToLoad( maxWaitTimeInMs );
+    }
+
+    protected void waitForElementPresent( String locator )
+    {
+        waitForElementPresent( locator, true );
+    }
+
+    /*
+     * This will wait for the condition to be met.
+     *   * shouldBePresent - if the locator is expected or not (true or false respectively)
+     */
+    void waitForElementPresent( String locator, boolean shouldBePresent )
+    {
+        waitForOneOfElementsPresent( Collections.singletonList( locator ), shouldBePresent );
+    }
+
+    protected void waitForOneOfElementsPresent( List<String> locators, boolean shouldBePresent )
+    {
+        int currentIt = 0;
+        int maxIt = Integer.valueOf( getProperty( "WAIT_TRIES" ) );
+        String pageLoadTimeInMs = maxWaitTimeInMs;
+
+        while ( currentIt < maxIt )
+        {
+            for ( String locator : locators )
+            {
+                if ( isElementPresent( locator ) == shouldBePresent )
+                {
+                    return;
+                }
+            }
+
+            getSelenium().waitForPageToLoad( pageLoadTimeInMs );
+            currentIt++;
+        }
+    }
+
+    void assertEnabled()
+    {
+        Assert.assertTrue( getSelenium().isEditable( "alwaysBuild" ), "'" + "alwaysBuild" + "' is disabled" );
+    }
+}
diff --git a/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/parent/AbstractUserRolesManagementTest.java b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/parent/AbstractUserRolesManagementTest.java
new file mode 100644
index 0000000..92fd735
--- /dev/null
+++ b/continuum-webapp-test/src/test/testng/org/apache/continuum/web/test/parent/AbstractUserRolesManagementTest.java
@@ -0,0 +1,338 @@
+package org.apache.continuum.web.test.parent;
+
+/*
+ * 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.
+ */
+
+public abstract class AbstractUserRolesManagementTest
+    extends AbstractAdminTest
+{
+    protected String username;
+
+    protected String fullname;
+
+    protected String getUserEmail()
+    {
+        return getProperty( "USERROLE_EMAIL" );
+    }
+
+    protected String getUserRolePassword()
+    {
+        return getProperty( "USERROLE_PASSWORD" );
+    }
+
+    protected String getUserRoleNewPassword()
+    {
+        return getProperty( "NEW_USERROLE_PASSWORD" );
+    }
+
+    ////////////////////////////
+    // Assertions
+    ////////////////////////////
+    protected void assertCreateUserPage()
+    {
+        assertPage( "[Admin] User Create" );
+        assertTextPresent( "[Admin] User Create" );
+        assertTextPresent( "Username*:" );
+        assertElementPresent( "user.username" );
+        assertTextPresent( "Full Name*:" );
+        assertElementPresent( "user.fullName" );
+        assertTextPresent( "Email Address*:" );
+        assertElementPresent( "user.email" );
+        assertTextPresent( "Password*:" );
+        assertElementPresent( "user.password" );
+        assertTextPresent( "Confirm Password*:" );
+        assertElementPresent( "user.confirmPassword" );
+        assertButtonWithValuePresent( "Create User" );
+    }
+
+    protected void assertUserRolesPage()
+    {
+        assertPage( "[Admin] User Edit" );
+        assertTextPresent( "[Admin] User Roles" );
+        String userRoles =
+            "Username,Full Name,Email,Guest,Registered User,System Administrator,User Administrator,Continuum Group Project Administrator,Continuum Group Project Developer,Continuum Group Project User,Continuum Manage Build Environments,Continuum Manage Build Templates,Continuum Manage Installations,Continuum Manage Local Repositories,Continuum Manage Purging,Continuum Manage Queues,Continuum Manage Scheduling,Project Administrator,Project Developer,Project User,Default Project Group";
+        String[] arrayUserRoles = userRoles.split( "," );
+        for ( String userroles : arrayUserRoles )
+        {
+            assertTextPresent( userroles );
+        }
+    }
+
+    protected void assertCreatedUserInfo( String username )
+    {
+        selectValue( "name=ec_rd", "50" );
+        waitPage();
+        clickLinkWithText( username );
+        clickLinkWithText( "Edit Roles" );
+    }
+
+    void assertUserRoleCheckBoxPresent( String value )
+    {
+        getSelenium().isElementPresent(
+            "xpath=//input[@id='addRolesToUser_addNDSelectedRoles' and @name='addNDSelectedRoles' and @value='" +
+                value + "']" );
+    }
+
+    void assertResourceRolesCheckBoxPresent( String value )
+    {
+        getSelenium().isElementPresent( "xpath=//input[@name='addDSelectedRoles' and @value='" + value + "']" );
+    }
+
+    protected void checkUserRoleWithValue( String value )
+    {
+        assertUserRoleCheckBoxPresent( value );
+        getSelenium().click(
+            "xpath=//input[@id='addRolesToUser_addNDSelectedRoles' and @name='addNDSelectedRoles' and @value='" +
+                value + "']" );
+    }
+
+    protected void checkResourceRoleWithValue( String value )
+    {
+        assertResourceRolesCheckBoxPresent( value );
+        getSelenium().click( "xpath=//input[@name='addDSelectedRoles' and @value='" + value + "']" );
+    }
+
+    protected void assertLeftNavMenuWithRole( String role )
+    {
+        if ( "System Administrator".equals( role ) )
+        {
+            String navMenu =
+                "About,Show Project Groups,Maven Project,Maven 1.x Project,Ant Project,Shell Project,Local Repositories,Purge Configurations,Schedules,Installations,Build Environments,Queues,Build Definition Templates,Configuration,Appearance,Users,Roles,Build Queue";
+            String[] arrayNavMenu = navMenu.split( "," );
+            for ( String navmenu : arrayNavMenu )
+            {
+                assertLinkPresent( navmenu );
+            }
+        }
+        else if ( "User Administrator".equals( role ) )
+        {
+            String navMenu = "About,Show Project Groups,Users,Roles";
+            String[] arrayNavMenu = navMenu.split( "," );
+            for ( String navmenu : arrayNavMenu )
+            {
+                assertLinkPresent( navmenu );
+            }
+        }
+        else if ( "Continuum Group Project Administrator".equals( role ) )
+        {
+            String navMenu =
+                "About,Show Project Groups,Maven Project,Maven 1.x Project,Ant Project,Shell Project,Schedules,Queues,Users,Roles";
+            String[] arrayNavMenu = navMenu.split( "," );
+            for ( String navmenu : arrayNavMenu )
+            {
+                assertLinkPresent( navmenu );
+            }
+        }
+        else if ( "Continuum Group Project Developer".equals( role ) )
+        {
+            String navMenu = "About,Show Project Groups,Queues";
+            String[] arrayNavMenu = navMenu.split( "," );
+            for ( String navmenu : arrayNavMenu )
+            {
+                assertLinkPresent( navmenu );
+            }
+        }
+        else if ( "Continuum Group Project User".equals( role ) )
+        {
+            String navMenu = "About,Show Project Groups,Queues";
+            String[] arrayNavMenu = navMenu.split( "," );
+            for ( String navmenu : arrayNavMenu )
+            {
+                assertLinkPresent( navmenu );
+            }
+        }
+        else if ( "Continuum Manage Build Environments".equals( role ) )
+        {
+            String navMenu = "About,Show Project Groups,Build Environments";
+            String[] arrayNavMenu = navMenu.split( "," );
+            for ( String navmenu : arrayNavMenu )
+            {
+                assertLinkPresent( navmenu );
+            }
+        }
+        else if ( "Continuum Manage Build Templates".equals( role ) )
+        {
+            String navMenu = "About,Show Project Groups,Build Definition Templates";
+            String[] arrayNavMenu = navMenu.split( "," );
+            for ( String navmenu : arrayNavMenu )
+            {
+                assertLinkPresent( navmenu );
+            }
+        }
+        else if ( "Continuum Manage Installations".equals( role ) )
+        {
+            String navMenu = "About,Show Project Groups,Installations";
+            String[] arrayNavMenu = navMenu.split( "," );
+            for ( String navmenu : arrayNavMenu )
+            {
+                assertLinkPresent( navmenu );
+            }
+        }
+        else if ( "Continuum Manage Local Repositories".equals( role ) )
+        {
+            String navMenu = "About,Show Project Groups,Local Repositories";
+            String[] arrayNavMenu = navMenu.split( "," );
+            for ( String navmenu : arrayNavMenu )
+            {
+                assertLinkPresent( navmenu );
+            }
+        }
+        else if ( "Continuum Manage Purging".equals( role ) )
+        {
+            String navMenu = "About,Show Project Groups,Purge Configurations";
+            String[] arrayNavMenu = navMenu.split( "," );
+            for ( String navmenu : arrayNavMenu )
+            {
+                assertLinkPresent( navmenu );
+            }
+        }
+        else if ( "Continuum Manage Queues".equals( role ) )
+        {
+            String navMenu = "About,Show Project Groups,Queues";
+            String[] arrayNavMenu = navMenu.split( "," );
+            for ( String navmenu : arrayNavMenu )
+            {
+                assertLinkPresent( navmenu );
+            }
+        }
+        else if ( "Continuum Manage Scheduling".equals( role ) )
+        {
+            String navMenu = "About,Show Project Groups,Schedules";
+            String[] arrayNavMenu = navMenu.split( "," );
+            for ( String navmenu : arrayNavMenu )
+            {
+                assertLinkPresent( navmenu );
+            }
+        }
+        else if ( "Project Administrator - Default Project Group".equals( role ) )
+        {
+            String navMenu = "About,Show Project Groups,Queues,Users,Roles";
+            String[] arrayNavMenu = navMenu.split( "," );
+            for ( String navmenu : arrayNavMenu )
+            {
+                assertLinkPresent( navmenu );
+            }
+        }
+        else if ( "Project Developer - Default Project Group".equals( role ) ||
+            "Project User - Default Project Group".equals( role ) )
+        {
+            String navMenu = "About,Show Project Groups,Queues";
+            String[] arrayNavMenu = navMenu.split( "," );
+            for ( String navmenu : arrayNavMenu )
+            {
+                assertLinkPresent( navmenu );
+            }
+        }
+        else
+        {
+            String navMenu = "About,Show Project Groups";
+            String[] arrayNavMenu = navMenu.split( "," );
+            for ( String navmenu : arrayNavMenu )
+            {
+                assertLinkPresent( navmenu );
+            }
+            assertTextPresent( "Project Groups" );
+            //assertTextPresent( "Project Groups list is empty." );
+        }
+
+    }
+
+    void assertDeleteUserPage( String username )
+    {
+        assertPage( "[Admin] User Delete" );
+        assertTextPresent( "[Admin] User Delete" );
+        assertTextPresent( "The following user will be deleted:" );
+        assertTextPresent( "Username: " + username );
+        assertButtonWithValuePresent( "Delete User" );
+    }
+
+    protected void assertProjectAdministratorAccess()
+    {
+        assertLinkPresent( "About" );
+        assertLinkPresent( "Show Project Groups" );
+        assertLinkPresent( "Maven Project" );
+        assertLinkPresent( "Maven 1.x Project" );
+        assertLinkPresent( "Ant Project" );
+        assertLinkPresent( "Shell Project" );
+        assertLinkPresent( "Schedules" );
+        assertLinkPresent( "Queues" );
+        assertLinkPresent( "Users" );
+        assertLinkPresent( "Roles" );
+        assertLinkNotPresent( "Local Repositories" );
+        assertLinkNotPresent( "Purge Configurations" );
+        assertLinkNotPresent( "Installations" );
+        assertLinkNotPresent( "Build Environments" );
+        assertLinkNotPresent( "Build Definition Templates" );
+        assertLinkNotPresent( "Configuration" );
+        assertLinkNotPresent( "Appearance" );
+        assertLinkNotPresent( "Build Queue" );
+        assertLinkNotPresent( "Build Agent" );
+    }
+
+    /////////////////////////////////////////
+    // User Roles Management
+    /////////////////////////////////////////
+    protected void changePassword( String oldPassword, String newPassword )
+    {
+        assertPage( "Change Password" );
+        setFieldValue( "existingPassword", oldPassword );
+        setFieldValue( "newPassword", newPassword );
+        setFieldValue( "newPasswordConfirm", newPassword );
+        clickButtonWithValue( "Change Password" );
+    }
+
+    protected void createUser( String userName, String fullName, String email, String password )
+    {
+        createUser( userName, fullName, email, password, password );
+    }
+
+    private void createUser( String userName, String fullName, String emailAd, String password, String confirmPassword )
+    {
+        loginAsAdmin();
+        clickLinkWithText( "Users" );
+        clickButtonWithValue( "Create New User" );
+        assertCreateUserPage();
+        setFieldValue( "user.username", userName );
+        setFieldValue( "user.fullName", fullName );
+        setFieldValue( "user.email", emailAd );
+        setFieldValue( "user.password", password );
+        setFieldValue( "user.confirmPassword", confirmPassword );
+        submit();
+
+        assertUserRolesPage();
+        clickButtonWithValue( "Submit" );
+    }
+
+    protected void deleteUser( String userName )
+    {
+        deleteUser( userName, true );
+    }
+
+    protected void deleteUser( String userName, boolean failIfMissing )
+    {
+        String xpath = "//tr[.//a[text()='" + userName + "']]/td/a[@title='delete user']";
+        if ( failIfMissing || isElementPresent( "xpath=" + xpath ) )
+        {
+            clickLinkWithXPath( xpath );
+            assertDeleteUserPage( userName );
+            submit();
+            assertElementNotPresent( userName );
+        }
+    }
+}
diff --git a/continuum-webapp-test/src/test/tomcat5x/conf/Catalina/localhost/continuum.xml b/continuum-webapp-test/src/test/tomcat5x/conf/Catalina/localhost/continuum.xml
deleted file mode 100644
index 0efc6d6..0000000
--- a/continuum-webapp-test/src/test/tomcat5x/conf/Catalina/localhost/continuum.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ 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.
-  -->
-
-<Context path="/continuum"
-         docBase="${catalina.base}/webapps/continuum">
-
-    <Resource name="jdbc/users" auth="Container" type="javax.sql.DataSource"
-              username="sa"
-              password=""
-              driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
-              url="jdbc:derby:target/database/users;create=true"
-    />
-    <Resource name="jdbc/continuum" auth="Container" type="javax.sql.DataSource"
-              username="sa"
-              password=""
-              driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
-              url="jdbc:derby:target/database/continuum;create=true"
-    />
-</Context>
diff --git a/continuum-webapp-test/src/test/tomcat5x/conf/Catalina/localhost/host-manager.xml b/continuum-webapp-test/src/test/tomcat5x/conf/Catalina/localhost/host-manager.xml
deleted file mode 100644
index de78890..0000000
--- a/continuum-webapp-test/src/test/tomcat5x/conf/Catalina/localhost/host-manager.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!--
-
-    Context configuration file for the Tomcat Host Manager Web App
-
-    $Id$
-
--->
-
-
-<Context docBase="${catalina.home}/server/webapps/host-manager"
-         privileged="true" antiResourceLocking="false" antiJARLocking="false">
-
-</Context>
diff --git a/continuum-webapp-test/src/test/tomcat5x/conf/Catalina/localhost/manager.xml b/continuum-webapp-test/src/test/tomcat5x/conf/Catalina/localhost/manager.xml
deleted file mode 100644
index 90c35a6..0000000
--- a/continuum-webapp-test/src/test/tomcat5x/conf/Catalina/localhost/manager.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!--
-
-    Context configuration file for the Tomcat Manager Web App
-
-    $Id$
-
--->
-
-
-<Context docBase="${catalina.home}/server/webapps/manager"
-         privileged="true" antiResourceLocking="false" antiJARLocking="false">
-
-  <!-- Link to the user database we will get roles from -->
-  <ResourceLink name="users" global="UserDatabase"
-                type="org.apache.catalina.UserDatabase"/>
-
-</Context>
diff --git a/continuum-webapp-test/src/test/tomcat5x/conf/catalina.policy b/continuum-webapp-test/src/test/tomcat5x/conf/catalina.policy
deleted file mode 100644
index 53a6c90..0000000
--- a/continuum-webapp-test/src/test/tomcat5x/conf/catalina.policy
+++ /dev/null
@@ -1,172 +0,0 @@
-// ============================================================================

-// catalina.corepolicy - Security Policy Permissions for Tomcat 5

-//

-// This file contains a default set of security policies to be enforced (by the

-// JVM) when Catalina is executed with the "-security" option.  In addition

-// to the permissions granted here, the following additional permissions are

-// granted to the codebase specific to each web application:

-//

-// * Read access to the document root directory

-//

-// $Id: catalina.policy 393732 2006-04-13 06:32:25Z pero $

-// ============================================================================

-

-

-// ========== SYSTEM CODE PERMISSIONS =========================================

-

-

-// These permissions apply to javac

-grant codeBase "file:${java.home}/lib/-" {

-        permission java.security.AllPermission;

-};

-

-// These permissions apply to all shared system extensions

-grant codeBase "file:${java.home}/jre/lib/ext/-" {

-        permission java.security.AllPermission;

-};

-

-// These permissions apply to javac when ${java.home] points at $JAVA_HOME/jre

-grant codeBase "file:${java.home}/../lib/-" {

-        permission java.security.AllPermission;

-};

-

-// These permissions apply to all shared system extensions when

-// ${java.home} points at $JAVA_HOME/jre

-grant codeBase "file:${java.home}/lib/ext/-" {

-        permission java.security.AllPermission;

-};

-

-

-// ========== CATALINA CODE PERMISSIONS =======================================

-

-

-// These permissions apply to the launcher code

-grant codeBase "file:${catalina.home}/bin/commons-launcher.jar" {

-        permission java.security.AllPermission;

-};

-

-// These permissions apply to the daemon code

-grant codeBase "file:${catalina.home}/bin/commons-daemon.jar" {

-        permission java.security.AllPermission;

-};

-

-// These permissions apply to the commons-logging API

-grant codeBase "file:${catalina.home}/bin/commons-logging-api.jar" {

-        permission java.security.AllPermission;

-};

-

-// These permissions apply to the server startup code

-grant codeBase "file:${catalina.home}/bin/bootstrap.jar" {

-        permission java.security.AllPermission;

-};

-

-// These permissions apply to the JMX server

-grant codeBase "file:${catalina.home}/bin/jmx.jar" {

-        permission java.security.AllPermission;

-};

-

-// These permissions apply to JULI

-grant codeBase "file:${catalina.home}/bin/tomcat-juli.jar" {

-        permission java.security.AllPermission;

-};

-

-// These permissions apply to the servlet API classes

-// and those that are shared across all class loaders

-// located in the "common" directory

-grant codeBase "file:${catalina.home}/common/-" {

-        permission java.security.AllPermission;

-};

-

-// These permissions apply to the container's core code, plus any additional

-// libraries installed in the "server" directory

-grant codeBase "file:${catalina.home}/server/-" {

-        permission java.security.AllPermission;

-};

-

-// The permissions granted to the balancer WEB-INF/classes and WEB-INF/lib directory

-grant codeBase "file:${catalina.home}/webapps/balancer/-" {

-        permission java.lang.RuntimePermission "accessClassInPackage.org.apache.tomcat.util.digester";

-        permission java.lang.RuntimePermission "accessClassInPackage.org.apache.tomcat.util.digester.*";

-};

-// ========== WEB APPLICATION PERMISSIONS =====================================

-

-

-// These permissions are granted by default to all web applications

-// In addition, a web application will be given a read FilePermission

-// and JndiPermission for all files and directories in its document root.

-grant { 

-    // Required for JNDI lookup of named JDBC DataSource's and

-    // javamail named MimePart DataSource used to send mail

-    permission java.util.PropertyPermission "java.home", "read";

-    permission java.util.PropertyPermission "java.naming.*", "read";

-    permission java.util.PropertyPermission "javax.sql.*", "read";

-

-    // OS Specific properties to allow read access

-    permission java.util.PropertyPermission "os.name", "read";

-    permission java.util.PropertyPermission "os.version", "read";

-    permission java.util.PropertyPermission "os.arch", "read";

-    permission java.util.PropertyPermission "file.separator", "read";

-    permission java.util.PropertyPermission "path.separator", "read";

-    permission java.util.PropertyPermission "line.separator", "read";

-

-    // JVM properties to allow read access

-    permission java.util.PropertyPermission "java.version", "read";

-    permission java.util.PropertyPermission "java.vendor", "read";

-    permission java.util.PropertyPermission "java.vendor.url", "read";

-    permission java.util.PropertyPermission "java.class.version", "read";

-	permission java.util.PropertyPermission "java.specification.version", "read";

-	permission java.util.PropertyPermission "java.specification.vendor", "read";

-	permission java.util.PropertyPermission "java.specification.name", "read";

-

-	permission java.util.PropertyPermission "java.vm.specification.version", "read";

-	permission java.util.PropertyPermission "java.vm.specification.vendor", "read";

-	permission java.util.PropertyPermission "java.vm.specification.name", "read";

-	permission java.util.PropertyPermission "java.vm.version", "read";

-	permission java.util.PropertyPermission "java.vm.vendor", "read";

-	permission java.util.PropertyPermission "java.vm.name", "read";

-

-    // Required for OpenJMX

-    permission java.lang.RuntimePermission "getAttribute";

-

-	// Allow read of JAXP compliant XML parser debug

-	permission java.util.PropertyPermission "jaxp.debug", "read";

-

-    // Precompiled JSPs need access to this package.

-    permission java.lang.RuntimePermission "accessClassInPackage.org.apache.jasper.runtime";

-    permission java.lang.RuntimePermission "accessClassInPackage.org.apache.jasper.runtime.*";

-    

-};

-

-

-// You can assign additional permissions to particular web applications by

-// adding additional "grant" entries here, based on the code base for that

-// application, /WEB-INF/classes/, or /WEB-INF/lib/ jar files.

-//

-// Different permissions can be granted to JSP pages, classes loaded from

-// the /WEB-INF/classes/ directory, all jar files in the /WEB-INF/lib/

-// directory, or even to individual jar files in the /WEB-INF/lib/ directory.

-//

-// For instance, assume that the standard "examples" application

-// included a JDBC driver that needed to establish a network connection to the

-// corresponding database and used the scrape taglib to get the weather from

-// the NOAA web server.  You might create a "grant" entries like this:

-//

-// The permissions granted to the context root directory apply to JSP pages.

-// grant codeBase "file:${catalina.home}/webapps/examples/-" {

-//      permission java.net.SocketPermission "dbhost.mycompany.com:5432", "connect";

-//      permission java.net.SocketPermission "*.noaa.gov:80", "connect";

-// };

-//

-// The permissions granted to the context WEB-INF/classes directory

-// grant codeBase "file:${catalina.home}/webapps/examples/WEB-INF/classes/-" {

-// };

-//

-// The permission granted to your JDBC driver

-// grant codeBase "jar:file:${catalina.home}/webapps/examples/WEB-INF/lib/driver.jar!/-" {

-//      permission java.net.SocketPermission "dbhost.mycompany.com:5432", "connect";

-// };

-// The permission granted to the scrape taglib

-// grant codeBase "jar:file:${catalina.home}/webapps/examples/WEB-INF/lib/scrape.jar!/-" {

-//      permission java.net.SocketPermission "*.noaa.gov:80", "connect";

-// };

-

diff --git a/continuum-webapp-test/src/test/tomcat5x/conf/catalina.properties b/continuum-webapp-test/src/test/tomcat5x/conf/catalina.properties
deleted file mode 100644
index 3e937ac..0000000
--- a/continuum-webapp-test/src/test/tomcat5x/conf/catalina.properties
+++ /dev/null
@@ -1,85 +0,0 @@
-#
-# 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.
-#
-
-#
-# List of comma-separated packages that start with or equal this string
-# will cause a security exception to be thrown when
-# passed to checkPackageAccess unless the
-# corresponding RuntimePermission ("accessClassInPackage."+package) has
-# been granted.
-package.access=sun.,org.apache.catalina.,org.apache.coyote.,org.apache.tomcat.,org.apache.jasper.,sun.beans.
-#
-# List of comma-separated packages that start with or equal this string
-# will cause a security exception to be thrown when
-# passed to checkPackageDefinition unless the
-# corresponding RuntimePermission ("defineClassInPackage."+package) has
-# been granted.
-#
-# by default, no packages are restricted for definition, and none of
-# the class loaders supplied with the JDK call checkPackageDefinition.
-#
-package.definition=sun.,java.,org.apache.catalina.,org.apache.coyote.,org.apache.tomcat.,org.apache.jasper.
-
-#
-#
-# List of comma-separated paths defining the contents of the "common" 
-# classloader. Prefixes should be used to define what is the repository type.
-# Path may be relative to the CATALINA_HOME or CATALINA_BASE path or absolute.
-# If left as blank,the JVM system loader will be used as Catalina's "common" 
-# loader.
-# Examples:
-#     "foo": Add this folder as a class repository
-#     "foo/*.jar": Add all the JARs of the specified folder as class 
-#                  repositories
-#     "foo/bar.jar": Add bar.jar as a class repository
-common.loader=${catalina.home}/common/classes,${catalina.home}/common/i18n/*.jar,${catalina.home}/common/endorsed/*.jar,${catalina.home}/common/lib/*.jar
-
-#
-# List of comma-separated paths defining the contents of the "server" 
-# classloader. Prefixes should be used to define what is the repository type.
-# Path may be relative to the CATALINA_HOME or CATALINA_BASE path or absolute.
-# If left as blank, the "common" loader will be used as Catalina's "server" 
-# loader.
-# Examples:
-#     "foo": Add this folder as a class repository
-#     "foo/*.jar": Add all the JARs of the specified folder as class 
-#                  repositories
-#     "foo/bar.jar": Add bar.jar as a class repository
-server.loader=${catalina.home}/server/classes,${catalina.home}/server/lib/*.jar
-
-#
-# List of comma-separated paths defining the contents of the "shared" 
-# classloader. Prefixes should be used to define what is the repository type.
-# Path may be relative to the CATALINA_BASE path or absolute. If left as blank,
-# the "common" loader will be used as Catalina's "shared" loader.
-# Examples:
-#     "foo": Add this folder as a class repository
-#     "foo/*.jar": Add all the JARs of the specified folder as class 
-#                  repositories
-#     "foo/bar.jar": Add bar.jar as a class repository 
-# Please note that for individual jar files, e.g. bar.jar, you need the URL form
-# starting with file:.
-shared.loader=${catalina.base}/shared/classes,${catalina.base}/shared/lib/*.jar
-
-#
-# String cache configuration.
-tomcat.util.buf.StringCache.byte.enabled=true
-#tomcat.util.buf.StringCache.char.enabled=true
-#tomcat.util.buf.StringCache.trainThreshold=500000
-#tomcat.util.buf.StringCache.cacheSize=5000
diff --git a/continuum-webapp-test/src/test/tomcat5x/conf/context.xml b/continuum-webapp-test/src/test/tomcat5x/conf/context.xml
deleted file mode 100644
index c702caa..0000000
--- a/continuum-webapp-test/src/test/tomcat5x/conf/context.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!-- The contents of this file will be loaded for each web application -->
-<Context>
-
-    <!-- Default set of monitored resources -->
-    <WatchedResource>WEB-INF/web.xml</WatchedResource>
-	
-    <!-- Uncomment this to disable session persistence across Tomcat restarts -->
-    <!--
-    <Manager pathname="" />
-    -->
-
-</Context>
\ No newline at end of file
diff --git a/continuum-webapp-test/src/test/tomcat5x/conf/logging.properties b/continuum-webapp-test/src/test/tomcat5x/conf/logging.properties
deleted file mode 100644
index 07f85e2..0000000
--- a/continuum-webapp-test/src/test/tomcat5x/conf/logging.properties
+++ /dev/null
@@ -1,74 +0,0 @@
-#
-# 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.
-#
-
-handlers = 1catalina.org.apache.juli.FileHandler, 2localhost.org.apache.juli.FileHandler, 3manager.org.apache.juli.FileHandler, 4admin.org.apache.juli.FileHandler, 5host-manager.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
-
-.handlers = 1catalina.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
-
-############################################################
-# Handler specific properties.
-# Describes specific configuration info for Handlers.
-############################################################
-
-1catalina.org.apache.juli.FileHandler.level = FINE
-1catalina.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
-1catalina.org.apache.juli.FileHandler.prefix = catalina.
-
-2localhost.org.apache.juli.FileHandler.level = FINE
-2localhost.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
-2localhost.org.apache.juli.FileHandler.prefix = localhost.
-
-3manager.org.apache.juli.FileHandler.level = FINE
-3manager.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
-3manager.org.apache.juli.FileHandler.prefix = manager.
-
-4admin.org.apache.juli.FileHandler.level = FINE
-4admin.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
-4admin.org.apache.juli.FileHandler.prefix = admin.
-
-5host-manager.org.apache.juli.FileHandler.level = FINE
-5host-manager.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
-5host-manager.org.apache.juli.FileHandler.prefix = host-manager.
-
-java.util.logging.ConsoleHandler.level = FINE
-java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
-
-
-############################################################
-# Facility specific properties.
-# Provides extra control for each logger.
-############################################################
-
-org.apache.catalina.core.ContainerBase.[Catalina].[localhost].level = INFO
-org.apache.catalina.core.ContainerBase.[Catalina].[localhost].handlers = 2localhost.org.apache.juli.FileHandler
-
-org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager].level = INFO
-org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager].handlers = 3manager.org.apache.juli.FileHandler
-
-org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/admin].level = INFO
-org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/admin].handlers = 4admin.org.apache.juli.FileHandler
-
-org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager].level = INFO
-org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager].handlers = 5host-manager.org.apache.juli.FileHandler
-
-# For example, set the com.xyz.foo logger to only log SEVERE
-# messages:
-#org.apache.catalina.startup.ContextConfig.level = FINE
-#org.apache.catalina.startup.HostConfig.level = FINE
-#org.apache.catalina.session.ManagerBase.level = FINE
diff --git a/continuum-webapp-test/src/test/tomcat5x/conf/server-minimal.xml b/continuum-webapp-test/src/test/tomcat5x/conf/server-minimal.xml
deleted file mode 100644
index 97366c4..0000000
--- a/continuum-webapp-test/src/test/tomcat5x/conf/server-minimal.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<Server port="8005" shutdown="SHUTDOWN">
-
-  <GlobalNamingResources>
-    <!-- Used by Manager webapp -->
-    <Resource name="UserDatabase" auth="Container"
-              type="org.apache.catalina.UserDatabase"
-       description="User database that can be updated and saved"
-           factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
-          pathname="conf/tomcat-users.xml" />
-  </GlobalNamingResources>
-
-  <Service name="Catalina">
-    <Connector port="8080" />
-
-    <!-- This is here for compatibility only, not required -->
-    <Connector port="8009" protocol="AJP/1.3" />
-
-    <Engine name="Catalina" defaultHost="localhost">
-      <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
-             resourceName="UserDatabase" />
-      <Host name="localhost" appBase="webapps" />
-    </Engine>
-    
-  </Service>
-</Server>
diff --git a/continuum-webapp-test/src/test/tomcat5x/conf/server.xml b/continuum-webapp-test/src/test/tomcat5x/conf/server.xml
deleted file mode 100644
index a0a5483..0000000
--- a/continuum-webapp-test/src/test/tomcat5x/conf/server.xml
+++ /dev/null
@@ -1,385 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!-- Example Server Configuration File -->
-<!-- Note that component elements are nested corresponding to their
-     parent-child relationships with each other -->
-
-<!-- A "Server" is a singleton element that represents the entire JVM,
-     which may contain one or more "Service" instances.  The Server
-     listens for a shutdown command on the indicated port.
-
-     Note:  A "Server" is not itself a "Container", so you may not
-     define subcomponents such as "Valves" or "Loggers" at this level.
- -->
-
-<Server port="8005" shutdown="SHUTDOWN">
-
-  <!-- Comment these entries out to disable JMX MBeans support used for the 
-       administration web application -->
-  <Listener className="org.apache.catalina.core.AprLifecycleListener" />
-  <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" />
-  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
-  <Listener className="org.apache.catalina.storeconfig.StoreConfigLifecycleListener"/>
-
-  <!-- Global JNDI resources -->
-  <GlobalNamingResources>
-
-    <!-- Test entry for demonstration purposes -->
-    <Environment name="simpleValue" type="java.lang.Integer" value="30"/>
-
-    <!-- Editable user database that can also be used by
-         UserDatabaseRealm to authenticate users -->
-    <Resource name="UserDatabase" auth="Container"
-              type="org.apache.catalina.UserDatabase"
-       description="User database that can be updated and saved"
-           factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
-          pathname="conf/tomcat-users.xml" />
-
-  </GlobalNamingResources>
-
-  <!-- A "Service" is a collection of one or more "Connectors" that share
-       a single "Container" (and therefore the web applications visible
-       within that Container).  Normally, that Container is an "Engine",
-       but this is not required.
-
-       Note:  A "Service" is not itself a "Container", so you may not
-       define subcomponents such as "Valves" or "Loggers" at this level.
-   -->
-
-  <!-- Define the Tomcat Stand-Alone Service -->
-  <Service name="Catalina">
-
-    <!-- A "Connector" represents an endpoint by which requests are received
-         and responses are returned.  Each Connector passes requests on to the
-         associated "Container" (normally an Engine) for processing.
-
-         By default, a non-SSL HTTP/1.1 Connector is established on port 8080.
-         You can also enable an SSL HTTP/1.1 Connector on port 8443 by
-         following the instructions below and uncommenting the second Connector
-         entry.  SSL support requires the following steps (see the SSL Config
-         HOWTO in the Tomcat 5 documentation bundle for more detailed
-         instructions):
-         * If your JDK version 1.3 or prior, download and install JSSE 1.0.2 or
-           later, and put the JAR files into "$JAVA_HOME/jre/lib/ext".
-         * Execute:
-             %JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA (Windows)
-             $JAVA_HOME/bin/keytool -genkey -alias tomcat -keyalg RSA  (Unix)
-           with a password value of "changeit" for both the certificate and
-           the keystore itself.
-
-         By default, DNS lookups are enabled when a web application calls
-         request.getRemoteHost().  This can have an adverse impact on
-         performance, so you can disable it by setting the
-         "enableLookups" attribute to "false".  When DNS lookups are disabled,
-         request.getRemoteHost() will return the String version of the
-         IP address of the remote client.
-    -->
-
-    <!-- Define a non-SSL HTTP/1.1 Connector on port 8080 -->
-    <Connector port="9595" maxHttpHeaderSize="8192"
-               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
-               enableLookups="false" redirectPort="8443" acceptCount="100"
-               connectionTimeout="20000" disableUploadTimeout="true" />
-    <!-- Note : To disable connection timeouts, set connectionTimeout value
-     to 0 -->
-	
-	<!-- Note : To use gzip compression you could set the following properties :
-	
-			   compression="on" 
-			   compressionMinSize="2048" 
-			   noCompressionUserAgents="gozilla, traviata" 
-			   compressableMimeType="text/html,text/xml"
-	-->
-
-    <!-- Define a SSL HTTP/1.1 Connector on port 8443 -->
-    <!--
-    <Connector port="8443" maxHttpHeaderSize="8192"
-               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
-               enableLookups="false" disableUploadTimeout="true"
-               acceptCount="100" scheme="https" secure="true"
-               clientAuth="false" sslProtocol="TLS" />
-    -->
-
-    <!-- Define an AJP 1.3 Connector on port 8009 -->
-    <Connector port="8009" 
-               enableLookups="false" redirectPort="8443" protocol="AJP/1.3" />
-
-    <!-- Define a Proxied HTTP/1.1 Connector on port 8082 -->
-    <!-- See proxy documentation for more information about using this. -->
-    <!--
-    <Connector port="8082" 
-               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
-               enableLookups="false" acceptCount="100" connectionTimeout="20000"
-               proxyPort="80" disableUploadTimeout="true" />
-    -->
-
-    <!-- An Engine represents the entry point (within Catalina) that processes
-         every request.  The Engine implementation for Tomcat stand alone
-         analyzes the HTTP headers included with the request, and passes them
-         on to the appropriate Host (virtual host). -->
-
-    <!-- You should set jvmRoute to support load-balancing via AJP ie :
-    <Engine name="Standalone" defaultHost="localhost" jvmRoute="jvm1">         
-    --> 
-         
-    <!-- Define the top level container in our container hierarchy -->
-    <Engine name="Catalina" defaultHost="localhost">
-
-      <!-- The request dumper valve dumps useful debugging information about
-           the request headers and cookies that were received, and the response
-           headers and cookies that were sent, for all requests received by
-           this instance of Tomcat.  If you care only about requests to a
-           particular virtual host, or a particular application, nest this
-           element inside the corresponding <Host> or <Context> entry instead.
-
-           For a similar mechanism that is portable to all Servlet 2.4
-           containers, check out the "RequestDumperFilter" Filter in the
-           example application (the source for this filter may be found in
-           "$CATALINA_HOME/webapps/examples/WEB-INF/classes/filters").
-
-           Request dumping is disabled by default.  Uncomment the following
-           element to enable it. -->
-      <!--
-      <Valve className="org.apache.catalina.valves.RequestDumperValve"/>
-      -->
-
-      <!-- Because this Realm is here, an instance will be shared globally -->
-
-      <!-- This Realm uses the UserDatabase configured in the global JNDI
-           resources under the key "UserDatabase".  Any edits
-           that are performed against this UserDatabase are immediately
-           available for use by the Realm.  -->
-      <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
-             resourceName="UserDatabase"/>
-
-      <!-- Comment out the old realm but leave here for now in case we
-           need to go back quickly -->
-      <!--
-      <Realm className="org.apache.catalina.realm.MemoryRealm" />
-      -->
-
-      <!-- Replace the above Realm with one of the following to get a Realm
-           stored in a database and accessed via JDBC -->
-
-      <!--
-      <Realm  className="org.apache.catalina.realm.JDBCRealm"
-             driverName="org.gjt.mm.mysql.Driver"
-          connectionURL="jdbc:mysql://localhost/authority"
-         connectionName="test" connectionPassword="test"
-              userTable="users" userNameCol="user_name" userCredCol="user_pass"
-          userRoleTable="user_roles" roleNameCol="role_name" />
-      -->
-
-      <!--
-      <Realm  className="org.apache.catalina.realm.JDBCRealm"
-             driverName="oracle.jdbc.driver.OracleDriver"
-          connectionURL="jdbc:oracle:thin:@ntserver:1521:ORCL"
-         connectionName="scott" connectionPassword="tiger"
-              userTable="users" userNameCol="user_name" userCredCol="user_pass"
-          userRoleTable="user_roles" roleNameCol="role_name" />
-      -->
-
-      <!--
-      <Realm  className="org.apache.catalina.realm.JDBCRealm"
-             driverName="sun.jdbc.odbc.JdbcOdbcDriver"
-          connectionURL="jdbc:odbc:CATALINA"
-              userTable="users" userNameCol="user_name" userCredCol="user_pass"
-          userRoleTable="user_roles" roleNameCol="role_name" />
-      -->
-
-      <!-- Define the default virtual host
-           Note: XML Schema validation will not work with Xerces 2.2.
-       -->
-      <Host name="localhost" appBase="webapps"
-       unpackWARs="true" autoDeploy="true"
-       xmlValidation="false" xmlNamespaceAware="false">
-
-        <!-- Defines a cluster for this node,
-             By defining this element, means that every manager will be changed.
-             So when running a cluster, only make sure that you have webapps in there
-             that need to be clustered and remove the other ones.
-             A cluster has the following parameters:
-
-             className = the fully qualified name of the cluster class
-
-             clusterName = a descriptive name for your cluster, can be anything
-
-             mcastAddr = the multicast address, has to be the same for all the nodes
-
-             mcastPort = the multicast port, has to be the same for all the nodes
-             
-             mcastBindAddress = bind the multicast socket to a specific address
-             
-             mcastTTL = the multicast TTL if you want to limit your broadcast
-             
-             mcastSoTimeout = the multicast readtimeout 
-
-             mcastFrequency = the number of milliseconds in between sending a "I'm alive" heartbeat
-
-             mcastDropTime = the number a milliseconds before a node is considered "dead" if no heartbeat is received
-
-             tcpThreadCount = the number of threads to handle incoming replication requests, optimal would be the same amount of threads as nodes 
-
-             tcpListenAddress = the listen address (bind address) for TCP cluster request on this host, 
-                                in case of multiple ethernet cards.
-                                auto means that address becomes
-                                InetAddress.getLocalHost().getHostAddress()
-
-             tcpListenPort = the tcp listen port
-
-             tcpSelectorTimeout = the timeout (ms) for the Selector.select() method in case the OS
-                                  has a wakup bug in java.nio. Set to 0 for no timeout
-
-             printToScreen = true means that managers will also print to std.out
-
-             expireSessionsOnShutdown = true means that 
-
-             useDirtyFlag = true means that we only replicate a session after setAttribute,removeAttribute has been called.
-                            false means to replicate the session after each request.
-                            false means that replication would work for the following piece of code: (only for SimpleTcpReplicationManager)
-                            <%
-                            HashMap map = (HashMap)session.getAttribute("map");
-                            map.put("key","value");
-                            %>
-             replicationMode = can be either 'pooled', 'synchronous' or 'asynchronous'.
-                               * Pooled means that the replication happens using several sockets in a synchronous way. Ie, the data gets replicated, then the request return. This is the same as the 'synchronous' setting except it uses a pool of sockets, hence it is multithreaded. This is the fastest and safest configuration. To use this, also increase the nr of tcp threads that you have dealing with replication.
-                               * Synchronous means that the thread that executes the request, is also the
-                               thread the replicates the data to the other nodes, and will not return until all
-                               nodes have received the information.
-                               * Asynchronous means that there is a specific 'sender' thread for each cluster node,
-                               so the request thread will queue the replication request into a "smart" queue,
-                               and then return to the client.
-                               The "smart" queue is a queue where when a session is added to the queue, and the same session
-                               already exists in the queue from a previous request, that session will be replaced
-                               in the queue instead of replicating two requests. This almost never happens, unless there is a 
-                               large network delay.
-        -->             
-        <!--
-            When configuring for clustering, you also add in a valve to catch all the requests
-            coming in, at the end of the request, the session may or may not be replicated.
-            A session is replicated if and only if all the conditions are met:
-            1. useDirtyFlag is true or setAttribute or removeAttribute has been called AND
-            2. a session exists (has been created)
-            3. the request is not trapped by the "filter" attribute
-
-            The filter attribute is to filter out requests that could not modify the session,
-            hence we don't replicate the session after the end of this request.
-            The filter is negative, ie, anything you put in the filter, you mean to filter out,
-            ie, no replication will be done on requests that match one of the filters.
-            The filter attribute is delimited by ;, so you can't escape out ; even if you wanted to.
-
-            filter=".*\.gif;.*\.js;" means that we will not replicate the session after requests with the URI
-            ending with .gif and .js are intercepted.
-            
-            The deployer element can be used to deploy apps cluster wide.
-            Currently the deployment only deploys/undeploys to working members in the cluster
-            so no WARs are copied upons startup of a broken node.
-            The deployer watches a directory (watchDir) for WAR files when watchEnabled="true"
-            When a new war file is added the war gets deployed to the local instance,
-            and then deployed to the other instances in the cluster.
-            When a war file is deleted from the watchDir the war is undeployed locally 
-            and cluster wide
-        -->
-        
-        <!--
-        <Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster"
-                 managerClassName="org.apache.catalina.cluster.session.DeltaManager"
-                 expireSessionsOnShutdown="false"
-                 useDirtyFlag="true"
-                 notifyListenersOnReplication="true">
-
-            <Membership 
-                className="org.apache.catalina.cluster.mcast.McastService"
-                mcastAddr="228.0.0.4"
-                mcastPort="45564"
-                mcastFrequency="500"
-                mcastDropTime="3000"/>
-
-            <Receiver 
-                className="org.apache.catalina.cluster.tcp.ReplicationListener"
-                tcpListenAddress="auto"
-                tcpListenPort="4001"
-                tcpSelectorTimeout="100"
-                tcpThreadCount="6"/>
-
-            <Sender
-                className="org.apache.catalina.cluster.tcp.ReplicationTransmitter"
-                replicationMode="pooled"
-                ackTimeout="15000"
-                waitForAck="true"/>
-
-            <Valve className="org.apache.catalina.cluster.tcp.ReplicationValve"
-                   filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/>
-                   
-            <Deployer className="org.apache.catalina.cluster.deploy.FarmWarDeployer"
-                      tempDir="/tmp/war-temp/"
-                      deployDir="/tmp/war-deploy/"
-                      watchDir="/tmp/war-listen/"
-                      watchEnabled="false"/>
-                      
-            <ClusterListener className="org.apache.catalina.cluster.session.ClusterSessionListener"/>
-        </Cluster>
-        -->        
-
-
-
-        <!-- Normally, users must authenticate themselves to each web app
-             individually.  Uncomment the following entry if you would like
-             a user to be authenticated the first time they encounter a
-             resource protected by a security constraint, and then have that
-             user identity maintained across *all* web applications contained
-             in this virtual host. -->
-        <!--
-        <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
-        -->
-
-        <!-- Access log processes all requests for this virtual host.  By
-             default, log files are created in the "logs" directory relative to
-             $CATALINA_HOME.  If you wish, you can specify a different
-             directory with the "directory" attribute.  Specify either a relative
-             (to $CATALINA_HOME) or absolute path to the desired directory.
-        -->
-        <!--
-        <Valve className="org.apache.catalina.valves.AccessLogValve"
-                 directory="logs"  prefix="localhost_access_log." suffix=".txt"
-                 pattern="common" resolveHosts="false"/>
-        -->
-
-        <!-- Access log processes all requests for this virtual host.  By
-             default, log files are created in the "logs" directory relative to
-             $CATALINA_HOME.  If you wish, you can specify a different
-             directory with the "directory" attribute.  Specify either a relative
-             (to $CATALINA_HOME) or absolute path to the desired directory.
-             This access log implementation is optimized for maximum performance,
-             but is hardcoded to support only the "common" and "combined" patterns.
-        -->
-        <!--
-        <Valve className="org.apache.catalina.valves.FastCommonAccessLogValve"
-                 directory="logs"  prefix="localhost_access_log." suffix=".txt"
-                 pattern="common" resolveHosts="false"/>
-        -->
-
-      </Host>
-
-    </Engine>
-
-  </Service>
-
-</Server>
diff --git a/continuum-webapp-test/src/test/tomcat5x/conf/tomcat-users.xml b/continuum-webapp-test/src/test/tomcat5x/conf/tomcat-users.xml
deleted file mode 100644
index 3694037..0000000
--- a/continuum-webapp-test/src/test/tomcat5x/conf/tomcat-users.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!--
-  NOTE:  By default, no user is included in the "manager" role required
-  to operate the "/manager" web application.  If you wish to use this app,
-  you must define such a user - the username and password are arbitrary.
--->
-<tomcat-users>
-  <user name="tomcat" password="tomcat" roles="tomcat" />
-  <user name="role1"  password="tomcat" roles="role1"  />
-  <user name="both"   password="tomcat" roles="tomcat,role1" />
-</tomcat-users>
diff --git a/continuum-webapp-test/src/test/tomcat5x/conf/web.xml b/continuum-webapp-test/src/test/tomcat5x/conf/web.xml
deleted file mode 100644
index 9e408a8..0000000
--- a/continuum-webapp-test/src/test/tomcat5x/conf/web.xml
+++ /dev/null
@@ -1,1183 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!--
-  ~ 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.
-  -->
-
-<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
-    version="2.4">
-
-  <!-- ======================== Introduction ============================== -->
-  <!-- This document defines default values for *all* web applications      -->
-  <!-- loaded into this instance of Tomcat.  As each application is         -->
-  <!-- deployed, this file is processed, followed by the                    -->
-  <!-- "/WEB-INF/web.xml" deployment descriptor from your own               -->
-  <!-- applications.                                                        -->
-  <!--                                                                      -->
-  <!-- WARNING:  Do not configure application-specific resources here!      -->
-  <!-- They should go in the "/WEB-INF/web.xml" file in your application.   -->
-
-
-  <!-- ================== Built In Servlet Definitions ==================== -->
-
-
-  <!-- The default servlet for all web applications, that serves static     -->
-  <!-- resources.  It processes all requests that are not mapped to other   -->
-  <!-- servlets with servlet mappings (defined either here or in your own   -->
-  <!-- web.xml file.  This servlet supports the following initialization    -->
-  <!-- parameters (default values are in square brackets):                  -->
-  <!--                                                                      -->
-  <!--   debug               Debugging detail level for messages logged     -->
-  <!--                       by this servlet.  [0]                          -->
-  <!--                                                                      -->
-  <!--   fileEncoding        Encoding to be used to read static resources   -->
-  <!--                       [platform default]                             -->
-  <!--                                                                      -->
-  <!--   input               Input buffer size (in bytes) when reading      -->
-  <!--                       resources to be served.  [2048]                -->
-  <!--                                                                      -->
-  <!--   listings            Should directory listings be produced if there -->
-  <!--                       is no welcome file in this directory?  [false] -->
-  <!--                       WARNING: Listings for directories with many    -->
-  <!--                       entries can be slow and may consume            -->
-  <!--                       significant proportions of server resources.   -->
-  <!--                                                                      -->
-  <!--   output              Output buffer size (in bytes) when writing     -->
-  <!--                       resources to be served.  [2048]                -->
-  <!--                                                                      -->
-  <!--   readonly            Is this context "read only", so HTTP           -->
-  <!--                       commands like PUT and DELETE are               -->
-  <!--                       rejected?  [true]                              -->
-  <!--                                                                      -->
-  <!--   readmeFile          File name to display with the directory        -->
-  <!--                       contents. [null]                               -->
-  <!--                                                                      -->
-  <!--   sendfileSize        If the connector used supports sendfile, this  -->
-  <!--                       represents the minimal file size in KB for     -->
-  <!--                       which sendfile will be used. Use a negative    -->
-  <!--                       value to always disable sendfile.  [48]        -->
-  <!--                                                                      -->
-  <!--  For directory listing customization. Checks localXsltFile, then     -->
-  <!--  globalXsltFile, then defaults to original behavior.                 -->
-  <!--                                                                      -->
-  <!--   localXsltFile       Make directory listings an XML doc and         -->
-  <!--                       pass the result to this style sheet residing   -->
-  <!--                       in that directory. This overrides              -->
-  <!--                        globalXsltFile[null]                          -->
-  <!--                                                                      -->
-  <!--   globalXsltFile      Site wide configuration version of             -->
-  <!--                       localXsltFile This argument is expected        -->
-  <!--                       to be a physical file. [null]                  -->
-  <!--                                                                      -->
-  <!--                                                                      -->
-
-    <servlet>
-        <servlet-name>default</servlet-name>
-        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
-        <init-param>
-            <param-name>debug</param-name>
-            <param-value>0</param-value>
-        </init-param>
-        <init-param>
-            <param-name>listings</param-name>
-            <param-value>false</param-value>
-        </init-param>
-        <load-on-startup>1</load-on-startup>
-    </servlet>
-
-
-  <!-- The "invoker" servlet, which executes anonymous servlet classes      -->
-  <!-- that have not been defined in a web.xml file.  Traditionally, this   -->
-  <!-- servlet is mapped to the URL pattern "/servlet/*", but you can map   -->
-  <!-- it to other patterns as well.  The extra path info portion of such a -->
-  <!-- request must be the fully qualified class name of a Java class that  -->
-  <!-- implements Servlet (or extends HttpServlet), or the servlet name     -->
-  <!-- of an existing servlet definition.     This servlet supports the     -->
-  <!-- following initialization parameters (default values are in square    -->
-  <!-- brackets):                                                           -->
-  <!--                                                                      -->
-  <!--   debug               Debugging detail level for messages logged     -->
-  <!--                       by this servlet.  [0]                          -->
-
-<!--
-    <servlet>
-        <servlet-name>invoker</servlet-name>
-        <servlet-class>
-          org.apache.catalina.servlets.InvokerServlet
-        </servlet-class>
-        <init-param>
-            <param-name>debug</param-name>
-            <param-value>0</param-value>
-        </init-param>
-        <load-on-startup>2</load-on-startup>
-    </servlet>
--->
-
-
-  <!-- The JSP page compiler and execution servlet, which is the mechanism  -->
-  <!-- used by Tomcat to support JSP pages.  Traditionally, this servlet    -->
-  <!-- is mapped to the URL pattern "*.jsp".  This servlet supports the     -->
-  <!-- following initialization parameters (default values are in square    -->
-  <!-- brackets):                                                           -->
-  <!--                                                                      -->
-  <!--   checkInterval       If development is false and checkInterval is   -->
-  <!--                       greater than zero, background compilations are -->
-  <!--                       enabled. checkInterval is the time in seconds  -->
-  <!--                       between checks to see if a JSP page needs to   -->
-  <!--                       be recompiled. [0]                             -->
-  <!--                                                                      -->
-  <!--   modificationTestInterval                                           -->
-  <!--                       Causes a JSP (and its dependent files) to not  -->
-  <!--                       be checked for modification during the         -->
-  <!--                       specified time interval (in seconds) from the  -->
-  <!--                       last time the JSP was checked for              -->
-  <!--                       modification. A value of 0 will cause the JSP  -->
-  <!--                       to be checked on every access.                 -->
-  <!--                       Used in development mode only. [4]             -->
-  <!--                                                                      -->
-  <!--   compiler            Which compiler Ant should use to compile JSP   -->
-  <!--                       pages.  See the Ant documentation for more     -->
-  <!--                       information. [javac]                           -->
-  <!--                                                                      -->
-  <!--   classdebuginfo      Should the class file be compiled with         -->
-  <!--                       debugging information?  [true]                 -->
-  <!--                                                                      -->
-  <!--   classpath           What class path should I use while compiling   -->
-  <!--                       generated servlets?  [Created dynamically      -->
-  <!--                       based on the current web application]          -->
-  <!--                                                                      -->
-  <!--   development         Is Jasper used in development mode? If true,   -->
-  <!--                       the frequency at which JSPs are checked for    -->
-  <!--                       modification may be specified via the          -->
-  <!--                       modificationTestInterval parameter. [true]     -->
-  <!--                                                                      -->
-  <!--   enablePooling       Determines whether tag handler pooling is      -->
-  <!--                       enabled  [true]                                -->
-  <!--                                                                      -->
-  <!--   fork                Tell Ant to fork compiles of JSP pages so that -->
-  <!--                       a separate JVM is used for JSP page compiles   -->
-  <!--                       from the one Tomcat is running in. [true]      -->
-  <!--                                                                      -->
-  <!--   ieClassId           The class-id value to be sent to Internet      -->
-  <!--                       Explorer when using <jsp:plugin> tags.         -->
-  <!--                       [clsid:8AD9C840-044E-11D1-B3E9-00805F499D93]   -->
-  <!--                                                                      -->
-  <!--   javaEncoding        Java file encoding to use for generating java  -->
-  <!--                       source files. [UTF8]                           -->
-  <!--                                                                      -->
-  <!--   keepgenerated       Should we keep the generated Java source code  -->
-  <!--                       for each page instead of deleting it? [true]   -->
-  <!--                                                                      -->
-  <!--   mappedfile          Should we generate static content with one     -->
-  <!--                       print statement per input line, to ease        -->
-  <!--                       debugging?  [true]                             -->
-  <!--                                                                      -->
-  <!--   trimSpaces          Should white spaces in template text between   -->
-  <!--                       actions or directives be trimmed?  [false]     -->
-  <!--                                                                      -->
-  <!--   suppressSmap        Should the generation of SMAP info for JSR45   -->
-  <!--                       debugging be suppressed?  [false]              -->
-  <!--                                                                      -->
-  <!--   dumpSmap            Should the SMAP info for JSR45 debugging be    -->
-  <!--                       dumped to a file? [false]                      -->
-  <!--                       False if suppressSmap is true                  -->
-  <!--                                                                      -->
-  <!--   genStrAsCharArray   Should text strings be generated as char       -->
-  <!--                       arrays, to improve performance in some cases?  -->
-  <!--                       [false]                                        -->
-  <!--                                                                      -->
-  <!--   errorOnUseBeanInvalidClassAttribute                                -->
-  <!--                       Should Jasper issue an error when the value of -->
-  <!--                       the class attribute in an useBean action is    -->
-  <!--                       not a valid bean class?  [true]                -->
-  <!--                                                                      -->
-  <!--   scratchdir          What scratch directory should we use when      -->
-  <!--                       compiling JSP pages?  [default work directory  -->
-  <!--                       for the current web application]               -->
-  <!--                                                                      -->
-  <!--   xpoweredBy          Determines whether X-Powered-By response       -->
-  <!--                       header is added by generated servlet  [false]  -->
-  <!--                                                                      -->
-  <!--   compilerTargetVM    Compiler target VM                             -->  
-  <!--                       default is System.properties                   -->
-  <!--                        java.specification.version > 1.4              -->
-  <!--                        [1.5] else [1.4]                              -->
-  <!--                                                                      -->
-  <!--   compilerSourceVM    Compiler source VM                             -->
-  <!--                       default is System.properties                   -->
-  <!--                        java.specification.version > 1.4              -->
-  <!--                        [1.5] else [1.4]                              -->
-  <!--                                                                      -->
-  <!-- If you wish to use Jikes to compile JSP pages:                       -->
-  <!--   Please see the "Using Jikes" section of the Jasper-HowTo           -->
-  <!--   page in the Tomcat documentation.                                  -->
-
-    <servlet>
-        <servlet-name>jsp</servlet-name>
-        <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
-        <init-param>
-            <param-name>fork</param-name>
-            <param-value>false</param-value>
-        </init-param>
-        <init-param>
-            <param-name>xpoweredBy</param-name>
-            <param-value>false</param-value>
-        </init-param>
-        <load-on-startup>3</load-on-startup>
-    </servlet>
-
-
-  <!-- NOTE: An SSI Filter is also available as an alternative SSI          -->
-  <!-- implementation. Use either the Servlet or the Filter but NOT both.   -->
-  <!--                                                                      -->
-  <!-- Server Side Includes processing servlet, which processes SSI         -->
-  <!-- directives in HTML pages consistent with similar support in web      -->
-  <!-- servers like Apache.  Traditionally, this servlet is mapped to the   -->
-  <!-- URL pattern "*.shtml".  This servlet supports the following          -->
-  <!-- initialization parameters (default values are in square brackets):   -->
-  <!--                                                                      -->
-  <!--   buffered            Should output from this servlet be buffered?   -->
-  <!--                       (0=false, 1=true)  [0]                         -->
-  <!--                                                                      -->
-  <!--   debug               Debugging detail level for messages logged     -->
-  <!--                       by this servlet.  [0]                          -->
-  <!--                                                                      -->
-  <!--   expires             The number of seconds before a page with SSI   -->
-  <!--                       directives will expire.  [No default]          -->
-  <!--                                                                      -->
-  <!--   isVirtualWebappRelative                                            -->
-  <!--                       Should "virtual" paths be interpreted as       -->
-  <!--                       relative to the context root, instead of       -->
-  <!--                       the server root?  (0=false, 1=true) [0]        -->
-  <!--                                                                      -->
-  <!--   inputEncoding       The encoding to assume for SSI resources if    -->
-  <!--                       one is not available from the resource.        -->
-  <!--                       [Platform default]                             -->
-  <!--                                                                      -->
-  <!--   outputEncoding      The encoding to use for the page that results  -->
-  <!--                       from the SSI processing. [UTF-8]               -->
-  <!--                                                                      -->
-  <!--                                                                      -->
-  <!-- IMPORTANT: To use the SSI servlet, you also need to rename the       -->
-  <!--            $CATALINA_HOME/server/lib/servlets-ssi.renametojar file   -->
-  <!--            to $CATALINA_HOME/server/lib/servlets-ssi.jar             -->
-
-<!--
-    <servlet>
-        <servlet-name>ssi</servlet-name>
-        <servlet-class>
-          org.apache.catalina.ssi.SSIServlet
-        </servlet-class>
-        <init-param>
-          <param-name>buffered</param-name>
-          <param-value>1</param-value>
-        </init-param>
-        <init-param>
-          <param-name>debug</param-name>
-          <param-value>0</param-value>
-        </init-param>
-        <init-param>
-          <param-name>expires</param-name>
-          <param-value>666</param-value>
-        </init-param>
-        <init-param>
-          <param-name>isVirtualWebappRelative</param-name>
-          <param-value>0</param-value>
-        </init-param>
-        <load-on-startup>4</load-on-startup>
-    </servlet>
--->
-
-
-  <!-- Common Gateway Includes (CGI) processing servlet, which supports     -->
-  <!-- execution of external applications that conform to the CGI spec      -->
-  <!-- requirements.  Typically, this servlet is mapped to the URL pattern  -->
-  <!-- "/cgi-bin/*", which means that any CGI applications that are         -->
-  <!-- executed must be present within the web application.  This servlet   -->
-  <!-- supports the following initialization parameters (default values     -->
-  <!-- are in square brackets):                                             -->
-  <!--                                                                      -->
-  <!--   cgiPathPrefix        The CGI search path will start at             -->
-  <!--                        webAppRootDir + File.separator + this prefix. -->
-  <!--                        [WEB-INF/cgi]                                 -->
-  <!--                                                                      -->
-  <!--   debug                Debugging detail level for messages logged    -->
-  <!--                        by this servlet.  [0]                         -->
-  <!--                                                                      -->
-  <!--   executable           Name of the exectuable used to run the        -->
-  <!--                        script. [perl]                                -->
-  <!--                                                                      -->
-  <!--   parameterEncoding    Name of parameter encoding to be used with    -->
-  <!--                        CGI servlet.                                  -->
-  <!--                        [System.getProperty("file.encoding","UTF-8")] -->
-  <!--                                                                      -->
-  <!--   passShellEnvironment Should the shell environment variables (if    -->
-  <!--                        any) be passed to the CGI script? [false]     -->
-  <!--                                                                      -->
-  <!-- IMPORTANT: To use the CGI servlet, you also need to rename the       -->
-  <!--            $CATALINA_HOME/server/lib/servlets-cgi.renametojar file   -->
-  <!--            to $CATALINA_HOME/server/lib/servlets-cgi.jar             -->
-
-<!--
-    <servlet>
-        <servlet-name>cgi</servlet-name>
-        <servlet-class>org.apache.catalina.servlets.CGIServlet</servlet-class>
-        <init-param>
-          <param-name>debug</param-name>
-          <param-value>0</param-value>
-        </init-param>
-        <init-param>
-          <param-name>cgiPathPrefix</param-name>
-          <param-value>WEB-INF/cgi</param-value>
-        </init-param>
-         <load-on-startup>5</load-on-startup>
-    </servlet>
--->
-
-
-  <!-- ================ Built In Servlet Mappings ========================= -->
-
-
-  <!-- The servlet mappings for the built in servlets defined above.  Note  -->
-  <!-- that, by default, the CGI and SSI servlets are *not* mapped.  You    -->
-  <!-- must uncomment these mappings (or add them to your application's own -->
-  <!-- web.xml deployment descriptor) to enable these services              -->
-
-    <!-- The mapping for the default servlet -->
-    <servlet-mapping>
-        <servlet-name>default</servlet-name>
-        <url-pattern>/</url-pattern>
-    </servlet-mapping>
-
-    <!-- The mapping for the invoker servlet -->
-<!--
-    <servlet-mapping>
-        <servlet-name>invoker</servlet-name>
-        <url-pattern>/servlet/*</url-pattern>
-    </servlet-mapping>
--->
-
-    <!-- The mapping for the JSP servlet -->
-    <servlet-mapping>
-        <servlet-name>jsp</servlet-name>
-        <url-pattern>*.jsp</url-pattern>
-    </servlet-mapping>
-
-    <servlet-mapping>
-        <servlet-name>jsp</servlet-name>
-        <url-pattern>*.jspx</url-pattern>
-    </servlet-mapping>
-
-    <!-- The mapping for the SSI servlet -->
-<!--
-    <servlet-mapping>
-        <servlet-name>ssi</servlet-name>
-        <url-pattern>*.shtml</url-pattern>
-    </servlet-mapping>
--->
-
-    <!-- The mapping for the CGI Gateway servlet -->
-
-<!--
-    <servlet-mapping>
-        <servlet-name>cgi</servlet-name>
-        <url-pattern>/cgi-bin/*</url-pattern>
-    </servlet-mapping>
--->
-
-
-  <!-- ================== Built In Filter Definitions ===================== -->
-
-  <!-- NOTE: An SSI Servlet is also available as an alternative SSI         -->
-  <!-- implementation. Use either the Servlet or the Filter but NOT both.   -->
-  <!--                                                                      -->
-  <!-- Server Side Includes processing filter, which processes SSI          -->
-  <!-- directives in HTML pages consistent with similar support in web      -->
-  <!-- servers like Apache.  Traditionally, this filter is mapped to the    -->
-  <!-- URL pattern "*.shtml", though it can be mapped to "*" as it will     -->
-  <!-- selectively enable/disable SSI processing based on mime types. For   -->
-  <!-- this to work you will need to uncomment the .shtml mime type         -->
-  <!-- definition towards the bottom of this file.                          -->
-  <!-- The contentType init param allows you to apply SSI processing to JSP -->
-  <!-- pages, javascript, or any other content you wish.  This filter       -->
-  <!-- supports the following initialization parameters (default values are -->
-  <!-- in square brackets):                                                 -->
-  <!--                                                                      -->
-  <!--   contentType         A regex pattern that must be matched before    -->
-  <!--                       SSI processing is applied.                     -->
-  <!--                       [text/x-server-parsed-html(;.*)?]              -->
-  <!--                                                                      -->
-  <!--   debug               Debugging detail level for messages logged     -->
-  <!--                       by this servlet.  [0]                          -->
-  <!--                                                                      -->
-  <!--   expires             The number of seconds before a page with SSI   -->
-  <!--                       directives will expire.  [No default]          -->
-  <!--                                                                      -->
-  <!--   isVirtualWebappRelative                                            -->
-  <!--                       Should "virtual" paths be interpreted as       -->
-  <!--                       relative to the context root, instead of       -->
-  <!--                       the server root?  (0=false, 1=true) [0]        -->
-  <!--                                                                      -->
-  <!--                                                                      -->
-  <!-- IMPORTANT: To use the SSI filter, you also need to rename the        -->
-  <!--            $CATALINA_HOME/server/lib/servlets-ssi.renametojar file   -->
-  <!--            to $CATALINA_HOME/server/lib/servlets-ssi.jar             -->
-
-<!--
-    <filter>
-        <filter-name>ssi</filter-name>
-        <filter-class>
-          org.apache.catalina.ssi.SSIFilter
-        </filter-class>
-        <init-param>
-          <param-name>contentType</param-name>
-          <param-value>text/x-server-parsed-html(;.*)?</param-value>
-        </init-param>
-        <init-param>
-          <param-name>debug</param-name>
-          <param-value>0</param-value>
-        </init-param>
-        <init-param>
-          <param-name>expires</param-name>
-          <param-value>666</param-value>
-        </init-param>
-        <init-param>
-          <param-name>isVirtualWebappRelative</param-name>
-          <param-value>0</param-value>
-        </init-param>
-    </filter>
--->
-
-
-  <!-- ==================== Built In Filter Mappings ====================== -->
-
-  <!-- The mapping for the SSI Filter -->
-<!--
-    <filter-mapping>
-        <filter-name>ssi</filter-name>
-        <url-pattern>*.shtml</url-pattern>
-    </filter-mapping>
--->
-
-
-  <!-- ==================== Default Session Configuration ================= -->
-  <!-- You can set the default session timeout (in minutes) for all newly   -->
-  <!-- created sessions by modifying the value below.                       -->
-
-    <session-config>
-        <session-timeout>30</session-timeout>
-    </session-config>
-
-
-  <!-- ===================== Default MIME Type Mappings =================== -->
-  <!-- When serving static resources, Tomcat will automatically generate    -->
-  <!-- a "Content-Type" header based on the resource's filename extension,  -->
-  <!-- based on these mappings.  Additional mappings can be added here (to  -->
-  <!-- apply to all web applications), or in your own application's web.xml -->
-  <!-- deployment descriptor.                                               -->
-
-    <mime-mapping>
-        <extension>abs</extension>
-        <mime-type>audio/x-mpeg</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>ai</extension>
-        <mime-type>application/postscript</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>aif</extension>
-        <mime-type>audio/x-aiff</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>aifc</extension>
-        <mime-type>audio/x-aiff</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>aiff</extension>
-        <mime-type>audio/x-aiff</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>aim</extension>
-        <mime-type>application/x-aim</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>art</extension>
-        <mime-type>image/x-jg</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>asf</extension>
-        <mime-type>video/x-ms-asf</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>asx</extension>
-        <mime-type>video/x-ms-asf</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>au</extension>
-        <mime-type>audio/basic</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>avi</extension>
-        <mime-type>video/x-msvideo</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>avx</extension>
-        <mime-type>video/x-rad-screenplay</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>bcpio</extension>
-        <mime-type>application/x-bcpio</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>bin</extension>
-        <mime-type>application/octet-stream</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>bmp</extension>
-        <mime-type>image/bmp</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>body</extension>
-        <mime-type>text/html</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>cdf</extension>
-        <mime-type>application/x-netcdf</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>cer</extension>
-        <mime-type>application/x-x509-ca-cert</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>class</extension>
-        <mime-type>application/java</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>cpio</extension>
-        <mime-type>application/x-cpio</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>csh</extension>
-        <mime-type>application/x-csh</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>css</extension>
-        <mime-type>text/css</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>dib</extension>
-        <mime-type>image/bmp</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>doc</extension>
-        <mime-type>application/msword</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>dtd</extension>
-        <mime-type>application/xml-dtd</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>dv</extension>
-        <mime-type>video/x-dv</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>dvi</extension>
-        <mime-type>application/x-dvi</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>eps</extension>
-        <mime-type>application/postscript</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>etx</extension>
-        <mime-type>text/x-setext</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>exe</extension>
-        <mime-type>application/octet-stream</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>gif</extension>
-        <mime-type>image/gif</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>gtar</extension>
-        <mime-type>application/x-gtar</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>gz</extension>
-        <mime-type>application/x-gzip</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>hdf</extension>
-        <mime-type>application/x-hdf</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>htc</extension>
-        <mime-type>text/x-component</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>htm</extension>
-        <mime-type>text/html</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>html</extension>
-        <mime-type>text/html</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>hqx</extension>
-        <mime-type>application/mac-binhex40</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>ico</extension>
-        <mime-type>image/x-icon</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>ief</extension>
-        <mime-type>image/ief</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>jad</extension>
-        <mime-type>text/vnd.sun.j2me.app-descriptor</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>jar</extension>
-        <mime-type>application/java-archive</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>java</extension>
-        <mime-type>text/plain</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>jnlp</extension>
-        <mime-type>application/x-java-jnlp-file</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>jpe</extension>
-        <mime-type>image/jpeg</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>jpeg</extension>
-        <mime-type>image/jpeg</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>jpg</extension>
-        <mime-type>image/jpeg</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>js</extension>
-        <mime-type>text/javascript</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>jsf</extension>
-        <mime-type>text/plain</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>jspf</extension>
-        <mime-type>text/plain</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>kar</extension>
-        <mime-type>audio/midi</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>latex</extension>
-        <mime-type>application/x-latex</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>m3u</extension>
-        <mime-type>audio/x-mpegurl</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>mac</extension>
-        <mime-type>image/x-macpaint</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>man</extension>
-        <mime-type>application/x-troff-man</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>mathml</extension>
-        <mime-type>application/mathml+xml</mime-type> 
-    </mime-mapping>
-    <mime-mapping>
-        <extension>me</extension>
-        <mime-type>application/x-troff-me</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>mid</extension>
-        <mime-type>audio/midi</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>midi</extension>
-        <mime-type>audio/midi</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>mif</extension>
-        <mime-type>application/vnd.mif</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>mov</extension>
-        <mime-type>video/quicktime</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>movie</extension>
-        <mime-type>video/x-sgi-movie</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>mp1</extension>
-        <mime-type>audio/x-mpeg</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>mp2</extension>
-        <mime-type>audio/mpeg</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>mp3</extension>
-        <mime-type>audio/mpeg</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>mpa</extension>
-        <mime-type>audio/x-mpeg</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>mpe</extension>
-        <mime-type>video/mpeg</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>mpeg</extension>
-        <mime-type>video/mpeg</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>mpega</extension>
-        <mime-type>audio/x-mpeg</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>mpg</extension>
-        <mime-type>video/mpeg</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>mpv2</extension>
-        <mime-type>video/mpeg2</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>ms</extension>
-        <mime-type>application/x-troff-ms</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>nc</extension>
-        <mime-type>application/x-netcdf</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>oda</extension>
-        <mime-type>application/oda</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <!-- OpenDocument Database -->
-        <extension>odb</extension>
-        <mime-type>application/vnd.oasis.opendocument.database</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <!-- OpenDocument Chart -->
-        <extension>odc</extension>
-        <mime-type>application/vnd.oasis.opendocument.chart</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <!-- OpenDocument Formula -->
-        <extension>odf</extension>
-        <mime-type>application/vnd.oasis.opendocument.formula</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <!-- OpenDocument Drawing -->
-        <extension>odg</extension>
-        <mime-type>application/vnd.oasis.opendocument.graphics</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <!-- OpenDocument Image -->
-        <extension>odi</extension>
-        <mime-type>application/vnd.oasis.opendocument.image</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <!-- OpenDocument Master Document -->
-        <extension>odm</extension>
-        <mime-type>application/vnd.oasis.opendocument.text-master</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <!-- OpenDocument Presentation -->
-        <extension>odp</extension>
-        <mime-type>application/vnd.oasis.opendocument.presentation</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <!-- OpenDocument Spreadsheet -->
-        <extension>ods</extension>
-        <mime-type>application/vnd.oasis.opendocument.spreadsheet</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <!-- OpenDocument Text -->
-        <extension>odt</extension>
-        <mime-type>application/vnd.oasis.opendocument.text</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>ogg</extension>
-        <mime-type>application/ogg</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <!-- OpenDocument Drawing Template -->
-        <extension>otg </extension>
-        <mime-type>application/vnd.oasis.opendocument.graphics-template</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <!-- HTML Document Template -->
-        <extension>oth</extension>
-        <mime-type>application/vnd.oasis.opendocument.text-web</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <!-- OpenDocument Presentation Template -->
-        <extension>otp</extension>
-        <mime-type>application/vnd.oasis.opendocument.presentation-template</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <!-- OpenDocument Spreadsheet Template -->
-        <extension>ots</extension>
-        <mime-type>application/vnd.oasis.opendocument.spreadsheet-template </mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <!-- OpenDocument Text Template -->
-        <extension>ott</extension>
-        <mime-type>application/vnd.oasis.opendocument.text-template</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>pbm</extension>
-        <mime-type>image/x-portable-bitmap</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>pct</extension>
-        <mime-type>image/pict</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>pdf</extension>
-        <mime-type>application/pdf</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>pgm</extension>
-        <mime-type>image/x-portable-graymap</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>pic</extension>
-        <mime-type>image/pict</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>pict</extension>
-        <mime-type>image/pict</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>pls</extension>
-        <mime-type>audio/x-scpls</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>png</extension>
-        <mime-type>image/png</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>pnm</extension>
-        <mime-type>image/x-portable-anymap</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>pnt</extension>
-        <mime-type>image/x-macpaint</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>ppm</extension>
-        <mime-type>image/x-portable-pixmap</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>pps</extension>
-        <mime-type>application/vnd.ms-powerpoint</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>ppt</extension>
-        <mime-type>application/vnd.ms-powerpoint</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>ps</extension>
-        <mime-type>application/postscript</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>psd</extension>
-        <mime-type>image/x-photoshop</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>qt</extension>
-        <mime-type>video/quicktime</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>qti</extension>
-        <mime-type>image/x-quicktime</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>qtif</extension>
-        <mime-type>image/x-quicktime</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>ras</extension>
-        <mime-type>image/x-cmu-raster</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>rdf</extension>
-        <mime-type>application/rdf+xml</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>rgb</extension>
-        <mime-type>image/x-rgb</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>rm</extension>
-        <mime-type>application/vnd.rn-realmedia</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>roff</extension>
-        <mime-type>application/x-troff</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>rtf</extension>
-        <mime-type>text/rtf</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>rtx</extension>
-        <mime-type>text/richtext</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>sh</extension>
-        <mime-type>application/x-sh</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>shar</extension>
-        <mime-type>application/x-shar</mime-type>
-    </mime-mapping>
-<!--
-    <mime-mapping>
-        <extension>shtml</extension>
-        <mime-type>text/x-server-parsed-html</mime-type>
-    </mime-mapping>
--->
-    <mime-mapping>
-        <extension>smf</extension>
-        <mime-type>audio/x-midi</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>sit</extension>
-        <mime-type>application/x-stuffit</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>snd</extension>
-        <mime-type>audio/basic</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>src</extension>
-        <mime-type>application/x-wais-source</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>sv4cpio</extension>
-        <mime-type>application/x-sv4cpio</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>sv4crc</extension>
-        <mime-type>application/x-sv4crc</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>svg</extension>
-        <mime-type>image/svg+xml</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>svgz</extension>
-        <mime-type>image/svg</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>swf</extension>
-        <mime-type>application/x-shockwave-flash</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>t</extension>
-        <mime-type>application/x-troff</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>tar</extension>
-        <mime-type>application/x-tar</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>tcl</extension>
-        <mime-type>application/x-tcl</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>tex</extension>
-        <mime-type>application/x-tex</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>texi</extension>
-        <mime-type>application/x-texinfo</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>texinfo</extension>
-        <mime-type>application/x-texinfo</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>tif</extension>
-        <mime-type>image/tiff</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>tiff</extension>
-        <mime-type>image/tiff</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>tr</extension>
-        <mime-type>application/x-troff</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>tsv</extension>
-        <mime-type>text/tab-separated-values</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>txt</extension>
-        <mime-type>text/plain</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>ulw</extension>
-        <mime-type>audio/basic</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>ustar</extension>
-        <mime-type>application/x-ustar</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>vrml</extension>
-        <mime-type>model/vrml</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>vsd</extension>
-        <mime-type>application/x-visio</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>vxml</extension>
-        <mime-type>application/voicexml+xml</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>wav</extension>
-        <mime-type>audio/x-wav</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <!-- Wireless Bitmap -->
-        <extension>wbmp</extension>
-        <mime-type>image/vnd.wap.wbmp</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <!-- WML Source -->
-        <extension>wml</extension>
-        <mime-type>text/vnd.wap.wml</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <!-- Compiled WML -->
-        <extension>wmlc</extension>
-        <mime-type>application/vnd.wap.wmlc</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <!-- WML Script Source -->
-        <extension>wmls</extension>
-        <mime-type>text/vnd.wap.wmlscript</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <!-- Compiled WML Script -->
-        <extension>wmlscriptc</extension>
-        <mime-type>application/vnd.wap.wmlscriptc</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>wrl</extension>
-        <mime-type>model/vrml</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>xbm</extension>
-        <mime-type>image/x-xbitmap</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>xht</extension>
-        <mime-type>application/xhtml+xml</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>xhtml</extension>
-        <mime-type>application/xhtml+xml</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>xls</extension>
-        <mime-type>application/vnd.ms-excel</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>xml</extension>
-        <mime-type>application/xml</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>xpm</extension>
-        <mime-type>image/x-xpixmap</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>xsl</extension>
-        <mime-type>application/xml</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>xslt</extension>
-        <mime-type>application/xslt+xml</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>xul</extension>
-        <mime-type>application/vnd.mozilla.xul+xml</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>xwd</extension>
-        <mime-type>image/x-xwindowdump</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>Z</extension>
-        <mime-type>application/x-compress</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>z</extension>
-        <mime-type>application/x-compress</mime-type>
-    </mime-mapping>
-    <mime-mapping>
-        <extension>zip</extension>
-        <mime-type>application/zip</mime-type>
-    </mime-mapping>
-
-  <!-- ==================== Default Welcome File List ===================== -->
-  <!-- When a request URI refers to a directory, the default servlet looks  -->
-  <!-- for a "welcome file" within that directory and, if present,          -->
-  <!-- to the corresponding resource URI for display.  If no welcome file   -->
-  <!-- is present, the default servlet either serves a directory listing,   -->
-  <!-- or returns a 404 status, depending on how it is configured.          -->
-  <!--                                                                      -->
-  <!-- If you define welcome files in your own application's web.xml        -->
-  <!-- deployment descriptor, that list *replaces* the list configured      -->
-  <!-- here, so be sure that you include any of the default values that     -->
-  <!-- you wish to include.                                                 -->
-
-    <welcome-file-list>
-        <welcome-file>index.html</welcome-file>
-        <welcome-file>index.htm</welcome-file>
-        <welcome-file>index.jsp</welcome-file>
-    </welcome-file-list>
-
-</web-app>
diff --git a/continuum-webapp/pom.xml b/continuum-webapp/pom.xml
index 0f73646..1ab41f6 100644
--- a/continuum-webapp/pom.xml
+++ b/continuum-webapp/pom.xml
@@ -1,33 +1,34 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
+  ~ 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.
+  -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <artifactId>continuum</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>continuum-webapp</artifactId>
   <name>Continuum :: Web APP</name>
   <packaging>war</packaging>
-  <build> 
+  <build>
     <resources>
       <resource>
         <filtering>true</filtering>
@@ -49,61 +50,14 @@
         </excludes>
       </resource>
     </resources>
-    <pluginManagement>
-      <plugins>
-        <plugin>
-          <artifactId>maven-gpg-plugin</artifactId>
-          <version>1.0-alpha-3</version>
-        </plugin>
-      </plugins>
-    </pluginManagement>
     <plugins>
       <plugin>
-        <artifactId>maven-gpg-plugin</artifactId>
-        <version>1.0-alpha-3</version>
-      </plugin>
-      <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-clean-plugin</artifactId>
-        <version>2.1.1</version>
-        <!-- This configuration is added to cleanup from war:inplace -->
         <configuration>
           <filesets>
             <fileset>
-              <directory>${basedir}/src/main/webapp</directory>
-              <includes>
-                <!-- TODO: META-INF shouldn't be required, seems to be an issue with the current war plugin -->
-                <include>META-INF</include>
-                <include>images/redback</include>
-                <!-- Images from other wars -->
-                <include>template/</include>
-                <!-- validation.js -->
-                <include>template/redback</include>
-                <!-- Templates from other wars -->
-                <include>WEB-INF/classes</include>
-                <!-- Classes and Resources from other wars -->
-                <include>WEB-INF/lib</include>
-                <!-- Dependencies from other wars -->
-                <include>WEB-INF/database</include>
-                <!-- Database location configured in application.xml -->
-                <include>WEB-INF/logs</include>
-                <!-- Log file location specified in application.xml -->
-                <include>redback</include>
-                <!-- plexus-redback css and javascript -->
-                <include>css/redback</include>
-                <include>WEB-INF/jsp/redback</include>
-                <!-- plexus-redback jsps -->
-                <include>WEB-INF/template/redback</include>
-                <!-- plexus-security xwork templates -->
-                <include>WEB-INF/build-output-directory</include>
-                <!-- Directory created by jetty:run -->
-                <include>WEB-INF/working-directory</include>
-                <!-- Directory created by jetty:run -->
-                <include>WEB-INF/logs</include>
-                <!-- Directory created by jetty:run -->
-                <include>WEB-INF/temp</include>
-                <!-- Directory created by jetty:run -->
-              </includes>
+              <directory>${basedir}/data</directory>
             </fileset>
           </filesets>
         </configuration>
@@ -111,54 +65,13 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-war-plugin</artifactId>
-        <version>2.1-alpha-2</version>
         <configuration>
           <!-- Some versions of maven-war-plugin (snapshots) have this incorrectly defaulted to true.
                Specifically setting this to false to avoid accidental jar file creation. -->
           <archiveClasses>false</archiveClasses>
-          <dependentWarExcludes>META-INF/**,WEB-INF/web.xml,WEB-INF/classes/xwork.xml,WEB-INF/lib/**
-          </dependentWarExcludes>
+          <dependentWarExcludes>META-INF/**,WEB-INF/web.xml,WEB-INF/classes/xwork.xml,WEB-INF/lib/**</dependentWarExcludes>
         </configuration>
-        <!-- TODO: would be good to make the jetty plugin aware of these and remove the below -->
-        <executions>
-          <execution>
-            <phase>compile</phase>
-            <goals>
-              <!-- Needed to get the plexus-security war overlay to do its thing before jetty:run -->
-              <goal>inplace</goal>
-            </goals>
-          </execution>
-        </executions>
       </plugin>
-		
-      <!-- 
-        here an hack to prevent multiple struts core in classpath
-        which prevent struts start 
-        and same struts.xml in the classpath too
-      -->
-      <plugin>
-        <artifactId>maven-antrun-plugin</artifactId>
-        <executions>
-          <execution>
-            <id>cleanup-struts-jar-in-webapp</id>
-            <phase>compile</phase>
-            <goals>
-              <goal>run</goal>
-            </goals>
-            <configuration>
-              <tasks>
-                <delete includeemptydirs="true">
-                  <fileset dir="${basedir}/src/main/webapp/WEB-INF/lib" includes="**/struts2*.jar" />
-                </delete>
-                <delete includeemptydirs="true">
-                  <fileset dir="${basedir}/src/main/webapp/WEB-INF/classes" includes="**/struts.*" />
-                </delete>
-              </tasks>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>		
-
       <plugin>
         <groupId>org.codehaus.plexus</groupId>
         <artifactId>plexus-maven-plugin</artifactId>
@@ -171,7 +84,7 @@
             <roleDefault>
               <role>com.opensymphony.xwork2.validator.Validator</role>
               <instantiation-strategy>per-lookup</instantiation-strategy>
-            </roleDefault>            
+            </roleDefault>
           </roleDefaults>
         </configuration>
         <executions>
@@ -190,18 +103,10 @@
           <execution>
             <id>web summary model classes</id>
             <configuration>
-              <model>src/main/mdo/view-models.mdo</model>
-              <version>1.0.0</version>
-            </configuration>
-            <goals>
-              <goal>java</goal>
-            </goals>
-          </execution>
-          <execution>
-            <id>session model classes</id>
-            <configuration>
-              <model>src/main/mdo/session-models.mdo</model>
-              <version>1.0.0</version>
+              <models>
+                <model>src/main/mdo/view-models.mdo</model>
+              </models>
+              <version>1.4.1</version>
             </configuration>
             <goals>
               <goal>java</goal>
@@ -210,7 +115,9 @@
           <execution>
             <id>appearence model classes</id>
             <configuration>
-              <model>src/main/mdo/appearance-models.mdo</model>
+              <models>
+                <model>src/main/mdo/appearance-models.mdo</model>
+              </models>
               <version>1.0.0</version>
             </configuration>
             <goals>
@@ -218,13 +125,35 @@
               <goal>xpp3-reader</goal>
               <goal>xpp3-writer</goal>
             </goals>
-          </execution>          
+          </execution>
+        </executions>
+        <configuration>
+          <useJava5>true</useJava5>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>com.google.code.maven-replacer-plugin</groupId>
+        <artifactId>replacer</artifactId>
+        <executions>
+          <execution>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>replace</goal>
+            </goals>
+            <configuration>
+              <basedir>${basedir}</basedir>
+              <includes>
+                <include>target/generated-sources/**</include>
+              </includes>
+              <token>Generated by Modello.*</token>
+              <value>Generated by Modello</value>
+            </configuration>
+          </execution>
         </executions>
       </plugin>
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>jspc-maven-plugin</artifactId>
-        <version>1.4.6</version>
         <executions>
           <execution>
             <phase>package</phase>
@@ -234,27 +163,89 @@
           </execution>
         </executions>
         <configuration>
+          <source>1.5</source>
           <warSourceDirectory>${project.build.directory}/${project.build.finalName}/</warSourceDirectory>
           <injectString><![CDATA[<!-- [jspc-maven-plugin:post-compiled-jsps-as-servlets] -->]]></injectString>
-          <!-- 
+          <!--
             Uncomment outputWebXml if you want the generated web.xml to
             be placed in the working directory that the war:war mojo uses.
             -->
-          <!-- 
-          <outputWebXml>${project.build.directory}/${project.build.finalName}/WEB-INF/web.xml</outputWebXml> 
+          <!--
+          <outputWebXml>${project.build.directory}/${project.build.finalName}/WEB-INF/web.xml</outputWebXml>
           -->
         </configuration>
       </plugin>
+
+      <!-- hack for jetty:run, continuum web config files are checked in /WEB-INF/ dir -->
+      <plugin>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>copy-web-config-files</id>
+            <goals>
+              <goal>run</goal>
+            </goals>
+            <phase>compile</phase>
+            <configuration>
+              <tasks>
+                <mkdir dir="${basedir}/target/continuum/WEB-INF/" />
+                <copy todir="${basedir}/target/continuum/WEB-INF/">
+                  <fileset dir="${basedir}/target" includes="classes/" excludes="**/struts.xml" />
+                </copy>
+              </tasks>
+            </configuration>
+          </execution>
+          <execution>
+            <id>copy-appserver-base</id>
+            <phase>generate-resources</phase>
+            <goals>
+              <goal>run</goal>
+            </goals>
+            <configuration>
+              <tasks>
+                <copy todir="${project.build.directory}/appserver-base">
+                  <fileset dir="src/appserver-base" />
+                </copy>
+              </tasks>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <artifactId>maven-dependency-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>unpack-redback-war</id>
+            <goals>
+              <goal>unpack</goal>
+            </goals>
+            <phase>compile</phase>
+            <configuration>
+              <artifactItems>
+                <artifactItem>
+                  <groupId>org.codehaus.redback</groupId>
+                  <artifactId>redback-struts2-content</artifactId>
+                  <version>${redback.version}</version>
+                  <type>war</type>
+                  <overWrite>false</overWrite>
+                  <outputDirectory>${project.build.directory}/redback</outputDirectory>
+                  <excludes>**/struts-security.xml</excludes>
+                </artifactItem>
+              </artifactItems>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
       <plugin>
         <groupId>org.mortbay.jetty</groupId>
-        <artifactId>maven-jetty-plugin</artifactId>
-        <version>6.1.11</version>
+        <artifactId>jetty-maven-plugin</artifactId>
         <configuration>
-          <scanIntervalSeconds>10</scanIntervalSeconds>
-          <contextPath>/</contextPath>
-          <jettyEnvXml>${basedir}/src/jetty-env.xml</jettyEnvXml>
+          <webAppConfig>
+            <contextPath>/</contextPath>
+            <jettyEnvXml>${basedir}/src/jetty-env.xml</jettyEnvXml>
+          </webAppConfig>
           <connectors>
-            <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
+            <connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
               <port>9090</port>
               <maxIdleTime>60000</maxIdleTime>
             </connector>
@@ -267,12 +258,35 @@
             <systemProperty>
               <name>appserver.home</name>
               <value>${project.build.directory}/appserver-home</value>
-            </systemProperty>            
+            </systemProperty>
             <systemProperty>
               <name>derby.system.home</name>
               <value>${project.build.directory}/appserver-base/logs</value>
             </systemProperty>
           </systemProperties>
+          <stopKey>stopkey</stopKey>
+          <stopPort>9099</stopPort>
+        </configuration>
+        <dependencies>
+          <dependency>
+            <groupId>org.apache.derby</groupId>
+            <artifactId>derby</artifactId>
+            <version>10.1.3.1</version>
+          </dependency>
+        </dependencies>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>tomcat-maven-plugin</artifactId>
+        <configuration>
+          <path>/continuum</path>
+          <port>9090</port>
+          <contextFile>${basedir}/src/test/tomcat/tomcat-context-continuum.xml</contextFile>
+          <systemProperties>
+            <appserver.base>${project.build.directory}/appserver-base</appserver.base>
+            <appserver.home>${project.build.directory}/appserver-home</appserver.home>
+            <derby.system.home>${project.build.directory}/appserver-base/logs</derby.system.home>
+          </systemProperties>
         </configuration>
         <dependencies>
           <dependency>
@@ -280,6 +294,11 @@
             <artifactId>derby</artifactId>
             <version>10.1.3.1</version>
           </dependency>
+          <dependency>
+            <groupId>javax.mail</groupId>
+            <artifactId>mail</artifactId>
+            <version>1.4</version>
+          </dependency>
         </dependencies>
       </plugin>
       <plugin>
@@ -294,31 +313,51 @@
           </excludes>
         </configuration>
       </plugin>
-      <plugin>
-        <artifactId>maven-antrun-plugin</artifactId>
-        <executions>
-          <execution>
-            <phase>generate-resources</phase>
-            <goals>
-              <goal>run</goal>
-            </goals>
-            <configuration>
-              <tasks>
-                <copy todir="${project.build.directory}/appserver-base">
-                  <fileset dir="src/appserver-base" />
-                </copy>
-                <copy todir="src/main/webapp/template">
-                  <fileset file="src/main/resources/template/default/validation.js" />
-                </copy>
-              </tasks>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
     </plugins>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.rat</groupId>
+          <artifactId>apache-rat-plugin</artifactId>
+          <configuration>
+            <excludes combine.children="append">
+              <exclude>src/main/webapp/js/jquery-*</exclude>
+              <exclude>src/main/webapp/js/prototype.js</exclude>
+              <exclude>src/main/webapp/css/no-theme/jquery-*</exclude>
+            </excludes>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
   </build>
   <dependencies>
     <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-security</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-model</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-api</artifactId>
+      <exclusions>
+        <exclusion>
+          <groupId>xalan</groupId>
+          <artifactId>xalan</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-taskqueue</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-quartz</artifactId>
+    </dependency>
+    <dependency>
       <groupId>org.codehaus.plexus.registry</groupId>
       <artifactId>plexus-registry-api</artifactId>
     </dependency>
@@ -328,6 +367,22 @@
       <scope>runtime</scope>
     </dependency>
     <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-project</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-settings</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-artifact</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-model</artifactId>
+    </dependency>
+    <dependency>
       <groupId>org.apache.maven.shared</groupId>
       <artifactId>maven-app-configuration-model</artifactId>
     </dependency>
@@ -337,38 +392,40 @@
     </dependency>
     <dependency>
       <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-builder</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
       <artifactId>continuum-core</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-security</artifactId>
+      <artifactId>continuum-release</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-component-api</artifactId>
     </dependency>
     <dependency> <!-- added since depMgt doesn't override imported dependencies -->
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-utils</artifactId>
     </dependency>
     <dependency>
-      <groupId>javax.servlet</groupId>
-      <artifactId>servlet-api</artifactId>
-      <version>2.4</version>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>javax.servlet</groupId>
-      <artifactId>jsp-api</artifactId>
-      <version>2.0</version>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
       <groupId>opensymphony</groupId>
       <artifactId>sitemesh</artifactId>
-      <version>2.2.1</version>
+      <version>2.4.2</version>
       <scope>runtime</scope>
     </dependency>
     <dependency>
       <groupId>org.extremecomponents</groupId>
       <artifactId>extremecomponents</artifactId>
       <version>1.0.1</version>
+      <exclusions>
+        <exclusion>
+          <groupId>commons-logging</groupId>
+          <artifactId>commons-logging</artifactId>
+        </exclusion>
+      </exclusions>
     </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
@@ -378,13 +435,22 @@
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
-    </dependency>    
+    </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-log4j12</artifactId>
       <scope>runtime</scope>
     </dependency>
     <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>jcl-over-slf4j</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.atlassian.xmlrpc</groupId>
+      <artifactId>atlassian-xmlrpc-binder-server-spring</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
       <groupId>org.apache.derby</groupId>
       <artifactId>derby</artifactId>
       <scope>provided</scope>
@@ -400,34 +466,39 @@
       <scope>runtime</scope>
     </dependency>
     <dependency>
-      <groupId>taglibs</groupId>
-      <artifactId>standard</artifactId>
-      <version>1.1.2</version>
-      <scope>runtime</scope>
+      <groupId>javax.activation</groupId>
+      <artifactId>activation</artifactId>
     </dependency>
     <dependency>
       <groupId>javax.servlet</groupId>
       <artifactId>jstl</artifactId>
       <version>1.1.2</version>
+    </dependency>
+    <dependency>
+      <groupId>taglibs</groupId>
+      <artifactId>standard</artifactId>
+      <version>1.1.2</version>
       <scope>runtime</scope>
     </dependency>
     <dependency>
       <groupId>org.apache.maven.scm</groupId>
       <artifactId>maven-scm-providers-standard</artifactId>
       <type>pom</type>
+      <scope>runtime</scope>
     </dependency>
     <dependency>
       <groupId>org.apache.maven.scm</groupId>
-      <artifactId>maven-scm-provider-cvs-commons</artifactId>
-    </dependency>    
-    <dependency>
-      <groupId>org.apache.maven.scm</groupId>
       <artifactId>maven-scm-provider-svn-commons</artifactId>
-    </dependency>    
+    </dependency>
     <dependency>
-      <groupId>org.apache.maven.scm</groupId>
-      <artifactId>maven-scm-provider-local</artifactId>
-      <scope>runtime</scope>
+      <groupId>org.apache.maven.release</groupId>
+      <artifactId>maven-release-manager</artifactId>
+      <exclusions>
+        <exclusion>
+          <groupId>org.codehaus.plexus</groupId>
+          <artifactId>plexus-container-default</artifactId>
+        </exclusion>
+      </exclusions>
     </dependency>
     <dependency>
       <groupId>org.apache.continuum</groupId>
@@ -453,18 +524,26 @@
       <groupId>org.apache.continuum</groupId>
       <artifactId>continuum-xmlrpc-server</artifactId>
       <scope>runtime</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>org.codehaus.plexus</groupId>
+          <artifactId>plexus-container-default</artifactId>
+        </exclusion>
+      </exclusions>
     </dependency>
     <dependency>
       <groupId>org.apache.continuum</groupId>
       <artifactId>continuum-reports</artifactId>
+      <exclusions>
+        <exclusion>
+          <groupId>xml-apis</groupId>
+          <artifactId>xml-apis</artifactId>
+        </exclusion>
+      </exclusions>
     </dependency>
     <dependency>
       <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-distributed-build-transport-master-server</artifactId>
-    </dependency>    
-    <dependency>
-      <groupId>org.apache.maven.wagon</groupId>
-      <artifactId>wagon-provider-api</artifactId>
+      <artifactId>continuum-distributed-master-server</artifactId>
       <scope>runtime</scope>
     </dependency>
     <dependency>
@@ -476,6 +555,12 @@
       <groupId>org.apache.maven.wagon</groupId>
       <artifactId>wagon-http-lightweight</artifactId>
       <scope>runtime</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>xml-apis</groupId>
+          <artifactId>xml-apis</artifactId>
+        </exclusion>
+      </exclusions>
     </dependency>
     <dependency>
       <groupId>org.apache.maven.wagon</groupId>
@@ -489,7 +574,7 @@
     </dependency>
     <dependency>
       <groupId>org.apache.maven.wagon</groupId>
-      <artifactId>wagon-webdav</artifactId>
+      <artifactId>wagon-webdav-jackrabbit</artifactId>
       <scope>runtime</scope>
     </dependency>
     <dependency>
@@ -497,12 +582,21 @@
       <artifactId>struts2-core</artifactId>
     </dependency>
     <dependency>
-      <groupId>com.opensymphony</groupId>
-      <artifactId>xwork</artifactId>
-    </dependency>    
-    <dependency>
       <groupId>org.apache.struts</groupId>
       <artifactId>struts2-spring-plugin</artifactId>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>jsp-api</artifactId>
+      <version>2.0</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+      <version>2.4</version>
+      <scope>provided</scope>
     </dependency>
     <!--
       Redback Dependencies
@@ -511,55 +605,88 @@
       <groupId>org.codehaus.redback</groupId>
       <artifactId>redback-struts2-content</artifactId>
       <type>war</type>
-      <scope>runtime</scope> 
+      <scope>runtime</scope>
     </dependency>
     <dependency>
       <groupId>org.codehaus.redback</groupId>
       <artifactId>redback-struts2-integration</artifactId>
+      <scope>runtime</scope>
     </dependency>
     <dependency>
       <groupId>org.codehaus.redback</groupId>
       <artifactId>redback-common-integrations</artifactId>
     </dependency>
     <dependency>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>redback-rbac-role-manager</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>redback-users-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>redback-authorization-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>redback-system</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>redback-rbac-model</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>redback-xmlrpc-services</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>redback-xmlrpc-security</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
       <groupId>net.sf.ehcache</groupId>
       <artifactId>ehcache</artifactId>
       <scope>runtime</scope>
-    </dependency>    
-    <dependency>
-      <groupId>geronimo-spec</groupId>
-      <artifactId>geronimo-spec-jta</artifactId>
-      <version>1.0.1B-rc2</version>
-      <scope>provided</scope>
-    </dependency>   
-    <dependency>
-      <groupId>jpox</groupId>
-      <artifactId>jpox</artifactId>
-      <scope>runtime</scope>
       <exclusions>
-        <!-- targeting JDK 1.4 we don't need this -->
         <exclusion>
-          <groupId>javax.sql</groupId>
-          <artifactId>jdbc-stdext</artifactId>
+          <groupId>commons-logging</groupId>
+          <artifactId>commons-logging</artifactId>
         </exclusion>
       </exclusions>
     </dependency>
     <dependency>
+      <groupId>commons-collections</groupId>
+      <artifactId>commons-collections</artifactId>
+    </dependency>
+    <dependency>
       <groupId>commons-lang</groupId>
       <artifactId>commons-lang</artifactId>
     </dependency>
     <dependency>
-      <groupId>org.codehaus.plexus</groupId>
+      <groupId>org.codehaus.redback</groupId>
       <artifactId>plexus-spring</artifactId>
-    </dependency>    
+      <exclusions>
+        <exclusion>
+          <groupId>xml-apis</groupId>
+          <artifactId>xml-apis</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
     <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-web</artifactId>
     </dependency>
     <dependency>
       <groupId>org.springframework</groupId>
-      <artifactId>spring-context-support</artifactId>
-    </dependency>    
+      <artifactId>spring-context</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-tx</artifactId>
+    </dependency>
     <dependency>
       <groupId>jmock</groupId>
       <artifactId>jmock</artifactId>
@@ -568,14 +695,25 @@
     <dependency>
       <groupId>javax.mail</groupId>
       <artifactId>mail</artifactId>
-      <version>1.4</version>
       <scope>provided</scope>
     </dependency>
     <dependency>
-      <groupId>javax.activation</groupId>
-      <artifactId>activation</artifactId>
-      <version>1.1</version>
-      <scope>provided</scope>
+      <groupId>org.jsoup</groupId>
+      <artifactId>jsoup</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>jpox</groupId>
+      <artifactId>jpox-ehcache</artifactId>
+      <exclusions>
+        <exclusion>
+          <groupId>commons-logging</groupId>
+          <artifactId>commons-logging</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>ehcache</groupId>
+          <artifactId>ehcache</artifactId>
+        </exclusion>
+      </exclusions>
     </dependency>
   </dependencies>
   <profiles>
@@ -598,7 +736,7 @@
             </configuration>
           </plugin>
         </plugins>
-      </build>      
+      </build>
     </profile>
     <profile>
       <id>mysql</id>
@@ -638,7 +776,7 @@
                 <configuration>
                   <tasks>
                     <copy overwrite="true" file="${basedir}/src/test/resources/log4j.xml" todir="${basedir}/src/main/webapp/WEB-INF/classes" />
-					<copy overwrite="true" file="${basedir}/src/test/resources/log4j.xml" todir="${project.build.directory}/classes" />
+                    <copy overwrite="true" file="${basedir}/src/test/resources/log4j.xml" todir="${project.build.directory}/classes" />
                   </tasks>
                 </configuration>
               </execution>
@@ -665,7 +803,27 @@
             </configuration>
           </plugin>
         </plugins>
-      </build>      
-    </profile>  
+      </build>
+    </profile>
+    <profile>
+      <!-- local dev settings use a file which is ignore in svn -->
+      <id>local-tomcat-env</id>
+      <activation>
+        <file>
+          <exists>src/test/tomcat/tomcat-context-local.xml</exists>
+        </file>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>tomcat-maven-plugin</artifactId>
+            <configuration>
+              <contextFile>${basedir}/src/test/tomcat/tomcat-context-local.xml</contextFile>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
   </profiles>
 </project>
diff --git a/continuum-webapp/src/appserver-base/conf/shared.xml b/continuum-webapp/src/appserver-base/conf/shared.xml
index 9afb833..41e7cce 100644
--- a/continuum-webapp/src/appserver-base/conf/shared.xml
+++ b/continuum-webapp/src/appserver-base/conf/shared.xml
@@ -1 +1,20 @@
-<configuration />
+<!--
+  ~ 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.
+  -->
+
+<configuration/>
diff --git a/continuum-webapp/src/jetty-env-mysql.xml b/continuum-webapp/src/jetty-env-mysql.xml
index 88c7cef..24fbe65 100644
--- a/continuum-webapp/src/jetty-env-mysql.xml
+++ b/continuum-webapp/src/jetty-env-mysql.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0"?>
+
 <!--
   ~ Licensed to the Apache Software Foundation (ASF) under one
   ~ or more contributor license agreements.  See the NOTICE file
@@ -17,76 +18,58 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
   -->
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
 
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
+<Configure id='wac' class="org.eclipse.jetty.webapp.WebAppContext">
 
-<Configure class="org.mortbay.jetty.webapp.WebAppContext">
+  <New id="validation_mail" class="org.eclipse.jetty.plus.jndi.Resource">
+    <Arg>
+      <Ref id="wac"/>
+    </Arg>
+    <Arg>mail/Session</Arg>
+    <Arg>
+      <New class="org.eclipse.jetty.jndi.factories.MailSessionReference">
+        <Set name="user"></Set>
+        <Set name="password"></Set>
+        <Set name="properties">
+          <New class="java.util.Properties">
+            <Put name="mail.smtp.host">localhost</Put>
+          </New>
+        </Set>
+      </New>
+    </Arg>
+  </New>
 
+  <New id="continuum" class="org.eclipse.jetty.plus.jndi.Resource">
+    <Arg>
+      <Ref id="wac"/>
+    </Arg>
+    <Arg>jdbc/continuum</Arg>
+    <Arg>
+      <New class="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource">
+        <Set name="serverName">localhost</Set>
+        <Set name="databaseName">continuum</Set>
+        <Set name="user">root</Set>
+        <Set name="password"></Set>
+      </New>
+    </Arg>
+  </New>
 
+  <!-- Users / Security Database -->
 
-
-<New id="validation_mail" class="org.mortbay.jetty.plus.naming.Resource">
-  <Arg>mail/Session</Arg>
-  <Arg>
-    <New class="org.mortbay.naming.factories.MailSessionReference">
-      <Set name="user"></Set>
-      <Set name="password"></Set>
-      <Set name="properties">
-        <New class="java.util.Properties">
-          <Put name="mail.smtp.host">localhost</Put>
-          <Put name="mail.from">continuum@localhost</Put>
-          <Put name="mail.senderName">Continuum</Put>
-          <Put name="mail.debug">true</Put>
-        </New>
-      </Set>
-    </New>
-  </Arg>
-</New>
-
-<New id="continuum" class="org.mortbay.jetty.plus.naming.Resource">
-  <Arg>jdbc/continuum</Arg>
-  <Arg>
-    <New class="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource">
-      <Set name="serverName">localhost</Set>
-      <Set name="databaseName">continuum</Set>
-      <Set name="user">root</Set>
-      <Set name="password"></Set>
-    </New>
-  </Arg>
-</New>
-<New id="continuum_shutdown" class="org.mortbay.jetty.plus.naming.Resource">
-  <Arg>jdbc/continuum_shutdown</Arg>
-  <Arg>
-    <New class="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource">
-      <Set name="serverName">localhost</Set>
-      <Set name="databaseName">continuum</Set>
-      <Set name="user">root</Set>
-      <Set name="password"></Set>  
-    </New>
-  </Arg>
-</New>
-<New id="users" class="org.mortbay.jetty.plus.naming.Resource">
-  <Arg>jdbc/users</Arg>
-  <Arg>
-    <New class="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource">
-      <Set name="serverName">localhost</Set>
-      <Set name="databaseName">users</Set>
-      <Set name="user">root</Set>
-      <Set name="password"></Set>
-    </New>
-  </Arg>
-</New>
-<New id="users_shutdown" class="org.mortbay.jetty.plus.naming.Resource">
-  <Arg>jdbc/users_shutdown</Arg>
-  <Arg>
-    <New class="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource">
-      <Set name="serverName">localhost</Set>
-      <Set name="databaseName">users</Set>
-      <Set name="user">root</Set>
-      <Set name="password"></Set>  
-    </New>
-  </Arg>
-</New>
-
+  <New id="users" class="org.eclipse.jetty.plus.jndi.Resource">
+    <Arg>
+      <Ref id="wac"/>
+    </Arg>
+    <Arg>jdbc/users</Arg>
+    <Arg>
+      <New class="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource">
+        <Set name="serverName">localhost</Set>
+        <Set name="databaseName">users</Set>
+        <Set name="user">root</Set>
+        <Set name="password"></Set>
+      </New>
+    </Arg>
+  </New>
 </Configure>
 
diff --git a/continuum-webapp/src/jetty-env-postgres.xml b/continuum-webapp/src/jetty-env-postgres.xml
index 4ede1be..f05d6e4 100644
--- a/continuum-webapp/src/jetty-env-postgres.xml
+++ b/continuum-webapp/src/jetty-env-postgres.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0"?>
+
 <!--
   ~ Licensed to the Apache Software Foundation (ASF) under one
   ~ or more contributor license agreements.  See the NOTICE file
@@ -17,55 +18,55 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
   -->
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
 
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
+<Configure id='wac' class="org.eclipse.jetty.webapp.WebAppContext">
 
-<Configure class="org.mortbay.jetty.webapp.WebAppContext">
+  <New id="validation_mail" class="org.eclipse.jetty.plus.jndi.Resource">
+    <Arg>
+      <Ref id="wac"/>
+    </Arg>
+    <Arg>mail/Session</Arg>
+    <Arg>
+      <New class="org.eclipse.jetty.jndi.factories.MailSessionReference">
+        <Set name="user"></Set>
+        <Set name="password"></Set>
+        <Set name="properties">
+          <New class="java.util.Properties">
+            <Put name="mail.smtp.host">localhost</Put>
+          </New>
+        </Set>
+      </New>
+    </Arg>
+  </New>
 
+  <New id="continuumDataSource" class="org.postgresql.ds.PGPoolingDataSource">
+    <Set name="serverName">localhost</Set>
+    <Set name="databaseName">continuum</Set>
+    <Set name="user">postgres</Set>
+    <Set name="password">sparky</Set>
+  </New>
 
+  <New id="continuum" class="org.eclipse.jetty.plus.jndi.Resource">
+    <Arg>
+      <Ref id="wac"/>
+    </Arg>
+    <Arg>jdbc/continuum</Arg>
+    <Arg>
+      <Ref id="continuumDataSource"/>
+    </Arg>
+  </New>
 
+  <!-- Users / Security Database -->
 
-<New id="validation_mail" class="org.mortbay.jetty.plus.naming.Resource">
-  <Arg>mail/Session</Arg>
-  <Arg>
-    <New class="org.mortbay.naming.factories.MailSessionReference">
-      <Set name="user"></Set>
-      <Set name="password"></Set>
-      <Set name="properties">
-        <New class="java.util.Properties">
-          <Put name="mail.smtp.host">localhost</Put>
-          <Put name="mail.from">continuum@localhost</Put>
-          <Put name="mail.senderName">Continuum</Put>
-          <Put name="mail.debug">true</Put>
-        </New>
-      </Set>
-    </New>
-  </Arg>
-</New>
-
-<New id="continuumDataSource" class="org.postgresql.ds.PGPoolingDataSource">
-  <Set name="serverName">localhost</Set>
-  <Set name="databaseName">continuum</Set>
-  <Set name="user">postgres</Set>
-  <Set name="password">sparky</Set>
-</New>
-
-<New id="continuum" class="org.mortbay.jetty.plus.naming.Resource">
-  <Arg>jdbc/continuum</Arg>
-  <Arg><Ref id="continuumDataSource"/></Arg>
-</New>
-<New id="continuum_shutdown" class="org.mortbay.jetty.plus.naming.Resource">
-  <Arg>jdbc/continuum_shutdown</Arg>
-  <Arg><Ref id="continuumDataSource"/></Arg>
-</New>
-<New id="users" class="org.mortbay.jetty.plus.naming.Resource">
-  <Arg>jdbc/users</Arg>
-  <Arg><Ref id="continuumDataSource"/></Arg>
-</New>
-<New id="users_shutdown" class="org.mortbay.jetty.plus.naming.Resource">
-  <Arg>jdbc/users_shutdown</Arg>
-  <Arg><Ref id="continuumDataSource"/></Arg>
-</New>
-
+  <New id="users" class="org.eclipse.jetty.plus.jndi.Resource">
+    <Arg>
+      <Ref id="wac"/>
+    </Arg>
+    <Arg>jdbc/users</Arg>
+    <Arg>
+      <Ref id="continuumDataSource"/>
+    </Arg>
+  </New>
 </Configure>
 
diff --git a/continuum-webapp/src/jetty-env.xml b/continuum-webapp/src/jetty-env.xml
index 736dd5a..1f8f48e 100644
--- a/continuum-webapp/src/jetty-env.xml
+++ b/continuum-webapp/src/jetty-env.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0"?>
+
 <!--
   ~ Licensed to the Apache Software Foundation (ASF) under one
   ~ or more contributor license agreements.  See the NOTICE file
@@ -17,69 +18,56 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
   -->
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
 
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
+<Configure id='wac' class="org.eclipse.jetty.webapp.WebAppContext">
 
-<Configure class="org.mortbay.jetty.webapp.WebAppContext">
+  <New id="validation_mail" class="org.eclipse.jetty.plus.jndi.Resource">
+    <Arg>
+      <Ref id="wac"/>
+    </Arg>
+    <Arg>mail/Session</Arg>
+    <Arg>
+      <New class="org.eclipse.jetty.jndi.factories.MailSessionReference">
+        <Set name="user"></Set>
+        <Set name="password"></Set>
+        <Set name="properties">
+          <New class="java.util.Properties">
+            <Put name="mail.smtp.host">localhost</Put>
+          </New>
+        </Set>
+      </New>
+    </Arg>
+  </New>
 
-<New id="validation_mail" class="org.mortbay.jetty.plus.naming.Resource">
-  <Arg>mail/Session</Arg>
-  <Arg>
-    <New class="org.mortbay.naming.factories.MailSessionReference">
-      <Set name="user"></Set>
-      <Set name="password"></Set>
-      <Set name="properties">
-        <New class="java.util.Properties">
-          <Put name="mail.smtp.host">localhost</Put>
-          <Put name="mail.from">continuum@localhost</Put>
-          <Put name="mail.senderName">Continuum</Put>
-          <Put name="mail.debug">true</Put>
-        </New>
-      </Set>
-    </New>
-  </Arg>
-</New>
+  <New id="continuum" class="org.eclipse.jetty.plus.jndi.Resource">
+    <Arg>
+      <Ref id="wac"/>
+    </Arg>
+    <Arg>jdbc/continuum</Arg>
+    <Arg>
+      <New class="org.apache.derby.jdbc.EmbeddedDataSource">
+        <Set name="DatabaseName">../continuum_database</Set>
+        <Set name="user">sa</Set>
+        <Set name="createDatabase">create</Set>
+      </New>
+    </Arg>
+  </New>
 
-<New id="continuum" class="org.mortbay.jetty.plus.naming.Resource">
-  <Arg>jdbc/continuum</Arg>
-  <Arg>
-    <New class="org.apache.derby.jdbc.EmbeddedDataSource">
-      <Set name="DatabaseName">../continuum_database</Set>
-      <Set name="user">sa</Set>
-      <Set name="createDatabase">create</Set>
-    </New>
-  </Arg>
-</New>
-<New id="continuum_shutdown" class="org.mortbay.jetty.plus.naming.Resource">
-  <Arg>jdbc/continuum_shutdown</Arg>
-  <Arg>
-    <New class="org.apache.derby.jdbc.EmbeddedDataSource">
-      <Set name="DatabaseName">../continuum_database</Set>
-      <Set name="user">sa</Set>
-      <Set name="shutdownDatabase">shutdown</Set>
-    </New>
-  </Arg>
-</New>
-<New id="users" class="org.mortbay.jetty.plus.naming.Resource">
-  <Arg>jdbc/users</Arg>
-  <Arg>
-    <New class="org.apache.derby.jdbc.EmbeddedDataSource">
-      <Set name="DatabaseName">../users_database</Set>
-      <Set name="user">sa</Set>
-      <Set name="createDatabase">create</Set>
-    </New>
-  </Arg>
-</New>
-<New id="users_shutdown" class="org.mortbay.jetty.plus.naming.Resource">
-  <Arg>jdbc/users_shutdown</Arg>
-  <Arg>
-    <New class="org.apache.derby.jdbc.EmbeddedDataSource">
-      <Set name="DatabaseName">../users_database</Set>
-      <Set name="user">sa</Set>
-      <Set name="shutdownDatabase">shutdown</Set>
-    </New>
-  </Arg>
-</New>
+  <!-- Users / Security Database -->
 
+  <New id="users" class="org.eclipse.jetty.plus.jndi.Resource">
+    <Arg>
+      <Ref id="wac"/>
+    </Arg>
+    <Arg>jdbc/users</Arg>
+    <Arg>
+      <New class="org.apache.derby.jdbc.EmbeddedDataSource">
+        <Set name="DatabaseName">../users_database</Set>
+        <Set name="user">sa</Set>
+        <Set name="createDatabase">create</Set>
+      </New>
+    </Arg>
+  </New>
 </Configure>
 
diff --git a/continuum-webapp/src/main/java/org/apache/continuum/web/action/AbstractReleaseAction.java b/continuum-webapp/src/main/java/org/apache/continuum/web/action/AbstractReleaseAction.java
new file mode 100644
index 0000000..8205db0
--- /dev/null
+++ b/continuum-webapp/src/main/java/org/apache/continuum/web/action/AbstractReleaseAction.java
@@ -0,0 +1,134 @@
+package org.apache.continuum.web.action;
+
+/*
+ * 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 org.apache.continuum.configuration.BuildAgentConfiguration;
+import org.apache.continuum.configuration.BuildAgentGroupConfiguration;
+import org.apache.continuum.release.distributed.DistributedReleaseUtil;
+import org.apache.maven.continuum.installation.InstallationService;
+import org.apache.maven.continuum.model.system.Installation;
+import org.apache.maven.continuum.model.system.Profile;
+import org.apache.maven.continuum.web.action.ContinuumActionSupport;
+import org.codehaus.plexus.util.StringUtils;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class AbstractReleaseAction
+    extends ContinuumActionSupport
+{
+    protected Map<String, String> getEnvironments( Profile profile, String defaultBuildagent )
+    {
+        if ( profile == null )
+        {
+            if ( defaultBuildagent != null )
+            {
+                return Collections.singletonMap( DistributedReleaseUtil.KEY_BUILD_AGENT_URL, defaultBuildagent );
+            }
+            else
+            {
+                return Collections.emptyMap();
+            }
+        }
+
+        Map<String, String> envVars = new HashMap<String, String>();
+
+        if ( defaultBuildagent != null && defaultBuildagent.length() > 0 )
+        {
+            // get buildagent to be used from the buildagent group for distributed builds setup
+            BuildAgentGroupConfiguration group = getContinuum().getConfiguration().getBuildAgentGroup(
+                profile.getBuildAgentGroup() );
+
+            if ( group != null )
+            {
+                List<BuildAgentConfiguration> agents = group.getBuildAgents();
+                if ( agents != null )
+                {
+                    if ( isDefaultBuildAgentEnabledInGroup( defaultBuildagent, agents ) )
+                    {
+                        envVars.put( DistributedReleaseUtil.KEY_BUILD_AGENT_URL, defaultBuildagent );
+                    }
+                    else
+                    {
+                        for ( BuildAgentConfiguration agent : agents )
+                        {
+                            if ( agent.isEnabled() == true )
+                            {
+                                envVars.put( DistributedReleaseUtil.KEY_BUILD_AGENT_URL, agent.getUrl() );
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        String javaHome = getJavaHomeValue( profile );
+        if ( !StringUtils.isEmpty( javaHome ) )
+        {
+            envVars.put( getContinuum().getInstallationService().getEnvVar( InstallationService.JDK_TYPE ), javaHome );
+        }
+
+        Installation builder = profile.getBuilder();
+        if ( builder != null )
+        {
+            envVars.put( getContinuum().getInstallationService().getEnvVar( InstallationService.MAVEN2_TYPE ),
+                         builder.getVarValue() );
+        }
+
+        List<Installation> installations = profile.getEnvironmentVariables();
+        for ( Installation installation : installations )
+        {
+            envVars.put( installation.getVarName(), installation.getVarValue() );
+        }
+        return envVars;
+    }
+
+    private boolean isDefaultBuildAgentEnabledInGroup( String defaultBuildagent, List<BuildAgentConfiguration> agents )
+    {
+        boolean isInGroup = false;
+
+        for ( BuildAgentConfiguration agent : agents )
+        {
+            if ( agent.isEnabled() == true )
+            {
+                if ( defaultBuildagent.equals( agent.getUrl() ) )
+                {
+                    isInGroup = true;
+                    break;
+                }
+            }
+        }
+
+        return isInGroup;
+    }
+
+    private String getJavaHomeValue( Profile profile )
+    {
+        Installation jdk = profile.getJdk();
+        if ( jdk == null )
+        {
+            return null;
+        }
+        return jdk.getVarValue();
+    }
+}
diff --git a/continuum-webapp/src/main/java/org/apache/continuum/web/action/DistributedReleasesAction.java b/continuum-webapp/src/main/java/org/apache/continuum/web/action/DistributedReleasesAction.java
new file mode 100644
index 0000000..94183dc
--- /dev/null
+++ b/continuum-webapp/src/main/java/org/apache/continuum/web/action/DistributedReleasesAction.java
@@ -0,0 +1,87 @@
+package org.apache.continuum.web.action;
+
+/*
+ * 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 org.apache.continuum.release.distributed.DistributedReleaseUtil;
+import org.apache.continuum.release.distributed.manager.DistributedReleaseManager;
+import org.apache.maven.continuum.security.ContinuumRoleConstants;
+import org.apache.maven.continuum.web.action.ContinuumActionSupport;
+import org.apache.maven.continuum.web.model.DistributedReleaseSummary;
+import org.codehaus.plexus.redback.rbac.Resource;
+import org.codehaus.redback.integration.interceptor.SecureAction;
+import org.codehaus.redback.integration.interceptor.SecureActionBundle;
+import org.codehaus.redback.integration.interceptor.SecureActionException;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @plexus.component role="com.opensymphony.xwork2.Action" role-hint="distributedRelease"
+ */
+public class DistributedReleasesAction
+    extends ContinuumActionSupport
+    implements SecureAction
+{
+    private List<DistributedReleaseSummary> releasesSummary;
+
+    public String list()
+        throws Exception
+    {
+        DistributedReleaseManager releaseManager = getContinuum().getDistributedReleaseManager();
+
+        List<Map<String, Object>> releases = releaseManager.getAllReleasesInProgress();
+
+        releasesSummary = new ArrayList<DistributedReleaseSummary>();
+
+        for ( Map<String, Object> release : releases )
+        {
+            DistributedReleaseSummary summary = new DistributedReleaseSummary();
+            summary.setReleaseId( DistributedReleaseUtil.getReleaseId( release ) );
+            summary.setReleaseGoal( DistributedReleaseUtil.getReleaseGoal( release ) );
+            summary.setBuildAgentUrl( DistributedReleaseUtil.getBuildAgentUrl( release ) );
+            summary.setProjectId( DistributedReleaseUtil.getProjectId( release ) );
+
+            releasesSummary.add( summary );
+        }
+
+        return SUCCESS;
+    }
+
+    public List<DistributedReleaseSummary> getReleasesSummary()
+    {
+        return releasesSummary;
+    }
+
+    public void setReleasesSummary( List<DistributedReleaseSummary> releasesSummary )
+    {
+        this.releasesSummary = releasesSummary;
+    }
+
+    public SecureActionBundle getSecureActionBundle()
+        throws SecureActionException
+    {
+        SecureActionBundle bundle = new SecureActionBundle();
+        bundle.setRequiresAuthentication( true );
+        bundle.addRequiredAuthorization( ContinuumRoleConstants.CONTINUUM_VIEW_RELEASE, Resource.GLOBAL );
+
+        return bundle;
+    }
+}
diff --git a/continuum-webapp/src/main/java/org/apache/continuum/web/action/ReleaseResultAction.java b/continuum-webapp/src/main/java/org/apache/continuum/web/action/ReleaseResultAction.java
index 2f99e9f..68af13b 100644
--- a/continuum-webapp/src/main/java/org/apache/continuum/web/action/ReleaseResultAction.java
+++ b/continuum-webapp/src/main/java/org/apache/continuum/web/action/ReleaseResultAction.java
@@ -19,10 +19,6 @@
  * under the License.
  */
 
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
-
 import org.apache.commons.lang.StringEscapeUtils;
 import org.apache.continuum.model.release.ContinuumReleaseResult;
 import org.apache.maven.continuum.ContinuumException;
@@ -32,6 +28,12 @@
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
 import org.apache.maven.shared.release.ReleaseResult;
 import org.codehaus.plexus.util.FileUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
 
 /**
  * @author <a href="mailto:ctan@apache.org">Maria Catherine Tan</a>
@@ -40,24 +42,28 @@
 public class ReleaseResultAction
     extends ContinuumConfirmAction
 {
+    private static final Logger logger = LoggerFactory.getLogger( ReleaseResultAction.class );
+
     private int projectGroupId;
-    
+
     private int releaseResultId;
-    
+
     private List<ContinuumReleaseResult> releaseResults;
-    
+
     private List<String> selectedReleaseResults;
-    
+
     private ProjectGroup projectGroup;
-    
+
     private ReleaseResult result;
-    
+
     private boolean confirmed;
 
     private String projectName;
 
     private String releaseGoal;
 
+    private String username;
+
     public String list()
         throws ContinuumException
     {
@@ -70,13 +76,13 @@
             addActionError( authzE.getMessage() );
             return REQUIRES_AUTHORIZATION;
         }
-        
+
         releaseResults = getContinuum().getContinuumReleaseResultsByProjectGroup( projectGroupId );
-        
+
         return SUCCESS;
 
     }
-    
+
     public String remove()
         throws ContinuumException
     {
@@ -88,7 +94,7 @@
         {
             return REQUIRES_AUTHORIZATION;
         }
-     
+
         if ( confirmed )
         {
             if ( selectedReleaseResults != null && !selectedReleaseResults.isEmpty() )
@@ -99,23 +105,23 @@
 
                     try
                     {
-                        getLogger().info( "Removing ContinuumReleaseResult with id=" + resultId );
+                        logger.info( "Removing ContinuumReleaseResult with id=" + resultId );
 
                         getContinuum().removeContinuumReleaseResult( resultId );
                     }
                     catch ( ContinuumException e )
                     {
-                        getLogger().error( "Error removing ContinuumReleaseResult with id=" + resultId );
+                        logger.error( "Error removing ContinuumReleaseResult with id=" + resultId );
                         addActionError( getText( "Unable to remove ContinuumReleaseResult with id=" + resultId ) );
                     }
                 }
             }
             return SUCCESS;
         }
-        
+
         return CONFIRM;
     }
-    
+
     public String viewResult()
         throws ContinuumException
     {
@@ -128,9 +134,9 @@
             addActionError( authzE.getMessage() );
             return REQUIRES_AUTHORIZATION;
         }
-        
+
         ContinuumReleaseResult releaseResult = getContinuum().getContinuumReleaseResult( releaseResultId );
-        
+
         result = new ReleaseResult();
         result.setStartTime( releaseResult.getStartTime() );
         result.setEndTime( releaseResult.getEndTime() );
@@ -138,10 +144,13 @@
 
         releaseGoal = releaseResult.getReleaseGoal();
         projectName = releaseResult.getProject().getName();
+        username = releaseResult.getUsername();
 
         try
         {
-            File releaseOutputFile = getContinuum().getConfiguration().getReleaseOutputFile( projectGroupId, "releases-" + releaseResult.getStartTime() );
+            File releaseOutputFile = getContinuum().getConfiguration().getReleaseOutputFile( projectGroupId,
+                                                                                             "releases-" +
+                                                                                                 releaseResult.getStartTime() );
 
             if ( releaseOutputFile.exists() )
             {
@@ -157,17 +166,17 @@
         {
             //getLogger().error( "" );
         }
-        
+
         return SUCCESS;
     }
-    
+
     public String getProjectGroupName()
         throws ContinuumException
     {
-    
+
         return getProjectGroup( projectGroupId ).getName();
     }
-    
+
     public ProjectGroup getProjectGroup( int projectGroupId )
         throws ContinuumException
     {
@@ -182,45 +191,45 @@
                 projectGroup = getContinuum().getProjectGroup( projectGroupId );
             }
         }
-    
+
         return projectGroup;
     }
-    
+
     public ProjectGroup getProjectGroup()
     {
         return projectGroup;
     }
-    
+
     public void setProjectGroup( ProjectGroup projectGroup )
     {
         this.projectGroup = projectGroup;
     }
-    
+
     public int getProjectGroupId()
     {
         return projectGroupId;
     }
-    
+
     public void setProjectGroupId( int projectGroupId )
     {
         this.projectGroupId = projectGroupId;
     }
-    
+
     public int getReleaseResultId()
     {
         return releaseResultId;
     }
-    
+
     public void setReleaseResultId( int releaseResultId )
     {
         this.releaseResultId = releaseResultId;
     }
-    
+
     public List<ContinuumReleaseResult> getReleaseResults()
     {
         return releaseResults;
     }
-    
+
     public void setReleaseResults( List<ContinuumReleaseResult> releaseResults )
     {
         this.releaseResults = releaseResults;
@@ -230,27 +239,27 @@
     {
         return selectedReleaseResults;
     }
-    
+
     public void setSelectedReleaseResults( List<String> selectedReleaseResults )
     {
         this.selectedReleaseResults = selectedReleaseResults;
     }
-    
+
     public ReleaseResult getResult()
     {
         return result;
     }
-    
+
     public void setResult( ReleaseResult result )
     {
         this.result = result;
     }
-    
+
     public boolean isConfirmed()
     {
         return confirmed;
     }
-    
+
     public void setConfirmed( boolean confirmed )
     {
         this.confirmed = confirmed;
@@ -275,4 +284,14 @@
     {
         this.releaseGoal = releaseGoal;
     }
+
+    public void setUsername( String username )
+    {
+        this.username = username;
+    }
+
+    public String getUsername()
+    {
+        return username;
+    }
 }
diff --git a/continuum-webapp/src/main/java/org/apache/continuum/web/action/ScmResultAction.java b/continuum-webapp/src/main/java/org/apache/continuum/web/action/ScmResultAction.java
index 782e334..1b30f40 100644
--- a/continuum-webapp/src/main/java/org/apache/continuum/web/action/ScmResultAction.java
+++ b/continuum-webapp/src/main/java/org/apache/continuum/web/action/ScmResultAction.java
@@ -1,12 +1,29 @@
 package org.apache.continuum.web.action;
 
+/*
+ * 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 org.apache.continuum.model.project.ProjectScmRoot;
 import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.web.action.ContinuumActionSupport;
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
 import org.apache.maven.continuum.web.util.StateGenerator;
-import org.codehaus.plexus.util.StringUtils;
-
 import org.apache.struts2.ServletActionContext;
 
 /**
@@ -16,88 +33,86 @@
 public class ScmResultAction
     extends ContinuumActionSupport
 {
-   private int projectGroupId;
+    private int projectGroupId;
 
-   private int projectScmRootId;
+    private int projectScmRootId;
 
-   private String projectGroupName;
+    private String projectGroupName;
 
-   private String state;
+    private String state;
 
-   private ProjectScmRoot projectScmRoot;
+    private ProjectScmRoot projectScmRoot;
 
-   public String execute()
-       throws Exception
-   {
-       try
-       {
-           checkViewProjectGroupAuthorization( getProjectGroupName() );
-       }
-       catch ( AuthorizationRequiredException e )
-       {
-           return REQUIRES_AUTHORIZATION;
-       }
-
-       projectScmRoot = getContinuum().getProjectScmRoot( projectScmRootId );
-
-       state = StateGenerator.generate( projectScmRoot.getState(), ServletActionContext.getRequest().getContextPath() );
-       
-       return SUCCESS;
-   }
-
-   public int getProjectGroupId()
-   {
-       return projectGroupId;
-   }
-
-   public void setProjectGroupId( int projectGroupId )
-   {
-       this.projectGroupId = projectGroupId;
-   }
-
-   public int getProjectScmRootId()
-   {
-       return projectScmRootId;
-   }
-
-   public void setProjectScmRootId( int projectScmRootId )
-   {
-       this.projectScmRootId = projectScmRootId;
-   }
-
-   public ProjectScmRoot getProjectScmRoot()
-   {
-       return projectScmRoot;
-   }
-
-   public void setProjectScmRoot( ProjectScmRoot projectScmRoot )
-   {
-       this.projectScmRoot = projectScmRoot;
-   }
-
-   public String getProjectGroupName()
-       throws ContinuumException
+    public String execute()
+        throws Exception
     {
-       if ( StringUtils.isEmpty( projectGroupName ) )
-       {
-           projectGroupName = getContinuum().getProjectGroup( getProjectGroupId() ).getName();
-       }
-    
-       return projectGroupName;
+        try
+        {
+            checkViewProjectGroupAuthorization( getProjectGroupName() );
+        }
+        catch ( AuthorizationRequiredException e )
+        {
+            return REQUIRES_AUTHORIZATION;
+        }
+
+        projectScmRoot = getContinuum().getProjectScmRoot( projectScmRootId );
+
+        state = StateGenerator.generate( projectScmRoot.getState(),
+                                         ServletActionContext.getRequest().getContextPath() );
+
+        return SUCCESS;
     }
-   
-   public void setProjectGroupName( String projectGroupName )
-   {
-       this.projectGroupName = projectGroupName;
-   }
 
-   public String getState()
-   {
-       return state;
-   }
+    public int getProjectGroupId()
+    {
+        return projectGroupId;
+    }
 
-   public void setState( String state )
-   {
-       this.state = state;
-   }
+    public void setProjectGroupId( int projectGroupId )
+    {
+        this.projectGroupId = projectGroupId;
+    }
+
+    public int getProjectScmRootId()
+    {
+        return projectScmRootId;
+    }
+
+    public void setProjectScmRootId( int projectScmRootId )
+    {
+        this.projectScmRootId = projectScmRootId;
+    }
+
+    public ProjectScmRoot getProjectScmRoot()
+    {
+        return projectScmRoot;
+    }
+
+    public void setProjectScmRoot( ProjectScmRoot projectScmRoot )
+    {
+        this.projectScmRoot = projectScmRoot;
+    }
+
+    public String getProjectGroupName()
+        throws ContinuumException
+    {
+        projectGroupName = getContinuum().getProjectGroup( getProjectGroupId() ).getName();
+
+        return projectGroupName;
+    }
+
+    public void setProjectGroupName( String projectGroupName )
+    {
+        this.projectGroupName = projectGroupName;
+    }
+
+    public String getState()
+    {
+        return state;
+    }
+
+    public void setState( String state )
+    {
+        this.state = state;
+    }
 }
diff --git a/continuum-webapp/src/main/java/org/apache/continuum/web/action/ViewBuildsReportAction.java b/continuum-webapp/src/main/java/org/apache/continuum/web/action/ViewBuildsReportAction.java
new file mode 100644
index 0000000..001ca99
--- /dev/null
+++ b/continuum-webapp/src/main/java/org/apache/continuum/web/action/ViewBuildsReportAction.java
@@ -0,0 +1,450 @@
+package org.apache.continuum.web.action;
+
+/*
+ * 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 org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.time.DateUtils;
+import org.apache.maven.continuum.model.project.BuildResult;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.project.ProjectGroup;
+import org.apache.maven.continuum.project.ContinuumProjectState;
+import org.apache.maven.continuum.web.action.ContinuumActionSupport;
+import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
+import org.apache.maven.continuum.web.model.ProjectBuildsSummary;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @plexus.component role="com.opensymphony.xwork2.Action" role-hint="projectBuildsReport"
+ */
+public class ViewBuildsReportAction
+    extends ContinuumActionSupport
+{
+    private int buildStatus;
+
+    private String triggeredBy = "";
+
+    private String startDate = "";
+
+    private String endDate = "";
+
+    private int projectGroupId;
+
+    private int rowCount = 30;
+
+    private int page = 1;
+
+    private int numPages;
+
+    private Map<Integer, String> buildStatuses;
+
+    private Map<Integer, String> projectGroups;
+
+    private List<ProjectBuildsSummary> projectBuilds;
+
+    private InputStream inputStream;
+
+    public static final String SEND_FILE = "send-file";
+
+    private static final String[] datePatterns =
+        new String[]{"MM/dd/yy", "MM/dd/yyyy", "MMMMM/dd/yyyy", "MMMMM/dd/yy", "dd MMMMM yyyy", "dd/MM/yy",
+            "dd/MM/yyyy", "yyyy/MM/dd", "yyyy-MM-dd", "yyyy-dd-MM", "MM-dd-yyyy", "MM-dd-yy"};
+
+    public void prepare()
+        throws Exception
+    {
+        super.prepare();
+
+        buildStatuses = new LinkedHashMap<Integer, String>();
+        buildStatuses.put( 0, "ALL" );
+        buildStatuses.put( ContinuumProjectState.OK, "Ok" );
+        buildStatuses.put( ContinuumProjectState.FAILED, "Failed" );
+        buildStatuses.put( ContinuumProjectState.ERROR, "Error" );
+
+        projectGroups = new LinkedHashMap<Integer, String>();
+        projectGroups.put( 0, "ALL" );
+
+        List<ProjectGroup> groups = getContinuum().getAllProjectGroups();
+        if ( groups != null )
+        {
+            for ( ProjectGroup group : groups )
+            {
+                projectGroups.put( group.getId(), group.getName() );
+            }
+        }
+    }
+
+    public String init()
+    {
+        try
+        {
+            checkViewReportsAuthorization();
+        }
+        catch ( AuthorizationRequiredException authzE )
+        {
+            addActionError( authzE.getMessage() );
+            return REQUIRES_AUTHORIZATION;
+        }
+
+        // action class was called from the Menu; do not generate report first
+        return SUCCESS;
+    }
+
+    public String execute()
+    {
+        try
+        {
+            checkViewReportsAuthorization();
+        }
+        catch ( AuthorizationRequiredException authzE )
+        {
+            addActionError( authzE.getMessage() );
+            return REQUIRES_AUTHORIZATION;
+        }
+
+        Date fromDate = null;
+        Date toDate = null;
+
+        try
+        {
+            fromDate = getStartDateInDateFormat();
+            toDate = getEndDateInDateFormat();
+        }
+        catch ( ParseException e )
+        {
+            addActionError( "Error parsing date(s): " + e.getMessage() );
+            return ERROR;
+        }
+
+        if ( fromDate != null && toDate != null && fromDate.after( toDate ) )
+        {
+            addFieldError( "startDate", "Start Date must be earlier than the End Date" );
+            return INPUT;
+        }
+
+        if ( rowCount < 10 )
+        {
+            // TODO: move to validation framework
+            addFieldError( "rowCount", "Row count should be at least 10." );
+            return INPUT;
+        }
+
+        List<BuildResult> buildResults = getContinuum().getBuildResultsInRange( projectGroupId, fromDate, toDate,
+                                                                                buildStatus, triggeredBy );
+        projectBuilds = Collections.emptyList();
+
+        if ( buildResults != null && !buildResults.isEmpty() )
+        {
+            projectBuilds = mapBuildResultsToProjectBuildsSummaries( buildResults );
+
+            int extraPage = ( projectBuilds.size() % rowCount ) != 0 ? 1 : 0;
+            numPages = ( projectBuilds.size() / rowCount ) + extraPage;
+
+            if ( page > numPages )
+            {
+                addActionError(
+                    "Error encountered while generating project builds report :: The requested page exceeds the total number of pages." );
+                return ERROR;
+            }
+
+            int start = rowCount * ( page - 1 );
+            int end = ( start + rowCount );
+
+            if ( end > projectBuilds.size() )
+            {
+                end = projectBuilds.size();
+            }
+
+            projectBuilds = projectBuilds.subList( start, end );
+        }
+
+        return SUCCESS;
+    }
+
+    /*
+    * Export Builds Report to .csv
+    */
+    public String downloadBuildsReport()
+    {
+        try
+        {
+            checkViewReportsAuthorization();
+        }
+        catch ( AuthorizationRequiredException authzE )
+        {
+            addActionError( authzE.getMessage() );
+            return REQUIRES_AUTHORIZATION;
+        }
+
+        Date fromDate = null;
+        Date toDate = null;
+
+        try
+        {
+            fromDate = getStartDateInDateFormat();
+            toDate = getEndDateInDateFormat();
+        }
+        catch ( ParseException e )
+        {
+            addActionError( "Error parsing date(s): " + e.getMessage() );
+            return ERROR;
+        }
+
+        if ( fromDate != null && toDate != null && fromDate.after( toDate ) )
+        {
+            addFieldError( "startDate", "Start Date must be earlier than the End Date" );
+            return INPUT;
+        }
+
+        List<BuildResult> buildResults = getContinuum().getBuildResultsInRange( projectGroupId, fromDate, toDate,
+                                                                                buildStatus, triggeredBy );
+        List<ProjectBuildsSummary> builds = Collections.emptyList();
+
+        StringBuffer input = new StringBuffer( "Project Group,Project Name,Build Date,Triggered By,Build Status\n" );
+
+        if ( buildResults != null && !buildResults.isEmpty() )
+        {
+            builds = mapBuildResultsToProjectBuildsSummaries( buildResults );
+
+            for ( ProjectBuildsSummary build : builds )
+            {
+                input.append( build.getProjectGroupName() ).append( "," );
+                input.append( build.getProjectName() ).append( "," );
+
+                input.append( new Date( build.getBuildDate() ) ).append( "," );
+
+                input.append( build.getBuildTriggeredBy() ).append( "," );
+
+                String status;
+                switch ( build.getBuildState() )
+                {
+                    case 2:
+                        status = "Ok";
+                        break;
+                    case 3:
+                        status = "Failed";
+                        break;
+                    case 4:
+                        status = "Error";
+                        break;
+                    case 6:
+                        status = "Building";
+                        break;
+                    case 7:
+                        status = "Checking Out";
+                        break;
+                    case 8:
+                        status = "Updating";
+                        break;
+                    default:
+                        status = "";
+                }
+                input.append( status );
+                input.append( "\n" );
+            }
+        }
+
+        StringReader reader = new StringReader( input.toString() );
+
+        try
+        {
+            inputStream = new ByteArrayInputStream( IOUtils.toByteArray( reader ) );
+        }
+        catch ( IOException e )
+        {
+            addActionError( "Error occurred while generating CSV file." );
+            return ERROR;
+        }
+
+        return SEND_FILE;
+    }
+
+    private List<ProjectBuildsSummary> mapBuildResultsToProjectBuildsSummaries( List<BuildResult> buildResults )
+    {
+        List<ProjectBuildsSummary> buildsSummary = new ArrayList<ProjectBuildsSummary>();
+
+        for ( BuildResult buildResult : buildResults )
+        {
+            Project project = buildResult.getProject();
+
+            // check if user is authorised to view build result
+            if ( !isAuthorized( project.getProjectGroup().getName() ) )
+            {
+                continue;
+            }
+
+            ProjectBuildsSummary summary = new ProjectBuildsSummary();
+            summary.setProjectGroupName( project.getProjectGroup().getName() );
+            summary.setProjectName( project.getName() );
+            summary.setBuildDate( buildResult.getStartTime() );
+            summary.setBuildState( buildResult.getState() );
+            summary.setBuildTriggeredBy( buildResult.getUsername() );
+
+            buildsSummary.add( summary );
+        }
+
+        return buildsSummary;
+    }
+
+    private Date getStartDateInDateFormat()
+        throws ParseException
+    {
+        Date date = null;
+
+        if ( !StringUtils.isEmpty( startDate ) )
+        {
+            date = DateUtils.parseDate( startDate, datePatterns );
+        }
+
+        return date;
+    }
+
+    private Date getEndDateInDateFormat()
+        throws ParseException
+    {
+        Date date = null;
+
+        if ( !StringUtils.isEmpty( endDate ) )
+        {
+            date = DateUtils.parseDate( endDate, datePatterns );
+        }
+
+        return date;
+    }
+
+    public int getBuildStatus()
+    {
+        return this.buildStatus;
+    }
+
+    public void setBuildStatus( int buildStatus )
+    {
+        this.buildStatus = buildStatus;
+    }
+
+    public int getProjectGroupId()
+    {
+        return this.projectGroupId;
+    }
+
+    public void setProjectGroupId( int projectGroupId )
+    {
+        this.projectGroupId = projectGroupId;
+    }
+
+    public String getTriggeredBy()
+    {
+        return this.triggeredBy;
+    }
+
+    public void setTriggeredBy( String triggeredBy )
+    {
+        this.triggeredBy = triggeredBy;
+    }
+
+    public String getStartDate()
+    {
+        return this.startDate;
+    }
+
+    public void setStartDate( String startDate )
+    {
+        this.startDate = startDate;
+    }
+
+    public String getEndDate()
+    {
+        return this.endDate;
+    }
+
+    public void setEndDate( String endDate )
+    {
+        this.endDate = endDate;
+    }
+
+    public int getRowCount()
+    {
+        return rowCount;
+    }
+
+    public void setRowCount( int rowCount )
+    {
+        this.rowCount = rowCount;
+    }
+
+    public Map<Integer, String> getBuildStatuses()
+    {
+        return buildStatuses;
+    }
+
+    public Map<Integer, String> getProjectGroups()
+    {
+        return projectGroups;
+    }
+
+    public List<ProjectBuildsSummary> getProjectBuilds()
+    {
+        return projectBuilds;
+    }
+
+    public int getPage()
+    {
+        return page;
+    }
+
+    public void setPage( int page )
+    {
+        this.page = page;
+    }
+
+    public int getNumPages()
+    {
+        return numPages;
+    }
+
+    public InputStream getInputStream()
+    {
+        return inputStream;
+    }
+
+    private boolean isAuthorized( String projectGroupName )
+    {
+        try
+        {
+            checkViewProjectGroupAuthorization( projectGroupName );
+            return true;
+        }
+        catch ( AuthorizationRequiredException authzE )
+        {
+            return false;
+        }
+    }
+}
diff --git a/continuum-webapp/src/main/java/org/apache/continuum/web/action/admin/BuildAgentAction.java b/continuum-webapp/src/main/java/org/apache/continuum/web/action/admin/BuildAgentAction.java
index 7aad6ed..249e2a5 100644
--- a/continuum-webapp/src/main/java/org/apache/continuum/web/action/admin/BuildAgentAction.java
+++ b/continuum-webapp/src/main/java/org/apache/continuum/web/action/admin/BuildAgentAction.java
@@ -19,10 +19,15 @@
  * under the License.
  */
 
+import org.apache.commons.lang.StringEscapeUtils;
 import org.apache.continuum.configuration.BuildAgentConfiguration;
-import org.apache.continuum.builder.distributed.manager.DistributedBuildManager;
+import org.apache.continuum.configuration.BuildAgentGroupConfiguration;
+import org.apache.continuum.web.util.AuditLog;
+import org.apache.continuum.web.util.AuditLogConstants;
+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;
@@ -31,7 +36,11 @@
 import org.codehaus.redback.integration.interceptor.SecureAction;
 import org.codehaus.redback.integration.interceptor.SecureActionBundle;
 import org.codehaus.redback.integration.interceptor.SecureActionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -42,15 +51,20 @@
     extends ContinuumConfirmAction
     implements SecureAction
 {
-    /**
-     * @plexus.requirement
-     */
-    private DistributedBuildManager distributedBuildManager;
-    
+    private static final Logger logger = LoggerFactory.getLogger( BuildAgentAction.class );
+
     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;
 
     private boolean confirmed;
@@ -59,16 +73,28 @@
 
     private String type;
 
+    private String typeGroup;
+
+    public void prepare()
+        throws Exception
+    {
+        super.prepare();
+        this.setBuildAgents( getContinuum().getConfiguration().getBuildAgents() );
+    }
+
     public String input()
         throws Exception
     {
         if ( buildAgent != null && !StringUtils.isBlank( buildAgent.getUrl() ) )
         {
+            String escapedBuildAgentUrl = StringEscapeUtils.escapeXml( buildAgent.getUrl() );
+            buildAgent.setUrl( escapedBuildAgentUrl );
+
             List<BuildAgentConfiguration> agents = getContinuum().getConfiguration().getBuildAgents();
-            
+
             for ( BuildAgentConfiguration agent : agents )
             {
-                if ( agent.getUrl().equals( buildAgent.getUrl() ) )
+                if ( agent.getUrl().equals( escapedBuildAgentUrl ) )
                 {
                     buildAgent = agent;
                     type = "edit";
@@ -78,6 +104,8 @@
         else
         {
             type = "new";
+            buildAgent = new BuildAgentConfiguration();
+            buildAgent.setEnabled( true );
         }
 
         return INPUT;
@@ -94,6 +122,7 @@
         }
 
         this.buildAgents = getContinuum().getConfiguration().getBuildAgents();
+        this.buildAgentGroups = getContinuum().getConfiguration().getBuildAgentGroups();
 
         return SUCCESS;
     }
@@ -103,13 +132,26 @@
     {
         ConfigurationService configuration = getContinuum().getConfiguration();
 
-        for ( BuildAgentConfiguration agent : configuration.getBuildAgents() )
+        if ( buildAgent != null )
         {
-            if ( agent.getUrl().equals( buildAgent.getUrl() ) )
+            for ( BuildAgentConfiguration agent : configuration.getBuildAgents() )
             {
-                buildAgent = agent;
-                installations = distributedBuildManager.getAvailableInstallations( buildAgent.getUrl() );
-                break;
+                if ( agent.getUrl().equals( buildAgent.getUrl() ) )
+                {
+                    buildAgent = agent;
+
+                    try
+                    {
+                        installations = getContinuum().getDistributedBuildManager().getAvailableInstallations(
+                            buildAgent.getUrl() );
+                    }
+                    catch ( ContinuumException e )
+                    {
+                        logger.error( "Unable to retrieve installations of build agent '" + agent.getUrl() + "'", e );
+                    }
+
+                    break;
+                }
             }
         }
 
@@ -123,35 +165,56 @@
 
         ConfigurationService configuration = getContinuum().getConfiguration();
 
+        // escape xml to prevent xss attacks
+        buildAgent.setDescription(
+            StringEscapeUtils.escapeXml( StringEscapeUtils.unescapeXml( buildAgent.getDescription() ) ) );
+
         if ( configuration.getBuildAgents() != null )
         {
             for ( BuildAgentConfiguration agent : configuration.getBuildAgents() )
             {
-                if ( buildAgent.getUrl().equals( agent.getUrl() ) )
+                if ( agent.getUrl().equals( buildAgent.getUrl() ) )
                 {
-                    agent.setDescription( buildAgent.getDescription() );
-                    agent.setEnabled( buildAgent.isEnabled() );
-
-                    configuration.updateBuildAgent( agent );
+                    if ( type.equals( "new" ) )
+                    {
+                        addActionError( getResourceBundle().getString( "buildAgent.error.duplicate" ) );
+                        return INPUT;
+                    }
+                    else
+                    {
+                        agent.setDescription( buildAgent.getDescription() );
+                        agent.setEnabled( buildAgent.isEnabled() );
+                        configuration.updateBuildAgent( agent );
+                        configuration.store();
+                    }
                     found = true;
                 }
             }
         }
 
+        // update first, so that we don't add or change it if it fails
+        try
+        {
+            getContinuum().getDistributedBuildManager().update( buildAgent );
+        }
+        catch ( ContinuumException e )
+        {
+            addActionError( e.getMessage() );
+            return INPUT;
+        }
+
+        AuditLog event = new AuditLog( "Build Agent URL=" + buildAgent.getUrl(), AuditLogConstants.MODIFY_BUILD_AGENT );
+        event.setCategory( AuditLogConstants.BUILD_AGENT );
+        event.setCurrentUser( getPrincipal() );
+
         if ( !found )
         {
             configuration.addBuildAgent( buildAgent );
-        }
-        else
-        {
-            if ( type.equals( "new" ) )
-            {
-                addActionError( getResourceBundle().getString( "buildAgent.error.duplicate" ) );
-                return INPUT;
-            }
+            configuration.store();
+            event.setAction( AuditLogConstants.ADD_BUILD_AGENT );
         }
 
-        distributedBuildManager.reload();
+        event.log();
 
         return SUCCESS;
     }
@@ -159,29 +222,54 @@
     public String delete()
         throws Exception
     {
+        buildAgent.setUrl( StringEscapeUtils.escapeXml( buildAgent.getUrl() ) );
+
         if ( !confirmed )
         {
             return CONFIRM;
         }
 
-        if ( distributedBuildManager.isBuildAgentBusy( buildAgent.getUrl() ) )
+        if ( getContinuum().getDistributedBuildManager().isBuildAgentBusy( buildAgent.getUrl() ) )
         {
             message = getText( "buildAgent.error.delete.busy" );
             return ERROR;
         }
-        else
-        {
-            distributedBuildManager.removeAgentFromTaskQueueExecutor( buildAgent.getUrl() );
-        }
 
         ConfigurationService configuration = getContinuum().getConfiguration();
 
-        for ( BuildAgentConfiguration agent : configuration.getBuildAgents() )
+        if ( configuration.getBuildAgentGroups() != null )
         {
-            if ( buildAgent.getUrl().equals( agent.getUrl() ) )
+            for ( BuildAgentGroupConfiguration buildAgentGroup : configuration.getBuildAgentGroups() )
             {
-                configuration.removeBuildAgent( agent );
-                return SUCCESS;
+                if ( configuration.containsBuildAgentUrl( buildAgent.getUrl(), buildAgentGroup ) )
+                {
+                    message = getText( "buildAgent.error.remove.in.use" );
+                    return ERROR;
+                }
+            }
+        }
+
+        if ( configuration.getBuildAgents() != null )
+        {
+            for ( BuildAgentConfiguration agent : configuration.getBuildAgents() )
+            {
+                if ( buildAgent.getUrl().equals( agent.getUrl() ) )
+                {
+                    getContinuum().getDistributedBuildManager().removeDistributedBuildQueueOfAgent(
+                        buildAgent.getUrl() );
+                    configuration.removeBuildAgent( agent );
+                    configuration.store();
+
+                    AuditLog event =
+                        new AuditLog( "Build Agent URL=" + agent.getUrl(), AuditLogConstants.REMOVE_BUILD_AGENT );
+                    event.setCategory( AuditLogConstants.BUILD_AGENT );
+                    event.setCurrentUser( getPrincipal() );
+                    event.log();
+
+                    getContinuum().getDistributedBuildManager().reload();
+
+                    return SUCCESS;
+                }
             }
         }
 
@@ -189,6 +277,171 @@
         return ERROR;
     }
 
+    public String deleteGroup()
+        throws Exception
+    {
+        buildAgentGroup.setName( StringEscapeUtils.escapeXml( buildAgentGroup.getName() ) );
+
+        if ( !confirmed )
+        {
+            return CONFIRM;
+        }
+
+        List<Profile> profiles = getContinuum().getProfileService().getAllProfiles();
+        for ( Profile profile : profiles )
+        {
+            if ( buildAgentGroup.getName().equals( profile.getBuildAgentGroup() ) )
+            {
+                message = getText( "buildAgentGroup.error.remove.in.use", new String[]{ profile.getName() } );
+                return ERROR;
+            }
+        }
+
+        ConfigurationService configuration = getContinuum().getConfiguration();
+
+        for ( BuildAgentGroupConfiguration group : configuration.getBuildAgentGroups() )
+        {
+            if ( buildAgentGroup.getName().equals( group.getName() ) )
+            {
+                configuration.removeBuildAgentGroup( group );
+
+                AuditLog event =
+                    new AuditLog( "Build Agent Group=" + group.getName(), AuditLogConstants.REMOVE_BUILD_AGENT_GROUP );
+                event.setCategory( AuditLogConstants.BUILD_AGENT );
+                event.setCurrentUser( getPrincipal() );
+                event.log();
+
+                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;
+                }
+            }
+        }
+
+        AuditLog event = new AuditLog( "Build Agent Group=" + buildAgentGroup.getName(),
+                                       AuditLogConstants.MODIFY_BUILD_AGENT_GROUP );
+        event.setCategory( AuditLogConstants.BUILD_AGENT );
+        event.setCurrentUser( getPrincipal() );
+
+        if ( !found )
+        {
+            buildAgentGroup.setBuildAgents( selectedbuildAgents );
+            configuration.addBuildAgentGroup( buildAgentGroup );
+            event.setAction( AuditLogConstants.ADD_BUILD_AGENT_GROUP );
+        }
+        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 );
+            }
+        }
+
+        getContinuum().getDistributedBuildManager().reload();
+        event.log();
+
+        return SUCCESS;
+    }
+
+    public String inputGroup()
+        throws Exception
+    {
+        ConfigurationService configuration = getContinuum().getConfiguration();
+
+        if ( buildAgentGroup != null && !StringUtils.isBlank( buildAgentGroup.getName() ) )
+        {
+            String escapedBuildAgentGroupName = StringEscapeUtils.escapeXml( buildAgentGroup.getName() );
+            buildAgentGroup.setName( escapedBuildAgentGroupName );
+
+            List<BuildAgentGroupConfiguration> agentGroups = configuration.getBuildAgentGroups();
+
+            for ( BuildAgentGroupConfiguration group : agentGroups )
+            {
+                if ( group.getName().equals( escapedBuildAgentGroupName ) )
+                {
+                    buildAgentGroup = group;
+                    typeGroup = "edit";
+
+                    this.buildAgentGroup = configuration.getBuildAgentGroup( escapedBuildAgentGroupName );
+                    this.buildAgents = configuration.getBuildAgents();
+
+                    this.selectedBuildAgentIds = new ArrayList<String>();
+                    if ( this.buildAgentGroup.getBuildAgents() != null )
+                    {
+                        for ( BuildAgentConfiguration buildAgentConfiguration : buildAgentGroup.getBuildAgents() )
+                        {
+                            this.selectedBuildAgentIds.add( buildAgentConfiguration.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
+        {
+            buildAgentGroup = new BuildAgentGroupConfiguration();
+            typeGroup = "new";
+        }
+        return INPUT;
+    }
+
     public SecureActionBundle getSecureActionBundle()
         throws SecureActionException
     {
@@ -199,6 +452,25 @@
         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()
     {
         return buildAgents;
@@ -243,7 +515,7 @@
     {
         return this.message;
     }
-    
+
     public void setMessage( String message )
     {
         this.message = message;
@@ -258,4 +530,54 @@
     {
         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;
+    }
 }
diff --git a/continuum-webapp/src/main/java/org/apache/continuum/web/action/admin/DistributedPurgeConfigurationAction.java b/continuum-webapp/src/main/java/org/apache/continuum/web/action/admin/DistributedPurgeConfigurationAction.java
new file mode 100644
index 0000000..17c0835
--- /dev/null
+++ b/continuum-webapp/src/main/java/org/apache/continuum/web/action/admin/DistributedPurgeConfigurationAction.java
@@ -0,0 +1,480 @@
+package org.apache.continuum.web.action.admin;
+
+/*
+ * 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 com.opensymphony.xwork2.Preparable;
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.continuum.configuration.BuildAgentConfiguration;
+import org.apache.continuum.model.repository.AbstractPurgeConfiguration;
+import org.apache.continuum.model.repository.DirectoryPurgeConfiguration;
+import org.apache.continuum.model.repository.DistributedDirectoryPurgeConfiguration;
+import org.apache.continuum.purge.ContinuumPurgeManager;
+import org.apache.continuum.purge.PurgeConfigurationService;
+import org.apache.maven.continuum.model.project.Schedule;
+import org.apache.maven.continuum.security.ContinuumRoleConstants;
+import org.apache.maven.continuum.web.action.ContinuumConfirmAction;
+import org.codehaus.plexus.redback.rbac.Resource;
+import org.codehaus.redback.integration.interceptor.SecureAction;
+import org.codehaus.redback.integration.interceptor.SecureActionBundle;
+import org.codehaus.redback.integration.interceptor.SecureActionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author
+ * @version $Id$
+ * @plexus.component role="com.opensymphony.xwork2.Action" role-hint="distributedPurgeConfiguration"
+ */
+public class DistributedPurgeConfigurationAction
+    extends ContinuumConfirmAction
+    implements Preparable, SecureAction
+{
+    private static final Logger logger = LoggerFactory.getLogger( DistributedPurgeConfigurationAction.class );
+
+    private static final String PURGE_TYPE_DIRECTORY = "directory";
+
+    private static final String PURGE_DIRECTORY_RELEASES = "releases";
+
+    private static final String PURGE_DIRECTORY_WORKING = "working";
+
+    private static final int DEFAULT_RETENTION_COUNT = 2;
+
+    private static final int DEFAULT_DAYS_OLDER = 100;
+
+    private String purgeType;
+
+    private String directoryType;
+
+    private String description;
+
+    private String message;
+
+    private boolean deleteAll;
+
+    private boolean deleteReleasedSnapshots;
+
+    private boolean enabled;
+
+    private boolean confirmed;
+
+    private boolean defaultPurgeConfiguration;
+
+    private int retentionCount;
+
+    private int daysOlder;
+
+    private int scheduleId;
+
+    private int purgeConfigId;
+
+    private String buildAgentUrl;
+
+    private AbstractPurgeConfiguration purgeConfig;
+
+    private Map<Integer, String> schedules;
+
+    private List<String> directoryTypes;
+
+    private List<String> buildAgentUrls;
+
+    /**
+     * @plexus.requirement
+     */
+    private PurgeConfigurationService purgeConfigService;
+
+    @Override
+    public void prepare()
+        throws Exception
+    {
+        super.prepare();
+
+        // build schedules
+        if ( schedules == null )
+        {
+            schedules = new HashMap<Integer, String>();
+
+            Collection<Schedule> allSchedules = getContinuum().getSchedules();
+
+            for ( Schedule schedule : allSchedules )
+            {
+                schedules.put( schedule.getId(), schedule.getName() );
+            }
+        }
+
+        // build repositories
+        if ( buildAgentUrls == null )
+        {
+            List<BuildAgentConfiguration> buildAgents = getContinuum().getConfiguration().getBuildAgents();
+            buildAgentUrls = new ArrayList<String>( buildAgents.size() );
+            for ( BuildAgentConfiguration buildAgent : buildAgents )
+            {
+                buildAgentUrls.add( buildAgent.getUrl() );
+            }
+            Collections.sort( buildAgentUrls );
+        }
+
+        directoryTypes = new ArrayList<String>();
+        directoryTypes.add( PURGE_DIRECTORY_RELEASES );
+        directoryTypes.add( PURGE_DIRECTORY_WORKING );
+    }
+
+    @Override
+    public String input()
+        throws Exception
+    {
+        if ( purgeConfigId != 0 )
+        {
+            purgeConfig = purgeConfigService.getPurgeConfiguration( purgeConfigId );
+
+            if ( purgeConfig instanceof DistributedDirectoryPurgeConfiguration )
+            {
+                DistributedDirectoryPurgeConfiguration dirPurge = (DistributedDirectoryPurgeConfiguration) purgeConfig;
+
+                this.purgeType = PURGE_TYPE_DIRECTORY;
+                this.daysOlder = dirPurge.getDaysOlder();
+                this.retentionCount = dirPurge.getRetentionCount();
+                this.directoryType = dirPurge.getDirectoryType();
+                this.deleteAll = dirPurge.isDeleteAll();
+                this.enabled = dirPurge.isEnabled();
+                this.defaultPurgeConfiguration = dirPurge.isDefaultPurge();
+                this.description = dirPurge.getDescription();
+                this.buildAgentUrl = dirPurge.getBuildAgentUrl();
+                if ( dirPurge.getSchedule() != null )
+                {
+                    this.scheduleId = dirPurge.getSchedule().getId();
+                }
+            }
+        }
+        else
+        {
+            this.retentionCount = DEFAULT_RETENTION_COUNT;
+            this.daysOlder = DEFAULT_DAYS_OLDER;
+        }
+
+        return INPUT;
+    }
+
+    public String save()
+        throws Exception
+    {
+        if ( purgeConfigId == 0 )
+        {
+            purgeConfig = new DistributedDirectoryPurgeConfiguration();
+
+            purgeConfig = setupPurgeConfiguration( purgeConfig );
+
+            purgeConfig = purgeConfigService.addPurgeConfiguration( purgeConfig );
+        }
+        else
+        {
+            purgeConfig = purgeConfigService.getPurgeConfiguration( purgeConfigId );
+            purgeConfig = setupPurgeConfiguration( purgeConfig );
+
+            purgeConfigService.updatePurgeConfiguration( purgeConfig );
+        }
+
+        /*if ( purgeConfig.isDefaultPurge() )
+        {
+            updateDefaultPurgeConfiguration();
+        }*/
+
+        if ( purgeConfig.isEnabled() && purgeConfig.getSchedule() != null )
+        {
+            getContinuum().activePurgeSchedule( purgeConfig.getSchedule() );
+        }
+
+        return SUCCESS;
+    }
+
+    public String remove()
+        throws Exception
+    {
+
+        if ( confirmed )
+        {
+            purgeConfigService.removePurgeConfiguration( purgeConfigId );
+        }
+        else
+        {
+            return CONFIRM;
+        }
+
+        return SUCCESS;
+    }
+
+    public String purge()
+        throws Exception
+    {
+
+        ContinuumPurgeManager purgeManager = getContinuum().getPurgeManager();
+
+        if ( purgeConfigId > 0 )
+        {
+            purgeConfig = purgeConfigService.getPurgeConfiguration( purgeConfigId );
+
+            DistributedDirectoryPurgeConfiguration dirPurge = (DistributedDirectoryPurgeConfiguration) purgeConfig;
+            purgeManager.purgeDistributedDirectory( dirPurge );
+        }
+
+        return SUCCESS;
+    }
+
+    public String getPurgeType()
+    {
+        return this.purgeType;
+    }
+
+    public void setPurgeType( String purgeType )
+    {
+        this.purgeType = purgeType;
+    }
+
+    public String getDirectoryType()
+    {
+        return this.directoryType;
+    }
+
+    public void setDirectoryType( String directoryType )
+    {
+        this.directoryType = directoryType;
+    }
+
+    public String getDescription()
+    {
+        return this.description;
+    }
+
+    public void setDescription( String description )
+    {
+        this.description = description;
+    }
+
+    public String getMessage()
+    {
+        return this.message;
+    }
+
+    public void setMessage( String message )
+    {
+        this.message = message;
+    }
+
+    public boolean isDeleteAll()
+    {
+        return this.deleteAll;
+    }
+
+    public void setDeleteAll( boolean deleteAll )
+    {
+        this.deleteAll = deleteAll;
+    }
+
+    public boolean isDeleteReleasedSnapshots()
+    {
+        return this.deleteReleasedSnapshots;
+    }
+
+    public void setDeleteReleasedSnapshots( boolean deleteReleasedSnapshots )
+    {
+        this.deleteReleasedSnapshots = deleteReleasedSnapshots;
+    }
+
+    public boolean isEnabled()
+    {
+        return this.enabled;
+    }
+
+    public void setEnabled( boolean enabled )
+    {
+        this.enabled = enabled;
+    }
+
+    @Override
+    public boolean isConfirmed()
+    {
+        return this.confirmed;
+    }
+
+    @Override
+    public void setConfirmed( boolean confirmed )
+    {
+        this.confirmed = confirmed;
+    }
+
+    public boolean isDefaultPurgeConfiguration()
+    {
+        return this.defaultPurgeConfiguration;
+    }
+
+    public void setDefaultPurgeConfiguration( boolean defaultPurgeConfiguration )
+    {
+        this.defaultPurgeConfiguration = defaultPurgeConfiguration;
+    }
+
+    public int getRetentionCount()
+    {
+        return this.retentionCount;
+    }
+
+    public void setRetentionCount( int retentionCount )
+    {
+        this.retentionCount = retentionCount;
+    }
+
+    public int getDaysOlder()
+    {
+        return this.daysOlder;
+    }
+
+    public void setDaysOlder( int daysOlder )
+    {
+        this.daysOlder = daysOlder;
+    }
+
+    public int getScheduleId()
+    {
+        return this.scheduleId;
+    }
+
+    public void setScheduleId( int scheduleId )
+    {
+        this.scheduleId = scheduleId;
+    }
+
+    public int getPurgeConfigId()
+    {
+        return purgeConfigId;
+    }
+
+    public void setPurgeConfigId( int purgeConfigId )
+    {
+        this.purgeConfigId = purgeConfigId;
+    }
+
+    public AbstractPurgeConfiguration getPurgeConfig()
+    {
+        return this.purgeConfig;
+    }
+
+    public void setPurgeConfig( AbstractPurgeConfiguration purgeConfig )
+    {
+        this.purgeConfig = purgeConfig;
+    }
+
+    public Map<Integer, String> getSchedules()
+    {
+        return this.schedules;
+    }
+
+    public void setSchedules( Map<Integer, String> schedules )
+    {
+        this.schedules = schedules;
+    }
+
+    public List<String> getDirectoryTypes()
+    {
+        return this.directoryTypes;
+    }
+
+    public void setDirectoryTypes( List<String> directoryTypes )
+    {
+        this.directoryTypes = directoryTypes;
+    }
+
+    private AbstractPurgeConfiguration setupPurgeConfiguration( AbstractPurgeConfiguration purgeConfiguration )
+        throws Exception
+    {
+        return buildDirPurgeConfiguration();
+    }
+
+    public String getBuildAgentUrl()
+    {
+        return buildAgentUrl;
+    }
+
+    public void setBuildAgentUrl( String buildAgentUrl )
+    {
+        this.buildAgentUrl = buildAgentUrl;
+    }
+
+    public List<String> getBuildAgentUrls()
+    {
+        return buildAgentUrls;
+    }
+
+    public void setBuildAgentUrls( List<String> buildAgentUrls )
+    {
+        this.buildAgentUrls = buildAgentUrls;
+    }
+
+    private DistributedDirectoryPurgeConfiguration buildDirPurgeConfiguration()
+        throws Exception
+    {
+        DistributedDirectoryPurgeConfiguration dirPurge = (DistributedDirectoryPurgeConfiguration) purgeConfig;
+        dirPurge.setDeleteAll( this.deleteAll );
+        dirPurge.setEnabled( this.enabled );
+        dirPurge.setDaysOlder( this.daysOlder );
+        dirPurge.setRetentionCount( this.retentionCount );
+        dirPurge.setDirectoryType( this.directoryType );
+        dirPurge.setDefaultPurge( this.defaultPurgeConfiguration );
+        dirPurge.setBuildAgentUrl( buildAgentUrl );
+
+        // escape xml to prevent xss attacks
+        dirPurge.setDescription( StringEscapeUtils.escapeXml( StringEscapeUtils.unescapeXml( this.description ) ) );
+
+        if ( scheduleId > 0 )
+        {
+            Schedule schedule = getContinuum().getSchedule( scheduleId );
+            dirPurge.setSchedule( schedule );
+        }
+
+        return dirPurge;
+    }
+
+    private void updateDefaultPurgeConfiguration()
+        throws Exception
+    {
+        DirectoryPurgeConfiguration dirPurge = purgeConfigService.getDefaultPurgeConfigurationForDirectoryType(
+            directoryType );
+
+        if ( dirPurge != null && dirPurge.getId() != purgeConfig.getId() )
+        {
+            dirPurge.setDefaultPurge( false );
+            purgeConfigService.updateDirectoryPurgeConfiguration( dirPurge );
+        }
+    }
+
+    public SecureActionBundle getSecureActionBundle()
+        throws SecureActionException
+    {
+        SecureActionBundle bundle = new SecureActionBundle();
+        bundle.setRequiresAuthentication( true );
+        bundle.addRequiredAuthorization( ContinuumRoleConstants.CONTINUUM_MANAGE_PURGING, Resource.GLOBAL );
+
+        return bundle;
+    }
+}
diff --git a/continuum-webapp/src/main/java/org/apache/continuum/web/action/admin/LocalRepositoryAction.java b/continuum-webapp/src/main/java/org/apache/continuum/web/action/admin/LocalRepositoryAction.java
index 9a0177a..6ed2312 100644
--- a/continuum-webapp/src/main/java/org/apache/continuum/web/action/admin/LocalRepositoryAction.java
+++ b/continuum-webapp/src/main/java/org/apache/continuum/web/action/admin/LocalRepositoryAction.java
@@ -19,168 +19,164 @@
  * under the License.
  */
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
+import com.opensymphony.xwork2.Preparable;
 import org.apache.continuum.model.repository.LocalRepository;
 import org.apache.continuum.model.repository.RepositoryPurgeConfiguration;
 import org.apache.continuum.purge.ContinuumPurgeManager;
 import org.apache.continuum.purge.PurgeConfigurationService;
 import org.apache.continuum.repository.RepositoryService;
 import org.apache.continuum.taskqueue.manager.TaskQueueManager;
+import org.apache.continuum.web.util.AuditLog;
+import org.apache.continuum.web.util.AuditLogConstants;
 import org.apache.maven.continuum.model.project.ProjectGroup;
 import org.apache.maven.continuum.security.ContinuumRoleConstants;
 import org.apache.maven.continuum.web.action.ContinuumConfirmAction;
-import org.apache.struts2.ServletActionContext;
 import org.codehaus.plexus.redback.rbac.Resource;
 import org.codehaus.redback.integration.interceptor.SecureAction;
 import org.codehaus.redback.integration.interceptor.SecureActionBundle;
 import org.codehaus.redback.integration.interceptor.SecureActionException;
 
-import com.opensymphony.xwork2.Preparable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 /**
  * @author Maria Catherine Tan
  * @version $Id$
- * @since 25 jul 07
  * @plexus.component role="com.opensymphony.xwork2.Action" role-hint="localRepository"
+ * @since 25 jul 07
  */
 public class LocalRepositoryAction
     extends ContinuumConfirmAction
     implements Preparable, SecureAction
 {
     private static final String LAYOUT_DEFAULT = "default";
-    
+
     private static final String LAYOUT_LEGACY = "legacy";
-    
+
     private boolean confirmed;
 
     private boolean defaultRepo;
-    
+
     private LocalRepository repository;
-    
+
     private List<LocalRepository> repositories;
-    
+
     private List<ProjectGroup> groups;
-    
+
     private List<String> layouts;
-    
+
     private Map<String, Boolean> defaultPurgeMap;
-    
-    private String message;
-    
+
     /**
      * @plexus.requirement
      */
     private RepositoryService repositoryService;
-    
+
     /**
      * @plexus.requirement
      */
     private PurgeConfigurationService purgeConfigService;
-    
+
     public void prepare()
         throws Exception
     {
         super.prepare();
-        
+
         layouts = new ArrayList<String>();
         layouts.add( LAYOUT_DEFAULT );
         layouts.add( LAYOUT_LEGACY );
     }
-    
+
     public String input()
         throws Exception
     {
         defaultRepo = false;
-        
+
         if ( repository != null && repository.getId() > 0 )
         {
             repository = repositoryService.getLocalRepository( repository.getId() );
-            
+
             if ( repository.getName().equals( "DEFAULT" ) )
             {
                 defaultRepo = true;
             }
         }
-        
+
         return INPUT;
     }
-    
+
     public String list()
         throws Exception
     {
-        String errorMessage = ServletActionContext.getRequest().getParameter( "errorMessage" );
-        
-        if ( errorMessage != null )
-        {
-            addActionError( errorMessage );
-        }
-        
         repositories = repositoryService.getAllLocalRepositories();
-        
+
         defaultPurgeMap = new HashMap<String, Boolean>();
-        
+
         for ( LocalRepository repo : repositories )
         {
             // get default purge config of repository
-            RepositoryPurgeConfiguration purgeConfig = purgeConfigService.getDefaultPurgeConfigurationForRepository( repo.getId() );
-            
+            RepositoryPurgeConfiguration purgeConfig = purgeConfigService.getDefaultPurgeConfigurationForRepository(
+                repo.getId() );
+
             if ( purgeConfig == null )
             {
-                defaultPurgeMap.put(  repo.getName(), Boolean.FALSE );
+                defaultPurgeMap.put( repo.getName(), Boolean.FALSE );
             }
             else
             {
-                defaultPurgeMap.put(  repo.getName(), Boolean.TRUE );
+                defaultPurgeMap.put( repo.getName(), Boolean.TRUE );
             }
         }
-        
+
         return SUCCESS;
     }
-    
+
     public String save()
         throws Exception
     {
         List<LocalRepository> allRepositories = repositoryService.getAllLocalRepositories();
-        
-        for( LocalRepository repo : allRepositories )
+
+        for ( LocalRepository repo : allRepositories )
         {
             if ( repository.getId() != repo.getId() )
             {
-                if ( repository.getName().equals( repo.getName() ) )
+                if ( repository.getName().trim().equals( repo.getName() ) )
                 {
                     addActionError( getText( "repository.error.name.unique" ) );
                 }
-                
-                if ( repository.getLocation().equals( repo.getLocation() ) )
+
+                if ( repository.getLocation().trim().equals( repo.getLocation() ) )
                 {
                     addActionError( getText( "repository.error.location.unique" ) );
                 }
             }
         }
-        
+
         if ( repository.getName().trim().equals( "" ) )
         {
             addActionError( getText( "repository.error.name.cannot.be.spaces" ) );
         }
-        
+
         if ( repository.getLocation().trim().equals( "" ) )
         {
             addActionError( getText( "repository.error.location.cannot.be.spaces" ) );
         }
-        
+
         if ( hasActionErrors() )
         {
             return INPUT;
         }
-        
+
+        // trim repository name and location before saving
+        repository.setName( repository.getName().trim() );
+        repository.setLocation( repository.getLocation().trim() );
+
         if ( repository.getId() == 0 )
         {
             repository = repositoryService.addLocalRepository( repository );
-            
+
             createDefaultPurgeConfiguration();
         }
         else
@@ -192,49 +188,52 @@
                 addActionError( getText( "repository.error.save.in.use" ) );
                 return ERROR;
             }
-            
+
             LocalRepository retrievedRepo = repositoryService.getLocalRepository( repository.getId() );
-            
+
             retrievedRepo.setName( repository.getName() );
             retrievedRepo.setLocation( repository.getLocation() );
             retrievedRepo.setLayout( repository.getLayout() );
-            
+
             repositoryService.updateLocalRepository( retrievedRepo );
         }
-        
+
         return SUCCESS;
     }
-    
+
     public String remove()
         throws Exception
     {
         TaskQueueManager taskQueueManager = getContinuum().getTaskQueueManager();
+
+        repository = repositoryService.getLocalRepository( repository.getId() );
+
         if ( taskQueueManager.isRepositoryInUse( repository.getId() ) )
         {
-            message = "repository.error.remove.in.use";
-            return ERROR;
+            addActionError( getText( "repository.error.remove.in.use",
+                                     "Unable to remove local repository because it is in use" ) );
         }
-        
-        repository = repositoryService.getLocalRepository( repository.getId() );
-        
+
         if ( repository.getName().equals( "DEFAULT" ) )
         {
-            message = "repository.error.remove.default";
-            return ERROR;
+            addActionError( getText( "repository.error.remove.default", "Unable to remove default local repository" ) );
         }
-        
-        if ( confirmed )
+
+        if ( !hasActionErrors() )
         {
-            repositoryService.removeLocalRepository( repository.getId() );
+            if ( confirmed )
+            {
+                repositoryService.removeLocalRepository( repository.getId() );
+            }
+            else
+            {
+                return CONFIRM;
+            }
         }
-        else
-        {
-            return CONFIRM;
-        }
-        
+
         return SUCCESS;
     }
-    
+
     public String doPurge()
         throws Exception
     {
@@ -244,104 +243,103 @@
         // check if repository is in use
         if ( taskQueueManager.isRepositoryInUse( repository.getId() ) )
         {
-            message = "repository.error.purge.in.use";
-            return ERROR;
+            addActionError( getText( "repository.error.purge.in.use",
+                                     "Unable to purge repository because it is in use" ) );
         }
-        
-        // get default purge configuration for repository
-        RepositoryPurgeConfiguration purgeConfig = purgeConfigService.getDefaultPurgeConfigurationForRepository( repository.getId() );
-        
-        if ( purgeConfig != null )
+
+        if ( !hasActionErrors() )
         {
-            purgeManager.purgeRepository( purgeConfig );
+            // get default purge configuration for repository
+            RepositoryPurgeConfiguration purgeConfig = purgeConfigService.getDefaultPurgeConfigurationForRepository(
+                repository.getId() );
+
+            if ( purgeConfig != null )
+            {
+                purgeManager.purgeRepository( purgeConfig );
+
+                AuditLog event = new AuditLog( "Repository id=" + repository.getId(),
+                                               AuditLogConstants.PURGE_LOCAL_REPOSITORY );
+                event.setCategory( AuditLogConstants.LOCAL_REPOSITORY );
+                event.setCurrentUser( getPrincipal() );
+                event.log();
+            }
         }
-        
         return SUCCESS;
     }
-    
+
     public LocalRepository getRepository()
     {
         return this.repository;
     }
-    
+
     public void setRepository( LocalRepository repository )
     {
         this.repository = repository;
     }
-    
+
     public List<LocalRepository> getRepositories()
     {
         return this.repositories;
     }
-    
+
     public void setRepositories( List<LocalRepository> repositories )
     {
         this.repositories = repositories;
     }
-    
+
     public List<ProjectGroup> getGroups()
     {
         return this.groups;
     }
-    
+
     public void setGroups( List<ProjectGroup> groups )
     {
         this.groups = groups;
     }
-    
+
     public boolean isConfirmed()
     {
         return this.confirmed;
     }
-    
+
     public void setConfirmed( boolean confirmed )
     {
         this.confirmed = confirmed;
     }
-    
+
     public boolean isDefaultRepo()
     {
         return this.defaultRepo;
     }
-    
+
     public void setDefaultRepo( boolean defaultRepo )
     {
         this.defaultRepo = defaultRepo;
     }
-    
+
     public List<String> getLayouts()
     {
         return this.layouts;
     }
-    
+
     public Map<String, Boolean> getDefaultPurgeMap()
     {
         return this.defaultPurgeMap;
     }
-    
+
     public void setDefaultPurgeMap( Map<String, Boolean> defaultPurgeMap )
     {
         this.defaultPurgeMap = defaultPurgeMap;
     }
-    
-    public String getMessage()
-    {
-        return this.message;
-    }
-    
-    public void setMessage( String message )
-    {
-        this.message = message;
-    }
-    
+
     private void createDefaultPurgeConfiguration()
         throws Exception
     {
         RepositoryPurgeConfiguration repoPurge = new RepositoryPurgeConfiguration();
-        
+
         repoPurge.setRepository( repository );
         repoPurge.setDefaultPurge( true );
-        
+
         purgeConfigService.addRepositoryPurgeConfiguration( repoPurge );
     }
 
diff --git a/continuum-webapp/src/main/java/org/apache/continuum/web/action/admin/PurgeAction.java b/continuum-webapp/src/main/java/org/apache/continuum/web/action/admin/PurgeAction.java
new file mode 100644
index 0000000..3369608
--- /dev/null
+++ b/continuum-webapp/src/main/java/org/apache/continuum/web/action/admin/PurgeAction.java
@@ -0,0 +1,203 @@
+package org.apache.continuum.web.action.admin;
+
+/*
+ * 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 com.opensymphony.xwork2.Preparable;
+import org.apache.continuum.model.repository.DirectoryPurgeConfiguration;
+import org.apache.continuum.model.repository.DistributedDirectoryPurgeConfiguration;
+import org.apache.continuum.model.repository.RepositoryPurgeConfiguration;
+import org.apache.continuum.purge.PurgeConfigurationService;
+import org.apache.continuum.repository.RepositoryService;
+import org.apache.maven.continuum.model.project.Schedule;
+import org.apache.maven.continuum.security.ContinuumRoleConstants;
+import org.apache.maven.continuum.web.action.ContinuumConfirmAction;
+import org.apache.struts2.ServletActionContext;
+import org.codehaus.plexus.redback.rbac.Resource;
+import org.codehaus.redback.integration.interceptor.SecureAction;
+import org.codehaus.redback.integration.interceptor.SecureActionBundle;
+import org.codehaus.redback.integration.interceptor.SecureActionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author
+ * @version $Id$
+ * @plexus.component role="com.opensymphony.xwork2.Action" role-hint="purge"
+ */
+public class PurgeAction
+    extends ContinuumConfirmAction
+    implements Preparable, SecureAction
+{
+    private static final Logger logger = LoggerFactory.getLogger( PurgeConfigurationAction.class );
+
+    private static final String DISTRIBUTED_BUILD_SUCCESS = "distributed-build-success";
+
+    private static final String PURGE_TYPE_REPOSITORY = "repository";
+
+    private static final String PURGE_TYPE_DIRECTORY = "directory";
+
+    private static final String PURGE_DIRECTORY_RELEASES = "releases";
+
+    private static final String PURGE_DIRECTORY_BUILDOUTPUT = "buildOutput";
+
+    private static final String PURGE_DIRECTORY_WORKING = "working";
+
+    private Map<Integer, String> repositories;
+
+    private Map<Integer, String> schedules;
+
+    private List<RepositoryPurgeConfiguration> repoPurgeConfigs;
+
+    private List<DirectoryPurgeConfiguration> dirPurgeConfigs;
+
+    private List<DistributedDirectoryPurgeConfiguration> distributedDirPurgeConfigs;
+
+    private List<String> directoryTypes;
+
+    /**
+     * @plexus.requirement
+     */
+    private PurgeConfigurationService purgeConfigService;
+
+    /**
+     * @plexus.requirement
+     */
+    private RepositoryService repositoryService;
+
+    private Schedule sched = null;
+
+    public String display()
+        throws Exception
+    {
+        if ( schedules == null )
+        {
+            schedules = new HashMap<Integer, String>();
+
+            Collection<Schedule> allSchedules = getContinuum().getSchedules();
+
+            for ( Schedule schedule : allSchedules )
+            {
+                schedules.put( schedule.getId(), schedule.getName() );
+            }
+        }
+        if ( getContinuum().getConfiguration().isDistributedBuildEnabled() )
+        {
+            String errorMessage = ServletActionContext.getRequest().getParameter( "errorMessage" );
+
+            if ( errorMessage != null )
+            {
+                addActionError( getText( errorMessage ) );
+            }
+            distributedDirPurgeConfigs = purgeConfigService.getAllDistributedDirectoryPurgeConfigurations();
+
+            return DISTRIBUTED_BUILD_SUCCESS;
+        }
+        else
+        {
+
+            String errorMessage = ServletActionContext.getRequest().getParameter( "errorMessage" );
+
+            if ( errorMessage != null )
+            {
+                addActionError( getText( errorMessage ) );
+            }
+
+            repoPurgeConfigs = purgeConfigService.getAllRepositoryPurgeConfigurations();
+            dirPurgeConfigs = purgeConfigService.getAllDirectoryPurgeConfigurations();
+
+            return SUCCESS;
+        }
+    }
+
+    public SecureActionBundle getSecureActionBundle()
+        throws SecureActionException
+    {
+        SecureActionBundle bundle = new SecureActionBundle();
+        bundle.setRequiresAuthentication( true );
+        bundle.addRequiredAuthorization( ContinuumRoleConstants.CONTINUUM_MANAGE_PURGING, Resource.GLOBAL );
+
+        return bundle;
+    }
+
+    public Map<Integer, String> getRepositories()
+    {
+        return repositories;
+    }
+
+    public void setRepositories( Map<Integer, String> repositories )
+    {
+        this.repositories = repositories;
+    }
+
+    public List<RepositoryPurgeConfiguration> getRepoPurgeConfigs()
+    {
+        return repoPurgeConfigs;
+    }
+
+    public void setRepoPurgeConfigs( List<RepositoryPurgeConfiguration> repoPurgeConfigs )
+    {
+        this.repoPurgeConfigs = repoPurgeConfigs;
+    }
+
+    public List<DirectoryPurgeConfiguration> getDirPurgeConfigs()
+    {
+        return dirPurgeConfigs;
+    }
+
+    public void setDirPurgeConfigs( List<DirectoryPurgeConfiguration> dirPurgeConfigs )
+    {
+        this.dirPurgeConfigs = dirPurgeConfigs;
+    }
+
+    public List<DistributedDirectoryPurgeConfiguration> getDistributedDirPurgeConfigs()
+    {
+        return distributedDirPurgeConfigs;
+    }
+
+    public void setDistributedDirPurgeConfigs( List<DistributedDirectoryPurgeConfiguration> distributedDirPurgeConfigs )
+    {
+        this.distributedDirPurgeConfigs = distributedDirPurgeConfigs;
+    }
+
+    public List<String> getDirectoryTypes()
+    {
+        return directoryTypes;
+    }
+
+    public void setDirectoryTypes( List<String> directoryTypes )
+    {
+        this.directoryTypes = directoryTypes;
+    }
+
+    public PurgeConfigurationService getPurgeConfigService()
+    {
+        return purgeConfigService;
+    }
+
+    public void setPurgeConfigService( PurgeConfigurationService purgeConfigService )
+    {
+        this.purgeConfigService = purgeConfigService;
+    }
+}
diff --git a/continuum-webapp/src/main/java/org/apache/continuum/web/action/admin/PurgeConfigurationAction.java b/continuum-webapp/src/main/java/org/apache/continuum/web/action/admin/PurgeConfigurationAction.java
index 8a187af..a87ea34 100644
--- a/continuum-webapp/src/main/java/org/apache/continuum/web/action/admin/PurgeConfigurationAction.java
+++ b/continuum-webapp/src/main/java/org/apache/continuum/web/action/admin/PurgeConfigurationAction.java
@@ -19,12 +19,8 @@
  * under the License.
  */
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
+import com.opensymphony.xwork2.Preparable;
+import org.apache.commons.lang.StringEscapeUtils;
 import org.apache.continuum.model.repository.AbstractPurgeConfiguration;
 import org.apache.continuum.model.repository.DirectoryPurgeConfiguration;
 import org.apache.continuum.model.repository.LocalRepository;
@@ -33,6 +29,8 @@
 import org.apache.continuum.purge.PurgeConfigurationService;
 import org.apache.continuum.repository.RepositoryService;
 import org.apache.continuum.taskqueue.manager.TaskQueueManager;
+import org.apache.continuum.web.util.AuditLog;
+import org.apache.continuum.web.util.AuditLogConstants;
 import org.apache.maven.continuum.configuration.ConfigurationService;
 import org.apache.maven.continuum.model.project.Schedule;
 import org.apache.maven.continuum.security.ContinuumRoleConstants;
@@ -42,87 +40,95 @@
 import org.codehaus.redback.integration.interceptor.SecureAction;
 import org.codehaus.redback.integration.interceptor.SecureActionBundle;
 import org.codehaus.redback.integration.interceptor.SecureActionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-import com.opensymphony.xwork2.Preparable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 /**
  * @author Maria Catherine Tan
  * @version $Id$
- * @since 25 jul 07
  * @plexus.component role="com.opensymphony.xwork2.Action" role-hint="purgeConfiguration"
- *
+ * @since 25 jul 07
  */
 public class PurgeConfigurationAction
     extends ContinuumConfirmAction
     implements Preparable, SecureAction
 {
+    private static final Logger logger = LoggerFactory.getLogger( PurgeConfigurationAction.class );
+
     private static final String PURGE_TYPE_REPOSITORY = "repository";
-    
+
     private static final String PURGE_TYPE_DIRECTORY = "directory";
-    
+
     private static final String PURGE_DIRECTORY_RELEASES = "releases";
-    
+
     private static final String PURGE_DIRECTORY_BUILDOUTPUT = "buildOutput";
-    
+
     private static final int DEFAULT_RETENTION_COUNT = 2;
-    
+
     private static final int DEFAULT_DAYS_OLDER = 100;
-    
+
     private String purgeType;
-    
+
     private String directoryType;
-    
+
     private String description;
-    
+
     private String message;
-    
+
     private boolean deleteAll;
-    
+
     private boolean deleteReleasedSnapshots;
-    
+
     private boolean enabled;
-    
+
     private boolean confirmed;
-    
+
     private boolean defaultPurgeConfiguration;
-    
+
     private int retentionCount;
-    
+
     private int daysOlder;
-    
+
     private int repositoryId;
-    
+
     private int scheduleId;
-    
+
     private int purgeConfigId;
-    
+
     private AbstractPurgeConfiguration purgeConfig;
-    
+
     private Map<Integer, String> repositories;
-    
+
     private Map<Integer, String> schedules;
-    
+
     private List<RepositoryPurgeConfiguration> repoPurgeConfigs;
-    
+
     private List<DirectoryPurgeConfiguration> dirPurgeConfigs;
-    
+
     private List<String> directoryTypes;
-    
+
     /**
      * @plexus.requirement
      */
     private PurgeConfigurationService purgeConfigService;
-    
+
     /**
      * @plexus.requirement
      */
     private RepositoryService repositoryService;
-    
+
+    @Override
     public void prepare()
         throws Exception
     {
         super.prepare();
-        
+
         // build schedules
         if ( schedules == null )
         {
@@ -132,35 +138,36 @@
 
             for ( Schedule schedule : allSchedules )
             {
-                schedules.put( new Integer( schedule.getId() ), schedule.getName() );
+                schedules.put( schedule.getId(), schedule.getName() );
             }
         }
-        
+
         // build repositories
         if ( repositories == null )
         {
             repositories = new HashMap<Integer, String>();
-            
+
             List<LocalRepository> allRepositories = repositoryService.getAllLocalRepositories();
-            
+
             for ( LocalRepository repository : allRepositories )
             {
-                repositories.put( new Integer( repository.getId() ), repository.getName() );
+                repositories.put( repository.getId(), repository.getName() );
             }
         }
-        
+
         directoryTypes = new ArrayList<String>();
         directoryTypes.add( PURGE_DIRECTORY_RELEASES );
         directoryTypes.add( PURGE_DIRECTORY_BUILDOUTPUT );
     }
-    
+
+    @Override
     public String input()
         throws Exception
     {
         if ( purgeConfigId != 0 )
         {
             purgeConfig = purgeConfigService.getPurgeConfiguration( purgeConfigId );
-            
+
             if ( purgeConfig instanceof RepositoryPurgeConfiguration )
             {
                 RepositoryPurgeConfiguration repoPurge = (RepositoryPurgeConfiguration) purgeConfig;
@@ -173,12 +180,12 @@
                 this.enabled = repoPurge.isEnabled();
                 this.defaultPurgeConfiguration = repoPurge.isDefaultPurge();
                 this.description = repoPurge.getDescription();
-                
+
                 if ( repoPurge.getRepository() != null )
                 {
                     this.repositoryId = repoPurge.getRepository().getId();
                 }
-                
+
                 if ( repoPurge.getSchedule() != null )
                 {
                     this.scheduleId = repoPurge.getSchedule().getId();
@@ -187,7 +194,7 @@
             else if ( purgeConfig instanceof DirectoryPurgeConfiguration )
             {
                 DirectoryPurgeConfiguration dirPurge = (DirectoryPurgeConfiguration) purgeConfig;
-                
+
                 this.purgeType = PURGE_TYPE_DIRECTORY;
                 this.daysOlder = dirPurge.getDaysOlder();
                 this.retentionCount = dirPurge.getRetentionCount();
@@ -196,7 +203,7 @@
                 this.enabled = dirPurge.isEnabled();
                 this.defaultPurgeConfiguration = dirPurge.isDefaultPurge();
                 this.description = dirPurge.getDescription();
-                
+
                 if ( dirPurge.getSchedule() != null )
                 {
                     this.scheduleId = dirPurge.getSchedule().getId();
@@ -208,26 +215,26 @@
             this.retentionCount = DEFAULT_RETENTION_COUNT;
             this.daysOlder = DEFAULT_DAYS_OLDER;
         }
-        
+
         return INPUT;
     }
-    
+
     public String list()
         throws Exception
     {
         String errorMessage = ServletActionContext.getRequest().getParameter( "errorMessage" );
-        
+
         if ( errorMessage != null )
         {
-            addActionError( errorMessage );
+            addActionError( getText( errorMessage ) );
         }
-        
+
         repoPurgeConfigs = purgeConfigService.getAllRepositoryPurgeConfigurations();
         dirPurgeConfigs = purgeConfigService.getAllDirectoryPurgeConfigurations();
-        
+
         return SUCCESS;
     }
-    
+
     public String save()
         throws Exception
     {
@@ -241,268 +248,301 @@
             {
                 purgeConfig = new DirectoryPurgeConfiguration();
             }
-            
+
             purgeConfig = setupPurgeConfiguration( purgeConfig );
-            
+
             purgeConfig = purgeConfigService.addPurgeConfiguration( purgeConfig );
         }
         else
         {
             purgeConfig = purgeConfigService.getPurgeConfiguration( purgeConfigId );
             purgeConfig = setupPurgeConfiguration( purgeConfig );
-            
+
             purgeConfigService.updatePurgeConfiguration( purgeConfig );
         }
-        
+
         if ( purgeConfig.isDefaultPurge() )
         {
             updateDefaultPurgeConfiguration();
         }
-        
+
+        if ( purgeConfig.isEnabled() && purgeConfig.getSchedule() != null )
+        {
+            getContinuum().activePurgeSchedule( purgeConfig.getSchedule() );
+        }
+
         return SUCCESS;
     }
-    
+
     public String remove()
         throws Exception
     {
-        purgeConfigService.removePurgeConfiguration( purgeConfigId );
-        
+        if ( confirmed )
+        {
+            purgeConfigService.removePurgeConfiguration( purgeConfigId );
+        }
+        else
+        {
+            return CONFIRM;
+        }
+
         return SUCCESS;
     }
-    
+
     public String purge()
         throws Exception
     {
         ContinuumPurgeManager purgeManager = getContinuum().getPurgeManager();
         TaskQueueManager taskQueueManager = getContinuum().getTaskQueueManager();
-        
+
         if ( purgeConfigId > 0 )
         {
             purgeConfig = purgeConfigService.getPurgeConfiguration( purgeConfigId );
-            
+
+            AuditLog event;
+
             if ( purgeConfig instanceof RepositoryPurgeConfiguration )
             {
                 RepositoryPurgeConfiguration repoPurge = (RepositoryPurgeConfiguration) purgeConfig;
-                
+
                 // check if repository is in use
                 if ( taskQueueManager.isRepositoryInUse( repoPurge.getRepository().getId() ) )
                 {
                     message = "repository.error.purge.in.use";
                     return ERROR;
                 }
-                
+
                 purgeManager.purgeRepository( repoPurge );
+
+                event = new AuditLog( repoPurge.getRepository().getName(), AuditLogConstants.PURGE_LOCAL_REPOSITORY );
+                event.setCategory( AuditLogConstants.LOCAL_REPOSITORY );
             }
             else
             {
                 DirectoryPurgeConfiguration dirPurge = (DirectoryPurgeConfiguration) purgeConfig;
                 purgeManager.purgeDirectory( dirPurge );
+
+                if ( dirPurge.getDirectoryType().equals( PURGE_DIRECTORY_RELEASES ) )
+                {
+                    event = new AuditLog( dirPurge.getLocation(), AuditLogConstants.PURGE_DIRECTORY_RELEASES );
+                }
+                else
+                {
+                    event = new AuditLog( dirPurge.getLocation(), AuditLogConstants.PURGE_DIRECTORY_BUILDOUTPUT );
+                }
+
+                event.setCategory( AuditLogConstants.DIRECTORY );
             }
+
+            event.setCurrentUser( getPrincipal() );
+            event.log();
         }
-        
+
         return SUCCESS;
     }
-    
+
     public String getPurgeType()
     {
         return this.purgeType;
     }
-    
+
     public void setPurgeType( String purgeType )
     {
         this.purgeType = purgeType;
     }
-    
+
     public String getDirectoryType()
     {
         return this.directoryType;
     }
-    
+
     public void setDirectoryType( String directoryType )
     {
         this.directoryType = directoryType;
     }
-    
+
     public String getDescription()
     {
         return this.description;
     }
-    
+
     public void setDescription( String description )
     {
         this.description = description;
     }
-    
+
     public String getMessage()
     {
         return this.message;
     }
-    
+
     public void setMessage( String message )
     {
         this.message = message;
     }
-    
+
     public boolean isDeleteAll()
     {
         return this.deleteAll;
     }
-    
+
     public void setDeleteAll( boolean deleteAll )
     {
         this.deleteAll = deleteAll;
     }
-    
+
     public boolean isDeleteReleasedSnapshots()
     {
         return this.deleteReleasedSnapshots;
     }
-    
+
     public void setDeleteReleasedSnapshots( boolean deleteReleasedSnapshots )
     {
         this.deleteReleasedSnapshots = deleteReleasedSnapshots;
     }
-    
+
     public boolean isEnabled()
     {
         return this.enabled;
     }
-    
+
     public void setEnabled( boolean enabled )
     {
         this.enabled = enabled;
     }
-    
+
+    @Override
     public boolean isConfirmed()
     {
         return this.confirmed;
     }
-    
+
+    @Override
     public void setConfirmed( boolean confirmed )
     {
         this.confirmed = confirmed;
     }
-    
+
     public boolean isDefaultPurgeConfiguration()
     {
         return this.defaultPurgeConfiguration;
     }
-    
+
     public void setDefaultPurgeConfiguration( boolean defaultPurgeConfiguration )
     {
         this.defaultPurgeConfiguration = defaultPurgeConfiguration;
     }
-    
+
     public int getRetentionCount()
     {
         return this.retentionCount;
     }
-    
+
     public void setRetentionCount( int retentionCount )
     {
         this.retentionCount = retentionCount;
     }
-    
+
     public int getDaysOlder()
     {
         return this.daysOlder;
     }
-    
+
     public void setDaysOlder( int daysOlder )
     {
         this.daysOlder = daysOlder;
     }
-    
+
     public int getRepositoryId()
     {
         return this.repositoryId;
     }
-    
+
     public void setRepositoryId( int repositoryId )
     {
         this.repositoryId = repositoryId;
     }
-    
+
     public int getScheduleId()
     {
         return this.scheduleId;
     }
-    
+
     public void setScheduleId( int scheduleId )
     {
         this.scheduleId = scheduleId;
     }
-    
+
     public int getPurgeConfigId()
     {
         return purgeConfigId;
     }
-    
+
     public void setPurgeConfigId( int purgeConfigId )
     {
         this.purgeConfigId = purgeConfigId;
     }
-    
+
     public AbstractPurgeConfiguration getPurgeConfig()
     {
         return this.purgeConfig;
     }
-    
+
     public void setPurgeConfig( AbstractPurgeConfiguration purgeConfig )
     {
         this.purgeConfig = purgeConfig;
     }
-    
+
     public Map<Integer, String> getRepositories()
     {
         return this.repositories;
     }
-    
+
     public void setRepositories( Map<Integer, String> repositories )
     {
         this.repositories = repositories;
     }
-    
+
     public Map<Integer, String> getSchedules()
     {
         return this.schedules;
     }
-    
+
     public void setSchedules( Map<Integer, String> schedules )
     {
         this.schedules = schedules;
     }
-    
+
     public List<RepositoryPurgeConfiguration> getRepoPurgeConfigs()
     {
         return this.repoPurgeConfigs;
     }
-    
+
     public void setRepoPurgeConfigs( List<RepositoryPurgeConfiguration> repoPurgeConfigs )
     {
         this.repoPurgeConfigs = repoPurgeConfigs;
     }
-    
+
     public List<DirectoryPurgeConfiguration> getDirPurgeConfigs()
     {
         return this.dirPurgeConfigs;
     }
-    
+
     public void setDirPurgeConfigs( List<DirectoryPurgeConfiguration> dirPurgeConfigs )
     {
         this.dirPurgeConfigs = dirPurgeConfigs;
     }
-    
+
     public List<String> getDirectoryTypes()
     {
         return this.directoryTypes;
     }
-    
+
     public void setDirectoryTypes( List<String> directoryTypes )
     {
         this.directoryTypes = directoryTypes;
     }
-    
+
     private AbstractPurgeConfiguration setupPurgeConfiguration( AbstractPurgeConfiguration purgeConfiguration )
         throws Exception
     {
@@ -515,7 +555,7 @@
             return buildDirPurgeConfiguration();
         }
     }
-    
+
     private RepositoryPurgeConfiguration buildRepoPurgeConfiguration()
         throws Exception
     {
@@ -526,24 +566,25 @@
         repoPurge.setRetentionCount( this.retentionCount );
         repoPurge.setEnabled( this.enabled );
         repoPurge.setDefaultPurge( this.defaultPurgeConfiguration );
-        repoPurge.setDescription( this.description );
+        // escape xml to prevent xss attacks
+        repoPurge.setDescription( StringEscapeUtils.escapeXml( StringEscapeUtils.unescapeXml( this.description ) ) );
         repoPurge.setDefaultPurge( this.defaultPurgeConfiguration );
-        
+
         if ( repositoryId != 0 )
         {
             LocalRepository repository = repositoryService.getLocalRepository( repositoryId );
             repoPurge.setRepository( repository );
         }
-        
+
         if ( scheduleId > 0 )
         {
             Schedule schedule = getContinuum().getSchedule( scheduleId );
             repoPurge.setSchedule( schedule );
         }
-        
+
         return repoPurge;
     }
-    
+
     private DirectoryPurgeConfiguration buildDirPurgeConfiguration()
         throws Exception
     {
@@ -552,19 +593,20 @@
         dirPurge.setEnabled( this.enabled );
         dirPurge.setDaysOlder( this.daysOlder );
         dirPurge.setRetentionCount( this.retentionCount );
-        dirPurge.setDescription( this.description );
+        // escape xml to prevent xss attacks
+        dirPurge.setDescription( StringEscapeUtils.escapeXml( StringEscapeUtils.unescapeXml( this.description ) ) );
         dirPurge.setDirectoryType( this.directoryType );
         dirPurge.setDefaultPurge( this.defaultPurgeConfiguration );
-        
+
         if ( scheduleId > 0 )
         {
             Schedule schedule = getContinuum().getSchedule( scheduleId );
             dirPurge.setSchedule( schedule );
         }
-        
+
         ConfigurationService configService = getContinuum().getConfiguration();
         String path = null;
-        
+
         if ( this.directoryType.equals( PURGE_DIRECTORY_RELEASES ) )
         {
             path = configService.getWorkingDirectory().getAbsolutePath();
@@ -573,19 +615,20 @@
         {
             path = configService.getBuildOutputDirectory().getAbsolutePath();
         }
-        
+
         dirPurge.setLocation( path );
-        
+
         return dirPurge;
     }
-    
+
     private void updateDefaultPurgeConfiguration()
         throws Exception
     {
         if ( purgeConfig instanceof RepositoryPurgeConfiguration )
         {
-            RepositoryPurgeConfiguration repoPurge = purgeConfigService.getDefaultPurgeConfigurationForRepository( repositoryId );
-            
+            RepositoryPurgeConfiguration repoPurge = purgeConfigService.getDefaultPurgeConfigurationForRepository(
+                repositoryId );
+
             if ( repoPurge != null && repoPurge.getId() != purgeConfig.getId() )
             {
                 repoPurge.setDefaultPurge( false );
@@ -594,8 +637,9 @@
         }
         else if ( purgeConfig instanceof DirectoryPurgeConfiguration )
         {
-            DirectoryPurgeConfiguration dirPurge = purgeConfigService.getDefaultPurgeConfigurationForDirectoryType( directoryType );
-            
+            DirectoryPurgeConfiguration dirPurge = purgeConfigService.getDefaultPurgeConfigurationForDirectoryType(
+                directoryType );
+
             if ( dirPurge != null && dirPurge.getId() != purgeConfig.getId() )
             {
                 dirPurge.setDefaultPurge( false );
@@ -603,7 +647,7 @@
             }
         }
     }
-    
+
     public SecureActionBundle getSecureActionBundle()
         throws SecureActionException
     {
diff --git a/continuum-webapp/src/main/java/org/apache/continuum/web/action/error/HttpError.java b/continuum-webapp/src/main/java/org/apache/continuum/web/action/error/HttpError.java
new file mode 100644
index 0000000..394cad1
--- /dev/null
+++ b/continuum-webapp/src/main/java/org/apache/continuum/web/action/error/HttpError.java
@@ -0,0 +1,51 @@
+package org.apache.continuum.web.action.error;
+
+/*
+ * 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 org.apache.maven.continuum.web.action.ContinuumActionSupport;
+
+/**
+ * AboutAction:
+ *
+ * @author: Emmanuel Venisse <evenisse@apache.org>
+ * @version: $Id:$
+ * @plexus.component role="com.opensymphony.xwork2.Action" role-hint="httpError"
+ */
+public class HttpError
+    extends ContinuumActionSupport
+{
+    private int errorCode;
+
+    public String execute()
+        throws Exception
+    {
+        return SUCCESS;
+    }
+
+    public int getErrorCode()
+    {
+        return errorCode;
+    }
+
+    public void setErrorCode( int errorCode )
+    {
+        this.errorCode = errorCode;
+    }
+}
diff --git a/continuum-webapp/src/main/java/org/apache/continuum/web/integration/Struts2PlexusInSpringObjectFactory.java b/continuum-webapp/src/main/java/org/apache/continuum/web/integration/Struts2PlexusInSpringObjectFactory.java
new file mode 100644
index 0000000..0660ec4
--- /dev/null
+++ b/continuum-webapp/src/main/java/org/apache/continuum/web/integration/Struts2PlexusInSpringObjectFactory.java
@@ -0,0 +1,120 @@
+package org.apache.continuum.web.integration;
+
+/*
+  ~ Licensed 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 com.opensymphony.xwork2.Action;
+import com.opensymphony.xwork2.Result;
+import com.opensymphony.xwork2.inject.Container;
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.interceptor.Interceptor;
+import com.opensymphony.xwork2.validator.Validator;
+import org.apache.struts2.StrutsConstants;
+import org.apache.struts2.spring.StrutsSpringObjectFactory;
+import org.codehaus.plexus.spring.PlexusToSpringUtils;
+
+import javax.servlet.ServletContext;
+import java.util.Map;
+
+public class Struts2PlexusInSpringObjectFactory
+        extends StrutsSpringObjectFactory
+{
+    @Inject
+    public Struts2PlexusInSpringObjectFactory(
+            @Inject(value=StrutsConstants.STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE,required=false) String autoWire,
+            @Inject(value=StrutsConstants.STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE_ALWAYS_RESPECT,required=false) String alwaysAutoWire,
+            @Inject(value=StrutsConstants.STRUTS_OBJECTFACTORY_SPRING_USE_CLASS_CACHE,required=false) String useClassCacheStr,
+            @Inject(value=StrutsConstants.STRUTS_OBJECTFACTORY_SPRING_ENABLE_AOP_SUPPORT,required=false) String enableAopSupport,
+            @Inject ServletContext servletContext,
+            @Inject(StrutsConstants.STRUTS_DEVMODE) String devMode,
+            @Inject Container container)
+    {
+        super(autoWire, alwaysAutoWire, useClassCacheStr, enableAopSupport, servletContext, devMode, container);
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @see com.opensymphony.xwork2.spring.SpringObjectFactory#buildBean(java.lang.String, java.util.Map)
+     */
+    @Override
+    public Object buildBean( String name, Map map )
+            throws Exception
+    {
+        String id = PlexusToSpringUtils.buildSpringId(Action.class, name);
+        if ( appContext.containsBean( id ) )
+        {
+            return super.buildBean( id, map );
+        }
+
+        id = PlexusToSpringUtils.buildSpringId( Result.class, name );
+        if ( appContext.containsBean( id ) )
+        {
+            return super.buildBean( id, map );
+        }
+
+        id = PlexusToSpringUtils.buildSpringId( Interceptor.class, name );
+        if ( appContext.containsBean( id ) )
+        {
+            return super.buildBean( id, map );
+        }
+
+        id = PlexusToSpringUtils.buildSpringId( Validator.class, name );
+        if ( appContext.containsBean( id ) )
+        {
+            return super.buildBean( id, map );
+        }
+        return super.buildBean( name, map );
+    }
+
+    public Validator buildValidator( String className, Map params, Map extraContext )
+            throws Exception
+    {
+        String id = PlexusToSpringUtils.buildSpringId( Validator.class, className );
+        if ( appContext.containsBean( id ) )
+        {
+            return (Validator) appContext.getBean( id );
+        }
+        return super.buildValidator( className, params, extraContext );
+    }
+
+    @Override
+    public Class getClassInstance( String className )
+            throws ClassNotFoundException
+    {
+        String id = PlexusToSpringUtils.buildSpringId( Action.class, className );
+        if ( appContext.containsBean( id ) )
+        {
+            return appContext.getType( id );
+        }
+
+        id = PlexusToSpringUtils.buildSpringId( Result.class, className );
+        if ( appContext.containsBean( id ) )
+        {
+            return appContext.getType( id );
+        }
+
+        id = PlexusToSpringUtils.buildSpringId( Interceptor.class, className );
+        if ( appContext.containsBean( id ) )
+        {
+            return appContext.getType( id );
+        }
+        id = PlexusToSpringUtils.buildSpringId( Validator.class, className );
+        if ( appContext.containsBean( id ) )
+        {
+            return appContext.getType( id );
+        }
+        return super.getClassInstance( className );
+    }
+}
diff --git a/continuum-webapp/src/main/java/org/apache/continuum/web/startup/ContinuumStartup.java b/continuum-webapp/src/main/java/org/apache/continuum/web/startup/ContinuumStartup.java
index a79e262..92c6736 100644
--- a/continuum-webapp/src/main/java/org/apache/continuum/web/startup/ContinuumStartup.java
+++ b/continuum-webapp/src/main/java/org/apache/continuum/web/startup/ContinuumStartup.java
@@ -1,3 +1,5 @@
+package org.apache.continuum.web.startup;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,14 +18,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.continuum.web.startup;
-
-import javax.servlet.ServletContextEvent;
-import javax.servlet.ServletContextListener;
 
 import org.apache.continuum.builder.distributed.manager.DistributedBuildManager;
+import org.apache.continuum.buildmanager.BuildsManager;
 import org.apache.maven.continuum.Continuum;
-import org.apache.maven.continuum.ContinuumException;
 import org.codehaus.plexus.spring.PlexusToSpringUtils;
 import org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor;
 import org.slf4j.Logger;
@@ -31,18 +29,21 @@
 import org.springframework.web.context.WebApplicationContext;
 import org.springframework.web.context.support.WebApplicationContextUtils;
 
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
 /**
  * @author <a href="mailto:olamy@apache.org">olamy</a>
- * @since 15 mars 2008
  * @version $Id$
+ * @since 15 mars 2008
  */
 public class ContinuumStartup
     implements ServletContextListener
 {
 
     private Logger log = LoggerFactory.getLogger( getClass() );
-    
-    /** 
+
+    /**
      * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent)
      */
     public void contextDestroyed( ServletContextEvent sce )
@@ -51,40 +52,36 @@
 
     }
 
-    /** 
+    /**
      * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent)
      */
     public void contextInitialized( ServletContextEvent sce )
     {
-        WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext( sce
-            .getServletContext() );
+        WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(
+            sce.getServletContext() );
 
         // to simulate Plexus load on start with Spring
         Continuum continuum = (Continuum) wac.getBean( PlexusToSpringUtils.buildSpringId( Continuum.class ) );
 
-        TaskQueueExecutor buildProject = (TaskQueueExecutor) wac.getBean( PlexusToSpringUtils
-            .buildSpringId( TaskQueueExecutor.class, "build-project" ) );
+        BuildsManager buildsManager = (BuildsManager) wac.getBean( PlexusToSpringUtils.buildSpringId(
+            BuildsManager.class, "parallel" ) );
 
-        TaskQueueExecutor checkOutProject = (TaskQueueExecutor) wac.getBean( PlexusToSpringUtils
-            .buildSpringId( TaskQueueExecutor.class, "check-out-project" ) );
+        TaskQueueExecutor prepareRelease = (TaskQueueExecutor) wac.getBean( PlexusToSpringUtils.buildSpringId(
+            TaskQueueExecutor.class, "prepare-release" ) );
 
-        TaskQueueExecutor prepareRelease = (TaskQueueExecutor) wac.getBean( PlexusToSpringUtils
-            .buildSpringId( TaskQueueExecutor.class, "prepare-release" ) );
+        TaskQueueExecutor performRelease = (TaskQueueExecutor) wac.getBean( PlexusToSpringUtils.buildSpringId(
+            TaskQueueExecutor.class, "perform-release" ) );
 
-        TaskQueueExecutor performRelease = (TaskQueueExecutor) wac.getBean( PlexusToSpringUtils
-            .buildSpringId( TaskQueueExecutor.class, "perform-release" ) );
+        TaskQueueExecutor rollbackRelease = (TaskQueueExecutor) wac.getBean( PlexusToSpringUtils.buildSpringId(
+            TaskQueueExecutor.class, "rollback-release" ) );
 
-        TaskQueueExecutor rollbackRelease = (TaskQueueExecutor) wac.getBean( PlexusToSpringUtils
-            .buildSpringId( TaskQueueExecutor.class, "rollback-release" ) );        
-        
-        TaskQueueExecutor purge = (TaskQueueExecutor) wac.getBean( PlexusToSpringUtils
-            .buildSpringId( TaskQueueExecutor.class, "purge" ) );
+        TaskQueueExecutor purge = (TaskQueueExecutor) wac.getBean( PlexusToSpringUtils.buildSpringId(
+            TaskQueueExecutor.class, "purge" ) );
 
-        TaskQueueExecutor prepareBuildProject = (TaskQueueExecutor) wac.getBean( PlexusToSpringUtils
-            .buildSpringId( TaskQueueExecutor.class, "prepare-build-project" ) );
+        TaskQueueExecutor prepareBuildProject = (TaskQueueExecutor) wac.getBean( PlexusToSpringUtils.buildSpringId(
+            TaskQueueExecutor.class, "prepare-build-project" ) );
 
-        DistributedBuildManager distributedBuildManager = (DistributedBuildManager) wac.getBean( PlexusToSpringUtils
-            .buildSpringId( DistributedBuildManager.class ) );
+        DistributedBuildManager distributedBuildManager = (DistributedBuildManager) wac.getBean(
+            PlexusToSpringUtils.buildSpringId( DistributedBuildManager.class ) );
     }
-
 }
diff --git a/continuum-webapp/src/main/java/org/apache/continuum/web/util/AuditLog.java b/continuum-webapp/src/main/java/org/apache/continuum/web/util/AuditLog.java
new file mode 100644
index 0000000..9db7137
--- /dev/null
+++ b/continuum-webapp/src/main/java/org/apache/continuum/web/util/AuditLog.java
@@ -0,0 +1,114 @@
+package org.apache.continuum.web.util;
+
+/*
+ * 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 org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+
+/**
+ * @author Jevica Arianne B. Zurbano
+ * @version $Id: AuditLog.java
+ * @since 17 apr 09
+ */
+public class AuditLog
+{
+    private Logger logger = LoggerFactory.getLogger( AuditLog.class.getName() );
+
+    private String action;
+
+    private String category;
+
+    private String resource;
+
+    private String currentUser;
+
+    public AuditLog( String action )
+    {
+        this.action = action;
+    }
+
+    public AuditLog( String resource, String action )
+    {
+        this.action = action;
+        this.resource = resource;
+    }
+
+    public void setCurrentUser( String currentUser )
+    {
+        this.currentUser = currentUser;
+    }
+
+    public String getCurrentUser()
+    {
+        return currentUser;
+    }
+
+    public void setResource( String resource )
+    {
+        this.resource = resource;
+    }
+
+    public String getResource()
+    {
+        return resource;
+    }
+
+    public void setCategory( String category )
+    {
+        this.category = category;
+    }
+
+    public String getCategory()
+    {
+        return category;
+    }
+
+    public void setAction( String action )
+    {
+        this.action = action;
+    }
+
+    public String getAction()
+    {
+        return action;
+    }
+
+    public void log()
+    {
+        if ( currentUser != null )
+        {
+            MDC.put( "security.currentUser", currentUser );
+        }
+
+        if ( resource != null )
+        {
+            if ( category != null )
+            {
+                logger.info( category + " " + resource + " - " + action );
+            }
+            else
+            {
+                logger.info( resource + " - " + action );
+            }
+        }
+    }
+}
+
diff --git a/continuum-webapp/src/main/java/org/apache/continuum/web/util/AuditLogConstants.java b/continuum-webapp/src/main/java/org/apache/continuum/web/util/AuditLogConstants.java
new file mode 100644
index 0000000..64e1c0a
--- /dev/null
+++ b/continuum-webapp/src/main/java/org/apache/continuum/web/util/AuditLogConstants.java
@@ -0,0 +1,124 @@
+package org.apache.continuum.web.util;
+
+/*
+ * 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.
+ */
+
+/**
+ * @author Jevica Arianne B. Zurbano
+ * @version $Id: AuditLogConstants.java
+ * @since 09 apr 09
+ */
+public class AuditLogConstants
+{
+    public static final String PROJECT = "PROJECT";
+
+    public static final String SCHEDULE = "BUILD_SCHEDULE";
+
+    public static final String TEMPLATE = "BUILD_TEMPLATE";
+
+    public static final String BUILD_DEFINITION = "BUILD_DEFINITION";
+
+    public static final String PROJECT_GROUP = "PROJECT_GROUP";
+
+    public static final String BUILD_RESULT = "BUILD_RESULT";
+
+    public static final String BUILD_QUEUE = "BUILD_QUEUE";
+
+    public static final String BUILD_AGENT = "BUILD_AGENT";
+
+    public static final String LOCAL_REPOSITORY = "LOCAL_REPOSITORY";
+
+    public static final String DIRECTORY = "DIRECTORY";
+
+    // events
+    public static final String FORCE_BUILD = "Forced Project Build";
+
+    public static final String CANCEL_BUILD = "Cancelled Project Build";
+
+    public static final String CI_BUILD = "Scheduled Project Build";
+
+    public static final String PREPARE_RELEASE = "Prepare Project Release";
+
+    public static final String PERFORM_RELEASE = "Perform Project Release";
+
+    public static final String ROLLBACK_RELEASE = "Rollback Project Release";
+
+    public static final String ADD_M2_PROJECT = "Added M2 Project";
+
+    public static final String ADD_M2_PROJECT_FAILED = "Failed Adding M2 Project";
+
+    public static final String ADD_M1_PROJECT = "Added M1 Project";
+
+    public static final String ADD_M1_PROJECT_FAILED = "Failed Adding M1 Project";
+
+    public static final String ADD_PROJECT = "Added Project";
+
+    public static final String MODIFY_PROJECT = "Modified Project";
+
+    public static final String REMOVE_PROJECT = "Removed Project";
+
+    public static final String ADD_PROJECT_GROUP = "Added Project Group";
+
+    public static final String MODIFY_PROJECT_GROUP = "Modified Project Group";
+
+    public static final String REMOVE_PROJECT_GROUP = "Removed Project Group";
+
+    public static final String MODIFY_SCHEDULE = "Modified Build Schedule";
+
+    public static final String ADD_SCHEDULE = "Added Build Schedule";
+
+    public static final String REMOVE_SCHEDULE = "Removed Build Schedule";
+
+    public static final String ADD_GOAL = "Added Build Definition";
+
+    public static final String MODIFY_GOAL = "Modified Build Definition";
+
+    public static final String REMOVE_GOAL = "Removed Build Definition";
+
+    public static final String ADD_TEMPLATE = "Added Build Definition Template";
+
+    public static final String MODIFY_TEMPLATE = "Modified Build Definition Template";
+
+    public static final String REMOVE_TEMPLATE = "Removed Build Definition Template";
+
+    public static final String REMOVE_BUILD_RESULT = "Removed Build Result";
+
+    public static final String ADD_BUILD_QUEUE = "Added Build Queue";
+
+    public static final String REMOVE_BUILD_QUEUE = "Removed Build Queue";
+
+    public static final String PURGE_LOCAL_REPOSITORY = "Purged Local Repository";
+
+    public static final String PURGE_DIRECTORY_RELEASES = "Purged Releases Directory";
+
+    public static final String PURGE_DIRECTORY_BUILDOUTPUT = "Purged Build Output Directory";
+
+    public static final String ADD_BUILD_AGENT = "Added Build Agent";
+
+    public static final String ADD_BUILD_AGENT_GROUP = "Added Build Agent Group";
+
+    public static final String MODIFY_BUILD_AGENT = "Modified Build Agent";
+
+    public static final String MODIFY_BUILD_AGENT_GROUP = "Modified Build Agent Group";
+
+    public static final String REMOVE_BUILD_AGENT = "Removed Build Agent";
+
+    public static final String REMOVE_BUILD_AGENT_GROUP = "Removed Build Agent Group";
+}
+
diff --git a/continuum-webapp/src/main/java/org/apache/continuum/web/util/GenerateRecipentNotifier.java b/continuum-webapp/src/main/java/org/apache/continuum/web/util/GenerateRecipentNotifier.java
new file mode 100644
index 0000000..ad3dbf7
--- /dev/null
+++ b/continuum-webapp/src/main/java/org/apache/continuum/web/util/GenerateRecipentNotifier.java
@@ -0,0 +1,97 @@
+package org.apache.continuum.web.util;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.maven.continuum.model.project.ProjectNotifier;
+import org.apache.maven.continuum.notification.AbstractContinuumNotifier;
+import org.codehaus.plexus.util.StringUtils;
+
+import java.util.Map;
+
+/*
+ * 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.
+ */
+
+/**
+ * @author José Morales Martínez
+ * @version $Id$
+ */
+public final class GenerateRecipentNotifier
+{
+    private GenerateRecipentNotifier()
+    {
+
+    }
+
+    @SuppressWarnings( "unchecked" )
+    public static String generate( ProjectNotifier notifier )
+    {
+        Map<String, String> configuration = notifier.getConfiguration();
+        String recipent = "unknown";
+        if ( ( "mail".equals( notifier.getType() ) ) || ( "msn".equals( notifier.getType() ) ) ||
+            ( "jabber".equals( notifier.getType() ) ) )
+        {
+            if ( StringUtils.isNotEmpty( configuration.get( AbstractContinuumNotifier.ADDRESS_FIELD ) ) )
+            {
+                recipent = configuration.get( AbstractContinuumNotifier.ADDRESS_FIELD );
+            }
+            if ( StringUtils.isNotEmpty( configuration.get( AbstractContinuumNotifier.COMMITTER_FIELD ) ) )
+            {
+                if ( Boolean.parseBoolean( configuration.get( AbstractContinuumNotifier.COMMITTER_FIELD ) ) )
+                {
+                    if ( "unknown".equals( recipent ) )
+                    {
+                        recipent = "latest committers";
+                    }
+                    else
+                    {
+                        recipent += ", " + "latest committers";
+                    }
+                }
+            }
+            if ( StringUtils.isNotEmpty( configuration.get( AbstractContinuumNotifier.DEVELOPER_FIELD ) ) )
+            {
+                if ( Boolean.parseBoolean( configuration.get( AbstractContinuumNotifier.DEVELOPER_FIELD ) ) )
+                {
+                    if ( "unknown".equals( recipent ) )
+                    {
+                        recipent = "project developers";
+                    }
+                    else
+                    {
+                        recipent += ", " + "project developers";
+                    }
+                }
+            }
+        }
+        if ( "irc".equals( notifier.getType() ) )
+        {
+            recipent = configuration.get( "host" );
+            if ( configuration.get( "port" ) != null )
+            {
+                recipent = recipent + ":" + configuration.get( "port" );
+            }
+            recipent = recipent + ":" + configuration.get( "channel" );
+        }
+        if ( "wagon".equals( notifier.getType() ) )
+        {
+            recipent = configuration.get( "url" );
+        }
+        // escape the characters, it may contain characters possible for an XSS attack
+        return StringEscapeUtils.escapeXml( recipent );
+    }
+}
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AboutAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AboutAction.java
index f59e848..0e210a2 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AboutAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AboutAction.java
@@ -23,7 +23,7 @@
  * AboutAction:
  *
  * @author: Jesse McConnell <jmcconnell@apache.org>
- * @version: $ID:$
+ * @version: $Id$
  * @plexus.component role="com.opensymphony.xwork2.Action"
  * role-hint="about"
  */
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AbstractBuildAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AbstractBuildAction.java
index ed29d44..4ae9c1e 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AbstractBuildAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AbstractBuildAction.java
@@ -1,3 +1,5 @@
+package org.apache.maven.continuum.web.action;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,45 +18,44 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.continuum.web.action;
 
+import org.apache.continuum.buildmanager.BuildManagerException;
+import org.apache.continuum.buildmanager.BuildsManager;
 import org.apache.continuum.taskqueue.BuildProjectTask;
 import org.apache.maven.continuum.model.project.BuildResult;
 import org.apache.maven.continuum.project.ContinuumProjectState;
-import org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor;
+
+import java.util.Map;
+import java.util.Set;
 
 /**
  * @author <a href="mailto:olamy@apache.org">olamy</a>
- * @since 5 oct. 07
  * @version $Id$
+ * @since 5 oct. 07
  */
 public abstract class AbstractBuildAction
     extends ContinuumConfirmAction
 {
-    
     private int projectId;
-    
+
     private boolean canDelete = true;
-    
-    /**
-     * @plexus.requirement role-hint='build-project'
-     */
-    private TaskQueueExecutor taskQueueExecutor; 
-    
-    
-    
-    protected TaskQueueExecutor getTaskQueueExecutor()
+
+    protected boolean canRemoveBuildResult( BuildResult buildResult )
+        throws BuildManagerException
     {
-        return this.taskQueueExecutor;
-    }
-    
-    protected boolean canRemoveBuildResult(BuildResult buildResult)
-    {
-        BuildProjectTask buildProjectTask = (BuildProjectTask) getTaskQueueExecutor().getCurrentTask();
-        if ( buildProjectTask != null && buildResult != null )
+        BuildsManager buildsManager = getContinuum().getBuildsManager();
+
+        Map<String, BuildProjectTask> currentBuilds = buildsManager.getCurrentBuilds();
+        Set<String> keySet = currentBuilds.keySet();
+        for ( String key : keySet )
         {
-            return !( buildResult.getState() == ContinuumProjectState.BUILDING && ( buildProjectTask
-                .getBuildDefinitionId() == buildResult.getBuildDefinition().getId() && buildProjectTask.getProjectId() == this.getProjectId() ) );
+            BuildProjectTask buildProjectTask = currentBuilds.get( key );
+            if ( buildProjectTask != null && buildResult != null )
+            {
+                return !( buildResult.getState() == ContinuumProjectState.BUILDING &&
+                    ( buildProjectTask.getBuildDefinitionId() == buildResult.getBuildDefinition().getId() &&
+                        buildProjectTask.getProjectId() == this.getProjectId() ) );
+            }
         }
         return true;
     }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AbstractBuildDefinitionAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AbstractBuildDefinitionAction.java
index b2c4ffb..f3791c7 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AbstractBuildDefinitionAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AbstractBuildDefinitionAction.java
@@ -31,7 +31,7 @@
  * @since 16 sept. 07
  */
 public abstract class AbstractBuildDefinitionAction
-    extends ContinuumActionSupport
+    extends ContinuumConfirmAction
 {
 
     protected BuildDefinitionSummary generateBuildDefinitionSummary( BuildDefinition buildDefinition )
@@ -53,7 +53,7 @@
         }
         bds.setDescription( buildDefinition.getDescription() );
         bds.setType( buildDefinition.getType() );
-        bds.setAlwaysBuild( buildDefinition.isBuildFresh() || buildDefinition.isAlwaysBuild() );
+        bds.setAlwaysBuild( buildDefinition.isAlwaysBuild() );
         return bds;
     }
 
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AddMavenOneProjectAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AddMavenOneProjectAction.java
index f695d1f..18469f2 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AddMavenOneProjectAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AddMavenOneProjectAction.java
@@ -19,11 +19,13 @@
  * under the License.
  */
 
-import java.io.File;
-
+import org.apache.continuum.web.util.AuditLog;
+import org.apache.continuum.web.util.AuditLogConstants;
 import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
 
+import java.io.File;
+
 /**
  * Add a Maven 1 project to Continuum.
  *
@@ -40,8 +42,22 @@
                                                         boolean scmUseCache )
         throws ContinuumException
     {
-        return getContinuum().addMavenOneProject( pomUrl, selectedProjectGroup, checkProtocol, scmUseCache,
-                                                  this.getBuildDefinitionTemplateId() );
+        ContinuumProjectBuildingResult result = getContinuum().addMavenOneProject( pomUrl, selectedProjectGroup,
+                                                                                   checkProtocol, scmUseCache,
+                                                                                   this.getBuildDefinitionTemplateId() );
+
+        AuditLog event = new AuditLog( hidePasswordInUrl( pomUrl ), AuditLogConstants.ADD_M1_PROJECT );
+        event.setCategory( AuditLogConstants.PROJECT );
+        event.setCurrentUser( getPrincipal() );
+
+        if ( result == null || result.hasErrors() )
+        {
+            event.setAction( AuditLogConstants.ADD_M1_PROJECT_FAILED );
+        }
+
+        event.log();
+
+        return result;
     }
 
     /**
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AddMavenProjectAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AddMavenProjectAction.java
index 1344696..9f677f8 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AddMavenProjectAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AddMavenProjectAction.java
@@ -19,19 +19,12 @@
  * under the License.
  */
 
-import java.io.File;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLEncoder;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-
-import javax.servlet.http.HttpServletRequest;
-
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.config.ConfigurationManager;
+import com.opensymphony.xwork2.config.providers.XWorkConfigurationProvider;
+import com.opensymphony.xwork2.inject.Container;
+import com.opensymphony.xwork2.util.ValueStack;
+import com.opensymphony.xwork2.util.ValueStackFactory;
 import org.apache.commons.io.FileUtils;
 import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.builddefinition.BuildDefinitionServiceException;
@@ -42,6 +35,17 @@
 import org.apache.struts2.interceptor.ServletRequestAware;
 import org.codehaus.plexus.util.StringUtils;
 
+import java.io.File;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import javax.servlet.http.HttpServletRequest;
+
 /**
  * Action to add a Maven project to Continuum, either Maven 1 or Maven 2.
  *
@@ -66,7 +70,7 @@
 
     private String scmPassword;
 
-    private Collection projectGroups;
+    private Collection<ProjectGroup> projectGroups;
 
     private String projectGroupName;
 
@@ -81,11 +85,11 @@
     private List<BuildDefinitionTemplate> buildDefinitionTemplates;
 
     private int buildDefinitionTemplateId;
-    
+
     private List<String> errorMessages = new ArrayList<String>();
 
     private HttpServletRequest httpServletRequest;
-    
+
     public String execute()
         throws ContinuumException, BuildDefinitionServiceException
     {
@@ -108,6 +112,21 @@
             return REQUIRES_AUTHORIZATION;
         }
 
+        // ctan: hack for WW-3161
+        if ( ActionContext.getContext() == null )
+        {
+            // This fix allow initialization of ActionContext.getContext() to avoid NPE
+
+            ConfigurationManager configurationManager = new ConfigurationManager();
+            configurationManager.addContainerProvider( new XWorkConfigurationProvider() );
+            com.opensymphony.xwork2.config.Configuration config = configurationManager.getConfiguration();
+            Container container = config.getContainer();
+
+            ValueStack stack = container.getInstance( ValueStackFactory.class ).createValueStack();
+            stack.getContext().put( ActionContext.CONTAINER, container );
+            ActionContext.setContext( new ActionContext( stack.getContext() ) );
+        }
+
         boolean checkProtocol = true;
 
         if ( !StringUtils.isEmpty( pomUrl ) )
@@ -120,21 +139,26 @@
                     String encoding = this.httpServletRequest.getCharacterEncoding();
                     if ( StringUtils.isEmpty( encoding ) )
                     {
-                         encoding = System.getProperty( "file.encoding" );
+                        encoding = System.getProperty( "file.encoding" );
                     }
 
+                    // URL encode username and password so things like @ or : or / don't corrupt URL
                     String encodedUsername = URLEncoder.encode( scmUsername, encoding );
                     String encodedPassword = URLEncoder.encode( scmPassword, encoding );
 
                     StringBuffer urlBuffer = new StringBuffer();
                     urlBuffer.append( url.getProtocol() ).append( "://" );
-                    urlBuffer.append( encodedUsername ).append( ':' ).append( encodedPassword ).append( '@' )
-                        .append( url.getHost() );
+                    urlBuffer.append( encodedUsername ).append( ':' ).append( encodedPassword ).append( '@' ).append(
+                        url.getHost() );
                     if ( url.getPort() != -1 )
                     {
                         urlBuffer.append( ":" ).append( url.getPort() );
                     }
                     urlBuffer.append( url.getPath() );
+                    if ( url.getQuery() != null )
+                    {
+                        urlBuffer.append( "?" + url.getQuery() );
+                    }
 
                     pom = urlBuffer.toString();
                 }
@@ -153,7 +177,7 @@
                 addActionError( getText( "add.project.unknown.error" ) );
                 return doDefault();
             }
-            
+
         }
         else
         {
@@ -224,7 +248,7 @@
 
         if ( result.getProjectGroups() != null && !result.getProjectGroups().isEmpty() )
         {
-            this.setProjectGroupId( ( (ProjectGroup) result.getProjectGroups().get( 0 ) ).getId() );
+            this.setProjectGroupId( ( result.getProjectGroups().get( 0 ) ).getId() );
             return "projectGroupSummary";
         }
 
@@ -271,17 +295,16 @@
             addActionError( authzE.getMessage() );
             return REQUIRES_AUTHORIZATION;
         }
-        Collection allProjectGroups = getContinuum().getAllProjectGroups();
-        projectGroups = new ArrayList();
+        Collection<ProjectGroup> allProjectGroups = getContinuum().getAllProjectGroups();
+        projectGroups = new ArrayList<ProjectGroup>();
 
         ProjectGroup defaultGroup = new ProjectGroup();
         defaultGroup.setId( DEFINED_BY_POM_GROUP_ID );
         defaultGroup.setName( "Defined by POM" );
         projectGroups.add( defaultGroup );
 
-        for ( Iterator i = allProjectGroups.iterator(); i.hasNext(); )
+        for ( ProjectGroup pg : allProjectGroups )
         {
-            ProjectGroup pg = (ProjectGroup) i.next();
             if ( isAuthorizedToAddProjectToGroup( pg.getName() ) )
             {
                 projectGroups.add( pg );
@@ -293,9 +316,25 @@
         return INPUT;
     }
 
+    protected String hidePasswordInUrl( String url )
+    {
+        int indexAt = url.indexOf( "@" );
+
+        if ( indexAt < 0 )
+        {
+            return url;
+        }
+
+        String s = url.substring( 0, indexAt );
+
+        int pos = s.lastIndexOf( ":" );
+
+        return s.substring( 0, pos + 1 ) + "*****" + url.substring( indexAt );
+    }
+
     private void initializeProjectGroupName()
     {
-        if ( disableGroupSelection == true && selectedProjectGroup != DEFINED_BY_POM_GROUP_ID )
+        if ( disableGroupSelection && selectedProjectGroup != DEFINED_BY_POM_GROUP_ID )
         {
             try
             {
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AddMavenTwoProjectAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AddMavenTwoProjectAction.java
index 160c867..edb6463 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AddMavenTwoProjectAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AddMavenTwoProjectAction.java
@@ -19,20 +19,21 @@
  * under the License.
  */
 
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.io.IOException;
-import java.util.List;
-
+import org.apache.continuum.web.util.AuditLog;
+import org.apache.continuum.web.util.AuditLogConstants;
 import org.apache.maven.continuum.ContinuumException;
-import org.apache.maven.continuum.builddefinition.BuildDefinitionServiceException;
 import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
 import org.apache.maven.model.Model;
 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
+import org.codehaus.plexus.util.ReaderFactory;
 import org.codehaus.plexus.util.StringUtils;
 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
 
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.List;
+
 /**
  * Add a Maven 2 project to Continuum.
  *
@@ -51,7 +52,7 @@
 
     public static final String FILE_SCHEME = "file:/";
 
-    private boolean nonRecursiveProject;
+    private String checkoutOption;
 
     protected ContinuumProjectBuildingResult doExecute( String pomUrl, int selectedProjectGroup, boolean checkProtocol,
                                                         boolean scmUseCache )
@@ -60,7 +61,7 @@
         ContinuumProjectBuildingResult result = null;
 
         // TODO: remove this part once uploading of an m2 project with modules is supported ( CONTINUUM-1098 )
-        if ( checkProtocol == false )
+        if ( !checkProtocol )
         {
             MavenXpp3Reader m2pomReader = new MavenXpp3Reader();
 
@@ -79,7 +80,7 @@
                     filePath = filePath.substring( FILE_SCHEME.length() );
                 }
 
-                Model model = m2pomReader.read( new FileReader( filePath ) );
+                Model model = m2pomReader.read( ReaderFactory.newXmlReader( new File( filePath ) ) );
 
                 List modules = model.getModules();
 
@@ -103,20 +104,44 @@
             }
         }
 
+        boolean nonRecursiveProject;
+        boolean checkoutInSingleDirectory;
+
+        if ( "checkoutInSingleDirectory".equals( checkoutOption ) )
+        {
+            checkoutInSingleDirectory = true;
+            nonRecursiveProject = false;
+        }
+        else if ( "nonRecursiveProject".equals( checkoutOption ) )
+        {
+            checkoutInSingleDirectory = false;
+            nonRecursiveProject = true;
+        }
+        else
+        {
+            checkoutInSingleDirectory = false;
+            nonRecursiveProject = false;
+        }
+
         if ( result == null )
         {
             result = getContinuum().addMavenTwoProject( pomUrl, selectedProjectGroup, checkProtocol, scmUseCache,
-                                                        !this.isNonRecursiveProject(), this.getBuildDefinitionTemplateId() );
+                                                        !nonRecursiveProject, this.getBuildDefinitionTemplateId(),
+                                                        checkoutInSingleDirectory );
         }
 
+        AuditLog event = new AuditLog( hidePasswordInUrl( pomUrl ), AuditLogConstants.ADD_M2_PROJECT );
+        event.setCategory( AuditLogConstants.PROJECT );
+        event.setCurrentUser( getPrincipal() );
+
+        if ( result == null || result.hasErrors() )
+        {
+            event.setAction( AuditLogConstants.ADD_M2_PROJECT_FAILED );
+        }
+
+        event.log();
         return result;
     }
-    
-    public String doDefault()
-        throws BuildDefinitionServiceException
-    {
-        return super.doDefault();
-    }
 
     /**
      * @deprecated Use {@link #getPomFile()} instead
@@ -150,14 +175,13 @@
         setPomUrl( pomUrl );
     }
 
-    public boolean isNonRecursiveProject()
+    public String getCheckoutOption()
     {
-        return nonRecursiveProject;
+        return checkoutOption;
     }
 
-    public void setNonRecursiveProject( boolean nonRecursiveProject )
+    public void setCheckoutOption( String checkoutOption )
     {
-        this.nonRecursiveProject = nonRecursiveProject;
+        this.checkoutOption = checkoutOption;
     }
-
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AddProjectAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AddProjectAction.java
index ba2de97..bfa5ec6 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AddProjectAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AddProjectAction.java
@@ -19,8 +19,15 @@
  * under the License.
  */
 
-import com.opensymphony.xwork2.Validateable;
-import org.apache.maven.continuum.Continuum;
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.config.ConfigurationManager;
+import com.opensymphony.xwork2.config.providers.XWorkConfigurationProvider;
+import com.opensymphony.xwork2.inject.Container;
+import com.opensymphony.xwork2.util.ValueStack;
+import com.opensymphony.xwork2.util.ValueStackFactory;
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.continuum.web.util.AuditLog;
+import org.apache.continuum.web.util.AuditLogConstants;
 import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.builddefinition.BuildDefinitionServiceException;
 import org.apache.maven.continuum.model.project.BuildDefinitionTemplate;
@@ -31,10 +38,11 @@
 import org.apache.maven.continuum.profile.ProfileService;
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
 import org.codehaus.plexus.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Iterator;
 import java.util.List;
 
 /**
@@ -44,10 +52,13 @@
  */
 public class AddProjectAction
     extends ContinuumActionSupport
-    implements Validateable
 {
+    private static final Logger logger = LoggerFactory.getLogger( AddProjectAction.class );
+
     private String projectName;
 
+    private String projectDescription;
+
     private String projectVersion;
 
     private String projectScmUrl;
@@ -60,7 +71,7 @@
 
     private String projectType;
 
-    private Collection projectGroups;
+    private Collection<ProjectGroup> projectGroups;
 
     private int selectedProjectGroup;
 
@@ -83,66 +94,13 @@
 
     private List<BuildDefinitionTemplate> buildDefinitionTemplates;
 
-    public void validate()
-    {
-        boolean projectNameAlreadyExist = false;
-
-        clearErrorsAndMessages();
-        
-        try
-        {
-            if ( ( projectName.trim().length() > 0 ) && ( projectVersion.trim().length() > 0 ) && ( projectScmUrl.trim().length() > 0 ) )
-            {
-            Iterator<Project> projects = getContinuum().getProjects().iterator();
-            while ( projects.hasNext() )
-            {
-                Project project = projects.next();
-                // CONTINUUM-1445
-                if ( StringUtils.equalsIgnoreCase( project.getName(), projectName.trim() ) &&
-                    StringUtils.equalsIgnoreCase( project.getVersion(), projectVersion.trim() ) &&
-                    StringUtils.equalsIgnoreCase( project.getScmUrl(), projectScmUrl.trim() ) )
-                {
-                    projectNameAlreadyExist = true;
-                    break;
-                }
-            }
-            if ( projectNameAlreadyExist )
-            {
-                addActionError( getText( "projectName.already.exist.error" ) );
-                this.input();
-            }
-            }
-            else
-            {
-                if ( !( projectName.trim().length() > 0 ) )
-                {
-                    addActionError( getText( "addProject.name.required" ) );
-                }
-                if ( !( projectVersion.trim().length() > 0 ) )
-                {
-                    addActionError( getText( "addProject.version.required" ) );
-                }
-                if ( !( projectScmUrl.trim().length() > 0 ) )
-                {
-                    addActionError( getText( "addProject.scmUrl.required" ) );
-                }
-                this.input();
-            }
-        }
-        catch ( ContinuumException e )
-        {
-            getLogger().error( e.getMessage(), e );
-        }
-        catch ( BuildDefinitionServiceException e )
-        {
-            getLogger().error( e.getMessage(), e );
-        }
-    }
+    private boolean emptyProjectGroups;
 
     public String add()
-        throws ContinuumException
+        throws ContinuumException, ProfileException, BuildDefinitionServiceException
     {
         initializeProjectGroupName();
+        initializeActionContext();
 
         try
         {
@@ -161,13 +119,45 @@
             return REQUIRES_AUTHORIZATION;
         }
 
+        if ( isEmptyProjectGroups() )
+        {
+            addActionError( getText( "addProject.projectGroup.required" ) );
+        }
+
+        String projectNameTrim = projectName.trim();
+        String versionTrim = projectVersion.trim();
+        String scmTrim = projectScmUrl.trim();
+        //TODO: Instead of get all projects then test them, it would be better to check it directly in the DB
+        for ( Project project : getContinuum().getProjects() )
+        {
+            // CONTINUUM-1445
+            if ( StringUtils.equalsIgnoreCase( project.getName(), projectNameTrim ) &&
+                StringUtils.equalsIgnoreCase( project.getVersion(), versionTrim ) &&
+                StringUtils.equalsIgnoreCase( project.getScmUrl(), scmTrim ) )
+            {
+                addActionError( getText( "projectName.already.exist.error" ) );
+                break;
+            }
+        }
+
+        if ( hasActionErrors() )
+        {
+            return INPUT;
+        }
+
         Project project = new Project();
 
-        project.setName( projectName.trim() );
+        project.setName( projectNameTrim );
 
-        project.setVersion( projectVersion.trim() );
+        if ( projectDescription != null )
+        {
+            project.setDescription( StringEscapeUtils.escapeXml( StringEscapeUtils.unescapeXml(
+                projectDescription.trim() ) ) );
+        }
 
-        project.setScmUrl( projectScmUrl.trim() );
+        project.setVersion( versionTrim );
+
+        project.setScmUrl( scmTrim );
 
         project.setScmUsername( projectScmUsername );
 
@@ -187,6 +177,11 @@
             return "projectGroupSummary";
         }
 
+        AuditLog event = new AuditLog( "Project id=" + project.getId(), AuditLogConstants.ADD_PROJECT );
+        event.setCategory( AuditLogConstants.PROJECT );
+        event.setCurrentUser( getPrincipal() );
+        event.log();
+
         return SUCCESS;
     }
 
@@ -210,33 +205,26 @@
             return REQUIRES_AUTHORIZATION;
         }
 
-        projectGroups = new ArrayList();
+        projectGroups = new ArrayList<ProjectGroup>();
 
-        Collection allProjectGroups = getContinuum().getAllProjectGroups();
+        Collection<ProjectGroup> allProjectGroups = getContinuum().getAllProjectGroups();
 
-        for ( Iterator i = allProjectGroups.iterator(); i.hasNext(); )
+        for ( ProjectGroup pg : allProjectGroups )
         {
-            ProjectGroup pg = (ProjectGroup) i.next();
-
             if ( isAuthorizedToAddProjectToGroup( pg.getName() ) )
             {
                 projectGroups.add( pg );
             }
         }
 
-        if ( !disableGroupSelection )
-        {
-            selectedProjectGroup = getContinuum().getProjectGroupByGroupId( Continuum.DEFAULT_PROJECT_GROUP_GROUP_ID )
-                .getId();
-        }
         this.profiles = profileService.getAllProfiles();
         buildDefinitionTemplates = getContinuum().getBuildDefinitionService().getAllBuildDefinitionTemplate();
-        return SUCCESS;
+        return INPUT;
     }
 
     private void initializeProjectGroupName()
     {
-        if ( disableGroupSelection == true )
+        if ( disableGroupSelection )
         {
             try
             {
@@ -249,6 +237,24 @@
         }
     }
 
+    private void initializeActionContext()
+    {
+        // ctan: hack for WW-3161
+        if ( ActionContext.getContext() == null )
+        {
+            // This fix allow initialization of ActionContext.getContext() to avoid NPE
+
+            ConfigurationManager configurationManager = new ConfigurationManager();
+            configurationManager.addContainerProvider( new XWorkConfigurationProvider() );
+            com.opensymphony.xwork2.config.Configuration config = configurationManager.getConfiguration();
+            Container container = config.getContainer();
+
+            ValueStack stack = container.getInstance( ValueStackFactory.class ).createValueStack();
+            stack.getContext().put( ActionContext.CONTAINER, container );
+            ActionContext.setContext( new ActionContext( stack.getContext() ) );
+        }
+    }
+
     public String getProjectName()
     {
         return projectName;
@@ -319,12 +325,12 @@
         this.projectVersion = projectVersion;
     }
 
-    public Collection getProjectGroups()
+    public Collection<ProjectGroup> getProjectGroups()
     {
         return projectGroups;
     }
 
-    public void setProjectGroups( Collection projectGroups )
+    public void setProjectGroups( Collection<ProjectGroup> projectGroups )
     {
         this.projectGroups = projectGroups;
     }
@@ -421,4 +427,24 @@
             return false;
         }
     }
+
+    public String getProjectDescription()
+    {
+        return projectDescription;
+    }
+
+    public void setProjectDescription( String projectDescription )
+    {
+        this.projectDescription = projectDescription;
+    }
+
+    public boolean isEmptyProjectGroups()
+    {
+        return emptyProjectGroups;
+    }
+
+    public void setEmptyProjectGroups( boolean emptyProjectGroups )
+    {
+        this.emptyProjectGroups = emptyProjectGroups;
+    }
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AddProjectGroupAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AddProjectGroupAction.java
index b8467ac..98f7644 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AddProjectGroupAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/AddProjectGroupAction.java
@@ -19,16 +19,18 @@
  * under the License.
  */
 
-import java.util.Iterator;
-import java.util.List;
-
+import org.apache.commons.lang.StringEscapeUtils;
 import org.apache.continuum.model.repository.LocalRepository;
 import org.apache.continuum.repository.RepositoryServiceException;
+import org.apache.continuum.web.util.AuditLog;
+import org.apache.continuum.web.util.AuditLogConstants;
 import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.model.project.ProjectGroup;
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-import com.opensymphony.xwork2.Validateable;
+import java.util.List;
 
 /**
  * @author Henry Isidro <hisidro@exist.com>
@@ -36,74 +38,26 @@
  */
 public class AddProjectGroupAction
     extends ContinuumActionSupport
-    implements Validateable
 {
+    private static final Logger logger = LoggerFactory.getLogger( AddProjectGroupAction.class );
+
     private String name;
 
     private String groupId;
 
     private String description;
-    
+
     private int repositoryId;
-    
+
     private List<LocalRepository> repositories;
 
     public void prepare()
         throws Exception
     {
         super.prepare();
-        
+
         repositories = getContinuum().getRepositoryService().getAllLocalRepositories();
     }
-    
-    public void validate()
-    {
-        clearErrorsAndMessages();
-        if ( name != null && name.equals( "" ) )
-        {
-            addActionError( getText( "projectGroup.error.name.required" ) );
-        }
-        else if ( name != null && name.trim().equals( "" ) )
-        {
-            addActionError( getText( "projectGroup.error.name.cannot.be.spaces" ) );
-        }
-        else if ( name != null && !name.equals( "" ) )
-        {
-            Iterator iterator = getContinuum().getAllProjectGroups().iterator();
-            while ( iterator.hasNext() )
-            {
-                ProjectGroup projectGroup = (ProjectGroup) iterator.next();
-                if ( name.equals( projectGroup.getName() ) )
-                {
-                    addActionError( getText( "projectGroup.error.name.already.exists" ) );
-                    break;
-                }
-            }
-        }
-        if ( groupId != null && groupId.equals( "" ) )
-        {
-            addActionError( getText( "projectGroup.error.groupId.required" ) );
-        }
-        else if ( groupId != null && groupId.trim().equals( "" ) )
-        {
-            addActionError( getText( "projectGroup.error.groupId.cannot.be.spaces" ) );
-        }
-        else
-        {
-            try
-            {
-                if ( getContinuum().getProjectGroupByGroupId( groupId ) != null )
-                {
-                    addActionError( getText( "projectGroup.error.groupId.already.exists" ) );
-                }
-            }
-            catch ( ContinuumException e )
-            {
-                //since we want to add a new project group, we should be getting
-                //this exception
-            }
-        }
-    }
 
     public String execute()
     {
@@ -117,14 +71,41 @@
             return REQUIRES_AUTHORIZATION;
         }
 
+        for ( ProjectGroup projectGroup : getContinuum().getAllProjectGroups() )
+        {
+            if ( name.equals( projectGroup.getName() ) )
+            {
+                addActionError( getText( "projectGroup.error.name.already.exists" ) );
+                break;
+            }
+        }
+
+        try
+        {
+            if ( getContinuum().getProjectGroupByGroupId( groupId ) != null )
+            {
+                addActionError( getText( "projectGroup.error.groupId.already.exists" ) );
+            }
+        }
+        catch ( ContinuumException e )
+        {
+            //since we want to add a new project group, we should be getting
+            //this exception
+        }
+
+        if ( hasActionErrors() )
+        {
+            return INPUT;
+        }
+
         ProjectGroup projectGroup = new ProjectGroup();
 
-        projectGroup.setName( name );
+        projectGroup.setName( name.trim() );
 
-        projectGroup.setGroupId( groupId );
+        projectGroup.setGroupId( groupId.trim() );
 
-        projectGroup.setDescription( description );
-        
+        projectGroup.setDescription( StringEscapeUtils.escapeXml( StringEscapeUtils.unescapeXml( description ) ) );
+
         try
         {
             if ( repositoryId > 0 )
@@ -135,8 +116,8 @@
         }
         catch ( RepositoryServiceException e )
         {
-            getLogger().error( "Error adding project group" + e.getLocalizedMessage() );
-            
+            logger.error( "Error adding project group" + e.getLocalizedMessage() );
+
             return ERROR;
         }
 
@@ -146,11 +127,17 @@
         }
         catch ( ContinuumException e )
         {
-            getLogger().error( "Error adding project group: " + e.getLocalizedMessage() );
+            logger.error( "Error adding project group: " + e.getLocalizedMessage() );
 
             return ERROR;
         }
 
+        AuditLog event = new AuditLog( "Project Group id=" + projectGroup.getId(),
+                                       AuditLogConstants.ADD_PROJECT_GROUP );
+        event.setCategory( AuditLogConstants.PROJECT );
+        event.setCurrentUser( getPrincipal() );
+        event.log();
+
         return SUCCESS;
     }
 
@@ -198,22 +185,22 @@
     {
         this.name = name;
     }
-    
+
     public int getRepositoryId()
     {
         return repositoryId;
     }
-    
+
     public void setRepositoryId( int repositoryId )
     {
         this.repositoryId = repositoryId;
     }
-    
+
     public List<LocalRepository> getRepositories()
     {
         return repositories;
     }
-    
+
     public void setRepositories( List<LocalRepository> repositories )
     {
         this.repositories = repositories;
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/BuildDefinitionAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/BuildDefinitionAction.java
index ec79bff..4f6889a 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/BuildDefinitionAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/BuildDefinitionAction.java
@@ -19,16 +19,13 @@
  * under the License.
  */
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.continuum.web.util.AuditLog;
+import org.apache.continuum.web.util.AuditLogConstants;
 import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.builddefinition.BuildDefinitionService;
 import org.apache.maven.continuum.builddefinition.BuildDefinitionServiceException;
+import org.apache.maven.continuum.builddefinition.BuildDefinitionUpdatePolicyConstants;
 import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.Project;
@@ -40,6 +37,12 @@
 import org.apache.maven.continuum.web.exception.ContinuumActionException;
 import org.codehaus.plexus.util.StringUtils;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 /**
  * BuildDefinitionAction:
  *
@@ -72,12 +75,14 @@
 
     private boolean buildFresh;
 
-    private Map schedules;
+    private Map<Integer, String> schedules;
 
-    private List profiles;
+    private List<Profile> profiles;
 
     private boolean groupBuildDefinition = false;
 
+    private boolean groupBuildView = false;
+
     private String projectGroupName = "";
 
     private int profileId;
@@ -89,12 +94,17 @@
     private String buildDefinitionType;
 
     private boolean alwaysBuild;
-    
+
+    private int updatePolicy = BuildDefinitionUpdatePolicyConstants.UPDATE_DESCRIPTION_ALWAYS;
+
+    private Map<Integer, String> buildDefinitionUpdatePolicies;
+
     /**
      * @plexus.requirement
-     */    
-    private BuildDefinitionService buildDefinitionService;    
-    
+     */
+    private BuildDefinitionService buildDefinitionService;
+
+    @Override
     public void prepare()
         throws Exception
     {
@@ -102,15 +112,13 @@
 
         if ( schedules == null )
         {
-            schedules = new HashMap();
+            schedules = new HashMap<Integer, String>();
 
-            Collection allSchedules = getContinuum().getSchedules();
+            Collection<Schedule> allSchedules = getContinuum().getSchedules();
 
-            for ( Iterator i = allSchedules.iterator(); i.hasNext(); )
+            for ( Schedule schedule : allSchedules )
             {
-                Schedule schedule = (Schedule) i.next();
-
-                schedules.put( new Integer( schedule.getId() ), schedule.getName() );
+                schedules.put( schedule.getId(), schedule.getName() );
             }
         }
 
@@ -125,6 +133,15 @@
         buildDefinitionTypes.add( ContinuumBuildExecutorConstants.MAVEN_ONE_BUILD_EXECUTOR );
         buildDefinitionTypes.add( ContinuumBuildExecutorConstants.MAVEN_TWO_BUILD_EXECUTOR );
         buildDefinitionTypes.add( ContinuumBuildExecutorConstants.SHELL_BUILD_EXECUTOR );
+
+        buildDefinitionUpdatePolicies = new HashMap<Integer, String>();
+        String text = getText( "buildDefinition.updatePolicy.always" );
+        buildDefinitionUpdatePolicies.put( BuildDefinitionUpdatePolicyConstants.UPDATE_DESCRIPTION_ALWAYS, text );
+        text = getText( "buildDefinition.updatePolicy.never" );
+        buildDefinitionUpdatePolicies.put( BuildDefinitionUpdatePolicyConstants.UPDATE_DESCRIPTION_NEVER, text );
+        text = getText( "buildDefinition.updatePolicy.newPom" );
+        buildDefinitionUpdatePolicies.put( BuildDefinitionUpdatePolicyConstants.UPDATE_DESCRIPTION_ONLY_FOR_NEW_POM,
+                                           text );
     }
 
     /**
@@ -132,6 +149,7 @@
      *
      * @return action result
      */
+    @Override
     public String input()
         throws ContinuumException, ContinuumStoreException, BuildDefinitionServiceException
     {
@@ -145,11 +163,11 @@
                 }
                 else
                 {
-                    List projects = getContinuum().getProjectGroupWithProjects( projectGroupId ).getProjects();
+                    List<Project> projects = getContinuum().getProjectGroupWithProjects( projectGroupId ).getProjects();
 
                     if ( projects.size() > 0 )
                     {
-                        Project project = (Project) projects.get( 0 );
+                        Project project = projects.get( 0 );
                         executor = project.getExecutorId();
                     }
                 }
@@ -181,6 +199,7 @@
                 description = buildDefinition.getDescription();
                 buildDefinitionType = buildDefinition.getType();
                 alwaysBuild = buildDefinition.isAlwaysBuild();
+                updatePolicy = buildDefinition.getUpdatePolicy();
             }
             else
             {
@@ -198,10 +217,10 @@
                 else
                 {
                     checkAddGroupBuildDefinitionAuthorization( getProjectGroupName() );
-                    List bds = getContinuum().getBuildDefinitionsForProjectGroup( projectGroupId );
+                    List<BuildDefinition> bds = getContinuum().getBuildDefinitionsForProjectGroup( projectGroupId );
                     if ( bds != null && !bds.isEmpty() )
                     {
-                        preDefinedBuildFile = ( (BuildDefinition) bds.get( 0 ) ).getBuildFile();
+                        preDefinedBuildFile = bds.get( 0 ).getBuildFile();
                     }
                 }
 
@@ -209,22 +228,23 @@
                 {
                     if ( ContinuumBuildExecutorConstants.MAVEN_TWO_BUILD_EXECUTOR.equals( executor ) )
                     {
-                        buildFile = ( (BuildDefinition) buildDefinitionService
-                            .getDefaultMavenTwoBuildDefinitionTemplate().getBuildDefinitions().get( 0 ) )
-                            .getBuildFile();
+                        buildFile =
+                            ( (BuildDefinition) buildDefinitionService.getDefaultMavenTwoBuildDefinitionTemplate().getBuildDefinitions().get(
+                                0 ) ).getBuildFile();
                         buildDefinitionType = ContinuumBuildExecutorConstants.MAVEN_TWO_BUILD_EXECUTOR;
                     }
                     else if ( ContinuumBuildExecutorConstants.MAVEN_ONE_BUILD_EXECUTOR.equals( executor ) )
                     {
-                        buildFile = ( (BuildDefinition) buildDefinitionService
-                            .getDefaultMavenOneBuildDefinitionTemplate().getBuildDefinitions().get( 0 ) )
-                            .getBuildFile();
+                        buildFile =
+                            ( (BuildDefinition) buildDefinitionService.getDefaultMavenOneBuildDefinitionTemplate().getBuildDefinitions().get(
+                                0 ) ).getBuildFile();
                         buildDefinitionType = ContinuumBuildExecutorConstants.MAVEN_ONE_BUILD_EXECUTOR;
                     }
                     else if ( ContinuumBuildExecutorConstants.ANT_BUILD_EXECUTOR.equals( executor ) )
                     {
-                        buildFile = ( (BuildDefinition) buildDefinitionService.getDefaultAntBuildDefinitionTemplate()
-                            .getBuildDefinitions().get( 0 ) ).getBuildFile();
+                        buildFile =
+                            ( (BuildDefinition) buildDefinitionService.getDefaultAntBuildDefinitionTemplate().getBuildDefinitions().get(
+                                0 ) ).getBuildFile();
                         buildDefinitionType = ContinuumBuildExecutorConstants.ANT_BUILD_EXECUTOR;
                     }
                     else
@@ -285,6 +305,9 @@
         throws ContinuumException, ProfileException
     {
 
+        AuditLog event = null;
+        String resource = "Project id=" + projectId + ":" + goals + " " + arguments;
+
         try
         {
             if ( buildDefinitionId == 0 )
@@ -292,12 +315,16 @@
                 checkAddProjectBuildDefinitionAuthorization( getProjectGroupName() );
 
                 getContinuum().addBuildDefinitionToProject( projectId, getBuildDefinitionFromInput() );
+
+                event = new AuditLog( resource, AuditLogConstants.ADD_GOAL );
             }
             else
             {
                 checkModifyProjectBuildDefinitionAuthorization( getProjectGroupName() );
 
                 getContinuum().updateBuildDefinitionForProject( projectId, getBuildDefinitionFromInput() );
+
+                event = new AuditLog( resource, AuditLogConstants.MODIFY_GOAL );
             }
         }
         catch ( ContinuumActionException cae )
@@ -311,6 +338,15 @@
             return REQUIRES_AUTHORIZATION;
         }
 
+        event.setCategory( AuditLogConstants.BUILD_DEFINITION );
+        event.setCurrentUser( getPrincipal() );
+        event.log();
+
+        if ( groupBuildView )
+        {
+            return "success_group";
+        }
+
         return SUCCESS;
     }
 
@@ -352,10 +388,36 @@
 
         if ( projectId != 0 )
         {
+            String resource = "Project id=" + projectId + ":" + goals + " " + arguments;
+            AuditLog event = null;
+            if ( buildDefinitionId == 0 )
+            {
+                event = new AuditLog( resource, AuditLogConstants.ADD_GOAL );
+            }
+            else
+            {
+                event = new AuditLog( resource, AuditLogConstants.MODIFY_GOAL );
+            }
+            event.setCategory( AuditLogConstants.BUILD_DEFINITION );
+            event.setCurrentUser( getPrincipal() );
+            event.log();
             return SUCCESS;
         }
         else
         {
+            String resource = "Project Group id=" + projectGroupId + ":" + goals + " " + arguments;
+            AuditLog event = null;
+            if ( buildDefinitionId == 0 )
+            {
+                event = new AuditLog( resource, AuditLogConstants.ADD_GOAL );
+            }
+            else
+            {
+                event = new AuditLog( resource, AuditLogConstants.MODIFY_GOAL );
+            }
+            event.setCategory( AuditLogConstants.BUILD_DEFINITION );
+            event.setCurrentUser( getPrincipal() );
+            event.log();
             return "success_group";
         }
     }
@@ -371,6 +433,12 @@
             {
                 getContinuum().removeBuildDefinitionFromProject( projectId, buildDefinitionId );
 
+                String resource = "Project id=" + projectId + ":" + goals + " " + arguments;
+                AuditLog event = new AuditLog( resource, AuditLogConstants.REMOVE_GOAL );
+                event.setCategory( AuditLogConstants.BUILD_DEFINITION );
+                event.setCurrentUser( getPrincipal() );
+                event.log();
+
                 return SUCCESS;
             }
             else
@@ -399,6 +467,12 @@
             {
                 getContinuum().removeBuildDefinitionFromProjectGroup( projectGroupId, buildDefinitionId );
 
+                String resource = "Project Group id=" + projectGroupId + ":" + goals + " " + arguments;
+                AuditLog event = new AuditLog( resource, AuditLogConstants.REMOVE_GOAL );
+                event.setCategory( AuditLogConstants.BUILD_DEFINITION );
+                event.setCurrentUser( getPrincipal() );
+                event.log();
+
                 return SUCCESS;
             }
             else
@@ -452,9 +526,10 @@
                 buildDefinition.setProfile( profile );
             }
         }
-        buildDefinition.setDescription( description );
+        buildDefinition.setDescription( StringEscapeUtils.escapeXml( StringEscapeUtils.unescapeXml( description ) ) );
         buildDefinition.setType( buildDefinitionType );
         buildDefinition.setAlwaysBuild( alwaysBuild );
+        buildDefinition.setUpdatePolicy( updatePolicy );
         return buildDefinition;
     }
 
@@ -463,7 +538,7 @@
         return buildDefinitionId;
     }
 
-    public void setBuildDefinitionId( int buildDefinitionId )
+    public void setBuildDefinitionId( final int buildDefinitionId )
     {
         this.buildDefinitionId = buildDefinitionId;
     }
@@ -473,7 +548,7 @@
         return projectId;
     }
 
-    public void setProjectId( int projectId )
+    public void setProjectId( final int projectId )
     {
         this.projectId = projectId;
     }
@@ -483,7 +558,7 @@
         return projectGroupId;
     }
 
-    public void setProjectGroupId( int projectGroupId )
+    public void setProjectGroupId( final int projectGroupId )
     {
         this.projectGroupId = projectGroupId;
     }
@@ -493,7 +568,7 @@
         return scheduleId;
     }
 
-    public void setScheduleId( int scheduleId )
+    public void setScheduleId( final int scheduleId )
     {
         this.scheduleId = scheduleId;
     }
@@ -503,17 +578,19 @@
         return defaultBuildDefinition;
     }
 
-    public void setDefaultBuildDefinition( boolean defaultBuildDefinition )
+    public void setDefaultBuildDefinition( final boolean defaultBuildDefinition )
     {
         this.defaultBuildDefinition = defaultBuildDefinition;
     }
 
+    @Override
     public boolean isConfirmed()
     {
         return confirmed;
     }
 
-    public void setConfirmed( boolean confirmed )
+    @Override
+    public void setConfirmed( final boolean confirmed )
     {
         this.confirmed = confirmed;
     }
@@ -523,7 +600,7 @@
         return executor;
     }
 
-    public void setExecutor( String executor )
+    public void setExecutor( final String executor )
     {
         this.executor = executor;
     }
@@ -533,7 +610,7 @@
         return goals;
     }
 
-    public void setGoals( String goals )
+    public void setGoals( final String goals )
     {
         this.goals = goals;
     }
@@ -543,7 +620,7 @@
         return arguments;
     }
 
-    public void setArguments( String arguments )
+    public void setArguments( final String arguments )
     {
         this.arguments = arguments;
     }
@@ -553,7 +630,7 @@
         return buildFile;
     }
 
-    public void setBuildFile( String buildFile )
+    public void setBuildFile( final String buildFile )
     {
         this.buildFile = buildFile;
     }
@@ -563,27 +640,27 @@
         return buildFresh;
     }
 
-    public void setBuildFresh( boolean buildFresh )
+    public void setBuildFresh( final boolean buildFresh )
     {
         this.buildFresh = buildFresh;
     }
 
-    public Map getSchedules()
+    public Map<Integer, String> getSchedules()
     {
         return schedules;
     }
 
-    public void setSchedules( Map schedules )
+    public void setSchedules( final Map<Integer, String> schedules )
     {
         this.schedules = schedules;
     }
 
-    public List getProfiles()
+    public List<Profile> getProfiles()
     {
         return profiles;
     }
 
-    public void setProfiles( List profiles )
+    public void setProfiles( final List<Profile> profiles )
     {
         this.profiles = profiles;
     }
@@ -593,7 +670,7 @@
         return groupBuildDefinition;
     }
 
-    public void setGroupBuildDefinition( boolean groupBuildDefinition )
+    public void setGroupBuildDefinition( final boolean groupBuildDefinition )
     {
         this.groupBuildDefinition = groupBuildDefinition;
     }
@@ -621,7 +698,7 @@
         return profileId;
     }
 
-    public void setProfileId( int profileId )
+    public void setProfileId( final int profileId )
     {
         this.profileId = profileId;
     }
@@ -631,7 +708,7 @@
         return description;
     }
 
-    public void setDescription( String description )
+    public void setDescription( final String description )
     {
         this.description = description;
     }
@@ -641,7 +718,7 @@
         return buildDefinitionType;
     }
 
-    public void setBuildDefinitionType( String buildDefinitionType )
+    public void setBuildDefinitionType( final String buildDefinitionType )
     {
         this.buildDefinitionType = buildDefinitionType;
     }
@@ -656,9 +733,33 @@
         return alwaysBuild;
     }
 
-    public void setAlwaysBuild( boolean alwaysBuild )
+    public void setAlwaysBuild( final boolean alwaysBuild )
     {
         this.alwaysBuild = alwaysBuild;
     }
-    
+
+    public boolean isGroupBuildView()
+    {
+        return groupBuildView;
+    }
+
+    public void setGroupBuildView( final boolean groupBuildView )
+    {
+        this.groupBuildView = groupBuildView;
+    }
+
+    public int getUpdatePolicy()
+    {
+        return updatePolicy;
+    }
+
+    public void setUpdatePolicy( int updatePolicy )
+    {
+        this.updatePolicy = updatePolicy;
+    }
+
+    public Map<Integer, String> getBuildDefinitionUpdatePolicies()
+    {
+        return buildDefinitionUpdatePolicies;
+    }
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/BuildProjectAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/BuildProjectAction.java
index efa93dd..6ebb1cc 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/BuildProjectAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/BuildProjectAction.java
@@ -19,7 +19,14 @@
  * under the License.
  */
 
+import org.apache.continuum.buildagent.NoBuildAgentException;
+import org.apache.continuum.buildagent.NoBuildAgentInGroupException;
+import org.apache.continuum.utils.build.BuildTrigger;
+import org.apache.continuum.web.util.AuditLog;
+import org.apache.continuum.web.util.AuditLogConstants;
 import org.apache.maven.continuum.ContinuumException;
+import org.apache.maven.continuum.model.project.ProjectGroup;
+import org.apache.maven.continuum.project.ContinuumProjectState;
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
 import org.codehaus.plexus.util.StringUtils;
 
@@ -55,39 +62,72 @@
             return REQUIRES_AUTHORIZATION;
         }
 
-        if ( projectId > 0 )
+        BuildTrigger buildTrigger = new BuildTrigger( ContinuumProjectState.TRIGGER_FORCED, getPrincipal() );
+
+        try
         {
-            if ( buildDefinitionId > 0 )
+            if ( projectId > 0 )
             {
-                getContinuum().buildProjectWithBuildDefinition( projectId, buildDefinitionId );
+                if ( buildDefinitionId > 0 )
+                {
+                    getContinuum().buildProjectWithBuildDefinition( projectId, buildDefinitionId, buildTrigger );
+                }
+                else
+                {
+                    getContinuum().buildProject( projectId, buildTrigger.getTriggeredBy() );
+                }
             }
             else
             {
-                getContinuum().buildProject( projectId );
+                if ( buildDefinitionId > 0 )
+                {
+                    getContinuum().buildProjectGroupWithBuildDefinition( projectGroupId, buildDefinitionId,
+                                                                         buildTrigger );
+                }
+                else
+                {
+                    //TODO: Check if this code is called, I don't think
+                    //If it is, it should used the projectId
+                    getContinuum().buildProjects( buildTrigger.getTriggeredBy() );
+                }
+            }
+        }
+        catch ( NoBuildAgentException e )
+        {
+            addActionError( getText( "projectGroup.build.error.noBuildAgent" ) );
+        }
+        catch ( NoBuildAgentInGroupException e )
+        {
+            addActionError( getText( "projectGroup.build.error.noBuildAgentInGroup" ) );
+        }
+
+        AuditLog event = new AuditLog( AuditLogConstants.FORCE_BUILD );
+        event.setCurrentUser( getPrincipal() );
+
+        if ( projectId > 0 )
+        {
+            event.setResource( "Project id=" + projectId );
+            event.setCategory( AuditLogConstants.PROJECT );
+            event.log();
+
+            if ( fromGroupPage || hasActionErrors() )
+            {
+                return "to_group_page";
+            }
+            if ( fromProjectPage )
+            {
+                return "to_project_page";
             }
         }
         else
         {
-            if ( buildDefinitionId > 0 )
-            {
-                getContinuum().buildProjectGroupWithBuildDefinition( projectGroupId, buildDefinitionId );
-            }
-            else
-            {
-                getContinuum().buildProjects();
-            }
-        }
-
-        if ( projectId > 0 )
-        {
-            if ( fromGroupPage == true )
+            event.setResource( "Project Group id=" + projectGroupId );
+            event.setCategory( AuditLogConstants.PROJECT_GROUP );
+            event.log();
+            if ( fromGroupPage )
             {
                 return "to_group_page";
             }
-            if ( fromProjectPage == true )
-            {
-                return "to_project_page";
-            }
         }
 
         return SUCCESS;
@@ -154,7 +194,10 @@
             }
             else
             {
-                projectGroupName = getContinuum().getProjectGroupByProjectId( projectId ).getName();
+                ProjectGroup projectGroup = getContinuum().getProjectGroupByProjectId( projectId );
+
+                projectGroupName = projectGroup.getName();
+                projectGroupId = projectGroup.getId();
             }
         }
 
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/BuildResultAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/BuildResultAction.java
index cdb6a0c..db660fa 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/BuildResultAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/BuildResultAction.java
@@ -20,13 +20,17 @@
  */
 
 import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang.StringEscapeUtils;
 import org.apache.continuum.builder.distributed.manager.DistributedBuildManager;
 import org.apache.continuum.builder.utils.ContinuumBuildConstant;
+import org.apache.continuum.buildmanager.BuildManagerException;
+import org.apache.continuum.web.util.AuditLog;
+import org.apache.continuum.web.util.AuditLogConstants;
 import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.configuration.ConfigurationException;
+import org.apache.maven.continuum.configuration.ConfigurationService;
 import org.apache.maven.continuum.model.project.BuildResult;
 import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.scm.ChangeSet;
 import org.apache.maven.continuum.project.ContinuumProjectState;
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
 import org.apache.maven.continuum.web.util.StateGenerator;
@@ -60,7 +64,7 @@
 
     private int buildId;
 
-    private List changeSet;
+    private List<ChangeSet> changeSet;
 
     private boolean hasSurefireResults;
 
@@ -73,7 +77,7 @@
     private int projectGroupId;
 
     public String execute()
-        throws ContinuumException, ConfigurationException, IOException
+        throws ContinuumException, ConfigurationException, IOException, BuildManagerException
     {
         try
         {
@@ -88,8 +92,14 @@
         // check if there are surefire results to display
         project = getContinuum().getProject( getProjectId() );
 
-        if ( getContinuum().getConfiguration().isDistributedBuildEnabled() && project.getState() == ContinuumProjectState.BUILDING )
+        ConfigurationService configuration = getContinuum().getConfiguration();
+
+        // view build result of the current build from the distributed build agent
+        if ( configuration.isDistributedBuildEnabled() &&
+            project.getState() == ContinuumProjectState.BUILDING && getBuildId() == 0 )
         {
+            // if the project is currently building in distributed build agent, the build result will be stored in the database after the build is finished. 
+            // it's safe to assume that the build result will be null at this point
             Map<String, Object> map = distributedBuildManager.getBuildResult( project.getId() );
 
             if ( map == null )
@@ -104,6 +114,12 @@
                 buildResult = ContinuumBuildConstant.getBuildResult( map, null );
 
                 buildOutput = ContinuumBuildConstant.getBuildOutput( map );
+
+                if ( ServletActionContext.getRequest() != null )
+                {
+                    state = StateGenerator.generate( buildResult.getState(),
+                                                     ServletActionContext.getRequest().getContextPath() );
+                }
             }
             changeSet = null;
 
@@ -114,25 +130,21 @@
         else
         {
             buildResult = getContinuum().getBuildResult( getBuildId() );
-    
+
             // directory contains files ?
-            File surefireReportsDirectory =
-                getContinuum().getConfiguration().getTestReportsDirectory( buildId, getProjectId() );
+            File surefireReportsDirectory = configuration.getTestReportsDirectory( buildId, getProjectId() );
             File[] files = surefireReportsDirectory.listFiles();
-            if ( files == null )
-            {
-                hasSurefireResults = false;
-            }
-            else
-            {
-                hasSurefireResults = files.length > 0;
-            }
-            changeSet = getContinuum().getChangesSinceLastUpdate( getProjectId() );
-    
+            hasSurefireResults = files != null && files.length > 0;
+            changeSet = getContinuum().getChangesSinceLastSuccess( getProjectId(), getBuildId() );
+
             buildOutput = getBuildOutputText();
-    
-            state = StateGenerator.generate( buildResult.getState(), ServletActionContext.getRequest().getContextPath() );
-    
+
+            if ( ServletActionContext.getRequest() != null )
+            {
+                state = StateGenerator.generate( buildResult.getState(),
+                                                 ServletActionContext.getRequest().getContextPath() );
+            }
+
             this.setCanDelete( this.canRemoveBuildResult( buildResult ) );
         }
 
@@ -152,7 +164,32 @@
         }
         if ( this.isConfirmed() )
         {
-            getContinuum().removeBuildResult( buildId );
+            try
+            {
+                if ( canRemoveBuildResult( getContinuum().getBuildResult( buildId ) ) )
+                {
+                    getContinuum().removeBuildResult( buildId );
+                }
+                else
+                {
+                    addActionError( getText( "buildResult.cannot.delete" ) );
+                }
+            }
+            catch ( ContinuumException e )
+            {
+                addActionError( getText( "buildResult.delete.error", "Unable to delete build result", new Integer(
+                    buildId ).toString() ) );
+            }
+            catch ( BuildManagerException e )
+            {
+                throw new ContinuumException( e.getMessage(), e );
+            }
+
+            AuditLog event = new AuditLog( "Build Result id=" + buildId, AuditLogConstants.REMOVE_BUILD_RESULT );
+            event.setCategory( AuditLogConstants.BUILD_RESULT );
+            event.setCurrentUser( getPrincipal() );
+            event.log();
+
             return SUCCESS;
         }
 
@@ -170,18 +207,18 @@
     public InputStream getBuildOutputInputStream()
         throws ConfigurationException, IOException
     {
-        String outputText = getBuildOutputText();
-        return outputText == null ? null : IOUtils.toInputStream( outputText );
+        return IOUtils.toInputStream( buildOutput );
     }
 
     private String getBuildOutputText()
         throws ConfigurationException, IOException
     {
-        File buildOutputFile = getContinuum().getConfiguration().getBuildOutputFile( getBuildId(), getProjectId() );
+        ConfigurationService configuration = getContinuum().getConfiguration();
+        File buildOutputFile = configuration.getBuildOutputFile( getBuildId(), getProjectId() );
 
         if ( buildOutputFile.exists() )
         {
-            return StringEscapeUtils.escapeHtml( FileUtils.fileRead( buildOutputFile ) );
+            return FileUtils.fileRead( buildOutputFile );
         }
         return null;
     }
@@ -207,7 +244,7 @@
         return buildResult;
     }
 
-    public List getChangesSinceLastSuccess()
+    public List<ChangeSet> getChangesSinceLastSuccess()
     {
         return changeSet;
     }
@@ -247,4 +284,10 @@
     {
         return projectGroupId;
     }
+
+    // for testing
+    public void setDistributedBuildManager( DistributedBuildManager distributedBuildManager )
+    {
+        this.distributedBuildManager = distributedBuildManager;
+    }
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/BuildResultsListAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/BuildResultsListAction.java
index 85cbafe..1da9a0a 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/BuildResultsListAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/BuildResultsListAction.java
@@ -19,14 +19,20 @@
  * under the License.
  */
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
+import org.apache.continuum.buildmanager.BuildManagerException;
+import org.apache.continuum.web.util.AuditLog;
+import org.apache.continuum.web.util.AuditLogConstants;
 import org.apache.maven.continuum.ContinuumException;
+import org.apache.maven.continuum.model.project.BuildResult;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
 import org.codehaus.plexus.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
@@ -36,20 +42,22 @@
 public class BuildResultsListAction
     extends AbstractBuildAction
 {
+    private static final Logger logger = LoggerFactory.getLogger( BuildResultsListAction.class );
+
     private Project project;
 
-    private Collection buildResults;
-    
+    private Collection<BuildResult> buildResults;
+
     private Collection<String> selectedBuildResults;
 
     private int projectId;
-    
+
     private int projectGroupId;
 
     private String projectName;
 
     private String projectGroupName = "";
-    
+
     public String execute()
         throws ContinuumException
     {
@@ -68,7 +76,7 @@
 
         return SUCCESS;
     }
-    
+
     public String remove()
         throws ContinuumException
     {
@@ -90,14 +98,21 @@
 
                     try
                     {
-                        getLogger().info( "Removing BuildResult with id=" + buildId );
+                        logger.info( "Removing BuildResult with id=" + buildId );
 
                         getContinuum().removeBuildResult( buildId );
+
+                        AuditLog event = new AuditLog( "Build Result id=" + buildId,
+                                                       AuditLogConstants.REMOVE_BUILD_RESULT );
+                        event.setCategory( AuditLogConstants.BUILD_RESULT );
+                        event.setCurrentUser( getPrincipal() );
+                        event.log();
                     }
                     catch ( ContinuumException e )
                     {
-                        getLogger().error( "Error removing BuildResult with id=" + buildId );
-                        addActionError( getText( "Unable to remove BuildResult with id=" + buildId ) );
+                        logger.error( "Error removing BuildResult with id=" + buildId );
+                        addActionError( getText( "buildResult.delete.error", "Unable to delete build result",
+                                                 new Integer( buildId ).toString() ) );
                     }
                 }
             }
@@ -112,13 +127,22 @@
                 {
                     int buildId = Integer.parseInt( id );
 
-                    if ( canRemoveBuildResult( getContinuum().getBuildResult( buildId ) ) )
+                    try
                     {
-                        buildResultsRemovable.add( Integer.toString( buildId ) );
+                        if ( canRemoveBuildResult( getContinuum().getBuildResult( buildId ) ) )
+                        {
+                            buildResultsRemovable.add( Integer.toString( buildId ) );
+                        }
+                        else
+                        {
+                            this.addActionMessage( getResourceBundle().getString( "buildResult.cannot.delete" ) );
+                            return SUCCESS;
+                        }
                     }
-                    else
+                    catch ( BuildManagerException e )
                     {
-                        this.addActionMessage( getResourceBundle().getString( "buildResult.cannot.delete" ) );
+                        logger.error( e.getMessage() );
+                        throw new ContinuumException( e.getMessage(), e );
                     }
                 }
             }
@@ -137,7 +161,7 @@
         this.projectId = projectId;
     }
 
-    public Collection getBuildResults()
+    public Collection<BuildResult> getBuildResults()
     {
         return buildResults;
     }
@@ -168,12 +192,12 @@
         return projectGroupName;
     }
 
-    public Collection getSelectedBuildResults()
+    public Collection<String> getSelectedBuildResults()
     {
         return selectedBuildResults;
     }
 
-    public void setSelectedBuildResults( Collection selectedBuildResults )
+    public void setSelectedBuildResults( Collection<String> selectedBuildResults )
     {
         this.selectedBuildResults = selectedBuildResults;
     }
@@ -187,6 +211,4 @@
     {
         this.projectGroupId = projectGroupId;
     }
-
-    
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/CancelBuildAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/CancelBuildAction.java
index c6c715c..66d3d82 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/CancelBuildAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/CancelBuildAction.java
@@ -19,18 +19,25 @@
  * under the License.
  */
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
 import org.apache.commons.lang.ArrayUtils;
+import org.apache.continuum.buildmanager.BuildManagerException;
+import org.apache.continuum.buildmanager.BuildsManager;
 import org.apache.continuum.model.project.ProjectScmRoot;
-import org.apache.continuum.taskqueue.manager.TaskQueueManager;
-import org.apache.continuum.taskqueue.manager.TaskQueueManagerException;
+import org.apache.continuum.taskqueue.BuildProjectTask;
+import org.apache.continuum.web.util.AuditLog;
+import org.apache.continuum.web.util.AuditLogConstants;
 import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
 import org.codehaus.plexus.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
@@ -40,6 +47,7 @@
 public class CancelBuildAction
     extends ContinuumActionSupport
 {
+    private static final Logger logger = LoggerFactory.getLogger( CancelBuildAction.class );
 
     private int projectId;
 
@@ -56,15 +64,27 @@
         {
             checkBuildProjectInGroupAuthorization( getProjectGroupName() );
 
-            TaskQueueManager taskQueueManager = getContinuum().getTaskQueueManager();
+            if ( getContinuum().getConfiguration().isDistributedBuildEnabled() )
+            {
+                getContinuum().getDistributedBuildManager().cancelBuild( projectId );
+            }
+            else
+            {
+                BuildsManager buildsManager = getContinuum().getBuildsManager();
 
-            taskQueueManager.cancelBuildTask( projectId );
+                buildsManager.cancelBuild( projectId );
+            }
+
+            AuditLog event = new AuditLog( "Project id=" + projectId, AuditLogConstants.CANCEL_BUILD );
+            event.setCategory( AuditLogConstants.PROJECT );
+            event.setCurrentUser( getPrincipal() );
+            event.log();
         }
         catch ( AuthorizationRequiredException e )
         {
             return REQUIRES_AUTHORIZATION;
         }
-        catch ( TaskQueueManagerException e )
+        catch ( BuildManagerException e )
         {
             throw new ContinuumException( "Error while canceling build", e );
         }
@@ -86,21 +106,44 @@
             projectsId = ArrayUtils.add( projectsId, projectId );
         }
 
-        TaskQueueManager taskQueueManager = getContinuum().getTaskQueueManager();
-        try
+        if ( getContinuum().getConfiguration().isDistributedBuildEnabled() )
         {
-            taskQueueManager.removeProjectsFromBuildingQueue( projectsId );
-            
-            // now we must check if the current build is one of this
-        	int index = ArrayUtils.indexOf( projectsId, taskQueueManager.getCurrentProjectIdBuilding() );
-        	if ( index > 0 )
-        	{
-            	taskQueueManager.cancelBuildTask( projectsId[index] );
-        	}
+            for ( int i = 0; i < projectsId.length; i++ )
+            {
+                getContinuum().getDistributedBuildManager().cancelBuild( projectsId[i] );
+
+                AuditLog event = new AuditLog( "Project id=" + projectsId[i], AuditLogConstants.CANCEL_BUILD );
+                event.setCategory( AuditLogConstants.PROJECT );
+                event.setCurrentUser( getPrincipal() );
+                event.log();
+            }
         }
-        catch ( TaskQueueManagerException e )
+        else
         {
-            throw new ContinuumException( "Unable to remove projects from building queue", e );
+            BuildsManager parallelBuildsManager = getContinuum().getBuildsManager();
+            parallelBuildsManager.removeProjectsFromBuildQueue( projectsId );
+
+            try
+            {
+                // now we must check if the current build is one of this
+                int index = ArrayUtils.indexOf( projectsId, getCurrentProjectIdBuilding() );
+                if ( index > 0 )
+                {
+                    int projId = projectsId[index];
+                    getContinuum().getBuildsManager().cancelBuild( projId );
+
+                    AuditLog event = new AuditLog( "Project id=" + projId, AuditLogConstants.CANCEL_BUILD );
+                    event.setCategory( AuditLogConstants.PROJECT );
+                    event.setCurrentUser( getPrincipal() );
+                    event.log();
+                }
+
+            }
+            catch ( BuildManagerException e )
+            {
+                logger.error( e.getMessage() );
+                throw new ContinuumException( e.getMessage(), e );
+            }
         }
 
         return SUCCESS;
@@ -111,43 +154,59 @@
     {
         try
         {
-            checkBuildProjectInGroupAuthorization( getContinuum().getProjectGroup( projectGroupId).getName() );
+            checkBuildProjectInGroupAuthorization( getContinuum().getProjectGroup( projectGroupId ).getName() );
         }
         catch ( AuthorizationRequiredException e )
         {
             return REQUIRES_AUTHORIZATION;
         }
 
-        TaskQueueManager taskQueueManager = getContinuum().getTaskQueueManager();
-
-        List<ProjectScmRoot> scmRoots = getContinuum().getProjectScmRootByProjectGroup( projectGroupId );
-        
-        if ( scmRoots != null )
+        if ( getContinuum().getConfiguration().isDistributedBuildEnabled() )
         {
-            for ( ProjectScmRoot scmRoot : scmRoots )
+            getContinuum().getDistributedBuildManager().cancelGroupBuild( projectGroupId );
+
+            AuditLog event = new AuditLog( "Project Group id=" + projectGroupId, AuditLogConstants.CANCEL_BUILD );
+            event.setCategory( AuditLogConstants.PROJECT_GROUP );
+            event.setCurrentUser( getPrincipal() );
+            event.log();
+
+            return SUCCESS;
+        }
+        else
+        {
+            BuildsManager buildsManager = getContinuum().getBuildsManager();
+
+            List<ProjectScmRoot> scmRoots = getContinuum().getProjectScmRootByProjectGroup( projectGroupId );
+
+            if ( scmRoots != null )
             {
-                try
+                for ( ProjectScmRoot scmRoot : scmRoots )
                 {
-                    taskQueueManager.removeFromPrepareBuildQueue( projectGroupId, scmRoot.getScmRootAddress() );
-                }
-                catch ( TaskQueueManagerException e )
-                {
-                    throw new ContinuumException( "Unable to cancel group build", e );
+                    try
+                    {
+                        buildsManager.removeProjectGroupFromPrepareBuildQueue( projectGroupId,
+                                                                               scmRoot.getScmRootAddress() );
+                        //taskQueueManager.removeFromPrepareBuildQueue( projectGroupId, scmRoot.getScmRootAddress() );
+                    }
+                    catch ( BuildManagerException e )
+                    {
+                        throw new ContinuumException( "Unable to cancel group build", e );
+                    }
                 }
             }
+            Collection<Project> projects = getContinuum().getProjectsInGroup( projectGroupId );
+
+            List<String> projectIds = new ArrayList<String>();
+
+            for ( Project project : projects )
+            {
+                projectIds.add( Integer.toString( project.getId() ) );
+            }
+
+            setSelectedProjects( projectIds );
+
+            return cancelBuilds();
         }
-        Collection<Project> projects = getContinuum().getProjectsInGroup( projectGroupId );
-
-        List<String> projectIds = new ArrayList<String>();
-        
-        for ( Project project : projects )
-        {
-            projectIds.add( Integer.toString( project.getId() ) );
-        }
-
-        setSelectedProjects( projectIds );
-
-        return cancelBuilds();
     }
 
     public void setProjectId( int projectId )
@@ -185,4 +244,25 @@
     {
         this.projectGroupId = projectGroupId;
     }
+
+    /**
+     * @return -1 if not project currently building
+     * @throws ContinuumException
+     */
+    protected int getCurrentProjectIdBuilding()
+        throws ContinuumException, BuildManagerException
+    {
+        Map<String, BuildProjectTask> currentBuilds = getContinuum().getBuildsManager().getCurrentBuilds();
+        Set<String> keySet = currentBuilds.keySet();
+
+        for ( String key : keySet )
+        {
+            BuildProjectTask task = currentBuilds.get( key );
+            if ( task != null )
+            {
+                return task.getProjectId();
+            }
+        }
+        return -1;
+    }
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ContinuumActionSupport.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ContinuumActionSupport.java
index 0475364..7eff38f 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ContinuumActionSupport.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ContinuumActionSupport.java
@@ -19,12 +19,10 @@
  * under the License.
  */
 
-import java.text.SimpleDateFormat;
-import java.util.ResourceBundle;
-
 import com.opensymphony.xwork2.ActionContext;
 import com.opensymphony.xwork2.Preparable;
 import org.apache.maven.continuum.Continuum;
+import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
 import org.apache.maven.continuum.security.ContinuumRoleConstants;
 import org.apache.maven.continuum.web.exception.AuthenticationRequiredException;
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
@@ -32,8 +30,13 @@
 import org.codehaus.plexus.redback.system.SecuritySession;
 import org.codehaus.plexus.redback.system.SecuritySystem;
 import org.codehaus.plexus.redback.system.SecuritySystemConstants;
+import org.codehaus.plexus.redback.users.User;
+import org.codehaus.plexus.redback.users.UserNotFoundException;
 import org.codehaus.plexus.util.StringUtils;
 
+import java.text.SimpleDateFormat;
+import java.util.ResourceBundle;
+
 /**
  * ContinuumActionSupport
  *
@@ -55,6 +58,8 @@
 
     protected static final String REQUIRES_AUTHORIZATION = "requires-authorization";
 
+    protected static final String RELEASE_ERROR = "releaseError";
+
     protected static final String ERROR_MSG_AUTHORIZATION_REQUIRED = "You are not authorized to access this page. " +
         "Please contact your administrator to be granted the appropriate permissions.";
 
@@ -65,16 +70,16 @@
      * @plexus.requirement
      */
     private Continuum continuum;
-    
-    protected SimpleDateFormat dateFormatter = new SimpleDateFormat("MMM dd, yyyy hh:mm:ss aaa z");
+
+    protected final SimpleDateFormat dateFormatter = new SimpleDateFormat( "MMM dd, yyyy hh:mm:ss aaa z" );
 
     public void prepare()
         throws Exception
     {
         if ( securitySession == null )
         {
-            securitySession =
-                (SecuritySession) getContext().getSession().get( SecuritySystemConstants.SECURITY_SESSION_KEY );
+            securitySession = (SecuritySession) getContext().getSession().get(
+                SecuritySystemConstants.SECURITY_SESSION_KEY );
         }
     }
 
@@ -461,9 +466,10 @@
     }
 
     /**
-     * Check if the current user is authorized to manage queues 
-     * 
-     * @throws AuthenticationRequiredException if the user isn't authenticated
+     * Check if the current user is authorized to manage queues
+     *
+     * @throws AuthenticationRequiredException
+     *                                        if the user isn't authenticated
      * @throws AuthorizationRequiredException if the user isn't authorized
      */
     protected void checkManageQueuesAuthorization()
@@ -473,16 +479,22 @@
         {
             throw new AuthenticationRequiredException( "Authentication required" );
         }
-        
+
         checkAuthorization( ContinuumRoleConstants.CONTINUUM_MANAGE_QUEUES );
     }
-    
+
     protected void checkManageLocalRepositoriesAuthorization()
         throws AuthorizationRequiredException
-    {   
+    {
         checkAuthorization( ContinuumRoleConstants.CONTINUUM_MANAGE_REPOSITORIES );
     }
-    
+
+    protected void checkViewReportsAuthorization()
+        throws AuthorizationRequiredException
+    {
+        checkAuthorization( ContinuumRoleConstants.CONTINUUM_VIEW_REPORT );
+    }
+
     /**
      * Get the security session
      *
@@ -537,9 +549,45 @@
 
         return true;
     }
-    
+
     protected ResourceBundle getResourceBundle()
     {
         return getTexts( "localization/Continuum" );
-    }    
+    }
+
+    protected String getPrincipal()
+    {
+        String principal = "guest";
+
+        if ( getSecuritySession() != null )
+        {
+            if ( getSecuritySession().getUser() != null )
+            {
+                principal = (String) getSecuritySession().getUser().getPrincipal();
+            }
+        }
+        else
+        {
+            principal = "unknown-user";
+        }
+        return principal;
+    }
+
+    protected User getUser( String principal )
+        throws UserNotFoundException
+    {
+        return getSecuritySystem().getUserManager().findUser( principal );
+    }
+
+    /**
+     * Convenience method to determine whether a build is a maven build. We could call the static method directly,
+     * but for struts2 validator access, we would need to enable static method invocation.
+     *
+     * @param buildType
+     * @return true if the build type is will result in a maven 1 or 2+ build.
+     */
+    public boolean isMavenBuildType( String buildType )
+    {
+        return ContinuumBuildExecutorConstants.isMaven( buildType );
+    }
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/DeleteProjectAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/DeleteProjectAction.java
index 1f511a9..5dec281 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/DeleteProjectAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/DeleteProjectAction.java
@@ -19,9 +19,14 @@
  * under the License.
  */
 
+import org.apache.continuum.web.util.AuditLog;
+import org.apache.continuum.web.util.AuditLogConstants;
 import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.project.ProjectGroup;
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
@@ -31,6 +36,8 @@
 public class DeleteProjectAction
     extends ContinuumActionSupport
 {
+    private Logger logger = LoggerFactory.getLogger( this.getClass() );
+
     private int projectId;
 
     private String projectName;
@@ -51,7 +58,21 @@
             return REQUIRES_AUTHORIZATION;
         }
 
-        getContinuum().removeProject( projectId );
+        AuditLog event = new AuditLog( "Project id=" + projectId, AuditLogConstants.REMOVE_PROJECT );
+        event.setCurrentUser( getPrincipal() );
+        event.setCategory( AuditLogConstants.PROJECT );
+        event.log();
+
+        try
+        {
+            getContinuum().removeProject( projectId );
+        }
+        catch ( ContinuumException e )
+        {
+            logger.error( "Error removing project with id " + projectId, e );
+            addActionError( getText( "deleteProject.error", "Unable to delete project", new Integer(
+                projectId ).toString() ) );
+        }
 
         return SUCCESS;
     }
@@ -115,7 +136,9 @@
             }
             else
             {
-                projectGroupName = getContinuum().getProjectGroupByProjectId( projectId ).getName();
+                ProjectGroup group = getContinuum().getProjectGroupByProjectId( projectId );
+                projectGroupName = group.getName();
+                projectGroupId = group.getId();
             }
         }
 
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/GroupSummaryAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/GroupSummaryAction.java
index cdd98e6..8c6f937 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/GroupSummaryAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/GroupSummaryAction.java
@@ -19,15 +19,18 @@
  * under the License.
  */
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
+import org.apache.continuum.model.project.ProjectGroupSummary;
 import org.apache.maven.continuum.ContinuumException;
-import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.project.ProjectGroup;
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
 import org.apache.maven.continuum.web.model.GroupSummary;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
@@ -37,6 +40,8 @@
 public class GroupSummaryAction
     extends ContinuumActionSupport
 {
+    private static final Logger logger = LoggerFactory.getLogger( GroupSummaryAction.class );
+
     private String infoMessage;
 
     private List<GroupSummary> groups;
@@ -46,61 +51,43 @@
     {
         groups = new ArrayList<GroupSummary>();
 
-        Collection<ProjectGroup> projectGroups = getContinuum().getAllProjectGroupsWithProjects();
+        //TODO: Merge this two requests to one
+        Collection<ProjectGroup> projectGroups = getContinuum().getAllProjectGroups();
+        Map<Integer, ProjectGroupSummary> summaries = getContinuum().getProjectsSummaryByGroups();
 
         for ( ProjectGroup projectGroup : projectGroups )
         {
 
             if ( isAuthorized( projectGroup.getName() ) )
             {
-                getLogger().debug( "GroupSummaryAction: building group " + projectGroup.getName() );
+                if ( logger.isDebugEnabled() )
+                {
+                    logger.debug( "GroupSummaryAction: building group " + projectGroup.getName() );
+                }
 
                 GroupSummary groupModel = new GroupSummary();
                 groupModel.setId( projectGroup.getId() );
                 groupModel.setGroupId( projectGroup.getGroupId() );
                 groupModel.setName( projectGroup.getName() );
                 groupModel.setDescription( projectGroup.getDescription() );
-                
-                if ( projectGroup.getLocalRepository() != null )
+
+                ProjectGroupSummary summary = summaries.get( projectGroup.getId() );
+
+                if ( summary != null )
                 {
-                    groupModel.setRepositoryId( projectGroup.getLocalRepository().getId() );
-                    groupModel.setRepositoryName( projectGroup.getLocalRepository().getName() );
-                }
-
-                //TODO: Create a summary jpox request so code will be more simple and performance will be better
-                Collection<Project> projects = projectGroup.getProjects();
-
-                groupModel.setNumProjects( projects.size() );
-
-                int numSuccesses = 0;
-                int numFailures = 0;
-                int numErrors = 0;
-
-                for ( Project project : projects )
-                {
-                    
-                    if ( project.getState() == 2 )
-                    {
-                        numSuccesses++;
-                    }
-                    else if ( project.getState() == 3 )
-                    {
-                        numFailures++;
-                    }
-                    else if ( project.getState() == 4 )
-                    {
-                        numErrors++;
-                    }
+                    groupModel.setNumProjects( summary.getNumberOfProjects() );
+                    groupModel.setNumErrors( summary.getNumberOfErrors() );
+                    groupModel.setNumFailures( summary.getNumberOfFailures() );
+                    groupModel.setNumSuccesses( summary.getNumberOfSuccesses() );
                 }
 
                 //todo wire in the next scheduled build for the project group and a meaningful status message
                 //groupModel.setNextScheduledBuild( "unknown" );
                 //groupModel.setStatusMessage( "none" );
-
-                groupModel.setNumSuccesses( numSuccesses );
-                groupModel.setNumFailures( numFailures );
-                groupModel.setNumErrors( numErrors );
-                getLogger().debug( "GroupSummaryAction: adding group to groups list " + groupModel.getName() );
+                if ( logger.isDebugEnabled() )
+                {
+                    logger.debug( "GroupSummaryAction: adding group to groups list " + groupModel.getName() );
+                }
                 groups.add( groupModel );
             }
         }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/PlexusActionSupport.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/PlexusActionSupport.java
index 65a2826..77aeaa2 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/PlexusActionSupport.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/PlexusActionSupport.java
@@ -9,7 +9,7 @@
  * "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
+ *   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
@@ -21,8 +21,6 @@
 
 import com.opensymphony.xwork2.ActionSupport;
 import org.apache.struts2.interceptor.SessionAware;
-import org.codehaus.plexus.logging.LogEnabled;
-import org.codehaus.plexus.logging.Logger;
 
 import java.util.Map;
 
@@ -34,25 +32,13 @@
  */
 public abstract class PlexusActionSupport
     extends ActionSupport
-    implements LogEnabled, SessionAware
+    implements SessionAware
 {
     protected Map session;
 
-    private Logger logger;
-
     public void setSession( Map map )
     {
         //noinspection AssignmentToCollectionOrArrayFieldFromParameter
         this.session = map;
     }
-
-    public void enableLogging( Logger logger )
-    {
-        this.logger = logger;
-    }
-
-    protected Logger getLogger()
-    {
-        return logger;
-    }
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ProjectEditAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ProjectEditAction.java
index 49a0d4b..f40467c 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ProjectEditAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ProjectEditAction.java
@@ -19,6 +19,8 @@
  * under the License.
  */
 
+import org.apache.continuum.web.util.AuditLog;
+import org.apache.continuum.web.util.AuditLogConstants;
 import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
@@ -79,6 +81,11 @@
 
         getContinuum().updateProject( project );
 
+        AuditLog event = new AuditLog( "Project id=" + projectId, AuditLogConstants.MODIFY_PROJECT );
+        event.setCategory( AuditLogConstants.PROJECT );
+        event.setCurrentUser( getPrincipal() );
+        event.log();
+
         return SUCCESS;
     }
 
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ProjectGroupAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ProjectGroupAction.java
index bdd73ac..a6e2e11 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ProjectGroupAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ProjectGroupAction.java
@@ -19,10 +19,18 @@
  * under the License.
  */
 
+import org.apache.commons.collections.ComparatorUtils;
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.continuum.buildagent.NoBuildAgentException;
+import org.apache.continuum.buildagent.NoBuildAgentInGroupException;
+import org.apache.continuum.buildmanager.BuildManagerException;
+import org.apache.continuum.buildmanager.BuildsManager;
 import org.apache.continuum.model.project.ProjectScmRoot;
 import org.apache.continuum.model.repository.LocalRepository;
-import org.apache.continuum.taskqueue.manager.TaskQueueManager;
-import org.apache.continuum.taskqueue.manager.TaskQueueManagerException;
+import org.apache.continuum.utils.build.BuildTrigger;
+import org.apache.continuum.web.util.AuditLog;
+import org.apache.continuum.web.util.AuditLogConstants;
 import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.BuildResult;
@@ -40,12 +48,13 @@
 import org.codehaus.plexus.redback.role.RoleManager;
 import org.codehaus.plexus.redback.role.RoleManagerException;
 import org.codehaus.plexus.redback.users.User;
-import org.codehaus.plexus.util.StringUtils;
-import org.codehaus.plexus.util.dag.CycleDetectedException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
@@ -62,7 +71,9 @@
 public class ProjectGroupAction
     extends ContinuumConfirmAction
 {
-    private final static Map FILTER_CRITERIA = new HashMap();
+    private static final Logger logger = LoggerFactory.getLogger( ProjectGroupAction.class );
+
+    private static final Map<String, String> FILTER_CRITERIA = new HashMap<String, String>();
 
     static
     {
@@ -82,9 +93,9 @@
     private RoleManager roleManager;
 
     /**
-     * @plexus.requirement
+     * @plexus.requirement role-hint="parallel"
      */
-    private TaskQueueManager taskQueueManager;
+    private BuildsManager parallelBuildsManager;
 
     private int projectGroupId;
 
@@ -96,20 +107,21 @@
 
     private Map projects = new HashMap();
 
-    private Map projectGroups = new HashMap();
-
-    private boolean confirmed;
+    private Map<Integer, String> projectGroups = new HashMap<Integer, String>();
 
     private boolean projectInCOQueue = false;
 
-    private Collection projectList;
+    private Collection<Project> projectList;
 
-    private List projectGroupUsers;
+    private List<ProjectGroupUserBean> projectGroupUsers;
 
     private String filterProperty;
 
     private String filterKey;
 
+    //Default order is by username
+    private String sorterProperty = "username";
+
     private boolean ascending = true;
 
     private Collection groupProjects;
@@ -134,6 +146,14 @@
 
     private List<ProjectScmRoot> projectScmRoots;
 
+    public void prepare()
+        throws Exception
+    {
+        super.prepare();
+
+        repositories = getContinuum().getRepositoryService().getAllLocalRepositories();
+    }
+
     public String summary()
         throws ContinuumException
     {
@@ -146,11 +166,17 @@
             addActionError( authzE.getMessage() );
             return REQUIRES_AUTHORIZATION;
         }
+        catch ( ContinuumException e )
+        {
+            addActionError( getText( "projectGroup.invalid.id", "Invalid Project Group Id: " + projectGroupId,
+                                     Integer.toString( projectGroupId ) ) );
+            return "to_summary_page";
+        }
 
         projectGroup = getContinuum().getProjectGroupWithProjects( projectGroupId );
 
-        List<BuildDefinition> projectGroupBuildDefs =
-            getContinuum().getBuildDefinitionsForProjectGroup( projectGroupId );
+        List<BuildDefinition> projectGroupBuildDefs = getContinuum().getBuildDefinitionsForProjectGroup(
+            projectGroupId );
 
         if ( projectGroupBuildDefs != null )
         {
@@ -160,10 +186,10 @@
 
                 if ( !buildDefinition.isDefaultForProject() )
                 {
-                    String key = StringUtils.isEmpty( buildDefinition.getDescription() ) ? buildDefinition.getGoals()
-                        : buildDefinition
-                            .getDescription();
-                    buildDefinitions.put( key, Integer.valueOf( buildDefinition.getId() ) );
+                    String key = StringUtils.isEmpty( buildDefinition.getDescription() )
+                        ? buildDefinition.getGoals()
+                        : buildDefinition.getDescription();
+                    buildDefinitions.put( key, buildDefinition.getId() );
                 }
             }
         }
@@ -181,20 +207,11 @@
                 int nbAntProjects = 0;
                 int nbShellProjects = 0;
 
-                // get the projects according to build order (first project in the group is the root project)            
-                try
+                Project rootProject = ( getContinuum().getProjectsInBuildOrder(
+                    getContinuum().getProjectsInGroupWithDependencies( projectGroupId ) ) ).get( 0 );
+                if ( "maven2".equals( rootProject.getExecutorId() ) || "maven-1".equals( rootProject.getExecutorId() ) )
                 {
-                    Project rootProject = ( getContinuum().getProjectsInBuildOrder(
-                        getContinuum().getProjectsInGroupWithDependencies( projectGroupId ) ) ).get( 0 );
-                    if ( "maven2".equals( rootProject.getExecutorId() ) ||
-                        "maven-1".equals( rootProject.getExecutorId() ) )
-                    {
-                        url = rootProject.getUrl();
-                    }
-                }
-                catch ( CycleDetectedException e )
-                {
-                    // ignore. url won't be displayed if null
+                    url = rootProject.getUrl();
                 }
 
                 for ( Object o : projectGroup.getProjects() )
@@ -294,25 +311,31 @@
             return REQUIRES_AUTHORIZATION;
         }
 
-        if ( confirmed )
+        try
         {
             getContinuum().removeProjectGroup( projectGroupId );
         }
-        else
+        catch ( ContinuumException e )
         {
-            name = getProjectGroupName();
-            return CONFIRM;
+            logger.error( "Error while removing project group with id " + projectGroupId, e );
+            addActionError( getText( "projectGroup.delete.error", "Unable to remove project group", Integer.toString(
+                projectGroupId ) ) );
         }
 
+        AuditLog event = new AuditLog( "Project Group id=" + projectGroupId, AuditLogConstants.REMOVE_PROJECT_GROUP );
+        event.setCategory( AuditLogConstants.PROJECT );
+        event.setCurrentUser( getPrincipal() );
+        event.log();
+
         return SUCCESS;
     }
 
-    public String edit()
-        throws ContinuumException, CycleDetectedException
+    public String confirmRemove()
+        throws ContinuumException
     {
         try
         {
-            checkModifyProjectGroupAuthorization( getProjectGroupName() );
+            checkRemoveProjectGroupAuthorization( getProjectGroupName() );
         }
         catch ( AuthorizationRequiredException authzE )
         {
@@ -320,6 +343,13 @@
             return REQUIRES_AUTHORIZATION;
         }
 
+        name = getProjectGroupName();
+        return CONFIRM;
+    }
+
+    private void initialize()
+        throws ContinuumException
+    {
         try
         {
             checkManageLocalRepositoriesAuthorization();
@@ -332,44 +362,58 @@
 
         projectGroup = getContinuum().getProjectGroupWithProjects( projectGroupId );
 
+        projectList = projectGroup.getProjects();
+
+        if ( projectList != null )
+        {
+            for ( Project p : projectList )
+            {
+                try
+                {
+                    if ( parallelBuildsManager.isInAnyCheckoutQueue( p.getId() ) )
+                    {
+                        projectInCOQueue = true;
+                    }
+                }
+                catch ( BuildManagerException e )
+                {
+                    throw new ContinuumException( e.getMessage(), e );
+                }
+                projects.put( p, p.getProjectGroup().getId() );
+            }
+        }
+
+        for ( ProjectGroup pg : getContinuum().getAllProjectGroups() )
+        {
+            if ( isAuthorized( projectGroup.getName() ) )
+            {
+                projectGroups.put( pg.getId(), pg.getName() );
+            }
+        }
+        repositories = getContinuum().getRepositoryService().getAllLocalRepositories();
+    }
+
+    public String edit()
+        throws ContinuumException
+    {
+        try
+        {
+            checkModifyProjectGroupAuthorization( getProjectGroupName() );
+        }
+        catch ( AuthorizationRequiredException authzE )
+        {
+            addActionError( authzE.getMessage() );
+            return REQUIRES_AUTHORIZATION;
+        }
+
+        initialize();
+
         name = projectGroup.getName();
 
         description = projectGroup.getDescription();
 
         projectList = projectGroup.getProjects();
 
-        if ( projectList != null )
-        {
-            Iterator proj = projectList.iterator();
-
-            while ( proj.hasNext() )
-            {
-                Project p = (Project) proj.next();
-                try
-                {
-                    if ( taskQueueManager.isInCheckoutQueue( p.getId() ) )
-                    {
-                        projectInCOQueue = true;
-                    }
-                }
-                catch ( TaskQueueManagerException e )
-                {
-                    throw new ContinuumException( e.getMessage(), e );
-                }
-                projects.put( p, new Integer( p.getProjectGroup().getId() ) );
-            }
-        }
-
-        Iterator proj_group = getContinuum().getAllProjectGroupsWithProjects().iterator();
-        while ( proj_group.hasNext() )
-        {
-            ProjectGroup pg = (ProjectGroup) proj_group.next();
-            if ( isAuthorized( projectGroup.getName() ) )
-            {
-                projectGroups.put( new Integer( pg.getId() ), pg.getName() );
-            }
-        }
-
         if ( projectGroup.getLocalRepository() != null )
         {
             repositoryId = projectGroup.getLocalRepository().getId();
@@ -379,14 +423,12 @@
             repositoryId = -1;
         }
 
-        repositories = getContinuum().getRepositoryService().getAllLocalRepositories();
-
         Collection<Project> projList = getContinuum().getProjectsInGroupWithDependencies( projectGroup.getId() );
         if ( projList != null && projList.size() > 0 )
         {
             Project rootProject = ( getContinuum().getProjectsInBuildOrder( projList ) ).get( 0 );
 
-            if (rootProject != null)
+            if ( rootProject != null )
             {
                 setUrl( rootProject.getUrl() );
             }
@@ -407,30 +449,18 @@
             return REQUIRES_AUTHORIZATION;
         }
 
-        if ( name != null )
+        for ( ProjectGroup projectGroup : getContinuum().getAllProjectGroups() )
         {
-            if ( name.equals( "" ) )
+            if ( name.equals( projectGroup.getName() ) && projectGroup.getId() != projectGroupId )
             {
-                addActionError( getText( "projectGroup.error.name.required" ) );
-                return INPUT;
+                addActionError( getText( "projectGroup.error.name.already.exists" ) );
             }
-            else if ( name.trim().equals( "" ) )
-            {
-                addActionError( getText( "projectGroup.error.name.cannot.be.spaces" ) );
-                return INPUT;
-            }
-            else
-            {
-                name = name.trim();
-                for ( ProjectGroup projectGroup : getContinuum().getAllProjectGroups() )
-                {
-                    if ( name.equals( projectGroup.getName() ) && projectGroup.getId() != projectGroupId )
-                    {
-                        addActionError( getText( "projectGroup.error.name.already.exists" ) );
-                        return INPUT;
-                    }
-                }
-            }
+        }
+
+        if ( hasActionErrors() )
+        {
+            initialize();
+            return INPUT;
         }
 
         projectGroup = getContinuum().getProjectGroupWithProjects( projectGroupId );
@@ -439,7 +469,7 @@
         // todo convert everything like to work off of string keys
         if ( !name.equals( projectGroup.getName() ) )
         {
-            //CONTINUUM-1502
+            // CONTINUUM-1502
             name = name.trim();
             try
             {
@@ -456,17 +486,14 @@
 
         }
 
-        projectGroup.setDescription( description );
+        projectGroup.setDescription( StringEscapeUtils.escapeXml( StringEscapeUtils.unescapeXml( description ) ) );
 
+        // [CONTINUUM-2228]. In select field can't select empty values.
         if ( repositoryId > 0 )
         {
             LocalRepository repository = getContinuum().getRepositoryService().getLocalRepository( repositoryId );
             projectGroup.setLocalRepository( repository );
         }
-        else
-        {
-            projectGroup.setLocalRepository( null );
-        }
 
         getContinuum().updateProjectGroup( projectGroup );
 
@@ -500,16 +527,14 @@
                 }
             }
 
-            ProjectGroup newProjectGroup =
-                getContinuum().getProjectGroupWithProjects( new Integer( id[0] ).intValue() );
+            ProjectGroup newProjectGroup = getContinuum().getProjectGroupWithProjects( new Integer( id[0] ) );
 
             if ( newProjectGroup.getId() != projectGroup.getId() && isAuthorized( newProjectGroup.getName() ) )
             {
-                getLogger().info(
-                    "Moving project " + project.getName() + " to project group " + newProjectGroup.getName() );
+                logger.info( "Moving project " + project.getName() + " to project group " + newProjectGroup.getName() );
                 project.setProjectGroup( newProjectGroup );
 
-                //CONTINUUM-1512
+                // CONTINUUM-1512
                 Collection<BuildResult> results = getContinuum().getBuildResultsForProject( project.getId() );
                 for ( BuildResult br : results )
                 {
@@ -520,6 +545,11 @@
             }
         }
 
+        AuditLog event = new AuditLog( "Project Group id=" + projectGroupId, AuditLogConstants.MODIFY_PROJECT_GROUP );
+        event.setCategory( AuditLogConstants.PROJECT );
+        event.setCurrentUser( getPrincipal() );
+        event.log();
+
         return SUCCESS;
     }
 
@@ -536,14 +566,32 @@
             return REQUIRES_AUTHORIZATION;
         }
 
-        if ( this.getBuildDefinitionId() == -1 )
+        BuildTrigger buildTrigger = new BuildTrigger( ContinuumProjectState.TRIGGER_FORCED, getPrincipal() );
+
+        try
         {
-            getContinuum().buildProjectGroup( projectGroupId );
+            if ( this.getBuildDefinitionId() == -1 )
+            {
+                getContinuum().buildProjectGroup( projectGroupId, buildTrigger );
+            }
+            else
+            {
+                getContinuum().buildProjectGroupWithBuildDefinition( projectGroupId, buildDefinitionId, buildTrigger );
+            }
         }
-        else
+        catch ( NoBuildAgentException e )
         {
-            getContinuum().buildProjectGroupWithBuildDefinition( projectGroupId, buildDefinitionId );
+            addActionError( getText( "projectGroup.build.error.noBuildAgent" ) );
         }
+        catch ( NoBuildAgentInGroupException e )
+        {
+            addActionError( getText( "projectGroup.build.error.noBuildAgentInGroup" ) );
+        }
+
+        AuditLog event = new AuditLog( "Project Group id=" + projectGroupId, AuditLogConstants.FORCE_BUILD );
+        event.setCategory( AuditLogConstants.PROJECT );
+        event.setCurrentUser( getPrincipal() );
+        event.log();
 
         if ( this.isFromSummaryPage() )
         {
@@ -568,8 +616,8 @@
             return REQUIRES_AUTHORIZATION;
         }
 
-        //get the parent of the group by finding the parent project
-        //i.e., the project that doesn't have a parent, or it's parent is not in the group.
+        // get the parent of the group by finding the parent project
+        // i.e., the project that doesn't have a parent, or it's parent is not in the group.
 
         Project parent = null;
 
@@ -581,14 +629,13 @@
 
         if ( projectList != null )
         {
-            Iterator proj = projectList.iterator();
-
-            while ( proj.hasNext() )
+            for ( Project p : projectList )
             {
-                Project p = (Project) proj.next();
-
                 if ( p.getState() != ContinuumProjectState.OK )
                 {
+                    logger.info(
+                        "Attempt to release group '" + projectGroup.getName() + "' failed as project '" + p.getName() +
+                            "' is in state " + p.getState() );
                     allBuildsOk = false;
                 }
 
@@ -600,8 +647,11 @@
                     }
                     else
                     {
-                        //currently, we have no provisions for releasing 2 or more parents
-                        //at the same time, this will be implemented in the future
+                        logger.info( "Attempt to release group '" + projectGroup.getName() + "' failed as project '" +
+                                         p.getName() + "' and project '" + parent.getName() + "' are both parents" );
+
+                        // currently, we have no provisions for releasing 2 or more parents
+                        // at the same time, this will be implemented in the future
                         addActionError( getText( "projectGroup.release.error.severalParentProjects" ) );
                         return INPUT;
                     }
@@ -609,6 +659,9 @@
 
                 if ( !"maven2".equals( p.getExecutorId() ) )
                 {
+                    logger.info(
+                        "Attempt to release group '" + projectGroup.getName() + "' failed as project '" + p.getName() +
+                            "' is not a Maven project (executor '" + p.getExecutorId() + "')" );
                     allMavenTwo = false;
                 }
             }
@@ -633,17 +686,13 @@
         }
     }
 
-    private boolean isParentInProjectGroup( ProjectDependency parent, Collection projectsInGroup )
+    private boolean isParentInProjectGroup( ProjectDependency parent, Collection<Project> projectsInGroup )
         throws ContinuumException
     {
         boolean result = false;
 
-        Iterator projectsIterator = projectsInGroup.iterator();
-
-        while ( projectsIterator.hasNext() )
+        for ( Project project : projectsInGroup )
         {
-            Project project = (Project) projectsIterator.next();
-
             if ( parent != null )
             {
                 if ( ( project.getArtifactId().equals( parent.getArtifactId() ) ) &&
@@ -668,7 +717,9 @@
             List<String> roleNames = new ArrayList<String>();
             for ( Role r : roles )
             {
-                if ( r.getName().indexOf( projectGroup.getName() ) > -1 )
+                String projectGroupName = StringUtils.substringAfter( r.getName(), "-" ).trim();
+
+                if ( projectGroupName.equals( group.getName() ) )
                 {
                     roleNames.add( r.getName() );
                 }
@@ -676,7 +727,7 @@
             List<UserAssignment> userAssignments = rbac.getUserAssignmentsForRoles( roleNames );
             for ( UserAssignment ua : userAssignments )
             {
-                User u = getSecuritySystem().getUserManager().findUser( ua.getPrincipal() );
+                User u = getUser( ua.getPrincipal() );
                 if ( u != null )
                 {
                     users.add( u );
@@ -685,15 +736,19 @@
         }
         catch ( Exception e )
         {
-            getLogger().error( "Can't get the users list", e );
+            logger.error( "Can't get the users list", e );
         }
 
-        if ( !StringUtils.isEmpty( filterKey ) )
+        if ( StringUtils.isNotBlank( filterKey ) )
         {
-            users = findUsers( users, filterProperty, filterKey, ascending );
+            users = findUsers( users, filterProperty, filterKey );
+        }
+        if ( StringUtils.isNotBlank( sorterProperty ) )
+        {
+            sortUsers( users, sorterProperty, ascending );
         }
 
-        projectGroupUsers = new ArrayList();
+        projectGroupUsers = new ArrayList<ProjectGroupUserBean>();
 
         if ( users == null )
         {
@@ -710,19 +765,24 @@
 
             try
             {
-                Collection effectiveRoles = rbac.getEffectivelyAssignedRoles( user.getUsername() );
+                Collection<Role> effectiveRoles = rbac.getEffectivelyAssignedRoles( user.getUsername() );
+                boolean isGroupUser = false;
 
-                for ( Iterator j = effectiveRoles.iterator(); j.hasNext(); )
+                for ( Role role : effectiveRoles )
                 {
-                    Role role = (Role) j.next();
+                    String projectGroupName = StringUtils.substringAfter( role.getName(), "-" ).trim();
 
-                    if ( role.getName().indexOf( projectGroup.getName() ) > -1 )
+                    if ( projectGroupName.equals( projectGroup.getName() ) )
                     {
-                        pgUser.setRoles( effectiveRoles );
-                        projectGroupUsers.add( pgUser );
-                        break;
+                        pgUser.addRole( role );
+                        isGroupUser = true;
                     }
                 }
+
+                if ( isGroupUser )
+                {
+                    projectGroupUsers.add( pgUser );
+                }
             }
             catch ( RbacObjectNotFoundException e )
             {
@@ -735,7 +795,7 @@
         }
     }
 
-    private List<User> findUsers( List<User> users, String searchProperty, String searchKey, boolean orderAscending )
+    private List<User> findUsers( List<User> users, String searchProperty, String searchKey )
     {
         List<User> userList = new ArrayList<User>();
         for ( User user : users )
@@ -778,6 +838,37 @@
         return userList;
     }
 
+    private void sortUsers( List<User> userList, final String sorterProperty, final boolean orderAscending )
+    {
+        Collections.sort( userList, new Comparator<User>()
+        {
+            public int compare( User o1, User o2 )
+            {
+                String value1, value2;
+                if ( "fullName".equals( sorterProperty ) )
+                {
+                    value1 = o1.getFullName();
+                    value2 = o2.getFullName();
+                }
+                else if ( "email".equals( sorterProperty ) )
+                {
+                    value1 = o1.getEmail();
+                    value2 = o2.getEmail();
+                }
+                else
+                {
+                    value1 = o1.getUsername();
+                    value2 = o2.getUsername();
+                }
+                if ( orderAscending )
+                {
+                    return ComparatorUtils.nullLowComparator( null ).compare( value1, value2 );
+                }
+                return ComparatorUtils.nullLowComparator( null ).compare( value2, value1 );
+            }
+        } );
+    }
+
     public int getProjectGroupId()
     {
         return projectGroupId;
@@ -798,16 +889,6 @@
         this.projectGroup = projectGroup;
     }
 
-    public boolean isConfirmed()
-    {
-        return confirmed;
-    }
-
-    public void setConfirmed( boolean confirmed )
-    {
-        this.confirmed = confirmed;
-    }
-
     public String getDescription()
     {
         return description;
@@ -838,12 +919,12 @@
         this.projects = projects;
     }
 
-    public Map getProjectGroups()
+    public Map<Integer, String> getProjectGroups()
     {
         return projectGroups;
     }
 
-    public void setProjectGroups( Map projectGroups )
+    public void setProjectGroups( Map<Integer, String> projectGroups )
     {
         this.projectGroups = projectGroups;
     }
@@ -858,12 +939,12 @@
         this.projectInCOQueue = projectInQueue;
     }
 
-    public Collection getProjectList()
+    public Collection<Project> getProjectList()
     {
         return projectList;
     }
 
-    public List getProjectGroupUsers()
+    public List<ProjectGroupUserBean> getProjectGroupUsers()
     {
         return projectGroupUsers;
     }
@@ -898,7 +979,7 @@
         this.filterProperty = filterProperty;
     }
 
-    public Map getCriteria()
+    public Map<String, String> getCriteria()
     {
         return FILTER_CRITERIA;
     }
@@ -934,7 +1015,6 @@
     public String getProjectGroupName()
         throws ContinuumException
     {
-
         return getProjectGroup( projectGroupId ).getName();
     }
 
@@ -1035,4 +1115,20 @@
             return false;
         }
     }
+
+    public String getSorterProperty()
+    {
+        return sorterProperty;
+    }
+
+    public void setSorterProperty( String sorterProperty )
+    {
+        this.sorterProperty = sorterProperty;
+    }
+
+    // for testing
+    public void setRbacManager( RBACManager rbac )
+    {
+        this.rbac = rbac;
+    }
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ProjectViewAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ProjectViewAction.java
index d422bce..f685170 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ProjectViewAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ProjectViewAction.java
@@ -19,13 +19,15 @@
  * under the License.
  */
 
-import java.util.Date;
-
 import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.model.project.BuildResult;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.project.ProjectGroup;
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Date;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
@@ -35,22 +37,18 @@
 public class ProjectViewAction
     extends ContinuumActionSupport
 {
+    private static final Logger logger = LoggerFactory.getLogger( ProjectViewAction.class );
 
     private Project project;
 
     private int projectId;
-    
-    private String lastBuildDateTime;
 
-    /**
-     * Target {@link ProjectGroup} to view.
-     */
-    private ProjectGroup projectGroup;
+    private String lastBuildDateTime;
 
     public String execute()
         throws ContinuumException
     {
-        projectGroup = getProjectGroup();
+        ProjectGroup projectGroup = getProjectGroup();
 
         try
         {
@@ -66,20 +64,21 @@
         {
             try
             {
-            BuildResult lastBuildResult = getContinuum().getBuildResult( project.getLatestBuildId() );
-            if ( lastBuildResult != null )
-            {
-                this.setLastBuildDateTime( dateFormatter.format( new Date( lastBuildResult.getEndTime() ) ) );
+                BuildResult lastBuildResult = getContinuum().getBuildResult( project.getLatestBuildId() );
+                if ( lastBuildResult != null )
+                {
+                    this.setLastBuildDateTime( dateFormatter.format( new Date( lastBuildResult.getEndTime() ) ) );
+                }
             }
-            } catch (ContinuumException e)
+            catch ( ContinuumException e )
             {
-                getLogger().info( "buildResult with id " + project.getLatestBuildId() + " has been deleted" );
+                logger.info( "buildResult with id " + project.getLatestBuildId() + " has been deleted" );
             }
         }
 
         return SUCCESS;
     }
-    
+
     public void setProjectId( int projectId )
     {
         this.projectId = projectId;
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ProjectsListAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ProjectsListAction.java
index 0078f8b..f66030b 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ProjectsListAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ProjectsListAction.java
@@ -19,16 +19,20 @@
  * under the License.
  */
 
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
+import org.apache.continuum.buildagent.NoBuildAgentException;
+import org.apache.continuum.buildagent.NoBuildAgentInGroupException;
+import org.apache.continuum.web.util.AuditLog;
+import org.apache.continuum.web.util.AuditLogConstants;
 import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
 import org.codehaus.plexus.util.StringUtils;
-import org.codehaus.plexus.util.dag.CycleDetectedException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
@@ -38,8 +42,10 @@
 public class ProjectsListAction
     extends ContinuumActionSupport
 {
+    private static final Logger logger = LoggerFactory.getLogger( ProjectsListAction.class );
+
     private List<String> selectedProjects;
-    
+
     private List<String> selectedProjectsNames;
 
     private String projectGroupName = "";
@@ -66,14 +72,14 @@
         {
             return remove();
         }
-        else if ("confirmRemove".equals( methodToCall ))
+        else if ( "confirmRemove".equals( methodToCall ) )
         {
             return confirmRemove();
         }
 
         return SUCCESS;
     }
-   
+
     private String remove()
         throws ContinuumException
     {
@@ -94,14 +100,18 @@
 
                 try
                 {
-                    getLogger().info( "Removing Project with id=" + projectId );
+                    AuditLog event = new AuditLog( "Project id=" + projectId, AuditLogConstants.REMOVE_PROJECT );
+                    event.setCategory( AuditLogConstants.PROJECT );
+                    event.setCurrentUser( getPrincipal() );
+                    event.log();
 
                     getContinuum().removeProject( projectId );
                 }
                 catch ( ContinuumException e )
                 {
-                    getLogger().error( "Error removing Project with id=" + projectId );
-                    addActionError( getText( "Unable to remove Project with id=" + projectId ) );
+                    logger.error( "Error removing Project with id=" + projectId );
+                    addActionError( getText( "deleteProject.error", "Unable to delete project", new Integer(
+                        projectId ).toString() ) );
                 }
             }
         }
@@ -123,7 +133,7 @@
         }
         return "confirmRemove";
     }
-    
+
     private String build()
         throws ContinuumException
     {
@@ -139,31 +149,40 @@
         if ( selectedProjects != null && !selectedProjects.isEmpty() )
         {
             ArrayList<Project> projectsList = new ArrayList<Project>();
-            for ( Iterator i = selectedProjects.iterator(); i.hasNext(); )
+            for ( String pId : selectedProjects )
             {
-                int projectId = Integer.parseInt( (String) i.next() );
+                int projectId = Integer.parseInt( pId );
                 Project p = getContinuum().getProjectWithAllDetails( projectId );
                 projectsList.add( p );
+
+                AuditLog event = new AuditLog( "Project id=" + projectId, AuditLogConstants.FORCE_BUILD );
+                event.setCategory( AuditLogConstants.PROJECT );
+                event.setCurrentUser( getPrincipal() );
+                event.log();
             }
 
-            List<Project> sortedProjects;
+            List<Project> sortedProjects = getContinuum().getProjectsInBuildOrder( projectsList );
+
             try
             {
-                sortedProjects = getContinuum().getProjectsInBuildOrder( projectsList );
+                if ( this.getBuildDefinitionId() <= 0 )
+                {
+                    List<BuildDefinition> groupDefaultBDs = getContinuum().getDefaultBuildDefinitionsForProjectGroup(
+                        projectGroupId );
+                    getContinuum().buildProjectsWithBuildDefinition( sortedProjects, groupDefaultBDs );
+                }
+                else
+                {
+                    getContinuum().buildProjectsWithBuildDefinition( sortedProjects, buildDefinitionId );
+                }
             }
-            catch ( CycleDetectedException e )
+            catch ( NoBuildAgentException e )
             {
-                sortedProjects = projectsList;
+                addActionError( getText( "projectGroup.build.error.noBuildAgent" ) );
             }
-
-            if ( this.getBuildDefinitionId() <= 0 )
+            catch ( NoBuildAgentInGroupException e )
             {
-                List<BuildDefinition> groupDefaultBDs = getContinuum().getDefaultBuildDefinitionsForProjectGroup( projectGroupId );
-                getContinuum().buildProjectsWithBuildDefinition( sortedProjects, groupDefaultBDs );
-            }
-            else
-            {
-                getContinuum().buildProjectsWithBuildDefinition( sortedProjects, buildDefinitionId );
+                addActionError( getText( "projectGroup.build.error.noBuildAgentInGroup" ) );
             }
         }
 
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ReleaseCleanupAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ReleaseCleanupAction.java
index 6d256c2..84d4367 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ReleaseCleanupAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ReleaseCleanupAction.java
@@ -19,16 +19,21 @@
  * under the License.
  */
 
+import org.apache.continuum.configuration.BuildAgentConfigurationException;
+import org.apache.continuum.release.distributed.manager.DistributedReleaseManager;
 import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.release.ContinuumReleaseManager;
 import org.apache.maven.continuum.release.ContinuumReleaseManagerListener;
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
+import org.codehaus.plexus.util.StringUtils;
+
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * @author Edwin Punzalan
  * @version $Id$
  * @plexus.component role="com.opensymphony.xwork2.Action" role-hint="releaseCleanup"
- * 
  */
 public class ReleaseCleanupAction
     extends ContinuumActionSupport
@@ -51,24 +56,52 @@
             return REQUIRES_AUTHORIZATION;
         }
 
-        ContinuumReleaseManager releaseManager = getContinuum().getReleaseManager();
-
-        releaseManager.getReleaseResults().remove( releaseId );
-
-        ContinuumReleaseManagerListener listener =
-            (ContinuumReleaseManagerListener) releaseManager.getListeners().remove( releaseId );
-
-        if ( listener != null )
+        if ( getContinuum().getConfiguration().isDistributedBuildEnabled() )
         {
-            String goal = listener.getGoalName();
+            DistributedReleaseManager releaseManager = getContinuum().getDistributedReleaseManager();
 
-            return goal + "Finished";
+            try
+            {
+                String goal = releaseManager.releaseCleanup( releaseId );
+
+                if ( StringUtils.isNotBlank( goal ) )
+                {
+                    return goal;
+                }
+                else
+                {
+                    throw new Exception( "No listener to cleanup for id " + releaseId );
+                }
+            }
+            catch ( BuildAgentConfigurationException e )
+            {
+                List<Object> args = new ArrayList<Object>();
+                args.add( e.getMessage() );
+
+                addActionError( getText( "releaseCleanup.error", args ) );
+                return RELEASE_ERROR;
+            }
         }
         else
         {
-            throw new Exception( "No listener to cleanup for id " + releaseId );
-        }
+            ContinuumReleaseManager releaseManager = getContinuum().getReleaseManager();
 
+            releaseManager.getReleaseResults().remove( releaseId );
+
+            ContinuumReleaseManagerListener listener =
+                (ContinuumReleaseManagerListener) releaseManager.getListeners().remove( releaseId );
+
+            if ( listener != null )
+            {
+                String goal = listener.getGoalName();
+
+                return goal + "Finished";
+            }
+            else
+            {
+                throw new Exception( "No listener to cleanup for id " + releaseId );
+            }
+        }
     }
 
     public String getReleaseId()
@@ -101,4 +134,10 @@
 
         return projectGroupName;
     }
+
+    public int getProjectGroupId()
+        throws ContinuumException
+    {
+        return getContinuum().getProjectGroupByProjectId( projectId ).getId();
+    }
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ReleaseInProgressAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ReleaseInProgressAction.java
index a08314d..c6e8876 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ReleaseInProgressAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ReleaseInProgressAction.java
@@ -19,21 +19,20 @@
  * under the License.
  */
 
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.PrintWriter;
-
-import org.apache.continuum.model.release.ContinuumReleaseResult;
+import org.apache.continuum.configuration.BuildAgentConfigurationException;
+import org.apache.continuum.model.release.ReleaseListenerSummary;
+import org.apache.continuum.release.distributed.DistributedReleaseUtil;
+import org.apache.continuum.release.distributed.manager.DistributedReleaseManager;
 import org.apache.maven.continuum.ContinuumException;
-import org.apache.maven.continuum.configuration.ConfigurationException;
-import org.apache.maven.continuum.model.project.Project;
-import org.apache.maven.continuum.model.project.ProjectGroup;
 import org.apache.maven.continuum.release.ContinuumReleaseManager;
 import org.apache.maven.continuum.release.ContinuumReleaseManagerListener;
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
 import org.apache.maven.shared.release.ReleaseResult;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
 /**
  * @author Edwin Punzalan
  * @version $Id$
@@ -54,6 +53,10 @@
 
     private String projectGroupName = "";
 
+    private ReleaseListenerSummary listenerSummary;
+
+    private String username = "";
+
     public String execute()
         throws Exception
     {
@@ -68,38 +71,92 @@
 
         String status = "";
 
-        ContinuumReleaseManager releaseManager = getContinuum().getReleaseManager();
+        listenerSummary = new ReleaseListenerSummary();
 
-        listener = (ContinuumReleaseManagerListener) releaseManager.getListeners().get( releaseId );
-
-        if ( listener != null )
+        if ( getContinuum().getConfiguration().isDistributedBuildEnabled() )
         {
-            if ( listener.getState() == ContinuumReleaseManagerListener.LISTENING )
+            DistributedReleaseManager releaseManager = getContinuum().getDistributedReleaseManager();
+
+            Map map;
+
+            try
             {
-                status = "inProgress";
+                map = releaseManager.getListener( releaseId );
             }
-            else if ( listener.getState() == ContinuumReleaseManagerListener.FINISHED )
+            catch ( BuildAgentConfigurationException e )
             {
-                status = SUCCESS;
+                List<Object> args = new ArrayList<Object>();
+                args.add( e.getMessage() );
+
+                addActionError( getText( "distributedBuild.releaseInProgress.error", args ) );
+                return RELEASE_ERROR;
+            }
+
+            if ( map != null && !map.isEmpty() )
+            {
+                int state = DistributedReleaseUtil.getReleaseState( map );
+
+                username = DistributedReleaseUtil.getUsername( map );
+
+                if ( state == ContinuumReleaseManagerListener.LISTENING )
+                {
+                    status = "inProgress";
+                }
+                else if ( state == ContinuumReleaseManagerListener.FINISHED )
+                {
+                    status = SUCCESS;
+                }
+                else
+                {
+                    status = "initialized";
+                }
+
+                if ( status.equals( SUCCESS ) )
+                {
+                    getContinuum().addContinuumReleaseResult( projectId, releaseId, releaseGoal );
+                }
+
+                listenerSummary.setPhases( DistributedReleaseUtil.getReleasePhases( map ) );
+                listenerSummary.setCompletedPhases( DistributedReleaseUtil.getCompletedReleasePhases( map ) );
+                listenerSummary.setInProgress( DistributedReleaseUtil.getReleaseInProgress( map ) );
+                listenerSummary.setError( DistributedReleaseUtil.getReleaseError( map ) );
             }
             else
             {
-                status = "initialized";
+                throw new Exception( "There is no on-going or finished release operation with id " + releaseId );
             }
         }
         else
         {
-            throw new Exception( "There is no on-going or finished release operation with id " + releaseId );
-        }
+            ContinuumReleaseManager releaseManager = getContinuum().getReleaseManager();
 
-        if ( status.equals( SUCCESS ) )
-        {
-            ReleaseResult result = (ReleaseResult) releaseManager.getReleaseResults().get( releaseId );
+            listenerSummary = releaseManager.getListener( releaseId );
 
-            if ( result != null && getContinuum().getContinuumReleaseResult( projectId, releaseGoal, result.getStartTime(), result.getEndTime() ) == null )
+            if ( listenerSummary != null )
             {
-                ContinuumReleaseResult releaseResult = createContinuumReleaseResult( result );
-                getContinuum().addContinuumReleaseResult( releaseResult );
+                username = listenerSummary.getUsername();
+
+                if ( listenerSummary.getState() == ContinuumReleaseManagerListener.LISTENING )
+                {
+                    status = "inProgress";
+                }
+                else if ( listenerSummary.getState() == ContinuumReleaseManagerListener.FINISHED )
+                {
+                    status = SUCCESS;
+                }
+                else
+                {
+                    status = "initialized";
+                }
+            }
+            else
+            {
+                throw new Exception( "There is no on-going or finished release operation with id " + releaseId );
+            }
+
+            if ( status.equals( SUCCESS ) )
+            {
+                getContinuum().addContinuumReleaseResult( projectId, releaseId, releaseGoal );
             }
         }
 
@@ -118,26 +175,77 @@
             return REQUIRES_AUTHORIZATION;
         }
 
-        ContinuumReleaseManager releaseManager = getContinuum().getReleaseManager();
+        listenerSummary = new ReleaseListenerSummary();
 
-        listener = (ContinuumReleaseManagerListener) releaseManager.getListeners().get( releaseId );
-
-        if ( listener != null )
+        if ( getContinuum().getConfiguration().isDistributedBuildEnabled() )
         {
-            if ( listener.getState() == ContinuumReleaseManagerListener.FINISHED )
-            {
-                result = (ReleaseResult) releaseManager.getReleaseResults().get( releaseId );
+            DistributedReleaseManager releaseManager = getContinuum().getDistributedReleaseManager();
 
-                return SUCCESS;
-            }
-            else
+            try
             {
-                throw new Exception( "The release operation with id " + releaseId + "has not finished yet." );
+                Map map = releaseManager.getListener( releaseId );
+
+                if ( map != null && !map.isEmpty() )
+                {
+                    int state = DistributedReleaseUtil.getReleaseState( map );
+
+                    listenerSummary.setPhases( DistributedReleaseUtil.getReleasePhases( map ) );
+                    listenerSummary.setCompletedPhases( DistributedReleaseUtil.getCompletedReleasePhases( map ) );
+                    listenerSummary.setInProgress( DistributedReleaseUtil.getReleaseInProgress( map ) );
+                    listenerSummary.setError( DistributedReleaseUtil.getReleaseError( map ) );
+
+                    username = DistributedReleaseUtil.getUsername( map );
+
+                    if ( state == ContinuumReleaseManagerListener.FINISHED )
+                    {
+                        result = releaseManager.getReleaseResult( releaseId );
+
+                        return SUCCESS;
+                    }
+                    else
+                    {
+                        throw new Exception( "The release operation with id " + releaseId + "has not finished yet." );
+                    }
+                }
+                else
+                {
+                    throw new Exception( "There is no finished release operation with id " + releaseId );
+                }
+            }
+            catch ( BuildAgentConfigurationException e )
+            {
+                List<Object> args = new ArrayList<Object>();
+                args.add( e.getMessage() );
+
+                addActionError( getText( "releaseViewResult.error", args ) );
+                return RELEASE_ERROR;
             }
         }
         else
         {
-            throw new Exception( "There is no finished release operation with id " + releaseId );
+            ContinuumReleaseManager releaseManager = getContinuum().getReleaseManager();
+
+            listenerSummary = releaseManager.getListener( releaseId );
+
+            if ( listenerSummary != null )
+            {
+                username = listenerSummary.getUsername();
+
+                if ( listenerSummary.getState() == ContinuumReleaseManagerListener.FINISHED )
+                {
+                    result = (ReleaseResult) releaseManager.getReleaseResults().get( releaseId );
+
+                    return SUCCESS;
+                }
+                else
+                {
+                    throw new Exception( "The release operation with id " + releaseId + "has not finished yet." );
+                }
+            }
+            else
+            {
+                throw new Exception( "There is no finished release operation with id " + releaseId );
+            }
         }
     }
 
@@ -202,40 +310,25 @@
         return projectGroupName;
     }
 
-    private ContinuumReleaseResult createContinuumReleaseResult( ReleaseResult result )
+    public ReleaseListenerSummary getListenerSummary()
+    {
+        return listenerSummary;
+    }
+
+    public void setListenerSummary( ReleaseListenerSummary listenerSummary )
+    {
+        this.listenerSummary = listenerSummary;
+    }
+
+    public String getProjectName()
         throws ContinuumException
     {
-        ContinuumReleaseResult releaseResult = new ContinuumReleaseResult();
-        releaseResult.setStartTime( result.getStartTime() );
-        releaseResult.setEndTime( result.getEndTime() );
-        releaseResult.setResultCode( result.getResultCode() );
+        return getProjectGroupName();
+    }
 
-        Project project = getContinuum().getProject( projectId );
-        ProjectGroup projectGroup = project.getProjectGroup();
-        releaseResult.setProjectGroup( projectGroup );
-        releaseResult.setProject( project );
-        releaseResult.setReleaseGoal( releaseGoal );
-
-        String releaseName = "releases-" + result.getStartTime();
-
-        try
-        {
-            File logFile = getContinuum().getConfiguration().getReleaseOutputFile( projectGroup.getId(), releaseName );
-
-            PrintWriter writer = new PrintWriter( new FileWriter( logFile ) );
-            writer.write( result.getOutput() );
-            writer.close();
-        }
-        catch ( ConfigurationException e )
-        {
-            throw new ContinuumException( e.getMessage(), e );
-        }
-        catch ( IOException e )
-        {
-            throw new ContinuumException( "Unable to write output to file", e );
-        }
-
-        return releaseResult;
+    public String getUsername()
+    {
+        return this.username;
     }
 
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ReleasePerformAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ReleasePerformAction.java
index 64b5050..18826cf 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ReleasePerformAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ReleasePerformAction.java
@@ -19,8 +19,15 @@
  * under the License.
  */
 
+import org.apache.continuum.configuration.BuildAgentConfigurationException;
 import org.apache.continuum.model.repository.LocalRepository;
 import org.apache.continuum.release.config.ContinuumReleaseDescriptor;
+import org.apache.continuum.release.distributed.DistributedReleaseUtil;
+import org.apache.continuum.release.distributed.manager.DistributedReleaseManager;
+import org.apache.continuum.utils.release.ReleaseUtil;
+import org.apache.continuum.web.action.AbstractReleaseAction;
+import org.apache.continuum.web.util.AuditLog;
+import org.apache.continuum.web.util.AuditLogConstants;
 import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.system.Profile;
@@ -30,9 +37,13 @@
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
 import org.apache.maven.scm.provider.svn.repository.SvnScmProviderRepository;
 import org.apache.maven.shared.release.ReleaseResult;
+import org.codehaus.plexus.util.StringUtils;
 
 import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * @author Edwin Punzalan
@@ -40,7 +51,7 @@
  * @plexus.component role="com.opensymphony.xwork2.Action" role-hint="releasePerform"
  */
 public class ReleasePerformAction
-    extends ContinuumActionSupport
+    extends AbstractReleaseAction
 {
     private int projectId;
 
@@ -56,9 +67,11 @@
 
     private String scmTagBase;
 
-    private String goals;
+    private String goals = "clean deploy";
 
-    private boolean useReleaseProfile;
+    private String arguments;
+
+    private boolean useReleaseProfile = true;
 
     private ContinuumReleaseManagerListener listener;
 
@@ -70,6 +83,25 @@
 
     private int profileId;
 
+    private void init()
+        throws Exception
+    {
+        if ( getContinuum().getConfiguration().isDistributedBuildEnabled() )
+        {
+            DistributedReleaseManager distributedReleaseManager = getContinuum().getDistributedReleaseManager();
+
+            getReleasePluginParameters( distributedReleaseManager.getReleasePluginParameters( projectId, "pom.xml" ) );
+        }
+        else
+        {
+            Project project = getContinuum().getProject( projectId );
+
+            String workingDirectory = getContinuum().getWorkingDirectory( project.getId() ).getPath();
+
+            getReleasePluginParameters( workingDirectory, "pom.xml" );
+        }
+    }
+
     public String inputFromScm()
         throws Exception
     {
@@ -82,6 +114,19 @@
             return REQUIRES_AUTHORIZATION;
         }
 
+        try
+        {
+            init();
+        }
+        catch ( BuildAgentConfigurationException e )
+        {
+            List<Object> args = new ArrayList<Object>();
+            args.add( e.getMessage() );
+
+            addActionError( getText( "distributedBuild.releasePerform.input.error", args ) );
+            return RELEASE_ERROR;
+        }
+
         populateFromProject();
 
         releaseId = "";
@@ -103,9 +148,47 @@
             return REQUIRES_AUTHORIZATION;
         }
 
+        try
+        {
+            init();
+        }
+        catch ( BuildAgentConfigurationException e )
+        {
+            List<Object> args = new ArrayList<Object>();
+            args.add( e.getMessage() );
+
+            addActionError( getText( "distributedBuild.releasePerform.input.error", args ) );
+            return RELEASE_ERROR;
+        }
+
         return SUCCESS;
     }
 
+    /**
+     * FIXME olamy is it really the good place to do that ? should be moved to continuum-release
+     * TODO handle remoteTagging
+     */
+    private void getReleasePluginParameters( String workingDirectory, String pomFilename )
+        throws Exception
+    {
+        Map<String, Object> params = ReleaseUtil.getReleasePluginParameters( workingDirectory, pomFilename );
+
+        if ( params.get( "use-release-profile" ) != null )
+        {
+            useReleaseProfile = (Boolean) params.get( "use-release-profile" );
+        }
+
+        if ( params.get( "perform-goals" ) != null )
+        {
+            goals = (String) params.get( "perform-goals" );
+        }
+
+        if ( params.get( "arguments" ) != null )
+        {
+            arguments = (String) params.get( "arguments" );
+        }
+    }
+
     public String execute()
         throws Exception
     {
@@ -118,20 +201,51 @@
             return REQUIRES_AUTHORIZATION;
         }
 
-        listener = new DefaultReleaseManagerListener();
-
-        ContinuumReleaseManager releaseManager = getContinuum().getReleaseManager();
-
         Project project = getContinuum().getProject( projectId );
 
-        //todo should be configurable
-        File performDirectory = new File( getContinuum().getConfiguration().getWorkingDirectory(),
-                                          "releases-" + System.currentTimeMillis() );
-        performDirectory.mkdirs();
-        
         LocalRepository repository = project.getProjectGroup().getLocalRepository();
-        
-        releaseManager.perform( releaseId, performDirectory, goals, useReleaseProfile, listener, repository );
+
+        String username = getPrincipal();
+
+        if ( getContinuum().getConfiguration().isDistributedBuildEnabled() )
+        {
+            DistributedReleaseManager releaseManager = getContinuum().getDistributedReleaseManager();
+
+            try
+            {
+                releaseManager.releasePerform( projectId, releaseId, goals, arguments, useReleaseProfile, repository,
+                                               username );
+            }
+            catch ( BuildAgentConfigurationException e )
+            {
+                List<Object> args = new ArrayList<Object>();
+                args.add( e.getMessage() );
+
+                addActionError( getText( "distributedBuild.releasePerform.release.error", args ) );
+                return RELEASE_ERROR;
+            }
+        }
+        else
+        {
+            listener = new DefaultReleaseManagerListener();
+
+            listener.setUsername( username );
+
+            ContinuumReleaseManager releaseManager = getContinuum().getReleaseManager();
+
+            //todo should be configurable
+            File performDirectory = new File( getContinuum().getConfiguration().getWorkingDirectory(),
+                                              "releases-" + System.currentTimeMillis() );
+            performDirectory.mkdirs();
+
+            releaseManager.perform( releaseId, performDirectory, goals, arguments, useReleaseProfile, listener,
+                                    repository );
+        }
+
+        AuditLog event = new AuditLog( "ReleaseId=" + releaseId, AuditLogConstants.PERFORM_RELEASE );
+        event.setCategory( AuditLogConstants.PROJECT );
+        event.setCurrentUser( username );
+        event.log();
 
         return SUCCESS;
     }
@@ -139,32 +253,66 @@
     public String executeFromScm()
         throws Exception
     {
-        ContinuumReleaseManager releaseManager = getContinuum().getReleaseManager();
-
-        ContinuumReleaseDescriptor descriptor = new ContinuumReleaseDescriptor();
-        descriptor.setScmSourceUrl( scmUrl );
-        descriptor.setScmUsername( scmUsername );
-        descriptor.setScmPassword( scmPassword );
-        descriptor.setScmReleaseLabel( scmTag );
-        descriptor.setScmTagBase( scmTagBase );
-        
-        Profile profile = null;
-        
-        if ( profileId != -1 )
+        if ( getContinuum().getConfiguration().isDistributedBuildEnabled() )
         {
-            profile = getContinuum().getProfileService().getProfile( profileId );
-            descriptor.setEnvironments( releaseManager.getEnvironments( profile ) );
-        }
+            Project project = getContinuum().getProject( projectId );
 
-        do
+            LocalRepository repository = project.getProjectGroup().getLocalRepository();
+
+            DistributedReleaseManager releaseManager = getContinuum().getDistributedReleaseManager();
+
+            Profile profile = null;
+            if ( profileId != -1 )
+            {
+                profile = getContinuum().getProfileService().getProfile( profileId );
+            }
+            Map<String, String> environments =
+                getEnvironments( profile, releaseManager.getDefaultBuildagent( projectId ) );
+
+            try
+            {
+                releaseId = releaseManager.releasePerformFromScm( projectId, goals, arguments, useReleaseProfile,
+                                                                  repository, scmUrl, scmUsername, scmPassword, scmTag,
+                                                                  scmTagBase, environments, getPrincipal() );
+            }
+            catch ( BuildAgentConfigurationException e )
+            {
+                List<Object> args = new ArrayList<Object>();
+                args.add( e.getMessage() );
+
+                addActionError( getText( "distributedBuild.releasePerform.release.error", args ) );
+                return RELEASE_ERROR;
+            }
+
+            return SUCCESS;
+        }
+        else
         {
-            releaseId = String.valueOf( System.currentTimeMillis() );
+            ContinuumReleaseManager releaseManager = getContinuum().getReleaseManager();
+
+            ContinuumReleaseDescriptor descriptor = new ContinuumReleaseDescriptor();
+            descriptor.setScmSourceUrl( scmUrl );
+            descriptor.setScmUsername( scmUsername );
+            descriptor.setScmPassword( scmPassword );
+            descriptor.setScmReleaseLabel( scmTag );
+            descriptor.setScmTagBase( scmTagBase );
+
+            if ( profileId != -1 )
+            {
+                Profile profile = getContinuum().getProfileService().getProfile( profileId );
+                descriptor.setEnvironments( getEnvironments( profile, null ) );
+            }
+
+            do
+            {
+                releaseId = String.valueOf( System.currentTimeMillis() );
+            }
+            while ( releaseManager.getPreparedReleases().containsKey( releaseId ) );
+
+            releaseManager.getPreparedReleases().put( releaseId, descriptor );
+
+            return execute();
         }
-        while ( releaseManager.getPreparedReleases().containsKey( releaseId ) );
-
-        releaseManager.getPreparedReleases().put( releaseId, descriptor );
-
-        return execute();
     }
 
     private void populateFromProject()
@@ -188,6 +336,21 @@
         releaseId = "";
     }
 
+    private void getReleasePluginParameters( Map context )
+    {
+        useReleaseProfile = DistributedReleaseUtil.getUseReleaseProfile( context, useReleaseProfile );
+
+        if ( StringUtils.isNotEmpty( DistributedReleaseUtil.getPerformGoals( context, goals ) ) )
+        {
+            goals = DistributedReleaseUtil.getPerformGoals( context, goals );
+        }
+
+        if ( StringUtils.isNotEmpty( DistributedReleaseUtil.getArguments( context, "" ) ) )
+        {
+            arguments = DistributedReleaseUtil.getArguments( context, "" );
+        }
+    }
+
     public String getReleaseId()
     {
         return releaseId;
@@ -328,5 +491,14 @@
     {
         this.profileId = profileId;
     }
-    
+
+    public String getArguments()
+    {
+        return arguments;
+    }
+
+    public void setArguments( String arguments )
+    {
+        this.arguments = arguments;
+    }
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ReleasePrepareAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ReleasePrepareAction.java
index d874a17..6753ec2 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ReleasePrepareAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ReleasePrepareAction.java
@@ -19,28 +19,29 @@
  * under the License.
  */
 
+import org.apache.continuum.configuration.BuildAgentConfigurationException;
+import org.apache.continuum.model.release.ReleaseListenerSummary;
+import org.apache.continuum.release.distributed.DistributedReleaseUtil;
+import org.apache.continuum.release.distributed.manager.DistributedReleaseManager;
+import org.apache.continuum.utils.release.ReleaseUtil;
+import org.apache.continuum.web.action.AbstractReleaseAction;
+import org.apache.continuum.web.util.AuditLog;
+import org.apache.continuum.web.util.AuditLogConstants;
 import org.apache.maven.continuum.ContinuumException;
+import org.apache.maven.continuum.installation.InstallationService;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.system.Profile;
 import org.apache.maven.continuum.release.ContinuumReleaseManager;
 import org.apache.maven.continuum.release.ContinuumReleaseManagerListener;
 import org.apache.maven.continuum.release.DefaultReleaseManagerListener;
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
-import org.apache.maven.model.Model;
-import org.apache.maven.model.Plugin;
-import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
 import org.apache.maven.scm.provider.svn.repository.SvnScmProviderRepository;
 import org.apache.maven.shared.release.ReleaseResult;
-import org.apache.maven.shared.release.versions.DefaultVersionInfo;
-import org.apache.maven.shared.release.versions.VersionInfo;
 import org.codehaus.plexus.util.StringUtils;
-import org.codehaus.plexus.util.xml.Xpp3Dom;
 
 import java.io.File;
-import java.io.FileReader;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
@@ -51,10 +52,10 @@
  * @plexus.component role="com.opensymphony.xwork2.Action" role-hint="releasePrepare"
  */
 public class ReleasePrepareAction
-    extends ContinuumActionSupport
+    extends AbstractReleaseAction
 {
     private static final String SCM_SVN_PROTOCOL_PREFIX = "scm:svn";
-    
+
     private static final String SNAPSHOT_VERSION_SUFFIX = "-SNAPSHOT";
 
     private int projectId;
@@ -71,18 +72,22 @@
 
     private String scmTagBase;
 
+    private String scmCommentPrefix;
+
     private boolean scmUseEditMode = false;
-    
-    private List projects = new ArrayList();
 
-    private List projectKeys;
+    private List<Map<String, String>> projects = new ArrayList<Map<String, String>>();
 
-    private List devVersions;
+    private List<String> projectKeys;
 
-    private List relVersions;
+    private List<String> devVersions;
+
+    private List<String> relVersions;
 
     private String prepareGoals;
 
+    private String arguments;
+
     private ReleaseResult result;
 
     private ContinuumReleaseManagerListener listener;
@@ -93,6 +98,12 @@
 
     private int profileId;
 
+    private boolean autoVersionSubmodules = false;
+
+    private boolean addSchema = true;
+
+    private ReleaseListenerSummary listenerSummary;
+
     public String input()
         throws Exception
     {
@@ -109,12 +120,12 @@
         scmUsername = project.getScmUsername();
         scmPassword = project.getScmPassword();
         scmTag = project.getScmTag();
-        
+
         if ( scmTag == null )
         {
             String version = project.getVersion();
             int idx = version.indexOf( SNAPSHOT_VERSION_SUFFIX );
-            
+
             if ( idx >= 0 )
             {
                 // strip the snapshot version suffix
@@ -125,8 +136,6 @@
                 scmTag = project.getArtifactId() + "-" + version;
             }
         }
-        
-        String workingDirectory = getContinuum().getWorkingDirectory( project.getId() ).getPath();
 
         String scmUrl = project.getScmUrl();
         if ( scmUrl.startsWith( SCM_SVN_PROTOCOL_PREFIX ) )
@@ -140,11 +149,52 @@
             scmTagBase = "";
         }
 
+        ContinuumReleaseManager releaseManager = getContinuum().getReleaseManager();
+
+        //CONTINUUM-1503
+        releaseManager.sanitizeTagName( scmUrl, scmTag );
+
         prepareGoals = "clean integration-test";
 
-        getReleasePluginParameters( workingDirectory, "pom.xml" );
+        if ( getContinuum().getConfiguration().isDistributedBuildEnabled() )
+        {
+            DistributedReleaseManager distributedReleaseManager = getContinuum().getDistributedReleaseManager();
 
-        processProject( workingDirectory, "pom.xml" );
+            try
+            {
+                getReleasePluginParameters( distributedReleaseManager.getReleasePluginParameters( projectId,
+                                                                                                  "pom.xml" ) );
+
+                projects = distributedReleaseManager.processProject( projectId, "pom.xml", autoVersionSubmodules );
+            }
+            catch ( BuildAgentConfigurationException e )
+            {
+                List<Object> args = new ArrayList<Object>();
+                args.add( e.getMessage() );
+
+                addActionError( getText( "distributedBuild.releasePrepare.input.error", args ) );
+                return RELEASE_ERROR;
+            }
+        }
+        else
+        {
+            try
+            {
+                String workingDirectory = getContinuum().getWorkingDirectory( project.getId() ).getPath();
+
+                getReleasePluginParameters( workingDirectory, "pom.xml" );
+
+                ReleaseUtil.processProject( workingDirectory, "pom.xml", autoVersionSubmodules, projects );
+            }
+            catch ( Exception e )
+            {
+                List<Object> args = new ArrayList<Object>();
+                args.add( e.getMessage() );
+
+                addActionError( getText( "releasePrepare.input.error", args ) );
+                return RELEASE_ERROR;
+            }
+        }
 
         profiles = this.getContinuum().getProfileService().getAllProfiles();
 
@@ -154,48 +204,42 @@
     private void getReleasePluginParameters( String workingDirectory, String pomFilename )
         throws Exception
     {
-        MavenXpp3Reader pomReader = new MavenXpp3Reader();
-        Model model = pomReader.read( new FileReader( new File( workingDirectory, pomFilename ) ) );
+        Map<String, Object> params = ReleaseUtil.getReleasePluginParameters( workingDirectory, pomFilename );
 
-        if ( model.getBuild() != null && model.getBuild().getPlugins() != null )
+        // TODO: use constants for this
+        if ( params.get( "scm-tag" ) != null )
         {
-            for ( Iterator plugins = model.getBuild().getPlugins().iterator(); plugins.hasNext(); )
-            {
-                Plugin plugin = (Plugin) plugins.next();
+            scmTag = (String) params.get( "scm-tag" );
+        }
 
-                if ( plugin.getGroupId() != null && plugin.getGroupId().equals( "org.apache.maven.plugins" ) &&
-                    plugin.getArtifactId() != null && plugin.getArtifactId().equals( "maven-release-plugin" ) )
-                {
-                    Xpp3Dom dom = (Xpp3Dom) plugin.getConfiguration();
+        if ( params.get( "scm-tagbase" ) != null )
+        {
+            scmTagBase = (String) params.get( "scm-tagbase" );
+        }
 
-                    if ( dom != null )
-                    {
-                        Xpp3Dom configuration = dom.getChild( "releaseLabel" );
-                        if ( configuration != null )
-                        {
-                            scmTag = configuration.getValue();
-                        }
+        if ( params.get( "preparation-goals" ) != null )
+        {
+            prepareGoals = (String) params.get( "preparation-goals" );
+        }
 
-                        configuration = dom.getChild( "tag" );
-                        if ( configuration != null )
-                        {
-                            scmTag = configuration.getValue();
-                        }
+        if ( params.get( "arguments" ) != null )
+        {
+            arguments = (String) params.get( "arguments" );
+        }
 
-                        configuration = dom.getChild( "tagBase" );
-                        if ( configuration != null )
-                        {
-                            scmTagBase = configuration.getValue();
-                        }
+        if ( params.get( "scm-comment-prefix" ) != null )
+        {
+            scmCommentPrefix = (String) params.get( "scm-comment-prefix" );
+        }
 
-                        configuration = dom.getChild( "preparationGoals" );
-                        if ( configuration != null )
-                        {
-                            prepareGoals = configuration.getValue();
-                        }
-                    }
-                }
-            }
+        if ( params.get( "auto-version-submodules" ) != null )
+        {
+            autoVersionSubmodules = (Boolean) params.get( "auto-version-submodules" );
+        }
+
+        if ( params.get( "add-schema" ) != null )
+        {
+            addSchema = (Boolean) params.get( "add-schema" );
         }
     }
 
@@ -211,8 +255,6 @@
             return REQUIRES_AUTHORIZATION;
         }
 
-        listener = new DefaultReleaseManagerListener();
-
         Project project = getContinuum().getProject( projectId );
 
         name = project.getName();
@@ -220,18 +262,78 @@
         {
             name = project.getArtifactId();
         }
-        
+
         Profile profile = null;
-        
+
         if ( profileId != -1 )
         {
             profile = getContinuum().getProfileService().getProfile( profileId );
         }
 
-        ContinuumReleaseManager releaseManager = getContinuum().getReleaseManager();
+        String username = getPrincipal();
 
-        releaseId =
-            releaseManager.prepare( project, getReleaseProperties(), getRelVersionMap(), getDevVersionMap(), listener, profile );
+        Map<String, String> environments = new HashMap<String, String>();
+
+        if ( getContinuum().getConfiguration().isDistributedBuildEnabled() )
+        {
+            DistributedReleaseManager distributedReleaseManager = getContinuum().getDistributedReleaseManager();
+
+            environments = getEnvironments( profile, distributedReleaseManager.getDefaultBuildagent( projectId ) );
+
+            try
+            {
+                releaseId = distributedReleaseManager.releasePrepare( project, getReleaseProperties(),
+                                                                      getRelVersionMap(), getDevVersionMap(),
+                                                                      environments, username );
+
+                if ( releaseId == null )
+                {
+                    addActionError( "Failed to release project" );
+                    return RELEASE_ERROR;
+                }
+            }
+            catch ( BuildAgentConfigurationException e )
+            {
+                List<Object> args = new ArrayList<Object>();
+                args.add( e.getMessage() );
+
+                addActionError( getText( "distributedBuild.releasePrepare.release.error", args ) );
+                return RELEASE_ERROR;
+            }
+        }
+        else
+        {
+            environments = getEnvironments( profile, null );
+
+            listener = new DefaultReleaseManagerListener();
+
+            listener.setUsername( username );
+
+            String workingDirectory = getContinuum().getWorkingDirectory( projectId ).getPath();
+
+            ContinuumReleaseManager releaseManager = getContinuum().getReleaseManager();
+
+            String executable = getContinuum().getInstallationService().getExecutorConfigurator(
+                InstallationService.MAVEN2_TYPE ).getExecutable();
+
+            if ( environments != null )
+            {
+                String m2Home = environments.get( getContinuum().getInstallationService().getEnvVar(
+                    InstallationService.MAVEN2_TYPE ) );
+                if ( StringUtils.isNotEmpty( m2Home ) )
+                {
+                    executable = m2Home + File.separator + "bin" + File.separator + executable;
+                }
+            }
+
+            releaseId = releaseManager.prepare( project, getReleaseProperties(), getRelVersionMap(), getDevVersionMap(),
+                                                listener, workingDirectory, environments, executable );
+        }
+
+        AuditLog event = new AuditLog( "Release id=" + releaseId, AuditLogConstants.PREPARE_RELEASE );
+        event.setCategory( AuditLogConstants.PROJECT );
+        event.setCurrentUser( username );
+        event.log();
 
         return SUCCESS;
     }
@@ -248,7 +350,24 @@
             return REQUIRES_AUTHORIZATION;
         }
 
-        result = (ReleaseResult) getContinuum().getReleaseManager().getReleaseResults().get( releaseId );
+        if ( getContinuum().getConfiguration().isDistributedBuildEnabled() )
+        {
+            DistributedReleaseManager distributedReleaseManager = getContinuum().getDistributedReleaseManager();
+
+            try
+            {
+                result = distributedReleaseManager.getReleaseResult( releaseId );
+            }
+            catch ( BuildAgentConfigurationException e )
+            {
+                addActionError( "release" );
+                return "viewResultError";
+            }
+        }
+        else
+        {
+            result = (ReleaseResult) getContinuum().getReleaseManager().getReleaseResults().get( releaseId );
+        }
 
         return "viewResult";
     }
@@ -267,96 +386,105 @@
 
         String status;
 
-        ContinuumReleaseManager releaseManager = getContinuum().getReleaseManager();
+        listenerSummary = new ReleaseListenerSummary();
 
-        listener = (ContinuumReleaseManagerListener) releaseManager.getListeners().get( releaseId );
-
-        if ( listener != null )
+        if ( getContinuum().getConfiguration().isDistributedBuildEnabled() )
         {
-            if ( listener.getState() == ContinuumReleaseManagerListener.FINISHED )
+            DistributedReleaseManager distributedReleaseManager = getContinuum().getDistributedReleaseManager();
+            Map listenerMap;
+            try
             {
-                releaseManager.getListeners().remove( releaseId );
+                listenerMap = distributedReleaseManager.getListener( releaseId );
+            }
+            catch ( BuildAgentConfigurationException e )
+            {
+                addActionError( "Failed to retrieve listener for release: " + releaseId );
+                return "";
+            }
 
-                result = (ReleaseResult) releaseManager.getReleaseResults().get( releaseId );
+            if ( listenerMap != null && !listenerMap.isEmpty() )
+            {
+                int state = DistributedReleaseUtil.getReleaseState( listenerMap );
 
-                status = "finished";
+                if ( state == ContinuumReleaseManagerListener.FINISHED )
+                {
+                    distributedReleaseManager.removeListener( releaseId );
+
+                    result = distributedReleaseManager.getReleaseResult( releaseId );
+
+                    status = "finished";
+                }
+                else
+                {
+                    status = "inProgress";
+                }
+
+                listenerSummary.setPhases( DistributedReleaseUtil.getReleasePhases( listenerMap ) );
+                listenerSummary.setCompletedPhases( DistributedReleaseUtil.getCompletedReleasePhases( listenerMap ) );
+                listenerSummary.setInProgress( DistributedReleaseUtil.getReleaseInProgress( listenerMap ) );
+                listenerSummary.setError( DistributedReleaseUtil.getReleaseError( listenerMap ) );
             }
             else
             {
-                status = "inProgress";
+                throw new Exception( "There is no release on-going or finished with id: " + releaseId );
             }
         }
         else
         {
-            throw new Exception( "There is no release on-going or finished with id: " + releaseId );
+            ContinuumReleaseManager releaseManager = getContinuum().getReleaseManager();
+
+            listenerSummary = releaseManager.getListener( releaseId );
+
+            if ( listenerSummary != null )
+            {
+                if ( listenerSummary.getState() == ContinuumReleaseManagerListener.FINISHED )
+                {
+                    releaseManager.getListeners().remove( releaseId );
+
+                    result = (ReleaseResult) releaseManager.getReleaseResults().get( releaseId );
+
+                    status = "finished";
+                }
+                else
+                {
+                    status = "inProgress";
+                }
+            }
+            else
+            {
+                throw new Exception( "There is no release on-going or finished with id: " + releaseId );
+            }
         }
 
         return status;
     }
 
-    private void processProject( String workingDirectory, String pomFilename )
-        throws Exception
-    {
-        MavenXpp3Reader pomReader = new MavenXpp3Reader();
-        Model model = pomReader.read( new FileReader( new File( workingDirectory, pomFilename ) ) );
-
-        if ( model.getGroupId() == null )
-        {
-            model.setGroupId( model.getParent().getGroupId() );
-        }
-
-        if ( model.getVersion() == null )
-        {
-            model.setVersion( model.getParent().getVersion() );
-        }
-
-        setProperties( model );
-
-        for ( Iterator modules = model.getModules().iterator(); modules.hasNext(); )
-        {
-            processProject( workingDirectory + "/" + modules.next().toString(), "pom.xml" );
-        }
-    }
-
-    private void setProperties( Model model )
-        throws Exception
-    {
-        Map params = new HashMap();
-
-        params.put( "key", model.getGroupId() + ":" + model.getArtifactId() );
-
-        if ( model.getName() == null )
-        {
-            model.setName( model.getArtifactId() );
-        }
-        params.put( "name", model.getName() );
-
-        VersionInfo version = new DefaultVersionInfo( model.getVersion() );
-
-        params.put( "release", version.getReleaseVersionString() );
-        params.put( "dev", version.getNextVersion().getSnapshotVersionString() );
-
-        projects.add( params );
-    }
-
-    private Map getDevVersionMap()
+    private Map<String, String> getDevVersionMap()
     {
         return getVersionMap( projectKeys, devVersions );
     }
 
-    private Map getRelVersionMap()
+    private Map<String, String> getRelVersionMap()
     {
         return getVersionMap( projectKeys, relVersions );
     }
 
-    private Map getVersionMap( List keys, List versions )
+    private Map<String, String> getVersionMap( List<String> keys, List<String> versions )
     {
-        Map versionMap = new HashMap();
+        Map<String, String> versionMap = new HashMap<String, String>();
 
         for ( int idx = 0; idx < keys.size(); idx++ )
         {
-            String key = keys.get( idx ).toString();
-            String version = versions.get( idx ).toString();
+            String key = keys.get( idx );
+            String version;
+            if ( !autoVersionSubmodules )
+            {
+                version = versions.get( idx );
+            }
+            else
+            {
+                version = versions.get( 0 );
+            }
 
             versionMap.put( key, version );
         }
@@ -370,52 +498,93 @@
 
         if ( StringUtils.isNotEmpty( scmUsername ) )
         {
-            p.setProperty( "username", scmUsername );
+            p.setProperty( "scm-username", scmUsername );
         }
 
         if ( StringUtils.isNotEmpty( scmPassword ) )
         {
-            p.setProperty( "password", scmPassword );
+            p.setProperty( "scm-password", scmPassword );
         }
 
         if ( StringUtils.isNotEmpty( scmTagBase ) )
         {
-            p.setProperty( "tagBase", scmTagBase );
+            p.setProperty( "scm-tagbase", scmTagBase );
         }
 
-        p.setProperty( "tag", scmTag );
-        p.setProperty( "prepareGoals", prepareGoals );
-        p.setProperty( "useEditMode", Boolean.toString( scmUseEditMode ) );
+        if ( StringUtils.isNotEmpty( scmCommentPrefix ) )
+        {
+            // CONTINUUM-2619
+            p.setProperty( "scm-comment-prefix", scmCommentPrefix.trim() + " " );
+        }
+
+        p.setProperty( "scm-tag", scmTag );
+        p.setProperty( "preparation-goals", prepareGoals );
+        p.setProperty( "arguments", arguments );
+        p.setProperty( "use-edit-mode", Boolean.toString( scmUseEditMode ) );
+        p.setProperty( "add-schema", Boolean.toString( addSchema ) );
+        p.setProperty( "auto-version-submodules", Boolean.toString( autoVersionSubmodules ) );
 
         return p;
     }
 
-    public List getProjectKeys()
+    private void getReleasePluginParameters( Map context )
+    {
+        if ( StringUtils.isNotEmpty( DistributedReleaseUtil.getScmTag( context, scmTag ) ) )
+        {
+            scmTag = DistributedReleaseUtil.getScmTag( context, scmTag );
+        }
+
+        if ( StringUtils.isNotEmpty( DistributedReleaseUtil.getScmTagBase( context, scmTagBase ) ) )
+        {
+            scmTagBase = DistributedReleaseUtil.getScmTagBase( context, scmTagBase );
+        }
+
+        if ( StringUtils.isNotEmpty( DistributedReleaseUtil.getPrepareGoals( context, prepareGoals ) ) )
+        {
+            prepareGoals = DistributedReleaseUtil.getPrepareGoals( context, prepareGoals );
+        }
+
+        if ( StringUtils.isNotEmpty( DistributedReleaseUtil.getArguments( context, "" ) ) )
+        {
+            arguments = DistributedReleaseUtil.getArguments( context, "" );
+        }
+
+        if ( StringUtils.isNotEmpty( DistributedReleaseUtil.getScmCommentPrefix( context, "" ) ) )
+        {
+            scmCommentPrefix = DistributedReleaseUtil.getScmCommentPrefix( context, "" );
+        }
+
+        autoVersionSubmodules = DistributedReleaseUtil.getAutoVersionSubmodules( context, false );
+
+        addSchema = DistributedReleaseUtil.getAddSchema( context, true );
+    }
+
+    public List<String> getProjectKeys()
     {
         return projectKeys;
     }
 
-    public void setProjectKeys( List projectKeys )
+    public void setProjectKeys( List<String> projectKeys )
     {
         this.projectKeys = projectKeys;
     }
 
-    public List getDevVersions()
+    public List<String> getDevVersions()
     {
         return devVersions;
     }
 
-    public void setDevVersions( List devVersions )
+    public void setDevVersions( List<String> devVersions )
     {
         this.devVersions = devVersions;
     }
 
-    public List getRelVersions()
+    public List<String> getRelVersions()
     {
         return relVersions;
     }
 
-    public void setRelVersions( List relVersions )
+    public void setRelVersions( List<String> relVersions )
     {
         this.relVersions = relVersions;
     }
@@ -470,12 +639,12 @@
         this.scmTagBase = scmTagBase;
     }
 
-    public List getProjects()
+    public List<Map<String, String>> getProjects()
     {
         return projects;
     }
 
-    public void setProjects( List projects )
+    public void setProjects( List<Map<String, String>> projects )
     {
         this.projects = projects;
     }
@@ -530,6 +699,16 @@
         this.prepareGoals = prepareGoals;
     }
 
+    public String getArguments()
+    {
+        return arguments;
+    }
+
+    public void setArguments( String arguments )
+    {
+        this.arguments = arguments;
+    }
+
     public void validate()
     {
     }
@@ -565,15 +744,53 @@
         this.profileId = profileId;
     }
 
-	public boolean isScmUseEditMode() 
-	{
-		return scmUseEditMode;
-	}
+    public boolean isScmUseEditMode()
+    {
+        return scmUseEditMode;
+    }
 
-	public void setScmUseEditMode(boolean scmUseEditMode) 
-	{
-		this.scmUseEditMode = scmUseEditMode;
-	}
-    
-    
+    public void setScmUseEditMode( boolean scmUseEditMode )
+    {
+        this.scmUseEditMode = scmUseEditMode;
+    }
+
+    public String getScmCommentPrefix()
+    {
+        return scmCommentPrefix;
+    }
+
+    public void setScmCommentPrefix( String scmCommentPrefix )
+    {
+        this.scmCommentPrefix = scmCommentPrefix;
+    }
+
+    public boolean isAutoVersionSubmodules()
+    {
+        return autoVersionSubmodules;
+    }
+
+    public void setAutoVersionSubmodules( boolean autoVersionSubmodules )
+    {
+        this.autoVersionSubmodules = autoVersionSubmodules;
+    }
+
+    public boolean isAddSchema()
+    {
+        return addSchema;
+    }
+
+    public void setAddSchema( boolean addSchema )
+    {
+        this.addSchema = addSchema;
+    }
+
+    public ReleaseListenerSummary getListenerSummary()
+    {
+        return listenerSummary;
+    }
+
+    public void setListenerSummary( ReleaseListenerSummary listenerSummary )
+    {
+        this.listenerSummary = listenerSummary;
+    }
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ReleaseProjectAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ReleaseProjectAction.java
index dd57725..4e9dbf0 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ReleaseProjectAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ReleaseProjectAction.java
@@ -19,14 +19,14 @@
  * under the License.
  */
 
-import org.apache.maven.artifact.ArtifactUtils;
+import org.apache.continuum.release.distributed.manager.DistributedReleaseManager;
 import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.release.ContinuumReleaseManager;
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
-import org.apache.maven.shared.release.config.ReleaseDescriptor;
 import org.codehaus.plexus.util.StringUtils;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
@@ -42,7 +42,7 @@
 
     private String projectName;
 
-    private String preparedReleaseName;
+    private Map<String, String> preparedReleases;
 
     private String preparedReleaseId;
 
@@ -75,21 +75,31 @@
         {
             return REQUIRES_CONFIGURATION;
         }
-        
+
         project = getContinuum().getProjectWithAllDetails( projectId );
 
-        String releaseId = ArtifactUtils.versionlessKey( project.getGroupId(), project.getArtifactId() );
-
-        ContinuumReleaseManager releaseManager = getContinuum().getReleaseManager();
-
-        Map preparedReleases = releaseManager.getPreparedReleases();
-        if ( preparedReleases.containsKey( releaseId ) )
+        if ( getContinuum().getConfiguration().isDistributedBuildEnabled() )
         {
-            ReleaseDescriptor descriptor = (ReleaseDescriptor) preparedReleases.get( releaseId );
+            DistributedReleaseManager releaseManager = getContinuum().getDistributedReleaseManager();
 
-            preparedReleaseName = descriptor.getReleaseVersions().get( releaseId ).toString();
+            preparedReleases = releaseManager.getPreparedReleases( project.getGroupId(), project.getArtifactId() );
+        }
+        else
+        {
+            ContinuumReleaseManager releaseManager = getContinuum().getReleaseManager();
 
-            preparedReleaseId = releaseId;
+            this.preparedReleases = releaseManager.getPreparedReleasesForProject( project.getGroupId(),
+                                                                                  project.getArtifactId() );
+        }
+
+        if ( !preparedReleases.isEmpty() )
+        {
+            // use last release as default choice
+            preparedReleaseId = new ArrayList<String>( preparedReleases.keySet() ).get( preparedReleases.size() - 1 );
+        }
+        else
+        {
+            preparedReleaseId = null;
         }
 
         projectName = project.getName();
@@ -140,16 +150,6 @@
         this.projectId = projectId;
     }
 
-    public String getPreparedReleaseName()
-    {
-        return preparedReleaseName;
-    }
-
-    public void setPreparedReleaseName( String preparedReleaseName )
-    {
-        this.preparedReleaseName = preparedReleaseName;
-    }
-
     public String getGoal()
     {
         return goal;
@@ -220,4 +220,14 @@
 
         return projectGroupName;
     }
+
+    public Map<String, String> getPreparedReleases()
+    {
+        return preparedReleases;
+    }
+
+    public void setPreparedReleases( Map<String, String> preparedReleases )
+    {
+        this.preparedReleases = preparedReleases;
+    }
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ReleaseProjectGoalAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ReleaseProjectGoalAction.java
deleted file mode 100644
index 7d9055a..0000000
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ReleaseProjectGoalAction.java
+++ /dev/null
@@ -1,145 +0,0 @@
-package org.apache.maven.continuum.web.action;
-
-/*
- * 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 org.apache.maven.artifact.ArtifactUtils;
-import org.apache.maven.continuum.ContinuumException;
-import org.apache.maven.continuum.model.project.Project;
-import org.apache.maven.continuum.release.ContinuumReleaseManager;
-import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
-import org.apache.maven.shared.release.config.ReleaseDescriptor;
-import org.codehaus.plexus.util.StringUtils;
-
-import java.util.Map;
-
-/**
- * @author Edwin Punzalan
- * @version $Id$
- * @plexus.component role="com.opensymphony.xwork2.Action" role-hint="releaseProjectGoal"
- */
-public class ReleaseProjectGoalAction
-    extends ContinuumActionSupport
-{
-    private int projectId;
-
-    private int projectGroupId;
-
-    private String projectName;
-
-    private String preparedReleaseName;
-
-    private String preparedReleaseId;
-
-    private String projectGroupName = "";
-
-    public String execute()
-        throws Exception
-    {
-        try
-        {
-            checkBuildProjectInGroupAuthorization( getProjectGroupName() );
-        }
-        catch ( AuthorizationRequiredException e )
-        {
-            return REQUIRES_AUTHORIZATION;
-        }
-
-        Project project = getContinuum().getProjectWithAllDetails( projectId );
-
-        String releaseId = ArtifactUtils.versionlessKey( project.getGroupId(), project.getArtifactId() );
-
-        ContinuumReleaseManager releaseManager = getContinuum().getReleaseManager();
-
-        Map preparedReleases = releaseManager.getPreparedReleases();
-        if ( preparedReleases.containsKey( releaseId ) )
-        {
-            ReleaseDescriptor descriptor = (ReleaseDescriptor) preparedReleases.get( releaseId );
-
-            preparedReleaseName = descriptor.getReleaseVersions().get( releaseId ).toString();
-
-            preparedReleaseId = releaseId;
-        }
-
-        projectName = project.getName();
-
-        return SUCCESS;
-    }
-
-    public int getProjectId()
-    {
-        return projectId;
-    }
-
-    public void setProjectId( int projectId )
-    {
-        this.projectId = projectId;
-    }
-
-    public int getProjectGroupId()
-    {
-        return projectGroupId;
-    }
-
-    public void setProjectGroupId( int projectGroupId )
-    {
-        this.projectGroupId = projectGroupId;
-    }
-
-    public String getProjectName()
-    {
-        return projectName;
-    }
-
-    public void setProjectName( String projectName )
-    {
-        this.projectName = projectName;
-    }
-
-    public String getPreparedReleaseName()
-    {
-        return preparedReleaseName;
-    }
-
-    public void setPreparedReleaseName( String preparedReleaseName )
-    {
-        this.preparedReleaseName = preparedReleaseName;
-    }
-
-    public String getPreparedReleaseId()
-    {
-        return preparedReleaseId;
-    }
-
-    public void setPreparedReleaseId( String preparedReleaseId )
-    {
-        this.preparedReleaseId = preparedReleaseId;
-    }
-
-    public String getProjectGroupName()
-        throws ContinuumException
-    {
-        if ( StringUtils.isEmpty( projectGroupName ) )
-        {
-            projectGroupName = getContinuum().getProjectGroupByProjectId( projectId ).getName();
-        }
-
-        return projectGroupName;
-    }
-}
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ReleaseRollbackAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ReleaseRollbackAction.java
index 62d2922..7dc0448 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ReleaseRollbackAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ReleaseRollbackAction.java
@@ -19,12 +19,17 @@
  * under the License.
  */
 
+import org.apache.continuum.configuration.BuildAgentConfigurationException;
+import org.apache.continuum.release.distributed.manager.DistributedReleaseManager;
+import org.apache.continuum.web.util.AuditLog;
+import org.apache.continuum.web.util.AuditLogConstants;
 import org.apache.maven.continuum.ContinuumException;
-import org.apache.maven.continuum.utils.WorkingDirectoryService;
 import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.release.ContinuumReleaseException;
 import org.apache.maven.continuum.release.ContinuumReleaseManager;
 import org.apache.maven.continuum.release.ContinuumReleaseManagerListener;
 import org.apache.maven.continuum.release.DefaultReleaseManagerListener;
+import org.apache.maven.continuum.utils.WorkingDirectoryService;
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
 import org.codehaus.plexus.util.StringUtils;
 
@@ -61,28 +66,65 @@
             return REQUIRES_AUTHORIZATION;
         }
 
-        ContinuumReleaseManager releaseManager = getContinuum().getReleaseManager();
-
-        ContinuumReleaseManagerListener listener = new DefaultReleaseManagerListener();
-
-        Project project = getContinuum().getProject( projectId );
-
-        releaseManager.rollback( releaseId, workingDirectoryService.getWorkingDirectory( project ).getPath(), listener );
-
-        //recurse until rollback is finished
-        while ( listener.getState() != ContinuumReleaseManagerListener.FINISHED )
+        if ( getContinuum().getConfiguration().isDistributedBuildEnabled() )
         {
+            DistributedReleaseManager releaseManager = getContinuum().getDistributedReleaseManager();
+
             try
             {
-                Thread.sleep( 1000 );
+                releaseManager.releaseRollback( releaseId, projectId );
             }
-            catch ( InterruptedException e )
+            catch ( ContinuumReleaseException e )
             {
-                //do nothing
+                if ( e.getMessage() != null )
+                {
+                    addActionError( e.getMessage() );
+                    return RELEASE_ERROR;
+                }
+                else
+                {
+                    throw e;
+                }
+            }
+            catch ( BuildAgentConfigurationException e )
+            {
+                addActionError( "Error with configuration of build agent: " + e.getMessage() );
+                return RELEASE_ERROR;
             }
         }
+        else
+        {
+            ContinuumReleaseManager releaseManager = getContinuum().getReleaseManager();
 
-        releaseManager.getPreparedReleases().remove( releaseId );
+            ContinuumReleaseManagerListener listener = new DefaultReleaseManagerListener();
+
+            listener.setUsername( getPrincipal() );
+
+            Project project = getContinuum().getProject( projectId );
+
+            releaseManager.rollback( releaseId, workingDirectoryService.getWorkingDirectory( project ).getPath(),
+                                     listener );
+
+            //recurse until rollback is finished
+            while ( listener.getState() != ContinuumReleaseManagerListener.FINISHED )
+            {
+                try
+                {
+                    Thread.sleep( 1000 );
+                }
+                catch ( InterruptedException e )
+                {
+                    //do nothing
+                }
+            }
+
+            AuditLog event = new AuditLog( "Release id=" + releaseId, AuditLogConstants.ROLLBACK_RELEASE );
+            event.setCategory( AuditLogConstants.PROJECT );
+            event.setCurrentUser( getPrincipal() );
+            event.log();
+
+            releaseManager.getPreparedReleases().remove( releaseId );
+        }
 
         return SUCCESS;
     }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ScheduleAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ScheduleAction.java
index f0896b3..5a5499e 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ScheduleAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/ScheduleAction.java
@@ -19,12 +19,22 @@
  * under the License.
  */
 
+import com.opensymphony.xwork2.Preparable;
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.continuum.web.util.AuditLog;
+import org.apache.continuum.web.util.AuditLogConstants;
 import org.apache.maven.continuum.ContinuumException;
+import org.apache.maven.continuum.model.project.BuildQueue;
 import org.apache.maven.continuum.model.project.Schedule;
 import org.apache.maven.continuum.web.exception.AuthenticationRequiredException;
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.List;
 
 /**
  * @author Nik Gonzalez
@@ -33,7 +43,10 @@
  */
 public class ScheduleAction
     extends ContinuumConfirmAction
+    implements Preparable
 {
+    private static final Logger logger = LoggerFactory.getLogger( ScheduleAction.class );
+
     private int id;
 
     private boolean active = false;
@@ -66,6 +79,44 @@
 
     private String year;
 
+    private List<BuildQueue> availableBuildQueues;
+
+    private List<BuildQueue> selectedBuildQueues = new ArrayList<BuildQueue>();
+
+    private List<String> selectedBuildQueuesIds = new ArrayList<String>();
+
+    public void prepare()
+        throws Exception
+    {
+        super.prepare();
+
+        populateBuildQueues();
+    }
+
+    private void populateBuildQueues()
+        throws ContinuumException
+    {
+        if ( schedule != null )
+        {
+            selectedBuildQueues = schedule.getBuildQueues();
+            for ( BuildQueue bq : selectedBuildQueues )
+            {
+                this.selectedBuildQueuesIds.add( Integer.toString( bq.getId() ) );
+            }
+        }
+
+        availableBuildQueues = getContinuum().getAllBuildQueues();
+
+        // remove selected build queues from available build queues
+        for ( BuildQueue buildQueue : selectedBuildQueues )
+        {
+            if ( availableBuildQueues.contains( buildQueue ) )
+            {
+                availableBuildQueues.remove( buildQueue );
+            }
+        }
+    }
+
     public String summary()
         throws ContinuumException
     {
@@ -82,6 +133,7 @@
         {
             addActionError( e.getMessage() );
             return REQUIRES_AUTHENTICATION;
+
         }
 
         schedules = getContinuum().getSchedules();
@@ -92,6 +144,7 @@
     public String input()
         throws ContinuumException
     {
+
         try
         {
             checkManageSchedulesAuthorization();
@@ -128,6 +181,8 @@
             name = schedule.getName();
             delay = schedule.getDelay();
             maxJobExecutionTime = schedule.getMaxJobExecutionTime();
+
+            populateBuildQueues();
         }
         else
         {
@@ -141,6 +196,7 @@
     public String save()
         throws ContinuumException
     {
+
         try
         {
             checkManageSchedulesAuthorization();
@@ -156,35 +212,89 @@
             return REQUIRES_AUTHENTICATION;
         }
 
-        if ( ( "".equals( name ) ) || ( name == null ) )
+        if ( StringUtils.isBlank( name ) )
         {
-            getLogger().error( "Can't create schedule. No schedule name was supplied." );
+            logger.error( "Can't create schedule. No schedule name was supplied." );
             addActionError( getText( "buildDefinition.noname.save.error.message" ) );
+        }
+        if ( !getContinuum().getConfiguration().isDistributedBuildEnabled() &&
+            ( selectedBuildQueuesIds == null || selectedBuildQueuesIds.isEmpty() ) )
+        {
+            addActionError( getText( "schedule.buildqueues.empty.error" ) );
+        }
+        if ( hasErrors() )
+        {
             return ERROR;
         }
+
+        try
+        {
+            Schedule s = getContinuum().getScheduleByName( name );
+            if ( s != null && id != s.getId() )
+            {
+                addActionError( getText( "schedule.name.already.exists" ) );
+                return ERROR;
+            }
+        }
+        catch ( ContinuumException e )
+        {
+            logger.debug( "Unexpected error getting schedule" );
+        }
+
+        AuditLog event = new AuditLog( getName(), AuditLogConstants.ADD_SCHEDULE );
+        event.setCategory( AuditLogConstants.SCHEDULE );
+        event.setCurrentUser( getPrincipal() );
+
+        if ( id == 0 )
+        {
+            try
+            {
+                getContinuum().addSchedule( setFields( new Schedule() ) );
+                event.log();
+            }
+            catch ( ContinuumException e )
+            {
+                addActionError( getText( "schedule.buildqueues.add.error" ) );
+                return ERROR;
+            }
+            return SUCCESS;
+        }
         else
         {
-            if ( id == 0 )
-            {
-                getContinuum().addSchedule( setFields( new Schedule() ) );
-                return SUCCESS;
-            }
-            else
+            try
             {
                 getContinuum().updateSchedule( setFields( getContinuum().getSchedule( id ) ) );
-                return SUCCESS;
+                event.setAction( AuditLogConstants.MODIFY_SCHEDULE );
+                event.log();
             }
+            catch ( ContinuumException e )
+            {
+                addActionError( getText( "schedule.buildqueues.add.error" ) );
+                return ERROR;
+            }
+            return SUCCESS;
         }
     }
 
     private Schedule setFields( Schedule schedule )
+        throws ContinuumException
     {
         schedule.setActive( active );
         schedule.setCronExpression( getCronExpression() );
         schedule.setDelay( delay );
-        schedule.setDescription( description );
+        schedule.setDescription( StringEscapeUtils.escapeXml( StringEscapeUtils.unescapeXml( description ) ) );
         schedule.setName( name );
         schedule.setMaxJobExecutionTime( maxJobExecutionTime );
+        if ( !getContinuum().getConfiguration().isDistributedBuildEnabled() )
+        {
+            // if distributed build don't update schedules
+            schedule.setBuildQueues( null );
+            for ( String id : selectedBuildQueuesIds )
+            {
+                BuildQueue buildQueue = getContinuum().getBuildQueue( Integer.parseInt( id ) );
+                schedule.addBuildQueue( buildQueue );
+            }
+        }
 
         return schedule;
     }
@@ -239,7 +349,6 @@
             catch ( ContinuumException e )
             {
                 addActionError( getText( "schedule.remove.error" ) );
-
                 return ERROR;
             }
         }
@@ -252,6 +361,11 @@
             return CONFIRM;
         }
 
+        AuditLog event = new AuditLog( name, AuditLogConstants.REMOVE_SCHEDULE );
+        event.setCategory( AuditLogConstants.SCHEDULE );
+        event.setCurrentUser( getPrincipal() );
+        event.log();
+
         return SUCCESS;
     }
 
@@ -415,4 +529,34 @@
         return ( second + " " + minute + " " + hour + " " + dayOfMonth + " " + month + " " + dayOfWeek + " " +
             year ).trim();
     }
+
+    public List<BuildQueue> getAvailableBuildQueues()
+    {
+        return availableBuildQueues;
+    }
+
+    public void setAvailableBuildQueues( List<BuildQueue> availableBuildQueues )
+    {
+        this.availableBuildQueues = availableBuildQueues;
+    }
+
+    public List<BuildQueue> getSelectedBuildQueues()
+    {
+        return selectedBuildQueues;
+    }
+
+    public void setSelectedBuildQueues( List<BuildQueue> selectedBuildQueues )
+    {
+        this.selectedBuildQueues = selectedBuildQueues;
+    }
+
+    public List<String> getSelectedBuildQueuesIds()
+    {
+        return selectedBuildQueuesIds;
+    }
+
+    public void setSelectedBuildQueuesIds( List<String> selectedBuildQueuesIds )
+    {
+        this.selectedBuildQueuesIds = selectedBuildQueuesIds;
+    }
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/SummaryAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/SummaryAction.java
index 1000ea2..507f2b6 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/SummaryAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/SummaryAction.java
@@ -19,21 +19,23 @@
  * under the License.
  */
 
-import org.apache.continuum.taskqueue.manager.TaskQueueManager;
-import org.apache.continuum.taskqueue.manager.TaskQueueManagerException;
+import org.apache.continuum.buildmanager.BuildManagerException;
+import org.apache.continuum.buildmanager.BuildsManager;
 import org.apache.maven.continuum.ContinuumException;
+import org.apache.maven.continuum.configuration.ConfigurationService;
 import org.apache.maven.continuum.model.project.BuildResult;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.project.ContinuumProjectState;
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
 import org.apache.maven.continuum.web.model.GroupSummary;
 import org.apache.maven.continuum.web.model.ProjectSummary;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
@@ -47,18 +49,20 @@
 public class SummaryAction
     extends ContinuumActionSupport
 {
+    private static final Logger logger = LoggerFactory.getLogger( SummaryAction.class );
+
     private int projectGroupId;
 
     private String projectGroupName;
 
-    private List summary;
+    private List<ProjectSummary> summary;
 
     private GroupSummary groupSummary = new GroupSummary();
 
     /**
-     * @plexus.requirement
+     * @plexus.requirement role-hint="parallel"
      */
-    private TaskQueueManager taskQueueManager;
+    private BuildsManager parallelBuildsManager;
 
     public String execute()
         throws ContinuumException
@@ -73,14 +77,14 @@
             return REQUIRES_AUTHORIZATION;
         }
 
-        Collection projectsInGroup;
+        Collection<Project> projectsInGroup;
 
         //TODO: Create a summary jpox request so code will be more simple and performance will be better
         projectsInGroup = getContinuum().getProjectsInGroup( projectGroupId );
 
-        Map buildResults = getContinuum().getLatestBuildResults( projectGroupId );
+        Map<Integer, BuildResult> buildResults = getContinuum().getLatestBuildResults( projectGroupId );
 
-        Map buildResultsInSuccess = getContinuum().getBuildResultsInSuccess( projectGroupId );
+        Map<Integer, BuildResult> buildResultsInSuccess = getContinuum().getBuildResultsInSuccess( projectGroupId );
 
         summary = new ArrayList<ProjectSummary>();
 
@@ -89,10 +93,8 @@
         groupSummary.setNumSuccesses( 0 );
         groupSummary.setNumProjects( 0 );
 
-        for ( Iterator i = projectsInGroup.iterator(); i.hasNext(); )
+        for ( Project project : projectsInGroup )
         {
-            Project project = (Project) i.next();
-
             groupSummary.setNumProjects( groupSummary.getNumProjects() + 1 );
 
             ProjectSummary model = new ProjectSummary();
@@ -111,11 +113,12 @@
 
             try
             {
-                if ( taskQueueManager.isInBuildingQueue( project.getId() ) )
+                if ( parallelBuildsManager.isInAnyBuildQueue( project.getId() ) ||
+                    parallelBuildsManager.isInPrepareBuildQueue( project.getId() ) )
                 {
                     model.setInBuildingQueue( true );
                 }
-                else if ( taskQueueManager.isInCheckoutQueue( project.getId() ) )
+                else if ( parallelBuildsManager.isInAnyCheckoutQueue( project.getId() ) )
                 {
                     model.setInCheckoutQueue( true );
                 }
@@ -125,7 +128,7 @@
                     model.setInCheckoutQueue( false );
                 }
             }
-            catch ( TaskQueueManagerException e )
+            catch ( BuildManagerException e )
             {
                 throw new ContinuumException( e.getMessage(), e );
             }
@@ -136,7 +139,7 @@
 
             if ( buildResultsInSuccess != null )
             {
-                BuildResult buildInSuccess = (BuildResult) buildResultsInSuccess.get( new Integer( project.getId() ) );
+                BuildResult buildInSuccess = buildResultsInSuccess.get( project.getId() );
 
                 if ( buildInSuccess != null )
                 {
@@ -146,7 +149,7 @@
 
             if ( buildResults != null )
             {
-                BuildResult latestBuild = (BuildResult) buildResults.get( new Integer( project.getId() ) );
+                BuildResult latestBuild = buildResults.get( project.getId() );
 
                 if ( latestBuild != null )
                 {
@@ -155,6 +158,13 @@
                     model.setLastBuildDateTime( latestBuild.getEndTime() );
                     model.setLastBuildDuration( latestBuild.getDurationTime() );
                 }
+
+                ConfigurationService configuration = getContinuum().getConfiguration();
+
+                if ( configuration.isDistributedBuildEnabled() && project.getState() == ContinuumProjectState.BUILDING )
+                {
+                    model.setLatestBuildId( 0 );
+                }
             }
 
             summary.add( model );
@@ -189,13 +199,13 @@
             default:
                 if ( latestBuild.getState() == 5 || latestBuild.getState() > 10 )
                 {
-                    getLogger().warn(
+                    logger.warn(
                         "unknown buildState value " + latestBuild.getState() + " with build " + latestBuild.getId() );
                 }
         }
     }
 
-    public List getProjects()
+    public List<ProjectSummary> getProjects()
     {
         return summary;
     }
@@ -210,7 +220,6 @@
         this.projectGroupId = projectGroupId;
     }
 
-
     public String getProjectGroupName()
     {
         return projectGroupName;
@@ -230,4 +239,10 @@
     {
         this.groupSummary = groupSummary;
     }
+
+    // test
+    public void setParallelBuildsManager( BuildsManager parallelBuildsManager )
+    {
+        this.parallelBuildsManager = parallelBuildsManager;
+    }
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/SurefireReportAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/SurefireReportAction.java
index 55f6f4c..39b351c 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/SurefireReportAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/SurefireReportAction.java
@@ -19,14 +19,6 @@
  * under the License.
  */
 
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
 import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.configuration.ConfigurationException;
 import org.apache.maven.continuum.model.project.Project;
@@ -35,8 +27,12 @@
 import org.apache.maven.continuum.reports.surefire.ReportTestSuiteGenerator;
 import org.apache.maven.continuum.reports.surefire.ReportTestSuiteGeneratorException;
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
-import org.codehaus.plexus.util.DirectoryScanner;
-import org.codehaus.plexus.util.StringUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
 
 /**
  * @author Edwin Punzalan
@@ -49,18 +45,18 @@
 {
     /**
      * @plexus.requirement
-     */    
+     */
     private ReportTestSuiteGenerator reportTestSuiteGenerator;
-    
+
     private int buildId;
 
     private int projectId;
 
-    private List testSuites;
+    private List<ReportTestSuite> testSuites;
 
-    private List testSummaryList;
+    private List<ReportTest> testSummaryList;
 
-    private List testPackageList;
+    private List<ReportTest> testPackageList;
 
     private String projectName;
 
@@ -89,7 +85,7 @@
         return SUCCESS;
     }
 
-    private void getSummary( List suiteList )
+    private void getSummary( List<ReportTestSuite> suiteList )
     {
         int totalTests = 0;
 
@@ -99,11 +95,8 @@
 
         float totalTime = 0.0f;
 
-        for ( Iterator suites = suiteList.iterator(); suites.hasNext(); )
+        for ( ReportTestSuite suite : suiteList )
         {
-
-            ReportTestSuite suite = (ReportTestSuite) suites.next();
-
             totalTests += suite.getNumberOfTests();
 
             totalErrors += suite.getNumberOfErrors();
@@ -124,11 +117,11 @@
 
     private void getDetails( List<ReportTestSuite> suiteList )
     {
-        Map testsByPackage = new LinkedHashMap();
+        Map<String, ReportTest> testsByPackage = new LinkedHashMap<String, ReportTest>();
 
         for ( ReportTestSuite suite : suiteList )
         {
-            ReportTest report = (ReportTest) testsByPackage.get( suite.getPackageName() );
+            ReportTest report = testsByPackage.get( suite.getPackageName() );
 
             if ( report == null )
             {
@@ -158,7 +151,7 @@
             testsByPackage.put( suite.getPackageName(), report );
         }
 
-        testPackageList = new ArrayList( testsByPackage.values() );
+        testPackageList = new ArrayList<ReportTest>( testsByPackage.values() );
     }
 
     public int getBuildId()
@@ -186,27 +179,12 @@
         this.projectId = projectId;
     }
 
-    private String[] getIncludedFiles( File directory, String includes, String excludes )
-    {
-        DirectoryScanner scanner = new DirectoryScanner();
-
-        scanner.setBasedir( directory );
-
-        scanner.setIncludes( StringUtils.split( includes, "," ) );
-
-        scanner.setExcludes( StringUtils.split( excludes, "," ) );
-
-        scanner.scan();
-
-        return scanner.getIncludedFiles();
-    }
-
-    public List getTestSuites()
+    public List<ReportTestSuite> getTestSuites()
     {
         return testSuites;
     }
 
-    public void setTestSuites( List testSuites )
+    public void setTestSuites( List<ReportTestSuite> testSuites )
     {
         this.testSuites = testSuites;
     }
@@ -221,22 +199,22 @@
         this.projectName = projectName;
     }
 
-    public List getTestSummaryList()
+    public List<ReportTest> getTestSummaryList()
     {
         return testSummaryList;
     }
 
-    public void setTestSummaryList( List testSummaryList )
+    public void setTestSummaryList( List<ReportTest> testSummaryList )
     {
         this.testSummaryList = testSummaryList;
     }
 
-    public List getTestPackageList()
+    public List<ReportTest> getTestPackageList()
     {
         return testPackageList;
     }
 
-    public void setTestPackageList( List testPackageList )
+    public void setTestPackageList( List<ReportTest> testPackageList )
     {
         this.testPackageList = testPackageList;
     }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/WorkingCopyAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/WorkingCopyAction.java
index 5167304..7385f56 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/WorkingCopyAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/WorkingCopyAction.java
@@ -19,21 +19,25 @@
  * under the License.
  */
 
+import org.apache.continuum.builder.distributed.manager.DistributedBuildManager;
 import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
+import org.apache.maven.continuum.web.util.UrlHelperFactory;
 import org.apache.maven.continuum.web.util.WorkingCopyContentGenerator;
 import org.apache.struts2.ServletActionContext;
 import org.apache.struts2.views.util.UrlHelper;
 import org.codehaus.plexus.util.StringUtils;
 
-import javax.activation.MimetypesFileTypeMap;
+import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.InputStream;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import javax.activation.MimetypesFileTypeMap;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
@@ -48,6 +52,11 @@
      */
     private WorkingCopyContentGenerator generator;
 
+    /**
+     * @plexus.requirement
+     */
+    private DistributedBuildManager distributedBuildManager;
+
     private Project project;
 
     private int projectId;
@@ -66,10 +75,16 @@
 
     private String mimeType = "application/octet-stream";
 
-    private static String FILE_SEPARATOR = System.getProperty( "file.separator" );
+    private static final String FILE_SEPARATOR = System.getProperty( "file.separator" );
 
     private String projectGroupName = "";
 
+    private String downloadFileName = "";
+
+    private String downloadFileLength = "";
+
+    private InputStream downloadFileInputStream;
+
     public String execute()
         throws ContinuumException
     {
@@ -87,61 +102,102 @@
             throw new ContinuumException( "release.properties is not accessible." );
         }
 
-        List<File> files = getContinuum().getFiles( projectId, userDirectory );
-
         project = getContinuum().getProject( projectId );
 
         projectName = project.getName();
 
-        HashMap params = new HashMap();
+        HashMap<String, Object> params = new HashMap<String, Object>();
 
-        params.put( "projectId", new Integer( projectId ) );
+        params.put( "projectId", projectId );
 
         params.put( "projectName", projectName );
 
-        String baseUrl = UrlHelper.buildUrl( "/workingCopy.action", ServletActionContext.getRequest(),
+        UrlHelper urlHelper = UrlHelperFactory.getInstance();
+        
+        String baseUrl = urlHelper.buildUrl( "/workingCopy.action", ServletActionContext.getRequest(),
                                              ServletActionContext.getResponse(), params );
 
-        String imagesBaseUrl = UrlHelper.buildUrl( "/images/", ServletActionContext.getRequest(),
+        String imagesBaseUrl = urlHelper.buildUrl( "/images/", ServletActionContext.getRequest(),
                                                    ServletActionContext.getResponse(), params );
 
         imagesBaseUrl = imagesBaseUrl.substring( 0, imagesBaseUrl.indexOf( "/images/" ) + "/images/".length() );
 
-        output = generator.generate( files, baseUrl, imagesBaseUrl, getContinuum().getWorkingDirectory( projectId ) );
-
-        if ( currentFile != null && !currentFile.equals( "" ) )
+        if ( getContinuum().getConfiguration().isDistributedBuildEnabled() )
         {
-            String dir;
+            output = distributedBuildManager.generateWorkingCopyContent( projectId, userDirectory, baseUrl,
+                                                                         imagesBaseUrl );
 
-            //TODO: maybe create a plexus component for this so that additional mimetypes can be easily added
-            MimetypesFileTypeMap mimeTypesMap = new MimetypesFileTypeMap();
-            mimeTypesMap.addMimeTypes( "application/java-archive jar war ear" );
-            mimeTypesMap.addMimeTypes( "application/java-class class" );
-            mimeTypesMap.addMimeTypes( "image/png png" );
-
-            if ( FILE_SEPARATOR.equals( userDirectory ) )
+            if ( currentFile != null && !currentFile.equals( "" ) )
             {
-                dir = userDirectory;
+                Map<String, Object> projectFile = distributedBuildManager.getFileContent( projectId, userDirectory,
+                                                                                          currentFile );
+
+                if ( projectFile == null )
+                {
+                    currentFileContent = "";
+                }
+                else
+                {
+                    downloadFileInputStream = new ByteArrayInputStream( (byte[]) projectFile.get( "downloadFile" ) );
+                    downloadFileLength = (String) projectFile.get( "downloadFileLength" );
+                    downloadFileName = (String) projectFile.get( "downloadFileName" );
+                    currentFileContent = (String) projectFile.get( "fileContent" );
+                    mimeType = (String) projectFile.get( "mimeType" );
+
+                    if ( (Boolean) projectFile.get( "isStream" ) )
+                    {
+                        return "stream";
+                    }
+                }
             }
             else
             {
-                dir = FILE_SEPARATOR + userDirectory + FILE_SEPARATOR;
+                currentFileContent = "";
             }
-
-            downloadFile = new File( getContinuum().getWorkingDirectory( projectId ) + dir + currentFile );
-            mimeType = mimeTypesMap.getContentType( downloadFile );
-
-            if ( ( mimeType.indexOf( "image" ) >= 0 ) || ( mimeType.indexOf( "java-archive" ) >= 0 ) ||
-                ( mimeType.indexOf( "java-class" ) >= 0 ) || ( downloadFile.length() > 100000 ) )
-            {
-                return "stream";
-            }
-
-            currentFileContent = getContinuum().getFileContent( projectId, userDirectory, currentFile );
         }
         else
         {
-            currentFileContent = "";
+            List<File> files = getContinuum().getFiles( projectId, userDirectory );
+
+            output = generator.generate( files, baseUrl, imagesBaseUrl, getContinuum().getWorkingDirectory(
+                projectId ) );
+
+            if ( currentFile != null && !currentFile.equals( "" ) )
+            {
+                String dir;
+
+                //TODO: maybe create a plexus component for this so that additional mimetypes can be easily added
+                MimetypesFileTypeMap mimeTypesMap = new MimetypesFileTypeMap();
+                mimeTypesMap.addMimeTypes( "application/java-archive jar war ear" );
+                mimeTypesMap.addMimeTypes( "application/java-class class" );
+                mimeTypesMap.addMimeTypes( "image/png png" );
+
+                if ( FILE_SEPARATOR.equals( userDirectory ) )
+                {
+                    dir = userDirectory;
+                }
+                else
+                {
+                    dir = FILE_SEPARATOR + userDirectory + FILE_SEPARATOR;
+                }
+
+                downloadFile = new File( getContinuum().getWorkingDirectory( projectId ) + dir + currentFile );
+                mimeType = mimeTypesMap.getContentType( downloadFile );
+                downloadFileLength = Long.toString( downloadFile.length() );
+                downloadFileName = downloadFile.getName();
+
+                if ( ( mimeType.indexOf( "image" ) >= 0 ) || ( mimeType.indexOf( "java-archive" ) >= 0 ) ||
+                    ( mimeType.indexOf( "java-class" ) >= 0 ) || ( downloadFile.length() > 100000 ) )
+                {
+                    return "stream";
+                }
+
+                currentFileContent = getContinuum().getFileContent( projectId, userDirectory, currentFile );
+            }
+            else
+            {
+                currentFileContent = "";
+            }
         }
 
         return SUCCESS;
@@ -196,27 +252,34 @@
     public InputStream getInputStream()
         throws ContinuumException
     {
-        FileInputStream fis;
-        try
+        if ( getContinuum().getConfiguration().isDistributedBuildEnabled() )
         {
-            fis = new FileInputStream( downloadFile );
+            return downloadFileInputStream;
         }
-        catch ( FileNotFoundException fne )
+        else
         {
-            throw new ContinuumException( "Error accessing file.", fne );
-        }
+            FileInputStream fis;
+            try
+            {
+                fis = new FileInputStream( downloadFile );
+            }
+            catch ( FileNotFoundException fne )
+            {
+                throw new ContinuumException( "Error accessing file.", fne );
+            }
 
-        return fis;
+            return fis;
+        }
     }
 
     public String getFileLength()
     {
-        return Long.toString( downloadFile.length() );
+        return downloadFileLength;
     }
 
     public String getDownloadFilename()
     {
-        return downloadFile.getName();
+        return downloadFileName;
     }
 
     public String getMimeType()
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction.java
index 992fb29..136815e 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction.java
@@ -19,15 +19,13 @@
  * under the License.
  */
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-
+import com.opensymphony.xwork2.Preparable;
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.continuum.web.util.AuditLog;
+import org.apache.continuum.web.util.AuditLogConstants;
 import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.builddefinition.BuildDefinitionServiceException;
+import org.apache.maven.continuum.builddefinition.BuildDefinitionUpdatePolicyConstants;
 import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.BuildDefinitionTemplate;
@@ -41,13 +39,19 @@
 import org.codehaus.redback.integration.interceptor.SecureActionBundle;
 import org.codehaus.redback.integration.interceptor.SecureActionException;
 
-import com.opensymphony.xwork2.Preparable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
 
 /**
  * @author <a href="mailto:olamy@apache.org">olamy</a>
- * @since 16 sept. 07
  * @version $Id$
  * @plexus.component role="com.opensymphony.xwork2.Action" role-hint="buildDefinitionTemplates"
+ * @since 16 sept. 07
  */
 public class BuildDefinitionTemplateAction
     extends AbstractBuildDefinitionAction
@@ -66,15 +70,18 @@
     private Collection<Schedule> schedules;
 
     private List<Profile> profiles;
- 
+
     private List<String> selectedBuildDefinitionIds;
-    
+
     private List<BuildDefinition> buildDefinitions;
-    
+
+    private Map<Integer, String> buildDefinitionUpdatePolicies;
+
     // -------------------------------------------------------
     //  Webwork Methods
     // ------------------------------------------------------- 
 
+    @Override
     public void prepare()
         throws Exception
     {
@@ -87,6 +94,14 @@
         this.setSchedules( getContinuum().getSchedules() );
         this.setProfiles( getContinuum().getProfileService().getAllProfiles() );
         this.setBuildDefinitions( getContinuum().getBuildDefinitionService().getAllTemplates() );
+        buildDefinitionUpdatePolicies = new HashMap<Integer, String>();
+        String text = getText( "buildDefinition.updatePolicy.always" );
+        buildDefinitionUpdatePolicies.put( BuildDefinitionUpdatePolicyConstants.UPDATE_DESCRIPTION_ALWAYS, text );
+        text = getText( "buildDefinition.updatePolicy.never" );
+        buildDefinitionUpdatePolicies.put( BuildDefinitionUpdatePolicyConstants.UPDATE_DESCRIPTION_NEVER, text );
+        text = getText( "buildDefinition.updatePolicy.newPom" );
+        buildDefinitionUpdatePolicies.put( BuildDefinitionUpdatePolicyConstants.UPDATE_DESCRIPTION_ONLY_FOR_NEW_POM,
+                                           text );
     }
 
     public String input()
@@ -107,16 +122,15 @@
     public String edit()
         throws Exception
     {
-        this.buildDefinitionTemplate = getContinuum().getBuildDefinitionService()
-            .getBuildDefinitionTemplate( this.buildDefinitionTemplate.getId() );
+        this.buildDefinitionTemplate = getContinuum().getBuildDefinitionService().getBuildDefinitionTemplate(
+            this.buildDefinitionTemplate.getId() );
         this.setBuildDefinitions( getContinuum().getBuildDefinitionService().getAllTemplates() );
         this.selectedBuildDefinitionIds = new ArrayList<String>();
         if ( this.buildDefinitionTemplate.getBuildDefinitions() != null )
         {
-            for ( Iterator<BuildDefinition> iterator = this.buildDefinitionTemplate.getBuildDefinitions().iterator(); iterator
-                .hasNext(); )
+            for ( BuildDefinition bd : (List<BuildDefinition>) buildDefinitionTemplate.getBuildDefinitions() )
             {
-                this.selectedBuildDefinitionIds.add( Integer.toString( iterator.next().getId() ) );
+                this.selectedBuildDefinitionIds.add( Integer.toString( bd.getId() ) );
             }
         }
         List<BuildDefinition> nonUsedBuildDefinitions = new ArrayList<BuildDefinition>();
@@ -135,16 +149,36 @@
         throws Exception
     {
         List<BuildDefinition> selectedBuildDefinitions = getBuildDefinitionsFromSelectedBuildDefinitions();
+
+        BuildDefinitionTemplate result;
+
+        AuditLog event = new AuditLog( buildDefinitionTemplate.getName(), AuditLogConstants.ADD_TEMPLATE );
+        event.setCategory( AuditLogConstants.TEMPLATE );
+        event.setCurrentUser( getPrincipal() );
+
         if ( this.buildDefinitionTemplate.getId() > 0 )
         {
             buildDefinitionTemplate.setBuildDefinitions( selectedBuildDefinitions );
-            this.getContinuum().getBuildDefinitionService().updateBuildDefinitionTemplate( buildDefinitionTemplate );
+            result = this.getContinuum().getBuildDefinitionService().updateBuildDefinitionTemplate(
+                buildDefinitionTemplate );
+            event.setAction( AuditLogConstants.MODIFY_TEMPLATE );
         }
         else
         {
             buildDefinitionTemplate.setBuildDefinitions( selectedBuildDefinitions );
-            this.buildDefinitionTemplate = this.getContinuum().getBuildDefinitionService()
-                .addBuildDefinitionTemplate( buildDefinitionTemplate );
+            this.buildDefinitionTemplate = this.getContinuum().getBuildDefinitionService().addBuildDefinitionTemplate(
+                buildDefinitionTemplate );
+            result = this.buildDefinitionTemplate;
+        }
+
+        if ( result == null )
+        {
+            addActionError( getText( "buildDefintionTemplate.name.exists" ) );
+            return INPUT;
+        }
+        else
+        {
+            event.log();
         }
 
         return SUCCESS;
@@ -153,13 +187,26 @@
     public String delete()
         throws BuildDefinitionServiceException
     {
-        buildDefinitionTemplate = getContinuum().getBuildDefinitionService()
-            .getBuildDefinitionTemplate( this.buildDefinitionTemplate.getId() );
-        this.getContinuum().getBuildDefinitionService().removeBuildDefinitionTemplate( buildDefinitionTemplate );
+        if ( confirmed )
+        {
+            buildDefinitionTemplate = getContinuum().getBuildDefinitionService().getBuildDefinitionTemplate(
+                this.buildDefinitionTemplate.getId() );
+
+            AuditLog event = new AuditLog( buildDefinitionTemplate.getName(), AuditLogConstants.REMOVE_TEMPLATE );
+            event.setCategory( AuditLogConstants.TEMPLATE );
+            event.setCurrentUser( getPrincipal() );
+            event.log();
+
+            this.getContinuum().getBuildDefinitionService().removeBuildDefinitionTemplate( buildDefinitionTemplate );
+        }
+        else
+        {
+            return CONFIRM;
+        }
         return SUCCESS;
     }
-    
-    private List<BuildDefinition> getBuildDefinitionsFromSelectedBuildDefinitions()
+
+    public List<BuildDefinition> getBuildDefinitionsFromSelectedBuildDefinitions()
         throws ContinuumException
     {
         if ( this.selectedBuildDefinitionIds == null )
@@ -169,8 +216,8 @@
         List<BuildDefinition> selectedBuildDefinitions = new ArrayList<BuildDefinition>();
         for ( String selectedBuildDefinitionId : selectedBuildDefinitionIds )
         {
-            BuildDefinition buildDefinition = getContinuum()
-                .getBuildDefinition( Integer.parseInt( selectedBuildDefinitionId ) );
+            BuildDefinition buildDefinition = getContinuum().getBuildDefinition( Integer.parseInt(
+                selectedBuildDefinitionId ) );
             selectedBuildDefinitions.add( buildDefinition );
         }
         return selectedBuildDefinitions;
@@ -180,23 +227,23 @@
     //  BuildDefinition
     // -----------------------------------------------------
 
-    public String inputBuildDefinition()
-    {
-        return INPUT;
-    }
-    
     public String editBuildDefinition()
         throws Exception
     {
         this.buildDefinition = getContinuum().getBuildDefinitionService().getBuildDefinition(
-                                                                                              this.buildDefinition
-                                                                                                  .getId() );
+            this.buildDefinition.getId() );
         return SUCCESS;
     }
 
     public String saveBuildDefinition()
         throws Exception
     {
+        Schedule schedule = null;
+
+        // need to escape xml to prevent xss attacks
+        buildDefinition.setDescription( StringEscapeUtils.escapeXml( StringEscapeUtils.unescapeXml(
+            buildDefinition.getDescription() ) ) );
+
         if ( buildDefinition.getProfile() != null )
         {
             Profile profile = getContinuum().getProfileService().getProfile( buildDefinition.getProfile().getId() );
@@ -213,18 +260,24 @@
         {
             if ( buildDefinition.getSchedule().getId() > 0 )
             {
-                buildDefinition.setSchedule( getContinuum().getSchedule( buildDefinition.getSchedule().getId() ) );
+                schedule = getContinuum().getSchedule( buildDefinition.getSchedule().getId() );
+                buildDefinition.setSchedule( schedule );
             }
         }
-        
-        
+
         if ( this.buildDefinition.getId() > 0 )
         {
             this.getContinuum().getBuildDefinitionService().updateBuildDefinition( buildDefinition );
         }
         else
         {
-            this.buildDefinition = this.getContinuum().getBuildDefinitionService().addBuildDefinition( buildDefinition );
+            this.buildDefinition = this.getContinuum().getBuildDefinitionService().addBuildDefinition(
+                buildDefinition );
+        }
+
+        if ( schedule != null )
+        {
+            getContinuum().activeBuildDefinitionSchedule( schedule );
         }
 
         return SUCCESS;
@@ -233,8 +286,25 @@
     public String deleteBuildDefinition()
         throws BuildDefinitionServiceException
     {
-        buildDefinition = getContinuum().getBuildDefinitionService().getBuildDefinition( this.buildDefinition.getId() );
-        this.getContinuum().getBuildDefinitionService().removeBuildDefinition( buildDefinition );
+        if ( confirmed )
+        {
+            if ( getContinuum().getBuildDefinitionService().isBuildDefinitionInUse( buildDefinition ) )
+            {
+                addActionError( getText( "buildDefinition.used" ) );
+                return ERROR;
+            }
+            else
+            {
+                buildDefinition =
+                    getContinuum().getBuildDefinitionService().getBuildDefinition( this.buildDefinition.getId() );
+                this.getContinuum().getBuildDefinitionService().removeBuildDefinition( buildDefinition );
+            }
+        }
+        else
+        {
+            return CONFIRM;
+        }
+
         return SUCCESS;
     }
 
@@ -258,7 +328,7 @@
 
     public BuildDefinitionTemplate getBuildDefinitionTemplate()
     {
-        if (buildDefinitionTemplate == null)
+        if ( buildDefinitionTemplate == null )
         {
             this.buildDefinitionTemplate = new BuildDefinitionTemplate();
         }
@@ -333,7 +403,7 @@
     {
         return schedules;
     }
-    
+
     public List<BuildDefinition> getBuildDefinitions()
     {
         return buildDefinitions;
@@ -354,4 +424,9 @@
         this.selectedBuildDefinitionIds = selectedBuildDefinitionIds;
     }
 
+    public Map<Integer, String> getBuildDefinitionUpdatePolicies()
+    {
+        return buildDefinitionUpdatePolicies;
+    }
+
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/BuildQueueAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/BuildQueueAction.java
new file mode 100644
index 0000000..4f1ff97
--- /dev/null
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/BuildQueueAction.java
@@ -0,0 +1,258 @@
+package org.apache.maven.continuum.web.action.admin;
+
+/*
+ * 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 com.opensymphony.xwork2.Preparable;
+import org.apache.continuum.buildmanager.BuildManagerException;
+import org.apache.continuum.web.util.AuditLog;
+import org.apache.continuum.web.util.AuditLogConstants;
+import org.apache.maven.continuum.ContinuumException;
+import org.apache.maven.continuum.model.project.BuildQueue;
+import org.apache.maven.continuum.security.ContinuumRoleConstants;
+import org.apache.maven.continuum.web.action.ContinuumConfirmAction;
+import org.codehaus.plexus.redback.rbac.Resource;
+import org.codehaus.redback.integration.interceptor.SecureAction;
+import org.codehaus.redback.integration.interceptor.SecureActionBundle;
+import org.codehaus.redback.integration.interceptor.SecureActionException;
+
+import java.util.List;
+
+/**
+ * @plexus.component role="com.opensymphony.xwork2.Action" role-hint="buildQueueAction"
+ */
+public class BuildQueueAction
+    extends ContinuumConfirmAction
+    implements Preparable, SecureAction
+{
+    private String name;
+
+    private int size;
+
+    private List<BuildQueue> buildQueueList;
+
+    private BuildQueue buildQueue;
+
+    private String message;
+
+    private boolean confirmed;
+
+    public void prepare()
+        throws ContinuumException
+    {
+        this.buildQueueList = getContinuum().getAllBuildQueues();
+    }
+
+    public String input()
+    {
+        return INPUT;
+    }
+
+    public String list()
+        throws Exception
+    {
+        try
+        {
+            this.buildQueueList = getContinuum().getAllBuildQueues();
+        }
+        catch ( ContinuumException e )
+        {
+            addActionError( "Cannot get build queues from the database : " + e.getMessage() );
+            return ERROR;
+        }
+        return SUCCESS;
+    }
+
+    public String save()
+        throws Exception
+    {
+        int allowedBuilds = getContinuum().getConfiguration().getNumberOfBuildsInParallel();
+        if ( allowedBuilds < ( this.buildQueueList.size() + 1 ) )
+        {
+            addActionError( "You are only allowed " + allowedBuilds + " number of builds in parallel." );
+            return ERROR;
+        }
+        else
+        {
+            try
+            {
+                if ( !isDuplicate( name ) )
+                {
+                    BuildQueue buildQueue = new BuildQueue();
+                    buildQueue.setName( name );
+                    BuildQueue addedBuildQueue = getContinuum().addBuildQueue( buildQueue );
+
+                    getContinuum().getBuildsManager().addOverallBuildQueue( addedBuildQueue );
+
+                    AuditLog event = new AuditLog( "Build Queue id=" + addedBuildQueue.getId(),
+                                                   AuditLogConstants.ADD_BUILD_QUEUE );
+                    event.setCategory( AuditLogConstants.BUILD_QUEUE );
+                    event.setCurrentUser( getPrincipal() );
+                    event.log();
+                }
+                else
+                {
+                    addActionError( "Build queue name already exists." );
+                    return ERROR;
+                }
+            }
+            catch ( ContinuumException e )
+            {
+                addActionError( "Error adding build queue to database: " + e.getMessage() );
+                return ERROR;
+            }
+            catch ( BuildManagerException e )
+            {
+                addActionError( "Error creating overall build queue: " + e.getMessage() );
+                return ERROR;
+            }
+
+            return SUCCESS;
+        }
+    }
+
+    public String edit()
+        throws Exception
+    {
+        try
+        {
+            BuildQueue buildQueueToBeEdited = getContinuum().getBuildQueue( this.buildQueue.getId() );
+        }
+        catch ( ContinuumException e )
+        {
+            addActionError( "Error retrieving build queue from the database : " + e.getMessage() );
+            return ERROR;
+        }
+        return SUCCESS;
+    }
+
+    public String delete()
+        throws Exception
+    {
+        if ( confirmed )
+        {
+            BuildQueue buildQueueToBeDeleted = getContinuum().getBuildQueue( this.buildQueue.getId() );
+            getContinuum().getBuildsManager().removeOverallBuildQueue( buildQueueToBeDeleted.getId() );
+            getContinuum().removeBuildQueue( buildQueueToBeDeleted );
+
+            this.buildQueueList = getContinuum().getAllBuildQueues();
+
+            AuditLog event = new AuditLog( "Build Queue id=" + buildQueue.getId(),
+                                           AuditLogConstants.REMOVE_BUILD_QUEUE );
+            event.setCategory( AuditLogConstants.BUILD_QUEUE );
+            event.setCurrentUser( getPrincipal() );
+            event.log();
+        }
+        else
+        {
+            return CONFIRM;
+        }
+
+        return SUCCESS;
+    }
+
+    public SecureActionBundle getSecureActionBundle()
+        throws SecureActionException
+    {
+        SecureActionBundle bundle = new SecureActionBundle();
+        bundle.setRequiresAuthentication( true );
+        bundle.addRequiredAuthorization( ContinuumRoleConstants.CONTINUUM_MANAGE_PARALLEL_BUILDS, Resource.GLOBAL );
+
+        return bundle;
+    }
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName( String name )
+    {
+        this.name = name;
+    }
+
+    public List<BuildQueue> getBuildQueueList()
+    {
+        return buildQueueList;
+    }
+
+    public void setBuildQueueList( List<BuildQueue> buildQueueList )
+    {
+        this.buildQueueList = buildQueueList;
+    }
+
+    public int getSize()
+    {
+        return size;
+    }
+
+    public void setSize( int size )
+    {
+        this.size = size;
+    }
+
+    public BuildQueue getBuildQueue()
+    {
+        return buildQueue;
+    }
+
+    public void setBuildQueue( BuildQueue buildQueue )
+    {
+        this.buildQueue = buildQueue;
+    }
+
+    public String getMessage()
+    {
+        return message;
+    }
+
+    public void setMessage( String message )
+    {
+        this.message = message;
+    }
+
+    private boolean isDuplicate( String queueName )
+        throws ContinuumException
+    {
+        boolean isExisting = false;
+
+        List<BuildQueue> buildQueues = getContinuum().getAllBuildQueues();
+
+        for ( BuildQueue bq : buildQueues )
+        {
+            if ( queueName.equals( bq.getName() ) )
+            {
+                isExisting = true;
+                break;
+            }
+        }
+
+        return isExisting;
+    }
+
+    public boolean isConfirmed()
+    {
+        return confirmed;
+    }
+
+    public void setConfirmed( boolean confirmed )
+    {
+        this.confirmed = confirmed;
+    }
+}
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/ConfigurationAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/ConfigurationAction.java
index d0dedac..e21155c 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/ConfigurationAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/ConfigurationAction.java
@@ -19,10 +19,7 @@
  * under the License.
  */
 
-import java.io.File;
-
-import javax.servlet.http.HttpServletRequest;
-
+import com.opensymphony.xwork2.Preparable;
 import org.apache.continuum.configuration.ContinuumConfigurationException;
 import org.apache.maven.continuum.configuration.ConfigurationService;
 import org.apache.maven.continuum.configuration.ConfigurationStoringException;
@@ -35,8 +32,11 @@
 import org.codehaus.redback.integration.interceptor.SecureAction;
 import org.codehaus.redback.integration.interceptor.SecureActionBundle;
 import org.codehaus.redback.integration.interceptor.SecureActionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-import com.opensymphony.xwork2.Preparable;
+import java.io.File;
+import javax.servlet.http.HttpServletRequest;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
@@ -47,6 +47,8 @@
     extends ContinuumActionSupport
     implements Preparable, SecureAction
 {
+    private static final Logger logger = LoggerFactory.getLogger( ConfigurationAction.class );
+
     private String workingDirectory;
 
     private String buildOutputDirectory;
@@ -54,13 +56,17 @@
     private String deploymentRepositoryDirectory;
 
     private String baseUrl;
-    
+
     private String releaseOutputDirectory;
 
+    private int numberOfAllowedBuildsinParallel = 1;
+
     private boolean requireReleaseOutput;
 
     private boolean distributedBuildEnabled;
 
+    private String sharedSecretPassword;
+
     public void prepare()
     {
         ConfigurationService configuration = getContinuum().getConfiguration();
@@ -90,7 +96,7 @@
             HttpServletRequest request = ServletActionContext.getRequest();
             baseUrl = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() +
                 request.getContextPath();
-            getLogger().info( "baseUrl='" + baseUrl + "'" );
+            logger.info( "baseUrl='" + baseUrl + "'" );
         }
 
         File releaseOutputDirectoryFile = configuration.getReleaseOutputDirectory();
@@ -98,11 +104,20 @@
         {
             releaseOutputDirectory = releaseOutputDirectoryFile.getAbsolutePath();
         }
-        
+
+        numberOfAllowedBuildsinParallel = configuration.getNumberOfBuildsInParallel();
+
+        if ( numberOfAllowedBuildsinParallel == 0 )
+        {
+            numberOfAllowedBuildsinParallel = 1;
+        }
+
         String requireRelease = ServletActionContext.getRequest().getParameter( "requireReleaseOutput" );
-        setRequireReleaseOutput( new Boolean( requireRelease ) );
+        setRequireReleaseOutput( Boolean.valueOf( requireRelease ) );
 
         distributedBuildEnabled = configuration.isDistributedBuildEnabled();
+
+        sharedSecretPassword = configuration.getSharedSecretPassword();
     }
 
     public String input()
@@ -111,19 +126,32 @@
         {
             addActionError( getText( "configuration.releaseOutputDirectory.required" ) );
         }
-        
+
+        if ( numberOfAllowedBuildsinParallel <= 0 )
+        {
+            addActionError( getText( "configuration.numberOfBuildsInParallel.invalid" ) );
+        }
+
         return INPUT;
     }
 
     public String save()
         throws ConfigurationStoringException, ContinuumStoreException, ContinuumConfigurationException
     {
+        if ( numberOfAllowedBuildsinParallel <= 0 )
+        {
+            addActionError( "Number of Allowed Builds in Parallel must be greater than zero." );
+            return ERROR;
+        }
+
         ConfigurationService configuration = getContinuum().getConfiguration();
 
         configuration.setWorkingDirectory( new File( workingDirectory ) );
 
         configuration.setBuildOutputDirectory( new File( buildOutputDirectory ) );
 
+        configuration.setNumberOfBuildsInParallel( numberOfAllowedBuildsinParallel );
+
         if ( StringUtils.isNotEmpty( deploymentRepositoryDirectory ) )
         {
             configuration.setDeploymentRepositoryDirectory( new File( deploymentRepositoryDirectory ) );
@@ -153,6 +181,8 @@
 
         configuration.setDistributedBuildEnabled( distributedBuildEnabled );
 
+        configuration.setSharedSecretPassword( sharedSecretPassword );
+
         configuration.store();
 
         return SUCCESS;
@@ -222,12 +252,22 @@
     {
         return requireReleaseOutput;
     }
-    
+
     public void setRequireReleaseOutput( boolean requireReleaseOutput )
     {
         this.requireReleaseOutput = requireReleaseOutput;
     }
 
+    public int getNumberOfAllowedBuildsinParallel()
+    {
+        return numberOfAllowedBuildsinParallel;
+    }
+
+    public void setNumberOfAllowedBuildsinParallel( int numberOfAllowedBuildsinParallel )
+    {
+        this.numberOfAllowedBuildsinParallel = numberOfAllowedBuildsinParallel;
+    }
+
     public boolean isDistributedBuildEnabled()
     {
         return distributedBuildEnabled;
@@ -237,4 +277,14 @@
     {
         this.distributedBuildEnabled = distributedBuildEnabled;
     }
+
+    public void setSharedSecretPassword( String sharedSecretPassword )
+    {
+        this.sharedSecretPassword = sharedSecretPassword;
+    }
+
+    public String getSharedSecretPassword()
+    {
+        return sharedSecretPassword;
+    }
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/ConfigureAppearanceAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/ConfigureAppearanceAction.java
index 9c5d41c..a1966f1 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/ConfigureAppearanceAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/ConfigureAppearanceAction.java
@@ -19,11 +19,7 @@
  * under the License.
  */
 
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
+import com.opensymphony.xwork2.ModelDriven;
 import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
 import org.apache.maven.artifact.repository.ArtifactRepository;
 import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
@@ -49,7 +45,10 @@
 import org.codehaus.redback.integration.interceptor.SecureActionBundle;
 import org.codehaus.redback.integration.interceptor.SecureActionException;
 
-import com.opensymphony.xwork2.ModelDriven;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
 
 /**
  * @author <a href="mailto:brett@apache.org">Brett Porter</a>
@@ -145,9 +144,10 @@
                     {
                         for ( Repository repo : repos )
                         {
-                            remoteRepositories.add(
-                                artifactRepositoryFactory.createArtifactRepository( repo.getId(), repo
-                                    .getUrl(), layout, null, null ) );
+                            remoteRepositories.add( artifactRepositoryFactory.createArtifactRepository( repo.getId(),
+                                                                                                        repo.getUrl(),
+                                                                                                        layout, null,
+                                                                                                        null ) );
                         }
                     }
                 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/ConfigureFooterAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/ConfigureFooterAction.java
index a947cf5..bba7c95 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/ConfigureFooterAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/ConfigureFooterAction.java
@@ -1,3 +1,5 @@
+package org.apache.maven.continuum.web.action.admin;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,18 +18,17 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.continuum.web.action.admin;
-
-import java.io.IOException;
 
 import org.apache.maven.continuum.web.action.component.AbstractFooterAction;
 import org.apache.maven.continuum.web.appareance.AppareanceConfiguration;
 
+import java.io.IOException;
+
 /**
  * @author <a href="mailto:olamy@apache.org">olamy</a>
- * @since 9 nov. 07
  * @version $Id$
  * @plexus.component role="com.opensymphony.xwork2.Action" role-hint="configureFooter"
+ * @since 9 nov. 07
  */
 public class ConfigureFooterAction
     extends AbstractFooterAction
@@ -35,13 +36,14 @@
 
     /**
      * @plexus.requirement
-     */    
+     */
     private AppareanceConfiguration appareanceConfiguration;
 
     public String saveFooter()
         throws IOException
     {
         appareanceConfiguration.saveFooter( getFooter() );
+        addActionMessage( getResourceBundle().getString( "appearance.footerContent.success" ) );
         return SUCCESS;
     }
 
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/EditPomAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/EditPomAction.java
index 75ff1cd..4ca5529 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/EditPomAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/EditPomAction.java
@@ -19,8 +19,7 @@
  * under the License.
  */
 
-import java.io.IOException;
-
+import com.opensymphony.xwork2.ModelDriven;
 import org.apache.maven.artifact.installer.ArtifactInstallationException;
 import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
 import org.apache.maven.continuum.execution.maven.m2.MavenBuilderHelper;
@@ -38,7 +37,7 @@
 import org.codehaus.redback.integration.interceptor.SecureActionBundle;
 import org.codehaus.redback.integration.interceptor.SecureActionException;
 
-import com.opensymphony.xwork2.ModelDriven;
+import java.io.IOException;
 
 /**
  * @author <a href="mailto:brett@apache.org">Brett Porter</a>
@@ -55,17 +54,14 @@
     private MavenAppConfiguration appConfiguration;
 
     /**
-     * The configuration.
-     */
-    private Configuration configuration;
-
-    /**
      * @plexus.requirement
      */
     private CompanyPomHandler companyPomHandler;
 
     private Model companyModel;
 
+    private String organizationLogo;
+
     /**
      * @plexus.requirement
      */
@@ -74,11 +70,9 @@
     public String execute()
         throws IOException, ArtifactInstallationException, SettingsConfigurationException
     {
-        // TODO: hack for passed in String[]
-        String[] logo = (String[]) companyModel.getProperties().get( "organization.logo" );
-        if ( logo != null )
+        if ( organizationLogo != null )
         {
-            companyModel.getProperties().put( "organization.logo", logo[0] );
+            companyModel.getProperties().setProperty( "organization.logo", organizationLogo );
         }
 
         companyPomHandler.save( companyModel, helper.getLocalRepository() );
@@ -99,7 +93,7 @@
     public void prepare()
         throws ProjectBuildingException, ArtifactMetadataRetrievalException, SettingsConfigurationException
     {
-        configuration = appConfiguration.getConfiguration();
+        Configuration configuration = appConfiguration.getConfiguration();
 
         CompanyPom companyPom = configuration.getCompanyPom();
         companyModel = companyPomHandler.getCompanyPomModel( companyPom, helper.getLocalRepository() );
@@ -116,6 +110,18 @@
                 companyModel.setArtifactId( companyPom.getArtifactId() );
             }
         }
+
+        organizationLogo = companyModel.getProperties().getProperty( "organization.logo" );
+    }
+
+    public String getOrganizationLogo()
+    {
+        return organizationLogo;
+    }
+
+    public void setOrganizationLogo( String organizationLogo )
+    {
+        this.organizationLogo = organizationLogo;
     }
 
     public Model getCompanyModel()
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/InstallationAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/InstallationAction.java
index 1e8f837..75c2c0a 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/InstallationAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/InstallationAction.java
@@ -1,22 +1,23 @@
 package org.apache.maven.continuum.web.action.admin;
 
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.ResourceBundle;
-
+import com.opensymphony.xwork2.Preparable;
+import org.apache.commons.lang.StringUtils;
 import org.apache.maven.continuum.installation.AlreadyExistsInstallationException;
 import org.apache.maven.continuum.installation.InstallationService;
 import org.apache.maven.continuum.model.system.Installation;
+import org.apache.maven.continuum.profile.AlreadyExistsProfileException;
 import org.apache.maven.continuum.security.ContinuumRoleConstants;
-import org.apache.maven.continuum.web.action.ContinuumActionSupport;
+import org.apache.maven.continuum.web.action.ContinuumConfirmAction;
 import org.codehaus.plexus.redback.rbac.Resource;
 import org.codehaus.redback.integration.interceptor.SecureAction;
 import org.codehaus.redback.integration.interceptor.SecureActionBundle;
 import org.codehaus.redback.integration.interceptor.SecureActionException;
 
-import com.opensymphony.xwork2.Preparable;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.ResourceBundle;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -36,6 +37,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 /**
  * @author <a href="mailto:olamy@codehaus.org">olamy</a>
  * @version $Id$
@@ -43,7 +45,7 @@
  * @since 14 juin 07
  */
 public class InstallationAction
-    extends ContinuumActionSupport
+    extends ContinuumConfirmAction
     implements Preparable, SecureAction
 {
 
@@ -61,21 +63,23 @@
     private List<String> types;
 
     private boolean varNameUpdatable = false;
-   
+
     private boolean automaticProfile;
-   
+
     private boolean varNameDisplayable = false;
-    
+
     private boolean displayTypes = true;
-    
+
     private String installationType;
-    
+
     private Map<String, String> installationTypes;
-    
+
     private static final String TOOL_TYPE_KEY = "tool";
-    
+
     private boolean automaticProfileDisplayable = true;
-   
+
+    private boolean confirmed;
+
     // -----------------------------------------------------
     // Webwork methods
     // -----------------------------------------------------
@@ -125,6 +129,13 @@
         if ( InstallationService.ENVVAR_TYPE.equalsIgnoreCase( this.getInstallationType() ) )
         {
             this.installation.setType( InstallationService.ENVVAR_TYPE );
+            if ( StringUtils.isEmpty( installation.getVarName() ) )
+            {
+                addFieldError( "installation.varName", getResourceBundle().getString(
+                    "installation.varName.required" ) );
+                return INPUT;
+            }
+
         }
         if ( installation.getInstallationId() == 0 )
         {
@@ -137,23 +148,41 @@
                 this.addActionError( getResourceBundle().getString( "installation.name.duplicate" ) );
                 return INPUT;
             }
+            catch ( AlreadyExistsProfileException e )
+            {
+                this.addActionError( getResourceBundle().getString( "profile.name.already.exists" ) );
+                return INPUT;
+            }
         }
         else
         {
             this.configureUiFlags();
-            installationService.update( installation );
-            return "edit";
+            try
+            {
+                installationService.update( installation );
+            }
+            catch ( AlreadyExistsInstallationException e )
+            {
+                this.addActionError( getResourceBundle().getString( "installation.name.duplicate" ) );
+                return INPUT;
+            }
         }
-        this.configureUiFlags();
         return SUCCESS;
     }
 
     public String delete()
         throws Exception
     {
-        Installation installationToDelete = installationService.getInstallation( installation.getInstallationId() );
-        installationService.delete( installationToDelete );
-        this.installations = installationService.getAllInstallations();
+        if ( confirmed )
+        {
+            Installation installationToDelete = installationService.getInstallation( installation.getInstallationId() );
+            installationService.delete( installationToDelete );
+            this.installations = installationService.getAllInstallations();
+        }
+        else
+        {
+            return CONFIRM;
+        }
         return SUCCESS;
     }
 
@@ -162,15 +191,16 @@
         this.installationTypes = new LinkedHashMap<String, String>();
         ResourceBundle resourceBundle = getResourceBundle();
         this.installationTypes.put( TOOL_TYPE_KEY, resourceBundle.getString( "installationTypeChoice.tool.label" ) );
-        this.installationTypes.put( InstallationService.ENVVAR_TYPE, resourceBundle.getString( "installationTypeChoice.envar.label" ) );
+        this.installationTypes.put( InstallationService.ENVVAR_TYPE, resourceBundle.getString(
+            "installationTypeChoice.envar.label" ) );
 
         return SUCCESS;
     }
-    
+
     // -----------------------------------------------------
     // security
-    // -----------------------------------------------------    
-    
+    // -----------------------------------------------------
+
     public SecureActionBundle getSecureActionBundle()
         throws SecureActionException
     {
@@ -183,7 +213,7 @@
 
     // -----------------------------------------------------
     // utils
-    // -----------------------------------------------------    
+    // -----------------------------------------------------
     private void configureUiFlags()
     {
         // we can update env var name only with env var type
@@ -200,8 +230,7 @@
         }
         this.setInstallationType( this.getInstallation().getType() );
     }
-    
-    
+
     // -----------------------------------------------------
     // getter/setters
     // -----------------------------------------------------
@@ -232,14 +261,14 @@
         {
             this.typesLabels = new LinkedHashMap<String, String>();
             ResourceBundle resourceBundle = getResourceBundle();
-            this.typesLabels.put( InstallationService.JDK_TYPE, resourceBundle
-                .getString( "installation.jdk.type.label" ) );
-            this.typesLabels.put( InstallationService.MAVEN2_TYPE, resourceBundle
-                .getString( "installation.maven2.type.label" ) );
-            this.typesLabels.put( InstallationService.MAVEN1_TYPE, resourceBundle
-                .getString( "installation.maven1.type.label" ) );
-            this.typesLabels.put( InstallationService.ANT_TYPE, resourceBundle
-                .getString( "installation.ant.type.label" ) );
+            this.typesLabels.put( InstallationService.JDK_TYPE, resourceBundle.getString(
+                "installation.jdk.type.label" ) );
+            this.typesLabels.put( InstallationService.MAVEN2_TYPE, resourceBundle.getString(
+                "installation.maven2.type.label" ) );
+            this.typesLabels.put( InstallationService.MAVEN1_TYPE, resourceBundle.getString(
+                "installation.maven1.type.label" ) );
+            this.typesLabels.put( InstallationService.ANT_TYPE, resourceBundle.getString(
+                "installation.ant.type.label" ) );
             // CONTINUUM-1430
             //this.typesLabels.put( InstallationService.ENVVAR_TYPE, resourceBundle
             //    .getString( "installation.envvar.type.label" ) );
@@ -266,7 +295,7 @@
     {
         if ( this.types == null )
         {
-            this.types = new ArrayList<String>(5);
+            this.types = new ArrayList<String>( 5 );
             this.types.add( InstallationService.JDK_TYPE );
             this.types.add( InstallationService.MAVEN2_TYPE );
             this.types.add( InstallationService.MAVEN1_TYPE );
@@ -341,6 +370,15 @@
     public void setAutomaticProfileDisplayable( boolean automaticProfileDisplayable )
     {
         this.automaticProfileDisplayable = automaticProfileDisplayable;
-    }    
-    
+    }
+
+    public boolean isConfirmed()
+    {
+        return confirmed;
+    }
+
+    public void setConfirmed( boolean confirmed )
+    {
+        this.confirmed = confirmed;
+    }
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/ProfileAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/ProfileAction.java
index 04c319d..b9b9416 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/ProfileAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/ProfileAction.java
@@ -19,11 +19,9 @@
  * under the License.
  */
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
+import com.opensymphony.xwork2.Preparable;
 import org.apache.commons.lang.StringUtils;
+import org.apache.continuum.configuration.BuildAgentGroupConfiguration;
 import org.apache.maven.continuum.installation.InstallationService;
 import org.apache.maven.continuum.model.system.Installation;
 import org.apache.maven.continuum.model.system.Profile;
@@ -32,13 +30,16 @@
 import org.apache.maven.continuum.profile.ProfileService;
 import org.apache.maven.continuum.security.ContinuumRoleConstants;
 import org.apache.maven.continuum.web.action.ContinuumActionSupport;
-import org.apache.struts2.ServletActionContext;
 import org.codehaus.plexus.redback.rbac.Resource;
 import org.codehaus.redback.integration.interceptor.SecureAction;
 import org.codehaus.redback.integration.interceptor.SecureActionBundle;
 import org.codehaus.redback.integration.interceptor.SecureActionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-import com.opensymphony.xwork2.Preparable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 
 /**
  * @author <a href="mailto:olamy@codehaus.org">olamy</a>
@@ -49,8 +50,9 @@
 public class ProfileAction
     extends ContinuumActionSupport
     implements Preparable, SecureAction
-
 {
+    private static final Logger logger = LoggerFactory.getLogger( ProfileAction.class );
+
     /**
      * @plexus.requirement role-hint="default"
      */
@@ -71,7 +73,20 @@
 
     private List<Installation> profileInstallations;
 
-    private String message;
+    private List<BuildAgentGroupConfiguration> buildAgentGroups;
+
+    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
@@ -87,13 +102,6 @@
     public String list()
         throws Exception
     {
-        String errorMessage = ServletActionContext.getRequest().getParameter( "errorMessage" );
-
-        if ( errorMessage != null )
-        {
-            addActionError( errorMessage );
-        }
-        
         this.profiles = profileService.getAllProfiles();
         return SUCCESS;
     }
@@ -101,9 +109,9 @@
     public String edit()
         throws Exception
     {
-        if ( getLogger().isDebugEnabled() )
+        if ( logger.isDebugEnabled() )
         {
-            getLogger().debug( "edit profile with id " + profile.getId() );
+            logger.debug( "edit profile with id " + profile.getId() );
         }
         this.profile = profileService.getProfile( profile.getId() );
         return SUCCESS;
@@ -139,11 +147,16 @@
                 // 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 );
                 }
             }
@@ -159,18 +172,18 @@
 
     public String delete()
         throws Exception
-    {   
+    {
         try
         {
             profileService.deleteProfile( profile.getId() );
             this.profiles = profileService.getAllProfiles();
-            return SUCCESS;
         }
         catch ( ProfileException e )
         {
-            message = "profile.remove.error";
-            return ERROR;
+            // display action error in default/success page -- CONTINUUM-2250
+            addActionError( getText( "profile.remove.error" ) );
         }
+        return SUCCESS;
     }
 
     public String confirmDelete()
@@ -179,7 +192,7 @@
         this.profile = getContinuum().getProfileService().getProfile( profile.getId() );
         return SUCCESS;
     }
-    
+
     public String addInstallation()
         throws Exception
     {
@@ -206,7 +219,7 @@
     // -----------------------------------------------------
     // security
     // -----------------------------------------------------    
-    
+
     public SecureActionBundle getSecureActionBundle()
         throws SecureActionException
     {
@@ -215,8 +228,8 @@
         bundle.addRequiredAuthorization( ContinuumRoleConstants.CONTINUUM_MANAGE_PROFILES, Resource.GLOBAL );
 
         return bundle;
-    }    
-    
+    }
+
     // -------------------------------------------------------
     // Webwork setter/getter
     // -------------------------------------------------------
@@ -249,7 +262,7 @@
             this.allInstallations = installationService.getAllInstallations();
         }
         // CONTINUUM-1742 (olamy) don't display already attached en var
-        if (this.profile != null)
+        if ( this.profile != null )
         {
             this.allInstallations.removeAll( this.profile.getEnvironmentVariables() );
         }
@@ -302,13 +315,13 @@
         this.installationId = installationId;
     }
 
-    public String getMessage()
+    public List<BuildAgentGroupConfiguration> getBuildAgentGroups()
     {
-        return message;
+        return buildAgentGroups;
     }
 
-    public void setMessage( String message )
+    public void setBuildAgentGroups( List<BuildAgentGroupConfiguration> buildAgentGroups )
     {
-        this.message = message;
+        this.buildAgentGroups = buildAgentGroups;
     }
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/QueuesAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/QueuesAction.java
index 8c69d03..5f4382d 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/QueuesAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/admin/QueuesAction.java
@@ -19,32 +19,33 @@
  * under the License.
  */
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
 import org.apache.commons.lang.ArrayUtils;
-import org.apache.continuum.builder.distributed.manager.DistributedBuildManager;
-import org.apache.continuum.model.project.ProjectScmRoot;
+import org.apache.continuum.buildmanager.BuildManagerException;
 import org.apache.continuum.taskqueue.BuildProjectTask;
 import org.apache.continuum.taskqueue.CheckOutTask;
 import org.apache.continuum.taskqueue.PrepareBuildProjectsTask;
-import org.apache.continuum.taskqueue.manager.TaskQueueManager;
-import org.apache.maven.continuum.Continuum;
+import org.apache.continuum.utils.build.BuildTrigger;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.project.ProjectGroup;
-import org.apache.maven.continuum.project.ContinuumProjectState;
 import org.apache.maven.continuum.security.ContinuumRoleConstants;
 import org.apache.maven.continuum.web.action.ContinuumActionSupport;
+import org.apache.maven.continuum.web.bean.BuildProjectQueue;
+import org.apache.maven.continuum.web.bean.CheckoutQueue;
 import org.apache.maven.continuum.web.exception.AuthenticationRequiredException;
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
 import org.apache.maven.continuum.web.model.DistributedBuildSummary;
-import org.codehaus.plexus.logging.LogEnabled;
+import org.apache.maven.continuum.web.model.PrepareBuildSummary;
 import org.codehaus.plexus.redback.rbac.Resource;
-import org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor;
 import org.codehaus.redback.integration.interceptor.SecureAction;
 import org.codehaus.redback.integration.interceptor.SecureActionBundle;
 import org.codehaus.redback.integration.interceptor.SecureActionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 /**
  * @author <a href="mailto:olamy@apache.org">olamy</a>
@@ -54,32 +55,18 @@
  */
 public class QueuesAction
     extends ContinuumActionSupport
-    implements SecureAction, LogEnabled
+    implements SecureAction
 {
+    private static final Logger logger = LoggerFactory.getLogger( QueuesAction.class );
+
     private static final String DISTRIBUTED_BUILD_SUCCESS = "distributed-build-success";
 
-    /**
-     * @plexus.requirement role-hint='build-project'
-     */
-    private TaskQueueExecutor taskQueueExecutor;    
-    
-    private BuildProjectTask currentBuildProjectTask;
-    
-    private List<BuildProjectTask> buildProjectTasks;
-    
+    private List<String> selectedPrepareBuildTaskHashCodes;
+
     private List<String> selectedBuildTaskHashCodes;
-    
-    /**
-     * @plexus.requirement role-hint='check-out-project'
-     */    
-    private TaskQueueExecutor checkoutTaskQueueExecutor; 
-    
-    private CheckOutTask currentCheckOutTask;
-    
-    private List<CheckOutTask> currentCheckOutTasks;
-    
+
     private List<String> selectedCheckOutTaskHashCodes;
-    
+
     private int buildDefinitionId;
 
     private int projectId;
@@ -88,60 +75,44 @@
 
     private String projectName;
 
-    /**
-     * @plexus.requirement
-     */
-    private TaskQueueManager taskQueueManager;
+    private List<BuildProjectQueue> currentBuildProjectTasks = new ArrayList<BuildProjectQueue>();
 
-    /**
-     * @plexus.requirement
-     */
-    DistributedBuildManager distributedBuildManager;
+    private List<CheckoutQueue> currentCheckoutTasks = new ArrayList<CheckoutQueue>();
 
-    private List<DistributedBuildSummary> distributedBuildSummary;
+    private List<BuildProjectQueue> buildsInQueue = new ArrayList<BuildProjectQueue>();
 
-    private List<PrepareBuildProjectsTask> distributedBuildQueues;
+    private List<CheckoutQueue> checkoutsInQueue = new ArrayList<CheckoutQueue>();
+
+    private List<PrepareBuildSummary> currentPrepareBuilds = new ArrayList<PrepareBuildSummary>();
+
+    private List<PrepareBuildSummary> prepareBuildQueues = new ArrayList<PrepareBuildSummary>();
+
+    private List<PrepareBuildSummary> currentDistributedPrepareBuilds = new ArrayList<PrepareBuildSummary>();
+
+    private List<PrepareBuildSummary> distributedPrepareBuildQueues = new ArrayList<PrepareBuildSummary>();
+
+    private List<DistributedBuildSummary> currentDistributedBuilds = new ArrayList<DistributedBuildSummary>();
+
+    private List<DistributedBuildSummary> distributedBuildQueues = new ArrayList<DistributedBuildSummary>();
 
     private String buildAgentUrl;
 
     private int projectGroupId;
 
-    private String scmRootAddress;
-
-    private List<String> selectedDistributedBuildTaskHashCodes;
+    private int scmRootId;
 
     // -----------------------------------------------------
     //  webwork
-    // -----------------------------------------------------     
-
-    public int getProjectGroupId()
-    {
-        return projectGroupId;
-    }
-
-    public void setProjectGroupId( int projectGroupId )
-    {
-        this.projectGroupId = projectGroupId;
-    }
-
-    public String getScmRootAddress()
-    {
-        return scmRootAddress;
-    }
-
-    public void setScmRootAddress( String scmRootAddress )
-    {
-        this.scmRootAddress = scmRootAddress;
-    }
+    // -----------------------------------------------------
 
     public String cancelCurrent()
         throws Exception
     {
-        try 
+        try
         {
             checkManageQueuesAuthorization();
         }
-        catch( AuthorizationRequiredException authzE )
+        catch ( AuthorizationRequiredException authzE )
         {
             addActionError( authzE.getMessage() );
             return REQUIRES_AUTHORIZATION;
@@ -152,19 +123,27 @@
             return REQUIRES_AUTHENTICATION;
         }
 
-        taskQueueManager.cancelBuildTask( projectId );
+        try
+        {
+            getContinuum().getBuildsManager().cancelBuild( projectId );
+        }
+        catch ( BuildManagerException e )
+        {
+            addActionError( e.getMessage() );
+            return ERROR;
+        }
 
         return SUCCESS;
     }
-    
+
     public String removeCheckout()
         throws Exception
     {
-        try 
+        try
         {
             checkManageQueuesAuthorization();
         }
-        catch( AuthorizationRequiredException authzE )
+        catch ( AuthorizationRequiredException authzE )
         {
             addActionError( authzE.getMessage() );
             return REQUIRES_AUTHORIZATION;
@@ -174,19 +153,28 @@
             addActionError( e.getMessage() );
             return REQUIRES_AUTHENTICATION;
         }
-            
-        taskQueueManager.removeProjectFromCheckoutQueue( projectId );
+
+        try
+        {
+            getContinuum().getBuildsManager().removeProjectFromCheckoutQueue( projectId );
+        }
+        catch ( BuildManagerException e )
+        {
+            addActionError( e.getMessage() );
+            return ERROR;
+        }
+
         return SUCCESS;
     }
 
     public String cancelCurrentCheckout()
         throws Exception
     {
-        try 
+        try
         {
             checkManageQueuesAuthorization();
         }
-        catch( AuthorizationRequiredException authzE )
+        catch ( AuthorizationRequiredException authzE )
         {
             addActionError( authzE.getMessage() );
             return REQUIRES_AUTHORIZATION;
@@ -196,70 +184,269 @@
             addActionError( e.getMessage() );
             return REQUIRES_AUTHENTICATION;
         }
-        
-        taskQueueManager.cancelCheckout( projectId );
+        try
+        {
+            cancelCheckout( projectId );
+        }
+        catch ( BuildManagerException e )
+        {
+            addActionError( e.getMessage() );
+            return ERROR;
+        }
+
         return SUCCESS;
     }
-    
+
     public String display()
         throws Exception
     {
-        Continuum continuum = getContinuum();
-
-        if ( continuum.getConfiguration().isDistributedBuildEnabled() )
+        if ( getContinuum().getConfiguration().isDistributedBuildEnabled() )
         {
-            distributedBuildSummary = new ArrayList<DistributedBuildSummary>();
+            // current prepare build task
+            Map<String, PrepareBuildProjectsTask> currentPrepareBuildMap =
+                getContinuum().getDistributedBuildManager().getProjectsCurrentlyPreparingBuild();
 
-            Map<String, PrepareBuildProjectsTask> map = distributedBuildManager.getDistributedBuildProjects();
-
-            for ( String url : map.keySet() )
+            for ( String url : currentPrepareBuildMap.keySet() )
             {
-               PrepareBuildProjectsTask task = map.get( url );
-               
-               ProjectGroup projectGroup = continuum.getProjectGroup( task.getProjectGroupId() );
-               
-               DistributedBuildSummary summary = new DistributedBuildSummary();
-               summary.setUrl( url );
-               summary.setProjectGroupId( task.getProjectGroupId() );
-               summary.setProjectGroupName( projectGroup.getName() );
-               summary.setScmRootAddress( task.getScmRootAddress() );
-               
-               ProjectScmRoot scmRoot = continuum.getProjectScmRootByProjectGroupAndScmRootAddress( task.getProjectGroupId(), 
-                                                                                                    task.getScmRootAddress() );
-               if ( scmRoot.getState() == ContinuumProjectState.UPDATING )
-               {
-                   summary.setCancelEnabled( false );
-               }
-               else
-               {
-                   summary.setCancelEnabled( true );
-               }
+                PrepareBuildProjectsTask task = currentPrepareBuildMap.get( url );
 
-               distributedBuildSummary.add( summary );
+                ProjectGroup projectGroup = getContinuum().getProjectGroup( task.getProjectGroupId() );
+
+                PrepareBuildSummary summary = new PrepareBuildSummary();
+                summary.setBuildAgentUrl( url );
+                summary.setProjectGroupId( task.getProjectGroupId() );
+                summary.setProjectGroupName( projectGroup.getName() );
+                summary.setScmRootAddress( task.getScmRootAddress() );
+                summary.setScmRootId( task.getProjectScmRootId() );
+
+                currentDistributedPrepareBuilds.add( summary );
             }
 
-            distributedBuildQueues = taskQueueManager.getDistributedBuildProjectsInQueue();
+            // current builds
+            Map<String, BuildProjectTask> currentBuildMap =
+                getContinuum().getDistributedBuildManager().getProjectsCurrentlyBuilding();
+
+            for ( String url : currentBuildMap.keySet() )
+            {
+                BuildProjectTask task = currentBuildMap.get( url );
+
+                Project project = getContinuum().getProject( task.getProjectId() );
+
+                DistributedBuildSummary summary = new DistributedBuildSummary();
+                summary.setProjectId( project.getId() );
+                summary.setProjectName( project.getName() );
+                summary.setProjectGroupName( project.getProjectGroup().getName() );
+                summary.setBuildDefinitionId( task.getBuildDefinitionId() );
+                summary.setBuildDefinitionLabel( task.getBuildDefinitionLabel() );
+                summary.setHashCode( task.getHashCode() );
+                summary.setBuildAgentUrl( url );
+
+                currentDistributedBuilds.add( summary );
+            }
+
+            // prepare build queues
+            Map<String, List<PrepareBuildProjectsTask>> prepareBuildMap =
+                getContinuum().getDistributedBuildManager().getProjectsInPrepareBuildQueue();
+
+            for ( String url : prepareBuildMap.keySet() )
+            {
+                for ( PrepareBuildProjectsTask task : prepareBuildMap.get( url ) )
+                {
+                    ProjectGroup projectGroup = getContinuum().getProjectGroup( task.getProjectGroupId() );
+
+                    PrepareBuildSummary summary = new PrepareBuildSummary();
+                    summary.setBuildAgentUrl( url );
+                    summary.setProjectGroupId( task.getProjectGroupId() );
+                    summary.setProjectGroupName( projectGroup.getName() );
+                    summary.setScmRootAddress( task.getScmRootAddress() );
+                    summary.setScmRootId( task.getProjectScmRootId() );
+                    summary.setHashCode( task.getHashCode() );
+
+                    distributedPrepareBuildQueues.add( summary );
+                }
+            }
+
+            // build queues
+            Map<String, List<BuildProjectTask>> buildMap =
+                getContinuum().getDistributedBuildManager().getProjectsInBuildQueue();
+
+            for ( String url : buildMap.keySet() )
+            {
+                for ( BuildProjectTask task : buildMap.get( url ) )
+                {
+                    DistributedBuildSummary summary = new DistributedBuildSummary();
+
+                    Project project = getContinuum().getProject( task.getProjectId() );
+
+                    summary.setProjectId( project.getId() );
+                    summary.setProjectName( project.getName() );
+                    summary.setProjectGroupName( project.getProjectGroup().getName() );
+                    summary.setBuildDefinitionId( task.getBuildDefinitionId() );
+                    summary.setBuildDefinitionLabel( task.getBuildDefinitionLabel() );
+                    summary.setHashCode( task.getHashCode() );
+                    summary.setBuildAgentUrl( url );
+
+                    distributedBuildQueues.add( summary );
+                }
+            }
 
             return DISTRIBUTED_BUILD_SUCCESS;
         }
         else
         {
-            this.setCurrentBuildProjectTask( (BuildProjectTask) taskQueueExecutor.getCurrentTask() );        
-            this.setBuildProjectTasks( taskQueueManager.getProjectsInBuildQueue() );
-            this.setCurrentCheckOutTask( (CheckOutTask) checkoutTaskQueueExecutor.getCurrentTask() );
-            this.setCurrentCheckOutTasks( taskQueueManager.getCheckOutTasksInQueue() );
-            return SUCCESS;
+            try
+            {
+                // current prepare builds
+                Map<String, PrepareBuildProjectsTask> currentPrepareBuildTasks =
+                    getContinuum().getBuildsManager().getCurrentProjectInPrepareBuild();
+
+                Set<String> keySet = currentPrepareBuildTasks.keySet();
+                for ( String key : keySet )
+                {
+                    PrepareBuildProjectsTask prepareBuildTask = currentPrepareBuildTasks.get( key );
+
+                    PrepareBuildSummary s = new PrepareBuildSummary();
+                    s.setProjectGroupId( prepareBuildTask.getProjectGroupId() );
+                    s.setProjectGroupName( prepareBuildTask.getProjectGroupName() );
+                    s.setScmRootId( prepareBuildTask.getProjectScmRootId() );
+                    s.setScmRootAddress( prepareBuildTask.getScmRootAddress() );
+                    s.setQueueName( key );
+                    currentPrepareBuilds.add( s );
+                }
+            }
+            catch ( BuildManagerException e )
+            {
+                addActionError( e.getMessage() );
+                return ERROR;
+            }
+
+            try
+            {
+                // current builds
+                Map<String, BuildProjectTask> currentBuilds = getContinuum().getBuildsManager().getCurrentBuilds();
+                Set<String> keySet = currentBuilds.keySet();
+                for ( String key : keySet )
+                {
+                    BuildProjectTask buildTask = currentBuilds.get( key );
+                    BuildProjectQueue queue = new BuildProjectQueue();
+                    queue.setName( key );
+                    queue.setTask( buildTask );
+                    currentBuildProjectTasks.add( queue );
+                }
+            }
+            catch ( BuildManagerException e )
+            {
+                addActionError( e.getMessage() );
+                return ERROR;
+            }
+
+            try
+            {
+                // queued prepare builds
+                Map<String, List<PrepareBuildProjectsTask>> prepareBuilds =
+                    getContinuum().getBuildsManager().getProjectsInPrepareBuildQueue();
+
+                Set<String> keySet = prepareBuilds.keySet();
+                for ( String key : keySet )
+                {
+                    for ( PrepareBuildProjectsTask task : prepareBuilds.get( key ) )
+                    {
+                        PrepareBuildSummary summary = new PrepareBuildSummary();
+                        summary.setProjectGroupId( task.getProjectGroupId() );
+                        summary.setProjectGroupName( task.getProjectGroupName() );
+                        summary.setScmRootId( task.getProjectScmRootId() );
+                        summary.setScmRootAddress( task.getScmRootAddress() );
+                        summary.setHashCode( task.getHashCode() );
+                        summary.setQueueName( key );
+
+                        prepareBuildQueues.add( summary );
+                    }
+                }
+            }
+            catch ( BuildManagerException e )
+            {
+                addActionError( e.getMessage() );
+                return ERROR;
+            }
+
+            try
+            {
+                // queued builds
+                Map<String, List<BuildProjectTask>> builds =
+                    getContinuum().getBuildsManager().getProjectsInBuildQueues();
+                Set<String> keySet = builds.keySet();
+                for ( String key : keySet )
+                {
+                    for ( BuildProjectTask task : builds.get( key ) )
+                    {
+                        BuildProjectQueue queue = new BuildProjectQueue();
+                        queue.setName( key );
+                        queue.setTask( task );
+                        buildsInQueue.add( queue );
+                    }
+                }
+            }
+            catch ( BuildManagerException e )
+            {
+                addActionError( e.getMessage() );
+                return ERROR;
+            }
+
+            try
+            {
+                // current checkouts
+                Map<String, CheckOutTask> currentCheckouts = getContinuum().getBuildsManager().getCurrentCheckouts();
+                Set<String> keySet = currentCheckouts.keySet();
+                for ( String key : keySet )
+                {
+                    CheckOutTask checkoutTask = currentCheckouts.get( key );
+                    CheckoutQueue queue = new CheckoutQueue();
+                    queue.setName( key );
+                    queue.setTask( checkoutTask );
+                    currentCheckoutTasks.add( queue );
+                }
+            }
+            catch ( BuildManagerException e )
+            {
+                addActionError( e.getMessage() );
+                return ERROR;
+            }
+
+            try
+            {
+                // queued checkouts
+                Map<String, List<CheckOutTask>> checkouts =
+                    getContinuum().getBuildsManager().getProjectsInCheckoutQueues();
+                Set<String> keySet = checkouts.keySet();
+                for ( String key : keySet )
+                {
+                    for ( CheckOutTask task : checkouts.get( key ) )
+                    {
+                        CheckoutQueue queue = new CheckoutQueue();
+                        queue.setName( key );
+                        queue.setTask( task );
+                        checkoutsInQueue.add( queue );
+                    }
+                }
+            }
+            catch ( BuildManagerException e )
+            {
+                addActionError( e.getMessage() );
+                return ERROR;
+            }
         }
+
+        return SUCCESS;
     }
 
     public String remove()
         throws Exception
     {
-        try 
+        try
         {
             checkManageQueuesAuthorization();
         }
-        catch( AuthorizationRequiredException authzE )
+        catch ( AuthorizationRequiredException authzE )
         {
             addActionError( authzE.getMessage() );
             return REQUIRES_AUTHORIZATION;
@@ -269,23 +456,24 @@
             addActionError( e.getMessage() );
             return REQUIRES_AUTHENTICATION;
         }
-        
-        taskQueueManager.removeFromBuildingQueue( projectId, buildDefinitionId, trigger, projectName );
+
+        getContinuum().getBuildsManager().removeProjectFromBuildQueue( projectId, buildDefinitionId, new BuildTrigger(
+            trigger, "" ), projectName, projectGroupId );
         Project project = getContinuum().getProject( projectId );
         project.setState( project.getOldState() );
         getContinuum().updateProject( project );
 
         return SUCCESS;
     }
-    
+
     public String removeBuildEntries()
         throws Exception
     {
-        try 
+        try
         {
             checkManageQueuesAuthorization();
         }
-        catch( AuthorizationRequiredException authzE )
+        catch ( AuthorizationRequiredException authzE )
         {
             addActionError( authzE.getMessage() );
             return REQUIRES_AUTHORIZATION;
@@ -295,19 +483,20 @@
             addActionError( e.getMessage() );
             return REQUIRES_AUTHENTICATION;
         }
-        
-        taskQueueManager.removeProjectsFromBuildingQueueWithHashCodes( listToIntArray(this.getSelectedBuildTaskHashCodes()) );
+
+        getContinuum().getBuildsManager().removeProjectsFromBuildQueueWithHashcodes( listToIntArray(
+            this.getSelectedBuildTaskHashCodes() ) );
         return SUCCESS;
     }
 
     public String removeCheckoutEntries()
         throws Exception
     {
-        try 
+        try
         {
             checkManageQueuesAuthorization();
         }
-        catch( AuthorizationRequiredException authzE )
+        catch ( AuthorizationRequiredException authzE )
         {
             addActionError( authzE.getMessage() );
             return REQUIRES_AUTHORIZATION;
@@ -317,20 +506,65 @@
             addActionError( e.getMessage() );
             return REQUIRES_AUTHENTICATION;
         }
-        
-        taskQueueManager
-            .removeTasksFromCheckoutQueueWithHashCodes( listToIntArray( this.getSelectedCheckOutTaskHashCodes() ) );
+
+        getContinuum().getBuildsManager().removeProjectsFromCheckoutQueueWithHashcodes( listToIntArray(
+            this.getSelectedCheckOutTaskHashCodes() ) );
+        return SUCCESS;
+    }
+
+    public String removePrepareBuildEntry()
+        throws Exception
+    {
+        try
+        {
+            checkManageQueuesAuthorization();
+        }
+        catch ( AuthorizationRequiredException authzE )
+        {
+            addActionError( authzE.getMessage() );
+            return REQUIRES_AUTHORIZATION;
+        }
+        catch ( AuthenticationRequiredException e )
+        {
+            addActionError( e.getMessage() );
+            return REQUIRES_AUTHENTICATION;
+        }
+
+        getContinuum().getBuildsManager().removeProjectFromPrepareBuildQueue( projectGroupId, scmRootId );
+        return SUCCESS;
+    }
+
+    public String removePrepareBuildEntries()
+        throws Exception
+    {
+        try
+        {
+            checkManageQueuesAuthorization();
+        }
+        catch ( AuthorizationRequiredException authzE )
+        {
+            addActionError( authzE.getMessage() );
+            return REQUIRES_AUTHORIZATION;
+        }
+        catch ( AuthenticationRequiredException e )
+        {
+            addActionError( e.getMessage() );
+            return REQUIRES_AUTHENTICATION;
+        }
+
+        getContinuum().getBuildsManager().removeProjectsFromPrepareBuildQueueWithHashCodes( listToIntArray(
+            this.selectedPrepareBuildTaskHashCodes ) );
         return SUCCESS;
     }
 
     public String cancelDistributedBuild()
         throws Exception
     {
-        try 
+        try
         {
             checkManageQueuesAuthorization();
         }
-        catch( AuthorizationRequiredException authzE )
+        catch ( AuthorizationRequiredException authzE )
         {
             addActionError( authzE.getMessage() );
             return REQUIRES_AUTHORIZATION;
@@ -341,7 +575,55 @@
             return REQUIRES_AUTHENTICATION;
         }
 
-        distributedBuildManager.cancelDistributedBuild( buildAgentUrl, projectGroupId, scmRootAddress );
+        getContinuum().getDistributedBuildManager().cancelDistributedBuild( buildAgentUrl );
+
+        return SUCCESS;
+    }
+
+    public String removeDistributedPrepareBuildEntry()
+        throws Exception
+    {
+        try
+        {
+            checkManageQueuesAuthorization();
+        }
+        catch ( AuthorizationRequiredException authzE )
+        {
+            addActionError( authzE.getMessage() );
+            return REQUIRES_AUTHORIZATION;
+        }
+        catch ( AuthenticationRequiredException e )
+        {
+            addActionError( e.getMessage() );
+            return REQUIRES_AUTHENTICATION;
+        }
+
+        getContinuum().getDistributedBuildManager().removeFromPrepareBuildQueue( buildAgentUrl, projectGroupId,
+                                                                                 scmRootId );
+
+        return SUCCESS;
+    }
+
+    public String removeDistributedPrepareBuildEntries()
+        throws Exception
+    {
+        try
+        {
+            checkManageQueuesAuthorization();
+        }
+        catch ( AuthorizationRequiredException authzE )
+        {
+            addActionError( authzE.getMessage() );
+            return REQUIRES_AUTHORIZATION;
+        }
+        catch ( AuthenticationRequiredException e )
+        {
+            addActionError( e.getMessage() );
+            return REQUIRES_AUTHENTICATION;
+        }
+
+        getContinuum().getDistributedBuildManager().removeFromPrepareBuildQueue(
+            this.getSelectedPrepareBuildTaskHashCodes() );
 
         return SUCCESS;
     }
@@ -349,11 +631,11 @@
     public String removeDistributedBuildEntry()
         throws Exception
     {
-        try 
+        try
         {
             checkManageQueuesAuthorization();
         }
-        catch( AuthorizationRequiredException authzE )
+        catch ( AuthorizationRequiredException authzE )
         {
             addActionError( authzE.getMessage() );
             return REQUIRES_AUTHORIZATION;
@@ -364,7 +646,7 @@
             return REQUIRES_AUTHENTICATION;
         }
 
-        taskQueueManager.removeFromDistributedBuildQueue( projectGroupId, scmRootAddress );
+        getContinuum().getDistributedBuildManager().removeFromBuildQueue( buildAgentUrl, projectId, buildDefinitionId );
 
         return SUCCESS;
     }
@@ -372,11 +654,11 @@
     public String removeDistributedBuildEntries()
         throws Exception
     {
-        try 
+        try
         {
             checkManageQueuesAuthorization();
         }
-        catch( AuthorizationRequiredException authzE )
+        catch ( AuthorizationRequiredException authzE )
         {
             addActionError( authzE.getMessage() );
             return REQUIRES_AUTHORIZATION;
@@ -387,8 +669,7 @@
             return REQUIRES_AUTHENTICATION;
         }
 
-        taskQueueManager
-            .removeTasksFromDistributedBuildQueueWithHashCodes( listToIntArray( this.getSelectedDistributedBuildTaskHashCodes() ) );
+        getContinuum().getDistributedBuildManager().removeFromBuildQueue( this.getSelectedBuildTaskHashCodes() );
 
         return SUCCESS;
     }
@@ -406,11 +687,10 @@
         }
         return array;
     }
-    
-    
+
     // -----------------------------------------------------
     //  security
-    // -----------------------------------------------------    
+    // -----------------------------------------------------
 
     public SecureActionBundle getSecureActionBundle()
         throws SecureActionException
@@ -422,14 +702,38 @@
         return bundle;
     }
 
-    public List<BuildProjectTask> getBuildProjectTasks()
+    private boolean cancelCheckout( int projectId )
+        throws BuildManagerException
     {
-        return buildProjectTasks;
-    }
+        Map<String, CheckOutTask> tasks = getContinuum().getBuildsManager().getCurrentCheckouts();
+        if ( tasks != null )
+        {
+            Set<String> keySet = tasks.keySet();
+            for ( String key : keySet )
+            {
+                CheckOutTask task = tasks.get( key );
+                if ( task != null )
+                {
+                    if ( task.getProjectId() == projectId )
+                    {
+                        logger.info( "Cancelling checkout for project " + projectId );
+                        return getContinuum().getBuildsManager().cancelCheckout( projectId );
+                    }
+                    else
+                    {
+                        logger.warn(
+                            "Current task is not for the given projectId (" + projectId + "): " + task.getProjectId() +
+                                "; not cancelling checkout" );
+                    }
+                }
+            }
+        }
+        else
+        {
+            logger.warn( "No task running - not cancelling checkout" );
+        }
 
-    public void setBuildProjectTasks( List<BuildProjectTask> buildProjectTasks )
-    {
-        this.buildProjectTasks = buildProjectTasks;
+        return false;
     }
 
     public int getBuildDefinitionId()
@@ -472,57 +776,6 @@
         this.projectName = projectName;
     }
 
-    public BuildProjectTask getCurrentBuildProjectTask()
-    {
-        return currentBuildProjectTask;
-    }
-
-    public void setCurrentBuildProjectTask( BuildProjectTask currentBuildProjectTask )
-    {
-        this.currentBuildProjectTask = currentBuildProjectTask;
-    }
-
-    public TaskQueueExecutor getTaskQueueExecutor()
-    {
-        return taskQueueExecutor;
-    }
-
-
-    public TaskQueueExecutor getCheckoutTaskQueueExecutor()
-    {
-        return checkoutTaskQueueExecutor;
-    }
-
-
-    public void setCheckoutTaskQueueExecutor( TaskQueueExecutor checkoutTaskQueueExecutor )
-    {
-        this.checkoutTaskQueueExecutor = checkoutTaskQueueExecutor;
-    }
-
-
-    public CheckOutTask getCurrentCheckOutTask()
-    {
-        return currentCheckOutTask;
-    }
-
-
-    public void setCurrentCheckOutTask( CheckOutTask currentCheckOutTask )
-    {
-        this.currentCheckOutTask = currentCheckOutTask;
-    }
-
-
-    public List<CheckOutTask> getCurrentCheckOutTasks()
-    {
-        return currentCheckOutTasks;
-    }
-
-
-    public void setCurrentCheckOutTasks( List<CheckOutTask> currentCheckOutTasks )
-    {
-        this.currentCheckOutTasks = currentCheckOutTasks;
-    }
-
     public List<String> getSelectedBuildTaskHashCodes()
     {
         return selectedBuildTaskHashCodes;
@@ -543,14 +796,74 @@
         this.selectedCheckOutTaskHashCodes = selectedCheckOutTaskHashCodes;
     }
 
-    public List<DistributedBuildSummary> getDistributedBuildSummary()
+    public List<BuildProjectQueue> getCurrentBuildProjectTasks()
     {
-        return distributedBuildSummary;
+        return currentBuildProjectTasks;
     }
 
-    public void setDistributedBuildSummary( List<DistributedBuildSummary> distributedBuildSummary )
+    public void setCurrentBuildProjectTasks( List<BuildProjectQueue> currentBuildProjectTasks )
     {
-        this.distributedBuildSummary = distributedBuildSummary;
+        this.currentBuildProjectTasks = currentBuildProjectTasks;
+    }
+
+    public List<CheckoutQueue> getCurrentCheckoutTasks()
+    {
+        return currentCheckoutTasks;
+    }
+
+    public void setCurrentCheckoutTasks( List<CheckoutQueue> currentCheckoutTasks )
+    {
+        this.currentCheckoutTasks = currentCheckoutTasks;
+    }
+
+    public List<BuildProjectQueue> getBuildsInQueue()
+    {
+        return buildsInQueue;
+    }
+
+    public void setBuildsInQueue( List<BuildProjectQueue> buildsInQueue )
+    {
+        this.buildsInQueue = buildsInQueue;
+    }
+
+    public List<CheckoutQueue> getCheckoutsInQueue()
+    {
+        return checkoutsInQueue;
+    }
+
+    public void setCheckoutsInQueue( List<CheckoutQueue> checkoutsInQueue )
+    {
+        this.checkoutsInQueue = checkoutsInQueue;
+    }
+
+    public List<PrepareBuildSummary> getCurrentDistributedPrepareBuilds()
+    {
+        return currentDistributedPrepareBuilds;
+    }
+
+    public List<DistributedBuildSummary> getCurrentDistributedBuilds()
+    {
+        return currentDistributedBuilds;
+    }
+
+    public List<PrepareBuildSummary> getDistributedPrepareBuildQueues()
+    {
+        return distributedPrepareBuildQueues;
+    }
+
+    public List<DistributedBuildSummary> getDistributedBuildQueues()
+    {
+        return distributedBuildQueues;
+    }
+
+    public List<PrepareBuildSummary> getCurrentPrepareBuilds()
+    {
+        return currentPrepareBuilds;
+    }
+
+    public List<PrepareBuildSummary> getPrepareBuildQueues()
+    {
+        return prepareBuildQueues;
     }
 
     public String getBuildAgentUrl()
@@ -563,23 +876,23 @@
         this.buildAgentUrl = buildAgentUrl;
     }
 
-    public List<PrepareBuildProjectsTask> getDistributedBuildQueues()
+    public void setProjectGroupId( int projectGroupId )
     {
-        return distributedBuildQueues;
+        this.projectGroupId = projectGroupId;
     }
 
-    public void setDistributedBuildQueues( List<PrepareBuildProjectsTask> distributedBuildQueues )
+    public void setScmRootId( int scmRootId )
     {
-        this.distributedBuildQueues = distributedBuildQueues;
+        this.scmRootId = scmRootId;
     }
 
-    public List<String> getSelectedDistributedBuildTaskHashCodes()
+    public void setSelectedPrepareBuildTaskHashCodes( List<String> selectedPrepareBuildTaskHashCodes )
     {
-        return selectedDistributedBuildTaskHashCodes;
+        this.selectedPrepareBuildTaskHashCodes = selectedPrepareBuildTaskHashCodes;
     }
 
-    public void setSelectedDistributedBuildTaskHashCodes( List<String> selectedDistributedBuildTaskHashCodes )
+    public List<String> getSelectedPrepareBuildTaskHashCodes()
     {
-        this.selectedDistributedBuildTaskHashCodes = selectedDistributedBuildTaskHashCodes;
+        return selectedPrepareBuildTaskHashCodes;
     }
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/component/AbstractFooterAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/component/AbstractFooterAction.java
index c79b25a..899043f 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/component/AbstractFooterAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/component/AbstractFooterAction.java
@@ -1,3 +1,5 @@
+package org.apache.maven.continuum.web.action.component;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,25 +18,24 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.continuum.web.action.component;
 
 import org.apache.maven.continuum.web.action.ContinuumActionSupport;
 import org.apache.maven.continuum.web.appareance.AppareanceConfiguration;
 
 /**
  * @author <a href="mailto:olamy@apache.org">olamy</a>
- * @since 8 nov. 07
  * @version $Id$
+ * @since 8 nov. 07
  */
 public abstract class AbstractFooterAction
     extends ContinuumActionSupport
 {
-    
+
     private String footer;
-    
+
     /**
      * @plexus.requirement
-     */    
+     */
     private AppareanceConfiguration appareanceConfiguration;
 
     public String getContinuumFooter()
@@ -51,6 +52,4 @@
     {
         this.footer = footer;
     }
-
-    
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/component/BottomAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/component/BottomAction.java
index 1ffc7ae..f364ccd 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/component/BottomAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/component/BottomAction.java
@@ -1,3 +1,5 @@
+package org.apache.maven.continuum.web.action.component;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,22 +18,20 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.continuum.web.action.component;
-
 
 /**
  * @author <a href="mailto:olamy@apache.org">olamy</a>
- * @since 8 nov. 07
  * @version $Id$
  * @plexus.component role="com.opensymphony.xwork2.Action" role-hint="bottom"
+ * @since 8 nov. 07
  */
 public class BottomAction
     extends AbstractFooterAction
 {
-   
+
     public String execute()
     {
         return SUCCESS;
     }
-    
+
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/component/BuildDefinitionSummaryAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/component/BuildDefinitionSummaryAction.java
index 1195c07..78d130b 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/component/BuildDefinitionSummaryAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/component/BuildDefinitionSummaryAction.java
@@ -19,10 +19,6 @@
  * under the License.
  */
 
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
 import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.Project;
@@ -30,6 +26,11 @@
 import org.apache.maven.continuum.web.action.AbstractBuildDefinitionAction;
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
 import org.apache.maven.continuum.web.model.BuildDefinitionSummary;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * BuildDefinitionSummaryAction:
@@ -41,12 +42,17 @@
 public class BuildDefinitionSummaryAction
     extends AbstractBuildDefinitionAction
 {
+    private static final Logger logger = LoggerFactory.getLogger( BuildDefinitionSummaryAction.class );
+
     private int projectGroupId;
 
     private String projectGroupName;
 
     private int projectId;
 
+    // Allow dont remove default group build definition in project list 
+    private int defaultGroupDefinitionId;
+
     private ProjectGroup projectGroup;
 
     private List<BuildDefinitionSummary> projectBuildDefinitionSummaries = new ArrayList<BuildDefinitionSummary>();
@@ -68,7 +74,7 @@
             checkViewProjectGroupAuthorization( projectGroupName );
 
             groupBuildDefinitionSummaries = gatherGroupBuildDefinitionSummaries( projectGroupId );
-            projectBuildDefinitionSummaries = gatherProjectBuildDefinitionSummaries( projectId );
+            projectBuildDefinitionSummaries = gatherProjectBuildDefinitionSummaries( projectId, projectGroupId );
 
             fixDefaultBuildDefinitions();
 
@@ -77,7 +83,7 @@
         }
         catch ( ContinuumException e )
         {
-            getLogger().info( "unable to build summary" );
+            logger.info( "unable to build summary" );
             return ERROR;
         }
         catch ( AuthorizationRequiredException authzE )
@@ -99,10 +105,10 @@
 
             checkViewProjectGroupAuthorization( projectGroup.getName() );
 
-            for ( Iterator i = projectGroup.getProjects().iterator(); i.hasNext(); )
+            for ( Project project : (List<Project>) projectGroup.getProjects() )
             {
-                Project project = (Project) i.next();
-                projectBuildDefinitionSummaries.addAll( gatherProjectBuildDefinitionSummaries( project.getId() ) );
+                projectBuildDefinitionSummaries.addAll( gatherProjectBuildDefinitionSummaries( project.getId(),
+                                                                                               projectGroupId ) );
 
             }
 
@@ -111,7 +117,7 @@
         }
         catch ( ContinuumException e )
         {
-            getLogger().info( "unable to build summary" );
+            logger.info( "unable to build summary" );
             return ERROR;
         }
         catch ( AuthorizationRequiredException authzE )
@@ -135,27 +141,33 @@
             }
         }
 
-        if ( containsDefaultBDForProject )
+        for ( BuildDefinitionSummary bds : groupBuildDefinitionSummaries )
         {
-            for ( BuildDefinitionSummary bds : groupBuildDefinitionSummaries )
+            if ( bds.isIsDefault() )
+            {
+                defaultGroupDefinitionId = bds.getId();
+            }
+
+            if ( containsDefaultBDForProject )
             {
                 bds.setIsDefault( false );
             }
         }
     }
 
-    private List<BuildDefinitionSummary> gatherProjectBuildDefinitionSummaries( int projectId )
+    private List<BuildDefinitionSummary> gatherProjectBuildDefinitionSummaries( int projectId, int projectGroupId )
         throws ContinuumException
     {
         List<BuildDefinitionSummary> summaryList = new ArrayList<BuildDefinitionSummary>();
 
         Project project = getContinuum().getProjectWithAllDetails( projectId );
-        for ( Iterator i = project.getBuildDefinitions().iterator(); i.hasNext(); )
+        for ( BuildDefinition bd : (List<BuildDefinition>) project.getBuildDefinitions() )
         {
-            BuildDefinitionSummary bds = generateBuildDefinitionSummary( (BuildDefinition) i.next() );
+            BuildDefinitionSummary bds = generateBuildDefinitionSummary( bd );
             bds.setFrom( "PROJECT" );
             bds.setProjectId( project.getId() );
             bds.setProjectName( project.getName() );
+            bds.setProjectGroupId( projectGroupId );
 
             summaryList.add( bds );
         }
@@ -170,9 +182,9 @@
 
         projectGroup = getContinuum().getProjectGroupWithBuildDetails( projectGroupId );
 
-        for ( Iterator i = projectGroup.getBuildDefinitions().iterator(); i.hasNext(); )
+        for ( BuildDefinition bd : (List<BuildDefinition>) projectGroup.getBuildDefinitions() )
         {
-            BuildDefinitionSummary bds = generateBuildDefinitionSummary( (BuildDefinition) i.next() );
+            BuildDefinitionSummary bds = generateBuildDefinitionSummary( bd );
             bds.setFrom( "GROUP" );
             bds.setProjectGroupId( projectGroup.getId() );
 
@@ -182,7 +194,6 @@
         return summaryList;
     }
 
-    
 
     public int getProjectId()
     {
@@ -214,7 +225,7 @@
         this.projectGroupName = projectGroupName;
     }
 
-    public List getProjectBuildDefinitionSummaries()
+    public List<BuildDefinitionSummary> getProjectBuildDefinitionSummaries()
     {
         return projectBuildDefinitionSummaries;
     }
@@ -253,4 +264,9 @@
     {
         this.projectGroup = projectGroup;
     }
+
+    public int getDefaultGroupDefinitionId()
+    {
+        return defaultGroupDefinitionId;
+    }
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/component/NotifierSummaryAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/component/NotifierSummaryAction.java
index c99498c..37bc8ab 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/component/NotifierSummaryAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/component/NotifierSummaryAction.java
@@ -22,20 +22,20 @@
  * under the License.
  */
 
+import org.apache.continuum.web.util.GenerateRecipentNotifier;
 import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.project.ProjectGroup;
 import org.apache.maven.continuum.model.project.ProjectNotifier;
-import org.apache.maven.continuum.notification.AbstractContinuumNotifier;
 import org.apache.maven.continuum.web.action.ContinuumActionSupport;
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
 import org.apache.maven.continuum.web.model.NotifierSummary;
-import org.codehaus.plexus.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
-import java.util.Map;
 
 /**
  * Component Action that prepares and provides Project Group Notifier and
@@ -48,6 +48,8 @@
 public class NotifierSummaryAction
     extends ContinuumActionSupport
 {
+    private static final Logger logger = LoggerFactory.getLogger( NotifierSummaryAction.class );
+
     /**
      * Identifier for the {@link ProjectGroup} for which the Notifier summary
      * needs to be prepared for.
@@ -78,7 +80,7 @@
      */
     public String summarizeForProject()
     {
-        getLogger().debug( "Obtaining summary for Project Id: " + projectId );
+        logger.debug( "Obtaining summary for Project Id: " + projectId );
 
         try
         {
@@ -88,7 +90,7 @@
         }
         catch ( ContinuumException e )
         {
-            getLogger().error( "Unable to prepare Notifier summaries for Project Id: " + projectId, e );
+            logger.error( "Unable to prepare Notifier summaries for Project Id: " + projectId, e );
             return ERROR;
         }
         catch ( AuthorizationRequiredException authzE )
@@ -119,7 +121,7 @@
      */
     public String summarizeForProjectGroup()
     {
-        getLogger().debug( "Obtaining summary for ProjectGroup Id:" + projectGroupId );
+        logger.debug( "Obtaining summary for ProjectGroup Id:" + projectGroupId );
 
         try
         {
@@ -138,7 +140,7 @@
         }
         catch ( ContinuumException e )
         {
-            getLogger().error( "Unable to prepare Notifier summaries for ProjectGroup Id: " + projectGroupId, e );
+            logger.error( "Unable to prepare Notifier summaries for ProjectGroup Id: " + projectGroupId, e );
             return ERROR;
         }
         catch ( AuthorizationRequiredException authzE )
@@ -243,50 +245,7 @@
             ns.setFromProject( false );
         }
 
-        // Source the recipient 
-        Map configuration = notifier.getConfiguration();
-
-        String recipient = "unknown";
-
-        if ( ( "mail".equals( notifier.getType() ) ) || ( "msn".equals( notifier.getType() ) ) ||
-            ( "jabber".equals( notifier.getType() ) ) )
-        {
-            if ( StringUtils.isNotEmpty( (String) configuration.get( AbstractContinuumNotifier.ADDRESS_FIELD ) ) )
-            {
-                recipient = (String) configuration.get( AbstractContinuumNotifier.ADDRESS_FIELD );
-            }
-            if ( StringUtils.isNotEmpty( (String) configuration.get( AbstractContinuumNotifier.COMMITTER_FIELD ) ) )
-            {
-                if ( Boolean.parseBoolean( (String) configuration.get( AbstractContinuumNotifier.COMMITTER_FIELD ) ) )
-                {
-                    if ( "unknown".equals( recipient ) )
-                    {
-                        recipient = "latest committers";
-                    }
-                    else
-                    {
-                        recipient += ", " + "latest committers";
-                    }
-                }
-            }
-        }
-
-        if ( "irc".equals( notifier.getType() ) )
-        {
-            recipient = (String) configuration.get( "host" );
-
-            if ( configuration.get( "port" ) != null )
-            {
-                recipient = recipient + ":" + (String) configuration.get( "port" );
-            }
-
-            recipient = recipient + ":" + (String) configuration.get( "channel" );
-        }
-
-        if ( "wagon".equals( notifier.getType() ) )
-        {
-            recipient = (String) configuration.get( "url" );
-        }
+        String recipient = GenerateRecipentNotifier.generate( notifier );
 
         ns.setRecipient( recipient );
 
@@ -334,7 +293,7 @@
         return ns;
     }
 
-    // property accessors 
+    // property accessors
 
     /**
      * @return the projectGroupId
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/AbstractNotifierEditActionSupport.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/AbstractNotifierEditActionSupport.java
index f9545f6..1adb29b 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/AbstractNotifierEditActionSupport.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/AbstractNotifierEditActionSupport.java
@@ -327,13 +327,13 @@
      *
      * @param configuration map of configuration key-value pairs.
      */
-    protected abstract void initConfiguration( Map configuration );
+    protected abstract void initConfiguration( Map<String, String> configuration );
 
     /**
      * Sets the configuration for the specified {@link ProjectNotifier}
      * instance.
      *
-     * @param notifier
+     * @param notifier The project notifier.
      * @see #initConfiguration(Map)
      */
     protected abstract void setNotifierConfiguration( ProjectNotifier notifier );
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/AddProjectNotifierAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/AddProjectNotifierAction.java
index 0067f01..6251310 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/AddProjectNotifierAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/AddProjectNotifierAction.java
@@ -140,7 +140,7 @@
      * Sets the identifier for the Project to be edited for
      * project notifiers.
      *
-     * @param projectId
+     * @param projectId The project id to set.
      */
     public void setProjectId( int projectId )
     {
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/DeleteGroupNotifierAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/DeleteGroupNotifierAction.java
index 36edb58..50b77a7 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/DeleteGroupNotifierAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/DeleteGroupNotifierAction.java
@@ -19,16 +19,14 @@
  * under the License.
  */
 
+import org.apache.continuum.web.util.GenerateRecipentNotifier;
 import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.model.project.ProjectGroup;
 import org.apache.maven.continuum.model.project.ProjectNotifier;
-import org.apache.maven.continuum.notification.AbstractContinuumNotifier;
 import org.apache.maven.continuum.web.action.ContinuumActionSupport;
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
 import org.codehaus.plexus.util.StringUtils;
 
-import java.util.Map;
-
 /**
  * Action to delete a {@link ProjectNotifier} instance from a
  * specified {@link ProjectGroup}.
@@ -84,27 +82,9 @@
 
         ProjectNotifier notifier = getContinuum().getGroupNotifier( projectGroupId, notifierId );
 
-        Map configuration = notifier.getConfiguration();
-
         notifierType = notifier.getType();
 
-        if ( ( "mail".equals( notifierType ) ) || ( "msn".equals( notifierType ) ) ||
-            ( "jabber".equals( notifierType ) ) )
-        {
-            recipient = (String) configuration.get( AbstractContinuumNotifier.ADDRESS_FIELD );
-        }
-
-        if ( "irc".equals( notifierType ) )
-        {
-            recipient = (String) configuration.get( "host" );
-
-            if ( configuration.get( "port" ) != null )
-            {
-                recipient = recipient + ":" + (String) configuration.get( "port" );
-            }
-
-            recipient = recipient + ":" + (String) configuration.get( "channel" );
-        }
+        recipient = GenerateRecipentNotifier.generate( notifier );
 
         return "delete";
     }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/DeleteProjectNotifierAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/DeleteProjectNotifierAction.java
index a81a320..aef06f8 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/DeleteProjectNotifierAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/DeleteProjectNotifierAction.java
@@ -19,17 +19,15 @@
  * under the License.
  */
 
+import org.apache.continuum.web.util.GenerateRecipentNotifier;
 import org.apache.maven.continuum.ContinuumException;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.project.ProjectGroup;
 import org.apache.maven.continuum.model.project.ProjectNotifier;
-import org.apache.maven.continuum.notification.AbstractContinuumNotifier;
 import org.apache.maven.continuum.web.action.ContinuumActionSupport;
 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
 import org.codehaus.plexus.util.StringUtils;
 
-import java.util.Map;
-
 /**
  * Action that deletes a {@link ProjectNotifier} from a specified {@link Project}.
  *
@@ -95,27 +93,9 @@
 
         ProjectNotifier notifier = getContinuum().getNotifier( projectId, notifierId );
 
-        Map configuration = notifier.getConfiguration();
-
         notifierType = notifier.getType();
 
-        if ( ( "mail".equals( notifierType ) ) || ( "msn".equals( notifierType ) ) ||
-            ( "jabber".equals( notifierType ) ) )
-        {
-            recipient = (String) configuration.get( AbstractContinuumNotifier.ADDRESS_FIELD );
-        }
-
-        if ( "irc".equals( notifierType ) )
-        {
-            recipient = (String) configuration.get( "host" );
-
-            if ( configuration.get( "port" ) != null )
-            {
-                recipient = recipient + ":" + (String) configuration.get( "port" );
-            }
-
-            recipient = recipient + ":" + (String) configuration.get( "channel" );
-        }
+        recipient = GenerateRecipentNotifier.generate( notifier );
 
         return "delete";
     }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/IrcGroupNotifierEditAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/IrcGroupNotifierEditAction.java
index 03effcb..01c9566 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/IrcGroupNotifierEditAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/IrcGroupNotifierEditAction.java
@@ -55,36 +55,36 @@
 
     private boolean ssl = false;
 
-    protected void initConfiguration( Map configuration )
+    protected void initConfiguration( Map<String, String> configuration )
     {
-        host = (String) configuration.get( "host" );
+        host = configuration.get( "host" );
 
         if ( configuration.get( "port" ) != null )
         {
-            port = Integer.parseInt( (String) configuration.get( "port" ) );
+            port = Integer.parseInt( configuration.get( "port" ) );
         }
 
-        channel = (String) configuration.get( "channel" );
+        channel = configuration.get( "channel" );
 
-        nick = (String) configuration.get( "nick" );
+        nick = configuration.get( "nick" );
 
-        alternateNick = (String) configuration.get( "alternateNick" );
+        alternateNick = configuration.get( "alternateNick" );
 
-        username = (String) configuration.get( "username" );
+        username = configuration.get( "username" );
 
-        fullName = (String) configuration.get( "fullName" );
+        fullName = configuration.get( "fullName" );
 
-        password = (String) configuration.get( "password" );
+        password = configuration.get( "password" );
 
         if ( configuration.get( "ssl" ) != null )
         {
-            ssl = Boolean.parseBoolean( (String) configuration.get( "ssl" ) );
+            ssl = Boolean.parseBoolean( configuration.get( "ssl" ) );
         }
     }
 
     protected void setNotifierConfiguration( ProjectNotifier notifier )
     {
-        HashMap configuration = new HashMap();
+        HashMap<String, String> configuration = new HashMap<String, String>();
 
         configuration.put( "host", host );
 
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/IrcProjectNotifierEditAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/IrcProjectNotifierEditAction.java
index de9f0c7..a49f501 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/IrcProjectNotifierEditAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/IrcProjectNotifierEditAction.java
@@ -50,36 +50,36 @@
 
     private boolean ssl = false;
 
-    protected void initConfiguration( Map configuration )
+    protected void initConfiguration( Map<String, String> configuration )
     {
-        host = (String) configuration.get( "host" );
+        host = configuration.get( "host" );
 
         if ( configuration.get( "port" ) != null )
         {
-            port = Integer.parseInt( (String) configuration.get( "port" ) );
+            port = Integer.parseInt( configuration.get( "port" ) );
         }
 
-        channel = (String) configuration.get( "channel" );
+        channel = configuration.get( "channel" );
 
-        nick = (String) configuration.get( "nick" );
+        nick = configuration.get( "nick" );
 
-        alternateNick = (String) configuration.get( "alternateNick" );
+        alternateNick = configuration.get( "alternateNick" );
 
-        username = (String) configuration.get( "username" );
+        username = configuration.get( "username" );
 
-        fullName = (String) configuration.get( "fullName" );
+        fullName = configuration.get( "fullName" );
 
-        password = (String) configuration.get( "password" );
+        password = configuration.get( "password" );
 
         if ( configuration.get( "ssl" ) != null )
         {
-            ssl = Boolean.parseBoolean( (String) configuration.get( "ssl" ) );
+            ssl = Boolean.parseBoolean( configuration.get( "ssl" ) );
         }
     }
 
     protected void setNotifierConfiguration( ProjectNotifier notifier )
     {
-        HashMap configuration = new HashMap();
+        HashMap<String, String> configuration = new HashMap<String, String>();
 
         configuration.put( "host", host );
 
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/JabberGroupNotifierEditAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/JabberGroupNotifierEditAction.java
index 37d0ae6..961fb57 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/JabberGroupNotifierEditAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/JabberGroupNotifierEditAction.java
@@ -54,31 +54,31 @@
 
     private boolean group;
 
-    protected void initConfiguration( Map configuration )
+    protected void initConfiguration( Map<String, String> configuration )
     {
-        host = (String) configuration.get( "host" );
+        host = configuration.get( "host" );
 
         if ( configuration.get( "port" ) != null )
         {
-            port = Integer.parseInt( (String) configuration.get( "port" ) );
+            port = Integer.parseInt( configuration.get( "port" ) );
         }
 
-        login = (String) configuration.get( "login" );
+        login = configuration.get( "login" );
 
-        password = (String) configuration.get( "password" );
+        password = configuration.get( "password" );
 
-        domainName = (String) configuration.get( "domainName" );
+        domainName = configuration.get( "domainName" );
 
-        address = (String) configuration.get( AbstractContinuumNotifier.ADDRESS_FIELD );
+        address = configuration.get( AbstractContinuumNotifier.ADDRESS_FIELD );
 
-        sslConnection = Boolean.valueOf( (String) configuration.get( "sslConnection" ) ).booleanValue();
+        sslConnection = Boolean.valueOf( configuration.get( "sslConnection" ) );
 
-        group = Boolean.valueOf( (String) configuration.get( "isGroup" ) ).booleanValue();
+        group = Boolean.valueOf( configuration.get( "isGroup" ) );
     }
 
     protected void setNotifierConfiguration( ProjectNotifier notifier )
     {
-        HashMap configuration = new HashMap();
+        HashMap<String, String> configuration = new HashMap<String, String>();
 
         configuration.put( "host", host );
 
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/JabberProjectNotifierEditAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/JabberProjectNotifierEditAction.java
index 07e4a77..70747d7 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/JabberProjectNotifierEditAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/JabberProjectNotifierEditAction.java
@@ -53,31 +53,31 @@
 
     private boolean group;
 
-    protected void initConfiguration( Map configuration )
+    protected void initConfiguration( Map<String, String> configuration )
     {
-        host = (String) configuration.get( "host" );
+        host = configuration.get( "host" );
 
         if ( configuration.get( "port" ) != null )
         {
-            port = Integer.parseInt( (String) configuration.get( "port" ) );
+            port = Integer.parseInt( configuration.get( "port" ) );
         }
 
-        login = (String) configuration.get( "login" );
+        login = configuration.get( "login" );
 
-        password = (String) configuration.get( "password" );
+        password = configuration.get( "password" );
 
-        domainName = (String) configuration.get( "domainName" );
+        domainName = configuration.get( "domainName" );
 
-        address = (String) configuration.get( AbstractContinuumNotifier.ADDRESS_FIELD );
+        address = configuration.get( AbstractContinuumNotifier.ADDRESS_FIELD );
 
-        sslConnection = Boolean.valueOf( (String) configuration.get( "sslConnection" ) ).booleanValue();
+        sslConnection = Boolean.valueOf( configuration.get( "sslConnection" ) );
 
-        group = Boolean.valueOf( (String) configuration.get( "isGroup" ) ).booleanValue();
+        group = Boolean.valueOf( configuration.get( "isGroup" ) );
     }
 
     protected void setNotifierConfiguration( ProjectNotifier notifier )
     {
-        HashMap configuration = new HashMap();
+        HashMap<String, String> configuration = new HashMap<String, String>();
 
         configuration.put( "host", host );
 
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/MailGroupNotifierEditAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/MailGroupNotifierEditAction.java
index 257be24..891af5a 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/MailGroupNotifierEditAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/MailGroupNotifierEditAction.java
@@ -43,17 +43,23 @@
 
     private boolean committers;
 
-    protected void initConfiguration( Map configuration )
+    private boolean developers;
+
+    protected void initConfiguration( Map<String, String> configuration )
     {
-        if ( StringUtils.isNotEmpty( (String) configuration.get( AbstractContinuumNotifier.ADDRESS_FIELD ) ) )
+        if ( StringUtils.isNotEmpty( configuration.get( AbstractContinuumNotifier.ADDRESS_FIELD ) ) )
         {
-            address = (String) configuration.get( AbstractContinuumNotifier.ADDRESS_FIELD );
+            address = configuration.get( AbstractContinuumNotifier.ADDRESS_FIELD );
         }
 
-        if ( StringUtils.isNotEmpty( (String) configuration.get( AbstractContinuumNotifier.COMMITTER_FIELD ) ) )
+        if ( StringUtils.isNotEmpty( configuration.get( AbstractContinuumNotifier.COMMITTER_FIELD ) ) )
         {
-            committers =
-                Boolean.parseBoolean( (String) configuration.get( AbstractContinuumNotifier.COMMITTER_FIELD ) );
+            committers = Boolean.parseBoolean( configuration.get( AbstractContinuumNotifier.COMMITTER_FIELD ) );
+        }
+
+        if ( StringUtils.isNotEmpty( configuration.get( AbstractContinuumNotifier.DEVELOPER_FIELD ) ) )
+        {
+            developers = Boolean.parseBoolean( configuration.get( AbstractContinuumNotifier.DEVELOPER_FIELD ) );
         }
     }
 
@@ -68,6 +74,8 @@
 
         configuration.put( AbstractContinuumNotifier.COMMITTER_FIELD, String.valueOf( committers ) );
 
+        configuration.put( AbstractContinuumNotifier.DEVELOPER_FIELD, String.valueOf( developers ) );
+
         notifier.setConfiguration( configuration );
     }
 
@@ -90,4 +98,14 @@
     {
         this.committers = committers;
     }
+
+    public boolean isDevelopers()
+    {
+        return developers;
+    }
+
+    public void setDevelopers( boolean developers )
+    {
+        this.developers = developers;
+    }
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/MailProjectNotifierEditAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/MailProjectNotifierEditAction.java
index 00b5a90..bbac19a 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/MailProjectNotifierEditAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/MailProjectNotifierEditAction.java
@@ -43,17 +43,23 @@
 
     private boolean committers;
 
-    protected void initConfiguration( Map configuration )
+    private boolean developers;
+
+    protected void initConfiguration( Map<String, String> configuration )
     {
-        if ( StringUtils.isNotEmpty( (String) configuration.get( AbstractContinuumNotifier.ADDRESS_FIELD ) ) )
+        if ( StringUtils.isNotEmpty( configuration.get( AbstractContinuumNotifier.ADDRESS_FIELD ) ) )
         {
-            address = (String) configuration.get( AbstractContinuumNotifier.ADDRESS_FIELD );
+            address = configuration.get( AbstractContinuumNotifier.ADDRESS_FIELD );
         }
 
-        if ( StringUtils.isNotEmpty( (String) configuration.get( AbstractContinuumNotifier.COMMITTER_FIELD ) ) )
+        if ( StringUtils.isNotEmpty( configuration.get( AbstractContinuumNotifier.COMMITTER_FIELD ) ) )
         {
-            committers =
-                Boolean.parseBoolean( (String) configuration.get( AbstractContinuumNotifier.COMMITTER_FIELD ) );
+            committers = Boolean.parseBoolean( configuration.get( AbstractContinuumNotifier.COMMITTER_FIELD ) );
+        }
+
+        if ( StringUtils.isNotEmpty( configuration.get( AbstractContinuumNotifier.DEVELOPER_FIELD ) ) )
+        {
+            developers = Boolean.parseBoolean( configuration.get( AbstractContinuumNotifier.DEVELOPER_FIELD ) );
         }
     }
 
@@ -68,6 +74,8 @@
 
         configuration.put( AbstractContinuumNotifier.COMMITTER_FIELD, String.valueOf( committers ) );
 
+        configuration.put( AbstractContinuumNotifier.DEVELOPER_FIELD, String.valueOf( developers ) );
+
         notifier.setConfiguration( configuration );
     }
 
@@ -90,4 +98,14 @@
     {
         this.committers = committers;
     }
+
+    public boolean isDevelopers()
+    {
+        return developers;
+    }
+
+    public void setDevelopers( boolean developers )
+    {
+        this.developers = developers;
+    }
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/MsnGroupNotifierEditAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/MsnGroupNotifierEditAction.java
index 2d6da32..b2c6bea 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/MsnGroupNotifierEditAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/MsnGroupNotifierEditAction.java
@@ -43,18 +43,18 @@
 
     private String address;
 
-    protected void initConfiguration( Map configuration )
+    protected void initConfiguration( Map<String, String> configuration )
     {
-        login = (String) configuration.get( "login" );
+        login = configuration.get( "login" );
 
-        password = (String) configuration.get( "password" );
+        password = configuration.get( "password" );
 
-        address = (String) configuration.get( AbstractContinuumNotifier.ADDRESS_FIELD );
+        address = configuration.get( AbstractContinuumNotifier.ADDRESS_FIELD );
     }
 
     protected void setNotifierConfiguration( ProjectNotifier notifier )
     {
-        HashMap configuration = new HashMap();
+        HashMap<String, String> configuration = new HashMap<String, String>();
 
         configuration.put( "login", login );
 
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/MsnProjectNotifierEditAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/MsnProjectNotifierEditAction.java
index a00139e..3f238c0 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/MsnProjectNotifierEditAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/MsnProjectNotifierEditAction.java
@@ -44,18 +44,18 @@
 
     private String address;
 
-    protected void initConfiguration( Map configuration )
+    protected void initConfiguration( Map<String, String> configuration )
     {
-        login = (String) configuration.get( "login" );
+        login = configuration.get( "login" );
 
-        password = (String) configuration.get( "password" );
+        password = configuration.get( "password" );
 
-        address = (String) configuration.get( AbstractContinuumNotifier.ADDRESS_FIELD );
+        address = configuration.get( AbstractContinuumNotifier.ADDRESS_FIELD );
     }
 
     protected void setNotifierConfiguration( ProjectNotifier notifier )
     {
-        HashMap configuration = new HashMap();
+        HashMap<String, String> configuration = new HashMap<String, String>();
 
         configuration.put( "login", login );
 
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/WagonGroupNotifierEditAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/WagonGroupNotifierEditAction.java
index 9d6dc34..1680bb7 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/WagonGroupNotifierEditAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/WagonGroupNotifierEditAction.java
@@ -40,14 +40,15 @@
 
     private String id;
 
-    protected void initConfiguration( Map configuration )
+    protected void initConfiguration( Map<String, String> configuration )
     {
-        url = (String) configuration.get( "url" );
+        url = configuration.get( "url" );
+        id = configuration.get( "id" );
     }
 
     protected void setNotifierConfiguration( ProjectNotifier notifier )
     {
-        HashMap configuration = new HashMap();
+        HashMap<String, String> configuration = new HashMap<String, String>();
 
         configuration.put( "url", url );
 
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/WagonProjectNotifierEditAction.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/WagonProjectNotifierEditAction.java
index 82e66b2..335bbd2 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/WagonProjectNotifierEditAction.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/WagonProjectNotifierEditAction.java
@@ -40,14 +40,15 @@
 
     private String id;
 
-    protected void initConfiguration( Map configuration )
+    protected void initConfiguration( Map<String, String> configuration )
     {
-        url = (String) configuration.get( "url" );
+        url = configuration.get( "url" );
+        id = configuration.get( "id" );
     }
 
     protected void setNotifierConfiguration( ProjectNotifier notifier )
     {
-        HashMap configuration = new HashMap();
+        HashMap<String, String> configuration = new HashMap<String, String>();
 
         configuration.put( "url", url );
 
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/appareance/AppareanceConfiguration.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/appareance/AppareanceConfiguration.java
index 3f4019a..a81ce7a 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/appareance/AppareanceConfiguration.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/appareance/AppareanceConfiguration.java
@@ -1,3 +1,5 @@
+package org.apache.maven.continuum.web.appareance;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,16 +18,15 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.continuum.web.appareance;
-
-import java.io.IOException;
 
 import org.codehaus.plexus.registry.RegistryException;
 
+import java.io.IOException;
+
 /**
  * @author <a href="mailto:olamy@apache.org">olamy</a>
- * @since 10 nov. 07
  * @version $Id$
+ * @since 10 nov. 07
  */
 public interface AppareanceConfiguration
 {
@@ -38,11 +39,11 @@
         throws IOException;
 
     /**
-     * If no user configuration a default one will be user 
+     * If no user configuration a default one will be user
      * with Apache copyright content
-     * 
+     *
      * @return htmlFooter
      */
     public String getFooter();
-    
+
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/appareance/DefaultAppareanceConfiguration.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/appareance/DefaultAppareanceConfiguration.java
index bf74474..41f6a00 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/appareance/DefaultAppareanceConfiguration.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/appareance/DefaultAppareanceConfiguration.java
@@ -1,3 +1,5 @@
+package org.apache.maven.continuum.web.appareance;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,12 +18,6 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.continuum.web.appareance;
-
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.Calendar;
 
 import org.apache.continuum.web.appearance.ContinuumAppearance;
 import org.apache.continuum.web.appearance.io.xpp3.ContinuumAppearanceModelsXpp3Reader;
@@ -31,34 +27,41 @@
 import org.codehaus.plexus.util.ReaderFactory;
 import org.codehaus.plexus.util.StringUtils;
 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+import org.jsoup.Jsoup;
+import org.jsoup.safety.Whitelist;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Calendar;
+
 /**
  * @author <a href="mailto:olamy@apache.org">olamy</a>
- * @since 10 nov. 07
  * @version $Id$
  * @plexus.component role="org.apache.maven.continuum.web.appareance.AppareanceConfiguration" role-hint="default"
+ * @since 10 nov. 07
  */
 public class DefaultAppareanceConfiguration
     implements AppareanceConfiguration, Initializable
 {
-    private Logger log = LoggerFactory.getLogger( getClass() );
-    
+    private static final Logger log = LoggerFactory.getLogger( DefaultAppareanceConfiguration.class );
+
     private String footer;
-    
+
     public static final String APPEARANCE_FILE_NAME = "continuum-appearance.xml";
-    
-    private ContinuumAppearance continuumAppearance = new ContinuumAppearance(); 
-   
+
+    private ContinuumAppearance continuumAppearance = new ContinuumAppearance();
+
     // ------------------------------------------------
     //  Plexus Lifecycle
     // ------------------------------------------------
-    
+
     public void initialize()
         throws InitializationException
     {
-        
+
         File appearanceConfFile = getAppearanceConfigurationFile();
 
         if ( appearanceConfFile.exists() )
@@ -66,8 +69,7 @@
             try
             {
                 ContinuumAppearanceModelsXpp3Reader appearanceReader = new ContinuumAppearanceModelsXpp3Reader();
-                this.continuumAppearance = appearanceReader.read( ReaderFactory
-                    .newXmlReader( appearanceConfFile ) );
+                this.continuumAppearance = appearanceReader.read( ReaderFactory.newXmlReader( appearanceConfFile ) );
                 if ( continuumAppearance != null )
                 {
                     this.footer = continuumAppearance.getFooter();
@@ -75,13 +77,13 @@
             }
             catch ( IOException e )
             {
-                log.warn( "skip IOException reading appearance file " + APPEARANCE_FILE_NAME + ", msg "
-                    + e.getMessage() );
+                log.warn(
+                    "skip IOException reading appearance file " + APPEARANCE_FILE_NAME + ", msg " + e.getMessage() );
             }
             catch ( XmlPullParserException e )
             {
-                log.warn( "skip XmlPullParserException reading appearance file " + APPEARANCE_FILE_NAME + ", msg "
-                    + e.getMessage() );
+                log.warn( "skip XmlPullParserException reading appearance file " + APPEARANCE_FILE_NAME + ", msg " +
+                              e.getMessage() );
             }
         }
         if ( StringUtils.isEmpty( this.footer ) )
@@ -90,8 +92,8 @@
             this.footer = getDefaultFooter();
         }
     }
-    
-    /** 
+
+    /**
      * @see org.apache.maven.continuum.web.appareance.AppareanceConfiguration#getFooter()
      */
     public String getFooter()
@@ -99,21 +101,25 @@
         return this.footer;
     }
 
-    /** 
+    /**
      * @see org.apache.maven.continuum.web.appareance.AppareanceConfiguration#saveFooter(java.lang.String)
      */
     public void saveFooter( String footerHtmlContent )
         throws IOException
     {
-        continuumAppearance.setFooter( footerHtmlContent );
+        String safeFooterHtmlContent = Jsoup.clean( footerHtmlContent, Whitelist.basic() );
+
+        continuumAppearance.setFooter( safeFooterHtmlContent );
         ContinuumAppearanceModelsXpp3Writer writer = new ContinuumAppearanceModelsXpp3Writer();
         File confFile = getAppearanceConfigurationFile();
-        if (!confFile.exists())
+        if ( !confFile.exists() )
         {
             confFile.getParentFile().mkdirs();
         }
-        writer.write( new FileWriter( confFile ), continuumAppearance );
-        this.footer = footerHtmlContent;
+        FileWriter fileWriter = new FileWriter( confFile );
+        writer.write( fileWriter, continuumAppearance );
+        fileWriter.close();
+        this.footer = safeFooterHtmlContent;
     }
 
 
@@ -124,16 +130,16 @@
         StringBuilder stringBuilder = new StringBuilder();
         stringBuilder.append( "<div class=\"xright\">" );
         stringBuilder.append( "Copyright &copy; " );
-        stringBuilder.append( String.valueOf( inceptionYear ) + "-" + String.valueOf( currentYear ) );
+        stringBuilder.append( String.valueOf( inceptionYear ) ).append( "-" ).append( String.valueOf( currentYear ) );
         stringBuilder.append( "&nbsp;The Apache Software Foundation" );
         stringBuilder.append( "</div> <div class=\"clear\"><hr/></div>" );
         return stringBuilder.toString();
-    }    
-    
-    
+    }
+
+
     private File getAppearanceConfigurationFile()
     {
-        return new File( System.getProperty( "appserver.base" ) + File.separator + "conf" + File.separator
-            + APPEARANCE_FILE_NAME );
+        return new File( System.getProperty( "appserver.base" ) + File.separator + "conf" + File.separator +
+                             APPEARANCE_FILE_NAME );
     }
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/bean/BuildProjectQueue.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/bean/BuildProjectQueue.java
new file mode 100644
index 0000000..6aa4b43
--- /dev/null
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/bean/BuildProjectQueue.java
@@ -0,0 +1,42 @@
+package org.apache.maven.continuum.web.bean;
+
+/*
+ * 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 org.apache.continuum.taskqueue.BuildProjectTask;
+
+/**
+ * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
+ * @version $Id$
+ */
+public class BuildProjectQueue
+    extends Queue
+{
+    private BuildProjectTask task;
+
+    public BuildProjectTask getTask()
+    {
+        return task;
+    }
+
+    public void setTask( BuildProjectTask task )
+    {
+        this.task = task;
+    }
+}
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/bean/CheckoutQueue.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/bean/CheckoutQueue.java
new file mode 100644
index 0000000..79f037e
--- /dev/null
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/bean/CheckoutQueue.java
@@ -0,0 +1,42 @@
+package org.apache.maven.continuum.web.bean;
+
+/*
+ * 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 org.apache.continuum.taskqueue.CheckOutTask;
+
+/**
+ * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
+ * @version $Id$
+ */
+public class CheckoutQueue
+    extends Queue
+{
+    private CheckOutTask task;
+
+    public CheckOutTask getTask()
+    {
+        return task;
+    }
+
+    public void setTask( CheckOutTask task )
+    {
+        this.task = task;
+    }
+}
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/bean/ProjectGroupUserBean.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/bean/ProjectGroupUserBean.java
index 11175e3..0216d2a 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/bean/ProjectGroupUserBean.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/bean/ProjectGroupUserBean.java
@@ -23,6 +23,7 @@
 import org.codehaus.plexus.redback.rbac.Role;
 import org.codehaus.plexus.redback.users.User;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
 
@@ -73,21 +74,26 @@
         this.projectGroup = projectGroup;
     }
 
-    public void addRole( String role )
+    public void addRole( Role role )
     {
+        if ( roles == null )
+        {
+            roles = new ArrayList();
+        }
+
         roles.add( role );
 
-        if ( role.indexOf( ROLE_ADMINISTRATOR ) != -1 )
+        if ( role.getName().indexOf( ROLE_ADMINISTRATOR ) != -1 )
         {
             isAdministrator = true;
         }
 
-        if ( role.indexOf( ROLE_DEVELOPER ) != -1 )
+        if ( role.getName().indexOf( ROLE_DEVELOPER ) != -1 )
         {
             isDeveloper = true;
         }
 
-        if ( role.indexOf( ROLE_USER ) != -1 )
+        if ( role.getName().indexOf( ROLE_USER ) != -1 )
         {
             isUser = true;
         }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/bean/Queue.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/bean/Queue.java
new file mode 100644
index 0000000..af7d452
--- /dev/null
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/bean/Queue.java
@@ -0,0 +1,39 @@
+package org.apache.maven.continuum.web.bean;
+
+/*
+ * 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.
+ */
+
+/**
+ * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
+ * @version $Id$
+ */
+public class Queue
+{
+    private String name;
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName( String name )
+    {
+        this.name = name;
+    }
+}
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/checks/security/RoleProfileEnvironmentCheck.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/checks/security/RoleProfileEnvironmentCheck.java
index 4951e32..a30b370 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/checks/security/RoleProfileEnvironmentCheck.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/checks/security/RoleProfileEnvironmentCheck.java
@@ -28,7 +28,6 @@
 import org.slf4j.LoggerFactory;
 
 import java.util.Collection;
-import java.util.Iterator;
 import java.util.List;
 
 /**
@@ -42,7 +41,7 @@
 public class RoleProfileEnvironmentCheck
     implements EnvironmentCheck
 {
-    private Logger log = LoggerFactory.getLogger( RoleProfileEnvironmentCheck.class );
+    private static final Logger log = LoggerFactory.getLogger( RoleProfileEnvironmentCheck.class );
 
     /**
      * @plexus.requirement role-hint="default"
@@ -60,12 +59,10 @@
         {
             log.info( "Checking roles list." );
 
-            Collection projectGroups = continuum.getAllProjectGroups();
+            Collection<ProjectGroup> projectGroups = continuum.getAllProjectGroups();
 
-            for ( Iterator i = projectGroups.iterator(); i.hasNext(); )
+            for ( ProjectGroup group : projectGroups )
             {
-                ProjectGroup group = (ProjectGroup) i.next();
-
                 // gets the role, making it if it doesn't exist
                 //TODO: use continuum.executeAction( "add-assignable-roles", context ); or something like that to avoid code duplication
                 if ( !roleManager.templatedRoleExists( "project-administrator", group.getName() ) )
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/components/Data.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/components/Data.java
deleted file mode 100644
index 6ba808f..0000000
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/components/Data.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package org.apache.maven.continuum.web.components;
-
-/*
- * 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 com.opensymphony.xwork2.util.ValueStack;
-import org.apache.struts2.components.UIBean;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
- * @version $Id$
- */
-public class Data
-    extends UIBean
-{
-    private static final String TEMPLATE = "data";
-
-    protected String valueLink;
-
-    public Data( ValueStack stack, HttpServletRequest request, HttpServletResponse response )
-    {
-        super( stack, request, response );
-    }
-
-    protected String getDefaultTemplate()
-    {
-        return TEMPLATE;
-    }
-
-    public void setValueLink( String _link )
-    {
-        valueLink = _link;
-    }
-
-    public String getValueLink()
-    {
-        return valueLink;
-    }
-
-    protected void evaluateExtraParams()
-    {
-        if ( this.valueLink != null )
-        {
-            valueLink = findString( this.valueLink );
-            addParameter( "valueLink", valueLink );
-        }
-    }
-}
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/components/SubmitCancel.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/components/SubmitCancel.java
deleted file mode 100644
index 25e45a8..0000000
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/components/SubmitCancel.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.apache.maven.continuum.web.components;
-
-/*
- * 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 javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.struts2.components.UIBean;
-
-import com.opensymphony.xwork2.util.ValueStack;
-
-/**
- * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
- * @version $Id$
- */
-public class SubmitCancel
-    extends UIBean
-{
-    private static final String TEMPLATE = "submitCancel";
-
-    private String cancel;
-
-    public SubmitCancel( ValueStack stack, HttpServletRequest request, HttpServletResponse response )
-    {
-        super( stack, request, response );
-    }
-
-    protected String getDefaultTemplate()
-    {
-        return TEMPLATE;
-    }
-
-    public void evaluateParams()
-    {
-        super.evaluateParams();
-
-        if ( cancel != null )
-        {
-            addParameter( "cancel", findString( cancel ) );
-        }
-    }
-
-    public void setCancel( String cancel )
-    {
-        this.cancel = cancel;
-    }
-}
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/util/UrlHelperFactory.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/util/UrlHelperFactory.java
new file mode 100644
index 0000000..f987900
--- /dev/null
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/util/UrlHelperFactory.java
@@ -0,0 +1,33 @@
+package org.apache.maven.continuum.web.util;
+
+/*
+ * 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 org.apache.struts2.views.util.DefaultUrlHelper;
+import org.apache.struts2.views.util.UrlHelper;
+
+public class UrlHelperFactory {
+	
+	private UrlHelperFactory() {}
+	
+	public static UrlHelper getInstance() {
+		return new DefaultUrlHelper();
+	}
+
+}
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/util/WorkingCopyContentGenerator.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/util/WorkingCopyContentGenerator.java
index 6153741..9717fd6 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/util/WorkingCopyContentGenerator.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/util/WorkingCopyContentGenerator.java
@@ -38,7 +38,7 @@
 
     private String urlParamSeparator;
 
-    private static DecimalFormat decFormatter = new DecimalFormat( "###.##" );
+    private static final DecimalFormat decFormatter = new DecimalFormat( "###.##" );
 
     private static final long KILO = 1024;
 
@@ -104,8 +104,8 @@
                 }
                 else
                 {
-                    userDirectory =
-                        f.getParentFile().getAbsolutePath().substring( basedir.getAbsolutePath().length() + 1 );
+                    userDirectory = f.getParentFile().getAbsolutePath().substring(
+                        basedir.getAbsolutePath().length() + 1 );
                 }
 
                 userDirectory = StringUtils.replace( userDirectory, "\\", "/" );
@@ -116,8 +116,8 @@
                     imagesBaseUrl ).append( "file.gif\">&nbsp;<a href=\"" ).append( baseUrl ).append(
                     urlParamSeparator ).append( "userDirectory=" ).append( userDirectory ).append( "&file=" ).append(
                     fileName ).append( "\">" ).append( fileName ).append( "</a></td><td width=\"1%\">" ).append(
-                    getReadableFileSize( f.length() ) ).append( "</td><td width=\"1%\">" ).append(
-                    getFormattedDate( f.lastModified() ) ).append( "</td>\n" );
+                    getReadableFileSize( f.length() ) ).append( "</td><td width=\"1%\">" ).append( getFormattedDate(
+                    f.lastModified() ) ).append( "</td>\n" );
                 buf.append( "</tr>\n" );
 
                 odd = !odd;
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/validator/CronExpressionValidator.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/validator/CronExpressionValidator.java
index 23c7229..287c904 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/validator/CronExpressionValidator.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/validator/CronExpressionValidator.java
@@ -19,7 +19,6 @@
  * under the License.
  */
 
-import com.opensymphony.xwork2.ActionContext;
 import com.opensymphony.xwork2.validator.ValidationException;
 import com.opensymphony.xwork2.validator.ValidatorContext;
 import com.opensymphony.xwork2.validator.validators.ValidatorSupport;
@@ -42,8 +41,9 @@
         String dayOfWeek = (String) getFieldValue( "dayOfWeek", object );
         String year = (String) getFieldValue( "year", object );
 
-        String cronExpression = ( second + " " + minute + " " + hour + " " + dayOfMonth + " " + month + " " +
-            dayOfWeek + " " + year ).trim();
+        String cronExpression =
+            ( second + " " + minute + " " + hour + " " + dayOfMonth + " " + month + " " + dayOfWeek + " " +
+                year ).trim();
 
         org.codehaus.plexus.scheduler.CronExpressionValidator validator =
             new org.codehaus.plexus.scheduler.CronExpressionValidator();
@@ -54,7 +54,6 @@
         {
             // FIXME i18n
             ctxt.addActionError( "Invalid cron expression value(s)" );
-            return;
         }
     }
 
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/validator/InstallationValidator.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/validator/InstallationValidator.java
index 0bfe945..d3e44a9 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/validator/InstallationValidator.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/validator/InstallationValidator.java
@@ -24,11 +24,9 @@
 import org.apache.maven.continuum.execution.ExecutorConfigurator;
 import org.apache.maven.continuum.installation.InstallationException;
 import org.apache.maven.continuum.installation.InstallationService;
-import org.codehaus.plexus.logging.LogEnabled;
-import org.codehaus.plexus.logging.Logger;
 import org.codehaus.plexus.util.StringUtils;
-
-import java.util.List;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 
 /**
@@ -39,11 +37,10 @@
  */
 public class InstallationValidator
     extends ValidatorSupport
-    implements LogEnabled
 {
     private String fieldName;
 
-    private Logger logger;
+    private static final Logger logger = LoggerFactory.getLogger( InstallationValidator.class );
 
     /**
      * @plexus.requirement role-hint="default"
@@ -79,8 +76,7 @@
                 if ( executorConfigurator.getVersionArgument() != null )
                 {
                     // just try to get version infos to validate path is valid
-                    List<String> versionInfos = installationService
-                        .getExecutorConfiguratorVersion( varValue, executorConfigurator, null );
+                    installationService.getExecutorVersionInfo( varValue, executorConfigurator, null );
                 }
             }
         }
@@ -92,7 +88,6 @@
         }
     }
 
-
     public String getFieldName()
     {
         return fieldName;
@@ -102,12 +97,4 @@
     {
         this.fieldName = fieldName;
     }
-
-    /**
-     * @see org.codehaus.plexus.logging.LogEnabled#enableLogging(org.codehaus.plexus.logging.Logger)
-     */
-    public void enableLogging( Logger logger )
-    {
-        this.logger = logger;
-    }
 }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/BuildCell.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/BuildCell.java
index 200b240..9232b59 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/BuildCell.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/BuildCell.java
@@ -19,10 +19,15 @@
  * under the License.
  */
 
-import com.opensymphony.xwork2.ActionContext;
+import java.util.HashMap;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.jsp.PageContext;
+
 import org.apache.maven.continuum.security.ContinuumRoleConstants;
 import org.apache.maven.continuum.web.model.ProjectSummary;
-import org.apache.struts2.views.util.UrlHelper;
+import org.apache.maven.continuum.web.util.UrlHelperFactory;
 import org.codehaus.plexus.PlexusConstants;
 import org.codehaus.plexus.PlexusContainer;
 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
@@ -34,10 +39,7 @@
 import org.extremecomponents.table.cell.DisplayCell;
 import org.extremecomponents.table.core.TableModel;
 
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.jsp.PageContext;
-import java.util.HashMap;
+import com.opensymphony.xwork2.ActionContext;
 
 /**
  * Used in Summary view
@@ -76,15 +78,15 @@
             {
                 if ( buildNumber > 0 )
                 {
-                    HashMap params = new HashMap();
+                    HashMap<String, Object> params = new HashMap<String, Object>();
 
-                    params.put( "projectId", new Integer( project.getId() ) );
+                    params.put( "projectId", project.getId() );
 
                     params.put( "projectName", project.getName() );
 
-                    params.put( "buildId", new Integer( project.getBuildInSuccessId() ) );
+                    params.put( "buildId", project.getBuildInSuccessId() );
 
-                    params.put( "projectGroupId", new Integer( project.getProjectGroupId() ) );
+                    params.put( "projectGroupId", project.getProjectGroupId() );
 
                     PageContext pageContext = (PageContext) tableModel.getContext().getContextObject();
 
@@ -92,7 +94,7 @@
 
                     HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();
 
-                    String url = UrlHelper.buildUrl( "/buildResult.action", request, response, params );
+                    String url = UrlHelperFactory.getInstance().buildUrl( "/buildResult.action", request, response, params );
 
                     if ( isAuthorized( project ) )
                     {
@@ -140,8 +142,8 @@
         ActionContext context = ActionContext.getContext();
 
         PlexusContainer container = (PlexusContainer) context.getApplication().get( PlexusConstants.PLEXUS_KEY );
-        SecuritySession securitySession =
-            (SecuritySession) context.getSession().get( SecuritySystemConstants.SECURITY_SESSION_KEY );
+        SecuritySession securitySession = (SecuritySession) context.getSession().get(
+            SecuritySystemConstants.SECURITY_SESSION_KEY );
 
         try
         {
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/BuildStatusCell.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/BuildStatusCell.java
index 921a56f..dde835a 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/BuildStatusCell.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/BuildStatusCell.java
@@ -41,8 +41,8 @@
 
         String success = StateGenerator.generate( ContinuumProjectState.OK, tableModel.getContext().getContextPath() );
 
-        String failed =
-            StateGenerator.generate( ContinuumProjectState.FAILED, tableModel.getContext().getContextPath() );
+        String failed = StateGenerator.generate( ContinuumProjectState.FAILED,
+                                                 tableModel.getContext().getContextPath() );
 
         String error = StateGenerator.generate( ContinuumProjectState.ERROR, tableModel.getContext().getContextPath() );
 
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/StateCell.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/StateCell.java
index b4a4669..7af6d5d 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/StateCell.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/StateCell.java
@@ -19,17 +19,15 @@
  * under the License.
  */
 
-import com.opensymphony.xwork2.ActionContext;
-
-import org.apache.continuum.model.project.ProjectScmRoot;
+import java.util.HashMap;
 
 import org.apache.continuum.model.project.ProjectScmRoot;
 import org.apache.maven.continuum.project.ContinuumProjectState;
 import org.apache.maven.continuum.security.ContinuumRoleConstants;
 import org.apache.maven.continuum.web.model.ProjectSummary;
 import org.apache.maven.continuum.web.util.StateGenerator;
+import org.apache.maven.continuum.web.util.UrlHelperFactory;
 import org.apache.struts2.ServletActionContext;
-import org.apache.struts2.views.util.UrlHelper;
 import org.codehaus.plexus.PlexusConstants;
 import org.codehaus.plexus.PlexusContainer;
 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
@@ -41,7 +39,7 @@
 import org.extremecomponents.table.cell.DisplayCell;
 import org.extremecomponents.table.core.TableModel;
 
-import java.util.HashMap;
+import com.opensymphony.xwork2.ActionContext;
 
 /**
  * Used in Summary view
@@ -70,10 +68,11 @@
                 case ContinuumProjectState.UPDATING:
                 case ContinuumProjectState.CHECKING_OUT:
                 {
-                    String state = StateGenerator.generate( project.getState(), tableModel.getContext().getContextPath() );
+                    String state = StateGenerator.generate( project.getState(),
+                                                            tableModel.getContext().getContextPath() );
 
-                    if ( project.getLatestBuildId() != -1 && !StateGenerator.NEW.equals( state ) 
-                         && project.getState() != ContinuumProjectState.UPDATING )
+                    if ( project.getLatestBuildId() != -1 && !StateGenerator.NEW.equals( state ) &&
+                        project.getState() != ContinuumProjectState.UPDATING )
                     {
                         if ( isAuthorized( project.getProjectGroupName() ) )
                         {
@@ -96,7 +95,7 @@
                 }
             }
         }
-        else 
+        else
         {
             ProjectScmRoot projectScmRoot = (ProjectScmRoot) tableModel.getCurrentRowBean();
 
@@ -106,13 +105,13 @@
                 case ContinuumProjectState.UPDATED:
                 case ContinuumProjectState.ERROR:
                 {
-                    String state = StateGenerator.generate( projectScmRoot.getState(), 
+                    String state = StateGenerator.generate( projectScmRoot.getState(),
                                                             tableModel.getContext().getContextPath() );
-                    
+
                     if ( !StateGenerator.NEW.equals( state ) )
                     {
                         if ( isAuthorized( projectScmRoot.getProjectGroup().getName() ) &&
-                             projectScmRoot.getState() == ContinuumProjectState.ERROR )
+                            projectScmRoot.getState() == ContinuumProjectState.ERROR )
                         {
                             return createActionLink( "scmResult", projectScmRoot, state );
                         }
@@ -137,31 +136,31 @@
 
     private static String createActionLink( String action, ProjectSummary project, String state )
     {
-        HashMap params = new HashMap();
+        HashMap<String, Object> params = new HashMap<String, Object>();
 
-        params.put( "projectId", new Integer( project.getId() ) );
+        params.put( "projectId", project.getId() );
 
         params.put( "projectName", project.getName() );
 
-        params.put( "buildId", new Integer( project.getLatestBuildId() ) );
+        params.put( "buildId", project.getLatestBuildId() );
 
-        params.put( "projectGroupId", new Integer( project.getProjectGroupId() ) );
+        params.put( "projectGroupId", project.getProjectGroupId() );
 
-        String url = UrlHelper.buildUrl( "/" + action + ".action", ServletActionContext.getRequest(),
+        String url = UrlHelperFactory.getInstance().buildUrl( "/" + action + ".action", ServletActionContext.getRequest(),
                                          ServletActionContext.getResponse(), params );
 
         return "<a href=\"" + url + "\">" + state + "</a>";
     }
-    
+
     private static String createActionLink( String action, ProjectScmRoot scmRoot, String state )
     {
-        HashMap params = new HashMap();
+        HashMap<String, Object> params = new HashMap<String, Object>();
 
-        params.put( "projectGroupId", new Integer( scmRoot.getProjectGroup().getId() ) );
+        params.put( "projectGroupId", scmRoot.getProjectGroup().getId() );
 
-        params.put( "projectScmRootId", new Integer( scmRoot.getId() ) );
+        params.put( "projectScmRootId", scmRoot.getId() );
 
-        String url = UrlHelper.buildUrl( "/" + action + ".action", ServletActionContext.getRequest(), 
+        String url = UrlHelperFactory.getInstance().buildUrl( "/" + action + ".action", ServletActionContext.getRequest(),
                                          ServletActionContext.getResponse(), params );
 
         return "<a href=\"" + url + "\">" + state + "</a>";
@@ -173,8 +172,8 @@
         ActionContext context = ActionContext.getContext();
 
         PlexusContainer container = (PlexusContainer) context.getApplication().get( PlexusConstants.PLEXUS_KEY );
-        SecuritySession securitySession =
-            (SecuritySession) context.getSession().get( SecuritySystemConstants.SECURITY_SESSION_KEY );
+        SecuritySession securitySession = (SecuritySession) context.getSession().get(
+            SecuritySystemConstants.SECURITY_SESSION_KEY );
 
         try
         {
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/buildresults/StateCell.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/buildresults/StateCell.java
index e274677..65b76af 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/buildresults/StateCell.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/buildresults/StateCell.java
@@ -50,7 +50,7 @@
 
         if ( value instanceof Integer )
         {
-            state = ( (Integer) value ).intValue();
+            state = (Integer) value;
         }
 
         value = StateGenerator.generate( state, request.getContextPath() );
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/commons/DateCell.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/commons/DateCell.java
index 86ba90e..d74a045 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/commons/DateCell.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/commons/DateCell.java
@@ -51,7 +51,7 @@
             {
                 Calendar cal = Calendar.getInstance();
 
-                cal.setTimeInMillis( ( (Long) value ).longValue() );
+                cal.setTimeInMillis( (Long) value );
 
                 value = cal.getTime();
             }
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/jsp/ui/DataTag.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/jsp/ui/DataTag.java
deleted file mode 100644
index 2f2c46a..0000000
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/jsp/ui/DataTag.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package org.apache.maven.continuum.web.view.jsp.ui;
-
-/*
- * 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 com.opensymphony.xwork2.util.ValueStack;
-import org.apache.maven.continuum.web.components.Data;
-import org.apache.struts2.components.Component;
-import org.apache.struts2.views.jsp.ui.AbstractUITag;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
- * @version $Id$
- */
-public class DataTag
-    extends AbstractUITag
-{
-
-    protected String valueLink;
-
-    public Component getBean( ValueStack stack, HttpServletRequest req, HttpServletResponse res )
-    {
-        return new Data( stack, req, res );
-    }
-
-    public void setValueLink( String _link )
-    {
-        valueLink = _link;
-    }
-
-    protected void populateParams()
-    {
-        super.populateParams();
-
-        Data dataBean = (Data) this.component;
-        dataBean.setValueLink( valueLink );
-    }
-}
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/jsp/ui/DateTag.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/jsp/ui/DateTag.java
index 24d17aa..b55cdcc 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/jsp/ui/DateTag.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/jsp/ui/DateTag.java
@@ -24,14 +24,13 @@
 import com.opensymphony.xwork2.util.ValueStack;
 import org.apache.struts2.views.jsp.ui.TextareaTag;
 
-import javax.servlet.jsp.JspException;
 import java.io.IOException;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Date;
-import java.util.Iterator;
 import java.util.List;
+import javax.servlet.jsp.JspException;
 
 /**
  * First attempt at creating a date tag for the webwork framework. The tag will
@@ -86,8 +85,6 @@
     //our optional format parameter
     private String format;
 
-    private String actualName;
-
     private String nameAttr;
 
     private boolean nice;
@@ -99,7 +96,7 @@
     public int doEndTag()
         throws JspException
     {
-        actualName = findString( nameAttr );
+        String actualName = findString( nameAttr );
         String msg = null;
         ValueStack stack = getStack();
         //find the name on the valueStack, and cast it to a date
@@ -114,7 +111,7 @@
             else if ( dateObj instanceof Long )
             {
                 Calendar cal = Calendar.getInstance();
-                cal.setTimeInMillis( ( (Long) dateObj ).longValue() );
+                cal.setTimeInMillis( (Long) dateObj );
                 date = cal.getTime();
             }
             else
@@ -140,7 +137,7 @@
             {
                 if ( format == null )
                 {
-                    String globalFormat = null;
+                    String globalFormat;
                     //if the format is not specified, fall back using the defined
                     // property DATETAG_PROPERTY
 
@@ -148,8 +145,8 @@
 
                     if ( globalFormat != null )
                     {
-                        msg =
-                            new SimpleDateFormat( globalFormat, ActionContext.getContext().getLocale() ).format( date );
+                        msg = new SimpleDateFormat( globalFormat, ActionContext.getContext().getLocale() ).format(
+                            date );
                     }
                     else
                     {
@@ -189,10 +186,8 @@
 
     private TextProvider findProviderInStack()
     {
-        for ( Iterator iterator = getStack().getRoot().iterator(); iterator.hasNext(); )
+        for ( Object o : getStack().getRoot() )
         {
-            Object o = iterator.next();
-
             if ( o instanceof TextProvider )
             {
                 return (TextProvider) o;
@@ -205,7 +200,7 @@
     public String formatTime( Date date )
     {
         StringBuffer sb = new StringBuffer();
-        List args = new ArrayList();
+        List<Object> args = new ArrayList<Object>();
         long secs = ( new Date().getTime() - date.getTime() ) / 1000;
         long mins = secs / 60;
         int min = (int) mins % 60;
@@ -217,7 +212,7 @@
 
         if ( Math.abs( secs ) < 60 )
         {
-            args.add( new Long( secs ) );
+            args.add( secs );
             args.add( sb );
             args.add( null );
             sb.append( tp.getText( DATETAG_PROPERTY_SECONDS, DATETAG_DEFAULT_SECONDS, args ) );
@@ -225,7 +220,7 @@
         }
         else if ( hours == 0 )
         {
-            args.add( new Long( min ) );
+            args.add( (long) min );
             args.add( sb );
             args.add( null );
             sb.append( tp.getText( DATETAG_PROPERTY_MINUTES, DATETAG_DEFAULT_MINUTES, args ) );
@@ -233,24 +228,24 @@
         }
         else if ( days == 0 )
         {
-            args.add( new Long( hour ) );
-            args.add( new Long( min ) );
+            args.add( (long) hour );
+            args.add( (long) min );
             args.add( sb );
             args.add( null );
             sb.append( tp.getText( DATETAG_PROPERTY_HOURS, DATETAG_DEFAULT_HOURS, args ) );
         }
         else if ( years == 0 )
         {
-            args.add( new Long( days ) );
-            args.add( new Long( hour ) );
+            args.add( (long) days );
+            args.add( (long) hour );
             args.add( sb );
             args.add( null );
             sb.append( tp.getText( DATETAG_PROPERTY_DAYS, DATETAG_DEFAULT_DAYS, args ) );
         }
         else
         {
-            args.add( new Object[]{new Long( years )} );
-            args.add( new Object[]{new Long( day )} );
+            args.add( new Object[]{(long) years} );
+            args.add( new Object[]{(long) day} );
             args.add( sb );
             args.add( null );
 
@@ -269,12 +264,6 @@
         }
     }
 
-    public int doStartTag()
-        throws JspException
-    {
-        return super.doStartTag();
-    }
-
     public void setName( String name )
     {
         this.nameAttr = name;
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/jsp/ui/IfBuildTypeEnabledTag.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/jsp/ui/IfBuildTypeEnabledTag.java
new file mode 100644
index 0000000..07aae71
--- /dev/null
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/jsp/ui/IfBuildTypeEnabledTag.java
@@ -0,0 +1,88 @@
+package org.apache.maven.continuum.web.view.jsp.ui;
+
+/*
+ * 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 org.apache.maven.continuum.Continuum;
+import org.codehaus.plexus.spring.PlexusToSpringUtils;
+import org.springframework.context.ApplicationContext;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+
+import javax.servlet.jsp.JspTagException;
+import javax.servlet.jsp.jstl.core.ConditionalTagSupport;
+
+/**
+ * ifBuildTypeEnabledTag:
+ *
+ * @author Jan Ancajas <jansquared@gmail.com>
+ * @version $Id: IfBuildTypeEnabledTag.java
+ */
+public class IfBuildTypeEnabledTag
+    extends ConditionalTagSupport
+{
+    private Continuum continuum;
+
+    private String buildType;
+
+    public static final String DISTRIBUTED = "distributed";
+
+    protected boolean condition()
+        throws JspTagException
+    {
+
+        ApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(
+            pageContext.getServletContext() );
+        this.setContinuum( (Continuum) applicationContext.getBean( PlexusToSpringUtils.buildSpringId( Continuum.ROLE,
+                                                                                                      "default" ) ) );
+
+        if ( continuum == null )
+        {
+            throw new JspTagException( "cannot lookup component:  " + Continuum.ROLE );
+        }
+
+        if ( DISTRIBUTED.equals( buildType ) )
+        {
+            return continuum.getConfiguration().isDistributedBuildEnabled();
+        }
+
+        // left out 'parallel' buildType checking for cyclomatic complexity's sake :)
+        return !continuum.getConfiguration().isDistributedBuildEnabled();
+
+    }
+
+    public String getBuildType()
+    {
+        return buildType;
+    }
+
+    public void setBuildType( String buildType )
+    {
+        this.buildType = buildType;
+    }
+
+    public Continuum getContinuum()
+    {
+        return continuum;
+    }
+
+    public void setContinuum( Continuum continuum )
+    {
+        this.continuum = continuum;
+    }
+}
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/jsp/ui/SubmitCancelTag.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/jsp/ui/SubmitCancelTag.java
deleted file mode 100644
index 4ecf373..0000000
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/jsp/ui/SubmitCancelTag.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.apache.maven.continuum.web.view.jsp.ui;
-
-/*
- * 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 javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.maven.continuum.web.components.SubmitCancel;
-import org.apache.struts2.components.Component;
-import org.apache.struts2.views.jsp.ui.AbstractUITag;
-
-import com.opensymphony.xwork2.util.OgnlValueStack;
-import com.opensymphony.xwork2.util.ValueStack;
-
-/**
- * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
- * @version $Id$
- */
-public class SubmitCancelTag
-    extends AbstractUITag
-{
-    private String cancel;
-
-    public Component getBean( OgnlValueStack stack, HttpServletRequest req, HttpServletResponse res )
-    {
-        return new SubmitCancel( stack, req, res );
-    }
-
-    protected void populateParams()
-    {
-        super.populateParams();
-
-        SubmitCancel submitCancel = ( (SubmitCancel) component );
-        submitCancel.setCancel( cancel );
-    }
-
-    public void setCancel( String cancel )
-    {
-        this.cancel = cancel;
-    }
-    
-    public Component getBean( ValueStack valueStack, HttpServletRequest request, HttpServletResponse response )
-    {
-        return new SubmitCancel( valueStack, request, response );
-    }
-    
-}
diff --git a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/projectview/NotifierRecipientCell.java b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/projectview/NotifierRecipientCell.java
index 9a67bcc..7932fb1 100644
--- a/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/projectview/NotifierRecipientCell.java
+++ b/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/projectview/NotifierRecipientCell.java
@@ -19,8 +19,8 @@
  * under the License.
  */
 
+import org.apache.continuum.web.util.GenerateRecipentNotifier;
 import org.apache.maven.continuum.model.project.ProjectNotifier;
-import org.apache.maven.continuum.notification.AbstractContinuumNotifier;
 import org.extremecomponents.table.bean.Column;
 import org.extremecomponents.table.cell.DisplayCell;
 import org.extremecomponents.table.core.TableModel;
@@ -40,37 +40,6 @@
     {
         ProjectNotifier notifier = (ProjectNotifier) tableModel.getCurrentRowBean();
 
-        if ( "irc".equals( notifier.getType() ) )
-        {
-            String address = "";
-
-            if ( notifier.getConfiguration().get( "host" ) != null )
-            {
-                address += notifier.getConfiguration().get( "host" ) + ":";
-            }
-
-            if ( notifier.getConfiguration().get( "port" ) != null )
-            {
-                address += notifier.getConfiguration().get( "port" ) + ":";
-            }
-
-            if ( notifier.getConfiguration().get( "channel" ) != null )
-            {
-                address += notifier.getConfiguration().get( "channel" );
-            }
-
-            return address;
-        }
-        else
-        {
-            if ( "wagon".equals( notifier.getType() ) )
-            {
-                return notifier.getConfiguration().get( "url" ).toString();
-            }
-
-            String address = (String) notifier.getConfiguration().get( AbstractContinuumNotifier.ADDRESS_FIELD );
-
-            return address == null ? "" : address;
-        }
+        return GenerateRecipentNotifier.generate( notifier );
     }
 }
diff --git a/continuum-webapp/src/main/mdo/appearance-models.mdo b/continuum-webapp/src/main/mdo/appearance-models.mdo
index eee9090..8947a8a 100644
--- a/continuum-webapp/src/main/mdo/appearance-models.mdo
+++ b/continuum-webapp/src/main/mdo/appearance-models.mdo
@@ -1,4 +1,5 @@
 <?xml version="1.0"?>
+
 <!--
   ~ Licensed to the Apache Software Foundation (ASF) under one
   ~ or more contributor license agreements.  See the NOTICE file
@@ -17,6 +18,7 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
   -->
+
 <model>
   <id>continuum-appearance-models</id>
   <name>ContinuumAppearanceModels</name>
diff --git a/continuum-webapp/src/main/mdo/session-models.mdo b/continuum-webapp/src/main/mdo/session-models.mdo
deleted file mode 100644
index a14cd25..0000000
--- a/continuum-webapp/src/main/mdo/session-models.mdo
+++ /dev/null
@@ -1,97 +0,0 @@
-<?xml version="1.0"?>
-<!--
-  ~ 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.
-  -->
-<model>
-  <id>continuum-session-models</id>
-  <name>ContinuumSessionModels</name>
-  <defaults>
-    <default>
-      <key>package</key>
-      <value>org.apache.maven.continuum.web.model</value>
-    </default>
-  </defaults>
-  <classes>
-    <class rootElement="true">
-      <name>Session</name>
-      <version>1.0.0</version>
-      <fields>
-        <field>
-          <name>sessionUsers</name>
-          <version>1.0.0</version>
-          <description></description>
-          <required>true</required>
-          <association>
-            <type>SessionUser</type>
-            <multiplicity>*</multiplicity>
-          </association>
-        </field>
-      </fields>
-    </class>
-    <class>
-      <name>SessionUser</name>
-      <version>1.0.0</version>
-      <fields>
-        <field>
-          <name>id</name>
-          <version>1.0.0</version>
-          <required>true</required>
-          <description>id of the user</description>
-          <type>int</type>
-        </field>
-        <field>
-          <name>username</name>
-          <version>1.0.0</version>
-          <required>true</required>
-          <description>username</description>
-          <type>String</type>
-        </field>
-        <field>
-          <name>fullName</name>
-          <version>1.0.0</version>
-          <required>true</required>
-          <description>full name of the user</description>
-          <type>String</type>
-        </field>
-        <field>
-          <name>email</name>
-          <version>1.0.0</version>
-          <required>true</required>
-          <description>email of the user</description>
-          <type>String</type>
-        </field>
-        <field>
-          <name>userGroupId</name>
-          <version>1.0.0</version>
-          <required>true</required>
-          <description>user group the user is a member of</description>
-          <type>int</type>
-        </field>
-        <field>
-          <name>loggedIn</name>
-          <version>1.0.0</version>
-          <required>true</required>
-          <description>boolean for the user is logged in or not</description>
-          <type>boolean</type>
-          <required>true</required>
-          <defaultValue>false</defaultValue>
-        </field>
-      </fields>
-    </class>
-  </classes>
-</model>
\ No newline at end of file
diff --git a/continuum-webapp/src/main/mdo/view-models.mdo b/continuum-webapp/src/main/mdo/view-models.mdo
index 750ca32..2db17c0 100644
--- a/continuum-webapp/src/main/mdo/view-models.mdo
+++ b/continuum-webapp/src/main/mdo/view-models.mdo
@@ -1,4 +1,5 @@
 <?xml version="1.0"?>
+
 <!--
   ~ Licensed to the Apache Software Foundation (ASF) under one
   ~ or more contributor license agreements.  See the NOTICE file
@@ -17,6 +18,7 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
   -->
+
 <model>
   <id>continuum-view-models</id>
   <name>ContinuumViewModels</name>
@@ -29,11 +31,11 @@
   <classes>
     <class rootElement="true">
       <name>ContinuumViewModels</name>
-      <version>1.0.0</version>
+      <version>1.0.0+</version>
       <fields>
         <field>
           <name>projectSummarys</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <description></description>
           <required>true</required>
           <association>
@@ -41,9 +43,9 @@
             <multiplicity>*</multiplicity>
           </association>
         </field>
-         <field>
+        <field>
           <name>groupSummarys</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <description></description>
           <required>true</required>
           <association>
@@ -51,9 +53,9 @@
             <multiplicity>*</multiplicity>
           </association>
         </field>
-         <field>
+        <field>
           <name>buildDefinitionSummarys</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <description></description>
           <required>true</required>
           <association>
@@ -63,7 +65,7 @@
         </field>
         <field>
           <name>notifierSummarys</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <description></description>
           <required>false</required>
           <association>
@@ -75,11 +77,11 @@
     </class>
     <class>
       <name>ProjectSummary</name>
-      <version>1.0.0</version>
+      <version>1.0.0+</version>
       <fields>
         <field>
           <name>id</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>project id of the project</description>
           <type>int</type>
@@ -87,21 +89,21 @@
         </field>
         <field>
           <name>name</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>name of the project</description>
           <type>String</type>
         </field>
         <field>
           <name>version</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>version of the project</description>
           <type>String</type>
         </field>
         <field>
           <name>projectGroupId</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>id of the project group this project is a member of</description>
           <type>int</type>
@@ -109,14 +111,14 @@
         </field>
         <field>
           <name>projectGroupName</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>name of the project group this project is a member of</description>
           <type>String</type>
         </field>
         <field>
           <name>latestBuildId</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>latest build id of the project</description>
           <type>int</type>
@@ -124,7 +126,7 @@
         </field>
         <field>
           <name>buildInSuccessId</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description></description>
           <type>int</type>
@@ -132,7 +134,7 @@
         </field>
         <field>
           <name>buildNumber</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description></description>
           <type>int</type>
@@ -140,7 +142,7 @@
         </field>
         <field>
           <name>state</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>lifecycle state of the project</description>
           <type>int</type>
@@ -148,7 +150,7 @@
         </field>
         <field>
           <name>inBuildingQueue</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>true/false depending on if the project is in the build queue or not</description>
           <type>boolean</type>
@@ -156,7 +158,7 @@
         </field>
         <field>
           <name>inCheckoutQueue</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>true/false depending on if the project is in the checkout queue or not</description>
           <type>boolean</type>
@@ -164,21 +166,21 @@
         </field>
         <field>
           <name>lastBuildDateTime</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>last build dateTime of the project</description>
           <type>long</type>
         </field>
         <field>
           <name>lastBuildDuration</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>last build duration of the project</description>
           <type>String</type>
         </field>
         <field>
           <name>projectType</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>type of the project</description>
           <type>String</type>
@@ -187,11 +189,11 @@
     </class>
     <class>
       <name>GroupSummary</name>
-      <version>1.0.0</version>
+      <version>1.0.0+</version>
       <fields>
         <field>
           <name>id</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>internal continuum group id</description>
           <type>int</type>
@@ -199,56 +201,56 @@
         </field>
         <field>
           <name>name</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>name of the project group</description>
           <type>String</type>
         </field>
-         <field>
+        <field>
           <name>groupId</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>false</required>
           <description>maven groupId of the project group</description>
           <type>String</type>
         </field>
         <field>
           <name>description</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>false</required>
           <description>description of the project group</description>
           <type>String</type>
         </field>
         <field>
           <name>numProjects</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>the number of projects in the project group</description>
           <type>int</type>
         </field>
         <field>
           <name>projectType</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>the type of project, maven2/maven1/ant/shell</description>
           <type>String</type>
         </field>
         <field>
           <name>statusMessage</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>false</required>
           <description>a status message like, (building project X)</description>
           <type>String</type>
         </field>
         <field>
-         <name>nextScheduledBuild</name>
-          <version>1.0.0</version>
+          <name>nextScheduledBuild</name>
+          <version>1.0.0+</version>
           <required>false</required>
           <description>timestamp for the next scheduled build</description>
           <type>String</type>
         </field>
         <field>
           <name>projects</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <description></description>
           <required>true</required>
           <association>
@@ -258,31 +260,31 @@
         </field>
         <field>
           <name>numSuccesses</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>number of successful builds in the project group</description>
           <type>int</type>
-          <defaultValue>-1</defaultValue>
+          <defaultValue>0</defaultValue>
         </field>
         <field>
           <name>numFailures</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>number of failed builds in the project group</description>
           <type>int</type>
-          <defaultValue>-1</defaultValue>
+          <defaultValue>0</defaultValue>
         </field>
         <field>
           <name>numErrors</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>number of errored builds in the project group</description>
           <type>int</type>
-          <defaultValue>-1</defaultValue>
+          <defaultValue>0</defaultValue>
         </field>
         <field>
           <name>repositoryId</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>false</required>
           <description>local repository id of the project group</description>
           <type>int</type>
@@ -290,7 +292,7 @@
         </field>
         <field>
           <name>repositoryName</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>false</required>
           <description>local repository name of the project group</description>
           <type>String</type>
@@ -303,235 +305,357 @@
       <fields>
         <field>
           <name>id</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>id of the build definition</description>
           <type>int</type>
         </field>
         <field>
           <name>projectId</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>false</required>
           <description>project id of the project containing the build definition</description>
           <type>int</type>
         </field>
         <field>
           <name>projectGroupId</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>false</required>
           <description>project group id of the project group with the build definition</description>
           <type>int</type>
         </field>
         <field>
           <name>goals</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>goals for build definition</description>
           <type>String</type>
         </field>
         <field>
           <name>arguments</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>arguments for build definition</description>
           <type>String</type>
         </field>
         <field>
           <name>buildFile</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>goals for build definition</description>
           <type>String</type>
         </field>
         <field>
           <name>isBuildFresh</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <description>if the build is to be smoked and checked back out from the scm each build</description>
           <type>boolean</type>
         </field>
         <field>
           <name>isDefault</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <description>if the build definition is used in default cases</description>
           <type>boolean</type>
         </field>
         <field>
           <name>scheduleId</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>id of the schedule for build definition</description>
           <type>int</type>
         </field>
         <field>
           <name>scheduleName</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>name of the schedule for build definition</description>
           <type>String</type>
         </field>
         <field>
           <name>from</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>source of build definition, project or project group lvl</description>
           <type>String</type>
         </field>
         <field>
           <name>profileName</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>name of the profile for the build definition</description>
           <type>String</type>
         </field>
         <field>
           <name>projectName</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>if project lvl, then the name of the project using the definition</description>
           <type>String</type>
         </field>
         <field>
           <name>profileId</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>id of the profile for build definition</description>
           <type>int</type>
-        </field> 
+        </field>
         <field>
           <name>description</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <type>String</type>
           <description>description of the buid defintion</description>
         </field>
         <field>
           <name>type</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <type>String</type>
           <description>type of the buid defintion</description>
-        </field>   
+        </field>
         <field>
           <name>alwaysBuild</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <type>boolean</type>
           <defaultValue>false</defaultValue>
           <description>true if the build had to be forced even if there is no scm change</description>
-        </field>                    
+        </field>
       </fields>
     </class>
     <class>
       <name>NotifierSummary</name>
       <version>1.0.0+</version>
-       <fields>
+      <fields>
         <field>
           <name>id</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>id of the notifier</description>
           <type>int</type>
         </field>
         <field>
           <name>projectId</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>false</required>
           <description>project id of the project containing the notifier</description>
           <type>int</type>
         </field>
         <field>
           <name>projectName</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>false</required>
           <description>project name of the project containing the notifier</description>
           <type>String</type>
         </field>
         <field>
           <name>projectGroupId</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>false</required>
           <description>project group id of the project group with the notifier</description>
           <type>int</type>
         </field>
         <field>
           <name>type</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>Type of notifier - mail, IRC, jabber etc.</description>
           <type>String</type>
         </field>
         <field>
           <name>fromProject</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>The origin of the notifier (pom or user).</description>
           <type>boolean</type>
         </field>
         <field>
           <name>events</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>false</required>
           <description>Events that trigger this notifier</description>
           <type>String</type>
         </field>
         <field>
           <name>recipient</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>false</required>
           <description>Recipient for notifications generated by the notifier</description>
           <type>String</type>
         </field>
         <field>
           <name>sender</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>false</required>
           <description>Sender of the notifications</description>
           <type>String</type>
         </field>
         <field>
           <name>enabled</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>Determines if the notifier is enabled</description>
           <type>boolean</type>
         </field>
       </fields>
-    </class>    
+    </class>
     <class>
-      <name>DistributedBuildSummary</name>
+      <name>PrepareBuildSummary</name>
       <version>1.0.0+</version>
       <fields>
         <field>
-          <name>url</name>
-          <version>1.0.0</version>
-          <required>true</required>
+          <name>buildAgentUrl</name>
+          <version>1.0.0+</version>
+          <required>false</required>
           <description>URL of the build agent</description>
           <type>String</type>
         </field>
         <field>
           <name>projectGroupId</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>ID of the project group</description>
           <type>int</type>
         </field>
         <field>
           <name>projectGroupName</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>Name of the project group</description>
           <type>String</type>
         </field>
         <field>
           <name>scmRootAddress</name>
-          <version>1.0.0</version>
+          <version>1.0.0+</version>
           <required>true</required>
           <description>Scm root address of projects</description>
           <type>String</type>
         </field>
         <field>
-          <name>cancelEnabled</name>
-          <version>1.0.0</version>
+          <name>scmRootId</name>
+          <version>1.0.0+</version>
           <required>true</required>
-          <description>Determines if the cancel button is enabled</description>
-          <type>boolean</type>
+          <description>ID of the scm root</description>
+          <type>int</type>
+        </field>
+        <field>
+          <name>hashCode</name>
+          <version>1.0.0+</version>
+          <required>false</required>
+          <type>int</type>
+        </field>
+        <field>
+          <name>queueName</name>
+          <version>1.4.1+</version>
+          <required>true</required>
+          <description>Name where the prepare build is queued</description>
+          <type>String</type>
+        </field>
+      </fields>
+    </class>
+    <class>
+      <name>DistributedReleaseSummary</name>
+      <version>1.0.0+</version>
+      <fields>
+        <field>
+          <name>releaseId</name>
+          <version>1.0.0+</version>
+          <required>true</required>
+          <type>String</type>
+        </field>
+        <field>
+          <name>releaseGoal</name>
+          <version>1.0.0+</version>
+          <required>true</required>
+          <type>String</type>
+        </field>
+        <field>
+          <name>buildAgentUrl</name>
+          <version>1.0.0+</version>
+          <required>true</required>
+          <type>String</type>
+        </field>
+        <field>
+          <name>projectId</name>
+          <version>1.0.0+</version>
+          <required>true</required>
+          <type>int</type>
+        </field>
+      </fields>
+    </class>
+    <class>
+      <name>DistributedBuildSummary</name>
+      <version>1.0.0+</version>
+      <fields>
+        <field>
+          <name>projectId</name>
+          <version>1.0.0+</version>
+          <required>true</required>
+          <type>int</type>
+        </field>
+        <field>
+          <name>projectName</name>
+          <version>1.0.0+</version>
+          <required>true</required>
+          <type>String</type>
+        </field>
+        <field>
+          <name>projectGroupName</name>
+          <version>1.0.0+</version>
+          <required>true</required>
+          <type>String</type>
+        </field>
+        <field>
+          <name>buildDefinitionId</name>
+          <version>1.0.0+</version>
+          <required>true</required>
+          <type>int</type>
+        </field>
+        <field>
+          <name>buildDefinitionLabel</name>
+          <version>1.0.0+</version>
+          <required>true</required>
+          <type>String</type>
+        </field>
+        <field>
+          <name>buildAgentUrl</name>
+          <version>1.0.0+</version>
+          <required>true</required>
+          <type>String</type>
+        </field>
+        <field>
+          <name>hashCode</name>
+          <version>1.0.0+</version>
+          <required>true</required>
+          <type>int</type>
+        </field>
+      </fields>
+    </class>
+    <class>
+      <name>ProjectBuildsSummary</name>
+      <version>1.4.1+</version>
+      <fields>
+        <field>
+          <name>projectGroupName</name>
+          <version>1.4.1+</version>
+          <type>String</type>
+        </field>
+        <field>
+          <name>projectName</name>
+          <version>1.4.1+</version>
+          <type>String</type>
+        </field>
+        <field>
+          <name>buildDate</name>
+          <version>1.4.1+</version>
+          <type>long</type>
+        </field>
+        <field>
+          <name>buildState</name>
+          <version>1.4.1+</version>
+          <type>int</type>
+        </field>
+        <field>
+          <name>buildTriggeredBy</name>
+          <version>1.4.1+</version>
+          <type>String</type>
         </field>
       </fields>
     </class>
diff --git a/continuum-webapp/src/main/resources/META-INF/continuum/continuum-configuration.xml b/continuum-webapp/src/main/resources/META-INF/continuum/continuum-configuration.xml
index d273425..7168804 100644
--- a/continuum-webapp/src/main/resources/META-INF/continuum/continuum-configuration.xml
+++ b/continuum-webapp/src/main/resources/META-INF/continuum/continuum-configuration.xml
@@ -21,9 +21,9 @@
 
 <configuration>
   <system/>
-  <jndi prefix="java:comp/env" config-optional="true"/>  
+  <jndi prefix="java:comp/env" config-optional="true"/>
   <xml fileName="${appserver.base}/conf/continuum.xml" config-optional="true"
        config-forceCreate="true" config-name="org.apache.continuum"/>
   <xml fileName="${user.home}/.m2/continuum.xml" config-optional="true"
-       config-forceCreate="true" config-name="org.apache.continuum.user"/>  
+       config-forceCreate="true" config-name="org.apache.continuum.user"/>
 </configuration>
diff --git a/continuum-webapp/src/main/resources/META-INF/plexus/application.xml b/continuum-webapp/src/main/resources/META-INF/plexus/application.xml
index 48f69bb..37488da 100644
--- a/continuum-webapp/src/main/resources/META-INF/plexus/application.xml
+++ b/continuum-webapp/src/main/resources/META-INF/plexus/application.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="ISO-8859-1"?>
+
 <!--
   ~ Licensed to the Apache Software Foundation (ASF) under one
   ~ or more contributor license agreements.  See the NOTICE file
@@ -17,6 +18,7 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
   -->
+
 <plexus>
   <components>
     <component>
@@ -33,11 +35,12 @@
           <properties fileName="${appserver.base}/conf/security.properties" config-optional="true"
                       config-at="org.codehaus.plexus.redback"/>
           <!-- Defaults -->
-          <properties fileName="org/apache/maven/continuum/security.properties" config-at="org.codehaus.plexus.redback"/>
+          <properties fileName="org/apache/maven/continuum/security.properties"
+                      config-at="org.codehaus.plexus.redback"/>
         </properties>
       </configuration>
     </component>
-  
+
 
     <!--
     | The mail notifier
@@ -70,13 +73,13 @@
           <role>org.apache.maven.continuum.reports.surefire.ReportTestSuiteGenerator</role>
           <field-name>reportTestSuiteGenerator</field-name>
           <role-hint>default</role-hint>
-        </requirement>        
+        </requirement>
       </requirements>
       <configuration>
         <from-mailbox></from-mailbox>
         <from-name></from-name>
         <timestamp-format>EEE d MMM yyyy HH:mm:ss Z</timestamp-format>
-        <!-- Customizable mail subject.  Use any combination of literal text, or state, project, or build attributes.
+        <!-- Customizable mail subject for the actual build.  Use any combination of literal text, or state, project, or build attributes.
           Examples: 
             "[continuum] BUILD ${state}: ${project.groupId} ${project.name}"
               results in "[continuum] BUILD SUCCESSFUL: foo.bar Hello World"
@@ -93,17 +96,20 @@
             "[continuum] BUILD ${state}: ${project.name}, Build Def - ${build.buildDefinition.description}" 
               results in "[continuum] BUILD SUCCESSFUL: Hello World, Build Def - Nightly Test Build"
          -->
-        <subject-format>[continuum] BUILD ${state}: ${project.projectGroup.name} - ${project.name} - ${build.buildDefinition.description}</subject-format>
-        <includeBuildResult>true</includeBuildResult>
+        <buildSubjectFormat>[continuum] BUILD ${state}: ${project.projectGroup.name} - ${project.name} -
+          ${build.buildDefinition.description}
+        </buildSubjectFormat>
+        <prepareBuildSubjectFormat>[continuum] PREPARE BUILD ${state}: ${projectScmRoot.projectGroup.name}
+        </prepareBuildSubjectFormat>
         <includeBuildSummary>true</includeBuildSummary>
         <includeTestSummary>true</includeTestSummary>
-        <includeOutput>false</includeOutput>
+        <includeBuildOutput>false</includeBuildOutput>
         <alwaysSend>false</alwaysSend>
         <!--
         Setting this propery will make Continuum send all emails to
         this address instead the address specified in the project
         configuration
-        -->        
+        -->
         <toOverride></toOverride>
       </configuration>
     </component>
@@ -205,12 +211,33 @@
             <name>org.jpox.rdbms.dateTimezone</name>
             <value>JDK_DEFAULT_TIMEZONE</value>
           </property>
-<!--
           <property>
-            <name>org.jpox.identifier.case</name>
-            <value>PreserveCase</value>
+            <name>org.jpox.cache.level2</name>
+            <value>true</value>
           </property>
--->
+          <property>
+            <name>org.jpox.cache.level2.type</name>
+            <value>ehcacheclassbased</value>
+          </property>
+          <property>
+            <name>org.jpox.cache.level2.configurationFile</name>
+            <value>/ehcache.xml</value>
+          </property>
+          <property>
+            <name>org.jpox.cache.level2.cacheName</name>
+            <value>default</value>
+          </property>
+          <!-- this is required for some MySQL versions and configurations, see CONTINUUM-1113 -->
+          <property>
+            <name>org.jpox.rdbms.stringDefaultLength</name>
+            <value>255</value>
+          </property>
+          <!--
+                    <property>
+                      <name>org.jpox.identifier.case</name>
+                      <value>PreserveCase</value>
+                    </property>
+          -->
         </otherProperties>
       </configuration>
     </component>
@@ -225,12 +252,16 @@
 
         <persistenceManagerFactoryClass>org.jpox.PersistenceManagerFactoryImpl</persistenceManagerFactoryClass>
 
+        <!-- START SNIPPET: mapping -->
         <otherProperties>
-          <!-- uncomment this property for mssql support - CONTINUUM-697 -->
-          <!-- property>
+          <property>
             <name>javax.jdo.option.Mapping</name>
-            <value>mssql</value>
-          </property -->
+            <value>default</value>
+            <!-- change this property for SQL Server or Oracle support - CONTINUUM-697 -->
+            <!-- value>mssql</value -->
+            <!-- value>oracle</value -->
+          </property>
+          <!-- END SNIPPET: mapping -->
           <property>
             <name>org.jpox.autoCreateSchema</name>
             <value>true</value>
@@ -268,13 +299,13 @@
             <name>org.jpox.autoCreateColumns</name>
             <value>true</value>
           </property>
-			
-<!--
-          <property>
-            <name>org.jpox.identifier.case</name>
-            <value>PreserveCase</value>
-          </property>
--->
+
+          <!--
+                    <property>
+                      <name>org.jpox.identifier.case</name>
+                      <value>PreserveCase</value>
+                    </property>
+          -->
         </otherProperties>
       </configuration>
     </component>
@@ -326,7 +357,6 @@
        user.manager.impl=ldap
        ldap.bind.authenticator.enabled=true
        redback.default.admin=admin
-       redback.default.guest=guest
        security.policy.password.expiration.enabled=false
 
        ldap.config.hostname=ldap.hostname
@@ -365,30 +395,30 @@
         </requirement>
       </requirements>
     </component-->
-    
+
     <!-- 
-    
-    this component manages the mapping of attributes in ldap to user information in redback. To configure the mapping, you can add the following properties in your security.properties
 
-       ============================================================
-       ldap.config.mapper.attribute.email=mail
-       ldap.config.mapper.attribute.fullname=givenName
-       ldap.config.mapper.attribute.password=userPassword
-       ldap.config.mapper.attribute.user.id=cn
-       ldap.config.mapper.attribute.user.base.dn=
-       ldap.config.mapper.attribute.user.object.class=inetOrgPerson
-       ldap.config.mapper.attribute.user.filter=(attributeName=value)
-       ============================================================
+   this component manages the mapping of attributes in ldap to user information in redback. To configure the mapping, you can add the following properties in your security.properties
+
+      ============================================================
+      ldap.config.mapper.attribute.email=mail
+      ldap.config.mapper.attribute.fullname=givenName
+      ldap.config.mapper.attribute.password=userPassword
+      ldap.config.mapper.attribute.user.id=cn
+      ldap.config.mapper.attribute.user.base.dn=
+      ldap.config.mapper.attribute.user.object.class=inetOrgPerson
+      ldap.config.mapper.attribute.user.filter=(attributeName=value)
+      ============================================================
 
 
-     * email-attribute - The name of the attribute on a user that contains the email address
-     * full-name-attribute - The name of the attribute on a user that contains the users fullName
-     * password-attribute - The name of the attribute containing the users password, used for the authentiction using the user manager and not the ldap bind authenticator
-     * user-id-attribute - The name of the attribute containing the users userId, most commonly cn or sn.
-     * user-base-dn - The base dn that will be subtree searched for users.
-     * user-object-class - the objectClass used in the ldap server for indentifying users, most commonly inetOrgPerson.
-     -->
-    
+    * email-attribute - The name of the attribute on a user that contains the email address
+    * full-name-attribute - The name of the attribute on a user that contains the users fullName
+    * password-attribute - The name of the attribute containing the users password, used for the authentiction using the user manager and not the ldap bind authenticator
+    * user-id-attribute - The name of the attribute containing the users userId, most commonly cn or sn.
+    * user-base-dn - The base dn that will be subtree searched for users.
+    * user-object-class - the objectClass used in the ldap server for indentifying users, most commonly inetOrgPerson.
+    -->
+
     <!-- component>
       <role>org.codehaus.plexus.redback.common.ldap.UserMapper</role>
       <role-hint>ldap</role-hint>
@@ -407,14 +437,14 @@
         </requirement>
       </requirements>
     </component-->
-    
+
     <!--
      
     If caching is desired to improve performance then make uncomment this and make sure the following configuration parameter is in the security.properties
      
     user.manager.impl=cached
     -->
-     
+
     <!-- component>
       <role>org.codehaus.plexus.redback.users.UserManager</role>
       <role-hint>cached</role-hint>
@@ -433,7 +463,7 @@
         </requirement>
       </requirements>
     </component-->
-    
+
     <!-- 
     
     if using the user manager authenticator to authenticate the user and not the ldap bind authenticator make sure
@@ -445,7 +475,7 @@
     
     in the security.properties
     -->
-    
+
     <!-- component>
       <role>org.codehaus.plexus.redback.policy.UserSecurityPolicy</role>
       <role-hint>default</role-hint>
diff --git a/continuum-webapp/src/main/resources/ehcache.xml b/continuum-webapp/src/main/resources/ehcache.xml
new file mode 100644
index 0000000..01be209
--- /dev/null
+++ b/continuum-webapp/src/main/resources/ehcache.xml
@@ -0,0 +1,113 @@
+<!--
+  ~ 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.
+  -->
+
+<ehcache>
+  <diskStore path="java.io.tmpdir"/>
+
+  <!-- make default cache very short lived -->
+  <defaultCache
+      maxElementsInMemory="100"
+      maxElementsOnDisk="0"
+      eternal="false"
+      overflowToDisk="false"
+      timeToIdleSeconds="300"
+      timeToLiveSeconds="600"
+      memoryStoreEvictionPolicy="LFU"/>
+
+  <!--
+    cache Redback classes longer to avoid a lot of SQL queries
+    See REDBACK-227
+  -->
+  <cache name="org.codehaus.plexus.redback.rbac.jdo.JdoOperation"
+         maxElementsInMemory="10000"
+         maxElementsOnDisk="0"
+         eternal="false"
+         overflowToDisk="false"
+         timeToIdleSeconds="1800"
+         timeToLiveSeconds="14400"
+         memoryStoreEvictionPolicy="LFU"/>
+
+  <cache name="org.codehaus.plexus.redback.rbac.jdo.JdoPermission"
+         maxElementsInMemory="10000"
+         maxElementsOnDisk="0"
+         eternal="false"
+         overflowToDisk="false"
+         timeToIdleSeconds="1800"
+         timeToLiveSeconds="14400"
+         memoryStoreEvictionPolicy="LFU"/>
+
+  <cache name="org.codehaus.plexus.redback.rbac.jdo.JdoResource"
+         maxElementsInMemory="10000"
+         maxElementsOnDisk="0"
+         eternal="false"
+         overflowToDisk="false"
+         timeToIdleSeconds="1800"
+         timeToLiveSeconds="14400"
+         memoryStoreEvictionPolicy="LFU"/>
+
+  <cache name="org.codehaus.plexus.redback.rbac.jdo.JdoRole"
+         maxElementsInMemory="10000"
+         maxElementsOnDisk="0"
+         eternal="false"
+         overflowToDisk="false"
+         timeToIdleSeconds="1800"
+         timeToLiveSeconds="14400"
+         memoryStoreEvictionPolicy="LFU"/>
+
+  <cache name="org.codehaus.plexus.redback.rbac.jdo.JdoUserAssignment"
+         maxElementsInMemory="10000"
+         maxElementsOnDisk="0"
+         eternal="false"
+         overflowToDisk="false"
+         timeToIdleSeconds="300"
+         timeToLiveSeconds="600"
+         memoryStoreEvictionPolicy="LFU"/>
+
+  <!-- 
+    cache Continuum classes
+   -->
+  <cache name="org.apache.maven.continuum.model.project.Project.buildResults"
+         maxElementsInMemory="10000"
+         maxElementsOnDisk="0"
+         eternal="false"
+         overflowToDisk="false"
+         timeToIdleSeconds="300"
+         timeToLiveSeconds="600"
+         memoryStoreEvictionPolicy="LFU"/>
+
+  <cache name="org.apache.maven.continuum.model.project.BuildResult"
+         maxElementsInMemory="10000"
+         maxElementsOnDisk="0"
+         eternal="false"
+         overflowToDisk="false"
+         timeToIdleSeconds="300"
+         timeToLiveSeconds="600"
+         memoryStoreEvictionPolicy="LFU"/>
+
+
+  <cache name="org.apache.continuum.model.release.ContinuumReleaseResult"
+         maxElementsInMemory="10000"
+         maxElementsOnDisk="0"
+         eternal="false"
+         overflowToDisk="false"
+         timeToIdleSeconds="300"
+         timeToLiveSeconds="600"
+         memoryStoreEvictionPolicy="LFU"/>
+
+</ehcache>
diff --git a/continuum-webapp/src/main/resources/freemarker.properties b/continuum-webapp/src/main/resources/freemarker.properties
index e2c1805..aca6171 100644
--- a/continuum-webapp/src/main/resources/freemarker.properties
+++ b/continuum-webapp/src/main/resources/freemarker.properties
@@ -16,5 +16,5 @@
 # specific language governing permissions and limitations
 # under the License.
 #
-# 1 hour
+
 template_update_delay=3600000
\ No newline at end of file
diff --git a/continuum-webapp/src/main/resources/localization/Continuum.properties b/continuum-webapp/src/main/resources/localization/Continuum.properties
index 064dcd1..e6449d7 100644
--- a/continuum-webapp/src/main/resources/localization/Continuum.properties
+++ b/continuum-webapp/src/main/resources/localization/Continuum.properties
@@ -47,6 +47,12 @@
 sort.descending = Sort Descending
 sort.ascending = Sort Ascending
 purge = Purge
+rollback=Rollback changes
+done=Done
+in.progress=In progress
+error=Error
+queued=Queued
+refresh=Refresh
 
 # ----------------------------------------------------------------------
 # Page: Top
@@ -60,11 +66,12 @@
 # ----------------------------------------------------------------------
 # Page: Menu
 # ----------------------------------------------------------------------
+menu.continuum = Continuum
 menu.continuum.about = About
 menu.continuum.showProjects = Show Projects
-menu.continuum.showProjectGroups = Show Project Groups
+menu.continuum.showProjectGroups = Show Project Groups 
 menu.addProject = Add Project
-menu.add.m2Project = Maven 2.0.x Project
+menu.add.m2Project = Maven Project
 menu.add.m1Project = Maven 1.x Project
 menu.add.antProject = Ant Project
 menu.add.shellProject = Shell Project
@@ -77,13 +84,19 @@
 menu.administration.users = Users
 menu.administration.userGroups = User Groups
 menu.administration.roles = Roles
-menu.administration.buildDefinitionTemplates = Build Definitions Templates
+menu.administration.buildDefinitionTemplates = Build Definition Templates
 menu.account.options = My account
 user.edit.account = Edit user info
 menu.administration.queues = Queues
 menu.administration.repositories = Local Repositories
 menu.administration.purge = Purge Configurations
-menu.administration.buildAgents = Build Agents
+menu.distributedBuilds = Distributed Builds
+menu.distributedBuilds.buildAgents = Build Agents
+menu.distributedBuilds.releases = Releases
+menu.parallelBuilds = Parallel Builds
+menu.parallelBuilds.build.queue= Build Queue
+menu.reports = Reports
+menu.reports.projectBuilds = Project Builds
 
 # ----------------------------------------------------------------------
 # Page: error
@@ -148,14 +161,13 @@
 groups.page.list.empty = Project Groups list is empty.
 groups.section.title = Project Group:
 groups.manage.label = Manage Group
-groups.confirmation.message = Are you sure you want to delete the project group "{0}"?
 groups.table.repositoryName = Local Repository
 
 # ----------------------------------------------------------------------
 # Page: Project Group
 # ----------------------------------------------------------------------
 projectGroup.page.title = Continuum - Project Group
-projectGroup.information.title = Project Group Information
+projectGroup.information.title = Project Group Information "{0}"
 projectGroup.name.label = Project Group Name
 projectGroup.groupId.label = Project Group Id
 projectGroup.description.label = Description
@@ -187,6 +199,9 @@
 projectGroup.scmRoot.title = Project Group Scm Root
 projectGroup.scmRoot.label = Scm Root URL
 projectGroup.cancelGroupBuild = Cancel Group Build
+projectGroup.invalid.id = Invalid Project Group Id: {0}
+projectGroup.build.error.noBuildAgent = Unable to build projects because no build agent is configured
+projectGroup.build.error.noBuildAgentInGroup = Unable to build projects because no build agent is configured in the build agent group
 
 # ----------------------------------------------------------------------
 # Page: Project Group - Members
@@ -204,12 +219,15 @@
 # ----------------------------------------------------------------------
 projectGroup.add.page.title = Continuum - Add Project Group
 projectGroup.add.section.title = Add Project Group
-projectGroup.error.name.required = Project Group Name required.
+projectGroup.error.name.required = Project Group Name is required.
 projectGroup.error.name.cannot.be.spaces = Project Group Name cannot contain spaces only.
 projectGroup.error.name.already.exists = Project Group Name already exists.
-projectGroup.error.groupId.required = Project Group ID required.
+projectGroup.error.name.invalid = Name contains invalid characters.
+projectGroup.error.groupId.required = Project Group ID is required.
 projectGroup.error.groupId.cannot.be.spaces = Project Group ID cannot contain spaces only.
 projectGroup.error.groupId.already.exists = Project Group ID already exists.
+projectGroup.error.groupId.invalid = Id contains invalid characters.
+projectGroup.error.description.invalid = Description contains invalid characters.
 
 # ----------------------------------------------------------------------
 # Page: Edit Project Group
@@ -222,6 +240,18 @@
 project.in.checkout.queue.error = Cannot edit this project group. Projects that are members of this project group are still being checked out from scm.
 
 # ----------------------------------------------------------------------
+# Page: Confirm Group Removal
+# ----------------------------------------------------------------------
+confirmGroupRemoval.page.title=Continuum - Project Group Removal
+confirmGroupRemoval.section.title=Project Group Removal
+confirmGroupRemoval.confirmation.message=Are you sure you want to delete the project group "{0}"?
+
+# ----------------------------------------------------------------------
+# Page: Delete Project Group
+# ----------------------------------------------------------------------
+projectGroup.delete.error = Unable to remove project group
+
+# ----------------------------------------------------------------------
 # Page: Configuration
 # ----------------------------------------------------------------------
 configuration.page.title = Continuum - Configuration
@@ -232,6 +262,8 @@
 configuration.buildOutputDirectory.label = Build Output Directory
 configuration.deploymentRepositoryDirectory.label = Deployment Repository Directory
 configuration.baseUrl.label = Base URL
+configuration.allowed.build.parallel = Number of Allowed Builds in Parallel
+configuration.disable.parallel.builds = Disable Parallel Builds
 configuration.submit.edit = Edit
 configuration.guest.message = Enable/Disable login as guest
 configuration.workingDirectory.message = Enter the working directory of the Continuum web application
@@ -241,10 +273,14 @@
 configuration.companyName.message = Enter the company name
 configuration.companyLogo.message = Enter the company logo
 configuration.companyUrl.message = Enter the URL of the official company website
+configuration.allowed.build.paralle.message = Enter the number of Allowed Builds in Parallel
 configuration.releaseOutputDirectory.label = Release Output Directory
 configuration.releaseOutputDirectory.message = Enter the release output directory of the Continuum web application
 configuration.releaseOutputDirectory.required = You must define a release output directory
+configuration.numberOfBuildsInParallel.invalid = Number of Allowed Builds in Parallel must be greater than zero
 configuration.distributedBuildEnabled.label = Enable Distributed Builds
+configuration.sharedSecretPassword.label = Shared Secret Password
+configuration.sharedSecretPassword.message = Enter the shared secret password between master and agents when distributed build is enabled
 
 # ----------------------------------------------------------------------
 # Page: Add Project
@@ -272,6 +308,7 @@
 add.project.project.building.error = Unknown error trying to build POM.
 add.project.unknown.error = The specified resource cannot be accessed. Please try again later or contact your administrator.
 add.project.nogroup.error = No project group specified.
+add.project.duplicate.error = Trying to add duplicate projects in the same project group.
 
 # ----------------------------------------------------------------------
 # Page: AddMavenOneProject
@@ -293,28 +330,30 @@
 # ----------------------------------------------------------------------
 # Page: AddMavenTwoProject
 # ----------------------------------------------------------------------
-add.m2.project.page.title = Continuum - Add Maven 2 Project
-add.m2.project.section.title = Add Maven 2.0+ Project
+add.m2.project.page.title = Continuum - Add Maven Project
+add.m2.project.section.title = Add Maven Project
 add.m2.project.m2PomUrl.label = POM Url
 add.m2.project.m2PomUrl.username.label = Username
 add.m2.project.m2PomUrl.password.label = Password
-add.m2.project.m2PomUrl.message =  Enter the URL to the Maven 2 POM. Provide the username and password if it is a secured resource.
+add.m2.project.m2PomUrl.message =  Enter the URL to the Maven POM. Provide the username and password if it is a secured resource.
 add.m2.project.m2PomUrl.error = You must enter a valid URL
 add.m2.project.m2PomFile.label = Upload POM
-add.m2.project.m2PomFile.message =  Enter the local filename of the Maven 2 POM to upload (works only for a single project without modules).
+add.m2.project.m2PomFile.message =  Enter the local filename of the Maven POM to upload (works only for a single project without modules).
 add.m2.project.m2PomFile.error = You must enter a valid URL
 add.m2.project.projectGroup = Project Group
 # TODO: remove this part once uploading of an m2 project with modules is supported ( CONTINUUM-1098 )
-add.m2.project.upload.modules.error = Cannot upload a Maven 2 project with modules.
-add.m2.project.nonRecursiveProject = For multi modules project, load only root as recursive build
+add.m2.project.upload.modules.error = Cannot upload a Maven project with modules.
+add.m2.project.nonRecursiveProject = For multi-module project, load only root as recursive build
 add.m2.project.buildDefinitionTemplate = Build Definition Template
 add.m2.project.defaultBuildDefinition = Default
+add.m2.project.checkoutInSingleDirectory = Checkout multi-module project in single directory
+add.m2.project.checkoutInSeparateDirectories = Checkout multi-module project in separate directories 
 
 # ----------------------------------------------------------------------
 # Page: AddProject (ant or shell)
 # ----------------------------------------------------------------------
 add.shell.project.page.title = Continuum - Add Shell Project
-add.shell.project.section.title = Continuum - Add Shell Project
+add.shell.project.section.title = Add Shell Project
 add.ant.project.page.title = Continuum - Add Ant Project
 add.ant.project.section.title = Add Ant Project
 
@@ -331,6 +370,9 @@
 projectScmUrl.error = You must provide an scm url
 projectScmUrl.message = Enter the <a href="http://maven.apache.org/scm/scm-url-format.html">Maven SCM URL</a>
 
+projectDescription.label = Description
+projectDescription.message = Enter a description of the project
+
 projectScmUsername.label = Scm Username
 projectScmUsername.message = Enter the scm username
 
@@ -354,13 +396,15 @@
 deleteProject.page.title = Continuum - Delete Continuum Project
 deleteProject.section.title = Delete Continuum Project
 deleteProject.confirmation.message = Are you sure you want to delete the project "{0}"?
+deleteProject.error = Unable to delete project with id {0}
 
 # ----------------------------------------------------------------------
 # Page: ProjectView
 # ----------------------------------------------------------------------
 projectView.page.title = Continuum - Continuum Project
-projectView.section.title = Continuum Project
+projectView.section.title = Continuum Project "{0}"
 projectView.project.name = Project Name
+projectView.project.description = Description
 projectView.project.version = Version
 projectView.project.scmUrl = SCM Url
 projectView.project.scmTag = SCM Branch/Tag
@@ -432,12 +476,17 @@
 buildDefinition.alwaysBuild.label = Always Build
 buildDefinition.noname.save.error.message = There was an error saving the schedule, no schedule name was supplied.
 buildDefinition.duplicatename.save.error.message = There was an error saving the schedule, a schedule with the same name already exists.
+buildDefinition.updatePolicy.label = Update Policy
+buildDefinition.updatePolicy.always = Always
+buildDefinition.updatePolicy.never = Never
+buildDefinition.updatePolicy.newPom = Only for new Pom
 
 # ----------------------------------------------------------------------
 # Page: BuildSummary
 # ----------------------------------------------------------------------
 buildDefinitionSummary.projectGroup.section.title = Project Group Build Definitions of {0} group
-
+buildDefinitionSummary.project.section.title=Project Build Definitions
+buildDefinitionSummary.project=Project
 
 # ----------------------------------------------------------------------
 # Page: DeleteBuildDefinition
@@ -463,6 +512,7 @@
 notifier.type.label = Type
 notifier.mail.recipient.address.label = Mail Recipient Address
 notifier.mail.recipient.committers.label = Send a mail to latest committers
+notifier.mail.recipient.developers.label = Send a mail to project developers
 notifier.irc.host.label = IRC Host
 notifier.irc.port.label = IRC port
 notifier.irc.channel.label = IRC channel
@@ -489,7 +539,7 @@
 notifier.event.sendOnFailure = Send on Failure
 notifier.event.sendOnError = Send on Error
 notifier.event.sendOnWarning = Send on Warning
-notifier.event.sendOnScmFailure = Send On SCM Failure
+notifier.event.sendOnScmFailure = Send on SCM Failure
 
 # ----------------------------------------------------------------------
 # Page: BuildResults
@@ -504,6 +554,7 @@
 buildResults.state = State
 buildResults.result = Result
 buildResults.buildDefinition.description = Build Definition Description
+buildResults.delete.error = Unable to delete Build Results
 
 # ----------------------------------------------------------------------
 # Page: BuildResults
@@ -517,6 +568,7 @@
 buildResult.trigger = Build Trigger
 buildResult.state = State
 buildResult.buildNumber = Build#
+buildResult.username = Triggered by
 buildResult.buildError = Build Error
 buildResult.buildOutput = Output
 buildResult.noOutput = No output.
@@ -553,6 +605,7 @@
 buildResult.buildDefinition.schedule = Schedule
 buildResult.buildDefinition.profileName = Build Environment
 buildResult.buildDefinition.description = Description
+buildResult.buildUrl = Build Agent Url
 
 # From ContinuumProjectState
 buildResult.trigger.0 = Scheduled
@@ -585,7 +638,6 @@
 schedules.table.cronExpression = Cron Expression
 schedules.table.active = Active
 schedules.table.maxJobExecutionTime = Max Job Time
-schedules.confirmation.message = Are you sure you want to delete the schedule "{0}"?
 
 # ----------------------------------------------------------------------
 # Page: Add/EditSchedule
@@ -600,7 +652,7 @@
 schedule.description.label = Description
 schedule.description.message = Enter a description of the schedule
 schedule.cronExpression.label = Cron Expression
-schedule.cronExpression.message = Enter the cron expression. Format is described there : <a href="http://www.opensymphony.com/quartz/api/org/quartz/CronTrigger.html" target="_blank">Syntax<a>
+schedule.cronExpression.message = Enter the cron expression. Format is described there : <a href="http://www.quartz-scheduler.org/docs/tutorials/crontrigger.html" target="_blank">Syntax<a>
 schedule.maxJobExecutionTime.label = Maximum job execution time (seconds)
 schedule.maxJobExecutionTime.message = Enter the maximum number of seconds a job may execute in this schedule before it''s terminated.
 schedule.quietPeriod.label = Quiet Period (seconds)
@@ -615,6 +667,20 @@
 schedule.dayOfWeek.label = Day of Week
 schedule.year.label = Year [optional]
 schedule.remove.error = The schedule can't be removed, it is probably used by a build definition.
+schedule.buildqueues.label = Add Build Queue
+schedule.buildqueues.define = Configure the used build queues
+schedule.available.buildqueues = --- Available Build Queues ---
+schedule.available.buildqueues.used = --- Used Build Queues ---
+schedule.buildqueues.add.error = Error attaching the build queue(s) to schedule.
+schedule.name.already.exists = A Schedule with the same name already exists
+schedule.buildqueues.empty.error = Used Build Queues cannot be empty
+
+# ----------------------------------------------------------------------
+# Page: Delete Schedule
+# ----------------------------------------------------------------------
+deleteSchedule.page.title = Continuum - Delete Schedule
+deleteSchedule.section.title = Delete Schedule
+deleteSchedule.confirmation.message = Are you sure you want to delete the schedule "{0}"?
 
 # ----------------------------------------------------------------------
 # Page: SurefireReport
@@ -642,16 +708,20 @@
 releaseProject.prepareReleaseOption=Prepare project for release
 releaseProject.performReleaseOption=Perform project release
 releaseProject.provideReleaseParameters=Provide Release Parameters
+releaseProject.rollbackWarning=This will revert all changes made by the previous release?
+releaseProject.rollbackWarning.section.title=Rollback release
 releasePrepare.section.title=Prepare Project for Release
-releasePrepare.parameters=Release Prepare Parameters
 releasePrepare.releaseVersion=Release Version*
 releasePrepare.nextDevelopmentVersion=Next Development Version*
+releasePrepare.parameters=Release Prepare Parameters
 releasePerform.section.title=Perform Project Release
 releasePerform.parameters=Release Perform Parameters
 releaseInProgress.section.title=Executing Release Goal
 releaseInProgress.status=Status
 releaseInProgress.phase=Release Phase
 releaseInProgress.viewOutput=View Output
+releaseInProgress.currently.initializing=The release goal is currently initializing...
+releaseInProgress.please.wait=Please wait while the server prepares your project for release.
 releaseViewResult.section.title=Project Release Summary
 releaseViewResult.summary=Release Project Details
 releaseViewResult.startTime=Start Time
@@ -663,21 +733,30 @@
 releaseViewResult.noOutput=No Output
 releaseViewResult.projectName=Project Name
 releaseViewResult.releaseGoal=Release Goal
+releaseViewResult.username=Triggered by
 releasePrepare.scmUsername.label=SCM Username
 releasePrepare.scmPassword.label=SCM Password
 releasePrepare.scmTag.label=SCM Tag
 releasePrepare.scmTagBase.label=SCM Tag Base
+releasePrepare.scmCommentPrefix.label=SCM Comment Prefix
 releasePrepare.prepareGoals.label=Preparation Goals
+releasePrepare.arguments.label=Arguments
 releasePrepare.buildEnvironment.label=Build Environment
 releasePrepare.useEditMode.label=Use edit mode
+releasePrepare.addSchema.label=Add a schema to the POM if it was previously missing on release
+releasePrepare.autoVersionSubmodules.label=autoVersionSubmodules (defined in the POM)
 releasePerformFromScm.scmUrl.label=SCM Connection URL
 releasePerformFromScm.scmUsername.label=SCM Username
 releasePerformFromScm.scmPassword.label=SCM Password
 releasePerformFromScm.scmTag.label=SCM Tag
 releasePerformFromScm.scmTagBase.label=SCM Tag Base
-releasePerformFromScm.goals.label=Maven Arguments
+releasePerformFromScm.goals.label=Perform Goals
 releasePerformFromScm.useReleaseProfile.label=Use Release Profile
 releasePerformFromScm.buildEnvironment.label=Build Environment
+releasePerformFromScm.page.title=Continuum - Perform Project Release
+releasePerformFromScm.section.title=Perform Project Release
+releasePerformFromScm.parameters.section.title=Release Perform Parameters
+releaseRollback.error=Failed to rollback release: {0}
 
 # ----------------------------------------------------------------------
 # Page: User
@@ -705,9 +784,10 @@
 # ----------------------------------------------------------------------
 # Page: Profiles List
 # ----------------------------------------------------------------------
-profilesList.page.title= Build Environments
+profilesList.page.title= Continuum - Build Environments
 profilesList.section.title= Build Environments
 profilesList.installations.label = Installations
+profilesList.buildAgentGroup.label = Build Agent Group
 
 # ----------------------------------------------------------------------
 # Page: Profile Edit
@@ -725,29 +805,31 @@
 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
 # ----------------------------------------------------------------------
-installationsList.page.title = Installations
+installationsList.page.title = Continuum - Installations
 installationsList.section.title = Installations
 
 # ----------------------------------------------------------------------
 # Page: Installation Edit
 # ----------------------------------------------------------------------
 installation.page.title = Continuum - Installation
-installation.section.title = Continuum - Installation
+installation.section.title = Installation
 installation.name.label = Name
 installation.type.label = Type
 installation.value.label = Value/Path
 installation.varName.label = Environment Variable Name
 installation.jdk.type.label = JDK
-installation.maven2.type.label = Maven 2
+installation.maven2.type.label = Maven
 installation.maven1.type.label = Maven 1
 installation.envvar.type.label = Environment Variable
 installation.ant.type.label = ANT
 installation.automaticProfile.label=Create a Build Environment with the Installation name
 installation.name.duplicate = Installation name already exists.
+installation.varName.required = You must define an environment variable
 
 # ----------------------------------------------------------------------
 # Page: Installations Type Choice
@@ -756,7 +838,14 @@
 installationTypeChoice.section.title = Installation Type Choice
 installationTypeChoice.action.label = Installation Type
 installationTypeChoice.tool.label = Tool
-installationTypeChoice.envar.label = Environment Variable 
+installationTypeChoice.envar.label = Environment Variable
+
+# ----------------------------------------------------------------------
+# Page: Delete Installation
+# ----------------------------------------------------------------------
+deleteInstallation.page.title = Continuum - Delete Installation
+deleteInstallation.section.title = Delete Installation
+deleteInstallation.confirmation.message = Are you sure you want to delete "{0}" installation ?
 
 # ----------------------------------------------------------------------
 # Page: Build Definitions Templates Summary
@@ -796,22 +885,51 @@
 buildDefinitionTemplate.builddefinitions.define = Configure the used Build Definitions
 
 # ----------------------------------------------------------------------
-# Page: Build Queue
+# Page: Delete Build Definition Template
+# ----------------------------------------------------------------------
+deletebuildDefinition.template.page.title = Continuum - Delete Build Definition Template
+deletebuildDefinition.template.section.title = Delete Build Definition Template
+deletebuildDefinition.template.confirmation.message = Are you sure you want to delete build definition template "{0}"?
+
+# ----------------------------------------------------------------------
+# Page: Build Definition Error
+# ----------------------------------------------------------------------
+buildDefinitionError.page.title=Delete Build Definition Error
+buildDefinitionError.section.title=Delete Build Definition Error
+
+# ----------------------------------------------------------------------
+# Page: Queues
 # ----------------------------------------------------------------------
 buildQueue.page.title = Continuum - Build Queue
-buildQueue.section.title = Continuum - Build Queue
+buildQueue.section.title = Build Queue
 buildQueue.empty = Build Queue is empty
 buildQueue.currentTask.section.title = Current Build
+buildQueue.currentTask.buildQueue = Build Queue
 buildQueue.currentTask.projectName = Project Name
 buildQueue.currentTask.buildDefinition = Build Definition
 buildQueue.no.currentTaks = Nothing is building
 buildQueue.removeEntries = Cancel Entries
 checkoutQueue.currentTask.section.title = Current Checkout
+checkoutQueue.currentTask.buildQueue = Build Queue
 checkoutQueue.currentTask.projectName = Project Name
 checkoutQueue.no.currentTaks = No current checkout
 checkoutQueue.section.title = Checkout Queue
 checkoutQueue.empty = Checkout Queue is empty
 checkoutQueue.removeEntries = Cancel Entries
+prepareBuildQueue.currentTask.section.title = Current Prepare Build
+prepareBuildQueue.section.title = Prepare Build Queue
+prepareBuildQueue.table.projectGroupName = Project Group
+prepareBuildQueue.table.scmRootAddress = SCM Root URL
+prepareBuildQueue.empty = Prepare Build Queue is empty
+prepareBuildQueue.no.currentTasks = No current prepare build
+prepareBuildQueue.removeEntries = Cancel Entries
+prepareBuildQueue.currentTask.buildQueue = Build Queue
+
+# ----------------------------------------------------------------------
+# Page: Build Queue
+# ----------------------------------------------------------------------
+buildQueue.cannot.delete = Cannot delete build queue, task is currently executing.
+buildQueue.delete.error = Unable to delete build queue from the database.
 
 # ----------------------------------------------------------------------
 # Page: Confirm Delete BuildResult(s)
@@ -819,7 +937,8 @@
 buildResult.delete.confirmation.page.title = Continuum - Delete Build Results
 buildResult.delete.confirmation.section.title = Delete Build Results
 buildResult.delete.confirmation.message = Are you sure you want to delete {0} build results ? 
-buildResult.cannot.delete = Cannot delete a build result which is currently building.
+buildResult.cannot.delete = Cannot delete the build result of a currently building project.
+buildResult.delete.error = Unable to delete Build Result with id {0}
 
 # ----------------------------------------------------------------------
 # Legend
@@ -839,7 +958,6 @@
 legend.buildInFailure=Build in Failure
 legend.buildInError=Build in Error
 
-
 # ----------------------------------------------------------------------
 # Page: Wait
 # ----------------------------------------------------------------------
@@ -883,7 +1001,7 @@
 repository.error.save.in.use = Unable to edit local repository because it is currently in use 
 repository.error.remove.in.use = Unable to remove local repository because it is currently in use
 repository.error.purge.in.use = Unable to purge local repository because it is currently in use
-repository.error.remove.default = Cannot remove default local repository.
+repository.error.remove.default = Cannot remove default local repository
 
 #-----------------------------------------------------------------------
 # Page: Delete Local Repository
@@ -907,6 +1025,7 @@
 purgeConfigs.table.directoryType = Directory Type
 purgeConfigs.table.default = Default
 purgeConfigs.table.enabled = Enabled
+purgeConfigs.table.buildAgent = Build Agent
 purgeConfigs.table.deleteReleasedSnapshots = Delete Released Snapshots
 
 #-----------------------------------------------------------------------
@@ -923,8 +1042,16 @@
 purgeConfig.defaultPurge.label = Is it Default?
 purgeConfig.schedule.label = Schedule
 purgeConfig.description.label = Description
-purgeConfig.enabled.label = Enabled
+purgeConfig.enabled.label = Enabled Purge Configuration
 purgeConfig.no.repositories = No repositories to purge
+purgeConfig.buildAgent.label = Build Agent
+
+#-----------------------------------------------------------------------
+# Page: Delete Purge Configuration
+#-----------------------------------------------------------------------
+deletePurgeConfiguration.page.title = Continuum - Delete Purge Configuration
+deletePurgeConfiguration.section.title = Delete Purge Configuration
+deletePurgeConfiguration.confirmation.message = Are you sure you want to delete Purge Configuration "{0}" ?
 
 # ----------------------------------------------------------------------
 # Page: Release Results
@@ -977,7 +1104,7 @@
 appearance.noCompanyPom = You have not yet specified a company POM.
 appearance.selectCompanyPom = Select a Company POM
 appearance.detailsIntroduction = Your selected company POM is below.
-appearance.maybeChange = If you would like to change the organization name, url or logo, you can
+appearance.maybeChange = If you would like to change the organization name, URL or logo, you can
 appearance.editThePomLink = edit the POM
 appearance.companyPom.groupId = Group ID
 appearance.companyPom.artifactId = Artifact ID
@@ -992,6 +1119,7 @@
 appearance.htmlContent.label = HTML Content
 appearance.enterCompanyPom = Enter the details of the company super POM below. If it exists, the organization name, URL and logo will be read from it.
 appearance.footerContent = Footer Content
+appearance.footerContent.success = Successfully saved footer content.
 
 # ----------------------------------------------------------------------
 # Page: Edit Company POM
@@ -1002,6 +1130,26 @@
 companyPom.organization = Organization
 
 # ----------------------------------------------------------------------
+# Page: Parallel Build Queue List
+# ----------------------------------------------------------------------
+parallel.build.queues.page.title = Continumm - Parallel Build Queue
+parallel.build.queues.section.title = Parallel Build Queue
+
+# ----------------------------------------------------------------------
+# Page: Parallel Build Edit
+# ----------------------------------------------------------------------
+parallel.build.queue.page.title = Continuum - Add/Edit Parallel Build Queue
+parallel.build.queue.section.title = Add/Edit Parallel Build Queue
+parallel.build.queue.name = Name
+
+# ----------------------------------------------------------------------
+# Page: Delete Parallel Build Queue 
+# ----------------------------------------------------------------------
+deleteBuildQueue.page.title = Continuum - Delete Parallel Build Queue 
+deleteBuildQueue.section.title = Delete Parallel Build Queue
+deleteBuildQueue.confirmation.message = Are you sure you want to delete the build queue "{0}"?
+
+# ----------------------------------------------------------------------
 # Page: BuildAgents
 # ----------------------------------------------------------------------
 buildAgents.page.title = Continuum - Build Agents
@@ -1009,6 +1157,11 @@
 buildAgents.table.url = Build Agent URL
 buildAgents.table.description = Description
 buildAgents.table.enabled = Enabled
+buildAgents.empty = No Build Agents
+
+buildAgentGroups.section.title = Build Agent Groups
+buildAgentGroups.table.name = Name
+buildAgentGroups.table.agents = Build Agents
 
 # ----------------------------------------------------------------------
 # Page: Add/Edit BuildAgent
@@ -1020,6 +1173,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
@@ -1027,6 +1181,10 @@
 viewBuildAgent.page.title = Continuum - View Build Agent
 viewBuildAgent.section.title = Build Agent
 viewBuildAgent.installations.title = Available Installations
+viewBuildAgent.installations.name=Name
+viewBuildAgent.installations.type=Type
+viewBuildAgent.installations.varName=Env Var Name
+viewBuildAgent.installations.varValue=Value/Path
 
 # ----------------------------------------------------------------------
 # Page: Delete BuildAgent
@@ -1039,10 +1197,105 @@
 # Page: View Distributed Build
 # ----------------------------------------------------------------------
 distributedBuilds.page.title = Continuum - View Distributed Builds
-distributedBuilds.section.title = Distributed Builds
+distributedBuilds.currentPrepareBuild.section.title = Current Prepare Build
+distributedBuilds.currentBuild.section.title = Current Build
+distributedBuilds.prepareBuildQueue.section.title = Prepare Build Queue
 distributedBuilds.buildQueue.section.title = Build Queue
+distributedPrepareBuild.table.projectGroupName = Project Group Name
+distributedPrepareBuild.table.scmRootAddress = SCM Root URL
+distributedPrepareBuild.table.buildAgentUrl = Build Agent URL
+distributedPrepareBuilds.empty = Prepare Build Queue is empty
+distributedPrepareBuilds.no.currentTasks = No current prepare build
+distributedPrepareBuilds.removeEntries = Cancel Entries
+distributedBuild.table.projectName = Project Name
+distributedBuild.table.buildDefinitionLabel = Build Definition Label
 distributedBuild.table.projectGroupName = Project Group Name
-distributedBuild.table.scmRootAddress = Scm Root Address
-distributedBuild.table.agentUrl = Build Agent URL
-distributedBuilds.empty = No Distributed Builds
-distributedBuilds.removeEntries = Cancel Entries
\ No newline at end of file
+distributedBuild.table.buildAgentUrl = Build Agent URL
+distributedBuilds.empty = Build Queue is empty
+distributedBuilds.no.currentTasks = No current build
+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 used by the build environment '{0}'.
+
+# ----------------------------------------------------------------------
+# Page: View Distributed Releases
+# ----------------------------------------------------------------------
+releases.page.title = Continuum - View Releases
+releases.section.title = View Releases
+releaseSummary.table.releaseId = Release ID
+releaseSummary.table.releaseGoal = Release Goal
+releaseSummary.table.buildAgentUrl = Build Agent URL
+
+# ----------------------------------------------------------------------
+# Page: Continuum Distributed Build Release Support
+# ----------------------------------------------------------------------
+distributedBuild.releasePrepare.input.error = Unable to get release plugin parameters and process project because either build agent {0} was removed or disabled, or no build was performed on a build agent yet. 
+distributedBuild.releasePrepare.error = Unable to prepare release.
+distributedBuild.releasePrepare.release.error = Unable to prepare release because build agent {0} was either removed or disabled
+distributedBuild.releaseInProgress.error = Unable to view release in progress because build agent {0} was either removed or disabled
+distributedBuild.releaseViewResult.error = Unable to view release result because build agent {0} was either removed or disabled
+distributedBuild.releaseCleanup.error = Unable to cleanup release because build agent {0} was either removed or disabled
+distributedBuild.releasePerform.input.error = Unable to get release plugin parameters because build agent {0} was either removed or disabled
+distributedBuild.releasePerform.release.error = Unable to perform release because build agent {0} was either removed or disabled
+
+# ----------------------------------------------------------------------
+# Page: Authorization Error
+# ----------------------------------------------------------------------
+authorizationError.page.title=Continuum - Authorization Error
+authorizationError.section.title=Authorization Error
+authorizationError.not.authorized=You are not authorized to access this page. Please contact your administrator to be granted the appropriate permissions.
+
+# ----------------------------------------------------------------------
+# Page: Error Occured
+# ----------------------------------------------------------------------
+errorOccured.page.title=Continuum - Error Occured
+errorOccured.section.title=Error Occured
+
+# ----------------------------------------------------------------------
+# Page: Release Error
+# ----------------------------------------------------------------------
+releaseError.page.title=Continuum - Release Error
+releaseError.section.title=Release Error
+releasePrepare.input.error = Unable to get release plugin parameters and process project - {0}
+
+# ----------------------------------------------------------------------
+# Page: Project Builds Report
+# ----------------------------------------------------------------------
+projectBuilds.report.title=Continuum - Project Builds Report
+projectBuilds.report.section.title=Project Builds Report
+projectBuilds.report.button.reset=Reset
+projectBuilds.report.project.group=Project Group
+projectBuilds.report.startDate=Start Date
+projectBuilds.report.endDate=End Date
+projectBuilds.report.triggeredBy=Triggered By
+projectBuilds.report.buildStatus=Build Status
+projectBuilds.report.rowCount=Row Count
+projectBuilds.report.view=View Report
+projectBuilds.report.prev=Prev
+projectBuilds.report.next=Next
+projectBuilds.report.projectGroup = Project Group
+projectBuilds.report.project=Project Name
+projectBuilds.report.buildDate=Build Date
+projectBuilds.report.noResult=No Results Found
+
diff --git a/continuum-webapp/src/main/resources/localization/Continuum_de.properties b/continuum-webapp/src/main/resources/localization/Continuum_de.properties
index 3d6b2a8..5b80e6b 100644
--- a/continuum-webapp/src/main/resources/localization/Continuum_de.properties
+++ b/continuum-webapp/src/main/resources/localization/Continuum_de.properties
@@ -61,10 +61,10 @@
 # Page: Menu
 # ----------------------------------------------------------------------
 menu.continuum.about = \u00DCber
-menu.continuum.showProjects = Projekte anzeigen
-menu.continuum.showProjectGroups = Projektgruppen anzeigen
+menu.continuum.showProjects = Projekte
+menu.continuum.showProjectGroups = Projektgruppen
 menu.addProject = Projekt hinzuf\u00FCgen
-menu.add.m2Project = Maven 2.0.x Projekt
+menu.add.m2Project = Maven Projekt
 menu.add.m1Project = Maven 1.x Projekt
 menu.add.antProject = Ant Projekt
 menu.add.shellProject = Shell Projekt
@@ -77,8 +77,8 @@
 menu.administration.users = Benutzer
 menu.administration.userGroups = Benutzergruppen
 menu.administration.roles = Rollen
-menu.administration.buildDefinitionTemplates = Vorgangsschablonen
-menu.account.options = Mein Profil
+menu.administration.buildDefinitionTemplates = Vorgangsvorlagen
+menu.account.options = Meine Daten
 user.edit.account = Benutzerinformationen bearbeiten
 menu.administration.queues = Warteschlangen
 menu.administration.repositories = Lokale Repositories
@@ -95,7 +95,7 @@
 error.403.section.title = Zugriff verweigert
 error.403.message = Zugriff auf den angeforderten URL verweigert.
 error.404.title = Fehler 404
-error.404.section.title = Resource nicht gefunden
+error.404.section.title = Ressource nicht gefunden
 error.404.message = Der angeforderte URL konnte nicht gefunden werden.
 error.500.title = Fehler 500
 error.500.section.title = Interner Fehler
@@ -105,11 +105,11 @@
 # Page: About
 # ----------------------------------------------------------------------
 about.page.title = Continuum - Vorstellung
-about.section.title = \u00DCber Continuum
+about.section.title = Continuum
 about.version.label = Version
 about.version.number = ${project.version}
 about.buildnumber.label = Build
-about.buildnumber = ${buildNumber}
+about.buildnumber=${buildNumber}
 
 # ----------------------------------------------------------------------
 # Page: Login
@@ -124,8 +124,8 @@
 # ----------------------------------------------------------------------
 # Page: Summary
 # ----------------------------------------------------------------------
-summary.page.title = Continuum - Zusammenfassung
-summary.section.title = Continuum Projekte
+summary.page.title = Continuum - \u00DCbersicht
+summary.section.title = Projekte
 summary.projectTable.name = Projektname
 summary.projectTable.version = Version
 summary.projectTable.build = Vorgang
@@ -138,29 +138,28 @@
 # ----------------------------------------------------------------------
 # Page: Group Summary
 # ----------------------------------------------------------------------
-groups.page.title = Continuum - Projektgruppen-Zusammenfassung
+groups.page.title = Continuum - Projektgruppen
 groups.page.section.title = Projektgruppen
 groups.table.name = Name
 groups.table.groupId = Bezeichner
 groups.table.totalProjects = Summe
 groups.table.summary = Zusammenfassung
-groups.page.list.empty = Die Liste der Projektgruppen ist leer.
+groups.page.list.empty = Leere Projektgruppen-Liste.
 groups.section.title = Projektgruppe:
 groups.manage.label = Gruppe verwalten
-groups.confirmation.message = Soll die Projektgruppe "{0}" wirklich gel\u00F6scht werden ?
 groups.table.repositoryName = Lokales Repository
 
 # ----------------------------------------------------------------------
 # Page: Project Group
 # ----------------------------------------------------------------------
 projectGroup.page.title = Continuum - Projektgruppe
-projectGroup.information.title = Informationen zur Projektgruppe
+projectGroup.information.title = {0} Gruppeninformationen
 projectGroup.name.label = Name
 projectGroup.groupId.label = Bezeichner
 projectGroup.description.label = Beschreibung
 projectGroup.url.label = URL der Projektseite
 projectGroup.projects.title = Projekte
-projectGroup.tab.summary = Zusammenfassung
+projectGroup.tab.summary = Projektgruppe
 projectGroup.tab.members = Projekte
 projectGroup.tab.buildDefinitions = Vorgangsdefinitionen
 projectGroup.tab.notifiers = Berichterstatter
@@ -187,7 +186,7 @@
 # ----------------------------------------------------------------------
 # Page: Project Group - Members
 # ----------------------------------------------------------------------
-projectGroup.members.section.title = Projekte in Gruppe {0}
+projectGroup.members.section.title = {0} Projekte
 projectGroup.members.users.title = Benutzer
 projectGroup.members.users.search.label = Benutzersuche
 projectGroup.members.users.search.button = Suchen
@@ -202,10 +201,10 @@
 projectGroup.add.section.title=Gruppe hinzuf\u00FCgen
 projectGroup.error.name.required = Es mu\u00DF ein Projektgruppen-Name angegeben werden.
 projectGroup.error.name.cannot.be.spaces = Es mu\u00DF ein Projektgruppen-Name angegeben werden.
-projectGroup.error.name.already.exists = Eine Gruppe mit demselben Namen existiert bereits.
+projectGroup.error.name.already.exists = Eine Gruppe mit identischem Namen existiert bereits.
 projectGroup.error.groupId.required = Es mu\u00DF ein Projektgruppen-Bezeichner angegeben werden.
 projectGroup.error.groupId.cannot.be.spaces = Es mu\u00DF ein Projektgruppen-Bezeichner angegeben werden.
-projectGroup.error.groupId.already.exists = Eine Gruppe mit demselben Bezeichner existiert bereits.
+projectGroup.error.groupId.already.exists = Eine Gruppe mit identischem Bezeichner existiert bereits.
 
 # ----------------------------------------------------------------------
 # Page: Edit Project Group
@@ -248,7 +247,7 @@
 add.project.unknown.host.error = Zugriff auf den angegebenen Host nicht m\u00F6glich.
 add.project.connect.error = Es konnte keine Verbindung zum entfernten System hergestellt werden.
 add.project.malformed.url.error = Ung\u00FCltiger URL.
-add.project.xml.parse.error = XML des POM kann nicht verarbeitet werden.
+add.project.xml.parse.error = POM XML kann nicht verarbeitet werden.
 add.project.extend.error = Es kann kein POM mit einem ''extend'' Element verwendet werden.
 add.project.missing.pom.error = Die angegebene POM-Datei oder ein Modul daraus existiert nicht.
 add.project.missing.groupid.error = Kein ''groupId'' Element im POM.
@@ -261,11 +260,11 @@
 add.project.missing.notifier.type.error = Kein ''type'' Element unterhalb des ''notifier'' Elements im POM.
 add.project.missing.notifier.configuration.error = Kein ''configuration'' Element unterhalb des ''notifier'' Elements im POM.
 add.project.metadata.transfer.error = Die \u00DCbertragung der Metadaten ist fehlgeschlagen.
-add.project.validation.protocol.not_allowed = Bei der angegebenen Resource handelt es sich nicht um eine Datei bzw. die Verwendung des angegebenen Protokolls ist nicht gestattet.
-add.project.unauthorized.error = Sie haben nicht die erforderliche Berechtigung zum Zugriff auf die angegebene Resource. Bitte \u00FCberpr\u00FCfen Sie Benutzername und Passwort.
+add.project.validation.protocol.not_allowed = Bei der angegebenen Ressource handelt es sich nicht um eine Datei bzw. die Verwendung des angegebenen Protokolls ist nicht gestattet.
+add.project.unauthorized.error = Sie haben nicht die erforderliche Berechtigung zum Zugriff auf die angegebene Ressource. Bitte \u00FCberpr\u00FCfen Sie Benutzername und Passwort.
 add.project.artifact.not.found.error = Fehlendes Artefakt beim Versuch das POM zu verarbeiten. Bitte pr\u00FCfen Sie, ob das Eltern-POM zur Verf\u00FCgung steht, oder f\u00FCgen Sie zuerst das Eltern-POM zu Continuum hinzu.
 add.project.project.building.error = Unbekannter Fehler bei der Verarbeitung des POM.
-add.project.unknown.error = Zugriff auf die angegebene Resource nicht m\u00F6glich. Bitte versuchen Sie es sp\u00E4ter erneut, oder kontaktieren Sie Ihren Administrator.
+add.project.unknown.error = Zugriff auf die angegebene Ressource nicht m\u00F6glich. Bitte versuchen Sie es sp\u00E4ter erneut, oder kontaktieren Sie Ihren Administrator.
 add.project.nogroup.error = Es wurde keine Projektgruppe angegeben.
 
 # ----------------------------------------------------------------------
@@ -276,46 +275,46 @@
 add.m1.project.m1PomUrl.label = M1 POM URL
 add.m1.project.m1PomUrl.username.label = Benutzername
 add.m1.project.m1PomUrl.password.label = Passwort
-add.m1.project.m1PomUrl.message = Bitte geben Sie den URL des Maven 1 POM an. Falls es sich um eine gesch\u00FCtzte Resource handelt, geben Sie zus\u00E4tzlich den Benutzernamen und das Passwort an.
+add.m1.project.m1PomUrl.message = Bitte geben Sie den URL des Maven 1 POM an. Falls es sich um eine gesch\u00FCtzte Ressource handelt, geben Sie zus\u00E4tzlich den Benutzernamen und das Passwort an.
 add.m1.project.m1PomUrl.error = Es mu\u00DF ein g\u00FCltiger URL angegeben werden.
 add.m1.project.m1PomFile.label = POM-Datei
 add.m1.project.m1PomFile.message =  Bitte geben Sie den lokalen Dateinamen des zu \u00FCbertragenden Maven 1 POM an.
 add.m1.project.m1PomFile.error = Es mu\u00DF ein g\u00FCltiger URL angegeben werden.
 add.m1.project.projectGroup = Projektgruppe
-add.m1.project.buildDefinitionTemplate = Vorgangsschablone
+add.m1.project.buildDefinitionTemplate = Vorgangsvorlage
 add.m1.project.defaultBuildDefinition = Standard
 
 # ----------------------------------------------------------------------
 # Page: AddMavenTwoProject
 # ----------------------------------------------------------------------
-add.m2.project.page.title = Continuum - Maven 2 Projekt hinzuf\u00FCgen
-add.m2.project.section.title = Maven 2.0+ Projekt hinzuf\u00FCgen
+add.m2.project.page.title = Continuum - Maven Projekt hinzuf\u00FCgen
+add.m2.project.section.title = Maven Projekt hinzuf\u00FCgen
 add.m2.project.m2PomUrl.label = POM URL
 add.m2.project.m2PomUrl.username.label = Benutzername
 add.m2.project.m2PomUrl.password.label = Passwort
-add.m2.project.m2PomUrl.message =  Bitte geben Sie den URL des zu \u00FCbertragenden Maven 2 POM an. Falls es sich um eine gesch\u00FCtzte Resource handelt, geben Sie zus\u00E4tzlich den Benutzernamen und das Passwort an.
+add.m2.project.m2PomUrl.message =  Bitte geben Sie den URL des zu \u00FCbertragenden Maven POM an. Falls es sich um eine gesch\u00FCtzte Ressource handelt, geben Sie zus\u00E4tzlich den Benutzernamen und das Passwort an.
 add.m2.project.m2PomUrl.error = Es mu\u00DF ein g\u00FCltiger URL angegeben werden.
 add.m2.project.m2PomFile.label = POM-Datei
-add.m2.project.m2PomFile.message =  Bitte geben Sie den lokalen Dateinamen des zu \u00FCbertragenden Maven 2 POM an. (Projekte mit mehreren Modulen werden nicht unterst\u00FCtzt).
+add.m2.project.m2PomFile.message =  Bitte geben Sie den lokalen Dateinamen des zu \u00FCbertragenden Maven POM an. (Projekte mit mehreren Modulen werden nicht unterst\u00FCtzt).
 add.m2.project.m2PomFile.error = Es mu\u00DF ein g\u00FCltiger URL angegeben werden.
 add.m2.project.projectGroup = Projektgruppe
 # TODO: remove this part once uploading of an m2 project with modules is supported ( CONTINUUM-1098 )
-add.m2.project.upload.modules.error = Es kann kein Maven 2 Projekt mit Modulen \u00FCbertragen werden.
+add.m2.project.upload.modules.error = Es kann kein Maven Projekt mit Modulen \u00FCbertragen werden.
 add.m2.project.nonRecursiveProject = Bei Projekten mit mehreren Modulen nur das Eltern-Projekt laden.
-add.m2.project.buildDefinitionTemplate = Vorgangsschablone
+add.m2.project.buildDefinitionTemplate = Vorgangsvorlage
 add.m2.project.defaultBuildDefinition = Standard
 
 # ----------------------------------------------------------------------
 # Page: AddProject (ant or shell)
 # ----------------------------------------------------------------------
 add.shell.project.page.title = Continuum - Shell Projekt hinzuf\u00FCgen
-add.shell.project.section.title = Continuum - Shell Projekt hinzuf\u00FCgen
+add.shell.project.section.title = Shell Projekt hinzuf\u00FCgen
 add.ant.project.page.title = Continuum - Ant Projekt hinzuf\u00FCgen
 add.ant.project.section.title = Ant Projekt hinzuf\u00FCgen
 
 projectName.label = Projektname
 projectName.error = Es mu\u00DF ein Projektname angegeben werden.
-projectName.already.exist.error = Ein Projekt mit demselben Namen existiert bereits.
+projectName.already.exist.error = Ein Projekt mit identischem Namen existiert bereits.
 projectName.message = Bitte geben Sie einen Projektnamen an.
 
 projectScm.label = SCM
@@ -340,21 +339,21 @@
 projectVersion.message = Bitte geben Sie die Version des Projekts an.
 
 projectScmUseCache.label = Legitimationsdaten zwischenspeichern, falls m\u00F6glich.
-add.project.buildDefinitionTemplate = Vorgangsschablone
+add.project.buildDefinitionTemplate = Vorgangsvorlage
 add.project.defaultBuildDefinition = Standard
 
 # ----------------------------------------------------------------------
 # Page: DeleteProject
 # ----------------------------------------------------------------------
-deleteProject.page.title = Continuum - Continuum Projekte l\u00F6schen
-deleteProject.section.title = Continuum Projekte l\u00F6schen
-deleteProject.confirmation.message = Soll das Projekt "{0}" wirklich gel\u00F6scht werden ?
+deleteProject.page.title = Continuum - Projekt l\u00F6schen
+deleteProject.section.title = Projekt l\u00F6schen
+deleteProject.confirmation.message = Soll das ''{0}'' Projekt wirklich gel\u00F6scht werden ?
 
 # ----------------------------------------------------------------------
 # Page: ProjectView
 # ----------------------------------------------------------------------
-projectView.page.title = Continuum - Continuum Projekt
-projectView.section.title = Continuum Projekt
+projectView.page.title = Continuum - Projekt
+projectView.section.title = {0} Projektinformationen
 projectView.project.name = Projektname
 projectView.project.version = Version
 projectView.project.scmUrl = SCM URL
@@ -372,7 +371,7 @@
 buildDefinition.profile.label = Umgebung
 projectView.buildDefinition.from = Von
 projectView.buildDefinition.default = Standard
-projectView.buildDefinition.buildFresh = Vollst\u00E4ndig auschecken
+projectView.buildDefinition.buildFresh = Vollst\u00E4ndiger Checkout
 projectView.buildDefinition.description = Beschreibung
 projectView.notifiers = Berichterstatter
 projectView.notifier.type = Typ
@@ -398,8 +397,8 @@
 # ----------------------------------------------------------------------
 # Page: ProjectEdit
 # ----------------------------------------------------------------------
-projectEdit.page.title = Continuum - Continuum Projekt bearbeiten
-projectEdit.section.title = Continuum Projekt bearbeiten
+projectEdit.page.title = Continuum - Projekt bearbeiten
+projectEdit.section.title = Projekt bearbeiten
 projectEdit.project.name.label = Projektname
 projectEdit.project.version.label = Version
 projectEdit.project.scmUrl.label = SCM URL
@@ -419,19 +418,19 @@
 buildDefinition.goals.ant.label = Targets
 buildDefinition.goals.maven.label = Goals
 buildDefinition.arguments.label = Argumente
-buildDefinition.buildFresh.label = Immer vollst\u00E4ndig auschecken.
+buildDefinition.buildFresh.label = Vollst\u00E4ndiger Checkout
 buildDefinition.type.label = Typ
 buildDefinition.defaultForProject.label = Standard ?
 buildDefinition.schedule.label = Zeitplan
 buildDefinition.description.label = Beschreibung
 buildDefinition.alwaysBuild.label = Immer ausf\u00FChren
 buildDefinition.noname.save.error.message = Es mu\u00DF ein Name angegeben werden.
-buildDefinition.duplicatename.save.error.message = Ein Zeitplan mit demselben Namen existiert bereits.
+buildDefinition.duplicatename.save.error.message = Ein Zeitplan mit identischem Namen existiert bereits.
 
 # ----------------------------------------------------------------------
 # Page: BuildSummary
 # ----------------------------------------------------------------------
-buildDefinitionSummary.projectGroup.section.title = Vorgangsdefinitionen der Projekt-Gruppe "{0}"
+buildDefinitionSummary.projectGroup.section.title = {0} Vorgangsdefinitionen
 
 
 # ----------------------------------------------------------------------
@@ -439,14 +438,14 @@
 # ----------------------------------------------------------------------
 deleteBuildDefinition.page.title = Continuum - Vorgangsdefinition l\u00F6schen
 deleteBuildDefinition.section.title = Vorgangsdefinition l\u00F6schen
-deleteBuildDefinition.confirmation.message = Soll die Vorgangsdefinition mit Beschreibung "{1}", Goals "{2}" und Bezeichner "{0}" wirklich gel\u00F6scht werden ?
+deleteBuildDefinition.confirmation.message = Soll die ''{0}'' Vorgangsdefinition mit Beschreibung ''{1}'' und Goals ''{2}'' wirklich gel\u00F6scht werden ?
 
 # ----------------------------------------------------------------------
 # Page: DeleteNotifier
 # ----------------------------------------------------------------------
 deleteNotifier.page.title = Continuum - Berichterstatter l\u00F6schen
 deleteNotifier.section.title = Berichterstatter l\u00F6schen
-deleteNotifier.confirmation.message = Soll der Berichterstatter "{0}" mit Empf\u00E4ngeradresse "{1}" wirklich gel\u00F6scht werden ?
+deleteNotifier.confirmation.message = Soll der ''{0}'' Berichterstatter mit Empf\u00E4ngeradresse ''{1}'' wirklich gel\u00F6scht werden ?
 
 # ----------------------------------------------------------------------
 # Page: Notifier
@@ -488,8 +487,8 @@
 # ----------------------------------------------------------------------
 # Page: BuildResults
 # ----------------------------------------------------------------------
-buildResults.page.title = Continuum - Vorgangsergebnisse
-buildResults.section.title = Ergebnisse f\u00FCr {0}
+buildResults.page.title = Continuum - Vorg\u00E4nge
+buildResults.section.title = {0} Vorg\u00E4nge
 buildResults.buildNumber = Vorgang #
 buildResults.startTime = Startzeitpunkt
 buildResults.endTime = Endzeitpunkt
@@ -502,8 +501,8 @@
 # ----------------------------------------------------------------------
 # Page: BuildResults
 # ----------------------------------------------------------------------
-buildResult.page.title = Continuum - Vorgangs-Ergebnis
-buildResult.section.title = Vorgangs-Ergebnis f\u00FCr {0}
+buildResult.page.title = Continuum - Vorgang
+buildResult.section.title = {0} Vorgangsinformationen
 buildResult.startTime = Startzeitpunkt
 buildResult.endTime = Endzeitpunkt
 buildResult.duration = Dauer
@@ -532,16 +531,16 @@
 buildResult.dependencies.artifactId = Artefakt-Bezeichner
 buildResult.dependencies.version = Version
 buildResult.changesSinceLastSuccess = Weitere \u00C4nderungen seit letzer erfolgreicher Ausf\u00FChrung
-buildResult.generatedReports.title = Generierte Berichte
+buildResult.generatedReports.title = Berichte
 buildResult.generatedReports.surefire = Surefire-Bericht
 buildResult.buildOutput.text = Als Text herunterladen
-buildResult.buildDefinition = Verwendete Vorgangsdefinition
+buildResult.buildDefinition = Vorgangsdefinition
 buildResult.buildDefinition.ant.label = Ant Projekt Dateiname
 buildResult.buildDefinition.shell.label = Shell Script
 buildResult.buildDefinition.maven.label = POM Dateiname
 buildResult.buildDefinition.goals = Goals
 buildResult.buildDefinition.arguments = Argumente
-buildResult.buildDefinition.buildFresh = Vollst\u00E4ndig ausf\u00FChren
+buildResult.buildDefinition.buildFresh = Vollst\u00E4ndiger Checkout
 buildResult.buildDefinition.alwaysBuild = Immer ausf\u00FChren
 buildResult.buildDefinition.defaultForProject = Standard ?
 buildResult.buildDefinition.schedule = Zeitplan
@@ -550,7 +549,7 @@
 
 # From ContinuumProjectState
 buildResult.trigger.0 = durch Warteschlange
-buildResult.trigger.1 = erzwungen
+buildResult.trigger.1 = durch Benutzer
 buildResult.state.1 = Neu
 buildResult.state.2 = Ok
 buildResult.state.3 = Fehlversuch
@@ -565,7 +564,7 @@
 # Page: WorkingCopy
 # ----------------------------------------------------------------------
 workingCopy.page.title = Continuum - Arbeitskopie
-workingCopy.section.title = Arbeitskopie von {0}
+workingCopy.section.title = {0} Arbeitskopie
 workingCopy.currentFile.text = Als Text herunterladen
 
 # ----------------------------------------------------------------------
@@ -579,7 +578,6 @@
 schedules.table.cronExpression = Cron-Ausdruck
 schedules.table.active = Aktiv
 schedules.table.maxJobExecutionTime = Maximale Vorgangsdauer
-schedules.confirmation.message = Soll der Zeitplan "{0}" wirklich gel\u00F6scht werden ?
 
 # ----------------------------------------------------------------------
 # Page: Add/EditSchedule
@@ -587,16 +585,16 @@
 
 addSchedule.page.title=Continuum - Zeitplan hinzuf\u00FCgen
 addSchedule.section.title = Zeitplan hinzuf\u00FCgen
-editSchedule.page.title = Continuum - Zeitplan bearbeiten
-editSchedule.section.title = Zeitplan bearbeiten
+editSchedule.page.title = Continuum - Zeitplan hinzuf\u00FCgen/bearbeiten
+editSchedule.section.title = Zeitplan hinzuf\u00FCgen/bearbeiten
 schedule.name.label = Name
 schedule.name.message = Bitte geben Sie den Namen dieses Zeitplans an.
 schedule.description.label = Beschreibung
 schedule.description.message = Bitte geben Sie eine Beschreibung des Zeitplans an.
 schedule.cronExpression.label = Cron-Ausdruck
-schedule.cronExpression.message = Bitte geben Sie den Cron-Ausdruck an. Eine Beschreibung des Formats finden Sie <a href="http://www.opensymphony.com/quartz/api/org/quartz/CronTrigger.html" target="_blank">hier<a>.
+schedule.cronExpression.message = Bitte geben Sie den Cron-Ausdruck an. Eine Beschreibung des Formats finden Sie <a href="http://www.quartz-scheduler.org/docs/tutorials/crontrigger.html" target="_blank">hier<a>.
 schedule.maxJobExecutionTime.label = Maximale Ausf\u00FChrungszeit (Sekunden)
-schedule.maxJobExecutionTime.message = Bitte geben Sie die maximale Anzahl Sekunden an, den ein Vorgang dieses Zeitplans ausgef\u00FChrt werden kann, bevor er abgebrochen wird.
+schedule.maxJobExecutionTime.message = Bitte geben Sie die maximale Anzahl Sekunden an, die ein Vorgang dieses Zeitplans ausgef\u00FChrt werden kann, bevor er abgebrochen wird.
 schedule.quietPeriod.label = Ruhezeit (Sekunden)
 schedule.quietPeriod.message = Bitte geben Sie eine Ruhezeit f\u00FCr diesen Zeitplan an.
 schedule.enabled.label = Aktiviert
@@ -668,7 +666,7 @@
 releasePerformFromScm.scmPassword.label=SCM Passwort
 releasePerformFromScm.scmTag.label=SCM Markierung
 releasePerformFromScm.scmTagBase.label=SCM Markierungs-Basis
-releasePerformFromScm.goals.label=Maven Argumente
+releasePerformFromScm.goals.label=Perform Goals
 releasePerformFromScm.useReleaseProfile.label=Ver\u00F6ffentlichungs-Profil verwenden
 releasePerformFromScm.buildEnvironment.label=Umgebung
 
@@ -698,22 +696,22 @@
 # ----------------------------------------------------------------------
 # Page: Profiles List
 # ----------------------------------------------------------------------
-profilesList.page.title= Umgebungen
+profilesList.page.title= Continuum - Umgebungen
 profilesList.section.title= Umgebungen
 profilesList.installations.label=Installationen
 
 # ----------------------------------------------------------------------
 # Page: Profile Edit
 # ----------------------------------------------------------------------
-profile.page.title= Continuum - Umgebung
-profile.section.title = Umgebung
+profile.page.title= Continuum - Umgebung hinzuf\u00FCgen/bearbeiten
+profile.section.title = Umgebung hinzuf\u00FCgen/bearbeiten
 profile.name.label= Name
 profile.jdk.name.label = Jdk Name
 profile.jdk.name.message = Der JDK Name
 profile.jdk.path.label = Jdk Pfad
 profile.jdk.path.message = Der JDK-Pfad (Wert f\u00FCr JAVA_HOME)
 profile.no.installations = Keine Installationen vorhanden.
-profile.name.already.exists = Eine Umgebung mit demselben Namen existiert bereits.
+profile.name.already.exists = Eine Umgebung mit identischem Namen existiert bereits.
 profile.name.required = Es mu\u00DF ein Name angegeben werden.
 profile.remove.error = Die Umgebung kann nicht entfernt werden, solange es Vorgangsdefinitionen gibt, die sich darauf beziehen.
 profile.installation.name.label=Installationsname
@@ -728,25 +726,25 @@
 # ----------------------------------------------------------------------
 # Page: Installation Edit
 # ----------------------------------------------------------------------
-installation.page.title = Continuum - Installation
-installation.section.title = Continuum - Installation
+installation.page.title = Continuum - Installation hinzuf\u00FCgen/bearbeiten
+installation.section.title = Installation hinzuf\u00FCgen/bearbeiten
 installation.name.label = Installationsname
 installation.type.label = Typ
 installation.value.label = Wert/Pfad
 installation.varName.label = Variablenname
 installation.jdk.type.label = JDK
-installation.maven2.type.label = Maven 2
+installation.maven2.type.label = Maven
 installation.maven1.type.label = Maven 1
 installation.envvar.type.label = Umgebungs-Variable
 installation.ant.type.label = ANT
 installation.automaticProfile.label=Eine Umgebung mit dem Installations-Namen erstellen.
-installation.name.duplicate = Eine Installation mit demselben Namen existiert bereits.
+installation.name.duplicate = Eine Installation mit identischem Namen existiert bereits.
 
 # ----------------------------------------------------------------------
 # Page: Installations Type Choice
 # ----------------------------------------------------------------------
-installationTypeChoice.page.title =  Continuum - Auswahl Installationstyp
-installationTypeChoice.section.title = Auswahl Installationstyp
+installationTypeChoice.page.title =  Continuum - Installationstyp
+installationTypeChoice.section.title = Installationstyp
 installationTypeChoice.action.label = Installationstyp
 installationTypeChoice.tool.label = Werkzeug
 installationTypeChoice.envar.label = Umgebungs-Variable
@@ -754,32 +752,32 @@
 # ----------------------------------------------------------------------
 # Page: Build Definitions Templates Summary
 # ----------------------------------------------------------------------
-buildDefinition.templates.page.title = Continuum - Vorgangsschablonen
+buildDefinition.templates.page.title = Continuum - Vorgangsvorlagen
 buildDefinition.templates.continuum.section.title = Continuum Standard Vorgangsdefinition
 buildDefinition.templates.goals = Goals
 buildDefinition.templates.arguments = Argumente
 buildDefinition.templates.buildFile = Projektdatei
 buildDefinition.templates.schedule = Zeitplan
 buildDefinition.templates.profile = Umgebung
-buildDefinition.templates.buildFresh = Vollst\u00E4ndige Ausf\u00FChrung
+buildDefinition.templates.buildFresh = Vollst\u00E4ndiger Checkout
 buildDefinition.templates.alwaysBuild = Immer ausf\u00FChren
 buildDefinition.templates.description = Beschreibung
 buildDefinition.templates.type = Typ
-buildDefinition.templates.section.title = Verf\u00FCgbare Vorgangsschablonen
+buildDefinition.templates.section.title = Verf\u00FCgbare Vorgangsvorlagen
 buildDefinition.templates.buildDefinitions.section.title = Verf\u00FCgbare Vorgangsdefinitionen
 
 # ----------------------------------------------------------------------
 # Page: Edit Build Definition Template
 # ----------------------------------------------------------------------
-buildDefinition.template.page.title = Continuum - Vorgangsschablone
-buildDefinition.template.section.title = Vorgangsschablone
+buildDefinition.template.page.title = Continuum - Vorgangsvorlage hinzuf\u00FCgen/bearbeiten
+buildDefinition.template.section.title = Vorgangsvorlage hinzuf\u00FCgen/bearbeiten
 buildDefinition.template.name = Name
 buildDefinition.template.buildDefinition.goals = Goals
 buildDefinition.template.buildDefinition.arguments = Argumente
 buildDefinition.template.buildDefinition.buildFile = Projektdatei
 buildDefinition.template.buildDefinition.schedule = Zeitplan
 buildDefinition.template.buildDefinition.profile = Umgebung
-buildDefinition.template.buildDefinition.buildFresh = Immer ausf\u00FChren ?
+buildDefinition.template.buildDefinition.buildFresh = Vollst\u00E4ndiger Checkout
 buildDefinition.template.buildDefinition.default = Standard
 buildDefinition.template.buildDefinition.description = Beschreibung
 buildDefinition.template.buildDefinition.type = Typ
@@ -791,18 +789,18 @@
 # ----------------------------------------------------------------------
 # Page: Build Queue
 # ----------------------------------------------------------------------
-buildQueue.page.title = Continuum - Vorgangs-Warteschlange
-buildQueue.section.title = Continuum - Vorgangs-Warteschlange
+buildQueue.page.title = Continuum - Warteschlangen
+buildQueue.section.title = Ausstehende Vorg\u00E4nge
 buildQueue.empty = Die Vorgangs-Warteschlange ist leer.
-buildQueue.currentTask.section.title = Aktueller Vorgang
+buildQueue.currentTask.section.title = Aktuelle Vorg\u00E4nge
 buildQueue.currentTask.projectName = Projektname
 buildQueue.currentTask.buildDefinition = Vorgangsdefinition
 buildQueue.no.currentTaks = Aktuell wird kein Vorgang ausgef\u00FChrt.
 buildQueue.removeEntries = Auswahl abbrechen
-checkoutQueue.currentTask.section.title = Aktueller Checkout
+checkoutQueue.currentTask.section.title = Aktuelle Checkouts
 checkoutQueue.currentTask.projectName = Projektname
 checkoutQueue.no.currentTaks = Aktuell wird kein Checkout ausgef\u00FChrt.
-checkoutQueue.section.title = Checkout Warteschlange
+checkoutQueue.section.title = Ausstehende Checkouts
 checkoutQueue.empty = Die Checkout-Warteschlange ist leer.
 checkoutQueue.removeEntries = Auswahl abbrechen
 
@@ -811,7 +809,7 @@
 # ----------------------------------------------------------------------
 buildResult.delete.confirmation.page.title = Continuum - Vorgangs-Ergebnisse l\u00F6schen
 buildResult.delete.confirmation.section.title = Vorgangs-Ergebnisse l\u00F6schen
-buildResult.delete.confirmation.message = Sollen diese {0} Vorgangs-Ergebnisse wirklich gel\u00F6scht werden ?
+buildResult.delete.confirmation.message = Sollen die {0} Vorgangs-Ergebnisse wirklich gel\u00F6scht werden ?
 buildResult.cannot.delete = Der Vorgang wird momentan ausgef\u00FChrt. L\u00F6schung nicht m\u00F6glich.
 
 # ----------------------------------------------------------------------
@@ -828,9 +826,9 @@
 legend.delete=L\u00F6schen
 legend.edit=Bearbeiten
 legend.release=Ver\u00F6ffentlichen
-legend.buildInSuccess=Ausf\u00FChrung erfolgreich
-legend.buildInFailure=Ausf\u00FChrung fehlgeschlagen
-legend.buildInError=Ausf\u00FChrung fehlerhaft
+legend.buildInSuccess=Vorgang erfolgreich
+legend.buildInFailure=Vorgang fehlgeschlagen
+legend.buildInError=Vorgang abgebrochen
 
 
 # ----------------------------------------------------------------------
@@ -841,16 +839,16 @@
 # ----------------------------------------------------------------------
 # Page: DeleteProjects
 # ----------------------------------------------------------------------
-deleteProjects.page.title = Continuum - Continuum Projekte l\u00F6schen
-deleteProjects.section.title = Continuum Projekte l\u00F6schen
-deleteProjects.confirmation.message = Sollen die Projekte "{0}"  wirklich gel\u00F6scht werden ?
+deleteProjects.page.title = Continuum - Projekte l\u00F6schen
+deleteProjects.section.title = Projekte l\u00F6schen
+deleteProjects.confirmation.message = Sollen die ''{0}'' Projekte  wirklich gel\u00F6scht werden ?
 
 # ----------------------------------------------------------------------
 # Page: Confirm Delete Build Env
 # ----------------------------------------------------------------------
 deleteBuildEnv.page.title = Continuum - Umgebung l\u00F6schen
 deleteBuildEnv.section.title = Umgebung l\u00F6schen
-deleteBuildEnv.confirmation.message = Soll die Umgebung "{0}" wirklich gel\u00F6scht werden ?
+deleteBuildEnv.confirmation.message = Soll die ''{0}'' Umgebung wirklich gel\u00F6scht werden ?
 
 #-----------------------------------------------------------------------
 # Page: Local Repositories
@@ -883,7 +881,7 @@
 #-----------------------------------------------------------------------
 deleteRepository.page.title = Continuum - Lokales Repository l\u00F6schen
 deleteRepository.section.title = Lokales Repository l\u00F6schen
-deleteRepository.confirmation.message = Soll das lokale Repository "{0}" wirklich gel\u00F6scht werden ?
+deleteRepository.confirmation.message = Soll das lokale ''{0}'' Repository wirklich gel\u00F6scht werden ?
 
 #-----------------------------------------------------------------------
 # Page: Purge Configurations
@@ -893,13 +891,14 @@
 purgeConfigs.dir.section.title = Verzeichnis Bereinigungskonfigurationen
 purgeConfigs.table.repository = Repository
 purgeConfigs.table.description = Beschreibung
-purgeConfigs.table.retentionCount = Aufbewahrungstage
+purgeConfigs.table.retentionCount=Aufzubewahrende Artefakte/Verzeichnisse
 purgeConfigs.table.schedule = Zeitplan
-purgeConfigs.table.daysOlder = \u00C4lter als (in Tagen)
+purgeConfigs.table.daysOlder = \u00C4lter als
 purgeConfigs.table.deleteAll = Alle l\u00F6schen
 purgeConfigs.table.directoryType = Verzeichnistyp
 purgeConfigs.table.default = Standard
 purgeConfigs.table.enabled = Aktiviert
+purgeConfigs.table.buildAgent = Vorgangsagent
 purgeConfigs.table.deleteReleasedSnapshots = Ver\u00F6ffentlichte Snapshots l\u00F6schen
 
 #-----------------------------------------------------------------------
@@ -909,7 +908,7 @@
 purgeConfig.section.title = Bereinigungskonfiguration hinzuf\u00FCgen/bearbeiten
 purgeConfig.repository.label = Repository
 purgeConfig.directoryType.label = Verzeichnistyp
-purgeConfig.retentionCount.label = Aufbewahrungstage
+purgeConfig.retentionCount.label=Aufzubewahrende Artefakte/Verzeichnisse
 purgeConfig.daysOlder.label = \u00C4lter als (in Tagen)
 purgeConfig.deleteAll.label = Alle l\u00F6schen
 purgeConfig.deleteReleasedSnapshots.label = Ver\u00F6ffentlichte Snapshots l\u00F6schen
@@ -918,11 +917,12 @@
 purgeConfig.description.label = Beschreibung
 purgeConfig.enabled.label = Aktiviert
 purgeConfig.no.repositories = Keine zu bereinigende Repositories.
+purgeConfig.buildAgent.label = Vorgangsagent
 
 # ----------------------------------------------------------------------
 # Page: Release Results
 # ----------------------------------------------------------------------
-projectGroup.releaseResults.section.title = Ver\u00F6ffentlichungen der Gruppe {0}
+projectGroup.releaseResults.section.title = {0} Ver\u00F6ffentlichungen
 releaseResults.viewResult = Ergebnis anzeigen
 releaseResults.state = Status
 releaseResults.startTime = Startzeitpunkt
@@ -935,9 +935,9 @@
 # ----------------------------------------------------------------------
 # Page: Confirm Delete Release Results
 # ----------------------------------------------------------------------
-deleteReleaseResults.page.title = Continuum - Ergebnisse der Ver\u00F6ffentlichung l\u00F6schen
-deleteReleaseResults.section.title = Ergebnisse der Ver\u00F6ffentlichung l\u00F6schen
-deleteReleaseResults.confirmation.message = Sollen diese {0} Ergebnisse der Ver\u00F6ffentlichung wirklich gel\u00F6scht werden ?
+deleteReleaseResults.page.title = Continuum - Ver\u00F6ffentlichungs-Ergebnisse l\u00F6schen
+deleteReleaseResults.section.title = Ver\u00F6ffentlichungs-Ergebnisse l\u00F6schen
+deleteReleaseResults.confirmation.message = Sollen die {0} Ver\u00F6ffentlichungs-Ergebnisse wirklich gel\u00F6scht werden ?
 
 # ----------------------------------------------------------------------
 # Component: Failure
@@ -948,7 +948,7 @@
 # Component: Project Group Notifier Summary
 # ----------------------------------------------------------------------
 projectGroupNotifierSummaryComponent.projectNotifiers=Projekt Berichterstatter
-projectGroupNotifierSummaryComponent.groupNotifiers=Berichterstatter der Gruppe {0}
+projectGroupNotifierSummaryComponent.groupNotifiers={0} Berichterstatter
 
 # ----------------------------------------------------------------------
 # Page: ScmResult
@@ -957,7 +957,7 @@
 scmResult.section.title = SCM Ergebnis
 scmResult.state = Status
 scmResult.projectGroupName = Projektgruppenname
-scmResult.scmRootAddress = SCM Wurzel-Verzeichnis-URL
+scmResult.scmRootAddress = SCM Hauptverzeichnis-URL
 scmResult.scmError = SCM Fehler
 
 # ----------------------------------------------------------------------
@@ -973,7 +973,7 @@
 appearance.maybeChange = Wenn Sie den Firmen-Namen, URL oder das Logo \u00E4ndern m\u00F6chten, k\u00F6nnen Sie
 appearance.editThePomLink = das POM bearbeiten
 appearance.companyPom.groupId = Gruppenbezeichner
-appearance.companyPom.artifactId = Artefaktbereichner
+appearance.companyPom.artifactId = Artefaktbezeichner
 appearance.companyPom.version = Version
 appearance.editCompanyPom = Firmen-POM bearbeiten
 appearance.companyPom.section.title = POM Informationen
@@ -990,6 +990,171 @@
 companyPom.section.title=Firmen-POM
 companyPom.autoIncrementVersion=Die Version wird beim Speichern automatisch inkrementiert.
 notifier.event.sendOnScmFailure=Bei SCM-Fehler senden
-projectGroup.scmRoot.label=SCM Wurzel-Verzeichnis-URL
-projectGroup.scmRoot.title=Projektgruppen SCM Wurzel-Verzeichnis
+projectGroup.scmRoot.label=SCM Hauptverzeichnis-URL
+projectGroup.scmRoot.title=SCM Hauptverzeichnisse
 releasePrepare.useEditMode.label=''Editmodus'' verwenden
+projectGroup.cancelGroupBuild=Gruppenvorg\u00E4nge abbrechen
+configuration.allowed.build.parallel=Maximal erlaubte Anzahl parallel ausgef\u00FChrter Vorg\u00E4nge
+configuration.disable.parallel.builds=Parallel ausf\u00FChrbare Vorg\u00E4nge deaktivieren
+configuration.allowed.build.paralle.message=Bitte geben Sie die maximal erlaubte Anzahl parallel ausf\u00FChrbarer Vorg\u00E4nge an.
+configuration.numberOfBuildsInParallel.invalid=Die erlaubte Anzahl parallel ausf\u00FChrbarer Vorg\u00E4nge mu\u00DF gr\u00F6\u00DFer als Null sein.
+configuration.distributedBuildEnabled.label=Vorgangsverteilung aktiv
+projectDescription.label=Beschreibung
+projectDescription.message=Bitte geben Sie eine Beschreibung des Projekts an.
+projectView.project.description=Beschreibung
+schedule.buildqueues.label=Konfiguration der zu verwendenden Warteschlangen
+schedule.buildqueues.define=Konfigurieren Sie die zu verwendenden Warteschlangen.
+schedule.available.buildqueues=--- Verf\u00FCgbare Warteschlangen ---
+schedule.available.buildqueues.used=--- Verwendete Warteschlangen ---
+schedule.buildqueues.add.error=Fehler beim Zuf\u00FCgen der Warteschlange(n) zum Zeitplan.
+releasePrepare.scmCommentPrefix.label=SCM Kommentar-Prefix
+releasePrepare.arguments.label=Argumente
+releasePrepare.addSchema.label=POM um XML-Schema-Angaben erweitern, falls nicht vorhanden.
+releasePrepare.autoVersionSubmodules.label=autoVersionSubmodules (aus POM)
+buildQueue.currentTask.buildQueue=Warteschlange
+checkoutQueue.currentTask.buildQueue=Warteschlange
+buildQueue.cannot.delete=Die Warteschlange kann nicht gel\u00F6scht werden, da Vorg\u00E4nge ausgef\u00FChrt werden.
+buildQueue.delete.error=Die Warteschlange konnte nicht aus der Datenbank entfernt werden.
+deletePurgeConfiguration.page.title=Continuum - Bereinigungskonfiguration l\u00F6schen
+deletePurgeConfiguration.section.title=Bereinigungskonfiguration l\u00F6schen
+deletePurgeConfiguration.confirmation.message=Soll die ''{0}'' Bereinigungskonfiguration wirklich gel\u00F6scht werden ?
+parallel.build.queues.page.title=Continuum - Warteschlangen
+parallel.build.queues.section.title=Warteschlangen
+parallel.build.queue.page.title=Continuum - Warteschlange hinzuf\u00FCgen/bearbeiten
+parallel.build.queue.section.title=Warteschlange hinzuf\u00FCgen/bearbeiten
+parallel.build.queue.name=Name
+buildAgents.page.title=Continuum - Vorgangsagenten
+buildAgents.section.title=Vorgangsagenten
+buildAgents.table.url=URL
+buildAgents.table.description=Beschreibung
+buildAgents.table.enabled=Aktiv
+buildAgent.page.title=Continuum - Vorgangsagent hinzuf\u00FCgen/bearbeiten
+buildAgent.section.title=Vorgangsagent hinzuf\u00FCgen/bearbeiten
+buildAgent.url.label=URL
+buildAgent.description.label=Beschreibung
+buildAgent.enabled.label=Aktiv
+buildAgent.error.doesnotexist=Vorgangsagent existiert nicht.
+buildAgent.error.duplicate=Der Vorgangsagent existiert bereits.
+viewBuildAgent.page.title=Continuum - Vorgangsagent
+viewBuildAgent.section.title=Vorgangsagent
+viewBuildAgent.installations.title=Verf\u00FCgbare Installationen
+deleteBuildAgent.page.title=Continuum - Vorgangsagent l\u00F6schen
+deleteBuildAgent.section.title=Vorgangsagent l\u00F6schen
+deleteBuildAgent.confirmation.message=Soll der ''{0}'' Vorgangsagent wirklich gel\u00F6scht werden ?
+distributedBuilds.page.title=Continuum - Warteschlangen
+distributedBuilds.buildQueue.section.title=Ausstehende Vorg\u00E4nge
+distributedBuild.table.projectGroupName=Projektgruppenname
+distributedBuilds.empty=Die Vorgangs-Warteschlange ist leer.
+distributedBuilds.removeEntries=Eintr\u00E4ge abbrechen
+buildDefinitionSummary.project.section.title=Projekt Vorgangsdefinitionen
+buildDefinitionSummary.project=Projekt
+rollback=\u00C4nderungen zur\u00FCcknehmen
+done=Abschlie\u00DFen
+in.progress=Wird ausgef\u00FChrt
+error=Fehler
+queued=Eingereiht
+refresh=Aktualisieren
+releaseInProgress.currently.initializing=Das Ver\u00F6ffentlichungs-Goal wird initialisiert...
+releaseInProgress.please.wait=Projektver\u00F6ffentlichung wird vorbereitet. Bitte warten.
+releaseProject.rollbackWarning=Dies wird alle \u00C4nderungen der letzten Ver\u00F6ffentlichung r\u00FCckg\u00E4ngig machen.
+releaseProject.rollbackWarning.section.title=Ver\u00F6ffentlichung zur\u00FCcknehmen
+viewBuildAgent.installations.name=Name
+viewBuildAgent.installations.type=Typ
+viewBuildAgent.installations.varName=Umgebungsvariable
+viewBuildAgent.installations.varValue=Wert/Pfad
+menu.distributedBuilds=Verteilte Ausf\u00FChrung
+menu.distributedBuilds.buildAgents=Vorgangsagenten
+menu.distributedBuilds.releases=Ver\u00F6ffentlichungen
+menu.parallelBuilds=Parallele Ausf\u00FChrung
+menu.parallelBuilds.build.queue=Warteschlangen
+schedule.name.already.exists=Ein Zeitplan mit identischem Namen existiert bereits.
+profilesList.buildAgentGroup.label=Vorgangsagenten-Gruppe
+profile.build.agent.group=Vorgangsagenten-Gruppe
+installation.varName.required=Es mu\u00DF eine Umgebungsvariable angegeben werden.
+deleteInstallation.page.title=Continuum - Installation l\u00F6schen
+deleteInstallation.section.title=Installation l\u00F6schen
+deleteInstallation.confirmation.message=Soll die ''{0}'' Installation wirklich gel\u00F6scht werden ?
+deletebuildDefinition.template.page.title=Continuum - Vorgangsvorlage l\u00F6schen
+deletebuildDefinition.template.section.title=Vorgangsvorlage l\u00F6schen
+deletebuildDefinition.template.confirmation.message=Soll die ''{0}'' Vorgangsvorlage wirklich gel\u00F6scht werden ?
+deleteBuildQueue.page.title=Continuum - Warteschlange l\u00F6schen
+deleteBuildQueue.section.title=Warteschlange l\u00F6schen
+deleteBuildQueue.confirmation.message=Soll die ''{0}'' Warteschlange wirklich gel\u00F6scht werden ?
+buildAgents.empty=Keine Vorgangsagenten
+buildAgentGroups.section.title=Gruppen
+buildAgentGroups.table.name=Name
+buildAgentGroups.table.agents=Vorgangsagenten
+buildAgent.error.remove.in.use=Der Vorgangsagent kann nicht gel\u00F6scht werden, da er mit einer Vorgangsagenten-Gruppe verwendet wird.
+deleteBuildAgentGroup.page.title=Continuum - Vorgangsagenten-Gruppe l\u00F6schen
+deleteBuildAgentGroup.section.title=Vorgangsagenten-Gruppe l\u00F6schen
+deleteBuildAgentGroup.confirmation.message=Soll die ''{0}'' Vorgangsagenten-Gruppe wirklich gel\u00F6scht werden ?
+buildAgentGroup.page.title=Continuum - Vorgangsagenten-Gruppe hinzuf\u00FCgen/bearbeiten
+buildAgentGroup.section.title=Vorgangsagenten-Gruppe hinzuf\u00FCgen/bearbeiten
+buildAgentGroup.name.label=Name
+buildAgentGroup.agents.label=Agenten
+buildAgentGroup.error.doesnotexist=Die Vorgangsagenten-Gruppe existiert nicht.
+buildAgentGroup.error.duplicate=Die Vorgangsagenten-Gruppe existiert bereits.
+buildAgentGroup.error.name.required=Es mu\u00DF ein Name angegeben werden.
+buildAgentGroup.error.name.cannot.be.spaces=Es mu\u00DF ein g\u00FCltiger Name angegeben werden.
+buildAgentGroup.available.buildAgents=--- Verf\u00FCgbare Vorgangsagenten ---
+buildAgentGroup.available.buildAgents.used=--- Verwendete Vorgangsagenten ---
+buildAgentGroup.buildAgents.define=Konfiguration der zu verwendenden Vorgangsagenten
+buildAgentGroup.error.remove.in.use=Die Vorgangsagenten-Gruppe kann nicht gel\u00F6scht werden - sie wird mit einer Umgebung verwendet.
+releases.page.title=Continuum - Ver\u00F6ffentlichungen
+releases.section.title=Ver\u00F6ffentlichungen
+releaseSummary.table.releaseId=Ver\u00F6ffentlichungs ID
+releaseSummary.table.releaseGoal=Ver\u00F6ffentlichungs-Goal
+releaseSummary.table.buildAgentUrl=URL des Vorgangsagenten
+distributedBuild.releasePrepare.input.error=Projektverarbeitung nicht m\u00F6glich. Der {0} Vorgangsagent wurde entweder entfernt bzw. deaktiviert, oder es wurde noch kein Vorgang ausgef\u00FChrt.
+distributedBuild.releasePrepare.error=Ver\u00F6ffentlichungs-Vorbereitung nicht m\u00F6glich.
+distributedBuild.releasePrepare.release.error=Ver\u00F6ffentlichungs-Vorbereitung nicht m\u00F6glich. Der {0} Vorgangsagent wurde zwischenzeitlich entfernt oder deaktiviert.
+distributedBuild.releaseInProgress.error=Anzeige des Ver\u00F6ffentlichungs-Vorgangs nicht m\u00F6glich. Der {0} Vorgangsagent wurde zwischenzeitlich entfernt oder deaktiviert.
+distributedBuild.releaseViewResult.error=Anzeige des Ver\u00F6ffentlichungs-Ergebnisses nicht m\u00F6glich. Der {0} Vorgangsagent wurde zwischenzeitlich entfernt oder deaktiviert.
+distributedBuild.releaseCleanup.error=Ver\u00F6ffentlichungs-Bereinigung nicht m\u00F6glich. Der {0} Vorgangsagent wurde zwischenzeitlich entfernt oder deaktiviert.
+distributedBuild.releasePerform.input.error=Ermittlung der Release-Plugin-Parameter nicht m\u00F6glich. Der {0} Vorgangsagent wurde zwischenzeitlich entfernt oder deaktiviert.
+distributedBuild.releasePerform.release.error=Ver\u00F6ffentlichung nicht m\u00F6glich. Der {0} Vorgangsagent wurde zwischenzeitlich entfernt oder deaktiviert.
+deleteSchedule.page.title=Continuum - Zeitplan l\u00F6schen
+deleteSchedule.section.title=Zeitplan l\u00F6schen
+deleteSchedule.confirmation.message = Soll der ''{0}'' Zeitplan wirklich gel\u00F6scht werden ?
+confirmGroupRemoval.page.title=Continuum - Projektgruppe l\u00F6schen
+confirmGroupRemoval.section.title=Projektgruppe l\u00F6schen
+confirmGroupRemoval.confirmation.message=Soll die ''{0}'' Projektgruppe wirklich gel\u00F6scht werden ?
+releasePerformFromScm.page.title=Continuum - Projekt ver\u00F6ffentlichen
+releasePerformFromScm.section.title=Projekt ver\u00F6ffentlichen
+releasePerformFromScm.parameters.section.title=Parameter
+authorizationError.page.title=Continuum - Autorisierungs-Fehler
+authorizationError.section.title=Autorisierungs-Fehler
+authorizationError.not.authorized=Autorisierung fehlgeschlagen. Bitte kontaktieren Sie Ihren Administrator, um entsprechende Berechtigungen erteilt zu bekommen.
+errorOccured.page.title=Continuum - Fehler
+errorOccured.section.title=Fehler
+menu.continuum=Continuum
+releaseError.page.title=Continuum - Ver\u00F6ffentlichung fehlgeschlagen
+releaseError.section.title=Ver\u00F6ffentlichung fehlgeschlagen
+add.project.duplicate.error=Ein identisches Projekt existiert in dieser Gruppe bereits.
+distributedPrepareBuild.table.scmRootAddress=SCM Hauptverzeichnis-URL
+distributedBuilds.currentBuild.section.title=Aktuelle Vorg\u00E4nge
+projectGroup.delete.error=Die Projektgruppe konnte nicht gel\u00F6scht werden.
+buildResult.delete.error=Das ''{0}'' Vorgangsergebnis konnte nicht gel\u00F6scht werden.
+prepareBuildQueue.table.projectGroupName=Projektgruppe
+distributedPrepareBuild.table.projectGroupName=Projektgruppen-Name
+prepareBuildQueue.table.scmRootAddress=SCM Hauptverzeichnis-URL
+deleteProject.error=Das ''{0}'' Projekt konnte nicht gel\u00F6scht werden.
+buildResults.delete.error=Die Vorgangsergebnisse konnten nicht gel\u00F6scht werden.
+distributedPrepareBuilds.no.currentTasks=Aktuell wird kein Vorgang vorbereitet.
+distributedBuilds.currentPrepareBuild.section.title=Aktuelle Vorbereitungen
+distributedBuilds.prepareBuildQueue.section.title=Ausstehende Vorbereitungen
+distributedPrepareBuild.table.buildAgentUrl=Vorgangsagent URL
+distributedBuild.table.buildAgentUrl=Vorgangsagent URL
+distributedBuild.table.projectName=Projektname
+prepareBuildQueue.currentTask.section.title=Aktuelle Vorbereitungen
+prepareBuildQueue.removeEntries=Auswahl abbrechen
+prepareBuildQueue.section.title=Ausstehende Vorbereitungen
+distributedBuild.table.buildDefinitionLabel=Vorgangsdefinition
+distributedBuilds.no.currentTasks=Aktuell wird kein Vorgang ausgef\u00FChrt.
+distributedPrepareBuilds.empty=Die Vorbereitungs-Warteschlange ist leer.
+prepareBuildQueue.empty=Die Vorbereitungs-Warteschlange ist leer.
+distributedPrepareBuilds.removeEntries=Auswahl abbrechen
+prepareBuildQueue.no.currentTasks=Aktuell wird kein Vorgang vorbereitet.
+releasePrepare.input.error=Die ''Release-Plugin'' Parameter konnten nicht ermittelt werden - Verarbeitung fehlgeschlagen - {0}
+projectGroup.invalid.id=Ung\u00FCltiger Gruppen-Bezeichner: {0}
+schedule.buildqueues.empty.error=Es m\u00FCssen zu verwendende Warteschlangen angegeben werden.
diff --git a/continuum-webapp/src/main/resources/localization/Continuum_en.properties b/continuum-webapp/src/main/resources/localization/Continuum_en.properties
new file mode 100644
index 0000000..661b0cb
--- /dev/null
+++ b/continuum-webapp/src/main/resources/localization/Continuum_en.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+
diff --git a/continuum-webapp/src/main/resources/localization/Continuum_fr.properties b/continuum-webapp/src/main/resources/localization/Continuum_fr.properties
index e32a52a..88ac6fb 100644
--- a/continuum-webapp/src/main/resources/localization/Continuum_fr.properties
+++ b/continuum-webapp/src/main/resources/localization/Continuum_fr.properties
@@ -16,7 +16,6 @@
 # specific language governing permissions and limitations
 # under the License.
 #
-# Translation by Damien Blugeon.
 
 ## version $Id$
 
@@ -47,6 +46,13 @@
 unselectAll = D\u00e9selectionner tous
 sort.descending = Tri d\u00e9croissant
 sort.ascending = Tri croissant
+purge = Purge
+rollback=Annulation des changements
+done=Termin\u00e9
+in.progress=En progression
+error=Erreur
+queued=En attente
+refresh=Rafraichir
 
 # ----------------------------------------------------------------------
 # Page: Top
@@ -60,26 +66,35 @@
 # ----------------------------------------------------------------------
 # Page: Menu
 # ----------------------------------------------------------------------
+menu.continuum = Continuum
 menu.continuum.about = A propos
 menu.continuum.showProjects = Afficher les projets
 menu.continuum.showProjectGroups = Groupes de projets
 menu.addProject = Ajouter un projet
-menu.add.m2Project = Projet Maven 2.0.X
+menu.add.m2Project = Projet Maven
 menu.add.m1Project = Projet Maven 1.x
 menu.add.antProject = Projet Ant
 menu.add.shellProject = Projet Console
 menu.administration = Administration
 menu.administration.configuration = Configuration
 menu.administration.appearance = Apparence
-menu.administration.profile = Environnement de Build
+menu.administration.profile = Environnement de construction
 menu.administration.installations = Installations
 menu.administration.schedules = Planifications
 menu.administration.users = Utilisateurs
 menu.administration.userGroups = Groupes d''utilisateurs
-menu.administration.buildDefinitionTemplates = Mod\u00e8les de d\u00e9f. des contructions
+menu.administration.roles = Roles
+menu.administration.buildDefinitionTemplates = Mod\u00e8les de d\u00e9f. des constructions
 menu.account.options = Mon compte
 user.edit.account = Editer les informations utilisateur
 menu.administration.queues = Files d''attente
+menu.administration.repositories = Repository Local
+menu.administration.purge = Configuration de la purge
+menu.distributedBuilds = Constructions distribu\u009ees
+menu.distributedBuilds.buildAgents = Agents de construction
+menu.distributedBuilds.releases = Releases
+menu.parallelBuilds = Constructionss parall\u00e8les
+menu.parallelBuilds.build.queue= File d''attente des constructions
 
 # ----------------------------------------------------------------------
 # Page: error
@@ -105,10 +120,9 @@
 about.section.title = A propos de Continuum
 about.version.label = Version
 about.version.number = ${project.version}
-about.buildnumber.label = Build Number
+about.buildnumber.label = Num\u00e9ro de la construction
 about.buildnumber = ${buildNumber}
 
-
 # ----------------------------------------------------------------------
 # Page: Login
 # ----------------------------------------------------------------------
@@ -145,16 +159,17 @@
 groups.page.list.empty = La liste des groupes de projets est vide.
 groups.section.title = Groupe de projet :
 groups.manage.label = G\u00e9rer le Groupe
-groups.confirmation.message = Etes vous s\u00fbr de vouloir supprimer le groupe de projets "{0}" ?
+groups.table.repositoryName = Repository Local
 
 # ----------------------------------------------------------------------
 # Page: Project Group
 # ----------------------------------------------------------------------
 projectGroup.page.title = Continuum - Groupe de projets
-projectGroup.information.title = Information sur le groupe de projets
+projectGroup.information.title = Information sur le groupe de projets "{0}"
 projectGroup.name.label = Nom du groupe de projets
 projectGroup.groupId.label = Id du groupe de projets
 projectGroup.description.label = Description
+projectGroup.url.label = URL de la page d''acceuil
 projectGroup.projects.title = Membres du projet
 projectGroup.tab.summary = Bilan du groupe de projets
 projectGroup.tab.members = Membres
@@ -170,13 +185,19 @@
 projectGroup.deleteProjects = Supprimer projet(s)
 projectGroup.buildProjects = Construire projet(s)
 projectGroup.cancelBuilds = Annuler construction(s)
-projectGroup.buildsStatut.title = Aperçu du r\u00e9sultat de la derni\u00e8re construction du groupe de projets
+projectGroup.buildsStatut.title = Aper\u00e7u du r\u00e9sultat de la derni\u00e8re construction du groupe de projets
 projectGroup.buildsStatut.errors = Erreurs
 projectGroup.buildsStatut.failures = Echec
 projectGroup.buildsStatut.success = Succ\u00e8s
 projectGroup.buildDefinition.label = D\u00e9finitions de la construction par d\u00e9fault
 projectGroup.addProject.label = Ajouter un nouveau projet
 projectGroup.releaseNow = Release du groupe
+projectGroup.repository.label = Repository Local
+projectGroup.tab.releaseResults = R\u009esultats de release
+projectGroup.scmRoot.title = Racine SCM du groupe de projet
+projectGroup.scmRoot.label = URL de la racine SCM
+projectGroup.cancelGroupBuild = Annuler la construction du groupe
+projectGroup.invalid.id = Id du groupe de projets invalide : {0}
 
 # ----------------------------------------------------------------------
 # Page: Project Group - Members
@@ -212,6 +233,13 @@
 project.in.checkout.queue.error = Ne peut pas \u00e9diter ce groupe de projets. Des projets qui sont des membres de ce groupe de projets sont en cours de r\u00e9cup\u00e9ration du gestionnaire de sources.
 
 # ----------------------------------------------------------------------
+# Page: Confirm Group Removal
+# ----------------------------------------------------------------------
+confirmGroupRemoval.page.title=Continuum - Suppression de groupe de projets
+confirmGroupRemoval.section.title=Suppression de groupe de projets
+confirmGroupRemoval.confirmation.message=Etes-vous s\u00fbr de vouloir supprimer le groupe de projets "{0}"?
+
+# ----------------------------------------------------------------------
 # Page: Configuration
 # ----------------------------------------------------------------------
 configuration.page.title = Continuum - Configuration
@@ -222,6 +250,8 @@
 configuration.buildOutputDirectory.label = R\u00e9pertoire des logs de construction
 configuration.deploymentRepositoryDirectory.label = R\u00e9pertoire du repository de d\u00e9ploiement
 configuration.baseUrl.label = URL de base
+configuration.allowed.build.parallel = Nombre de constructions en parall\u00e8le autoris\u00e9es
+configuration.disable.parallel.builds = D\u00e9sactiver les construction parall\u00e8les
 configuration.submit.edit = Editer
 configuration.guest.message = Activ\u00e9/D\u00e9sactiv\u00e9 l''utilisateur invit\u00e9
 configuration.workingDirectory.message = Entrer le r\u00e9pertoire de travail de l''application web Continuum
@@ -231,6 +261,12 @@
 configuration.companyName.message = Entrer le nom de l''entreprise
 configuration.companyLogo.message = Entrer le logo de l''entreprise
 configuration.companyUrl.message = Entrer l''URL de base du site officiel de la soci\u00e9t\u00e9
+configuration.allowed.build.paralle.message = Entrer le nombre de constructions en parall\u00e8le autoris\u00e9es
+configuration.releaseOutputDirectory.label = R\u00e9pertoire de sortie des releases
+configuration.releaseOutputDirectory.message = Entrer le r\u00e9pertoire de sortie des releases de l'application Continuum
+configuration.releaseOutputDirectory.required = Vous devez d\u00e9finir un r\u00e9pertoire de sortie des releases
+configuration.numberOfBuildsInParallel.invalid = Le nombre de constructions en parall\u00e8le doit \u00eatre sup\u00e9rieur \u00e0 z\u00e9ro
+configuration.distributedBuildEnabled.label = Activer les constructions distribu\u00e9es
 
 # ----------------------------------------------------------------------
 # Page: Add Project
@@ -273,27 +309,27 @@
 add.m1.project.m1PomFile.message =  Entrer le nom local du fichier pom(version Maven 1) \u00e0 uploader
 add.m1.project.m1PomFile.error = Vous devez entrer une URL valide
 add.m1.project.projectGroup = Groupe du projet
-add.m1.project.buildDefinitionTemplate = Mod\u00e8le de d\u00e9finition de la contruction
+add.m1.project.buildDefinitionTemplate = Mod\u00e8le de d\u00e9finition de la construction
 add.m1.project.defaultBuildDefinition = D\u00e9faut
 
 # ----------------------------------------------------------------------
 # Page: AddMavenTwoProject
 # ----------------------------------------------------------------------
-add.m2.project.page.title = Continuum - Ajouter un Projet Maven 2
-add.m2.project.section.title = Ajouter un Projet Maven 2.0+
+add.m2.project.page.title = Continuum - Ajouter un Projet Maven
+add.m2.project.section.title = Ajouter un Projet Maven
 add.m2.project.m2PomUrl.label = URL du POM
 add.m2.project.m2PomUrl.username.label = Nom d''utilisateur
 add.m2.project.m2PomUrl.password.label = Mot de passe
-add.m2.project.m2PomUrl.message =  Entrez l''URL du pom Maven 2. Fournissez le nom d''utilisateur et le mot de passe si c''est une ressource s\u00e9curis\u00e9e.
+add.m2.project.m2PomUrl.message =  Entrez l''URL du pom Maven. Fournissez le nom d''utilisateur et le mot de passe si c''est une ressource s\u00e9curis\u00e9e.
 add.m2.project.m2PomUrl.error = Vous devez entrer une URL valide
 add.m2.project.m2PomFile.label = Uploader un fichier POM
-add.m2.project.m2PomFile.message =  Entrer le nom local du fichier pom(version Maven 2) \u00e0 uploader (fonctionne uniquement avec un projet sans modules).
+add.m2.project.m2PomFile.message =  Entrer le nom local du fichier pom(version Maven 2.0+) \u00e0 uploader (fonctionne uniquement avec un projet sans modules).
 add.m2.project.m2PomFile.error = Vous devez entrer une URL valide
 add.m2.project.projectGroup = Groupe du projet
 # TODO: remove this part once uploading of an m2 project with modules is supported ( CONTINUUM-1098 )
-add.m2.project.upload.modules.error = Ne peut pas uploader un projet Maven 2 avec modules.
+add.m2.project.upload.modules.error = Ne peut pas uploader un projet Maven avec modules.
 add.m2.project.nonRecursiveProject = Pour les projets multi modules, charger uniquement la racine comme une construction r\u00e9cursive
-add.m2.project.buildDefinitionTemplate = Mod\u00e8le de d\u00e9finition de la contruction
+add.m2.project.buildDefinitionTemplate = Mod\u00e8le de d\u00e9finition de la construction
 add.m2.project.defaultBuildDefinition = D\u00e9faut
 
 # ----------------------------------------------------------------------
@@ -317,6 +353,9 @@
 projectScmUrl.error = Vous devez fournir une URL de gestionnaire de sources (SCM)
 projectScmUrl.message = Entrer <a href="http://maven.apache.org/scm/scm-url-format.html">URL de gestionnaire de sources au format de Maven</a>
 
+projectDescription.label = Description
+projectDescription.message = Entrer la description du project
+
 projectScmUsername.label = Nom d''utilisateur du gestionnaire de sources
 projectScmUsername.message = Entrer le nom d''utilisateur du gestionnaire de sources 
 
@@ -331,7 +370,7 @@
 projectVersion.message = Entrer la version du projet
 
 projectScmUseCache.label = Utiliser le cache d''authentification du gestionnaire de sources
-add.project.buildDefinitionTemplate = Mod\u00e8le de d\u00e9finition de la contruction
+add.project.buildDefinitionTemplate = Mod\u00e8le de d\u00e9finition de la construction
 add.project.defaultBuildDefinition = D\u00e9faut
 
 # ----------------------------------------------------------------------
@@ -339,14 +378,15 @@
 # ----------------------------------------------------------------------
 deleteProject.page.title = Continuum - Supprimer un projet Continuum
 deleteProject.section.title = Supprimer un projet Continuum
-deleteProject.confirmation.message = Etes vous s\u00fbr de vouloir supprimer le projet "{0}" ?
+deleteProject.confirmation.message = Etes-vous s\u00fbr de vouloir supprimer le projet "{0}" ?
 
 # ----------------------------------------------------------------------
 # Page: ProjectView
 # ----------------------------------------------------------------------
 projectView.page.title = Continuum - Projet Continuum
-projectView.section.title = Projet Continuum
+projectView.section.title = Projet Continuum "{0}"
 projectView.project.name = Nom du projet
+projectView.project.description = Description
 projectView.project.version = Version
 projectView.project.scmUrl = URL du gestionnaire de sources
 projectView.project.scmTag = Branche/Tag du gestionnaire de sources
@@ -356,11 +396,11 @@
 projectView.buildDefinition.goals = Goals
 projectView.buildDefinition.arguments = Arguments
 projectView.buildDefinition.buildFile = Fichier de construction
-projectView.buildDefinition.profile = Environnement de Build
+projectView.buildDefinition.profile = Environnement de construction
 projectView.buildDefinition.schedule = Planification
 projectView.buildDefinition.type = Type
-projectView.buildDefinition.alwaysBuild = Toujours Construire
-buildDefinition.profile.label = Environnement de Build
+projectView.buildDefinition.alwaysBuild = Toujours construire
+buildDefinition.profile.label = Environnement de construction
 projectView.buildDefinition.from = De
 projectView.buildDefinition.default = Par d\u00e9faut
 projectView.buildDefinition.buildFresh = Extraction compl\u00e8te
@@ -423,14 +463,15 @@
 # Page: BuildSummary
 # ----------------------------------------------------------------------
 buildDefinitionSummary.projectGroup.section.title = D\u00e9finition de construction du groupe de projets {0}
-
+buildDefinitionSummary.project.section.title=D\u00e9finitions de construction du projet
+buildDefinitionSummary.project=Projet
 
 # ----------------------------------------------------------------------
 # Page: DeleteBuildDefinition
 # ----------------------------------------------------------------------
 deleteBuildDefinition.page.title = Continuum - Supprimer une d\u00e9finition de construction
 deleteBuildDefinition.section.title = Supprimer une d\u00e9finition de construction
-deleteBuildDefinition.confirmation.message = Etes-vous s\u00fbr de vouloir supprimer la d\u00e9finition de contruction avec la description "{1}", de goals "{2}" et d''id "{0}" ?
+deleteBuildDefinition.confirmation.message = Etes-vous s\u00fbr de vouloir supprimer la d\u00e9finition de construction avec la description "{1}", de goals "{2}" et d''id "{0}" ?
 
 # ----------------------------------------------------------------------
 # Page: DeleteNotifier
@@ -475,6 +516,7 @@
 notifier.event.sendOnFailure = Envoyer en cas d''\u00e9chec
 notifier.event.sendOnError = Envoyer en cas d''erreur 
 notifier.event.sendOnWarning = Envoyer en cas d''avertissement 
+notifier.event.sendOnScmFailure = Envoyer en cas d''erreur SCM
 
 # ----------------------------------------------------------------------
 # Page: BuildResults
@@ -487,6 +529,7 @@
 buildResults.duration = Dur\u00e9e
 buildResults.startedSince = D\u00e9marr\u00e9 depuis
 buildResults.state = \u00c9tat
+buildResults.result = Resultat
 buildResults.buildDefinition.description = Description de la d\u00e9finition de construction
 
 # ----------------------------------------------------------------------
@@ -535,7 +578,7 @@
 buildResult.buildDefinition.alwaysBuild = Toujours construire
 buildResult.buildDefinition.defaultForProject = Est-ce par d\u00e9faut ?
 buildResult.buildDefinition.schedule = Planification
-buildResult.buildDefinition.profileName = Environnement de Build
+buildResult.buildDefinition.profileName = Environnement de construction
 buildResult.buildDefinition.description = Description
 
 # From ContinuumProjectState
@@ -569,7 +612,6 @@
 schedules.table.cronExpression = Expression cron
 schedules.table.active = Activer
 schedules.table.maxJobExecutionTime = Temp d'ex\u00e9cution max.
-schedules.confirmation.message = Etes vous s\u00fbr de vouloir supprimer la planification "{0}" ?
 
 # ----------------------------------------------------------------------
 # Page: Add/EditSchedule
@@ -584,7 +626,7 @@
 schedule.description.label = Description
 schedule.description.message = Entrer une description pour la planification
 schedule.cronExpression.label = Expression Cron
-schedule.cronExpression.message = Entrer l''expression Cron Le format est d\u00e9crit l\u00e0 : <a href="http://www.opensymphony.com/quartz/api/org/quartz/CronTrigger.html" target="_blank">Syntaxe<a>
+schedule.cronExpression.message = Entrer l''expression Cron Le format est d\u00e9crit l\u00e0 : <a href="http://www.quartz-scheduler.org/docs/tutorials/crontrigger.html" target="_blank">Syntaxe<a>
 schedule.maxJobExecutionTime.label = Temp d''ex\u00e9cution du travail maximum
 schedule.maxJobExecutionTime.message = Entrer le nombre maximal de secondes que le travail peut prendre pour s''executer dans cette planification avant d''\u00eatre tu\u00e9.
 schedule.quietPeriod.label = P\u00e9riode d''attente (secondes)
@@ -599,6 +641,19 @@
 schedule.dayOfWeek.label = Jour de la semaine
 schedule.year.label = Ann\u00e9e [optionnelle]
 schedule.remove.error = La planification ne peut \u00eatre supprim\u00e9e, c''est probablement parce qu''elle est utilis\u00e9e par une d\u00e9finition de construction.
+schedule.buildqueues.label = Ajouter une file d''attente
+schedule.buildqueues.define = Configurer les files d''attente utilis\u00e9es
+schedule.available.buildqueues = --- File d''attente disponible ---
+schedule.available.buildqueues.used = --- File d''atente disponible ---
+schedule.buildqueues.add.error = Erreur lors de l''attachement de la/des file(s) d''attente \u00e0 la planification.
+schedule.name.already.exists = Une planification avec le m\u00eame nom existe d\u00e9j\u00e0
+
+# ----------------------------------------------------------------------
+# Page: Delete Schedule
+# ----------------------------------------------------------------------
+deleteSchedule.page.title = Continuum - Supprimer la planification
+deleteSchedule.section.title = Supprimer la planification
+deleteSchedule.confirmation.message = Etes vous s\u00fbr de vouloir supprimer la planification "{0}" ?
 
 # ----------------------------------------------------------------------
 # Page: SurefireReport
@@ -626,16 +681,20 @@
 releaseProject.prepareReleaseOption=Pr\u00e9parer le projet pour la "release"
 releaseProject.performReleaseOption=Effectuer la "release" du projet
 releaseProject.provideReleaseParameters=Fournir les param\u00eatres de la "release"
+releaseProject.rollbackWarning=Ceci annulera tous les changements fait par la "release" pr\u00e9c\u00e9dente?
+releaseProject.rollbackWarning.section.title=Annuler la "release"
 releasePrepare.section.title=Pr\u00e9parer le projet pour la "release"
-releasePrepare.parameters=Param\u00eatres de la pr\u00e9paration de la "release"
 releasePrepare.releaseVersion=Version de la "release"*
 releasePrepare.nextDevelopmentVersion=Prochaine version de d\u00e9veloppement*
+releasePrepare.parameters=Parametres de la pr\u00e9paration de la release
 releasePerform.section.title=Effectuer la "release" du projet
 releasePerform.parameters=Param\u00eatres de la r\u00e9alisation de la "release"
 releaseInProgress.section.title=Ex\u00e9cution du "Release Goal"
 releaseInProgress.status=Statut
 releaseInProgress.phase=Phase de "release"
 releaseInProgress.viewOutput=Affichage de la sortie
+releaseInProgress.currently.initializing=La tache de "release" est en train de s''initialiser...
+releaseInProgress.please.wait=Veuillez patienter tant que le serveur pr\u00e9pare votre projet pour la "release".
 releaseViewResult.section.title=Bilan de la "release" du Project
 releaseViewResult.summary=D\u00e9tails de la "release" du Projet
 releaseViewResult.startTime=Date de d\u00e9but
@@ -645,6 +704,30 @@
 releaseViewResult.error=ERREUR
 releaseViewResult.output=Sortie de l''ex\u00e9cution de la "release"
 releaseViewResult.noOutput=Aucune Sortie
+releaseViewResult.projectName=Nom du projet
+releaseViewResult.releaseGoal=Release Goal
+releasePrepare.scmUsername.label=Nom d''utilisateur SCM
+releasePrepare.scmPassword.label=Mot de passe SCM
+releasePrepare.scmTag.label=SCM Tag
+releasePrepare.scmTagBase.label=SCM Tag Base
+releasePrepare.scmCommentPrefix.label=Pr\u00e9fixe du commentaire SCM
+releasePrepare.prepareGoals.label=Preparation Goals
+releasePrepare.arguments.label=Arguments
+releasePrepare.buildEnvironment.label=Environment de construction
+releasePrepare.useEditMode.label=Utilisation du mode edit
+releasePrepare.addSchema.label=Ajout d''un sch\u00e9ma au POM si il \u00e9tait manquant dans la release pr\u00e9c\u00e9dente
+releasePrepare.autoVersionSubmodules.label=autoVersionSubmodules (d\u00e9fini dans le POM)
+releasePerformFromScm.scmUrl.label=URL de connexion SCM
+releasePerformFromScm.scmUsername.label=Nom d''utilisateur SCM
+releasePerformFromScm.scmPassword.label=Mot de passe SCM
+releasePerformFromScm.scmTag.label=SCM Tag
+releasePerformFromScm.scmTagBase.label=SCM Tag Base
+releasePerformFromScm.goals.label=Perform Goals
+releasePerformFromScm.useReleaseProfile.label=Utilisation du profile "release"
+releasePerformFromScm.buildEnvironment.label=Environment de construction
+releasePerformFromScm.page.title=Continuum - Effectuer la "release" du projet
+releasePerformFromScm.section.title=Effectuer la "release" du projet
+releasePerformFromScm.parameters.section.title=Param\u00e8tres de r\u00e9alisation de la release
 
 # ----------------------------------------------------------------------
 # Page: User
@@ -672,22 +755,28 @@
 # ----------------------------------------------------------------------
 # Page: Profiles List
 # ----------------------------------------------------------------------
-profilesList.page.title= Environnements de Build
-profilesList.section.title= Environnements de Build
+profilesList.page.title= Environnements de construction
+profilesList.section.title= Environnements de construction
+profilesList.installations.label = Installations
+profilesList.buildAgentGroup.label = Groupe d''agents de construction
 
 # ----------------------------------------------------------------------
 # Page: Profile Edit
 # ----------------------------------------------------------------------
-profile.page.title= Continuum - Environnement de Build
-profile.section.title = Environnement de Build
-profile.name.label= Nom de l'environnement de Build
+profile.page.title= Continuum - Environnement de construction
+profile.section.title = Environnement de construction
+profile.name.label= Nom de l'environnement de construction
 profile.jdk.name.label = Nom du JDK
 profile.jdk.name.message = Le nom du JDK
 profile.jdk.path.label = Chemin du JDK
 profile.jdk.path.message = Le Chemin du JDK (Valeur de JAVA_HOME)
 profile.no.installations = Aucune installation disponible
-profile.name.already.exists = Un environnement de Build avec le meme nom existe deja.
+profile.name.already.exists = Un environnement de construction avec le m\u00eame nom existe d\u00e9j\u00e0.
 profile.name.required = Vous devez sp\u00e9cifier un nom.
+profile.remove.error = L''environnement de construction ne peut \u00eatre supprim\u00e9, il est probablement utilis\u00e9 par une d\u00e9finition de build.
+profile.installation.name.label = Nom d'installation
+profile.actionError = Action Error
+profile.build.agent.group = Groupe d''agents de construction
 
 # ----------------------------------------------------------------------
 # Page: Installations List
@@ -699,18 +788,19 @@
 # Page: Installation Edit
 # ----------------------------------------------------------------------
 installation.page.title = Continuum - Installation
-installation.section.title = Continuum - Installation
+installation.section.title = Installation
 installation.name.label = Nom
 installation.type.label = Type
 installation.value.label = Valeur/Chemin
 installation.varName.label = Nom de variable d''environnement
 installation.jdk.type.label = JDK
-installation.maven2.type.label = Maven 2
+installation.maven2.type.label = Maven
 installation.maven1.type.label = Maven 1
 installation.envvar.type.label = ariable d''environnement
 installation.ant.type.label = ANT
-installation.automaticProfile.label=Cr\u00e9er un Environnement de Build avec le nom de l''installation
+installation.automaticProfile.label=Cr\u00e9er un environnement de construction avec le nom de l''installation
 installation.name.duplicate = Une Installation avec le meme nom existe deja.
+installation.varName.required = Vous devez d\u00e9finir une variable d''environnement
 
 # ----------------------------------------------------------------------
 # Page: Installations Type Choice
@@ -722,6 +812,13 @@
 installationTypeChoice.envar.label = Variable d''environnement 
 
 # ----------------------------------------------------------------------
+# Page: Delete Installation
+# ----------------------------------------------------------------------
+deleteInstallation.page.title = Continuum - Suppression de l''installation
+deleteInstallation.section.title = Suppression de l''installation
+deleteInstallation.confirmation.message = Etes-vous s\u00fbr de vouloir supprimer l''installation "{0}" ?
+
+# ----------------------------------------------------------------------
 # Page: Build Definitions Templates Summary
 # ----------------------------------------------------------------------
 buildDefinition.templates.page.title = Continuum - Mod\u00e8les de d\u00e9finitions de construction
@@ -730,7 +827,7 @@
 buildDefinition.templates.arguments = Arguments
 buildDefinition.templates.buildFile = Fichier de construction
 buildDefinition.templates.schedule = Planification
-buildDefinition.templates.profile = Environnement de Build
+buildDefinition.templates.profile = Environnement de construction
 buildDefinition.templates.buildFresh = Extraction compl\u00e8te
 buildDefinition.templates.alwaysBuild = Toujours construire
 buildDefinition.templates.description = Description
@@ -742,13 +839,13 @@
 # Page: Edit Build Definition Template
 # ----------------------------------------------------------------------
 buildDefinition.template.page.title = Continuum - Mod\u00e8le de d\u00e9finitions de construction
-buildDefinition.template.section.title = Mod\u00e8le de d\u00e9finition de lacontruction
+buildDefinition.template.section.title = Mod\u00e8le de d\u00e9finition de la construction
 buildDefinition.template.name = Nom
 buildDefinition.template.buildDefinition.goals = Goals
 buildDefinition.template.buildDefinition.arguments = Arguments
 buildDefinition.template.buildDefinition.buildFile = Fichier de construction
 buildDefinition.template.buildDefinition.schedule = Planification
-buildDefinition.template.buildDefinition.profile = Environnement de Build
+buildDefinition.template.buildDefinition.profile = Environnement de construction
 buildDefinition.template.buildDefinition.buildFresh = Extraction compl\u00e8te ?
 buildDefinition.template.buildDefinition.default = D\u00e9faut
 buildDefinition.template.buildDefinition.description = Description
@@ -759,17 +856,26 @@
 buildDefinitionTemplate.builddefinitions.define = Configurer les d\u00e9finitions de constructions utilis\u00e9es
 
 # ----------------------------------------------------------------------
-# Page: Build Queue
+# Page: Delete Build Definition Template
+# ----------------------------------------------------------------------
+deletebuildDefinition.template.page.title = Continuum - Suppression du template de d\u00e9finition de construction
+deletebuildDefinition.template.section.title = Suppression du template de d\u00e9finition de construction
+deletebuildDefinition.template.confirmation.message = Etes-vous s\u00fbr de vouloir supprimer le template de d\u00e9finition de build "{0}"?
+
+# ----------------------------------------------------------------------
+# Page: Queues
 # ----------------------------------------------------------------------
 buildQueue.page.title = Continuum - Liste de constructions
 buildQueue.section.title = Continuum - Liste de constructions
 buildQueue.empty = La Liste de constructions est vide
 buildQueue.currentTask.section.title = Construction en cours
+buildQueue.currentTask.buildQueue = File d''attente de construction
 buildQueue.currentTask.projectName = Nom du Projet
 buildQueue.currentTask.buildDefinition = D\u00e9finition de la construction
 buildQueue.no.currentTaks = Aucune construction en cours
 buildQueue.removeEntries = Annuler les entr\u00e9es
 checkoutQueue.currentTask.section.title = Extraction en cours
+checkoutQueue.currentTask.buildQueue = File d''attente de construction
 checkoutQueue.currentTask.projectName = Nom du projet
 checkoutQueue.no.currentTaks = Aucune extraction en cours
 checkoutQueue.section.title = Extractions en attente
@@ -777,10 +883,16 @@
 checkoutQueue.removeEntries = Annuler les entr\u00e9es
 
 # ----------------------------------------------------------------------
+# Page: Build Queue
+# ----------------------------------------------------------------------
+buildQueue.cannot.delete = Impossible de supprimer la liste des construction en attente, la tache est en cours d''ex\u00e9cution.
+buildQueue.delete.error = Impossible de supprimer la liste des construction en attente dans la base de donn\u00e9es.
+
+# ----------------------------------------------------------------------
 # Page: Confirm Delete BuildResult(s)
 # ----------------------------------------------------------------------
-buildResult.delete.confirmation.page.title = Continuum - Supprimer les r\u00e9sultats de contructions
-buildResult.delete.confirmation.section.title = Supprimer les r\u00e9sultats de contructions
+buildResult.delete.confirmation.page.title = Continuum - Supprimer les r\u00e9sultats de constructions
+buildResult.delete.confirmation.section.title = Supprimer les r\u00e9sultats de constructions
 buildResult.delete.confirmation.message = Voulez-vous vraiment supprimer les r\u00e9sultats de construction {0}\u00a0? 
 buildResult.cannot.delete = Impossible de supprimer un r\u00e9sultat de construction qui est actuellement en construction.
 
@@ -802,11 +914,10 @@
 legend.buildInFailure=Construction en \u00e9chec
 legend.buildInError=Construction en erreur
 
-
 # ----------------------------------------------------------------------
 # Page: Wait
 # ----------------------------------------------------------------------
-wait.addprocessing.processing = L'ajout du projet est en cours ...
+wait.addprocessing.processing = L''ajout du projet est en cours ...
 
 # ----------------------------------------------------------------------
 # Page: DeleteProjects
@@ -818,6 +929,298 @@
 # ----------------------------------------------------------------------
 # Page: Confirm Delete Build Env
 # ----------------------------------------------------------------------
-deleteBuildEnv.page.title = Continuum - Supprimer des Build Environment
-deleteBuildEnv.section.title = Supprimer un Build Environment
-deleteBuildEnv.confirmation.message = Etes vous s\u00fbr de vouloir supprimer le Build Environment "{0}" ?
\ No newline at end of file
+deleteBuildEnv.page.title = Continuum - Supprimer des environnement de construction
+deleteBuildEnv.section.title = Supprimer un environnement de construction
+deleteBuildEnv.confirmation.message = Etes vous s\u00fbr de vouloir supprimer l''environnement de construction "{0}" ?
+
+#-----------------------------------------------------------------------
+# Page: Local Repositories
+#-----------------------------------------------------------------------
+repositories.page.title = Continuum - Repositories local
+repositories.section.title = Repositories local
+repositories.table.name = Nom
+repositories.table.location = Emplacement
+repositories.table.layout = Layout
+
+#-----------------------------------------------------------------------
+# Page: Add/Edit Local Repository
+#-----------------------------------------------------------------------
+repository.page.title = Continuum - Ajout/Edition du repository local
+repository.section.title = Ajout/Edition du repository local
+repository.name.label = Nom
+repository.location.label = Emplacement
+repository.layout.label = Layout
+repository.error.name.unique = Le nom du repository local doit \u00eatre unique
+repository.error.name.cannot.be.spaces = Le nom du repository local ne peut \u00eatre constitu\u00e9 uniquement d''espaces
+repository.error.location.unique = L''emplacement du repository local doit \u00eatre unique
+repository.error.location.cannot.be.spaces = L''emplacement du repository local ne peut \u00eatre constitu\u00e9 uniquement d''espaces
+repository.error.save.in.use = Impossible d''utiliser le repository local car il est actuellement utilis\u00e9
+repository.error.remove.in.use = Impossible de supprimer le repository local car il est actuellement utilis\u00e9
+repository.error.purge.in.use = Impossible de purger le repository local car il est actuellement utilis\u00e9
+repository.error.remove.default = Impossible de supprimer le repository local par d\u00e9faut.
+
+#-----------------------------------------------------------------------
+# Page: Delete Local Repository
+#-----------------------------------------------------------------------
+deleteRepository.page.title = Continuum - Suppression du repository local
+deleteRepository.section.title = Suppression du repository local
+deleteRepository.confirmation.message = Etes vous s\u00fbr de vouloir supprimer le repository local "{0}" ?
+
+#-----------------------------------------------------------------------
+# Page: Purge Configurations
+#-----------------------------------------------------------------------
+purgeConfigs.page.title = Continuum - Configuration des purges
+purgeConfigs.repo.section.title = Configuration de purge de repository
+purgeConfigs.dir.section.title = Configuration de purge de r\u00e8pertoires
+purgeConfigs.table.repository = Repository
+purgeConfigs.table.description = Description
+purgeConfigs.table.retentionCount = Nombre conserv\u00e9
+purgeConfigs.table.schedule = Planification
+purgeConfigs.table.daysOlder = Nombre de jour conserv\u00e9
+purgeConfigs.table.deleteAll = Supprimer tout
+purgeConfigs.table.directoryType = Type de r\u00e9pertoire
+purgeConfigs.table.default = Defaut
+purgeConfigs.table.enabled = Activ\u00e9
+purgeConfigs.table.buildAgent = Agent de construction
+purgeConfigs.table.deleteReleasedSnapshots = Suppression des snapshots "releas\u00e9"
+
+#-----------------------------------------------------------------------
+# Page: Add/Edit Purge Configuration
+#-----------------------------------------------------------------------
+purgeConfig.page.title = Continuum - Ajout/suppression de la configuration de purge
+purgeConfig.section.title = Ajout/suppression de la configuration de purge
+purgeConfig.repository.label = Repository
+purgeConfig.directoryType.label = Type de r\u00e9pertoire
+purgeConfig.retentionCount.label = Nombre de fichiers gard\u00e9s en r\u00e9tention
+purgeConfig.daysOlder.label = Nombre de jour conserv\u00e9
+purgeConfig.deleteAll.label = Supprimer tout
+purgeConfig.deleteReleasedSnapshots.label = Suppression des snapshots "releas\u00e9"
+purgeConfig.defaultPurge.label = Est-cela configuration par d\u00e9faut
+purgeConfig.schedule.label = Planification
+purgeConfig.description.label = Description
+purgeConfig.enabled.label = Activ\u00e9
+purgeConfig.no.repositories = Pas de repositories \u00e0 purger
+purgeConfig.buildAgent.label = Agent de construction
+
+
+#-----------------------------------------------------------------------
+# Page: Delete Purge Configuration
+#-----------------------------------------------------------------------
+deletePurgeConfiguration.page.title = Continuum - Suppression de la configuration de purge
+deletePurgeConfiguration.section.title = Suppression de la configuration de purge
+deletePurgeConfiguration.confirmation.message = Etes-vous s\u00fbr de vouloir supprimer la configuration de purge "{0}" ?
+
+# ----------------------------------------------------------------------
+# Page: Release Results
+# ----------------------------------------------------------------------
+projectGroup.releaseResults.section.title = R\u00e9sultats de release du groupe "{0}"
+releaseResults.viewResult = Voir le r\u00e9sultat
+releaseResults.state = Etat
+releaseResults.startTime = Date de d\u00e9but
+releaseResults.endTime = Date de fin
+releaseResults.success = SUCCESS
+releaseResults.error = ERREUR
+releaseResults.project = Nom du project
+releaseResults.releaseGoal = Tache de release
+
+# ----------------------------------------------------------------------
+# Page: Confirm Delete Release Results
+# ----------------------------------------------------------------------
+deleteReleaseResults.page.title = Continuum - Suppression des r\u00e9sultats de release
+deleteReleaseResults.section.title = Suppression des r\u00e9sultats de release
+deleteReleaseResults.confirmation.message = Etes-vous s\u00fbr de vouloir supprimer les r\u00e9sultats de release {0}?
+
+# ----------------------------------------------------------------------
+# Component: Failure
+# ----------------------------------------------------------------------
+failureComponent.section.title = Le rendu de ce composant  \u00e0 \u00e9chou\u00e9
+
+# ----------------------------------------------------------------------
+# Component: Project Group Notifier Summary
+# ----------------------------------------------------------------------
+projectGroupNotifierSummaryComponent.groupNotifiers = Notifications du groupe de projet {0}
+projectGroupNotifierSummaryComponent.projectNotifiers = Notifications de projet
+
+# ----------------------------------------------------------------------
+# Page: ScmResult
+# ----------------------------------------------------------------------
+scmResult.page.title = Continuum - R\u00e9sultat SCM
+scmResult.section.title = R\u00e9sultat SCM
+scmResult.state = Etat
+scmResult.projectGroupName = Nom du groupe de projet
+scmResult.scmRootAddress = URL racine SCM
+scmResult.scmError = Erreur SCM
+
+# ----------------------------------------------------------------------
+# Page: Appearance
+# ----------------------------------------------------------------------
+appearance.page.title = Configuration de l''apparence
+appearance.section.title = Apparence
+appearance.companyDetails = D\u00e9tails de l''organisation
+appearance.description = Le logo dans l''angle droit en haut est g\u00e9r\u00e9 par votre POM d''organisation s\u00e9lectionn\u00e9.
+appearance.noCompanyPom = Vous n''avez pas sp\u00e9cifi\u00e9 de POM d''organisation.
+appearance.selectCompanyPom = S\u00e9lectionner un POM d''organisation
+appearance.detailsIntroduction = Votre POM d''organisation est ci-dessous.
+appearance.maybeChange = Si vous voulez changer le nom, l''url ou le logo de l''organisation, vous pouvez
+appearance.editThePomLink = Edition du POM
+appearance.companyPom.groupId = Group ID
+appearance.companyPom.artifactId = Artifact ID
+appearance.companyPom.version = Version
+appearance.editCompanyPom = Edition du POM d''organisation
+appearance.companyPom.section.title = Information du POM
+appearance.companyPom.organizationName.label = Name
+appearance.companyPom.organizationUrl.label = URL
+appearance.companyPom.organizationLogoUrl.label = URL du logo
+appearance.companyPomDoesNotExist = Le POM d''organisation ''{0}'' n''existe pas.
+appearance.createCompanyPom = Creation du POM d''organisation
+appearance.htmlContent.label = Contenu HTML
+appearance.enterCompanyPom = Entrer les d\u00e9tails du super POM de l''organisation ci-dessous. Si il existe, le nom, l'URL et le logo seront lu \u00e0 partir de celui-ci.
+appearance.footerContent = Contenu du pied de page
+
+# ----------------------------------------------------------------------
+# Page: Edit Company POM
+# ----------------------------------------------------------------------
+companyPom.page.title = Edition du POM d''organisation
+companyPom.section.title = POM d''organisation
+companyPom.autoIncrementVersion = La version sera automatiquement incr\u00e9ment\u00e9e lorsque vous sauvegarderez ce formulaire.
+companyPom.organization = Organisation
+
+# ----------------------------------------------------------------------
+# Page: Parallel Build Queue List
+# ----------------------------------------------------------------------
+parallel.build.queues.page.title= Continumm - File d''attente des construction parall\u00e8les
+parallel.build.queues.section.title= Continuum - File d''attente des construction parall\u00e8les
+
+# ----------------------------------------------------------------------
+# Page: Parallel Build Edit
+# ----------------------------------------------------------------------
+parallel.build.queue.page.title= Continuum - Ajout/suppression d''une file d''attente des construction parall\u00e8les
+parallel.build.queue.section.title=Continuum - Ajout/suppression d''une file d''attente des construction parall\u00e8les
+parallel.build.queue.name = Nom
+
+# ----------------------------------------------------------------------
+# Page: Delete Parallel Build Queue
+# ----------------------------------------------------------------------
+deleteBuildQueue.page.title = Continuum - Suppression de la file d''attente des construction parall\u00e8les
+deleteBuildQueue.section.title = Suppression de la file d''attente des construction parall\u00e8les
+deleteBuildQueue.confirmation.message = Etes-vous s\u00fbr de vouloir supprimer la file d'attente "{0}"?
+
+# ----------------------------------------------------------------------
+# Page: BuildAgents
+# ----------------------------------------------------------------------
+buildAgents.page.title = Continuum - Agents de construction
+buildAgents.section.title = Agents de construction
+buildAgents.table.url = URL de l''agent de construction
+buildAgents.table.description = Description
+buildAgents.table.enabled = Activ\u00e9
+buildAgents.empty = Pas d''agent de construction
+
+buildAgentGroups.section.title = Groupes d''agents de construction
+buildAgentGroups.table.name = Nom
+buildAgentGroups.table.agents = Agents de construction
+
+# ----------------------------------------------------------------------
+# Page: Add/Edit BuildAgent
+# ----------------------------------------------------------------------
+buildAgent.page.title = Continuum - Ajout/Modification d''agent de construction
+buildAgent.section.title = Ajout/Modification d''agent de construction
+buildAgent.url.label = URL de l''agent de construction
+buildAgent.description.label = Description
+buildAgent.enabled.label = Activ\u00e9
+buildAgent.error.doesnotexist = L''agent de construction n''existe pas
+buildAgent.error.duplicate = L''agent de construction existe d\u00e9j\u00e0
+buildAgent.error.remove.in.use = L''agent de construction ne peut \u00eatre supprim\u00e9, il est probablement utilis\u00e9 par un groupe d''agent de construction.
+
+# ----------------------------------------------------------------------
+# Page: View BuildAgent
+# ----------------------------------------------------------------------
+viewBuildAgent.page.title = Continuum - Voir l''agent de construction
+viewBuildAgent.section.title = Agent de construction
+viewBuildAgent.installations.title = Installations disponible
+viewBuildAgent.installations.name=Nom
+viewBuildAgent.installations.type=Type
+viewBuildAgent.installations.varName=Nom de la variable d''environnement
+viewBuildAgent.installations.varValue=Valeur/Chemin
+
+# ----------------------------------------------------------------------
+# Page: Delete BuildAgent
+# ----------------------------------------------------------------------
+deleteBuildAgent.page.title = Continuum - Suppression de l''agent de construction
+deleteBuildAgent.section.title = Suppression de l''agent de construction
+deleteBuildAgent.confirmation.message = Etes-vous s\u00fbr de vouloir supprimer l''agent de construction {0} ?
+
+# ----------------------------------------------------------------------
+# Page: View Distributed Build
+# ----------------------------------------------------------------------
+distributedBuilds.page.title = Continuum - Voir les constructions distribu\u00e9es
+distributedBuilds.section.title = Voir les constructions distribu\u00e9es
+distributedBuilds.buildQueue.section.title = File d''attente de construction
+distributedBuild.table.projectGroupName = Nom du groupe de projet
+distributedBuild.table.scmRootAddress = Addresse de la racine SCM
+distributedBuild.table.agentUrl = URL de l''agent de construction
+distributedBuilds.empty = Pas de construction distribu\u00e9e
+distributedBuilds.removeEntries = Annuler les entr\u00e9es
+
+# ----------------------------------------------------------------------
+# Page: Delete BuildAgentGroup
+# ----------------------------------------------------------------------
+deleteBuildAgentGroup.page.title = Continuum - Suppression du groupe d''agents de construction
+deleteBuildAgentGroup.section.title = Suppression du groupe d''agents de construction
+deleteBuildAgentGroup.confirmation.message = Etes-vous s\u00fbr de vouloir supprimer le groupe d''agents de construction {0} ?
+
+# ----------------------------------------------------------------------
+# Page: Add/Edit BuildAgentGroup
+# ----------------------------------------------------------------------
+buildAgentGroup.page.title = Continuum - Ajout/suppression de groupe d''agents de construction
+buildAgentGroup.section.title = Ajout/suppression de groupe d''agents de construction
+buildAgentGroup.name.label = Nom
+buildAgentGroup.agents.label = Agents
+buildAgentGroup.error.doesnotexist = Le groupe d''agents de construction n''existe pas.
+buildAgentGroup.error.duplicate = Le groupe d''agents de construction existe d\u00e9j\u00e0.
+buildAgentGroup.error.name.required = Le nom du groupe d''agents de construction est requis.
+buildAgentGroup.error.name.cannot.be.spaces = Le nom du groupe d''agents de construction ne peut contenir uniquement des espaces.
+buildAgentGroup.available.buildAgents = --- Agents de construction disponible ---
+buildAgentGroup.available.buildAgents.used = --- Agents de construction utilis\u00e9s ---
+buildAgentGroup.buildAgents.define = Configuration des agents de construction utilis\u00e9s
+buildAgentGroup.error.remove.in.use = Le groupe d''agents de construction utilis\u00e9 ne peut \u00eatre supprim\u00e9, Il est probablement utilis\u00e9 par un environnement de construction.
+
+# ----------------------------------------------------------------------
+# Page: View Distributed Releases
+# ----------------------------------------------------------------------
+releases.page.title = Continuum - Voir les releases
+releases.section.title = Voir les releases
+releaseSummary.table.releaseId = Release ID
+releaseSummary.table.releaseGoal = Release Goal
+releaseSummary.table.buildAgentUrl = URL de l''agent de construction
+
+# ----------------------------------------------------------------------
+# Page: Continuum Distributed Build Release Support
+# ----------------------------------------------------------------------
+distributedBuild.releasePrepare.input.error = Impossible d''obtenir les param\u00e8tres du plugin de release car l''agent de construction {0} est soit supprim\u00e9, soit d\u00e9sactiv\u00e9 ou qu'aucune construction n''a encore \u00e9t\u00e9 effectu\u00e9e par l''agent de construction.
+distributedBuild.releasePrepare.error = Impossible de pr\u00e9parer la release.
+distributedBuild.releasePrepare.release.error = Impossible de pr\u00e9parer la release car l''agent de construction {0} est soit supprim\u00e9, soit d\u00e9sactiv\u00e9
+distributedBuild.releaseInProgress.error = Impossible de voir la progression de la release car l''agent de construction {0} est soit supprim\u00e9, soit d\u00e9sactiv\u00e9
+distributedBuild.releaseViewResult.error = Impossible de voir le r\u00e9sultat de la release car l''agent de construction {0} est soit supprim\u00e9, soit d\u00e9sactiv\u00e9
+distributedBuild.releaseCleanup.error = Impossible de nettoyer la release car l''agent de construction {0} est soit supprim\u00e9, soit d\u00e9sactiv\u00e9
+distributedBuild.releasePerform.input.error = Impossible d''obtenir les param\u00e8tres du plugin de release car l''agent de construction {0} est soit supprim\u00e9, soit d\u00e9sactiv\u00e9
+distributedBuild.releasePerform.release.error = Impossible de r\u00e9aliser la "release" car l''agent de construction {0} est soit supprim\u00e9, soit d\u00e9sactiv\u00e9
+
+# ----------------------------------------------------------------------
+# Page: Authorization Error
+# ----------------------------------------------------------------------
+authorizationError.page.title = Continuum - Erreur d''authorisation
+authorizationError.section.title = Erreur d''authorisation
+authorizationError.not.authorized = Vous n''\u00eates pas authoris\u00e9 \u00e0 acc\u00e9der \u00e0 cette page. S''il vous pla\u00eet, contactez vous administrateur pour obtenir des permissions appropri\u00e9s.
+
+# ----------------------------------------------------------------------
+# Page: Error Occured
+# ----------------------------------------------------------------------
+errorOccured.page.title = Continuum - Erreur apparue
+errorOccured.section.title = Erreur apparue
+
+# ----------------------------------------------------------------------
+# Page: Release Error
+# ----------------------------------------------------------------------
+releaseError.page.title = Continuum - Erreur de release
+releaseError.section.title = Erreur de release
+releasePrepare.input.error = Impossible d''obtenir les param\u00e8tres du plugin release et de d''ex\u00e9cuter le projet - {0}
diff --git a/continuum-webapp/src/main/resources/localization/Continuum_pt_BR.properties b/continuum-webapp/src/main/resources/localization/Continuum_pt_BR.properties
index 669f117..de4d97d 100644
--- a/continuum-webapp/src/main/resources/localization/Continuum_pt_BR.properties
+++ b/continuum-webapp/src/main/resources/localization/Continuum_pt_BR.properties
@@ -25,7 +25,7 @@
 about.section.title  = Sobre Continuum
 about.version.label  = Vers\u00E3o
 about.version.number = ${project.version}
-about.buildnumber.label = Build Number
+about.buildnumber.label = N\u00FAmero da Build
 about.buildnumber = ${buildNumber}
 
 
@@ -50,17 +50,17 @@
 add.m2.project.defaultBuildDefinition            = Padr\u00E3o
 add.m2.project.m2PomFile.error                   = Voc\u00EA deve fornecer uma URL v\u00E1lida
 add.m2.project.m2PomFile.label                   = Upload do POM
-add.m2.project.m2PomFile.message                 = Informe o nome de arquivo local do POM do Maven 2 para upload (funciona somente para projetos n\u00E3o-multim\u00F3dulos).
+add.m2.project.m2PomFile.message                 = Informe o nome de arquivo local do POM do Maven para upload (funciona somente para projetos n\u00E3o-multim\u00F3dulos).
 add.m2.project.m2PomUrl.error                    = Voc\u00EA deve fornecer uma URL v\u00E1lida
 add.m2.project.m2PomUrl.label                    = Url POM
-add.m2.project.m2PomUrl.message                  = Informe a URL para o POM do Maven 2. Forne\u00E7a o usu\u00E1rio e a senha se for um recurso protegido.
+add.m2.project.m2PomUrl.message                  = Informe a URL para o POM do Maven. Forne\u00E7a o usu\u00E1rio e a senha se for um recurso protegido.
 add.m2.project.m2PomUrl.password.label           = Senha
 add.m2.project.m2PomUrl.username.label           = Usu\u00E1rio
 add.m2.project.nonRecursiveProject               = Para projeto com m\u00F3dulos, carregar somente a raiz como um build recursivo
-add.m2.project.page.title                        = Continuum - Adicionar Projeto Maven 2
+add.m2.project.page.title                        = Continuum - Adicionar Projeto Maven
 add.m2.project.projectGroup                      = Grupo de Projeto
-add.m2.project.section.title                     = Adicionar Projeto Maven 2.0+
-add.m2.project.upload.modules.error              = N\u00E3o \u00E9 poss\u00EDvel realizar upload de um projeto Maven 2 com m\u00F3dulos.
+add.m2.project.section.title                     = Adicionar Projeto Maven
+add.m2.project.upload.modules.error              = N\u00E3o \u00E9 poss\u00EDvel realizar upload de um projeto Maven com m\u00F3dulos.
 add.project.artifact.not.found.error             = N\u00E3o foi encontrado um artefato no momento do build deste POM. Verifique se o POM ancestral est\u00E1 dispon\u00EDvel ou adicione-o primeiro no Continuum.
 add.project.buildDefinitionTemplate              = Defini\u00E7\u00E3o de Build
 add.project.connect.error                        = N\u00E3o foi poss\u00EDvel conectar ao servidor remoto
@@ -82,7 +82,7 @@
 add.project.nogroup.error                        = Nenhum grupo de projeto foi fornecido.
 add.project.project.building.error               = Erro desconhecido ao realizar build do POM.
 add.project.unauthorized.error                   = Voc\u00EA n\u00E3o est\u00E1 autorizado a acessar esta URL. Verifique se as credenciais fornecidas est\u00E3o corretas.
-add.project.unknown.error                        = O recurso especificado n\u00E3o pode ser acesso. Tente novamente mais tarde ou contate seu administrador.
+add.project.unknown.error                        = O recurso especificado n\u00E3o pode ser acessado. Tente novamente mais tarde ou contate seu administrador.
 add.project.unknown.host.error                   = O host especificado \u00E9 desconhecido ou inacess\u00EDvel
 add.project.validation.protocol.not_allowed      = O recurso especificado n\u00E3o \u00E9 um arquivo ou o protocolo usado n\u00E3o \u00E9 permitido
 add.project.xml.parse.error                      = O conte\u00FAdo XML do POM n\u00E3o pode ser interpretado.
@@ -107,8 +107,8 @@
 buildDefinition.defaultForProject.label                  = \u00C9 Padr\u00E3o?
 buildDefinition.description.label                        = Descri\u00E7\u00E3o
 buildDefinition.duplicatename.save.error.message         = Ocorreu um erro ao salvar o agendamento, um agendamento com o mesmo nome j\u00E1 existe.
-buildDefinition.goals.ant.label                          = Targets
-buildDefinition.goals.maven.label                        = Goals
+buildDefinition.goals.ant.label                          = Targets Ant
+buildDefinition.goals.maven.label                        = Goals Maven
 buildDefinition.noname.save.error.message                = Ocorreu um erro ao salvar o agendamento, nenhum nome de agendamento foi fornecido.
 buildDefinition.page.title                               = Continuum - Adicionar/Editar Defini\u00E7\u00E3o de Build
 buildDefinition.profile.label                            = Perfil
@@ -119,7 +119,7 @@
 buildDefinition.template.buildDefinition.buildFresh      = \u00C9 Build Nova ?
 buildDefinition.template.buildDefinition.default         = Padr\u00E3o
 buildDefinition.template.buildDefinition.description     = Descri\u00E7\u00E3o
-buildDefinition.template.buildDefinition.goals           = Goals
+buildDefinition.template.buildDefinition.goals           = A\u00E7\u00F5es (Goals)
 buildDefinition.template.buildDefinition.profile         = Perfil
 buildDefinition.template.buildDefinition.schedule        = Agendar
 buildDefinition.template.buildDefinition.type            = Tipo
@@ -133,7 +133,7 @@
 buildDefinition.templates.buildFresh                     = \u00C9 Build Nova
 buildDefinition.templates.continuum.section.title        = Continuum Defini\u00E7\u00E3o de Build Padr\u00E3o
 buildDefinition.templates.description                    = Descri\u00E7\u00E3o
-buildDefinition.templates.goals                          = Goals
+buildDefinition.templates.goals                          = A\u00E7\u00F5es (Goals)
 buildDefinition.templates.page.title                     = Continuum - Defini\u00E7\u00F5es de modelo de Build
 buildDefinition.templates.profile                        = Perfil
 buildDefinition.templates.schedule                       = Agendar
@@ -164,9 +164,9 @@
 buildResult.buildDefinition.buildFresh        = Build Nova
 buildResult.buildDefinition.defaultForProject = \u00C9 Padr\u00E3o?
 buildResult.buildDefinition.description       = Description
-buildResult.buildDefinition.goals             = Goals
-buildResult.buildDefinition.maven.label       = POM filename
-buildResult.buildDefinition.profileName       = Profile
+buildResult.buildDefinition.goals             = A\u00E7\u00F5es (Goals)
+buildResult.buildDefinition.maven.label       = Arquivo POM
+buildResult.buildDefinition.profileName       = Perfil
 buildResult.buildDefinition.schedule          = Agendamento
 buildResult.buildDefinition.shell.label       = Execut\u00E1vel de Linha de Comando
 buildResult.buildError                        = Erro de Build
@@ -186,7 +186,7 @@
 buildResult.dependencies.artifactId           = Artifact Id
 buildResult.dependencies.changes              = Mudan\u00E7as de Depend\u00EAncias
 buildResult.dependencies.groupId              = Group Id
-buildResult.dependencies.noChanges            = No dependencies changes
+buildResult.dependencies.noChanges            = Sem mudan\u00E7as de depend\u00EAncias
 buildResult.dependencies.version              = Vers\u00E3o
 buildResult.duration                          = Dura\u00E7\u00E3o
 buildResult.endTime                           = Hora de T\u00E9rmino
@@ -235,39 +235,39 @@
 checkoutQueue.currentTask.projectName   = Nome do Projeto
 checkoutQueue.currentTask.section.title = Checkout corrente
 checkoutQueue.empty                     = Fila de Checkout vazia
-checkoutQueue.no.currentTaks            = No current checkout
-checkoutQueue.removeEntries             = Cancel Entries
-checkoutQueue.section.title             = Checkout Queue
+checkoutQueue.no.currentTaks            = Sem checkout corrente
+checkoutQueue.removeEntries             = Cancelar Entradas
+checkoutQueue.section.title             = Fila de Checkout
 
-configuration.baseUrl.label                         = Base URL
-configuration.baseUrl.message                       = Enter the base URL for the Continuum web application
-configuration.buildOutputDirectory.label            = Build Output Directory
-configuration.buildOutputDirectory.message          = Enter the build output directory of the Continuum web application
-configuration.companyLogo.message                   = Enter the company logo
-configuration.companyName.message                   = Enter the company name
-configuration.companyUrl.message                    = Enter the URL of the official company website
-configuration.deploymentRepositoryDirectory.label   = Deployment Repository Directory
-configuration.deploymentRepositoryDirectory.message = Enter the deployment repository directory of the Continuum web application
+configuration.baseUrl.label                         = URL Base
+configuration.baseUrl.message                       = Informe a URL base para a aplica\u00E7\u00E3o web Continuum
+configuration.buildOutputDirectory.label            = Diret\u00F3rio de Sa\u00EDda de Build
+configuration.buildOutputDirectory.message          = Informe o diret\u00F3rio de sa\u00EDda de build para a aplica\u00E7\u00E3o web Continuum
+configuration.companyLogo.message                   = Informe o logotipo da empresa
+configuration.companyName.message                   = Informe o nome da empresa
+configuration.companyUrl.message                    = Informe a URL do website oficial da empresa
+configuration.deploymentRepositoryDirectory.label   = Diret\u00F3rio para Reposit\u00F3rio de Artefatos
+configuration.deploymentRepositoryDirectory.message = Informe o diret\u00F3rio para reposit\u00F3rio de artefatos para a aplica\u00E7\u00E3o web Continuum
 configuration.guest.label                           = Convidados
 configuration.guest.message                         = Ativar/Desativar login como convidado
 configuration.guest.value                           = Usu\u00E1rio Convidado: <strong style="color: green;">{0}</strong>
 configuration.page.title                            = Continuum - Configura\u00E7\u00E3o
 configuration.section.title                         = Configura\u00E7\u00E3o Geral
 configuration.submit.edit                           = Editar
-configuration.workingDirectory.label                = Working Directory
-configuration.workingDirectory.message              = Enter the working directory of the Continuum web application
+configuration.workingDirectory.label                = Diret\u00F3rio de Trabalho
+configuration.workingDirectory.message              = Informe o diret\u00F3rio de trabalho para a aplica\u00E7\u00E3o web Continuum
 
 delete = Excluir
 
-deleteBuildDefinition.confirmation.message = Are you sure you want to delete the build definition "{0}"?
-deleteBuildDefinition.page.title           = Continuum - Excluir Build Definition
-deleteBuildDefinition.section.title        = Excluir Build Definition
+deleteBuildDefinition.confirmation.message = Excluir Defini\u00E7\u00E3o de Build "{0}"?
+deleteBuildDefinition.page.title           = Continuum - Excluir Defini\u00E7\u00E3o de Build
+deleteBuildDefinition.section.title        = Excluir Defini\u00E7\u00E3o de Build
 
-deleteNotifier.confirmation.message = Apagar Notificador {0} com destinat\u00E1rio "{1}"?
+deleteNotifier.confirmation.message = Excluir Notificador {0} com destinat\u00E1rio "{1}"?
 deleteNotifier.page.title           = Continuum - Excluir Notificador
 deleteNotifier.section.title        = Excluir Notificador
 
-deleteProject.confirmation.message = Apagar projeto "{0}"?
+deleteProject.confirmation.message = Excluir projeto "{0}"?
 deleteProject.page.title           = Continuum - Excluir Projeto Continuum
 deleteProject.section.title        = Excluir Projeto Continuum
 
@@ -294,7 +294,6 @@
 error.page.title        = P\u00E1gina de Erro
 error.section.title     = Ocorreu um erro interno!
 
-groups.confirmation.message = Voc\u00EA tem certeza que deseja excluir o grupo de projeto "{0}"?
 groups.manage.label         = Gerenciar Grupo
 groups.page.title           = Continuum - Resumo do Grupo
 groups.section.title        = Grupo do Projeto:
@@ -306,14 +305,14 @@
 installation.envvar.type.label       = Vari\u00E1vel de Ambiente
 installation.jdk.type.label          = JDK
 installation.maven1.type.label       = Maven 1
-installation.maven2.type.label       = Maven 2
+installation.maven2.type.label       = Maven
 installation.name.label              = Name
 installation.page.title              = Continuum - Instala\u00E7\u00E3o
 installation.section.title           = Continuum - Instala\u00E7\u00E3o
 installation.type.label              = Tipo
 installation.value.label             = Valor/Caminho
 installation.varName.label           = Nome da Vari\u00E1vel de Ambiente
-installation.name.duplicate = Installation name already exists.
+installation.name.duplicate = Nome j\u00E1 existe.
 
 installationTypeChoice.action.label  = Tipo de Instala\u00E7\u00E3o
 installationTypeChoice.envar.label   = Vari\u00E1vel de Ambiente 
@@ -334,7 +333,7 @@
 menu.account.options                         = Minha conta
 menu.add.antProject                          = Projeto Ant
 menu.add.m1Project                           = Projeto Maven 1.x
-menu.add.m2Project                           = Projeto Maven 2.0.x
+menu.add.m2Project                           = Projeto Maven
 menu.add.shellProject                        = Projeto de Linha Comando
 menu.addProject                              = Adicionar Projeto
 menu.administration                          = Administra\u00E7\u00E3o
@@ -382,25 +381,25 @@
 notifier.msn.login.label                 = Login MSN
 notifier.msn.password.label              = Senha MSN
 notifier.page.add.title                  = Continuum - Adicionar Notificador
-notifier.page.title                      = Continuum - Adicionar/Edit {0} Notificador
+notifier.page.title                      = Continuum - Adicionar/Editar {0} Notificador
 notifier.section.add.title               = Adicionar Notificador
-notifier.section.title                   = Adicionar/Edit {0} Notificador
-notifier.type.label                      = Type
-notifier.wagon.id.label                  = Server Id (defined in your settings.xml for authentication)
-notifier.wagon.url.label                 = Projeto Site URL
+notifier.section.title                   = Adicionar/Editar {0} Notificador
+notifier.type.label                      = Tipo
+notifier.wagon.id.label                  = ID Servidor (definido no seu settings.xml -> <servers> para autentica\u00E7\u00E3o)
+notifier.wagon.url.label                 = URL Site Projeto
 
 or = OU
 
-profile.jdk.name.label     = Jdk name
-profile.jdk.name.message   = The JDK name
-profile.jdk.path.label     = Jdk path
-profile.jdk.path.message   = The JDK Path (JAVA_HOME value)
-profile.name.label         = Perfil Name
-profile.no.installations   = No installations available
+profile.jdk.name.label     = Nome do Jdk
+profile.jdk.name.message   = O Nome do JDK
+profile.jdk.path.label     = Caminho do Jdk
+profile.jdk.path.message   = O Caminho do JDK (valor de JAVA_HOME)
+profile.name.label         = Nome Perfil
+profile.no.installations   = Nenhuma instala\u00E7\u00E3o dispon\u00EDvel
 profile.page.title         = Continuum - Build do Perfil
 profile.section.title      = Perfil
-profile.name.already.exists = A Profile with the same name already exists
-profile.name.required = Você deve definir um nome.
+profile.name.already.exists = Um Perfil com este nome j\u00E1 existe
+profile.name.required = O Nome do perfil \u00E9 obrigat\u00F3rio.
 
 profilesList.page.title    = Perfis de Build 
 profilesList.section.title = Perfis de Build
@@ -409,13 +408,13 @@
 
 projectEdit.page.title                = Continuum - Atualizar Projeto Continuum
 projectEdit.project.name.label        = Nome Projeto
-projectEdit.project.scmPassword.label = Senha SCM
-projectEdit.project.scmTag.label      = SCM Branch/Tag
-projectEdit.project.scmUrl.label      = SCM Url
-projectEdit.project.scmUseCache.label = Use SCM Credentials Cache, if available
-projectEdit.project.scmUsername.label = SCM Username
-projectEdit.project.version.label     = Version
-projectEdit.section.title             = Update Continuum Projeto
+projectEdit.project.scmPassword.label = Senha do SCM
+projectEdit.project.scmTag.label      = Branch/Tag do SCM
+projectEdit.project.scmUrl.label      = Url do SCM
+projectEdit.project.scmUseCache.label = Usar Credenciais SCM, se dispon\u00EDvel
+projectEdit.project.scmUsername.label = Usu\u00E1rio do SCM
+projectEdit.project.version.label     = Vers\u00E3o
+projectEdit.section.title             = Atualizar Projeto Continuum
 
 projectGroup.actions.title                       = A\u00E7\u00F5es do Grupo
 projectGroup.add.page.title                      = Continuum - Adicionar Grupo de Projeto
@@ -490,7 +489,7 @@
 projectView.buildDefinition.default     = Padr\u00E3o
 projectView.buildDefinition.description = Descri\u00E7\u00E3o
 projectView.buildDefinition.from        = De
-projectView.buildDefinition.goals       = Goals
+projectView.buildDefinition.goals       = A\u00E7\u00F5es (Goals)
 projectView.buildDefinition.profile     = Perfil
 projectView.buildDefinition.schedule    = Agendamento
 projectView.buildDefinition.type        = Tipo
@@ -557,7 +556,7 @@
 save = Salvar
 
 schedule.cronExpression.label        = Express\u00E3o Cron
-schedule.cronExpression.message      = Informe a express\u00E3o cron. O formato est\u00E1 descrito aqui: <a href="http://www.opensymphony.com/quartz/api/org/quartz/CronTrigger.html" target="_blank">Sintaxe<a>
+schedule.cronExpression.message      = Informe a express\u00E3o cron. O formato est\u00E1 descrito aqui: <a href="http://www.quartz-scheduler.org/docs/tutorials/crontrigger.html" target="_blank">Sintaxe<a>
 schedule.dayOfMonth.label            = Dia do M\u00EAs
 schedule.dayOfWeek.label             = Dia da Semana
 schedule.description.label           = Descri\u00E7\u00E3o
@@ -591,7 +590,7 @@
 
 submit = Enviar
 
-summary.buildAll             = Fazer Build Total
+summary.buildAll             = Fazer Build de Tudo
 summary.buildHistory         = Hist\u00F3rico da Build
 summary.buildNow             = Fazer Build Agora
 summary.page.title           = Continuum - Resumo
@@ -638,7 +637,7 @@
 userGroup.name.label          = Nome
 userGroup.name.message        = Informe o nome do grupo de usu\u00E1rio
 
-webwork.date = MMM dd, yyyy hh:mm:ss aaa z
+webwork.date = dd/MM/yyyy hh:mm:ss aaa z
 
 workingCopy = C\u00F3pia de Trabalho
 
@@ -649,13 +648,13 @@
 # ----------------------------------------------------------------------
 # Page: DeleteProjects
 # ----------------------------------------------------------------------
-deleteProjects.page.title = Continuum - Delete Continuum Projects
-deleteProjects.section.title = Delete Continuum Projects
-deleteProjects.confirmation.message = Are you sure you want to delete the projects "{0}"?
+deleteProjects.page.title = Continuum - Excluir Projetos Continuum
+deleteProjects.section.title = Excluir Projetos Continuum
+deleteProjects.confirmation.message = Excluir projetos "{0}"?
 
 # ----------------------------------------------------------------------
 # Page: Confirm Delete Build Env
 # ----------------------------------------------------------------------
-deleteBuildEnv.page.title = Continuum - Delete Build Environment
-deleteBuildEnv.section.title = Delete Build Environment
-deleteBuildEnv.confirmation.message = Are you sure you want to delete Build Environment "{0}" ?
\ No newline at end of file
+deleteBuildEnv.page.title = Continuum - Excluir Perfis
+deleteBuildEnv.section.title = Excluir Perfil
+deleteBuildEnv.confirmation.message = Excluir perfil "{0}" ?
diff --git a/continuum-webapp/src/main/resources/localization/Continuum_zh_CN.properties b/continuum-webapp/src/main/resources/localization/Continuum_zh_CN.properties
new file mode 100644
index 0000000..1148ed5
--- /dev/null
+++ b/continuum-webapp/src/main/resources/localization/Continuum_zh_CN.properties
@@ -0,0 +1,951 @@
+#
+# 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.
+#
+
+## version $Id$
+
+# ----------------------------------------------------------------------
+# COMMONS
+# ----------------------------------------------------------------------
+webwork.date=MMM dd, yyyy hh:mm:ss aaa z
+
+message.success = \u6210\u529f
+message.failed = \u5931\u8d25
+message.error = \u9519\u8bef
+enabled = \u542f\u7528
+disabled = \u7981\u7528
+cancel = \u53d6\u6d88
+submit = \u63d0\u4ea4
+edit = \u7f16\u8f91
+delete = \u5220\u9664
+build = \u6784\u5efa
+release = \u53d1\u5e03
+save = \u4fdd\u5b58
+add = \u6dfb\u52a0
+back = \u540e\u9000
+workingCopy = \u5de5\u4f5c\u62f7\u8d1d
+builds = \u6784\u5efa
+info = \u9879\u76ee\u4fe1\u606f
+or = \u6216\u8005
+selectAll = \u5168\u9009
+unselectAll = \u5168\u4e0d\u9009
+sort.descending = \u5012\u5e8f\u6392\u5e8f
+sort.ascending = \u987a\u5e8f\u6392\u5e8f
+purge = \u6e05\u9664
+
+# ----------------------------------------------------------------------
+# Page: Top
+# ----------------------------------------------------------------------
+top.logo.default = [\u8fd9\u91cc\u662f\u4f60\u7684\u516c\u53f8\u7684\u5fbd\u6807]
+# ----------------------------------------------------------------------
+# Page: Bottom
+# ----------------------------------------------------------------------
+bottom.version.number = ${pom.parent.parent.version}
+
+# ----------------------------------------------------------------------
+# Page: Menu
+# ----------------------------------------------------------------------
+menu.continuum.about = \u5173\u4e8e
+menu.continuum.showProjects = \u663e\u793a\u9879\u76ee
+menu.continuum.showProjectGroups = \u663e\u793a\u9879\u76ee\u5206\u7ec4
+menu.addProject = \u6dfb\u52a0\u9879\u76ee
+menu.add.m2Project = Maven \u9879\u76ee
+menu.add.m1Project = Maven 1.x \u9879\u76ee
+menu.add.antProject = Ant \u9879\u76ee
+menu.add.shellProject = Shell \u9879\u76ee
+menu.administration = \u7ba1\u7406
+menu.administration.configuration = \u914d\u7f6e
+menu.administration.appearance = \u5916\u89c2
+menu.administration.profile = \u6784\u5efa\u73af\u5883
+menu.administration.installations = \u5b89\u88c5
+menu.administration.schedules = \u5b89\u6392
+menu.administration.users = \u7528\u6237
+menu.administration.userGroups = \u7528\u6237\u5206\u7ec4
+menu.administration.roles = \u89d2\u8272
+menu.administration.buildDefinitionTemplates = \u6784\u5efa\u5b9a\u4e49\u6a21\u677f
+menu.account.options = \u6211\u7684\u5e10\u53f7
+user.edit.account = \u7f16\u8f91\u7528\u6237\u4fe1\u606f
+menu.administration.queues = \u961f\u5217
+menu.administration.repositories = \u672c\u5730\u4ed3\u5e93
+menu.administration.purge = \u6e05\u9664\u914d\u7f6e
+
+# ----------------------------------------------------------------------
+# Page: error
+# ----------------------------------------------------------------------
+error.page.title = Error Page
+error.section.title = An Internal Error Has Occurred!
+error.exception.message = Exception Message:
+error.message = The server was not able of performing the request. Please try again later. Contact the administrator if this problem persists.
+error.403.title = Error 403
+error.403.section.title = Resource Forbidden
+error.403.message = The URL requested results in a forbidden page.
+error.404.title = Error 404
+error.404.section.title = Resource Not Found
+error.404.message = The URL requested cannot be found.
+error.500.title = Error 500
+error.500.section.title = Internal Error
+error.500.message = The URL requested results in an internal error.
+
+# ----------------------------------------------------------------------
+# Page: About
+# ----------------------------------------------------------------------
+about.page.title = Continuum - \u5173\u4e8e
+about.section.title = \u5173\u4e8e Continuum
+about.version.label = \u7248\u672c
+about.version.number = ${project.version}
+about.buildnumber.label = Build Number
+about.buildnumber = ${buildNumber}
+
+# ----------------------------------------------------------------------
+# Page: Login
+# ----------------------------------------------------------------------
+login.page.title = Continuum - \u8ba4\u8bc1
+login.section.title = \u8ba4\u8bc1
+login.username = \u7528\u6237\u540d
+login.password = \u5bc6\u7801
+login.rememberMe = \u8bb0\u4f4f\u6211
+login.submit = \u8fde\u63a5
+
+# ----------------------------------------------------------------------
+# Page: Summary
+# ----------------------------------------------------------------------
+summary.page.title = Continuum - \u6982\u8ff0
+summary.section.title = Continuum \u9879\u76ee
+summary.projectTable.name = \u9879\u76ee\u540d\u79f0
+summary.projectTable.version = \u7248\u672c
+summary.projectTable.build = \u6784\u5efa
+summary.projectTable.group = \u5206\u7ec4
+summary.projectTable.lastBuildDateTime = \u6700\u540e\u4e00\u6b21\u6784\u5efa\u65f6\u95f4
+summary.buildAll = \u6784\u5efa\u6240\u6709
+summary.buildHistory = \u6784\u5efa\u5386\u53f2
+summary.buildNow = \u7acb\u5373\u6784\u5efa
+
+# ----------------------------------------------------------------------
+# Page: Group Summary
+# ----------------------------------------------------------------------
+groups.page.title = Continuum - \u5206\u7ec4\u6982\u8981
+groups.page.section.title = \u9879\u76ee\u5206\u7ec4
+groups.table.name = \u540d\u79f0
+groups.table.groupId = \u5206\u7ec4&nbsp;Id
+groups.table.totalProjects = \u6240\u6709
+groups.table.summary = \u6982\u8981
+groups.page.list.empty = \u9879\u76ee\u5206\u7ec4\u5217\u8868\u662f\u7a7a\u7684\u3002
+groups.section.title = \u9879\u76ee\u5206\u7ec4\uff1a
+groups.manage.label = \u7ba1\u7406\u5206\u7ec4
+groups.table.repositoryName = \u672c\u5730\u4ed3\u5e93
+
+# ----------------------------------------------------------------------
+# Page: Project Group
+# ----------------------------------------------------------------------
+projectGroup.page.title = Continuum - \u9879\u76ee\u5206\u7ec4
+projectGroup.information.title = \u9879\u76ee\u5206\u7ec4\u4fe1\u606f
+projectGroup.name.label = \u9879\u76ee\u5206\u7ec4\u540d\u79f0
+projectGroup.groupId.label = \u9879\u76ee\u5206\u7ec4 Id
+projectGroup.description.label = \u63cf\u8ff0
+projectGroup.url.label = \u9996\u9875 Url
+projectGroup.projects.title = \u5b50\u9879\u76ee
+projectGroup.tab.summary = \u9879\u76ee\u5206\u7ec4\u6982\u8981
+projectGroup.tab.members = \u5b50\u9879\u76ee
+projectGroup.tab.buildDefinitions = \u6784\u5efa\u5b9a\u4e49
+projectGroup.tab.notifiers = \u901a\u77e5
+projectGroup.actions.title = Group Actions
+projectGroup.release.error.emptyGroup = \u4e0d\u80fd\u53d1\u5e03\u4e00\u4e2a\u7a7a\u7ec4\u3002
+projectGroup.release.error.severalParentProjects = \u4e0d\u80fd\u5728\u540c\u4e00\u4e2a\u9879\u76ee\u5206\u7ec4\u5185\u540c\u65f6\u53d1\u5e03\u4e24\u4e2a\u6216\u8005\u591a\u4e2a\u7236\u9879\u76ee\u3002
+projectGroup.release.error.projectNotInSuccess = \u4e0d\u80fd\u53d1\u5e03\u9879\u76ee\u5206\u7ec4\uff1a\u7ec4\u5185\u7684\u4e00\u4e2a\u6216\u8005\u591a\u4e2a\u9879\u76ee\u6ca1\u6709\u6784\u5efa\u6210\u529f\u3002
+projectGroup.deleteGroup = \u5220\u9664\u9879\u76ee\u5206\u7ec4
+projectGroup.buildGroup = \u6784\u5efa\u6240\u6709\u9879\u76ee
+projectGroup.buildGroupNow = Build Group Now\u7acb\u5373\u6784\u5efa\u9879\u76ee\u5206\u7ec4
+projectGroup.deleteProjects = \u5220\u9664\u9879\u76ee
+projectGroup.buildProjects = \u6784\u5efa\u9879\u76ee
+projectGroup.cancelBuilds = \u53d6\u6d88\u6784\u5efa
+projectGroup.buildsStatut.title = \u9879\u76ee\u7ec4\u5185\u6700\u540e\u4e00\u6b21\u6784\u5efa\u7ed3\u679c\u6982\u8ff0
+projectGroup.buildsStatut.errors = \u9519\u8bef
+projectGroup.buildsStatut.failures = \u5931\u8d25
+projectGroup.buildsStatut.success = \u6210\u529f
+projectGroup.buildDefinition.label = \u9ed8\u8ba4\u6784\u5efa\u5b9a\u4e49
+projectGroup.addProject.label = \u6dfb\u52a0\u65b0\u7684\u9879\u76ee
+projectGroup.releaseNow = \u53d1\u5e03\u7ec4
+projectGroup.repository.label = \u672c\u5730\u4ed3\u5e93
+projectGroup.tab.releaseResults = \u53d1\u5e03\u7ed3\u679c
+projectGroup.scmRoot.title = \u9879\u76ee\u5206\u7ec4Scm\u6839
+projectGroup.scmRoot.label = Scm\u6839URL
+projectGroup.cancelGroupBuild = \u53d6\u6d88\u7ec4\u6784\u5efa
+
+# ----------------------------------------------------------------------
+# Page: Project Group - Members
+# ----------------------------------------------------------------------
+projectGroup.members.section.title = \u7ec4 {0} \u7684\u5b50\u9879\u76ee
+projectGroup.members.users.title = \u7528\u6237
+projectGroup.members.users.search.label = \u7528\u6237\u641c\u7d22
+projectGroup.members.users.search.button = \u641c\u7d22
+projectGroup.members.user.role.administrator = \u7ba1\u7406\u5458
+projectGroup.members.user.role.developer = \u5f00\u53d1\u8005
+projectGroup.members.user.role.user = \u7528\u6237
+
+# ----------------------------------------------------------------------
+# Page: Add Project Group
+# ----------------------------------------------------------------------
+projectGroup.add.page.title = Continuum - \u6dfb\u52a0\u9879\u76ee\u5206\u7ec4
+projectGroup.add.section.title = \u6dfb\u52a0\u9879\u76ee\u5206\u7ec4
+projectGroup.error.name.required = \u9879\u76ee\u5206\u7ec4\u540d\u79f0\u5fc5\u586b\u3002
+projectGroup.error.name.cannot.be.spaces = \u9879\u76ee\u5206\u7ec4\u540d\u79f0\u4e0d\u80fd\u4ec5\u7531\u7a7a\u683c\u7ec4\u6210\u3002
+projectGroup.error.name.already.exists = \u9879\u76ee\u5206\u7ec4\u540d\u79f0\u5df2\u7ecf\u5b58\u5728\u3002
+projectGroup.error.groupId.required = \u9879\u76ee\u5206\u7ec4ID\u5fc5\u586b\u3002
+projectGroup.error.groupId.cannot.be.spaces = \u9879\u76ee\u5206\u7ec4ID\u4e0d\u80fd\u4ec5\u7531\u7a7a\u683c\u7ec4\u6210\u3002
+projectGroup.error.groupId.already.exists = \u9879\u76ee\u5206\u7ec4ID\u5df2\u7ecf\u5b58\u5728\u3002
+
+# ----------------------------------------------------------------------
+# Page: Edit Project Group
+# ----------------------------------------------------------------------
+projectGroup.edit.page.title = Continuum - \u66f4\u65b0\u9879\u76ee\u7ec4
+projectGroup.edit.section.title = \u66f4\u65b0\u9879\u76ee\u7ec4
+projectGroup.edit.section.projects.title = \u9879\u76ee
+projectGroup.edit.project.name = \u9879\u76ee\u540d
+projectGroup.edit.move.to.group = \u79fb\u52a8\u5230\u7ec4
+project.in.checkout.queue.error = \u65e0\u6cd5\u7f16\u8f91\u8fd9\u4e2a\u9879\u76ee\u7ec4\u3002\u8fd9\u4e2a\u9879\u76ee\u7ec4\u7684\u5b50\u9879\u76ee\u4ecd\u6b63\u5728\u4ecescm\u4e2d\u68c0\u51fa\u3002
+
+# ----------------------------------------------------------------------
+# Page: Configuration
+# ----------------------------------------------------------------------
+configuration.page.title = Continuum - \u914d\u7f6e
+configuration.section.title = \u5e38\u89c4\u914d\u7f6e
+configuration.guest.label = \u6e38\u5ba2
+configuration.guest.value = \u6e38\u5ba2\u662f<strong style="color: green;">{0}</strong>
+configuration.workingDirectory.label = \u5de5\u4f5c\u76ee\u5f55
+configuration.buildOutputDirectory.label = \u6784\u5efa\u8f93\u51fa\u76ee\u5f55
+configuration.deploymentRepositoryDirectory.label = \u90e8\u7f72\u4ed3\u5e93\u76ee\u5f55
+configuration.baseUrl.label = Base URL
+configuration.submit.edit = \u7f16\u8f91
+configuration.guest.message = \u5141\u8bb8\uff0f\u7981\u6b62\u6e38\u5ba2\u767b\u5f55
+configuration.workingDirectory.message = \u8f93\u5165Continuum web\u5e94\u7528\u7a0b\u5e8f\u7684\u5de5\u4f5c\u76ee\u5f55
+configuration.buildOutputDirectory.message = \u8f93\u5165Continuum web\u5e94\u7528\u7a0b\u5e8f\u7684\u6784\u5efa\u8f93\u51fa\u76ee\u5f55
+configuration.deploymentRepositoryDirectory.message = \u8f93\u5165Continuum web\u5e94\u7528\u7a0b\u5e8f\u7684\u90e8\u7f72\u4ed3\u5e93\u76ee\u5f55
+configuration.baseUrl.message = \u8f93\u5165Continuum web\u5e94\u7528\u7a0b\u5e8f\u7684base URL
+configuration.companyName.message = \u8f93\u5165\u516c\u53f8\u540d\u79f0
+configuration.companyLogo.message = \u8f93\u5165\u516c\u53f8\u5fbd\u6807
+configuration.companyUrl.message = \u8f93\u5165\u516c\u53f8\u5b98\u65b9\u7ad9\u70b9\u7684URL
+configuration.releaseOutputDirectory.label = \u53d1\u5e03\u8f93\u51fa\u76ee\u5f55
+configuration.releaseOutputDirectory.message = \u8f93\u5165Continuum web\u5e94\u7528\u7a0b\u5e8f\u7684\u53d1\u5e03\u8f93\u51fa\u76ee\u5f55
+configuration.releaseOutputDirectory.required = \u4f60\u5fc5\u987b\u5b9a\u4e49\u4e00\u4e2a\u53d1\u5e03\u8f93\u51fa\u76ee\u5f55
+
+# ----------------------------------------------------------------------
+# Page: Add Project
+# ----------------------------------------------------------------------
+add.project.field.required.error = \u5fc5\u987b\u586b\u5199POM URL\u6216\u8005\u4e0a\u4f20\u4e00\u4e2aPOM\u3002
+add.project.unknown.host.error = \u6307\u5b9a\u7684\u4e3b\u673a\u672a\u77e5\u6216\u8005\u65e0\u6cd5\u8bbf\u95ee\u3002
+add.project.connect.error = \u65e0\u6cd5\u8fde\u63a5\u8fdc\u7a0b\u670d\u52a1\u5668
+add.project.malformed.url.error = \u63d0\u4f9b\u7684URL\u683c\u5f0f\u4e0d\u6b63\u786e\u3002
+add.project.xml.parse.error = \u65e0\u6cd5\u89e3\u6790POM\u7684XML\u5185\u5bb9\u3002
+add.project.extend.error = \u4e0d\u80fd\u4f7f\u7528\u4e00\u4e2a\u542b\u6709''extend''\u5143\u7d20\u7684POM\u3002
+add.project.missing.pom.error = POM\u6587\u4ef6\u4e0d\u5b58\u5728\u3002\u4f60\u6307\u5b9a\u7684POM\u6216\u8005\u5b83\u7684\u4e00\u4e2a\u6a21\u5757\u4e0d\u5b58\u5728\u3002
+add.project.missing.groupid.error = POM\u4e2d\u7f3a\u5c11''groupId''\u5143\u7d20\u3002
+add.project.missing.artifactid.error = POM\u4e2d\u7f3a\u5c11''artifactId''\u5143\u7d20\u3002
+add.project.missing.version.error = POM\u4e2d\u7f3a\u5c11''version''\u5143\u7d20\u3002
+add.project.missing.name.error = POM\u4e2d\u7f3a\u5c11''name''\u5143\u7d20\u3002
+add.project.missing.repository.error = POM\u4e2d\u7f3a\u5c11''repository''\u5143\u7d20\u3002
+add.project.missing.scm.error = Missing ''scm'' element in the POM, project 
+add.project.missing.scm.connection.error = POM\u4e2d''scm''\u5143\u7d20\u7f3a\u5c11''connection''\u5b50\u5143\u7d20\u3002
+add.project.missing.notifier.type.error = POM\u4e2d''notifier''\u5143\u7d20\u7f3a\u5c11''type''\u5b50\u5143\u7d20\u3002
+add.project.missing.notifier.configuration.error = POM\u4e2d''notifier''\u5143\u7d20\u7f3a\u5c11''configuration''\u5b50\u5143\u7d20\u3002
+add.project.metadata.transfer.error = \u4f20\u8f93\u5143\u6570\u636e\u5931\u8d25\u3002
+add.project.validation.protocol.not_allowed = \u6307\u5b9a\u7684\u8d44\u6e90\u4e0d\u662f\u4e00\u4e2a\u6587\u4ef6\u6216\u8005\u4f7f\u7528\u7684\u534f\u8bae\u4e0d\u88ab\u5141\u8bb8\u3002
+add.project.unauthorized.error = \u4f60\u65e0\u6743\u8bbf\u95ee\u8bf7\u6c42\u7684URL\u3002\u8bf7\u786e\u8ba4\u4f60\u63d0\u4f9b\u7684\u7528\u6237\u540d\u548c\u5bc6\u7801\u662f\u6b63\u786e\u7684\u3002
+add.project.artifact.not.found.error = \u5c1d\u8bd5\u6784\u5efaPOM\u65f6\u7f3a\u5c11\u5236\u54c1\u3002\u8bf7\u786e\u8ba4\u5b83\u7684\u7236POM\u53ef\u7528\u6216\u8005\u9996\u5148\u628a\u5b83\u52a0\u5165\u5230Continuum\u4e2d\u3002
+add.project.project.building.error = \u5c1d\u8bd5\u6784\u5efaPOM\u65f6\u53d1\u751f\u4e86\u672a\u77e5\u9519\u8bef\u3002
+add.project.unknown.error = \u6307\u5b9a\u7684\u8d44\u6e90\u65e0\u6cd5\u8bbf\u95ee\u3002\u8bf7\u7a0d\u5019\u518d\u8bd5\u6216\u8005\u548c\u7ba1\u7406\u5458\u8054\u7cfb\u3002
+add.project.nogroup.error = \u6ca1\u6709\u6307\u5b9a\u9879\u76ee\u5206\u7ec4\u3002
+
+# ----------------------------------------------------------------------
+# Page: AddMavenOneProject
+# ----------------------------------------------------------------------
+add.m1.project.page.title = Continuum - \u6dfb\u52a0Maven 1\u9879\u76ee
+add.m1.project.section.title = \u6dfb\u52a0Maven 1.x\u9879\u76ee
+add.m1.project.m1PomUrl.label = M1 POM Url
+add.m1.project.m1PomUrl.username.label = \u7528\u6237\u540d
+add.m1.project.m1PomUrl.password.label = \u5bc6\u7801
+add.m1.project.m1PomUrl.message = \u8f93\u5165Maven 1 POM\u7684URL\u3002\u5982\u679c\u662f\u53d7\u4fdd\u62a4\u7684\u8d44\u6e90\uff0c\u8bf7\u63d0\u4f9b\u7528\u6237\u540d\u548c\u5bc6\u7801\u3002
+add.m1.project.m1PomUrl.error = \u4f60\u5fc5\u987b\u8f93\u5165\u4e00\u4e2a\u6709\u6548\u7684URL
+add.m1.project.m1PomFile.label = \u4e0a\u4f20POM
+add.m1.project.m1PomFile.message =  \u8f93\u5165Maven 1 POM\u7684\u672c\u5730\u6587\u4ef6\u540d\u6765\u4e0a\u4f20
+add.m1.project.m1PomFile.error = \u4f60\u5fc5\u987b\u8f93\u5165\u4e00\u4e2a\u6709\u6548\u7684URL
+add.m1.project.projectGroup = \u9879\u76ee\u5206\u7ec4
+add.m1.project.buildDefinitionTemplate = \u6784\u5efa\u5b9a\u4e49\u6a21\u677f
+add.m1.project.defaultBuildDefinition = \u9ed8\u8ba4
+
+# ----------------------------------------------------------------------
+# Page: AddMavenTwoProject
+# ----------------------------------------------------------------------
+add.m2.project.page.title = Continuum - \u6dfb\u52a0Maven\u9879\u76ee
+add.m2.project.section.title = \u6dfb\u52a0Maven\u9879\u76ee
+add.m2.project.m2PomUrl.label = POM Url
+add.m2.project.m2PomUrl.username.label = \u7528\u6237\u540d
+add.m2.project.m2PomUrl.password.label = \u5bc6\u7801
+add.m2.project.m2PomUrl.message =  \u8f93\u5165Maven POM\u7684URL\u3002\u5982\u679c\u662f\u53d7\u4fdd\u62a4\u7684\u8d44\u6e90\uff0c\u8bf7\u63d0\u4f9b\u7528\u6237\u540d\u548c\u5bc6\u7801\u3002
+add.m2.project.m2PomUrl.error = \u4f60\u5fc5\u987b\u8f93\u5165\u4e00\u4e2a\u6709\u6548\u7684URL
+add.m2.project.m2PomFile.label = \u4e0a\u4f20POM
+add.m2.project.m2PomFile.message = \u8f93\u5165Maven POM\u7684\u672c\u5730\u6587\u4ef6\u540d\u6765\u4e0a\u4f20\uff08\u53ea\u6709\u6ca1\u6709\u6a21\u5757\u7684\u5355\u4e00\u9879\u76ee\u53ef\u4ee5\u6b63\u5e38\u5de5\u4f5c\uff09\u3002
+add.m2.project.m2PomFile.error = \u4f60\u5fc5\u987b\u8f93\u5165\u4e00\u4e2a\u6709\u6548\u7684URL
+add.m2.project.projectGroup = \u9879\u76ee\u5206\u7ec4
+# TODO: remove this part once uploading of an m2 project with modules is supported ( CONTINUUM-1098 )
+add.m2.project.upload.modules.error = \u4e0d\u80fd\u4e0a\u4f20\u4e00\u4e2a\u5e26\u6709\u6a21\u5757\u7684Maven\u9879\u76ee\u3002
+add.m2.project.nonRecursiveProject = \u5bf9\u4e8e\u591a\u6a21\u5757\u7684\u9879\u76ee\uff0c\u4ec5\u52a0\u8f7d\u6839\u7136\u540e\u9012\u5f52\u5730\u6784\u5efa
+add.m2.project.buildDefinitionTemplate = \u6784\u5efa\u5b9a\u4e49\u6a21\u677f
+add.m2.project.defaultBuildDefinition = \u9ed8\u8ba4
+
+# ----------------------------------------------------------------------
+# Page: AddProject (ant or shell)
+# ----------------------------------------------------------------------
+add.shell.project.page.title = Continuum - \u6dfb\u52a0Shell\u9879\u76ee
+add.shell.project.section.title = Continuum - \u6dfb\u52a0Shell\u9879\u76ee
+add.ant.project.page.title = Continuum - \u6dfb\u52a0Ant\u9879\u76ee
+add.ant.project.section.title = \u6dfb\u52a0Ant\u9879\u76ee
+
+projectName.label = \u9879\u76ee\u540d\u79f0
+projectName.error = \u4f60\u5fc5\u987b\u63d0\u4f9b\u9879\u76ee\u540d\u79f0
+projectName.already.exist.error = \u9879\u76ee\u540d\u79f0\u5df2\u5b58\u5728
+projectName.message = \u8f93\u5165\u9879\u76ee\u540d\u79f0
+
+projectScm.label = Scm
+projectScm.error = \u4f60\u5fc5\u987b\u9009\u62e9\u4e00\u4e2aSCM
+projectScm.message = \u9009\u62e9\u4e00\u4e2aSCM
+
+projectScmUrl.label = Scm Url
+projectScmUrl.error = \u4f60\u5fc5\u987b\u63d0\u4f9b\u4e00\u4e2ascm url
+projectScmUrl.message = \u8f93\u5165<a href="http://maven.apache.org/scm/scm-url-format.html">Maven SCM URL</a>
+
+projectScmUsername.label = Scm\u7528\u6237\u540d
+projectScmUsername.message = \u8f93\u5165scm\u7528\u6237\u540d
+
+projectScmPassword.label = Scm\u5bc6\u7801
+projectScmPassword.message = \u8f93\u5165scm\u5bc6\u7801
+
+projectScmTag.label = Scm\u5206\u652f\uff0f\u6807\u7b7e
+projectScmTag.message = \u8f93\u5165scm\u5206\u652f\uff0f\u6807\u7b7e\u540d\uff08\u5bf9\u4e8esubversion\uff0c\u6807\u7b7e\u540d\u5fc5\u987b\u5728scm URL\u4e2d\u6307\u5b9a\u800c\u4e0d\u662f\u8fd9\u4e2a\u5b57\u6bb5\uff09
+
+projectVersion.label = \u7248\u672c
+projectVersion.error = \u4f60\u5fc5\u987b\u63d0\u4f9b\u4e00\u4e2a\u7248\u672c
+projectVersion.message = \u8f93\u5165\u9879\u76ee\u7684\u7248\u672c
+
+projectScmUseCache.label = \u5982\u679c\u53ef\u7528\uff0c\u4f7f\u7528SCM\u8eab\u4efd\u8bc1\u660e\u7f13\u5b58
+add.project.buildDefinitionTemplate = \u6784\u5efa\u5b9a\u4e49\u6a21\u677f
+add.project.defaultBuildDefinition = \u9ed8\u8ba4
+
+# ----------------------------------------------------------------------
+# Page: DeleteProject
+# ----------------------------------------------------------------------
+deleteProject.page.title = Continuum - \u5220\u9664Continuum\u9879\u76ee
+deleteProject.section.title = \u5220\u9664Continuum\u9879\u76ee
+deleteProject.confirmation.message = \u4f60\u786e\u5b9a\u8981\u5220\u9664\u9879\u76ee\u201c{0}\u201d\u5417\uff1f
+
+# ----------------------------------------------------------------------
+# Page: ProjectView
+# ----------------------------------------------------------------------
+projectView.page.title = Continuum - Continuum\u9879\u76ee
+projectView.section.title = Continuum\u9879\u76ee
+projectView.project.name = \u9879\u76ee\u540d\u79f0
+projectView.project.version = \u7248\u672c
+projectView.project.scmUrl = SCM Url
+projectView.project.scmTag = SCM\u5206\u652f\uff0f\u6807\u7b7e
+projectView.project.group = \u5206\u7ec4
+projectView.project.lastBuildDateTime = \u6700\u540e\u4e00\u6b21\u6784\u5efa\u65f6\u95f4
+projectView.buildDefinitions = \u6784\u5efa\u5b9a\u4e49
+projectView.buildDefinition.goals = \u76ee\u6807
+projectView.buildDefinition.arguments = \u53c2\u6570
+projectView.buildDefinition.buildFile = \u6784\u5efa\u6587\u4ef6
+projectView.buildDefinition.profile = \u6784\u5efa\u73af\u5883
+projectView.buildDefinition.schedule = \u8ba1\u5212
+projectView.buildDefinition.type = \u7c7b\u578b
+projectView.buildDefinition.alwaysBuild = \u603b\u662f\u6784\u5efa
+buildDefinition.profile.label = \u6784\u5efa\u73af\u5883
+projectView.buildDefinition.from = \u4ece
+projectView.buildDefinition.default = \u9ed8\u8ba4
+projectView.buildDefinition.buildFresh = \u5168\u65b0\u7684\u6784\u5efa
+projectView.buildDefinition.description = \u63cf\u8ff0
+projectView.notifiers = \u901a\u77e5
+projectView.notifier.type = \u7c7b\u578b
+projectView.notifier.recipient = \u63a5\u53d7\u8005
+projectView.notifier.events = \u4e8b\u4ef6
+projectView.notifier.from = \u4ece
+projectView.dependencies = \u4f9d\u8d56
+projectView.dependency.name = \u540d\u79f0
+projectView.dependency.groupId = \u5206\u7ec4Id
+projectView.dependency.artifactId = \u5236\u54c1Id
+projectView.dependency.version = \u7248\u672c
+projectView.usedBy= \u88ab\u4f7f\u7528
+projectView.developers = \u5f00\u53d1\u8005
+projectView.developer.name = \u540d\u79f0
+projectView.developer.email = \u7535\u5b50\u90ae\u4ef6
+projectView.username = \u7528\u6237\u540d
+projectView.role.view = \u67e5\u770b
+projectView.role.edit = \u7f16\u8f91
+projectView.role.delete = \u5220\u9664
+projectView.role.build = \u6784\u5efa
+projectView.role.administer = \u7ba1\u7406
+
+# ----------------------------------------------------------------------
+# Page: ProjectEdit
+# ----------------------------------------------------------------------
+projectEdit.page.title = Continuum - \u66f4\u65b0Continuum\u9879\u76ee
+projectEdit.section.title = \u66f4\u65b0Continuum\u9879\u76ee
+projectEdit.project.name.label = \u9879\u76ee\u540d\u79f0
+projectEdit.project.version.label = \u7248\u672c
+projectEdit.project.scmUrl.label = SCM Url
+projectEdit.project.scmUsername.label = SCM\u7528\u6237\u540d
+projectEdit.project.scmPassword.label = SCM\u5bc6\u7801
+projectEdit.project.scmUseCache.label = \u5982\u679c\u53ef\u7528\uff0c\u4f7f\u7528SCM\u8eab\u4efd\u8ba4\u8bc1\u7f13\u5b58
+projectEdit.project.scmTag.label = SCM\u5206\u652f\uff0f\u6807\u7b7e
+
+# ----------------------------------------------------------------------
+# Page: BuildDefinitionEdit
+# ----------------------------------------------------------------------
+buildDefinition.page.title = Continuum - \u6dfb\u52a0\uff0f\u7f16\u8f91\u6784\u5efa\u5b9a\u4e49
+buildDefinition.section.title = \u6dfb\u52a0\uff0f\u6784\u5efa\u5b9a\u4e49
+buildDefinition.buildFile.ant.label = Ant\u6784\u5efa\u6587\u4ef6\u540d
+buildDefinition.buildFile.shell.label = Shell\u53ef\u6267\u884c\u7684
+buildDefinition.buildFile.maven.label = POM\u6587\u4ef6\u540d
+buildDefinition.goals.ant.label = \u76ee\u6807
+buildDefinition.goals.maven.label = \u76ee\u6807
+buildDefinition.arguments.label = \u53c2\u6570
+buildDefinition.buildFresh.label = \u5168\u65b0\u7684\u6784\u5efa\uff08\u603b\u662f\u8fd0\u884c\u4e00\u4e2a\u5e72\u51c0\u7684\u68c0\u51fa\uff0c\u800c\u4e0d\u662f\u4f7f\u7528SCM\u66f4\u65b0\uff09
+buildDefinition.type.label = \u7c7b\u578b
+buildDefinition.defaultForProject.label = \u662f\u5426\u9ed8\u8ba4\uff1f
+buildDefinition.schedule.label = \u8ba1\u5212
+buildDefinition.description.label = \u63cf\u8ff0
+buildDefinition.alwaysBuild.label = \u603b\u662f\u6784\u5efa
+buildDefinition.noname.save.error.message = \u4fdd\u5b58\u8ba1\u5212\u65f6\u53d1\u751f\u4e00\u4e2a\u9519\u8bef\uff0c\u6ca1\u6709\u63d0\u4f9b\u8ba1\u5212\u540d\u79f0\u3002
+buildDefinition.duplicatename.save.error.message = \u4fdd\u5b58\u8ba1\u5212\u65f6\u53d1\u751f\u4e00\u4e2a\u9519\u8bef\uff0c\u5df2\u5b58\u5728\u4e00\u4e2a\u540c\u540d\u7684\u8ba1\u5212\u3002
+
+# ----------------------------------------------------------------------
+# Page: BuildSummary
+# ----------------------------------------------------------------------
+buildDefinitionSummary.projectGroup.section.title = \u9879\u76ee\u5206\u7ec4{0}\u7684\u6784\u5efa\u5b9a\u4e49
+
+
+# ----------------------------------------------------------------------
+# Page: DeleteBuildDefinition
+# ----------------------------------------------------------------------
+deleteBuildDefinition.page.title = Continuum - \u5220\u9664\u6784\u5efa\u5b9a\u4e49
+deleteBuildDefinition.section.title = \u5220\u9664\u6784\u5efa\u5b9a\u4e49
+deleteBuildDefinition.confirmation.message = \u4f60\u786e\u5b9a\u8981\u5220\u9664\u63cf\u8ff0\u4e3a\u201c{1}\u201d\uff0c\u76ee\u6807\u4e3a\u201c{2}\u201d\u4e14id\u4e3a\u201c{0}\u201d\u7684\u6784\u5efa\u5b9a\u4e49\u5417\uff1f
+
+# ----------------------------------------------------------------------
+# Page: DeleteNotifier
+# ----------------------------------------------------------------------
+deleteNotifier.page.title = Continuum - \u5220\u9664\u901a\u77e5
+deleteNotifier.section.title = \u5220\u9664\u901a\u77e5
+deleteNotifier.confirmation.message = \u4f60\u786e\u5b9a\u8981\u5220\u9664\u63a5\u53d7\u8005\u4e3a\u201c{1}\u201d\u7684\u901a\u77e5\u201c{0}\u201d\u5417\uff1f
+
+# ----------------------------------------------------------------------
+# Page: Notifier
+# ----------------------------------------------------------------------
+notifier.page.add.title = Continuum - \u6dfb\u52a0\u901a\u77e5
+notifier.section.add.title = \u6dfb\u52a0\u901a\u77e5
+notifier.page.title = Continuum - \u6dfb\u52a0\uff0f\u7f16\u8f91\u901a\u77e5{0}
+notifier.section.title = \u6dfb\u52a0\uff0f\u7f16\u8f91\u901a\u77e5{0}
+notifier.type.label = \u7c7b\u578b
+notifier.mail.recipient.address.label = \u90ae\u4ef6\u63a5\u53d7\u8005\u5730\u5740
+notifier.mail.recipient.committers.label = \u53d1\u9001\u4e00\u4e2a\u90ae\u4ef6\u7ed9\u6700\u540e\u4e00\u4e2a\u63d0\u4ea4\u8005
+notifier.irc.host.label = IRC\u4e3b\u673a
+notifier.irc.port.label = IRC\u7aef\u53e3
+notifier.irc.channel.label = IRC\u9891\u9053
+notifier.irc.nick.label = \u6635\u79f0\uff08\u9ed8\u8ba4\u503c\u4e3a\u2018continuum\u2019\uff09
+notifier.irc.alternateNick.label = \u5019\u8865\u7684\u6635\u79f0\uff08\u9ed8\u8ba4\u503c\u4e3a\u2018continuum_\u2019\uff09
+notifier.irc.username.label = \u7528\u6237\u540d\uff08\u9ed8\u8ba4\u503c\u4e3a\u6635\u79f0\uff09
+notifier.irc.fullName.label = \u5168\u540d\uff08\u9ed8\u8ba4\u503c\u4e3a\u6635\u79f0\uff09
+notifier.irc.password.label = \u5bc6\u7801
+notifier.irc.isSSL.label = SSL
+notifier.jabber.host.label = Jabber\u4e3b\u673a
+notifier.jabber.port.label = Jabber\u7aef\u53e3
+notifier.jabber.login.label = Jabber\u767b\u5f55\u540d
+notifier.jabber.password.label = Jabber\u5bc6\u7801
+notifier.jabber.domainName.label = Jabber\u57df\u540d\u79f0
+notifier.jabber.address.label = Jabber\u63a5\u53d7\u8005\u5730\u5740
+notifier.jabber.isSslConnection.label = \u662f\u4e00\u4e2aSSL\u8fde\u63a5\uff1f
+notifier.jabber.isGroup.label = \u662f\u4e00\u4e2aJabber\u7ec4\uff1f
+notifier.msn.login.label = MSN\u767b\u5f55\u540d
+notifier.msn.password.label = MSN\u5bc6\u7801
+notifier.msn.address.label = MSN\u63a5\u53d7\u8005\u5730\u5740
+notifier.wagon.url.label = \u9879\u76ee\u7ad9\u70b9URL
+notifier.wagon.id.label = \u670d\u52a1\u5668Id\uff08\u5b9a\u4e49\u5728\u4f60\u7684\u8eab\u4efd\u8ba4\u8bc1\u7684settings.xml\u4e2d\uff09
+notifier.event.sendOnSuccess = \u6210\u529f\u65f6\u53d1\u9001
+notifier.event.sendOnFailure = \u5931\u8d25\u65f6\u53d1\u9001
+notifier.event.sendOnError = \u9519\u8bef\u65f6\u53d1\u9001
+notifier.event.sendOnWarning = \u8b66\u544a\u65f6\u53d1\u9001
+notifier.event.sendOnScmFailure = SCM\u5931\u8d25\u65f6\u53d1\u9001
+
+# ----------------------------------------------------------------------
+# Page: BuildResults
+# ----------------------------------------------------------------------
+buildResults.page.title = Continuum - \u6784\u5efa\u7ed3\u679c
+buildResults.section.title = {0}\u7684\u6784\u5efa\u7ed3\u679c
+buildResults.buildNumber = \u6784\u5efa#
+buildResults.startTime = \u5f00\u59cb\u65f6\u95f4
+buildResults.endTime = \u7ed3\u675f\u65f6\u95f4
+buildResults.duration = \u6301\u7eed\u65f6\u95f4
+buildResults.startedSince = \u5f00\u59cb\u4e8e
+buildResults.state = \u72b6\u6001
+buildResults.result = \u7ed3\u679c
+buildResults.buildDefinition.description = \u6784\u5efa\u5b9a\u4e49\u63cf\u8ff0
+
+# ----------------------------------------------------------------------
+# Page: BuildResults
+# ----------------------------------------------------------------------
+buildResult.page.title = Continuum - \u6784\u5efa\u7ed3\u679c
+buildResult.section.title = {0}\u7684\u6784\u5efa\u7ed3\u679c
+buildResult.startTime = \u5f00\u59cb\u65f6\u95f4
+buildResult.endTime = \u7ed3\u675f\u65f6\u95f4
+buildResult.duration = \u6301\u7eed\u65f6\u95f4
+buildResult.startedSince = \u5f00\u59cb\u4e8e
+buildResult.trigger = \u6784\u5efa\u89e6\u53d1\u5668
+buildResult.state = \u72b6\u6001
+buildResult.buildNumber = \u6784\u5efa#
+buildResult.buildError = \u6784\u5efa\u9519\u8bef
+buildResult.buildOutput = \u8f93\u51fa
+buildResult.noOutput = \u6ca1\u6709\u8f93\u51fa\u3002
+buildResult.changes = \u4fee\u6539
+buildResult.noChanges = \u6ca1\u6709\u4fee\u6539
+buildResult.changes.author = \u4f5c\u8005
+buildResult.changes.date = \u65e5\u671f
+buildResult.changes.comment = \u6ce8\u91ca
+buildResult.changes.files = \u6587\u4ef6
+buildResult.scmResult.changes = SCM\u4fee\u6539
+buildResult.scmResult.noChanges = \u6ca1\u6709SCM\u4fee\u6539
+buildResult.scmResult.changes.author = \u4f5c\u8005
+buildResult.scmResult.changes.date = \u65e5\u671f
+buildResult.scmResult.changes.comment = \u6ce8\u91ca
+buildResult.scmResult.changes.files = \u6587\u4ef6
+buildResult.dependencies.changes = \u4f9d\u8d56\u4fee\u6539
+buildResult.dependencies.noChanges = \u6ca1\u6709\u4f9d\u8d56\u4fee\u6539
+buildResult.dependencies.groupId = \u7ec4Id
+buildResult.dependencies.artifactId = \u5236\u54c1Id
+buildResult.dependencies.version = \u7248\u672c
+buildResult.changesSinceLastSuccess = \u81ea\u4e0a\u6b21\u6210\u529f\u4ee5\u540e\u7684\u5176\u5b83\u4fee\u6539
+buildResult.generatedReports.title = \u751f\u6210\u7684\u62a5\u544a
+buildResult.generatedReports.surefire = Surefire\u62a5\u544a
+buildResult.buildOutput.text = \u4f5c\u4e3a\u6587\u672c\u4e0b\u8f7d
+buildResult.buildDefinition = \u6784\u5efa\u4f9d\u8d56\u4f7f\u7528\u4e86
+buildResult.buildDefinition.ant.label = Ant\u6784\u5efa\u6587\u4ef6\u540d
+buildResult.buildDefinition.shell.label = Shell\u53ef\u6267\u884c\u7684
+buildResult.buildDefinition.maven.label = POM\u6587\u4ef6\u540d
+buildResult.buildDefinition.goals = \u76ee\u6807
+buildResult.buildDefinition.arguments = \u53c2\u6570
+buildResult.buildDefinition.buildFresh = \u5168\u65b0\u7684\u6784\u5efa
+buildResult.buildDefinition.alwaysBuild = \u603b\u662f\u6784\u5efa
+buildResult.buildDefinition.defaultForProject = \u662f\u5426\u662f\u9ed8\u8ba4\u7684\uff1f
+buildResult.buildDefinition.schedule = \u8ba1\u5212
+buildResult.buildDefinition.profileName = \u6784\u5efa\u73af\u5883
+buildResult.buildDefinition.description = \u63cf\u8ff0
+
+# From ContinuumProjectState
+buildResult.trigger.0 = \u8ba1\u5212\u7684
+buildResult.trigger.1 = \u5f3a\u5236\u7684
+buildResult.state.1 = \u65b0\u5efa\u7684
+buildResult.state.2 = \u6210\u529f\u7684
+buildResult.state.3 = \u5931\u8d25\u7684
+buildResult.state.4 = \u9519\u8bef\u7684
+buildResult.state.6 = \u6784\u5efa\u4e2d
+buildResult.state.7 = \u68c0\u51fa\u4e2d
+buildResult.state.8 = \u66f4\u65b0\u4e2d
+buildResult.state.9 = \u8b66\u544a\u4e2d
+buildResult.state.10 = \u5df2\u68c0\u51fa
+
+# ----------------------------------------------------------------------
+# Page: WorkingCopy
+# ----------------------------------------------------------------------
+workingCopy.page.title = Continuum - \u5de5\u4f5c\u62f7\u8d1d
+workingCopy.section.title = {0}\u7684\u5de5\u4f5c\u62f7\u8d1d
+workingCopy.currentFile.text = \u4f5c\u4e3a\u6587\u672c\u4e0b\u8f7d
+
+# ----------------------------------------------------------------------
+# Page: Schedules
+# ----------------------------------------------------------------------
+schedules.page.title = Continuum - \u8ba1\u5212
+schedules.section.title = \u8ba1\u5212
+schedules.table.name = \u540d\u79f0
+schedules.table.description = \u63cf\u8ff0
+schedules.table.delay = \u5e73\u9759\u671f
+schedules.table.cronExpression = Cron \u8868\u8fbe\u5f0f
+schedules.table.active = \u6fc0\u6d3b\u7684
+schedules.table.maxJobExecutionTime = \u6700\u5927\u4f5c\u4e1a\u65f6\u95f4
+schedules.confirmation.message = \u4f60\u786e\u5b9a\u8981\u5220\u9664\u8ba1\u5212\u201c{0}\u201d\u5417\uff1f
+
+# ----------------------------------------------------------------------
+# Page: Add/EditSchedule
+# ----------------------------------------------------------------------
+
+addSchedule.page.title=Continuum - \u6dfb\u52a0\u8ba1\u5212
+addSchedule.section.title = \u6dfb\u52a0\u8ba1\u5212
+editSchedule.page.title = Continuum - \u7f16\u8f91\u8ba1\u5212
+editSchedule.section.title = \u7f16\u8f91\u8ba1\u5212
+schedule.name.label = \u540d\u79f0
+schedule.name.message = \u8f93\u5165\u8ba1\u5212\u540d\u79f0
+schedule.description.label = \u63cf\u8ff0
+schedule.description.message = \u8f93\u5165\u8ba1\u5212\u7684\u63cf\u8ff0
+schedule.cronExpression.label = Cron\u8868\u8fbe\u5f0f
+schedule.cronExpression.message = \u8f93\u5165cron\u8868\u8fbe\u5f0f\u3002\u683c\u5f0f\u5982\u8fd9\u91cc\u63cf\u8ff0\uff1a<a href="http://www.quartz-scheduler.org/docs/tutorials/crontrigger.html" target="_blank">\u8bed\u6cd5<a>
+schedule.maxJobExecutionTime.label = \u6700\u5927\u4f5c\u4e1a\u6267\u884c\u65f6\u95f4\uff08\u79d2\uff09
+schedule.maxJobExecutionTime.message = \u4e00\u4e2a\u4f5c\u4e1a\u6267\u884c\u5b8c\u6210\u53ef\u80fd\u4f7f\u7528\u7684\u6700\u5927\u79d2\u6570\u3002
+schedule.quietPeriod.label = \u5e73\u9759\u671f\uff08\u79d2\uff09
+schedule.quietPeriod.message = \u8f93\u5165\u8be5\u8ba1\u5212\u7684\u5e73\u9759\u671f
+schedule.enabled.label = \u542f\u7528
+schedule.enabled.message = \u542f\u7528\uff0f\u505c\u7528\u8ba1\u5212
+schedule.second.label = \u79d2
+schedule.minute.label = \u5206
+schedule.hour.label = \u65f6
+schedule.dayOfMonth.label = \u65e5
+schedule.month.label = \u6708
+schedule.dayOfWeek.label = \u661f\u671f
+schedule.year.label = \u5e74\uff3b\u53ef\u9009\uff3d
+schedule.remove.error = \u65e0\u6cd5\u5220\u9664\u8be5\u8ba1\u5212\uff0c\u53ef\u80fd\u67d0\u4e2a\u6784\u5efa\u5b9a\u4e49\u6b63\u5728\u4f7f\u7528\u5b83\u3002
+
+# ----------------------------------------------------------------------
+# Page: SurefireReport
+# ----------------------------------------------------------------------
+surefireReport.page.title = Continuum - Surefire\u62a5\u544a
+surefireReport.section.title = {0}\u6784\u5efa\u7f16\u53f7{1}\u7684Surefire\u62a5\u544a
+surefireReport.summary = \u6982\u8981
+surefireReport.tests = \u6d4b\u8bd5
+surefireReport.errors = \u9519\u8bef
+surefireReport.failures = \u5931\u8d25
+surefireReport.successRate = \u6210\u529f\u7387
+surefireReport.time = \u65f6\u95f4
+surefireReport.packageList = \u5305\u5217\u8868
+surefireReport.testCases = \u6d4b\u8bd5\u7528\u4f8b
+surefireReport.package = \u5305\u540d
+surefireReport.class = \u7c7b
+surefireReport.testCase = \u6d4b\u8bd5\u7528\u4f8b
+surefireReport.failureDetails = \u5931\u8d25\u8be6\u7ec6
+
+# ----------------------------------------------------------------------
+# Page: Continuum Release Support
+# ----------------------------------------------------------------------
+releaseProject.page.title=Continuum - \u53d1\u5e03\u9879\u76ee
+releaseProject.section.title=\u4e3a{0}\u9009\u62e9\u53d1\u5e03\u76ee\u6807
+releaseProject.prepareReleaseOption=\u4e3a\u53d1\u5e03\u51c6\u5907\u9879\u76ee
+releaseProject.performReleaseOption=\u5b9e\u65bd\u9879\u76ee\u53d1\u5e03
+releaseProject.provideReleaseParameters=\u63d0\u4f9b\u53d1\u5e03\u53c2\u6570
+releasePrepare.section.title=\u4e3a\u53d1\u5e03\u51c6\u5907\u9879\u76ee
+releasePrepare.parameters=\u53d1\u5e03\u51c6\u5907\u53c2\u6570
+releasePrepare.releaseVersion=\u53d1\u5e03\u7248\u672c*
+releasePrepare.nextDevelopmentVersion=\u4e0b\u4e00\u4e2a\u5f00\u53d1\u7248\u672c*
+releasePerform.section.title=\u5b9e\u65bd\u9879\u76ee\u53d1\u5e03
+releasePerform.parameters=\u53d1\u5e03\u5b9e\u65bd\u53c2\u6570
+releaseInProgress.section.title=\u6267\u884c\u53d1\u5e03\u76ee\u6807
+releaseInProgress.status=\u72b6\u6001
+releaseInProgress.phase=\u53d1\u5e03\u9636\u6bb5
+releaseInProgress.viewOutput=\u67e5\u770b\u8f93\u51fa
+releaseViewResult.section.title=\u9879\u76ee\u53d1\u5e03\u6982\u8981
+releaseViewResult.summary=\u53d1\u5e03\u9879\u76ee\u8be6\u7ec6
+releaseViewResult.startTime=\u5f00\u59cb\u65f6\u95f4
+releaseViewResult.endTime=\u7ed3\u675f\u65f6\u95f4
+releaseViewResult.state=\u72b6\u6001
+releaseViewResult.success=\u6210\u529f
+releaseViewResult.error=\u9519\u8bef
+releaseViewResult.output=\u53d1\u5e03\u6267\u884c\u8f93\u51fa
+releaseViewResult.noOutput=\u6ca1\u6709\u8f93\u51fa
+releaseViewResult.projectName=\u9879\u76ee\u540d\u79f0
+releaseViewResult.releaseGoal=\u53d1\u5e03\u76ee\u6807
+releasePrepare.scmUsername.label=SCM\u7528\u6237\u540d
+releasePrepare.scmPassword.label=SCM\u5bc6\u7801
+releasePrepare.scmTag.label=SCM\u6807\u7b7e
+releasePrepare.scmTagBase.label=SCM\u6807\u7b7eBase
+releasePrepare.prepareGoals.label=\u51c6\u5907\u7684\u76ee\u6807
+releasePrepare.buildEnvironment.label=\u6784\u5efa\u73af\u5883
+releasePrepare.useEditMode.label=\u4f7f\u7528\u7f16\u8f91\u6a21\u5f0f
+releasePerformFromScm.scmUrl.label=SCM\u8fde\u63a5URL
+releasePerformFromScm.scmUsername.label=SCM\u7528\u6237\u540d
+releasePerformFromScm.scmPassword.label=SCM\u5bc6\u7801
+releasePerformFromScm.scmTag.label=SCM\u6807\u7b7e
+releasePerformFromScm.scmTagBase.label=SCM\u6807\u7b7eBase
+releasePerformFromScm.goals.label=Perform Goals
+releasePerformFromScm.useReleaseProfile.label=\u4f7f\u7528\u53d1\u5e03\u914d\u7f6e\u9009\u9879
+releasePerformFromScm.buildEnvironment.label=\u6784\u5efa\u73af\u5883
+
+# ----------------------------------------------------------------------
+# Page: User
+# ----------------------------------------------------------------------
+user.username.label = \u7528\u6237\u540d
+user.username.message = \u8f93\u5165\u7528\u6237\u540d
+user.fullName.label = \u5168\u540d
+user.fullName.message = \u8f93\u5165\u7528\u6237\u7684\u5168\u540d
+user.email.label = \u7535\u5b50\u90ae\u4ef6
+user.email.message = \u8f93\u5165\u7528\u6237\u7684\u7535\u5b50\u90ae\u4ef6
+user.password.label = \u5bc6\u7801
+user.passwordTwo.label = \u5bc6\u7801\uff08\u518d\u8f93\u4e00\u6b21\uff09
+user.passwordTwo.message = \u4e24\u6b21\u8f93\u5165\u7684\u5bc6\u7801\u5fc5\u987b\u4e00\u81f4
+user.userGroup.label = \u7528\u6237\u7ec4
+user.userGroup.message = \u9009\u62e9\u4e00\u4e2a\u7528\u6237\u7ec4
+
+# ----------------------------------------------------------------------
+# Page: User Group
+# ----------------------------------------------------------------------
+userGroup.name.label = \u540d\u79f0
+userGroup.name.message = \u8f93\u5165\u4e00\u4e2a\u7528\u6237\u7ec4\u540d\u79f0
+userGroup.description.label = \u63cf\u8ff0
+userGroup.description.message = \u8f93\u5165\u63cf\u8ff0
+
+# ----------------------------------------------------------------------
+# Page: Profiles List
+# ----------------------------------------------------------------------
+profilesList.page.title= \u6784\u5efa\u73af\u5883
+profilesList.section.title= \u6784\u5efa\u73af\u5883
+
+# ----------------------------------------------------------------------
+# Page: Profile Edit
+# ----------------------------------------------------------------------
+profile.page.title= Continuum - \u6784\u5efa\u73af\u5883
+profile.section.title = \u6784\u5efa\u73af\u5883
+profile.name.label= \u6784\u5efa\u73af\u5883\u540d\u79f0
+profile.jdk.name.label = Jdk\u540d\u79f0
+profile.jdk.name.message = JDK\u540d\u79f0
+profile.jdk.path.label = Jdk\u8def\u5f84
+profile.jdk.path.message = JDK\u8def\u5f84\uff08JAVA_HOME\u7684\u503c\uff09
+profile.no.installations = \u6ca1\u6709\u53ef\u7528\u7684\u5b89\u88c5
+profile.name.already.exists = \u4e00\u4e2a\u540c\u540d\u7684\u6784\u5efa\u73af\u5883\u5df2\u5b58\u5728
+profile.name.required = \u4f60\u5fc5\u987b\u5b9a\u4e49\u4e00\u4e2a\u540d\u79f0\u3002
+profile.remove.error = \u4e0d\u80fd\u5220\u9664\u8fd9\u4e2a\u6784\u5efa\u73af\u5883\uff0c\u67d0\u4e2a\u6784\u5efa\u5b9a\u4e49\u53ef\u80fd\u6b63\u5728\u4f7f\u7528\u5b83\u3002
+
+# ----------------------------------------------------------------------
+# Page: Installations List
+# ----------------------------------------------------------------------
+installationsList.page.title = \u5b89\u88c5
+installationsList.section.title = \u5b89\u88c5
+
+# ----------------------------------------------------------------------
+# Page: Installation Edit
+# ----------------------------------------------------------------------
+installation.page.title = Continuum - \u5b89\u88c5
+installation.section.title = Continuum - \u5b89\u88c5
+installation.name.label = \u540d\u79f0
+installation.type.label = \u7c7b\u578b
+installation.value.label = \u503c\uff0f\u8def\u5f84
+installation.varName.label = \u73af\u5883\u53d8\u91cf\u540d
+installation.jdk.type.label = JDK
+installation.maven2.type.label = Maven
+installation.maven1.type.label = Maven 1
+installation.envvar.type.label = \u73af\u5883\u53d8\u91cf
+installation.ant.type.label = ANT
+installation.automaticProfile.label=\u7528\u5b89\u88c5\u540d\u521b\u5efa\u4e00\u4e2a\u6784\u5efa\u73af\u5883
+installation.name.duplicate = \u5b89\u88c5\u540d\u5df2\u5b58\u5728\u3002
+
+# ----------------------------------------------------------------------
+# Page: Installations Type Choice
+# ----------------------------------------------------------------------
+installationTypeChoice.page.title =  Continuum - \u5b89\u88c5\u7c7b\u578b\u9009\u62e9
+installationTypeChoice.section.title = \u5b89\u88c5\u7c7b\u578b\u9009\u62e9
+installationTypeChoice.action.label = \u5b89\u88c5\u7c7b\u578b
+installationTypeChoice.tool.label = \u5de5\u5177
+installationTypeChoice.envar.label = \u73af\u5883\u53d8\u91cf 
+
+# ----------------------------------------------------------------------
+# Page: Build Definitions Templates Summary
+# ----------------------------------------------------------------------
+buildDefinition.templates.page.title = Continuum - \u6784\u5efa\u5b9a\u4e49\u6a21\u677f
+buildDefinition.templates.continuum.section.title = Continuum\u9ed8\u8ba4\u6784\u5efa\u5b9a\u4e49
+buildDefinition.templates.goals = \u76ee\u6807
+buildDefinition.templates.arguments = \u53c2\u6570
+buildDefinition.templates.buildFile = \u6784\u5efa\u6587\u4ef6
+buildDefinition.templates.schedule = \u8ba1\u5212
+buildDefinition.templates.profile = \u6784\u5efa\u73af\u5883
+buildDefinition.templates.buildFresh = \u662f\u5426\u5168\u65b0\u6784\u5efa
+buildDefinition.templates.alwaysBuild = \u603b\u662f\u6784\u5efa
+buildDefinition.templates.description = \u63cf\u8ff0
+buildDefinition.templates.type = \u7c7b\u578b
+buildDefinition.templates.section.title = \u53ef\u7528\u6a21\u677f
+buildDefinition.templates.buildDefinitions.section.title = \u53ef\u7528\u6784\u5efa\u5b9a\u4e49
+
+# ----------------------------------------------------------------------
+# Page: Edit Build Definition Template
+# ----------------------------------------------------------------------
+buildDefinition.template.page.title = Continuum - \u6784\u5efa\u5b9a\u4e49\u6a21\u677f
+buildDefinition.template.section.title = \u6784\u5efa\u5b9a\u4e49\u6a21\u677f
+buildDefinition.template.name = \u540d\u79f0
+buildDefinition.template.buildDefinition.goals = \u76ee\u6807
+buildDefinition.template.buildDefinition.arguments = \u53c2\u6570
+buildDefinition.template.buildDefinition.buildFile = \u6784\u5efa\u6587\u4ef6
+buildDefinition.template.buildDefinition.schedule = \u8ba1\u5212
+buildDefinition.template.buildDefinition.profile = \u6784\u5efa\u73af\u5883
+buildDefinition.template.buildDefinition.buildFresh = \u662f\u5426\u5168\u65b0\u6784\u5efa\uff1f
+buildDefinition.template.buildDefinition.default = \u9ed8\u8ba4
+buildDefinition.template.buildDefinition.description = \u63cf\u8ff0
+buildDefinition.template.buildDefinition.type = \u7c7b\u578b
+buildDefinitionTemplate.name = \u540d\u79f0
+buildDefinitionTemplate.available.builddefinitions = --- \u53ef\u7528\u6784\u5efa\u5b9a\u4e49 ---
+buildDefinitionTemplate.available.builddefinitions.used = --- \u4f7f\u7528\u7684\u6784\u5efa\u5b9a\u4e49 ---
+buildDefinitionTemplate.builddefinitions.define = \u914d\u7f6e\u4f7f\u7528\u7684\u6784\u5efa\u5b9a\u4e49
+
+# ----------------------------------------------------------------------
+# Page: Build Queue
+# ----------------------------------------------------------------------
+buildQueue.page.title = Continuum - \u6784\u5efa\u961f\u5217
+buildQueue.section.title = Continuum - \u6784\u5efa\u961f\u5217
+buildQueue.empty = \u6784\u5efa\u961f\u5217\u662f\u7a7a\u7684
+buildQueue.currentTask.section.title = \u5f53\u524d\u6784\u5efa
+buildQueue.currentTask.projectName = \u9879\u76ee\u540d\u79f0
+buildQueue.currentTask.buildDefinition = \u6784\u5efa\u5b9a\u4e49
+buildQueue.no.currentTaks = \u6ca1\u6709\u6b63\u5728\u6784\u5efa\u7684
+buildQueue.removeEntries = \u53d6\u6d88\u5b83
+checkoutQueue.currentTask.section.title = \u5f53\u524d\u68c0\u51fa
+checkoutQueue.currentTask.projectName = \u9879\u76ee\u540d\u79f0
+checkoutQueue.no.currentTaks = \u6ca1\u6709\u6b63\u5728\u68c0\u51fa\u7684
+checkoutQueue.section.title = \u68c0\u51fa\u961f\u5217
+checkoutQueue.empty = \u68c0\u51fa\u961f\u5217\u662f\u7a7a\u7684
+checkoutQueue.removeEntries = \u53d6\u6d88\u5b83
+
+# ----------------------------------------------------------------------
+# Page: Confirm Delete BuildResult(s)
+# ----------------------------------------------------------------------
+buildResult.delete.confirmation.page.title = Continuum - \u5220\u9664\u6784\u5efa\u7ed3\u679c
+buildResult.delete.confirmation.section.title = \u5220\u9664\u6784\u5efa\u7ed3\u679c
+buildResult.delete.confirmation.message = \u4f60\u786e\u5b9a\u8981\u5220\u9664\u6784\u5efa\u7ed3\u679c{0}\u5417\uff1f 
+buildResult.cannot.delete = \u4e0d\u80fd\u5220\u9664\u6b63\u5728\u6784\u5efa\u4e2d\u7684\u6784\u5efa\u7ed3\u679c\u3002
+
+# ----------------------------------------------------------------------
+# Legend
+# ----------------------------------------------------------------------
+legend.title = \u56fe\u4f8b
+legend.buildNow = \u7acb\u5373\u6784\u5efa
+legend.buildHistory = \u6784\u5efa\u5386\u53f2
+legend.buildInProgress=\u8fdb\u884c\u4e2d\u7684\u6784\u5efa
+legend.workingCopy=\u5de5\u4f5c\u62f7\u8d1d
+legend.checkingOutBuild=\u68c0\u51fa\u4e2d\u7684\u6784\u5efa
+legend.queuedBuild=\u6b63\u5728\u6392\u961f\u7684\u6784\u5efa
+legend.cancelBuild=\u53d6\u6d88\u4e86\u7684\u6784\u5efa
+legend.delete=\u5220\u9664
+legend.edit=\u7f16\u8f91
+legend.release=\u53d1\u5e03
+legend.buildInSuccess=\u6210\u529f\u4e86\u7684\u6784\u5efa
+legend.buildInFailure=\u5931\u8d25\u4e86\u7684\u6784\u5efa
+legend.buildInError=\u53d1\u751f\u9519\u8bef\u7684\u6784\u5efa
+
+
+# ----------------------------------------------------------------------
+# Page: Wait
+# ----------------------------------------------------------------------
+wait.addprocessing.processing = \u6dfb\u52a0\u9879\u76ee\u6b63\u5728\u8fdb\u884c\u4e2d\u3002\u8bf7\u7a0d\u7b49\u22ef\u22ef
+
+# ----------------------------------------------------------------------
+# Page: DeleteProjects
+# ----------------------------------------------------------------------
+deleteProjects.page.title = Continuum - \u5220\u9664Continuum\u9879\u76ee
+deleteProjects.section.title = \u5220\u9664Continuum\u9879\u76ee
+deleteProjects.confirmation.message = \u4f60\u786e\u5b9a\u8981\u5220\u9664\u9879\u76ee\u201c{0}\u201d\u5417\uff1f
+
+# ----------------------------------------------------------------------
+# Page: Confirm Delete Build Env
+# ----------------------------------------------------------------------
+deleteBuildEnv.page.title = Continuum - \u5220\u9664\u6784\u5efa\u73af\u5883
+deleteBuildEnv.section.title = \u5220\u9664\u6784\u5efa\u73af\u5883
+deleteBuildEnv.confirmation.message = \u4f60\u786e\u5b9a\u8981\u5220\u9664\u6784\u5efa\u73af\u5883\u201c{0}\u201d\u5417\uff1f
+
+#-----------------------------------------------------------------------
+# Page: Local Repositories
+#-----------------------------------------------------------------------
+repositories.page.title = Continuum - \u672c\u5730\u4ed3\u5e93
+repositories.section.title = \u672c\u5730\u4ed3\u5e93
+repositories.table.name = \u540d\u79f0
+repositories.table.location = \u4f4d\u7f6e
+repositories.table.layout = \u5e03\u5c40
+
+#-----------------------------------------------------------------------
+# Page: Add/Edit Local Repository
+#-----------------------------------------------------------------------
+repository.page.title = Continuum - \u6dfb\u52a0\uff0f\u7f16\u8f91\u672c\u5730\u4ed3\u5e93
+repository.section.title = \u6dfb\u52a0\uff0f\u7f16\u8f91\u672c\u5730\u4ed3\u5e93
+repository.name.label = \u540d\u79f0
+repository.location.label = \u4f4d\u7f6e
+repository.layout.label = \u5e03\u5c40
+repository.error.name.unique = \u672c\u5730\u4ed3\u5e93\u540d\u79f0\u5fc5\u987b\u552f\u4e00
+repository.error.name.cannot.be.spaces = \u672c\u5730\u4ed3\u5e93\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a\u767d
+repository.error.location.unique = \u672c\u5730\u4ed3\u5e93\u4f4d\u7f6e\u5fc5\u987b\u552f\u4e00
+repository.error.location.cannot.be.spaces = \u672c\u5730\u4ed3\u5e93\u4f4d\u7f6e\u4e0d\u80fd\u4e3a\u7a7a\u767d
+repository.error.save.in.use = \u65e0\u6cd5\u7f16\u8f91\u672c\u5730\u4ed3\u5e93\uff0c\u56e0\u4e3a\u6b63\u5728\u4f7f\u7528\u4e2d
+repository.error.remove.in.use = \u65e0\u6cd5\u5220\u9664\u672c\u5730\u4ed3\u5e93\uff0c\u56e0\u4e3a\u6b63\u5728\u4f7f\u7528\u4e2d
+repository.error.purge.in.use = \u65e0\u6cd5\u6e05\u9664\u672c\u5730\u4ed3\u5e93\uff0c\u56e0\u4e3a\u6b63\u5728\u4f7f\u7528\u4e2d
+repository.error.remove.default = \u65e0\u6cd5\u5220\u9664\u9ed8\u8ba4\u672c\u5730\u4ed3\u5e93\u3002
+
+#-----------------------------------------------------------------------
+# Page: Delete Local Repository
+#-----------------------------------------------------------------------
+deleteRepository.page.title = Continuum - \u5220\u9664\u672c\u5730\u4ed3\u5e93
+deleteRepository.section.title = \u5220\u9664\u672c\u5730\u4ed3\u5e93
+deleteRepository.confirmation.message = \u4f60\u786e\u5b9a\u8981\u5220\u9664\u672c\u5730\u4ed3\u5e93\u201c{0}\u201d\u5417\uff1f
+
+#-----------------------------------------------------------------------
+# Page: Purge Configurations
+#-----------------------------------------------------------------------
+purgeConfigs.page.title = Continuum - \u6e05\u9664\u914d\u7f6e
+purgeConfigs.repo.section.title = \u4ed3\u5e93\u6e05\u9664\u914d\u7f6e
+purgeConfigs.dir.section.title = \u76ee\u5f55\u6e05\u9664\u914d\u7f6e
+purgeConfigs.table.repository = \u4ed3\u5e93
+purgeConfigs.table.description = \u63cf\u8ff0
+purgeConfigs.table.retentionCount = \u4fdd\u7559\u8ba1\u6570
+purgeConfigs.table.schedule = \u8ba1\u5212
+purgeConfigs.table.daysOlder = Days Older
+purgeConfigs.table.deleteAll = \u5220\u9664\u6240\u6709
+purgeConfigs.table.directoryType = \u76ee\u5f55\u7c7b\u578b
+purgeConfigs.table.default = \u9ed8\u8ba4
+purgeConfigs.table.enabled = \u542f\u7528
+purgeConfigs.table.deleteReleasedSnapshots = \u5220\u9664\u53d1\u5e03\u5feb\u7167
+
+#-----------------------------------------------------------------------
+# Page: Add/Edit Purge Configuration
+#-----------------------------------------------------------------------
+purgeConfig.page.title = Continuum - \u6dfb\u52a0\uff0f\u7f16\u8f91\u6e05\u9664\u914d\u7f6e
+purgeConfig.section.title = \u6dfb\u52a0\uff0f\u7f16\u8f91\u6e05\u9664\u914d\u7f6e
+purgeConfig.repository.label = \u4ed3\u5e93
+purgeConfig.directoryType.label = \u76ee\u5f55\u7c7b\u578b
+purgeConfig.retentionCount.label = \u4fdd\u7559\u8ba1\u6570
+purgeConfig.daysOlder.label = Days Older
+purgeConfig.deleteAll.label = \u5220\u9664\u6240\u6709
+purgeConfig.deleteReleasedSnapshots.label = \u5220\u9664\u53d1\u5e03\u5feb\u7167
+purgeConfig.defaultPurge.label = \u662f\u5426\u9ed8\u8ba4\uff1f
+purgeConfig.schedule.label = \u8ba1\u5212
+purgeConfig.description.label = \u63cf\u8ff0
+purgeConfig.enabled.label = \u542f\u7528
+purgeConfig.no.repositories = \u6ca1\u6709\u4ed3\u5e93\u9700\u8981\u6e05\u9664
+
+# ----------------------------------------------------------------------
+# Page: Release Results
+# ----------------------------------------------------------------------
+projectGroup.releaseResults.section.title = \u7ec4{0}\u7684\u53d1\u5e03\u7ed3\u679c
+releaseResults.viewResult = \u67e5\u770b\u7ed3\u679c
+releaseResults.state = \u72b6\u6001
+releaseResults.startTime = \u5f00\u59cb\u65f6\u95f4
+releaseResults.endTime = \u7ed3\u675f\u65f6\u95f4
+releaseResults.success = \u6210\u529f
+releaseResults.error = \u9519\u8bef
+releaseResults.project = \u9879\u76ee\u540d\u79f0
+releaseResults.releaseGoal = \u53d1\u5e03\u76ee\u6807
+
+# ----------------------------------------------------------------------
+# Page: Confirm Delete Release Results
+# ----------------------------------------------------------------------
+deleteReleaseResults.page.title = Continuum - \u5220\u9664\u53d1\u5e03\u7ed3\u679c
+deleteReleaseResults.section.title = \u5220\u9664\u53d1\u5e03\u7ed3\u679c
+deleteReleaseResults.confirmation.message = \u4f60\u786e\u5b9a\u8981\u5220\u9664\u53d1\u5e03\u7ed3\u679c{0}\u5417\uff1f
+
+# ----------------------------------------------------------------------
+# Page: ScmResult
+# ----------------------------------------------------------------------
+scmResult.page.title = Continuum - SCM\u7ed3\u679c
+scmResult.section.title = SCM\u7ed3\u679c
+scmResult.state = \u72b6\u6001
+scmResult.projectGroupName = \u9879\u76ee\u5206\u7ec4\u540d\u79f0
+scmResult.scmRootAddress = SCM\u6839URL
+scmResult.scmError = SCM\u9519\u8bef
diff --git a/continuum-webapp/src/main/resources/log4j.xml b/continuum-webapp/src/main/resources/log4j.xml
index 6116535..a5a54c0 100644
--- a/continuum-webapp/src/main/resources/log4j.xml
+++ b/continuum-webapp/src/main/resources/log4j.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" ?>
+
 <!--
   ~ Licensed to the Apache Software Foundation (ASF) under one
   ~ or more contributor license agreements.  See the NOTICE file
@@ -17,36 +18,82 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
   -->
+
 <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
 
 <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
 
   <appender name="rolling" class="org.apache.log4j.DailyRollingFileAppender">
-    <param name="file" value="${appserver.base}/logs/continuum.log" />
-    <param name="append" value="true" />
-    <param name="datePattern" value="'.'yyyy-MM-dd" />
+    <param name="file" value="${appserver.base}/logs/continuum.log"/>
+    <param name="append" value="true"/>
+    <param name="datePattern" value="'.'yyyy-MM-dd"/>
     <layout class="org.apache.log4j.PatternLayout">
       <param name="ConversionPattern" value="%d [%t] %-5p %c %x - %m%n"/>
     </layout>
   </appender>
 
-  <!-- Help identify bugs during testing -->
-  <logger name="org.apache.maven">
+  <appender name="continuumAuditlog" class="org.apache.log4j.DailyRollingFileAppender">
+    <param name="file" value="${appserver.base}/logs/continuum-audit.log"/>
+    <param name="append" value="true"/>
+    <param name="datePattern" value="'.'yyyy-MM-dd"/>
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} - %X{security.currentUser} - %m%n"/>
+    </layout>
+  </appender>
+
+  <appender name="redbackAuditLog" class="org.apache.log4j.DailyRollingFileAppender">
+    <param name="file" value="${appserver.base}/logs/continuum-security-audit.log"/>
+    <param name="append" value="true"/>
+    <param name="datePattern" value="'.'yyyy-MM-dd"/>
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} - %X{redback.currentUser} - %m%n"/>
+    </layout>
+  </appender>
+
+  <logger name="org.apache.continuum.web.util.AuditLog" additivity="false">
     <level value="info"/>
+    <appender-ref ref="continuumAuditlog"/>
   </logger>
 
-  <logger name="org.apache.maven.continuum">
-    <level value="info" />
-  </logger>
-
-  <logger name="org.apache.maven.scm">
-    <level value="info" />
-  </logger>
-
-  <logger name="org.codehaus.plexus.redback">
+  <logger name="org.codehaus.plexus.redback.struts2.action.AuditEvent" additivity="false">
     <level value="info"/>
+    <appender-ref ref="redbackAuditLog"/>
   </logger>
 
+  <!--
+    <logger name="org.apache.maven">
+      <level value="info"/>
+    </logger>
+
+    <logger name="org.apache.continuum">
+      <level value="info" />
+    </logger>
+
+    <logger name="org.codehaus.plexus.redback">
+      <level value="info"/>
+    </logger>
+
+    <logger name="org.codehaus.plexus.mailsender.MailSender">
+      <level value="info"/>
+    </logger>
+
+    <logger name="org.quartz">
+      <level value="info"/>
+    </logger>
+
+    <logger name="org.apache.jasper">
+      <level value="info"/>
+    </logger>
+
+    <logger name="com.opensymphony.xwork">
+      <level value="info"/>
+    </logger>
+
+    <logger name="org.codehaus.plexus.PlexusContainer">
+      <level value="info"/>
+    </logger>
+  -->
+
   <!-- squelch noisy objects (for now) -->
   <logger name="org.apache.commons">
     <level value="warn"/>
@@ -56,33 +103,21 @@
     <level value="warn"/>
   </logger>
 
-  <logger name="org.codehaus.plexus.mailsender.MailSender">
-    <level value="info"/>
-  </logger>
-
   <logger name="org.codehaus.plexus.velocity">
     <level value="error"/>
   </logger>
 
-  <logger name="org.quartz">
-    <level value="info"/>
-  </logger>
-
-  <logger name="org.apache.jasper">
-    <level value="info"/>
-  </logger>
-
-  <logger name="com.opensymphony.xwork">
-    <level value="info"/>
-  </logger>
-
-  <!-- CONTINUUM-1228 -->
-  <logger name="com.opensymphony.xwork2.util.OgnlUtil">
+  <logger name="com.opensymphony.xwork2.ognl.OgnlUtil">
     <level value="error"/>
   </logger>
 
-  <logger name="org.codehaus.plexus.PlexusContainer">
-    <level value="info"/>
+  <logger name="org.apache.struts2.util.TextProviderHelper">
+    <level value="error"/>
+  </logger>
+
+  <!-- Related https://issues.apache.org/struts/browse/WW-1714 -->
+  <logger name="com.opensymphony.xwork2.ObjectFactory">
+    <level value="fatal"/>
   </logger>
 
   <logger name="JPOX">
@@ -108,10 +143,11 @@
   <logger name="org.codehaus.plexus.component.manager.ClassicSingletonComponentManager">
     <level value="error"/>
   </logger>
-  
+
   <logger name="org.springframework.beans.factory.xml.XmlBeanDefinitionReader">
     <level value="error"/>
   </logger>
+
   <logger name="org.springframework.beans.factory.support.DefaultListableBeanFactory">
     <level value="error"/>
   </logger>
@@ -120,9 +156,14 @@
     <level value="warn"/>
   </logger>
 
+  <!-- Can be reverted back to "info" if using redback 1.3-M3 or 1.5+ -->
+  <logger name="org.codehaus.plexus.redback.authorization.rbac.RbacAuthorizer">
+    <level value="warn"/>
+  </logger>
+
   <root>
-    <priority value="info" />
-    <appender-ref ref="rolling" />
+    <priority value="info"/>
+    <appender-ref ref="rolling"/>
   </root>
 
 </log4j:configuration>
diff --git a/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/BuildAgentAction-saveBuildAgent-validation.xml b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/BuildAgentAction-saveBuildAgent-validation.xml
index 7ecdd41..798fe76 100644
--- a/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/BuildAgentAction-saveBuildAgent-validation.xml
+++ b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/BuildAgentAction-saveBuildAgent-validation.xml
@@ -16,15 +16,19 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
   -->
-  
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
 
 <validators>
   <field name="buildAgent.url">
     <field-validator type="requiredstring">
       <message key="buildAgent.url.required"/>
     </field-validator>
+    <field-validator type="regex">
+      <param name="regex"><![CDATA[[A-Za-z0-9_.@:/-]*]]></param>
+      <message key="buildAgent.url.invalid"/>
+    </field-validator>
   </field>
-</validators>
\ No newline at end of file
+</validators>
diff --git a/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/BuildAgentAction-saveBuildAgentGroup-validation.xml b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/BuildAgentAction-saveBuildAgentGroup-validation.xml
new file mode 100644
index 0000000..c6cc996
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/BuildAgentAction-saveBuildAgentGroup-validation.xml
@@ -0,0 +1,34 @@
+<!--
+  ~ 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.
+  -->
+
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
+
+<validators>
+  <field name="buildAgentGroup.name">
+    <field-validator type="requiredstring">
+      <message key="buildAgentGroup.name.required"/>
+    </field-validator>
+    <field-validator type="regex">
+      <param name="regex"><![CDATA[[A-Za-z0-9_.\s\-]*]]></param>
+      <message key="buildAgentGroup.name.invalid"/>
+    </field-validator>
+  </field>
+</validators>
diff --git a/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/BuildAgentAction.properties b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/BuildAgentAction.properties
index d016741..3c47aad 100644
--- a/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/BuildAgentAction.properties
+++ b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/BuildAgentAction.properties
@@ -18,6 +18,9 @@
 #
 
 buildAgent.url.required = Build agent url is required.
+buildAgent.url.invalid = Build agent url is invalid.
 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.
+buildAgentGroup.name.required = Build agent group name is required.
+buildAgentGroup.name.invalid = Build agent group name contains invalid characters.
\ No newline at end of file
diff --git a/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/BuildAgentAction_de.properties b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/BuildAgentAction_de.properties
new file mode 100644
index 0000000..d7123a5
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/BuildAgentAction_de.properties
@@ -0,0 +1,23 @@
+#
+# 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.
+#
+
+buildAgent.url.required = Es mu\u00DF ein URL angegeben werden.
+buildAgent.error.exist = Ein identischer Vorgangsagent existiert bereits.
+buildAgent.error.delete.busy = Momentan aktiver Vorgangsagent kann nicht gel\u00F6scht werden.
+buildAgent.error.notfound = Vorgangsagent existiert nicht.
diff --git a/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/BuildAgentAction_en.properties b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/BuildAgentAction_en.properties
new file mode 100644
index 0000000..661b0cb
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/BuildAgentAction_en.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+
diff --git a/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/BuildAgentAction_fr.properties b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/BuildAgentAction_fr.properties
new file mode 100644
index 0000000..e74701e
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/BuildAgentAction_fr.properties
@@ -0,0 +1,23 @@
+#
+# 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.
+#
+
+buildAgent.url.required = L''URL de l''agent de construction est requis.
+buildAgent.error.exist = l''agent de construction existe d\u00e9j\u00e0.
+buildAgent.error.delete.busy = Impossible de supprimer l''agent de construction car il est occup\u00e9 pour le moment
+buildAgent.error.notfound = L''agent de construction n''exite pas.
diff --git a/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/DistributedPurgeConfigurationAction-saveDistributedPurgeConfig-validation.xml b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/DistributedPurgeConfigurationAction-saveDistributedPurgeConfig-validation.xml
new file mode 100644
index 0000000..eb40074
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/DistributedPurgeConfigurationAction-saveDistributedPurgeConfig-validation.xml
@@ -0,0 +1,42 @@
+<!--
+  ~ 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.
+  -->
+
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
+
+<validators>
+  <field name="daysOlder">
+    <field-validator type="int">
+      <param name="min">0</param>
+      <message key="purgeConfig.daysOlder.min"/>
+    </field-validator>
+  </field>
+  <field name="retentionCount">
+    <field-validator type="int">
+      <param name="min">0</param>
+      <message key="purgeConfig.retentionCount.min"/>
+    </field-validator>
+  </field>
+  <field name="buildAgentUrl">
+    <field-validator type="requiredstring">
+      <message key="purgeConfig.buildagent.required"/>
+    </field-validator>
+  </field>
+</validators>
diff --git a/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/DistributedPurgeConfigurationAction.properties b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/DistributedPurgeConfigurationAction.properties
new file mode 100644
index 0000000..b06e868
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/DistributedPurgeConfigurationAction.properties
@@ -0,0 +1,23 @@
+#
+# 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.
+#
+
+purgeConfig.daysOlder.min = Days Older must be a positive number.
+purgeConfig.retentionCount.min = Retention Count must be a positive number.
+purgeConfig.description.invalid = Description contains invalid characters.
+purgeConfig.buildagent.required = Build Agent is required.
\ No newline at end of file
diff --git a/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/DistributedPurgeConfigurationAction_en.properties b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/DistributedPurgeConfigurationAction_en.properties
new file mode 100644
index 0000000..661b0cb
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/DistributedPurgeConfigurationAction_en.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+
diff --git a/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/LocalRepositoryAction-saveRepository-validation.xml b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/LocalRepositoryAction-saveRepository-validation.xml
index 5dff912..bee7a11 100644
--- a/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/LocalRepositoryAction-saveRepository-validation.xml
+++ b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/LocalRepositoryAction-saveRepository-validation.xml
@@ -16,20 +16,28 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
   -->
-  
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
 
 <validators>
   <field name="repository.name">
     <field-validator type="requiredstring">
       <message key="repository.name.required"/>
     </field-validator>
+    <field-validator type="regex">
+      <param name="regex"><![CDATA[[A-Za-z0-9_.\s\-]*]]></param>
+      <message key="repository.name.invalid"/>
+    </field-validator>
   </field>
   <field name="repository.location">
     <field-validator type="requiredstring">
       <message key="repository.location.required"/>
     </field-validator>
+    <field-validator type="regex">
+      <param name="regex"><![CDATA[[A-Za-z0-9_.:\\/\s\-]*]]></param>
+      <message key="repository.location.invalid"/>
+    </field-validator>
   </field>
 </validators>
diff --git a/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/LocalRepositoryAction.properties b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/LocalRepositoryAction.properties
index 0d68796..6e8e0e0 100644
--- a/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/LocalRepositoryAction.properties
+++ b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/LocalRepositoryAction.properties
@@ -18,4 +18,6 @@
 #
 
 repository.name.required = You must define a name.
+repository.name.invalid = Local repository name contains invalid characters.
 repository.location.required = You must define a local repository directory.
+repository.location.invalid = Local repository location contains invalid characters.
\ No newline at end of file
diff --git a/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/LocalRepositoryAction_en.properties b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/LocalRepositoryAction_en.properties
new file mode 100644
index 0000000..661b0cb
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/LocalRepositoryAction_en.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+
diff --git a/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/LocalRepositoryAction_fr.properties b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/LocalRepositoryAction_fr.properties
new file mode 100644
index 0000000..eccb124
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/LocalRepositoryAction_fr.properties
@@ -0,0 +1,21 @@
+#
+# 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.
+#
+
+repository.name.required = Vous devez d\u00e9finir un nom.
+repository.location.required = Vous devez d\u00e9finir un r\u00e9pertoire pour le repository local.
diff --git a/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/PurgeConfigurationAction-savePurgeConfig-validation.xml b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/PurgeConfigurationAction-savePurgeConfig-validation.xml
index 9dc52de..362c47b 100644
--- a/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/PurgeConfigurationAction-savePurgeConfig-validation.xml
+++ b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/PurgeConfigurationAction-savePurgeConfig-validation.xml
@@ -16,10 +16,10 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
   -->
-  
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
 
 <validators>
   <field name="daysOlder">
diff --git a/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/PurgeConfigurationAction.properties b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/PurgeConfigurationAction.properties
index 283c816..edc2de2 100644
--- a/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/PurgeConfigurationAction.properties
+++ b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/PurgeConfigurationAction.properties
@@ -18,4 +18,5 @@
 #
 
 purgeConfig.daysOlder.min = Days Older must be a positive number.
-purgeConfig.retentionCount.min = Retention Count must be greater than 0.
\ No newline at end of file
+purgeConfig.retentionCount.min = Retention Count must be greater than 0.
+purgeConfig.description.invalid = Description contains invalid characters.
\ No newline at end of file
diff --git a/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/PurgeConfigurationAction_en.properties b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/PurgeConfigurationAction_en.properties
new file mode 100644
index 0000000..661b0cb
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/PurgeConfigurationAction_en.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+
diff --git a/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/PurgeConfigurationAction_fr.properties b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/PurgeConfigurationAction_fr.properties
new file mode 100644
index 0000000..dbfa344
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/continuum/web/action/admin/PurgeConfigurationAction_fr.properties
@@ -0,0 +1,21 @@
+#
+# 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.
+#
+
+purgeConfig.daysOlder.min = Le nombre de jour conserv\u00e9 doit \u00eatre un nombre positif.
+purgeConfig.retentionCount.min = Le nombre de fichiers gard\u00e9s en r\u00e9tention doit \u00eatre sup\u00e9rieur \u00e0 0.
\ No newline at end of file
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/redback/custom.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/redback/custom.properties
index 134092c..c85df52 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/redback/custom.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/redback/custom.properties
@@ -1,3 +1,22 @@
+#
+# 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.
+#
+
 # text resources within redback can be customized by overriding them here
 
 #password.reset.success=An email has been sent.
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/IrcNotifierEditAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/security_en.properties
similarity index 100%
rename from continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/IrcNotifierEditAction.properties
rename to continuum-webapp/src/main/resources/org/apache/maven/continuum/security_en.properties
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/security_fr.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/security_fr.properties
new file mode 100644
index 0000000..816bdb9
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/security_fr.properties
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+### $Id$
+
+# The subject line for the email message.
+email.validation.subject=Bienvenue sur Apache Continuum
+
+# Feedback page
+email.feedback.path=http://continuum.apache.org/mail-lists.html
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectAction-addProject-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectAction-addProject-validation.xml
index 783ebda..9f850a1 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectAction-addProject-validation.xml
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectAction-addProject-validation.xml
@@ -17,24 +17,45 @@
   ~ under the License.
   -->
 
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
 
 <validators>
   <field name="projectName">
     <field-validator type="requiredstring">
       <message key="addProject.name.required"/>
     </field-validator>
+    <field-validator type="regex">
+      <param name="trim">true</param>
+      <param name="regex"><![CDATA[[a-zA-Z0-9_.\s:-]*]]></param>
+      <message key="addProject.name.invalid"/>
+    </field-validator>
   </field>
   <field name="projectVersion">
     <field-validator type="requiredstring">
       <message key="addProject.version.required"/>
     </field-validator>
+    <field-validator type="regex">
+      <param name="trim">true</param>
+      <param name="regex"><![CDATA[[a-zA-Z0-9.-]*]]></param>
+      <message key="addProject.version.invalid"/>
+    </field-validator>
   </field>
   <field name="projectScmUrl">
     <field-validator type="requiredstring">
       <message key="addProject.scmUrl.required"/>
     </field-validator>
+    <field-validator type="regex">
+      <param name="regex"><![CDATA[[a-zA-Z0-9_.:${}#~=@\\/|\[\]-]*]]></param>
+      <message key="addProject.scmUrl.invalid"/>
+    </field-validator>
+  </field>
+  <field name="projectScmTag">
+    <field-validator type="regex">
+      <param name="trim">true</param>
+      <param name="regex"><![CDATA[[a-zA-Z0-9_.:@\\/|#~=\[\]-]*]]></param>
+      <message key="addProject.scmTag.invalid"/>
+    </field-validator>
   </field>
 </validators>
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectAction.properties
index aa069c7..4800870 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectAction.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectAction.properties
@@ -18,5 +18,10 @@
 #
 
 addProject.name.required = Name is required and cannot contain null or spaces only
-addProject.version.required = Version is required and cannot contain null or spaces only
-addProject.scmUrl.required = SCM Url is required and cannot contain null or spaces only
+addProject.name.invalid = Name contains invalid characters.
+addProject.version.required = Version is required and cannot contain null or spaces only.
+addProject.version.invalid = Version contains invalid characters.
+addProject.scmUrl.required = SCM Url is required and cannot contain null or spaces only.
+addProject.scmUrl.invalid =  SCM Url contains invalid characters.
+addProject.scmTag.invalid = SCM Tag contains invalid characters.
+addProject.projectGroup.required = Project Group is required and all projects must be in a project group
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectAction_en.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectAction_en.properties
new file mode 100644
index 0000000..661b0cb
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectAction_en.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectAction_fr.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectAction_fr.properties
index c3cab2e..1ae0ea8 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectAction_fr.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectAction_fr.properties
@@ -20,3 +20,4 @@
 addProject.name.required = le nom est obligatoire et ne peut pas contenir uniquement des espaces
 addProject.version.required = la version est obligatoire et ne peut pas contenir uniquement des espaces
 addProject.scmUrl.required = l''URL du gestionnaire de sources est obligatoire et ne peut pas contenir uniquement des espaces
+addProject.projectGroup.required = Le groupe de projets est requis et tous les projets doivent \u00eatre dans un groupe de projets
\ No newline at end of file
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectGroupAction-addProjectGroup-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectGroupAction-addProjectGroup-validation.xml
new file mode 100644
index 0000000..09954d3
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectGroupAction-addProjectGroup-validation.xml
@@ -0,0 +1,43 @@
+<!--
+  ~ 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.
+  -->
+
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
+
+<validators>
+  <field name="name">
+    <field-validator type="requiredstring">
+      <message key="addProjectGroup.name.required"/>
+    </field-validator>
+    <field-validator type="regex">
+      <param name="regex"><![CDATA[[A-Za-z0-9_.\s\-():\/,]*]]></param>
+      <message key="addProjectGroup.name.invalid"/>
+    </field-validator>
+  </field>
+  <field name="groupId">
+    <field-validator type="requiredstring">
+      <message key="addProjectGroup.groupId.required"/>
+    </field-validator>
+    <field-validator type="regex">
+      <param name="regex"><![CDATA[[a-zA-Z0-9_.\s\-]*]]></param>
+      <message key="addProjectGroup.groupId.invalid"/>
+    </field-validator>
+  </field>
+</validators>
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectGroupAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectGroupAction.properties
new file mode 100755
index 0000000..69f7e27
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectGroupAction.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+addProjectGroup.name.required = Project Group Name is required
+addProjectGroup.name.invalid = Name contains invalid characters.
+addProjectGroup.groupId.required = Project Group ID is required
+addProjectGroup.groupId.invalid = Id contains invalid characters.
+
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectGroupAction_de.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectGroupAction_de.properties
new file mode 100755
index 0000000..89c532e
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectGroupAction_de.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+addProjectGroup.name.required = Es mu\u00DF ein Projektgruppen-Name angegeben werden.
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectGroupAction_en.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectGroupAction_en.properties
new file mode 100755
index 0000000..661b0cb
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectGroupAction_en.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectGroupAction_fr.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectGroupAction_fr.properties
new file mode 100755
index 0000000..b2b9c6a
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectGroupAction_fr.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+addProjectGroup.name.required = le nom du groupe de projets est obligatoire
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectGroupAction_pt_BR.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectGroupAction_pt_BR.properties
new file mode 100755
index 0000000..fe13ae4
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/AddProjectGroupAction_pt_BR.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+addProjectGroup.name.required=Nome de Grupo do Projeto \u00E9 obrigat\u00F3rio
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionAction-saveBuildDefinition-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionAction-saveBuildDefinition-validation.xml
index 39a5a0c..2ddec90 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionAction-saveBuildDefinition-validation.xml
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionAction-saveBuildDefinition-validation.xml
@@ -17,14 +17,37 @@
   ~ under the License.
   -->
 
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
 
 <validators>
   <field name="buildFile">
     <field-validator type="requiredstring">
       <message key="buildDefinition.buildFile.required"/>
     </field-validator>
+    <field-validator type="regex">
+      <param name="trim">true</param>
+      <param name="regex"><![CDATA[[A-Za-z0-9_.\-/\\]*]]></param>
+      <message key="buildDefinition.buildFile.invalid"/>
+    </field-validator>
+  </field>
+  <field name="goals">
+    <field-validator type="fieldexpression">
+      <param name="expression">not isMavenBuildType(buildDefinitionType) or goals.trim().length() > 0</param>
+      <message key="buildDefinition.goals.required"/>
+    </field-validator>
+    <field-validator type="regex">
+      <param name="trim">true</param>
+      <param name="regex"><![CDATA[[A-Za-z0-9_:\s.\-]*]]></param>
+      <message key="buildDefinition.goals.invalid"/>
+    </field-validator>
+  </field>
+  <field name="arguments">
+    <field-validator type="regex">
+      <param name="trim">true</param>
+      <param name="regex"><![CDATA[[!A-Za-z0-9_${}.\\/=,":\s\-]*]]></param>
+      <message key="buildDefinition.arguments.invalid"/>
+    </field-validator>
   </field>
 </validators>
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionAction-saveGroupBuildDefinition-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionAction-saveGroupBuildDefinition-validation.xml
deleted file mode 100644
index e69de29..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionAction-saveGroupBuildDefinition-validation.xml
+++ /dev/null
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionAction-saveProjectBuildDefinition-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionAction-saveProjectBuildDefinition-validation.xml
deleted file mode 100644
index e69de29..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionAction-saveProjectBuildDefinition-validation.xml
+++ /dev/null
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionAction.properties
index ec147b1..38c528e 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionAction.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionAction.properties
@@ -17,4 +17,8 @@
 # under the License.
 #
 
-buildDefinition.buildFile.required = Build file is required and cannot contain spaces only
+buildDefinition.buildFile.required = Build file is required and cannot contain spaces only.
+buildDefinition.buildFile.invalid = Build file contains invalid characters.
+buildDefinition.goals.required = Goals are required.
+buildDefinition.goals.invalid = Goals contains invalid characters.
+buildDefinition.arguments.invalid = Arguments contains invalid characters. 
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionAction_en.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionAction_en.properties
new file mode 100644
index 0000000..661b0cb
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionAction_en.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionAction_pt_BR.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionAction_pt_BR.properties
index d14d917..6affbe8 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionAction_pt_BR.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionAction_pt_BR.properties
@@ -16,4 +16,5 @@
 # specific language governing permissions and limitations
 # under the License.
 #
+
 buildDefinition.buildFile.required=Arquivo de Build \u00E9 obrigat\u00F3rio e n\u00E3o pode conter somente espa\u00E7os
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionEditAction-buildDefinitionSave-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionEditAction-buildDefinitionSave-validation.xml
deleted file mode 100644
index eba222b..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionEditAction-buildDefinitionSave-validation.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
-
-<validators>
-  <field name="buildFile">
-    <field-validator type="required">
-      <message key="BuildDefinition.buildFile.required"/>
-    </field-validator>
-  </field>
-</validators>
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionEditAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionEditAction.properties
deleted file mode 100644
index 343b331..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionEditAction.properties
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# 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.
-#
-
-BuildDefinition.buildFile.required = This field is required
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionEditAction_de.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionEditAction_de.properties
deleted file mode 100644
index 8eed6a3..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionEditAction_de.properties
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# 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.
-#
-
-BuildDefinition.buildFile.required = Pflichtfeld
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionEditAction_fr.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionEditAction_fr.properties
deleted file mode 100644
index 61ede8a..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionEditAction_fr.properties
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# 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.
-#
-
-BuildDefinition.buildFile.required = Ce champ est obligatoire
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionEditAction_pt_BR.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionEditAction_pt_BR.properties
deleted file mode 100644
index b815558..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/BuildDefinitionEditAction_pt_BR.properties
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# 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.
-#
-
-BuildDefinition.buildFile.required = Este campo é obrigatório
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/IrcNotifierEditAction-ircNotifierSave-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/IrcNotifierEditAction-ircNotifierSave-validation.xml
deleted file mode 100644
index cf613e8..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/IrcNotifierEditAction-ircNotifierSave-validation.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/IrcNotifierEditAction_de.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/IrcNotifierEditAction_de.properties
deleted file mode 100644
index d8a500d..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/IrcNotifierEditAction_de.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# 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.
-#
-
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/IrcNotifierEditAction_fr.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/IrcNotifierEditAction_fr.properties
deleted file mode 100644
index d8a500d..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/IrcNotifierEditAction_fr.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# 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.
-#
-
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/IrcNotifierEditAction_pt_BR.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/IrcNotifierEditAction_pt_BR.properties
deleted file mode 100644
index d8a500d..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/IrcNotifierEditAction_pt_BR.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# 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.
-#
-
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/JabberNotifierEditAction-jabberNotifierSave-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/JabberNotifierEditAction-jabberNotifierSave-validation.xml
deleted file mode 100644
index cf613e8..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/JabberNotifierEditAction-jabberNotifierSave-validation.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/JabberNotifierEditAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/JabberNotifierEditAction.properties
deleted file mode 100644
index d8a500d..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/JabberNotifierEditAction.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# 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.
-#
-
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/JabberNotifierEditAction_de.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/JabberNotifierEditAction_de.properties
deleted file mode 100644
index d8a500d..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/JabberNotifierEditAction_de.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# 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.
-#
-
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/JabberNotifierEditAction_fr.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/JabberNotifierEditAction_fr.properties
deleted file mode 100644
index d8a500d..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/JabberNotifierEditAction_fr.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# 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.
-#
-
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/JabberNotifierEditAction_pt_BR.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/JabberNotifierEditAction_pt_BR.properties
deleted file mode 100644
index d8a500d..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/JabberNotifierEditAction_pt_BR.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# 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.
-#
-
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/LoginAction-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/LoginAction-validation.xml
deleted file mode 100644
index 2fa9efd..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/LoginAction-validation.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
-
-<validators>
-  <field name="username">
-    <field-validator type="required">
-      <message key="login.username.required"/>
-    </field-validator>
-  </field>
-  <field name="password">
-    <field-validator type="required">
-      <message key="login.password.required"/>
-    </field-validator>
-  </field>
-</validators>
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/LoginAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/LoginAction.properties
deleted file mode 100644
index 6447f11..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/LoginAction.properties
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# 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.
-#
-
-login.username.required = Username is required!
-login.password.required = Password is required!
-login.bad_login_password = Username/password incorrect
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/LoginAction_de.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/LoginAction_de.properties
deleted file mode 100644
index 0646874..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/LoginAction_de.properties
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# 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.
-#
-
-login.username.required = Es mu\u00DF ein Benutzername angegeben werden.
-login.password.required = Es mu\u00DF ein Passwort angegeben werden.
-login.bad_login_password = Ung\u00FCltige Kombination von Benutzername und Passwort.
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/LoginAction_fr.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/LoginAction_fr.properties
deleted file mode 100644
index 4239fff..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/LoginAction_fr.properties
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# 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.
-#
-
-login.username.required = Le nom d''utilisateur est obligatoire!
-login.password.required = Le mot de passe est obligatoire!
-login.bad_login_password = nom d''utilisateur/mot de passe incorrect
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/LoginAction_pt_BR.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/LoginAction_pt_BR.properties
deleted file mode 100644
index 7d67a79..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/LoginAction_pt_BR.properties
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# 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.
-#
-login.bad_login_password=Usu\u00E1rio / Senha incorreta \!
-login.password.required=Senha \u00E9 obrigat\u00F3ria \!
-login.username.required=Usu\u00E1rio \u00E9 obrigat\u00F3rio \!
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MailNotifierEditAction-mailNotifierSave-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MailNotifierEditAction-mailNotifierSave-validation.xml
deleted file mode 100644
index cf613e8..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MailNotifierEditAction-mailNotifierSave-validation.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MailNotifierEditAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MailNotifierEditAction.properties
deleted file mode 100644
index d8a500d..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MailNotifierEditAction.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# 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.
-#
-
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MailNotifierEditAction_de.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MailNotifierEditAction_de.properties
deleted file mode 100644
index d8a500d..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MailNotifierEditAction_de.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# 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.
-#
-
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MailNotifierEditAction_fr.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MailNotifierEditAction_fr.properties
deleted file mode 100644
index d8a500d..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MailNotifierEditAction_fr.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# 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.
-#
-
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MailNotifierEditAction_pt_BR.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MailNotifierEditAction_pt_BR.properties
deleted file mode 100644
index d8a500d..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MailNotifierEditAction_pt_BR.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# 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.
-#
-
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MsnNotifierEditAction-msnNotifierSave-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MsnNotifierEditAction-msnNotifierSave-validation.xml
deleted file mode 100644
index cf613e8..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MsnNotifierEditAction-msnNotifierSave-validation.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MsnNotifierEditAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MsnNotifierEditAction.properties
deleted file mode 100644
index d8a500d..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MsnNotifierEditAction.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# 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.
-#
-
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MsnNotifierEditAction_de.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MsnNotifierEditAction_de.properties
deleted file mode 100644
index d8a500d..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MsnNotifierEditAction_de.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# 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.
-#
-
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MsnNotifierEditAction_fr.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MsnNotifierEditAction_fr.properties
deleted file mode 100644
index d8a500d..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MsnNotifierEditAction_fr.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# 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.
-#
-
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MsnNotifierEditAction_pt_BR.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MsnNotifierEditAction_pt_BR.properties
deleted file mode 100644
index d8a500d..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/MsnNotifierEditAction_pt_BR.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# 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.
-#
-
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectEditAction-projectSave-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectEditAction-projectSave-validation.xml
index 8270226..5d4e0dd 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectEditAction-projectSave-validation.xml
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectEditAction-projectSave-validation.xml
@@ -17,24 +17,46 @@
   ~ under the License.
   -->
 
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
 
 <validators>
   <field name="name">
     <field-validator type="requiredstring">
       <message key="projectEdit.name.required"/>
     </field-validator>
+    <field-validator type="regex">
+      <param name="trim">true</param>
+      <param name="regex"><![CDATA[[a-zA-Z0-9_.\s:-]*]]></param>
+      <message key="projectEdit.name.invalid"/>
+    </field-validator>
   </field>
   <field name="version">
     <field-validator type="requiredstring">
       <message key="projectEdit.version.required"/>
     </field-validator>
+    <field-validator type="regex">
+      <param name="trim">true</param>
+      <param name="regex"><![CDATA[[a-zA-Z0-9.-]*]]></param>
+      <message key="projectEdit.version.invalid"/>
+    </field-validator>
   </field>
   <field name="scmUrl">
     <field-validator type="requiredstring">
       <message key="projectEdit.scmUrl.required"/>
     </field-validator>
+    <field-validator type="regex">
+      <param name="trim">true</param>
+      <param name="regex"><![CDATA[[a-zA-Z0-9_.:@\\/|#~=\[\]-]*]]></param>
+      <message key="projectEdit.scmUrl.invalid"/>
+    </field-validator>
+  </field>
+  <field name="scmTag">
+    <field-validator type="regex">
+      <param name="trim">true</param>
+      <param name="regex"><![CDATA[[a-zA-Z0-9_.:@\\/|#~=\[\]-]*]]></param>
+      <message key="projectEdit.scmTag.invalid"/>
+    </field-validator>
   </field>
 </validators>
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectEditAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectEditAction.properties
index f804814..4ebc272 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectEditAction.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectEditAction.properties
@@ -17,6 +17,10 @@
 # under the License.
 #
 
-projectEdit.name.required = Project Name is required
-projectEdit.version.required = version is required
-projectEdit.scmUrl.required = scmUrl is required
+projectEdit.name.required = Project Name is required.
+projectEdit.name.invalid = Name contains invalid characters.
+projectEdit.version.required = Version is required.
+projectEdit.version.invalid = Version contains invalid characters.
+projectEdit.scmUrl.required = Scm Url is required.
+projectEdit.scmUrl.invalid = Scm Url contains invalid characters.
+projectEdit.scmTag.invalid = Scm Tag contains invalid characters.
\ No newline at end of file
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectEditAction_en.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectEditAction_en.properties
new file mode 100644
index 0000000..661b0cb
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectEditAction_en.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectEditAction_pt_BR.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectEditAction_pt_BR.properties
index 0ea5835..3567c7b 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectEditAction_pt_BR.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectEditAction_pt_BR.properties
@@ -16,6 +16,7 @@
 # specific language governing permissions and limitations
 # under the License.
 #
+
 projectEdit.name.required=Nome do Projeto \u00E9 obrigat\u00F3rio
 projectEdit.scmUrl.required=scmUrl \u00E9 obrigat\u00F3ria
 projectEdit.version.required=vers\u00E3o \u00E9 obrigat\u00F3ria
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectGroupAction-saveProjectGroup-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectGroupAction-saveProjectGroup-validation.xml
index e49023a..a53d10d 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectGroupAction-saveProjectGroup-validation.xml
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectGroupAction-saveProjectGroup-validation.xml
@@ -17,14 +17,18 @@
   ~ under the License.
   -->
 
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
 
 <validators>
   <field name="name">
-    <field-validator type="required">
+    <field-validator type="requiredstring">
       <message key="projectGroup.name.required"/>
     </field-validator>
+    <field-validator type="regex">
+      <param name="regex"><![CDATA[[A-Za-z0-9_.\s\-():\/,]*]]></param>
+      <message key="projectGroup.name.invalid"/>
+    </field-validator>
   </field>
 </validators>
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectGroupAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectGroupAction.properties
index 32dcc5d..38200ce 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectGroupAction.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectGroupAction.properties
@@ -18,3 +18,5 @@
 #
 
 projectGroup.name.required = Project Group Name is required
+projectGroup.name.invalid = Name contains invalid characters.
+
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectGroupAction_en.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectGroupAction_en.properties
new file mode 100644
index 0000000..661b0cb
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectGroupAction_en.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectGroupAction_pt_BR.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectGroupAction_pt_BR.properties
index 99abfc4..a992fee 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectGroupAction_pt_BR.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ProjectGroupAction_pt_BR.properties
@@ -16,4 +16,5 @@
 # specific language governing permissions and limitations
 # under the License.
 #
+
 projectGroup.name.required=Nome de Grupo do Projeto \u00E9 obrigat\u00F3rio
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePerformAction-releasePerform-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePerformAction-releasePerform-validation.xml
index 7ef3a4f..7d082a1 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePerformAction-releasePerform-validation.xml
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePerformAction-releasePerform-validation.xml
@@ -17,9 +17,9 @@
   ~ under the License.
   -->
 
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
 
 <validators>
   <field name="goals">
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePerformAction-releasePerformFromScm-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePerformAction-releasePerformFromScm-validation.xml
index e0a7cac..0087b5a 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePerformAction-releasePerformFromScm-validation.xml
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePerformAction-releasePerformFromScm-validation.xml
@@ -17,9 +17,9 @@
   ~ under the License.
   -->
 
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
 
 <validators>
   <field name="scmUrl">
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePerformAction_en.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePerformAction_en.properties
new file mode 100644
index 0000000..661b0cb
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePerformAction_en.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePerformAction_pt_BR.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePerformAction_pt_BR.properties
index cad9650..02afcb1 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePerformAction_pt_BR.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePerformAction_pt_BR.properties
@@ -16,6 +16,7 @@
 # specific language governing permissions and limitations
 # under the License.
 #
+
 releasePerformAction.goals.required="Goal(s)" do maven para executar a a\u00E7\u00E3o de libera\u00E7\u00E3o \u00E9 obrigat\u00F3rio.
 releasePerformAction.scmTag.required=Tag SCM ou etiqueta de libera\u00E7\u00E3o para uso nesta libera\u00E7\u00E3o \u00E9 obrigat\u00F3rio.
 releasePerformAction.scmUrl.required=Url SCM do projeto a ser liberado \u00E9 obrigat\u00F3rio.
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePrepareAction-releasePrepare-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePrepareAction-releasePrepare-validation.xml
index 66c4b67..66e15ca 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePrepareAction-releasePrepare-validation.xml
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePrepareAction-releasePrepare-validation.xml
@@ -17,21 +17,11 @@
   ~ under the License.
   -->
 
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
 
 <validators>
-  <field name="scmUsername">
-    <field-validator type="requiredstring">
-      <message key="releasePrepareAction.scmUsername.required"/>
-    </field-validator>
-  </field>
-  <field name="scmPassword">
-    <field-validator type="requiredstring">
-      <message key="releasePrepareAction.scmPassword.required"/>
-    </field-validator>
-  </field>
   <field name="scmTag">
     <field-validator type="requiredstring">
       <message key="releasePrepareAction.scmTag.required"/>
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePrepareAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePrepareAction.properties
index 19eea34..1226d2a 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePrepareAction.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePrepareAction.properties
@@ -17,7 +17,5 @@
 # under the License.
 #
 
-releasePrepareAction.scmUsername.required=SCM username with commit rights is required for release.
-releasePrepareAction.scmPassword.required=SCM password for the username above is required.
 releasePrepareAction.scmTag.required=SCM tag or release label to use for this release is required.
 releasePrepareAction.prepareGoals.required=The maven release preparation goal(s) is required.
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePrepareAction_de.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePrepareAction_de.properties
index 8fa9c62..c70b757 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePrepareAction_de.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePrepareAction_de.properties
@@ -17,7 +17,5 @@
 # under the License.
 #
 
-releasePrepareAction.scmUsername.required=Es mu\u00DF ein SCM-Benutzer mit Schreibrechten f\u00FCr die Ver\u00F6ffentlichung angegeben werden.
-releasePrepareAction.scmPassword.required=Es mu\u00DF ein Passwort f\u00FCr obigen SCM-Benutzer angegeben werden.
 releasePrepareAction.scmTag.required=Es mu\u00DF eine SCM-Markierung oder ein Ver\u00F6ffentlichungs-Kennzeichen f\u00FCr diese Ver\u00F6ffentlichung angegeben werden.
 releasePrepareAction.prepareGoals.required=Es m\u00FCssen die f\u00FCr die Ver\u00F6ffentlichung auszuf\u00FChrenden Maven-Goals angegeben werden.
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePrepareAction_en.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePrepareAction_en.properties
new file mode 100644
index 0000000..661b0cb
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePrepareAction_en.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePrepareAction_fr.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePrepareAction_fr.properties
index b6c19f0..b1c9c31 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePrepareAction_fr.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePrepareAction_fr.properties
@@ -17,7 +17,5 @@
 # under the License.
 #
 
-releasePrepareAction.scmUsername.required=Le nom d''utilisateur du gestionnaire de sources avec les droits de livraison est obligatoire pour effectuer la "release".
-releasePrepareAction.scmPassword.required=Le mot de passe du gestionnaire de sources pour l''utilisateur fournit est obligatoire.
 releasePrepareAction.scmTag.required=Le tag du gestionnaire de sources ou le libell\u00e9 de "release" \u00e0 utiliser pour cette "release" est obligatoire.
 releasePrepareAction.prepareGoals.required=Le(s) goal(s) de pr\u00e9paration de la "release" maven est obligatoire. 
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePrepareAction_pt_BR.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePrepareAction_pt_BR.properties
index 00bd0a2..b34038c 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePrepareAction_pt_BR.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ReleasePrepareAction_pt_BR.properties
@@ -16,7 +16,5 @@
 # specific language governing permissions and limitations
 # under the License.
 #
-releasePrepareAction.prepareGoals.required=O(s) "goal(s)" de libera\u00E7\u00E3o do maven \u00E9 obrigat\u00F3rio.
-releasePrepareAction.scmPassword.required=Senha SCM para o usu\u00E1rio acima \u00E9 obrigat\u00F3rio.
+
 releasePrepareAction.scmTag.required=Tag SCM or etiqueta de libera\u00E7\u00E3o para uso nessa libera\u00E7\u00E3o \u00E9 obrigat\u00F3rio.
-releasePrepareAction.scmUsername.required=Usu\u00E1rio SCM com direitos de commit \u00E9 obrigat\u00F3rio para esta libera\u00E7\u00E3o.
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ScheduleAction-saveSchedule-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ScheduleAction-saveSchedule-validation.xml
index 19e9236..3b151db 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ScheduleAction-saveSchedule-validation.xml
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ScheduleAction-saveSchedule-validation.xml
@@ -17,19 +17,24 @@
   ~ under the License.
   -->
 
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
 
 <validators>
   <field name="name">
     <field-validator type="requiredstring">
       <message key="schedule.name.required"/>
     </field-validator>
+    <field-validator type="regex">
+      <param name="trim">true</param>
+      <param name="regex"><![CDATA[[a-zA-Z0-9_.\s-]*]]></param>
+      <message key="schedule.name.invalid"/>
+    </field-validator>
   </field>
   <field name="description">
     <field-validator type="requiredstring">
-      <message key="schedule.version.required"/>
+      <message key="schedule.description.required"/>
     </field-validator>
   </field>
   <field name="maxJobExecutionTime">
@@ -37,14 +42,14 @@
       <message key="schedule.maxJobExecutionTime.required"/>
     </field-validator>
     <field-validator type="regex">
-      <param name="expression"><![CDATA[([0-9])]]></param>
+      <param name="regex"><![CDATA[([0-9])]]></param>
       <message key="schedule.maxJobExecutionTime.invalid"/>
     </field-validator>
   </field>
   <field name="delay">
     <field-validator type="regex">
-      <param name="expression"><![CDATA[([0-9])]]></param>
-      <message key="schedule.delay.invalid"/>  
+      <param name="regex"><![CDATA[([0-9])]]></param>
+      <message key="schedule.delay.invalid"/>
     </field-validator>
   </field>
   <validator type="cronexpression">
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ScheduleAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ScheduleAction.properties
index 77103c4..f11c7db 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ScheduleAction.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ScheduleAction.properties
@@ -17,8 +17,9 @@
 # under the License.
 #
 
-schedule.name.required = Name is required and cannot contain spaces only
-schedule.version.required = Description is required and cannot contain spaces only
-schedule.maxJobExecutionTime.required = Maximum job execution time is required
-schedule.maxJobExecutionTime.invalid = Maximum job execution time must be an integer
-schedule.delay.invalid = Quiet period must be an integer 
+schedule.name.required = Name is required and cannot contain spaces only.
+schedule.name.invalid = Name contains invalid characters.
+schedule.description.required = Description is required and cannot contain spaces only.
+schedule.maxJobExecutionTime.required = Maximum job execution time is required.
+schedule.maxJobExecutionTime.invalid = Maximum job execution time must be an integer.
+schedule.delay.invalid = Quiet period must be an integer.
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ScheduleAction_de.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ScheduleAction_de.properties
index f7cb8c2..eaba423 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ScheduleAction_de.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ScheduleAction_de.properties
@@ -18,7 +18,7 @@
 #
 
 schedule.name.required = Es mu\u00DF ein Name angegeben werden.
-schedule.version.required = Es mu\u00DF eine Beschreibung angegeben werden.
+schedule.description.required = Es mu\u00DF eine Beschreibung angegeben werden.
 schedule.maxJobExecutionTime.required = Es mu\u00DF eine maximale Ausf\u00FChrungszeit angegeben werden.
 schedule.maxJobExecutionTime.invalid = Es mu\u00DF eine Zahl f\u00FCr die maximale Ausf\u00FChrungszeit angegeben werden.
 schedule.delay.invalid = Es mu\u00DF eine Zahl f\u00FCr die Ruhezeit angegeben werden.
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ScheduleAction_en.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ScheduleAction_en.properties
new file mode 100644
index 0000000..661b0cb
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ScheduleAction_en.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ScheduleAction_fr.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ScheduleAction_fr.properties
index eae3789..2626f6a 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ScheduleAction_fr.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ScheduleAction_fr.properties
@@ -18,7 +18,7 @@
 #
 
 schedule.name.required = le nom est obligatoire et ne peut pas contenir uniquement des espaces
-schedule.version.required = la description est obligatoire et ne peut pas contenir uniquement des espaces
+schedule.description.required = la description est obligatoire et ne peut pas contenir uniquement des espaces
 schedule.maxJobExecutionTime.required = le temp d''ex\u00e9cution du travail maximum est obligatoire
 schedule.maxJobExecutionTime.invalid = le temp d''ex\u00e9cution du travail maximum doit \u00eatre un entier
 schedule.delay.invalid = la p\u00e9riode d''attente doit \u00eatre un entier 
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ScheduleAction_pt_BR.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ScheduleAction_pt_BR.properties
index 6e0b24e..561ac5d 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ScheduleAction_pt_BR.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/ScheduleAction_pt_BR.properties
@@ -16,8 +16,9 @@
 # specific language governing permissions and limitations
 # under the License.
 #
+
 schedule.delay.invalid=Per\u00EDodo de espera deve ser um inteiro
 schedule.maxJobExecutionTime.invalid=Tempo de execu\u00E7\u00E3o m\u00E1xima de um job deve ser um inteiro
 schedule.maxJobExecutionTime.required=Tempo de execu\u00E7\u00E3o m\u00E1xima de um job \u00E9 obrigat\u00F3rio
 schedule.name.required=Nome \u00E9 obrigat\u00F3rio e n\u00E3o pode conter somente espa\u00E7os
-schedule.version.required=Descri\u00E7\u00E3o \u00E9 obrigat\u00F3ria e n\u00E3o pode conter somente espa\u00E7os
+schedule.description.required=Descri\u00E7\u00E3o \u00E9 obrigat\u00F3ria e n\u00E3o pode conter somente espa\u00E7os
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserGroupManagementAction-saveUserGroup-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserGroupManagementAction-saveUserGroup-validation.xml
deleted file mode 100644
index 193d783..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserGroupManagementAction-saveUserGroup-validation.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
-
-<validators>
-  <field name="name">
-    <field-validator type="required">
-      <message key="userGroup.name.required"/>
-    </field-validator>
-  </field>
-</validators>
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserGroupManagementAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserGroupManagementAction.properties
deleted file mode 100644
index c1c7c42..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserGroupManagementAction.properties
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# 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.
-#
-
-userGroup.name.required = Name is required
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserGroupManagementAction_de.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserGroupManagementAction_de.properties
deleted file mode 100644
index f21b66b..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserGroupManagementAction_de.properties
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# 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.
-#
-
-userGroup.name.required = Es mu\u00DF ein Name angegeben werden.
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserGroupManagementAction_fr.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserGroupManagementAction_fr.properties
deleted file mode 100644
index 97e91f8..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserGroupManagementAction_fr.properties
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# 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.
-#
-
-userGroup.name.required = le nom est obligatoire
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserGroupManagementAction_pt_BR.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserGroupManagementAction_pt_BR.properties
deleted file mode 100644
index fa8cdd5..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserGroupManagementAction_pt_BR.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# 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.
-#
-userGroup.name.required=Nome \u00E9 obrigat\u00F3rio
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserManagementAction-saveUser-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserManagementAction-saveUser-validation.xml
deleted file mode 100644
index 9dbf59f..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserManagementAction-saveUser-validation.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
-
-<validators>
-  <field name="username">
-    <field-validator type="required">
-      <message key="user.username.required"/>
-    </field-validator>
-  </field>
-  <field name="fullName">
-    <field-validator type="required">
-      <message key="user.fullname.required"/>
-    </field-validator>
-  </field>
-  <field name="password">
-    <field-validator type="requiredstring">
-      <message key="user.password.required"/>
-    </field-validator>
-  </field>
-  <field name="passwordTwo">
-    <field-validator type="requiredstring">
-      <message key="user.passwordTwo.required"/>
-    </field-validator>
-  </field>
-  <validator type="expression">
-    <param name="expression">
-      password.equals(passwordTwo)</param>
-    <message key="user.passwordTwo.nomatch"/>
-  </validator>
-</validators>
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserManagementAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserManagementAction.properties
deleted file mode 100644
index f49da0e..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserManagementAction.properties
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# 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.
-#
-
-user.username.required = Username is required
-user.fullname.required = Full Name is required
-user.password.required = Password is required
-user.passwordTwo.required = Confirm password is required
-user.passwordTwo.nomatch = Password does not match
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserManagementAction_de.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserManagementAction_de.properties
deleted file mode 100644
index 851c04e..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserManagementAction_de.properties
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# 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.
-#
-
-user.username.required = Es mu\u00DF ein Benutzername angegeben werden.
-user.fullname.required = Es mu\u00DF ein vollst\u00E4ndiger Name angegeben werden.
-user.password.required = Es mu\u00DF ein Passwort angegeben werden.
-user.passwordTwo.required = Es mu\u00DF eine Passwortbest\u00E4tigung angegeben werden.
-user.passwordTwo.nomatch = Passwort und Passwortbest\u00E4tigung stimmen nicht \u00FCberein.
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserManagementAction_fr.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserManagementAction_fr.properties
deleted file mode 100644
index 4b9b9f4..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserManagementAction_fr.properties
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# 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.
-#
-
-user.username.required = Le nom d''utilisateur est obligatoire
-user.fullname.required = le nom Complet est obligatoire
-user.password.required = le mot de passe est obligatoire
-user.passwordTwo.required = la confirmation du mot de passe est obligatoire
-user.passwordTwo.nomatch = Les mots de passe ne correspondent pas
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserManagementAction_pt_BR.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserManagementAction_pt_BR.properties
deleted file mode 100644
index 7f67146..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/UserManagementAction_pt_BR.properties
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# 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.
-#
-user.fullname.required=Nome completo \u00E9 obrigat\u00F3rio
-user.password.required=Senha \u00E9 obrigat\u00F3rio
-user.passwordTwo.nomatch=Senha n\u00E3o confere
-user.passwordTwo.required=Confirma\u00E7\u00E3o de senha \u00E9 obrigat\u00F3rio
-user.username.required=Nome de usu\u00E1rio \u00E9 obrigat\u00F3rio
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction-saveBuildDefinitionAsTemplate-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction-saveBuildDefinitionAsTemplate-validation.xml
index 132b457..ef5f332 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction-saveBuildDefinitionAsTemplate-validation.xml
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction-saveBuildDefinitionAsTemplate-validation.xml
@@ -17,19 +17,39 @@
   ~ under the License.
   -->
 
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
 
 <validators>
   <field name="buildDefinition.buildFile">
     <field-validator type="requiredstring">
-      <message key="buildDefintion.buildFile.required"/>
+      <message key="buildDefinition.buildFile.required"/>
+    </field-validator>
+    <field-validator type="regex">
+      <param name="regex"><![CDATA[[A-Za-z0-9_.\-]*]]></param>
+      <message key="buildDefinition.buildFile.invalid"/>
     </field-validator>
   </field>
   <field name="buildDefinition.description">
     <field-validator type="requiredstring">
-      <message key="buildDefintion.description.required"/>
+      <message key="buildDefinition.description.required"/>
     </field-validator>
-  </field>  
-</validators>
\ No newline at end of file
+  </field>
+  <field name="buildDefinition.goals">
+    <field-validator type="fieldexpression">
+      <param name="expression">not isMavenBuildType(buildDefinition.type) or buildDefinition.goals.trim().length() > 0</param>
+      <message key="buildDefinition.goals.required"/>
+    </field-validator>
+    <field-validator type="regex">
+      <param name="regex"><![CDATA[[A-Za-z0-9_:\s\-]*]]></param>
+      <message key="buildDefinition.goals.invalid"/>
+    </field-validator>
+  </field>
+  <field name="buildDefinition.arguments">
+    <field-validator type="regex">
+      <param name="regex"><![CDATA[[!A-Za-z0-9_${}.\\/=,":\s\-]*]]></param>
+      <message key="buildDefinition.arguments.invalid"/>
+    </field-validator>
+  </field>
+</validators>
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction-saveBuildDefinitionTemplate-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction-saveBuildDefinitionTemplate-validation.xml
index 352288e..6a559d2 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction-saveBuildDefinitionTemplate-validation.xml
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction-saveBuildDefinitionTemplate-validation.xml
@@ -17,14 +17,22 @@
   ~ under the License.
   -->
 
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
 
 <validators>
   <field name="buildDefinitionTemplate.name">
     <field-validator type="requiredstring">
-      <message key="buildDefintionTemplate.name.required"/>
+      <message key="buildDefinitionTemplate.name.required"/>
+    </field-validator>
+    <field-validator type="regex">
+      <param name="regex"><![CDATA[[A-Za-z0-9_.\s\-]*]]></param>
+      <message key="buildDefinitionTemplate.name.invalid"/>
     </field-validator>
   </field>
-</validators>
\ No newline at end of file
+  <validator type="expression">
+    <param name="expression">#selectedDefs = buildDefinitionsFromSelectedBuildDefinitions, #selectedDefs != null and #selectedDefs.size() > 0</param>
+    <message key="buildDefinitionTemplate.definition.empty" />
+  </validator>
+</validators>
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction.properties
index 15f8fd4..90441b8 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction.properties
@@ -16,6 +16,15 @@
 # specific language governing permissions and limitations
 # under the License.
 #
-buildDefintionTemplate.name.required = Name is required
-buildDefintion.buildFile.required = BuildFile is required
-buildDefintion.description.required = Description is required
\ No newline at end of file
+
+buildDefinitionTemplate.name.exists = Name already exists
+buildDefinitionTemplate.name.required = Name is required
+buildDefinitionTemplate.definition.empty = Template requires at least one build definition
+buildDefinitionTemplate.name.invalid = Name contains invalid characters
+buildDefinition.buildFile.required = BuildFile is required
+buildDefinition.buildFile.invalid = BuildFile contains invalid characters
+buildDefinition.description.required = Description is required
+buildDefinition.used = Build definition is used by a template
+buildDefinition.goals.required = Goals are required
+buildDefinition.goals.invalid = Goals contain invalid characters
+buildDefinition.arguments.invalid = Arguments contain invalid characters
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction_de.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction_de.properties
index 0fa8544..2ca6bac 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction_de.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction_de.properties
@@ -16,6 +16,7 @@
 # specific language governing permissions and limitations
 # under the License.
 #
-buildDefintionTemplate.name.required = Es mu\u00DF ein Name angegeben werden.
-buildDefintion.buildFile.required = Es mu\u00DF eine Projektdatei angegeben werden.
-buildDefintion.description.required = Es mu\u00DF eine Beschreibung angegeben werden.
+
+buildDefinitionTemplate.name.required = Es mu\u00DF ein Name angegeben werden.
+buildDefinition.buildFile.required = Es mu\u00DF eine Projektdatei angegeben werden.
+buildDefinition.description.required = Es mu\u00DF eine Beschreibung angegeben werden.
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/IrcNotifierEditAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction_en.properties
similarity index 100%
copy from continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/IrcNotifierEditAction.properties
copy to continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction_en.properties
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction_fr.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction_fr.properties
index 16dd5b2..26a9590 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction_fr.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction_fr.properties
@@ -16,6 +16,7 @@
 # specific language governing permissions and limitations
 # under the License.
 #
-buildDefintionTemplate.name.required = le nom est obligatoire
-buildDefintion.buildFile.required = le fichier de construction est obligatoire
-buildDefintion.description.required = la description est obligatoire
+
+buildDefinitionTemplate.name.required = le nom est obligatoire
+buildDefinition.buildFile.required = le fichier de construction est obligatoire
+buildDefinition.description.required = la description est obligatoire
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction_pt_BR.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction_pt_BR.properties
index 4ce6036..0589abf 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction_pt_BR.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildDefinitionTemplateAction_pt_BR.properties
@@ -16,6 +16,7 @@
 # specific language governing permissions and limitations
 # under the License.
 #
-buildDefintionTemplate.name.required = Nome é obrigatório
-buildDefintion.buildFile.required = Arquivo de Build é obrigatório
-buildDefintion.description.required = Descrição é obrigatória
\ No newline at end of file
+
+buildDefinitionTemplate.name.required = Nome é obrigatório
+buildDefinition.buildFile.required = Arquivo de Build é obrigatório
+buildDefinition.description.required = Descrição é obrigatória
\ No newline at end of file
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildQueueAction-saveBuildQueue-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildQueueAction-saveBuildQueue-validation.xml
new file mode 100644
index 0000000..df6560f
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildQueueAction-saveBuildQueue-validation.xml
@@ -0,0 +1,34 @@
+<!--
+  ~ 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.
+  -->
+
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
+
+<validators>
+  <field name="name">
+    <field-validator type="requiredstring">
+      <message key="buildqueue.name.required"/>
+    </field-validator>
+    <field-validator type="regex">
+      <param name="regex"><![CDATA[[A-Za-z0-9_.\s\-]*]]></param>
+      <message key="buildqueue.name.invalid"/>
+    </field-validator>
+  </field>
+</validators>
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildQueueAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildQueueAction.properties
new file mode 100644
index 0000000..af18850
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildQueueAction.properties
@@ -0,0 +1,21 @@
+#
+# 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.
+#
+
+buildqueue.name.required = You must define a name.
+buildqueue.name.invalid = Build queue name contains invalid characters.
\ No newline at end of file
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildQueueAction_de.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildQueueAction_de.properties
new file mode 100644
index 0000000..7864bed
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildQueueAction_de.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+buildqueue.name.required = Es mu\u00DF ein Name angegeben werden.
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildQueueAction_en.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildQueueAction_en.properties
new file mode 100644
index 0000000..661b0cb
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildQueueAction_en.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildQueueAction_fr.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildQueueAction_fr.properties
new file mode 100644
index 0000000..f953b30
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildQueueAction_fr.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+buildqueue.name.required = Vous devez sp\u00e9cifier un nom. 
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildQueueAction_pt_BR.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildQueueAction_pt_BR.properties
new file mode 100644
index 0000000..0c47afd
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/BuildQueueAction_pt_BR.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+buildqueue.name.required = Você deve definir um nome.
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ConfigurationAction-configuration-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ConfigurationAction-configuration-validation.xml
deleted file mode 100644
index 77e23ea..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ConfigurationAction-configuration-validation.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
-
-<validators>
-  <field name="workingDirectory">
-    <field-validator type="requiredstring">
-      <message key="configuration.workingDirectory.required"/>
-    </field-validator>
-  </field>
-  <field name="buildOutputDirectory">
-    <field-validator type="requiredstring">
-      <message key="configuration.buildOutputDirectory.required"/>
-    </field-validator>
-  </field>
-  <field name="baseUrl">
-    <field-validator type="requiredstring" short-circuit="true">
-      <message key="configuration.baseUrl.required"/>
-    </field-validator>
-    <field-validator type="url">
-      <message key="configuration.baseUrl.invalid"/>
-    </field-validator>
-  </field>
-</validators>
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ConfigurationAction-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ConfigurationAction-validation.xml
new file mode 100644
index 0000000..e906db5
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ConfigurationAction-validation.xml
@@ -0,0 +1,63 @@
+<!--
+  ~ 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.
+  -->
+
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
+
+<validators>
+  <field name="workingDirectory">
+    <field-validator type="requiredstring">
+      <message key="configuration.workingDirectory.required"/>
+    </field-validator>
+    <field-validator type="regex">
+      <param name="regex"><![CDATA[[A-Za-z0-9_.:\\/\s\-]*]]></param>
+      <message key="configuration.workingDirectory.invalid"/>
+    </field-validator>
+  </field>
+  <field name="buildOutputDirectory">
+    <field-validator type="requiredstring">
+      <message key="configuration.buildOutputDirectory.required"/>
+    </field-validator>
+    <field-validator type="regex">
+      <param name="regex"><![CDATA[[A-Za-z0-9_.:\\/\s\-]*]]></param>
+      <message key="configuration.buildOutputDirectory.invalid"/>
+    </field-validator>
+  </field>
+  <field name="baseUrl">
+    <field-validator type="requiredstring" short-circuit="true">
+      <message key="configuration.baseUrl.required"/>
+    </field-validator>
+    <field-validator type="url">
+      <message key="configuration.baseUrl.invalid"/>
+    </field-validator>
+  </field>
+  <field name="releaseOutputDirectory">
+    <field-validator type="regex">
+      <param name="regex"><![CDATA[[A-Za-z0-9_.:\\/\s\-]*]]></param>
+      <message key="configuration.releaseOutputDirectory.invalid"/>
+    </field-validator>
+  </field>
+  <field name="deploymentRepositoryDirectory">
+    <field-validator type="regex">
+      <param name="regex"><![CDATA[[A-Za-z0-9_.:\\/\s\-]*]]></param>
+      <message key="configuration.deploymentRepositoryDirectory.invalid"/>
+    </field-validator>
+  </field>
+</validators>
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ConfigurationAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ConfigurationAction.properties
index 2e876a4..517381a 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ConfigurationAction.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ConfigurationAction.properties
@@ -18,6 +18,10 @@
 #
 
 configuration.workingDirectory.required = You must define a working directory.
+configuration.workingDirectory.invalid = Working directory contains invalid characters.
 configuration.buildOutputDirectory.required = You must define a build output directory.
+configuration.buildOutputDirectory.invalid = Build output directory contains invalid characters.
 configuration.baseUrl.required = You must define a URL.
-configuration.baseUrl.invalid = You must define a valid URL.
\ No newline at end of file
+configuration.baseUrl.invalid = You must define a valid URL.
+configuration.releaseOutputDirectory.invalid = Release output directory contains invalid characters.
+configuration.deploymentRepositoryDirectory.invalid = Deployment repository directory contains invalid characters.
\ No newline at end of file
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ConfigurationAction_en.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ConfigurationAction_en.properties
new file mode 100644
index 0000000..661b0cb
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ConfigurationAction_en.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ConfigurationAction_pt_BR.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ConfigurationAction_pt_BR.properties
index 17d4386..d1e24a9 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ConfigurationAction_pt_BR.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ConfigurationAction_pt_BR.properties
@@ -17,8 +17,7 @@
 # under the License.
 #
 
-configuration.workingDirectory.required = Você deve definir um diretório de trabalho.
-configuration.buildOutputDirectory.required = Você deve definir um diretório para saída da build.
-configuration.baseUrl.required = Você deve definir uma URL.
-configuration.baseUrl.invalid = Você deve definir uma URL válida
-.
+configuration.workingDirectory.required = Voc\u00EA deve definir um diret\u00F3rio de trabalho.
+configuration.buildOutputDirectory.required = Voc\u00EA deve definir um diret\u00F3rio para sa\u00EDda da build.
+configuration.baseUrl.required = Voc\u00EA deve definir uma URL.
+configuration.baseUrl.invalid = Voc\u00EA deve definir uma URL v\u00E1lida.
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ConfigureAppearanceAction-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ConfigureAppearanceAction-validation.xml
index 00a8bc8..1a35207 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ConfigureAppearanceAction-validation.xml
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ConfigureAppearanceAction-validation.xml
@@ -17,38 +17,27 @@
   ~ under the License.
   -->
 
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
 
 <validators>
   <field name="companyPom.groupId">
     <field-validator type="requiredstring">
       <message key="appearance.groupId.required"/>
     </field-validator>
+    <field-validator type="regex">
+      <param name="regex"><![CDATA[[A-Za-z0-9.]*]]></param>
+      <message key="appearance.groupId.invalid"/>
+    </field-validator>
   </field>
   <field name="companyPom.artifactId">
     <field-validator type="requiredstring">
       <message key="appearance.artifactId.required"/>
     </field-validator>
+    <field-validator type="regex">
+      <param name="regex"><![CDATA[[A-Za-z0-9\-]*]]></param>
+      <message key="appearance.artifactId.invalid"/>
+    </field-validator>
   </field>
 </validators>
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ConfigureAppearanceAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ConfigureAppearanceAction.properties
index 23c2ed9..ca17e51 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ConfigureAppearanceAction.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ConfigureAppearanceAction.properties
@@ -18,5 +18,7 @@
 #
 
 appearance.groupId.required = You must define a group identifier.
+appearance.groupId.invalid = Group identifier is invalid.
 appearance.artifactId.required = You must define an artifact identifier.
+appearance.artifactId.invalid = Artifact identifier is invalid.
 
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/InstallationAction-saveInstallation-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/InstallationAction-saveInstallation-validation.xml
index 144e535..2856bab 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/InstallationAction-saveInstallation-validation.xml
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/InstallationAction-saveInstallation-validation.xml
@@ -17,25 +17,36 @@
   ~ under the License.
   -->
 
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
 
 <validators>
   <field name="installation.name">
     <field-validator type="requiredstring">
       <message key="installation.name.required"/>
     </field-validator>
+    <field-validator type="regex">
+      <param name="regex"><![CDATA[[A-Za-z0-9_.\s\-]*]]></param>
+      <message key="installation.name.invalid"/>
+    </field-validator>
+  </field>
+  <field name="installation.varName">
+    <field-validator type="regex">
+      <param name="regex"><![CDATA[[A-Za-z][A-Za-z0-9_]*]]></param>
+      <message key="installation.varName.invalid"/>
+    </field-validator>
   </field>
   <field name="installation.varValue">
     <field-validator type="requiredstring">
       <message key="installation.varValue.required"/>
     </field-validator>
-  </field>  
-  <field name="installation.varValue">
+    <field-validator type="regex">
+      <param name="regex"><![CDATA[(?:[~A-Za-z0-9_.:=${}\\/\-+]|\s|[()])*]]></param>
+      <message key="installation.varValue.invalid"/>
+    </field-validator>
     <field-validator type="installationValidator">
       <message key="installation.varValue.version.failed"/>
     </field-validator>
-  </field>    
-    
+  </field>
 </validators>
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/InstallationAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/InstallationAction.properties
index ebbae0b..b7e21ee 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/InstallationAction.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/InstallationAction.properties
@@ -18,5 +18,8 @@
 #
 
 installation.name.required = You must define a name.
+installation.name.invalid = Installation name contains invalid characters.
 installation.varValue.required = You must define a value.
+installation.varValue.invalid = Installation value contains invalid characters.
 installation.varValue.version.failed = Failed to validate installation, check server log. 
+installation.varName.invalid = Environment variable name contains invalid characters.
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/InstallationAction_en.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/InstallationAction_en.properties
new file mode 100644
index 0000000..661b0cb
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/InstallationAction_en.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ProfileAction-saveBuildEnv-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ProfileAction-saveBuildEnv-validation.xml
new file mode 100755
index 0000000..16d0359
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ProfileAction-saveBuildEnv-validation.xml
@@ -0,0 +1,34 @@
+<!--
+  ~ 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.
+  -->
+
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
+
+<validators>
+  <field name="profile.name">
+    <field-validator type="requiredstring">
+      <message key="profile.name.required"/>
+    </field-validator>
+    <field-validator type="regex">
+      <param name="regex"><![CDATA[[A-Za-z0-9_.\s\-]*]]></param>
+      <message key="profile.name.invalid"/>
+    </field-validator>
+  </field>
+</validators>
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ProfileAction-saveProfile-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ProfileAction-saveProfile-validation.xml
deleted file mode 100644
index e69de29..0000000
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ProfileAction-saveProfile-validation.xml
+++ /dev/null
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ProfileAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ProfileAction.properties
index 3f3e051..a87606a 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ProfileAction.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ProfileAction.properties
@@ -18,3 +18,4 @@
 #
 
 profile.name.required = You must define a name.
+profile.name.invalid = Build environment name contains invalid characters.
\ No newline at end of file
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ProfileAction_en.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ProfileAction_en.properties
new file mode 100644
index 0000000..661b0cb
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/admin/ProfileAction_en.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/IrcGroupNotifierEditAction-ircProjectGroupNotifierSave-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/IrcGroupNotifierEditAction-ircProjectGroupNotifierSave-validation.xml
index 138b8fd..f5d4717 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/IrcGroupNotifierEditAction-ircProjectGroupNotifierSave-validation.xml
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/IrcGroupNotifierEditAction-ircProjectGroupNotifierSave-validation.xml
@@ -17,15 +17,20 @@
   ~ under the License.
   -->
 
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
 
 <validators>
   <field name="host">
     <field-validator type="requiredstring">
       <message key="ircNotifier.host.required"/>
     </field-validator>
+    <field-validator type="regex">
+      <param name="trim">true</param>
+      <param name="regex"><![CDATA[[a-zA-Z0-9_.:\\/-]*]]></param>
+      <message key="ircNotifier.host.invalid"/>
+    </field-validator>
   </field>
   <field name="port">
     <field-validator type="int">
@@ -38,5 +43,10 @@
     <field-validator type="requiredstring">
       <message key="ircNotifier.channel.required"/>
     </field-validator>
+    <field-validator type="regex">
+      <param name="trim">true</param>
+      <param name="regex"><![CDATA[[a-zA-Z0-9_.#-]*]]></param>
+      <message key="ircNotifier.channel.invalid"/>
+    </field-validator>
   </field>
 </validators>
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/IrcGroupNotifierEditAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/IrcGroupNotifierEditAction.properties
index f15089d..6e6dd46 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/IrcGroupNotifierEditAction.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/IrcGroupNotifierEditAction.properties
@@ -18,5 +18,7 @@
 #
 
 ircNotifier.host.required = Host is required
+ircNotifier.host.invalid = Host contains invalid character
 ircNotifier.port.invalid = Port must be an integer from 0 to 65535
 ircNotifier.channel.required = Channel is required
+ircNotifier.channel.invalid = Channel contains invalid character
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/IrcGroupNotifierEditAction_en.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/IrcGroupNotifierEditAction_en.properties
new file mode 100644
index 0000000..661b0cb
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/IrcGroupNotifierEditAction_en.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/IrcProjectNotifierEditAction-ircProjectNotifierSave-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/IrcProjectNotifierEditAction-ircProjectNotifierSave-validation.xml
index 138b8fd..f5d4717 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/IrcProjectNotifierEditAction-ircProjectNotifierSave-validation.xml
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/IrcProjectNotifierEditAction-ircProjectNotifierSave-validation.xml
@@ -17,15 +17,20 @@
   ~ under the License.
   -->
 
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
 
 <validators>
   <field name="host">
     <field-validator type="requiredstring">
       <message key="ircNotifier.host.required"/>
     </field-validator>
+    <field-validator type="regex">
+      <param name="trim">true</param>
+      <param name="regex"><![CDATA[[a-zA-Z0-9_.:\\/-]*]]></param>
+      <message key="ircNotifier.host.invalid"/>
+    </field-validator>
   </field>
   <field name="port">
     <field-validator type="int">
@@ -38,5 +43,10 @@
     <field-validator type="requiredstring">
       <message key="ircNotifier.channel.required"/>
     </field-validator>
+    <field-validator type="regex">
+      <param name="trim">true</param>
+      <param name="regex"><![CDATA[[a-zA-Z0-9_.#-]*]]></param>
+      <message key="ircNotifier.channel.invalid"/>
+    </field-validator>
   </field>
 </validators>
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/IrcProjectNotifierEditAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/IrcProjectNotifierEditAction.properties
index f15089d..6e6dd46 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/IrcProjectNotifierEditAction.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/IrcProjectNotifierEditAction.properties
@@ -18,5 +18,7 @@
 #
 
 ircNotifier.host.required = Host is required
+ircNotifier.host.invalid = Host contains invalid character
 ircNotifier.port.invalid = Port must be an integer from 0 to 65535
 ircNotifier.channel.required = Channel is required
+ircNotifier.channel.invalid = Channel contains invalid character
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/IrcProjectNotifierEditAction_en.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/IrcProjectNotifierEditAction_en.properties
new file mode 100644
index 0000000..661b0cb
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/IrcProjectNotifierEditAction_en.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/JabberGroupNotifierEditAction-jabberProjectGroupNotifierSave-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/JabberGroupNotifierEditAction-jabberProjectGroupNotifierSave-validation.xml
index ae51b9e..13a909b 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/JabberGroupNotifierEditAction-jabberProjectGroupNotifierSave-validation.xml
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/JabberGroupNotifierEditAction-jabberProjectGroupNotifierSave-validation.xml
@@ -17,15 +17,20 @@
   ~ under the License.
   -->
 
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
 
 <validators>
   <field name="host">
     <field-validator type="requiredstring">
       <message key="jabberNotifier.host.required"/>
     </field-validator>
+    <field-validator type="regex">
+      <param name="trim">true</param>
+      <param name="regex"><![CDATA[[a-zA-Z0-9_.:\\/-]*]]></param>
+      <message key="jabberNotifier.host.invalid"/>
+    </field-validator>
   </field>
   <field name="port">
     <field-validator type="int">
@@ -44,6 +49,13 @@
       <message key="jabberNotifier.password.required"/>
     </field-validator>
   </field>
+  <field name="domainName">
+    <field-validator type="regex">
+      <param name="trim">true</param>
+      <param name="regex"><![CDATA[[a-zA-Z0-9_.:\\/-]*]]></param>
+      <message key="jabberNotifier.domain.invalid"/>
+    </field-validator>
+  </field>
   <field name="address">
     <field-validator type="requiredstring">
       <message key="jabberNotifier.address.required"/>
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/JabberGroupNotifierEditAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/JabberGroupNotifierEditAction.properties
index d7c16de..0a62f83 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/JabberGroupNotifierEditAction.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/JabberGroupNotifierEditAction.properties
@@ -18,8 +18,10 @@
 #
 
 jabberNotifier.host.required = Host is required
+jabberNotifier.host.invalid = Host contains invalid character
 jabberNotifier.port.invalid = Port must be an integer from 0 to 65535
 jabberNotifier.login.required = Login is required
 jabberNotifier.password.required = Password is required
+jabberNotifier.domain.invalid = Domain contains invalid character
 jabberNotifier.address.required = Address is required
 jabberNotifier.address.invalid = Address is invalid
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/JabberGroupNotifierEditAction_en.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/JabberGroupNotifierEditAction_en.properties
new file mode 100644
index 0000000..661b0cb
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/JabberGroupNotifierEditAction_en.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/JabberProjectNotifierEditAction-jabberProjectNotifierSave-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/JabberProjectNotifierEditAction-jabberProjectNotifierSave-validation.xml
index ae51b9e..13a909b 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/JabberProjectNotifierEditAction-jabberProjectNotifierSave-validation.xml
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/JabberProjectNotifierEditAction-jabberProjectNotifierSave-validation.xml
@@ -17,15 +17,20 @@
   ~ under the License.
   -->
 
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
 
 <validators>
   <field name="host">
     <field-validator type="requiredstring">
       <message key="jabberNotifier.host.required"/>
     </field-validator>
+    <field-validator type="regex">
+      <param name="trim">true</param>
+      <param name="regex"><![CDATA[[a-zA-Z0-9_.:\\/-]*]]></param>
+      <message key="jabberNotifier.host.invalid"/>
+    </field-validator>
   </field>
   <field name="port">
     <field-validator type="int">
@@ -44,6 +49,13 @@
       <message key="jabberNotifier.password.required"/>
     </field-validator>
   </field>
+  <field name="domainName">
+    <field-validator type="regex">
+      <param name="trim">true</param>
+      <param name="regex"><![CDATA[[a-zA-Z0-9_.:\\/-]*]]></param>
+      <message key="jabberNotifier.domain.invalid"/>
+    </field-validator>
+  </field>
   <field name="address">
     <field-validator type="requiredstring">
       <message key="jabberNotifier.address.required"/>
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/JabberProjectNotifierEditAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/JabberProjectNotifierEditAction.properties
index d7c16de..16dea45 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/JabberProjectNotifierEditAction.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/JabberProjectNotifierEditAction.properties
@@ -18,8 +18,10 @@
 #
 
 jabberNotifier.host.required = Host is required
+jabberNotifier.host.invalid = Host contains invalid characters
 jabberNotifier.port.invalid = Port must be an integer from 0 to 65535
 jabberNotifier.login.required = Login is required
 jabberNotifier.password.required = Password is required
+jabberNotifier.domain.invalid = Domain contains invalid characters
 jabberNotifier.address.required = Address is required
 jabberNotifier.address.invalid = Address is invalid
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/JabberProjectNotifierEditAction_en.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/JabberProjectNotifierEditAction_en.properties
new file mode 100644
index 0000000..661b0cb
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/JabberProjectNotifierEditAction_en.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MailGroupNotifierEditAction-mailProjectGroupNotifierSave-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MailGroupNotifierEditAction-mailProjectGroupNotifierSave-validation.xml
index 1d143f6..cad7abd 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MailGroupNotifierEditAction-mailProjectGroupNotifierSave-validation.xml
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MailGroupNotifierEditAction-mailProjectGroupNotifierSave-validation.xml
@@ -17,17 +17,25 @@
   ~ under the License.
   -->
 
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
 
 <validators>
   <field name="address">
-    <field-validator type="requiredstring">
+    <field-validator type="expression">
+      <param name="expression">
+        ! (
+        ( address.trim() eq "")
+        and
+        ( committers eq "" )
+        )
+      </param>
       <message key="mailNotifier.address.required"/>
     </field-validator>
     <field-validator type="regex">
-      <param name="expression"><![CDATA[(^[_A-Za-z0-9-\&]+[\&_A-Za-z0-9-+]*(\.[_A-Za-z0-9-+\&]+)*@([A-Za-z0-9-\&])+(\.[A-Za-z0-9-]+)*((\.[A-Za-z0-9]{2,})|(\.[A-Za-z0-9]{2,}\.[A-Za-z0-9]{2,}))$)]]></param>
+      <param name="regex">
+        <![CDATA[(^[_A-Za-z0-9-\&]+[\&_A-Za-z0-9-+]*(\.[_A-Za-z0-9-+\&]+)*@([A-Za-z0-9-\&])+(\.[A-Za-z0-9-]+)*((\.[A-Za-z0-9]{2,})|(\.[A-Za-z0-9]{2,}\.[A-Za-z0-9]{2,}))$)]]></param>
       <message key="mailNotifier.address.invalid"/>
     </field-validator>
   </field>
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MailGroupNotifierEditAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MailGroupNotifierEditAction.properties
index d1c9592..05d0e60 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MailGroupNotifierEditAction.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MailGroupNotifierEditAction.properties
@@ -17,5 +17,5 @@
 # under the License.
 #
 
-mailNotifier.address.required = Address is required
+mailNotifier.address.required = You must either provide an address, or select to notify latest committers.
 mailNotifier.address.invalid = Address is invalid
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MailGroupNotifierEditAction_en.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MailGroupNotifierEditAction_en.properties
new file mode 100644
index 0000000..661b0cb
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MailGroupNotifierEditAction_en.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MailProjectNotifierEditAction-mailProjectNotifierSave-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MailProjectNotifierEditAction-mailProjectNotifierSave-validation.xml
index 1d143f6..6a8385a 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MailProjectNotifierEditAction-mailProjectNotifierSave-validation.xml
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MailProjectNotifierEditAction-mailProjectNotifierSave-validation.xml
@@ -17,17 +17,25 @@
   ~ under the License.
   -->
 
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
 
 <validators>
   <field name="address">
-    <field-validator type="requiredstring">
+    <field-validator type="expression">
+      <param name="expression">
+        ! (
+        ( address.trim() eq "" )
+        and
+        ( committers eq "" )
+        )
+      </param>
       <message key="mailNotifier.address.required"/>
     </field-validator>
     <field-validator type="regex">
-      <param name="expression"><![CDATA[(^[_A-Za-z0-9-\&]+[\&_A-Za-z0-9-+]*(\.[_A-Za-z0-9-+\&]+)*@([A-Za-z0-9-\&])+(\.[A-Za-z0-9-]+)*((\.[A-Za-z0-9]{2,})|(\.[A-Za-z0-9]{2,}\.[A-Za-z0-9]{2,}))$)]]></param>
+      <param name="regex">
+        <![CDATA[(^[_A-Za-z0-9-\&]+[\&_A-Za-z0-9-+]*(\.[_A-Za-z0-9-+\&]+)*@([A-Za-z0-9-\&])+(\.[A-Za-z0-9-]+)*((\.[A-Za-z0-9]{2,})|(\.[A-Za-z0-9]{2,}\.[A-Za-z0-9]{2,}))$)]]></param>
       <message key="mailNotifier.address.invalid"/>
     </field-validator>
   </field>
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MailProjectNotifierEditAction.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MailProjectNotifierEditAction.properties
index d1c9592..05d0e60 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MailProjectNotifierEditAction.properties
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MailProjectNotifierEditAction.properties
@@ -17,5 +17,5 @@
 # under the License.
 #
 
-mailNotifier.address.required = Address is required
+mailNotifier.address.required = You must either provide an address, or select to notify latest committers.
 mailNotifier.address.invalid = Address is invalid
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MailProjectNotifierEditAction_en.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MailProjectNotifierEditAction_en.properties
new file mode 100644
index 0000000..661b0cb
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MailProjectNotifierEditAction_en.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MsnGroupNotifierEditAction-msnProjectGroupNotifierSave-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MsnGroupNotifierEditAction-msnProjectGroupNotifierSave-validation.xml
index f6bd9d6..304648d 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MsnGroupNotifierEditAction-msnProjectGroupNotifierSave-validation.xml
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MsnGroupNotifierEditAction-msnProjectGroupNotifierSave-validation.xml
@@ -17,9 +17,9 @@
   ~ under the License.
   -->
 
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
 
 <validators>
   <field name="login">
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MsnGroupNotifierEditAction_en.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MsnGroupNotifierEditAction_en.properties
new file mode 100644
index 0000000..661b0cb
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MsnGroupNotifierEditAction_en.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MsnProjectNotifierEditAction-msnProjectNotifierSave-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MsnProjectNotifierEditAction-msnProjectNotifierSave-validation.xml
index f6bd9d6..304648d 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MsnProjectNotifierEditAction-msnProjectNotifierSave-validation.xml
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MsnProjectNotifierEditAction-msnProjectNotifierSave-validation.xml
@@ -17,9 +17,9 @@
   ~ under the License.
   -->
 
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
 
 <validators>
   <field name="login">
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MsnProjectNotifierEditAction_en.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MsnProjectNotifierEditAction_en.properties
new file mode 100644
index 0000000..661b0cb
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/MsnProjectNotifierEditAction_en.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/WagonGroupNotifierEditAction-wagonProjectGroupNotifierSave-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/WagonGroupNotifierEditAction-wagonProjectGroupNotifierSave-validation.xml
index aca34df..cbe905b 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/WagonGroupNotifierEditAction-wagonProjectGroupNotifierSave-validation.xml
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/WagonGroupNotifierEditAction-wagonProjectGroupNotifierSave-validation.xml
@@ -17,9 +17,9 @@
   ~ under the License.
   -->
 
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
 
 <validators>
   <field name="url">
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/WagonGroupNotifierEditAction_en.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/WagonGroupNotifierEditAction_en.properties
new file mode 100644
index 0000000..661b0cb
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/WagonGroupNotifierEditAction_en.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/WagonProjectNotifierEditAction-wagonProjectNotifierSave-validation.xml b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/WagonProjectNotifierEditAction-wagonProjectNotifierSave-validation.xml
index aca34df..cbe905b 100644
--- a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/WagonProjectNotifierEditAction-wagonProjectNotifierSave-validation.xml
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/WagonProjectNotifierEditAction-wagonProjectNotifierSave-validation.xml
@@ -17,9 +17,9 @@
   ~ under the License.
   -->
 
-<!DOCTYPE validators PUBLIC
-    "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
-    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator 1.0.2//EN"
+  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
 
 <validators>
   <field name="url">
diff --git a/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/WagonProjectNotifierEditAction_en.properties b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/WagonProjectNotifierEditAction_en.properties
new file mode 100644
index 0000000..661b0cb
--- /dev/null
+++ b/continuum-webapp/src/main/resources/org/apache/maven/continuum/web/action/notifier/WagonProjectNotifierEditAction_en.properties
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+
diff --git a/continuum-webapp/src/main/resources/struts.properties b/continuum-webapp/src/main/resources/struts.properties
index 909f892..1997228 100644
--- a/continuum-webapp/src/main/resources/struts.properties
+++ b/continuum-webapp/src/main/resources/struts.properties
@@ -17,13 +17,11 @@
 # under the License.
 #
 
-struts.objectFactory = org.codehaus.plexus.spring.Struts2PlexusInSpringObjectFactory
+struts.objectFactory = org.apache.continuum.web.integration.Struts2PlexusInSpringObjectFactory
 #struts.tag.altSyntax = true
 
-# Theme
-struts.ui.theme = default
-
-struts.serve.static = false
+# TODO: Need to extract updated resources from struts2-core into webapp to enable this
+#struts.serve.static = false
 
 # Locale
 #struts.locale=en_EN
diff --git a/continuum-webapp/src/main/resources/struts.xml b/continuum-webapp/src/main/resources/struts.xml
index 3728448..1627d35 100644
--- a/continuum-webapp/src/main/resources/struts.xml
+++ b/continuum-webapp/src/main/resources/struts.xml
@@ -1,6 +1,6 @@
 <!--
   ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE filebu
+  ~ 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
@@ -18,33 +18,79 @@
   -->
 
 <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
-    "http://struts.apache.org/dtds/struts-2.0.dtd"> 
+    "http://struts.apache.org/dtds/struts-2.0.dtd">
 
 <struts>
+  <constant name="struts.action.extension" value="action"/>
+  
+  <constant name="struts.xwork.chaining.copyErrors" value="true"/>
+  <constant name="struts.xwork.chaining.copyFieldErrors" value="true"/>
+  <constant name="struts.xwork.chaining.copyMessages" value="true"/>
+
   <include file="struts-default.xml"/>
 
   <!-- Include plexus-security xwork configurations. -->
   <include file="struts-security.xml"/>
 
-
   <package name="default" extends="struts-default">
 
     <interceptors>
+      <interceptor-stack name="defaultStack">
+        <interceptor-ref name="exception"/>
+        <interceptor-ref name="alias"/>
+        <interceptor-ref name="servletConfig"/>
+        <interceptor-ref name="i18n"/>
+        <interceptor-ref name="prepare"/>
+        <interceptor-ref name="chain"/>
+        <interceptor-ref name="debugging"/>
+        <interceptor-ref name="scopedModelDriven"/>
+        <interceptor-ref name="modelDriven"/>
+        <interceptor-ref name="fileUpload"/>
+        <interceptor-ref name="checkbox"/>
+        <interceptor-ref name="multiselect"/>
+        <interceptor-ref name="staticParams"/>
+        <interceptor-ref name="actionMappingParams"/>
+        <interceptor-ref name="params" />
+        <interceptor-ref name="conversionError"/>
+        <interceptor-ref name="validation">
+          <param name="excludeMethods">input,back,cancel,browse</param>
+        </interceptor-ref>
+        <interceptor-ref name="workflow">
+          <param name="excludeMethods">input,back,cancel,browse</param>
+        </interceptor-ref>
+      </interceptor-stack>
+
+      <interceptor-stack name="basicStack">
+        <interceptor-ref name="exception"/>
+        <interceptor-ref name="servletConfig"/>
+        <interceptor-ref name="prepare"/>
+        <interceptor-ref name="checkbox"/>
+        <interceptor-ref name="multiselect"/>
+        <interceptor-ref name="actionMappingParams"/>
+        <interceptor-ref name="params" />
+        <interceptor-ref name="conversionError"/>
+      </interceptor-stack>
+
       <interceptor name="continuumConfigurationCheck" class="forceContinuumConfigurationInterceptor"/>
       <interceptor name="redbackForceAdminUser" class="redbackForceAdminUserInterceptor"/>
       <interceptor name="redbackSecureActions" class="redbackSecureActionInterceptor"/>
       <interceptor name="redbackAutoLogin" class="redbackAutoLoginInterceptor"/>
       <interceptor name="redbackPolicyEnforcement" class="redbackPolicyEnforcementInterceptor"/>
       <interceptor name="redbackEnvironmentChecker" class="redbackEnvironmentCheckInterceptor"/>
-      
+
       <interceptor-stack name="configuredContinuumStack">
         <interceptor-ref name="redbackEnvironmentChecker"/>
         <interceptor-ref name="redbackForceAdminUser"/>
         <interceptor-ref name="redbackAutoLogin"/>
         <interceptor-ref name="defaultStack"/>
-        <interceptor-ref name="redbackSecureActions"/>
+        <interceptor-ref name="redbackSecureActions">
+          <param name="enableReferrerCheck">false</param>
+        </interceptor-ref>
         <interceptor-ref name="redbackPolicyEnforcement"/>
         <interceptor-ref name="continuumConfigurationCheck"/>
+        <interceptor-ref name="tokenSession">
+          <param name="excludeMethods">*</param>
+        </interceptor-ref>
         <interceptor-ref name="validation">
           <param name="excludeMethods">input,back,cancel,browse,edit</param>
         </interceptor-ref>
@@ -59,7 +105,9 @@
         <interceptor-ref name="redbackAutoLogin"/>
         <interceptor-ref name="defaultStack"/>
         <interceptor-ref name="redbackPolicyEnforcement"/>
-        <interceptor-ref name="redbackSecureActions"/>
+        <interceptor-ref name="redbackSecureActions">
+          <param name="enableReferrerCheck">false</param>
+        </interceptor-ref>
         <interceptor-ref name="validation">
           <param name="excludeMethods">input,back,cancel,browse,edit</param>
         </interceptor-ref>
@@ -67,6 +115,20 @@
           <param name="excludeMethods">input,back,cancel,browse,edit</param>
         </interceptor-ref>
       </interceptor-stack>
+
+      <interceptor-stack name="storeStack">
+        <interceptor-ref name="configuredContinuumStack"/>
+        <interceptor-ref name="store">
+          <param name="operationMode">STORE</param>
+        </interceptor-ref>
+      </interceptor-stack>
+
+      <interceptor-stack name="retrieveStack">
+        <interceptor-ref name="configuredContinuumStack"/>
+        <interceptor-ref name="store">
+          <param name="operationMode">RETRIEVE</param>
+        </interceptor-ref>
+      </interceptor-stack>
     </interceptors>
 
     <default-interceptor-ref name="configuredContinuumStack"/>
@@ -79,62 +141,63 @@
       <result name="requires-authorization">/WEB-INF/jsp/error/authorizationError.jsp</result>
 
 
-      <result name="continuum-configuration-required" type="redirect-action">
+      <result name="continuum-configuration-required" type="redirectAction">
         <param name="actionName">configuration</param>
         <param name="namespace">/admin</param>
-        <param name="method">input</param>
       </result>
 
       <!-- The following security-* result names arrive from the plexus-security package -->
-      <result name="security-login-success" type="redirect-action">
+      <result name="security-login-success" type="redirectAction">
         <param name="actionName">groupSummary</param>
         <param name="namespace">/</param>
       </result>
-      <result name="security-login-cancel" type="redirect-action">
+      <result name="security-login-cancel" type="redirectAction">
         <param name="actionName">groupSummary</param>
         <param name="namespace">/</param>
       </result>
-      <result name="security-login-locked" type="redirect-action">
+      <result name="security-login-locked" type="redirectAction">
         <param name="actionName">groupSummary</param>
         <param name="namespace">/</param>
         <param name="infoMessage">Account Locked</param>
       </result>
-      <result name="security-logout" type="redirect-action">
+      <result name="security-logout" type="redirectAction">
         <param name="actionName">groupSummary</param>
         <param name="namespace">/</param>
       </result>
-      <result name="requires-authentication" type="redirect-action">
+      <result name="requires-authentication" type="redirectAction">
         <param name="actionName">login</param>
         <param name="namespace">/security</param>
       </result>
-      <result name="security-register-success" type="redirect-action">
+      <result name="security-register-success" type="redirectAction">
         <param name="actionName">groupSummary</param>
         <param name="namespace">/security</param>
       </result>
-      <result name="security-register-cancel" type="redirect-action">
+      <result name="security-register-cancel" type="redirectAction">
         <param name="actionName">groupSummary</param>
         <param name="namespace">/</param>
       </result>
-      <result name="security-account-success" type="redirect-action">
+      <result name="security-account-success" type="redirectAction">
         <param name="actionName">groupSummary</param>
         <param name="namespace">/</param>
       </result>
-      <result name="security-account-cancel" type="redirect-action">
+      <result name="security-account-cancel" type="redirectAction">
         <param name="actionName">login</param>
         <param name="namespace">/security</param>
       </result>
-      <result name="security-admin-user-created" type="redirect-action">
+      <result name="security-admin-user-created" type="redirectAction">
         <param name="actionName">login</param>
         <param name="namespace">/security</param>
       </result>
-      <result name="security-admin-user-needed" type="redirect-action">
+      <result name="security-admin-user-needed" type="redirectAction">
         <param name="actionName">addadmin</param>
         <param name="namespace">/security</param>
       </result>
-      <result name="security-must-change-password" type="redirect-action">
+      <result name="security-must-change-password" type="redirectAction">
         <param name="actionName">password</param>
         <param name="namespace">/security</param>
       </result>
+
+      <result name="invalid.token">/WEB-INF/jsp/redback/invalidToken.jsp</result>
     </global-results>
 
     <global-exception-mappings>
@@ -147,100 +210,119 @@
              allowing plexus-security to call out from its own set of actions
              into the application webapp, using global result names. -->
     <action name="redbackRedirect" class="redback-redirect" method="redirect">
-      <result type="redirect-action">groupSummary</result>
+      <interceptor-ref name="retrieveStack"/>
+      <result type="redirectAction">groupSummary</result>
+    </action>
+
+    <action name="httpError" class="httpError">
+      <result name="success">/WEB-INF/jsp/error/httpError.jsp</result>
     </action>
 
     <action name="about" class="about">
       <result name="success">/WEB-INF/jsp/about.jsp</result>
     </action>
 
-
     <action name="companyInfo" class="companyInfo">
       <result name="success">/WEB-INF/jsp/components/companyLogo.jsp</result>
-      <interceptor-ref name="basicStack" />
+      <interceptor-ref name="basicStack"/>
     </action>
-    
+
     <action name="bottom" class="bottom">
       <result name="success">/WEB-INF/jsp/navigations/DefaultBottom.jsp</result>
-      <interceptor-ref name="basicStack" />
-    </action>    
-    
+      <interceptor-ref name="basicStack"/>
+    </action>
+
 
     <action name="groupSummary" class="groupSummary">
+      <interceptor-ref name="retrieveStack"/>
       <result name="success">/WEB-INF/jsp/groupSummary.jsp</result>
     </action>
 
-    <action name="addMavenTwoProjectInput" class="addMavenTwoProject">
+    <action name="addMavenTwoProjectInput" class="addMavenTwoProject" method="input">
       <result name="input">/WEB-INF/jsp/addMavenTwoProject.jsp</result>
-    </action>        
-    
+    </action>
+
     <action name="addMavenTwoProject" class="addMavenTwoProject">
       <interceptor-ref name="configuredContinuumStack"/>
       <interceptor-ref name="fileUpload"/>
       <interceptor-ref name="execAndWait">
         <param name="delay">200</param>
         <param name="delaySleepInterval">50</param>
-      </interceptor-ref> 
-      <result name="wait">/WEB-INF/jsp/navigations/wait.jsp</result>     
+      </interceptor-ref>
+      <result name="wait">/WEB-INF/jsp/navigations/wait.jsp</result>
       <result name="input">/WEB-INF/jsp/addMavenTwoProject.jsp</result>
       <result name="success" type="chain">groupSummary</result>
-      <result name="projectGroupSummary" type="redirect-action">
+      <result name="projectGroupSummary" type="redirectAction">
         <param name="actionName">projectGroupSummary</param>
         <param name="projectGroupId">${projectGroupId}</param>
       </result>
     </action>
 
-    <action name="addMavenOneProjectInput" class="addMavenOneProject">
+    <action name="addMavenOneProjectInput" class="addMavenOneProject" method="input">
       <result name="input">/WEB-INF/jsp/addMavenOneProject.jsp</result>
-    </action>    
-    
+    </action>
+
     <action name="addMavenOneProject" class="addMavenOneProject">
       <interceptor-ref name="configuredContinuumStack"/>
-      <interceptor-ref name="execAndWait"/> 
-      <result name="wait">/WEB-INF/jsp/navigations/wait.jsp</result>      
+      <interceptor-ref name="execAndWait"/>
+      <result name="wait">/WEB-INF/jsp/navigations/wait.jsp</result>
       <result name="input">/WEB-INF/jsp/addMavenOneProject.jsp</result>
       <result name="success" type="chain">groupSummary</result>
-      <result name="projectGroupSummary" type="redirect-action">
+      <result name="projectGroupSummary" type="redirectAction">
         <param name="actionName">projectGroupSummary</param>
         <param name="projectGroupId">${projectGroupId}</param>
       </result>
     </action>
 
     <action name="addProjectInput" class="addProject" method="input">
-      <result name="success">/WEB-INF/jsp/addProject.jsp</result>
+      <result name="input">/WEB-INF/jsp/addProject.jsp</result>
     </action>
 
     <action name="addProject" class="addProject" method="add">
       <interceptor-ref name="configuredContinuumStack"/>
-      <interceptor-ref name="execAndWait"/> 
-      <result name="wait">/WEB-INF/jsp/navigations/wait.jsp</result>      
-      <result name="input">/WEB-INF/jsp/addProject.jsp</result>
+      <result name="input" type="chain">addProjectInput</result>
       <result name="success" type="chain">groupSummary</result>
-      <result name="projectGroupSummary" type="redirect-action">
+      <result name="projectGroupSummary" type="redirectAction">
         <param name="actionName">projectGroupSummary</param>
         <param name="projectGroupId">${projectGroupId}</param>
-      </result>        
+      </result>
+    </action>
+
+    <action name="deleteProject_default" class="deleteProject" method="default">
+      <interceptor-ref name="storeStack">
+        <param name="tokenSession.includeMethods">*</param>
+      </interceptor-ref>
+      <result name="delete">/WEB-INF/jsp/deleteProject.jsp</result>
+      <result name="success" type="redirectAction">
+        <param name="actionName">projectGroupSummary</param>
+        <param name="projectGroupId">${projectGroupId}</param>
+      </result>
     </action>
 
     <action name="deleteProject" class="deleteProject">
+      <interceptor-ref name="storeStack">
+        <param name="tokenSession.includeMethods">*</param>
+      </interceptor-ref>
       <result name="delete">/WEB-INF/jsp/deleteProject.jsp</result>
-      <result name="success" type="redirect-action">
+      <result name="success" type="redirectAction">
         <param name="actionName">projectGroupSummary</param>
         <param name="projectGroupId">${projectGroupId}</param>
       </result>
     </action>
 
     <action name="ProjectsList" class="projects">
+      <interceptor-ref name="storeStack"/>
       <result name="confirmRemove">/WEB-INF/jsp/confirmDeleteProjects.jsp</result>
-      <result name="success" type="redirect-action">
+      <result name="success" type="redirectAction">
         <param name="actionName">projectGroupSummary</param>
         <param name="projectGroupId">${projectGroupId}</param>
       </result>
     </action>
 
     <action name="buildProject" class="buildProject">
+      <interceptor-ref name="storeStack"/>
       <result name="success" type="chain">groupSummary</result>
-      <result name="to_group_page" type="redirect-action">
+      <result name="to_group_page" type="redirectAction">
         <param name="actionName">projectGroupSummary</param>
         <param name="projectGroupId">${projectGroupId}</param>
       </result>
@@ -269,7 +351,10 @@
 
     <action name="saveBuildDefinition" class="buildDefinition" method="saveBuildDefinition">
       <result name="input">/WEB-INF/jsp/buildDefinitionEdit.jsp</result>
-      <result name="success" type="chain">projectView</result>
+      <result name="success" type="redirectAction">
+        <param name="actionName">projectView</param>
+        <param name="projectId">${projectId}</param>
+      </result>
       <result name="success_group" type="chain">projectGroupBuildDefinition</result>
     </action>
 
@@ -281,6 +366,9 @@
     <action name="removeProjectBuildDefinition" class="buildDefinition" method="removeFromProject">
       <result name="confirm">/WEB-INF/jsp/deleteBuildDefinition.jsp</result>
       <result name="success" type="chain">projectView</result>
+      <interceptor-ref name="configuredContinuumStack">
+        <param name="tokenSession.includeMethods">removeFromProject</param>
+      </interceptor-ref>
     </action>
 
     <action name="saveGroupBuildDefinition" class="buildDefinition" method="saveToGroup">
@@ -290,6 +378,9 @@
     <action name="removeGroupBuildDefinition" class="buildDefinition" method="removeFromProjectGroup">
       <result name="confirm">/WEB-INF/jsp/confirmBuildDefinitionRemoval.jsp</result>
       <result name="success" type="chain">projectGroupBuildDefinition</result>
+      <interceptor-ref name="configuredContinuumStack">
+        <param name="tokenSession.includeMethods">removeFromProjectGroup</param>
+      </interceptor-ref>
     </action>
 
 
@@ -297,7 +388,11 @@
     * project group actions
     -->
     <action name="projectGroupSummary" class="projectGroup" method="summary">
+      <interceptor-ref name="retrieveStack"/>
       <result name="success">/WEB-INF/jsp/projectGroupSummary.jsp</result>
+      <result name="to_summary_page" type="redirectAction">
+        <param name="actionName">groupSummary</param>
+      </result>
     </action>
 
     <action name="projectGroupMembers" class="projectGroup" method="members">
@@ -313,34 +408,47 @@
     </action>
 
     <action name="buildProjectGroup" class="projectGroup" method="build">
-      <result name="success" type="redirect-action">
+      <interceptor-ref name="storeStack"/>
+      <result name="success" type="redirectAction">
         <param name="actionName">projectGroupSummary</param>
         <param name="projectGroupId">${projectGroupId}</param>
       </result>
       <result name="to_summary_page" type="chain">groupSummary</result>
     </action>
 
-    <action name="removeProjectGroup" class="projectGroup" method="remove">
+    <action name="confirmRemoveProjectGroup" class="projectGroup" method="confirmRemove">
+      <interceptor-ref name="storeStack"/>
       <result name="confirm">/WEB-INF/jsp/confirmGroupRemoval.jsp</result>
-      <result name="success" type="redirect-action">
+    </action>
+
+    <action name="removeProjectGroup" class="projectGroup" method="remove">
+      <interceptor-ref name="storeStack">
+        <param name="tokenSession.includeMethods">remove</param>
+      </interceptor-ref>
+      <result name="success" type="redirectAction">
         <param name="actionName">groupSummary</param>
       </result>
     </action>
-    
+
     <action name="releaseProjectGroup" class="projectGroup" method="release">
-      <result name="input" type="redirect-action">
+      <interceptor-ref name="storeStack"/>
+      <result name="input" type="redirectAction">
         <param name="actionName">projectGroupSummary</param>
         <param name="projectGroupId">${projectGroupId}</param>
       </result>
-      <result name="success" type="redirect-action">
+      <result name="success" type="redirectAction">
         <param name="actionName">releasePromptGoal</param>
         <param name="projectId">${releaseProjectId}</param>
       </result>
     </action>
 
+    <action name="addProjectGroup_input" class="addProjectGroup" method="input">
+      <result name="input">/WEB-INF/jsp/projectGroupAdd.jsp</result>
+    </action>
+
     <action name="addProjectGroup" class="addProjectGroup">
       <result name="input">/WEB-INF/jsp/projectGroupAdd.jsp</result>
-      <result name="success" type="redirect-action">groupSummary</result>
+      <result name="success" type="redirectAction">groupSummary</result>
     </action>
 
     <action name="editProjectGroup" class="projectGroup" method="edit">
@@ -348,19 +456,24 @@
     </action>
 
     <action name="saveProjectGroup" class="projectGroup" method="save">
-      <result name="success" type="chain">projectGroupSummary</result>
       <result name="input">/WEB-INF/jsp/projectGroupEdit.jsp</result>
+      <result name="success" type="redirectAction">
+        <param name="actionName">projectGroupSummary</param>
+        <param name="projectGroupId">${projectGroupId}</param>
+      </result>
     </action>
 
     <!--
     *  build results, test reporting, working copy actions
     -->
     <action name="buildResults" class="buildResults">
+      <interceptor-ref name="retrieveStack"/>
       <result name="success">/WEB-INF/jsp/buildResults.jsp</result>
     </action>
-    
+
     <action name="removeBuildResults" class="buildResults" method="remove">
-      <result name="success" type="redirect-action">
+      <interceptor-ref name="storeStack"/>
+      <result name="success" type="redirectAction">
         <param name="actionName">buildResults</param>
         <param name="projectId">${projectId}</param>
       </result>
@@ -368,22 +481,26 @@
     </action>
 
     <action name="buildResult" class="buildResult">
+      <interceptor-ref name="storeStack"/>
       <result name="success">/WEB-INF/jsp/buildResult.jsp</result>
-      <result name="error" type="redirect-action">
+      <result name="error" type="redirectAction">
         <param name="actionName">projectGroupSummary</param>
         <param name="projectGroupId">${projectGroupId}</param>
       </result>
     </action>
-    
+
     <action name="buildOutputText" class="buildResult">
       <result name="success" type="stream">
         <param name="inputName">buildOutputInputStream</param>
         <param name="contentDisposition">attachment; filename="build-output.txt"</param>
       </result>
-    </action>    
-    
+    </action>
+
     <action name="removeBuildResult" class="buildResult" method="remove">
-      <result name="success" type="redirect-action">
+      <interceptor-ref name="storeStack">
+        <param name="tokenSession.includeMethods">remove</param>
+      </interceptor-ref>
+      <result name="success" type="redirectAction">
         <param name="actionName">buildResults</param>
         <param name="projectId">${projectId}</param>
       </result>
@@ -398,11 +515,11 @@
       <result name="success">/WEB-INF/jsp/workingCopy.jsp</result>
       <result name="stream" type="stream">
         <param name="contentType">application/octet-stream</param>
-        <param name="contentDisposition">filename="${downloadFilename}"</param>
+        <param name="contentDisposition">attachment; filename="${downloadFilename}"</param>
         <param name="contentLength">${fileLength}</param>
       </result>
     </action>
-    
+
     <action name="workingCopyFileText" class="workingCopy">
       <result name="success" type="stream">
         <param name="contentType">application/octet-stream</param>
@@ -414,7 +531,7 @@
     <action name="scmResult" class="scmResult">
       <result name="success">/WEB-INF/jsp/scmResult.jsp</result>
     </action>
-    
+
     <!--
     * schedule actions
     -->
@@ -431,25 +548,29 @@
       <result name="success" type="chain">schedules</result>
       <result name="error" type="chain">schedule</result>
     </action>
+
     <action name="removeSchedule" class="schedule" method="remove">
       <result name="confirm">/WEB-INF/jsp/confirmScheduleRemoval.jsp</result>
       <result name="success" type="chain">schedules</result>
       <result name="error" type="chain">schedule</result>
+      <interceptor-ref name="configuredContinuumStack">
+        <param name="tokenSession.includeMethods">remove</param>
+      </interceptor-ref>
     </action>
 
     <action name="cancelBuild" class="cancelBuild">
       <result name="success" type="chain">buildResults</result>
     </action>
-    
+
     <action name="cancelBuilds" class="cancelBuild" method="cancelBuilds">
-      <result name="success" type="redirect-action">
+      <result name="success" type="redirectAction">
         <param name="actionName">projectGroupSummary</param>
         <param name="projectGroupId">${projectGroupId}</param>
       </result>
-    </action>    
+    </action>
 
     <action name="cancelGroupBuild" class="cancelBuild" method="cancelGroupBuild">
-      <result name="success" type="redirect-action">
+      <result name="success" type="redirectAction">
         <param name="actionName">projectGroupSummary</param>
         <param name="projectGroupId">${projectGroupId}</param>
       </result>
@@ -460,25 +581,24 @@
     -->
     <action name="releasePromptGoal" class="releaseProject" method="promptReleaseGoal">
       <result name="success">/WEB-INF/jsp/releaseProject.jsp</result>
-      <result name="releaseOutputDir-required" type="redirect-action">
+      <result name="releaseOutputDir-required" type="redirectAction">
         <param name="actionName">configuration</param>
         <param name="namespace">/admin</param>
-        <param name="method">input</param>
         <param name="requireReleaseOutput">true</param>
       </result>
     </action>
 
     <action name="releaseProject" class="releaseProject">
-      <result name="prepareRelease" type="redirect-action">
+      <result name="prepareRelease" type="redirectAction">
         <param name="actionName">releasePrepareInput</param>
         <param name="projectId">${projectId}</param>
       </result>
-      <result name="performRelease" type="redirect-action">
+      <result name="performRelease" type="redirectAction">
         <param name="actionName">releasePerformInput</param>
         <param name="projectId">${projectId}</param>
         <param name="releaseId">${preparedReleaseId}</param>
       </result>
-      <result name="performReleaseFromScm" type="redirect-action">
+      <result name="performReleaseFromScm" type="redirectAction">
         <param name="actionName">releasePerformFromScmInput</param>
         <param name="projectId">${projectId}</param>
       </result>
@@ -486,50 +606,57 @@
 
     <action name="releasePrepareInput" class="releasePrepare" method="input">
       <result name="success">/WEB-INF/jsp/releasePrepare.jsp</result>
+      <result name="releaseError">/WEB-INF/jsp/error/releaseError.jsp</result>
     </action>
 
     <action name="releasePrepare" class="releasePrepare">
       <result name="input" type="chain">releasePrepareInput</result>
-      <result name="success" type="redirect-action">
+      <result name="success" type="redirectAction">
         <param name="actionName">releaseInProgress</param>
         <param name="releaseId">${releaseId}</param>
         <param name="projectId">${projectId}</param>
         <param name="releaseGoal">prepare</param>
       </result>
+      <result name="releaseError">/WEB-INF/jsp/error/releaseError.jsp</result>
     </action>
 
     <action name="releasePerformInput" class="releasePerform" method="input">
       <result name="success">/WEB-INF/jsp/releasePerform.jsp</result>
+      <result name="releaseError">/WEB-INF/jsp/error/releaseError.jsp</result>
     </action>
 
     <action name="releasePerform" class="releasePerform">
       <result name="input" type="chain">releasePerformInput</result>
-      <result name="success" type="redirect-action">
+      <result name="success" type="redirectAction">
         <param name="actionName">releaseInProgress</param>
         <param name="releaseId">${releaseId}</param>
         <param name="projectId">${projectId}</param>
         <param name="releaseGoal">perform</param>
       </result>
+      <result name="releaseError">/WEB-INF/jsp/error/releaseError.jsp</result>
     </action>
 
     <action name="releasePerformFromScmInput" class="releasePerform" method="inputFromScm">
       <result name="success">/WEB-INF/jsp/releasePerformFromScm.jsp</result>
+      <result name="releaseError">/WEB-INF/jsp/error/releaseError.jsp</result>
     </action>
 
     <action name="releasePerformFromScm" class="releasePerform" method="executeFromScm">
       <result name="input">/WEB-INF/jsp/releasePerformFromScm.jsp</result>
-      <result name="success" type="redirect-action">
+      <result name="success" type="redirectAction">
         <param name="actionName">releaseInProgress</param>
         <param name="projectId">${projectId}</param>
         <param name="releaseId">${releaseId}</param>
         <param name="releaseGoal">perform</param>
       </result>
+      <result name="releaseError">/WEB-INF/jsp/error/releaseError.jsp</result>
     </action>
 
     <action name="releaseInProgress" class="releaseInProgress">
       <result name="initialized">/WEB-INF/jsp/releaseInitialized.jsp</result>
       <result name="inProgress">/WEB-INF/jsp/releaseInProgress.jsp</result>
       <result name="success">/WEB-INF/jsp/releaseFinished.jsp</result>
+      <result name="releaseError">/WEB-INF/jsp/error/releaseError.jsp</result>
     </action>
 
     <action name="releaseRollbackWarning" class="releaseRollback" method="warn">
@@ -537,20 +664,26 @@
     </action>
 
     <action name="releaseRollback" class="releaseRollback">
-      <result name="success" type="redirect-action">
+      <result name="success" type="redirectAction">
         <param name="actionName">releaseCleanup</param>
         <param name="projectId">${projectId}</param>
         <param name="releaseId">${releaseId}</param>
       </result>
+      <result name="releaseError">/WEB-INF/jsp/error/releaseError.jsp</result>
     </action>
 
     <action name="releaseCleanup" class="releaseCleanup">
       <result name="prepareFinished" type="chain">releasePromptGoal</result>
-      <result name="performFinished" type="redirect-action">groupSummary</result>
+      <result name="performFinished" type="redirectAction">
+        <param name="actionName">projectGroupSummary</param>
+        <param name="projectGroupId">${projectGroupId}</param>
+      </result>
+      <result name="releaseError">/WEB-INF/jsp/error/releaseError.jsp</result>
     </action>
 
     <action name="releaseViewResult" class="releaseInProgress" method="viewResult">
       <result name="success">/WEB-INF/jsp/releaseViewResult.jsp</result>
+      <result name="releaseError">/WEB-INF/jsp/error/releaseError.jsp</result>
     </action>
 
     <action name="viewReleaseResult" class="releaseResult" method="viewResult">
@@ -563,10 +696,35 @@
 
     <action name="removeReleaseResults" class="releaseResult" method="remove">
       <result name="confirm">/WEB-INF/jsp/confirmReleaseResultsRemoval.jsp</result>
-      <result name="success" type="redirect-action">
+      <result name="success" type="redirectAction">
         <param name="actionName">projectGroupReleaseResults</param>
         <param name="projectGroupId">${projectGroupId}</param>
       </result>
+      <interceptor-ref name="configuredContinuumStack">
+        <param name="tokenSession.includeMethods">remove</param>
+      </interceptor-ref>
+    </action>
+
+    <action name="viewReleases" class="distributedRelease" method="list">
+      <result name="success">/WEB-INF/jsp/releases.jsp</result>
+    </action>
+
+    <action name="viewProjectBuildsReport" class="projectBuildsReport" method="init">
+      <result name="success">/WEB-INF/jsp/viewProjectBuildsReport.jsp</result>
+    </action>
+
+    <action name="generateProjectBuildsReport" class="projectBuildsReport">
+      <result name="input">/WEB-INF/jsp/viewProjectBuildsReport.jsp</result>
+      <result name="success">/WEB-INF/jsp/viewProjectBuildsReport.jsp</result>
+    </action>
+
+    <action name="downloadProjectBuildsReport" class="projectBuildsReport" method="downloadBuildsReport">
+      <result name="input">/WEB-INF/jsp/viewProjectBuildsReport.jsp</result>
+      <result name="success">/WEB-INF/jsp/viewProjectBuildsReport.jsp</result>
+      <result name="send-file" type="stream">
+        <param name="contentType">${contentType}</param>
+        <param name="contentDisposition">attachment; filename="continuum_project_builds_report.csv"</param>
+      </result>
     </action>
   </package>
 
@@ -580,7 +738,12 @@
   -->
   <package name="admin" extends="default">
 
-    <action name="configuration" class="configuration">
+    <action name="configuration" class="configuration" method="input">
+      <interceptor-ref name="unconfiguredContinuumStack"/>
+      <result name="input">/WEB-INF/jsp/admin/configurationEdit.jsp</result>
+    </action>
+
+    <action name="configuration_save" class="configuration" method="save">
       <interceptor-ref name="unconfiguredContinuumStack"/>
       <result name="input">/WEB-INF/jsp/admin/configurationEdit.jsp</result>
       <result name="success">/WEB-INF/jsp/admin/configuration.jsp</result>
@@ -590,19 +753,22 @@
     <action name="configureAppearance" class="configureAppearance" method="input">
       <result name="input">/WEB-INF/jsp/admin/appearance.jsp</result>
     </action>
-    
+
     <action name="saveFooter" class="configureFooter" method="saveFooter">
       <result name="input">/WEB-INF/jsp/admin/appearance.jsp</result>
       <result name="success">/WEB-INF/jsp/admin/appearance.jsp</result>
-    </action>    
-      
+      <interceptor-ref name="configuredContinuumStack">
+        <param name="tokenSession.includeMethods">saveFooter</param>
+      </interceptor-ref>
+    </action>
+
     <action name="editAppearance" class="configureAppearance" method="input">
       <result name="input">/WEB-INF/jsp/admin/editAppearance.jsp</result>
     </action>
 
     <action name="saveAppearance" class="configureAppearance">
       <result name="input">/WEB-INF/jsp/admin/editAppearance.jsp</result>
-      <result type="redirect-action">
+      <result type="redirectAction">
         <param name="actionName">configureAppearance</param>
         <param name="namespace">/admin</param>
       </result>
@@ -614,317 +780,466 @@
 
     <action name="saveCompanyPom" class="editPom">
       <result name="input">/WEB-INF/jsp/admin/editPom.jsp</result>
-      <result type="redirect-action">
+      <result type="redirectAction">
         <param name="actionName">configureAppearance</param>
         <param name="namespace">/admin</param>
       </result>
+      <interceptor-ref name="configuredContinuumStack">
+        <param name="tokenSession.includeMethods">execute</param>
+      </interceptor-ref>
     </action>
-      
+
     <!--
        Build Environment actions
-    -->      
-      
+    -->
+
     <action name="buildEnvList" class="profileAdministration" method="list">
+      <interceptor-ref name="retrieveStack"/>
       <result name="success">/WEB-INF/jsp/admin/profilesList.jsp</result>
-    </action>   
-      
-    <action name="addBuildEnv" class="profileAdministration">
-      <result name="input">/WEB-INF/jsp/admin/editProfile.jsp</result>   
     </action>
-        
-    <action name="editBuildEnv" class="profileAdministration">
+
+    <action name="addBuildEnv" class="profileAdministration" method="input">
+      <result name="input">/WEB-INF/jsp/admin/editProfile.jsp</result>
+    </action>
+
+    <action name="editBuildEnv" class="profileAdministration" method="edit">
       <result name="input">/WEB-INF/jsp/admin/editProfile.jsp</result>
       <result name="success">/WEB-INF/jsp/admin/editProfile.jsp</result>
     </action>
-      
+
     <action name="deleteBuildEnv" class="profileAdministration" method="delete">
-      <result name="success" type="redirect-action">
+      <interceptor-ref name="storeStack">
+        <param name="tokenSession.includeMethods">delete</param>
+      </interceptor-ref>
+      <result name="success" type="redirectAction">
         <param name="actionName">buildEnvList</param>
         <param name="namespace">/admin</param>
-        <param name="method">list</param>
       </result>
-      <result name="error" type="redirect-action">
-        <param name="actionName">buildEnvList</param>
-        <param name="namespace">/admin</param>
-        <param name="method">list</param>
-        <param name="errorMessage">${message}</param>
-      </result>
-    </action>      
-    
+    </action>
+
     <action name="confirmDeleteBuildEnv" class="profileAdministration" method="confirmDelete">
       <result name="success">/WEB-INF/jsp/admin/confirmDeleteBuildEnv.jsp</result>
-    </action>  
-      
+    </action>
+
     <action name="saveBuildEnv" class="profileAdministration" method="save">
       <result name="success">/WEB-INF/jsp/admin/profilesList.jsp</result>
       <result name="input">/WEB-INF/jsp/admin/editProfile.jsp</result>
       <result name="editProfile">/WEB-INF/jsp/admin/editProfile.jsp</result>
     </action>
-      
+
     <action name="addInstallationBuildEnv" class="profileAdministration" method="addInstallation">
       <result name="success">/WEB-INF/jsp/admin/editProfile.jsp</result>
-      <result name="input">/WEB-INF/jsp/admin/editProfile.jsp</result>        
-    </action>  
-    
+      <result name="input">/WEB-INF/jsp/admin/editProfile.jsp</result>
+    </action>
+
     <action name="removeBuildEnvInstallation" class="profileAdministration" method="removeInstallation">
       <result name="success">/WEB-INF/jsp/admin/editProfile.jsp</result>
-      <result name="input">/WEB-INF/jsp/admin/editProfile.jsp</result>        
+      <result name="input">/WEB-INF/jsp/admin/editProfile.jsp</result>
     </action>
-      
+
     <!--
        Installation actions 
-    -->  
+    -->
     <action name="installationsTypeChoice" class="installation" method="listTypes">
       <result name="success">/WEB-INF/jsp/admin/installationsTypeChoice.jsp</result>
     </action>
-    
+
     <action name="installationsList" class="installation" method="list">
       <result name="success">/WEB-INF/jsp/admin/installationsList.jsp</result>
-    </action>   
-      
-    <action name="addInstallation" class="installation" method="add">
-      <result name="input">/WEB-INF/jsp/admin/editInstallation.jsp</result>
-    </action>       
-      
+    </action>
+
     <action name="editInstallation" class="installation" method="edit">
       <result name="success">/WEB-INF/jsp/admin/editInstallation.jsp</result>
-      <result name="input">/WEB-INF/jsp/admin/editInstallation.jsp</result>    
+      <result name="input">/WEB-INF/jsp/admin/editInstallation.jsp</result>
     </action>
-      
+
+    <action name="editInstallation_input" class="installation" method="input">
+      <result name="input">/WEB-INF/jsp/admin/editInstallation.jsp</result>
+    </action>
+
     <action name="saveInstallation" class="installation" method="save">
       <result name="input">/WEB-INF/jsp/admin/editInstallation.jsp</result>
-      <result name="edit">/WEB-INF/jsp/admin/editInstallation.jsp</result>
-      <result name="success" type="redirect-action">installationsList</result>
-    </action> 
+      <result name="success" type="redirectAction">installationsList</result>
+    </action>
+
     <action name="deleteInstallation" class="installation" method="delete">
       <result name="input">/WEB-INF/jsp/admin/installationsList.jsp</result>
       <result name="success">/WEB-INF/jsp/admin/installationsList.jsp</result>
-    </action>  
-    
-    <!--
+      <result name="confirm">/WEB-INF/jsp/admin/confirmDeleteInstallation.jsp</result>
+    </action>
+
+    <!--addBuildEnv
        Build Definitions Templates actions 
-    -->  
+    -->
     <action name="buildDefinitionTemplates" class="buildDefinitionTemplates" method="summary">
       <result name="success">/WEB-INF/jsp/admin/buildDefinitionTemplateSummary.jsp</result>
     </action>
-    
+
     <action name="buildDefinitionTemplate" class="buildDefinitionTemplates" method="input">
       <result name="success">/WEB-INF/jsp/admin/editBuildDefinitionTemplate.jsp</result>
       <result name="input">/WEB-INF/jsp/admin/editBuildDefinitionTemplate.jsp</result>
     </action>
-    
+
     <action name="editBuildDefinitionTemplate" class="buildDefinitionTemplates" method="edit">
       <result name="success">/WEB-INF/jsp/admin/editBuildDefinitionTemplate.jsp</result>
       <result name="input">/WEB-INF/jsp/admin/editBuildDefinitionTemplate.jsp</result>
     </action>
 
     <action name="deleteDefinitionTemplate" class="buildDefinitionTemplates" method="delete">
-      <result name="success" type="redirect-action">
+      <result name="success" type="redirectAction">
         <param name="actionName">buildDefinitionTemplates.action</param>
       </result>
+      <result name="confirm">/WEB-INF/jsp/admin/confirmDeleteBuildDefinitionTemplate.jsp</result>
+      <interceptor-ref name="configuredContinuumStack">
+        <param name="tokenSession.includeMethods">delete</param>
+      </interceptor-ref>
     </action>
-    
+
     <action name="saveBuildDefinitionTemplate" class="buildDefinitionTemplates" method="save">
-      <result name="success" type="redirect-action">
+      <result name="success" type="redirectAction">
         <param name="actionName">buildDefinitionTemplates.action</param>
       </result>
       <result name="input">/WEB-INF/jsp/admin/editBuildDefinitionTemplate.jsp</result>
     </action>
-    
+
     <action name="editBuildDefinitionAsTemplate" class="buildDefinitionTemplates" method="editBuildDefinition">
       <result name="success">/WEB-INF/jsp/admin/editBuildDefinitionAsTemplate.jsp</result>
       <result name="input">/WEB-INF/jsp/admin/editBuildDefinitionAsTemplate.jsp</result>
     </action>
-    
+
     <action name="saveBuildDefinitionAsTemplate" class="buildDefinitionTemplates" method="saveBuildDefinition">
-      <result name="success" type="redirect-action">
+      <result name="success" type="redirectAction">
         <param name="actionName">buildDefinitionTemplates.action</param>
       </result>
       <result name="input">/WEB-INF/jsp/admin/editBuildDefinitionAsTemplate.jsp</result>
     </action>
 
+    <action name="buildDefinitionAsTemplate_input" class="buildDefinitionTemplates" method="input">
+      <result name="input">/WEB-INF/jsp/admin/editBuildDefinitionAsTemplate.jsp</result>
+    </action>
+
     <action name="buildDefinitionAsTemplate" class="buildDefinitionTemplates" method="saveBuildDefinition">
-      <result name="success" type="redirect-action">
+      <result name="success" type="redirectAction">
         <param name="actionName">buildDefinitionTemplates.action</param>
       </result>
       <result name="input">/WEB-INF/jsp/admin/editBuildDefinitionAsTemplate.jsp</result>
     </action>
-              
+
     <action name="deleteBuildDefinitionAsTemplate" class="buildDefinitionTemplates" method="deleteBuildDefinition">
-      <result name="success" type="redirect-action">
+      <result name="success" type="redirectAction">
         <param name="actionName">buildDefinitionTemplates.action</param>
       </result>
+      <result name="confirm">/WEB-INF/jsp/admin/confirmDeleteBuildDefinitionAsTemplate.jsp</result>
+      <result name="error">/WEB-INF/jsp/error/buildDefinitionError.jsp</result>
     </action>
-    
+
     <action name="displayQueues" class="queues" method="display">
       <result name="success">/WEB-INF/jsp/admin/buildQueueView.jsp</result>
       <result name="distributed-build-success">/WEB-INF/jsp/admin/viewDistributedBuilds.jsp</result>
     </action>
-    
+
     <action name="removeBuildQueueEntry" class="queues" method="remove">
-      <result name="success" type="redirect-action">
+      <result name="success" type="redirectAction">
         <param name="actionName">displayQueues</param>
-      </result>      
-    </action>   
-    
-    <action name="removeBuildQueueEntries" class="queues" method="removeBuildEntries">
-      <result name="success" type="redirect-action">
-        <param name="actionName">displayQueues</param>
-      </result>      
-    </action>    
-    
-    <action name="cancelCurrentBuildTask" class="queues" method="cancelCurrent">
-      <result name="success" type="redirect-action">
-        <param name="actionName">displayQueues</param>
-      </result>      
-    </action> 
-    
-    <action name="removeCheckoutQueueEntry" class="queues" method="removeCheckout">
-      <result name="success" type="redirect-action">
-        <param name="actionName">displayQueues</param>
-      </result>      
+      </result>
     </action>
-    
+
+    <action name="removeBuildQueueEntries" class="queues" method="removeBuildEntries">
+      <result name="success" type="redirectAction">
+        <param name="actionName">displayQueues</param>
+      </result>
+    </action>
+
+    <action name="cancelCurrentBuildTask" class="queues" method="cancelCurrent">
+      <result name="success" type="redirectAction">
+        <param name="actionName">displayQueues</param>
+      </result>
+    </action>
+
+    <action name="removeCheckoutQueueEntry" class="queues" method="removeCheckout">
+      <result name="success" type="redirectAction">
+        <param name="actionName">displayQueues</param>
+      </result>
+    </action>
+
     <action name="cancelCurrentQueueTask" class="queues" method="cancelCurrentCheckout">
-      <result name="success" type="redirect-action">
+      <result name="success" type="redirectAction">
         <param name="actionName">displayQueues</param>
-      </result>      
-    </action>    
-    
+      </result>
+    </action>
+
     <action name="removeCheckoutQueueEntries" class="queues" method="removeCheckoutEntries">
-      <result name="success" type="redirect-action">
+      <result name="success" type="redirectAction">
         <param name="actionName">displayQueues</param>
-      </result>      
-    </action>    
-    
+      </result>
+    </action>
+
+    <action name="removePrepareBuildEntry" class="queues" method="removePrepareBuildEntry">
+      <result name="success" type="redirectAction">
+        <param name="actionName">displayQueues</param>
+      </result>
+    </action>
+
+    <action name="removePrepareBuildEntries" class="queues" method="removePrepareBuildEntries">
+      <result name="success" type="redirectAction">
+        <param name="actionName">displayQueues</param>
+      </result>
+    </action>
+
     <action name="cancelDistributedBuild" class="queues" method="cancelDistributedBuild">
-      <result name="success" type="redirect-action">
+      <result name="success" type="redirectAction">
+        <param name="actionName">displayQueues</param>
+      </result>
+    </action>
+
+    <action name="removeDistributedPrepareBuildEntry" class="queues" method="removeDistributedPrepareBuildEntry">
+      <result name="success" type="redirectAction">
+        <param name="actionName">displayQueues</param>
+      </result>
+    </action>
+
+    <action name="removeDistributedPrepareBuildEntries" class="queues" method="removeDistributedPrepareBuildEntries">
+      <result name="success" type="redirectAction">
         <param name="actionName">displayQueues</param>
       </result>
     </action>
 
     <action name="removeDistributedBuildEntries" class="queues" method="removeDistributedBuildEntries">
-      <result name="success" type="redirect-action">
+      <result name="success" type="redirectAction">
         <param name="actionName">displayQueues</param>
       </result>
     </action>
-    
+
     <action name="removeDistributedBuildEntry" class="queues" method="removeDistributedBuildEntry">
-      <result name="success" type="redirect-action">
+      <result name="success" type="redirectAction">
         <param name="actionName">displayQueues</param>
       </result>
     </action>
-    
+
+    <!--
+    * Build Queue (Parallel Builds)
+    -->
+
+    <action name="buildQueueList" class="org.apache.maven.continuum.web.action.admin.BuildQueueAction" method="list">
+      <result name="success">/WEB-INF/jsp/admin/parallelbuilds.jsp</result>
+    </action>
+
+    <action name="addBuildQueue" class="org.apache.maven.continuum.web.action.admin.BuildQueueAction" method="input">
+      <result name="input">/WEB-INF/jsp/admin/editParallelBuilds.jsp</result>
+    </action>
+
+    <action name="saveBuildQueue" class="org.apache.maven.continuum.web.action.admin.BuildQueueAction" method="save">
+      <result name="input">/WEB-INF/jsp/admin/editParallelBuilds.jsp</result>
+      <result name="error">/WEB-INF/jsp/admin/editParallelBuilds.jsp</result>
+      <result name="success" type="redirectAction">buildQueueList</result>
+    </action>
+
+    <action name="deleteBuildQueue" class="org.apache.maven.continuum.web.action.admin.BuildQueueAction"
+            method="delete">
+      <result name="confirm">/WEB-INF/jsp/admin/confirmDeleteBuildQueue.jsp</result>
+      <result name="success" type="redirectAction">
+        <param name="actionName">buildQueueList</param>
+      </result>
+      <interceptor-ref name="configuredContinuumStack">
+        <param name="tokenSession.includeMethods">delete</param>
+      </interceptor-ref>
+    </action>
+
     <!--
     * Local Repository actions
     -->
-    
+
     <action name="repositoryList" class="localRepository" method="list">
+      <interceptor-ref name="retrieveStack"/>
       <result name="success">/WEB-INF/jsp/admin/localRepositoriesList.jsp</result>
     </action>
-    
+
     <action name="editRepository" class="localRepository" method="input">
       <result name="error">/WEB-INF/jsp/admin/editLocalRepository.jsp</result>
       <result name="input">/WEB-INF/jsp/admin/editLocalRepository.jsp</result>
     </action>
-    
+
     <action name="saveRepository" class="localRepository" method="save">
       <result name="error">/WEB-INF/jsp/admin/editLocalRepository.jsp</result>
       <result name="input">/WEB-INF/jsp/admin/editLocalRepository.jsp</result>
-      <result name="success" type="redirect-action">
+      <result name="success" type="redirectAction">
         <param name="actionName">repositoryList</param>
       </result>
     </action>
-    
+
     <action name="removeRepository" class="localRepository" method="remove">
-      <result name="error" type="redirect-action">
-        <param name="actionName">repositoryList</param>
-        <param name="errorMessage">${message}</param>
-      </result>
+      <interceptor-ref name="storeStack">
+        <param name="tokenSession.includeMethods">remove</param>
+      </interceptor-ref>
       <result name="confirm">/WEB-INF/jsp/admin/confirmDeleteLocalRepository.jsp</result>
-      <result name="success" type="redirect-action">
+      <result name="success" type="redirectAction">
         <param name="actionName">repositoryList</param>
       </result>
     </action>
-    
+
     <action name="purgeRepository" class="localRepository" method="doPurge">
-      <result name="success" type="redirect-action">
+      <interceptor-ref name="storeStack"/>
+      <result name="success" type="redirectAction">
         <param name="actionName">repositoryList</param>
       </result>
-      <result name="error" type="redirect-action">
-        <param name="actionName">repositoryList</param>
-        <param name="errorMessage">${message}</param>
-      </result>
     </action>
-    
+
     <!--
     * Purge actions
     -->
-    
+    <action name="displayPurge" class="purge" method="display">
+      <result name="success">/WEB-INF/jsp/admin/purgeConfigurationsList.jsp</result>
+      <result name="distributed-build-success">/WEB-INF/jsp/admin/distributedPurgeConfigurationsList.jsp</result>
+    </action>
+
+    <!--
+    * Parallel Purge Actions
+    -->
     <action name="purgeConfigList" class="purgeConfiguration" method="list">
       <result name="success">/WEB-INF/jsp/admin/purgeConfigurationsList.jsp</result>
     </action>
-    
+
     <action name="editPurgeConfig" class="purgeConfiguration" method="input">
       <result name="error">/WEB-INF/jsp/admin/editPurgeConfiguration.jsp</result>
       <result name="input">/WEB-INF/jsp/admin/editPurgeConfiguration.jsp</result>
     </action>
-    
+
     <action name="savePurgeConfig" class="purgeConfiguration" method="save">
       <result name="input">/WEB-INF/jsp/admin/editPurgeConfiguration.jsp</result>
-      <result name="success" type="redirect-action">
-        <param name="actionName">purgeConfigList</param>
+      <result name="success" type="redirectAction">
+        <param name="actionName">displayPurge</param>
       </result>
     </action>
-    
+
     <action name="removePurgeConfig" class="purgeConfiguration" method="remove">
-      <result name="success" type="redirect-action">
-        <param name="actionName">purgeConfigList</param>
-      </result>
-    </action>
-    
-    <action name="doPurge" class="purgeConfiguration" method="purge">
-      <result name="success" type="redirect-action">
-        <param name="actionName">purgeConfigList</param>
-      </result>
-      <result name="error" type="redirect-action">
+      <result name="error" type="redirectAction">
         <param name="actionName">purgeConfigList</param>
         <param name="errorMessage">${message}</param>
       </result>
+      <result name="confirm">/WEB-INF/jsp/admin/confirmDeletePurgeConfiguration.jsp</result>
+      <result name="success" type="redirectAction">
+        <param name="actionName">displayPurge</param>
+      </result>
+      <interceptor-ref name="configuredContinuumStack">
+        <param name="tokenSession.includeMethods">remove</param>
+      </interceptor-ref>
     </action>
-    
+
+    <action name="doPurge" class="purgeConfiguration" method="purge">
+      <result name="success" type="redirectAction">
+        <param name="actionName">displayPurge</param>
+      </result>
+      <result name="error" type="redirectAction">
+        <param name="actionName">displayPurge</param>
+        <param name="errorMessage">${message}</param>
+      </result>
+    </action>
+
+    <!--
+    * Distributed Purge actions
+    -->
+    <action name="editDistributedPurgeConfig" class="distributedPurgeConfiguration" method="input">
+      <result name="error">/WEB-INF/jsp/admin/editDistributedPurgeConfiguration.jsp</result>
+      <result name="input">/WEB-INF/jsp/admin/editDistributedPurgeConfiguration.jsp</result>
+    </action>
+
+    <action name="saveDistributedPurgeConfig" class="distributedPurgeConfiguration" method="save">
+      <result name="input">/WEB-INF/jsp/admin/editDistributedPurgeConfiguration.jsp</result>
+      <result name="success" type="redirectAction">
+        <param name="actionName">displayPurge</param>
+      </result>
+    </action>
+
+    <action name="removeDistributedPurgeConfig" class="distributedPurgeConfiguration" method="remove">
+      <result name="error" type="redirectAction">
+        <param name="actionName">purgeConfigList</param>
+        <param name="errorMessage">${message}</param>
+      </result>
+      <result name="confirm">/WEB-INF/jsp/admin/confirmDeleteDistributedPurgeConfiguration.jsp</result>
+      <result name="success" type="redirectAction">
+        <param name="actionName">displayPurge</param>
+      </result>
+      <interceptor-ref name="configuredContinuumStack">
+        <param name="tokenSession.includeMethods">remove</param>
+      </interceptor-ref>
+    </action>
+
+    <action name="doDistributedPurge" class="distributedPurgeConfiguration" method="purge">
+      <result name="success" type="redirectAction">
+        <param name="actionName">displayPurge</param>
+      </result>
+      <result name="error" type="redirectAction">
+        <param name="actionName">displayPurge</param>
+        <param name="errorMessage">${message}</param>
+      </result>
+    </action>
+
+    <!--
+    * Build Agent actions
+    -->
+
     <action name="buildAgentList" class="buildAgent" method="list">
       <result name="success">/WEB-INF/jsp/admin/buildAgentsList.jsp</result>
     </action>
-    
+
     <action name="editBuildAgent" class="buildAgent" method="input">
       <result name="input">/WEB-INF/jsp/admin/editBuildAgent.jsp</result>
       <result name="error">/WEB-INF/jsp/admin/editBuildAgent.jsp</result>
     </action>
-    
+
     <action name="saveBuildAgent" class="buildAgent" method="save">
       <result name="input">/WEB-INF/jsp/admin/editBuildAgent.jsp</result>
       <result name="error">/WEB-INF/jsp/admin/editBuildAgent.jsp</result>
-      <result name="success" type="redirect-action">
+      <result name="success" type="redirectAction">
         <param name="actionName">buildAgentList</param>
       </result>
     </action>
-    
+
     <action name="deleteBuildAgent" class="buildAgent" method="delete">
-      <result name="error" type="redirect-action">
+      <result name="error" type="redirectAction">
         <param name="actionName">buildAgentList</param>
         <param name="errorMessage">${message}</param>
       </result>
       <result name="confirm">/WEB-INF/jsp/admin/confirmDeleteBuildAgent.jsp</result>
-      <result name="success" type="redirect-action">
+      <result name="success" type="redirectAction">
         <param name="actionName">buildAgentList</param>
       </result>
+      <interceptor-ref name="configuredContinuumStack">
+        <param name="tokenSession.includeMethods">delete</param>
+      </interceptor-ref>
     </action>
-    
+
     <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="redirectAction">
+        <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="redirectAction">
+        <param name="actionName">buildAgentList</param>
+      </result>
+      <interceptor-ref name="configuredContinuumStack">
+        <param name="tokenSession.includeMethods">deleteGroup</param>
+      </interceptor-ref>
+    </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="redirectAction">
+        <param name="actionName">buildAgentList</param>
+      </result>
+    </action>
+
   </package>
 
   <package name="component" extends="default">
@@ -969,14 +1284,24 @@
     <!--
     * notifier actions :: Project
     -->
-    <action name="deleteProjectNotifier" class="deleteProjectNotifier">
+    <action name="deleteProjectNotifier_default" class="deleteProjectNotifier" method="default">
       <result name="delete">/WEB-INF/jsp/notifier/deleteNotifier.jsp</result>
+    </action>
+
+    <action name="deleteProjectNotifier" class="deleteProjectNotifier">
       <result name="success" type="chain">projectView</result>
       <result name="to_group_page" type="chain">projectGroupNotifier</result>
+      <interceptor-ref name="configuredContinuumStack">
+        <param name="tokenSession.includeMethods">execute</param>
+      </interceptor-ref>
     </action>
 
     <action name="addProjectNotifier" class="addProjectNotifier" method="doDefault">
       <result name="input">/WEB-INF/jsp/notifier/notifierSelectType.jsp</result>
+    </action>
+
+    <action name="addProjectNotifier_submit" class="addProjectNotifier" method="execute">
+      <result name="input">/WEB-INF/jsp/notifier/notifierSelectType.jsp</result>
       <result name="mail_input">/WEB-INF/jsp/notifier/notifierMail.jsp</result>
       <result name="irc_input">/WEB-INF/jsp/notifier/notifierIrc.jsp</result>
       <result name="msn_input">/WEB-INF/jsp/notifier/notifierMsn.jsp</result>
@@ -1046,13 +1371,23 @@
     * notifier actions :: Project Group
     -->
 
-    <action name="deleteProjectGroupNotifier" class="deleteGroupNotifier">
+    <action name="deleteProjectGroupNotifier_default" class="deleteGroupNotifier" method="default">
       <result name="delete">/WEB-INF/jsp/notifier/deleteNotifier.jsp</result>
+    </action>
+
+    <action name="deleteProjectGroupNotifier" class="deleteGroupNotifier">
       <result name="success" type="chain">projectGroupNotifier</result>
+      <interceptor-ref name="configuredContinuumStack">
+        <param name="tokenSession.includeMethods">execute</param>
+      </interceptor-ref>
     </action>
 
     <action name="addProjectGroupNotifier" class="addGroupNotifier" method="doDefault">
       <result name="input">/WEB-INF/jsp/notifier/notifierSelectType.jsp</result>
+    </action>
+
+    <action name="addProjectGroupNotifier_submit" class="addGroupNotifier" method="execute">
+      <result name="input">/WEB-INF/jsp/notifier/notifierSelectType.jsp</result>
       <result name="mail_input">/WEB-INF/jsp/notifier/notifierMail.jsp</result>
       <result name="irc_input">/WEB-INF/jsp/notifier/notifierIrc.jsp</result>
       <result name="msn_input">/WEB-INF/jsp/notifier/notifierMsn.jsp</result>
@@ -1112,6 +1447,6 @@
       <result name="input">/WEB-INF/jsp/notifier/notifierWagon.jsp</result>
       <result name="success" type="chain">projectGroupNotifier</result>
     </action>
-    
+
   </package>
 </struts>
diff --git a/continuum-webapp/src/main/resources/template/default/a-close.ftl b/continuum-webapp/src/main/resources/template/default/a-close.ftl
deleted file mode 100644
index 706f1f4..0000000
--- a/continuum-webapp/src/main/resources/template/default/a-close.ftl
+++ /dev/null
@@ -1 +0,0 @@
-</a><#rt/>
\ No newline at end of file
diff --git a/continuum-webapp/src/main/resources/template/default/a.ftl b/continuum-webapp/src/main/resources/template/default/a.ftl
deleted file mode 100644
index 1b41b31..0000000
--- a/continuum-webapp/src/main/resources/template/default/a.ftl
+++ /dev/null
@@ -1,22 +0,0 @@
-<a<#rt/>
-<#if parameters.id?if_exists != "">
- id="${parameters.id?html}"<#rt/>
-</#if>
-<#if parameters.href?if_exists != "">
- href="${parameters.href}"<#rt/>
-</#if>
-<#if parameters.tabindex?exists>
- tabindex="${parameters.tabindex?html}"<#rt/>
-</#if>
-<#if parameters.cssClass?exists>
- class="${parameters.cssClass?html}"<#rt/>
-</#if>
-<#if parameters.cssStyle?exists>
- style="${parameters.cssStyle?html}"<#rt/>
-</#if>
-<#if parameters.title?exists>
- title="${parameters.title?html}"<#rt/>
-</#if>
-<#include "/${parameters.templateDir}/simple/scripting-events.ftl" />
-<#include "/${parameters.templateDir}/simple/common-attributes.ftl" />
-><#rt/>
diff --git a/continuum-webapp/src/main/resources/template/default/actionerror.ftl b/continuum-webapp/src/main/resources/template/default/actionerror.ftl
deleted file mode 100644
index 74c3136..0000000
--- a/continuum-webapp/src/main/resources/template/default/actionerror.ftl
+++ /dev/null
@@ -1,7 +0,0 @@
-<#if (actionErrors?exists && actionErrors?size > 0)>
-	<ul>
-	<#list actionErrors as error>
-		<li><span class="errorMessage">${error}</span></li>
-	</#list>
-	</ul>
-</#if>
diff --git a/continuum-webapp/src/main/resources/template/default/actionmessage.ftl b/continuum-webapp/src/main/resources/template/default/actionmessage.ftl
deleted file mode 100644
index 384b755..0000000
--- a/continuum-webapp/src/main/resources/template/default/actionmessage.ftl
+++ /dev/null
@@ -1,7 +0,0 @@
-<#if (actionMessages?exists && actionMessages?size > 0)>
-	<ul>
-		<#list actionMessages as message>
-			<li><span class="actionMessage">${message}</span></li>
-		</#list>
-	</ul>
-</#if>
diff --git a/continuum-webapp/src/main/resources/template/default/checkbox.ftl b/continuum-webapp/src/main/resources/template/default/checkbox.ftl
deleted file mode 100644
index 33f1112..0000000
--- a/continuum-webapp/src/main/resources/template/default/checkbox.ftl
+++ /dev/null
@@ -1,102 +0,0 @@
-<#assign hasFieldErrors = fieldErrors?exists && fieldErrors[parameters.name]?exists/>
-<#if hasFieldErrors>
-<#list fieldErrors[parameters.name] as error>
-<tr<#rt/>
-<#if parameters.id?exists>
- errorFor="${parameters.id}"<#rt/>
-</#if>
->
-    <td align="left" valign="top" colspan="2"><#rt/>
-        <span class="errorMessage">${error?html}</span><#t/>
-    </td><#lt/>
-</tr>
-</#list>
-</#if>
-<#if parameters.labelposition?default("") == 'top'>
-<tr>
-    <td colspan="2">
-<#if parameters.label?exists> <label<#t/>
-<#if parameters.id?exists>
- for="${parameters.id?html}"<#rt/>
-</#if>
-<#if hasFieldErrors>
- class="checkboxErrorLabel"<#rt/>
-<#else>
- class="checkboxLabel"<#rt/>
-</#if>
->
-<#if parameters.required?default(false) && parameters.requiredposition?default("right") != 'right'>
-        <span class="required">*</span><#t/>
-</#if>
-${parameters.label?html}<#t/>
-<#if parameters.required?default(false) && parameters.requiredposition?default("right") == 'right'>
- <span class="required">*</span><#t/>
-</#if>
-:<#t/>
-<#if parameters.tooltip?exists>
-    <img src='<@s.url value="/webwork/tooltip/tooltip.gif" />' alt="${parameters.tooltip}" title="${parameters.tooltip}" onmouseover="return escape('${parameters.tooltip?js_string}');" />
-</#if>
-</label><#t/>
-</#if>
-    </td>
-</tr>
-<tr>
-    <td colspan="2">
-        <#include "/${parameters.templateDir}/simple/checkbox.ftl" />
-<#else>
-<tr>
-	<td valign="top" align="right">
-<#if parameters.labelposition?default("") == 'left'>
-<#if parameters.label?exists> <label<#t/>
-<#if parameters.id?exists>
- for="${parameters.id?html}"<#rt/>
-</#if>
-<#if hasFieldErrors>
- class="checkboxErrorLabel"<#rt/>
-<#else>
- class="checkboxLabel"<#rt/>
-</#if>
->
-<#if parameters.required?default(false) && parameters.requiredposition?default("right") != 'right'>
-        <span class="required">*</span><#t/>
-</#if>
-${parameters.label?html}<#t/>
-<#if parameters.required?default(false) && parameters.requiredposition?default("right") == 'right'>
- <span class="required">*</span><#t/>
-</#if>
-:<#t/>
-<#if parameters.tooltip?exists>
-    <img src='<@s.url value="/webwork/tooltip/tooltip.gif" />' alt="${parameters.tooltip}" title="${parameters.tooltip}" onmouseover="return escape('${parameters.tooltip?js_string}');" />
-</#if>
-</label><#t/>
-</#if>
-</#if>
-<#if parameters.labelposition?default("") == 'right'>
-    <#if parameters.required?default(false)>
-        <span class="required">*</span><#t/>
-    </#if>
-    <#if parameters.tooltip?exists>
-        <img src='<@s.url value="/webwork/tooltip/tooltip.gif" />' alt="${parameters.tooltip}" title="${parameters.tooltip}" onmouseover="return escape('${parameters.tooltip?js_string}');" />
-    </#if>
-</#if>
-    </td>
-    <td valign="top" align="left">
-
-<#if parameters.labelposition?default("") != 'top'>
-                	<#include "/${parameters.templateDir}/simple/checkbox.ftl" />
-</#if>                    
-<#if parameters.labelposition?default("") != 'top' && parameters.labelposition?default("") != 'left'>
-<#if parameters.label?exists> <label<#t/>
-<#if parameters.id?exists>
- for="${parameters.id?html}"<#rt/>
-</#if>
-<#if hasFieldErrors>
- class="checkboxErrorLabel"<#rt/>
-<#else>
- class="checkboxLabel"<#rt/>
-</#if>
->${parameters.label?html}</label><#rt/>
-</#if>
-</#if>
-</#if>
- <#include "/${parameters.templateDir}/${parameters.theme}/controlfooter.ftl" /><#nt/>
diff --git a/continuum-webapp/src/main/resources/template/default/checkboxlist.ftl b/continuum-webapp/src/main/resources/template/default/checkboxlist.ftl
deleted file mode 100644
index f5d5b6f..0000000
--- a/continuum-webapp/src/main/resources/template/default/checkboxlist.ftl
+++ /dev/null
@@ -1,4 +0,0 @@
-<#include "/${parameters.templateDir}/${parameters.theme}/controlheader.ftl" />
-
-<#include "/${parameters.templateDir}/simple/checkboxlist.ftl" />
-    <#include "/${parameters.templateDir}/${parameters.theme}/controlfooter.ftl" /><#nt/>
diff --git a/continuum-webapp/src/main/resources/template/default/combobox.ftl b/continuum-webapp/src/main/resources/template/default/combobox.ftl
deleted file mode 100644
index 1111702..0000000
--- a/continuum-webapp/src/main/resources/template/default/combobox.ftl
+++ /dev/null
@@ -1,4 +0,0 @@
-<#include "/${parameters.templateDir}/${parameters.theme}/controlheader.ftl" />
-
-<#include "/${parameters.templateDir}/simple/combobox.ftl" />
-    <#include "/${parameters.templateDir}/${parameters.theme}/controlfooter.ftl" /><#nt/>
diff --git a/continuum-webapp/src/main/resources/template/default/controlfooter.ftl b/continuum-webapp/src/main/resources/template/default/controlfooter.ftl
deleted file mode 100644
index cf10ea0..0000000
--- a/continuum-webapp/src/main/resources/template/default/controlfooter.ftl
+++ /dev/null
@@ -1,3 +0,0 @@
-${parameters.desc?if_exists} ${parameters.after?if_exists}<#t/>
-    </td><#lt/>
-</tr>
diff --git a/continuum-webapp/src/main/resources/template/default/controlheader-core.ftl b/continuum-webapp/src/main/resources/template/default/controlheader-core.ftl
deleted file mode 100644
index 07cac59..0000000
--- a/continuum-webapp/src/main/resources/template/default/controlheader-core.ftl
+++ /dev/null
@@ -1,56 +0,0 @@
-<#--
-	Only show message if errors are available.
-	This will be done if ActionSupport is used.
--->
-<#assign hasFieldErrors = parameters.name?exists && fieldErrors?exists && fieldErrors[parameters.name]?exists/>
-<#if hasFieldErrors>
-<#list fieldErrors[parameters.name] as error>
-<tr errorFor="${parameters.id}">
-<#if parameters.labelposition?default("") == 'top'>
-    <td align="left" valign="top" colspan="2"><#rt/>
-<#else>
-    <td align="center" valign="top" colspan="2"><#rt/>
-</#if>
-        <span class="errorMessage">${error?html}</span><#t/>
-    </td><#lt/>
-</tr>
-</#list>
-</#if>
-<#--
-	if the label position is top,
-	then give the label it's own row in the table
--->
-<tr class="b">
-<#if parameters.labelposition?default("") == 'top'>
-    <th align="left" valign="top" colspan="2"><#rt/>
-<#else>
-    <th><#rt/>
-</#if>
-<#if parameters.label?exists>
-    <label <#t/>
-<#if parameters.id?exists>
-        for="${parameters.id?html}" <#t/>
-</#if>
-<#if hasFieldErrors>
-        class="errorLabel"<#t/>
-<#else>
-        class="label"<#t/>
-</#if>
-    ><#t/>
-<#if parameters.required?default(false) && parameters.requiredposition?default("right") != 'right'>
-        <span class="required">*</span><#t/>
-</#if>
-${parameters.label?html}<#t/>
-<#if parameters.required?default(false) && parameters.requiredposition?default("right") == 'right'>
- <span class="required">*</span><#t/>
-</#if>
-:<#t/>
-<#include "/${parameters.templateDir}/${parameters.theme}/tooltip.ftl" /> 
-</label><#t/>
-</#if>
-    </th><#lt/>
-<#-- add the extra row -->
-<#if parameters.labelposition?default("") == 'top'>
-</tr>
-<tr>
-</#if>
diff --git a/continuum-webapp/src/main/resources/template/default/controlheader.ftl b/continuum-webapp/src/main/resources/template/default/controlheader.ftl
deleted file mode 100644
index e130265..0000000
--- a/continuum-webapp/src/main/resources/template/default/controlheader.ftl
+++ /dev/null
@@ -1,2 +0,0 @@
-<#include "/${parameters.templateDir}/${parameters.theme}/controlheader-core.ftl" />
-    <td>
diff --git a/continuum-webapp/src/main/resources/template/default/data.ftl b/continuum-webapp/src/main/resources/template/default/data.ftl
deleted file mode 100644
index aa36f52..0000000
--- a/continuum-webapp/src/main/resources/template/default/data.ftl
+++ /dev/null
@@ -1,9 +0,0 @@
-<#include "/${parameters.templateDir}/${parameters.theme}/controlheader.ftl" />
-<#if parameters.valueLink?exists>
-    <a href="${parameters.valueLink}">    
-</#if>    
-<#if parameters.nameValue?exists>${parameters.nameValue}</#if>
-<#if parameters.valueLink?exists>
-    </a>    
-</#if>    
-<#include "/${parameters.templateDir}/${parameters.theme}/controlfooter.ftl" />
diff --git a/continuum-webapp/src/main/resources/template/default/datepicker.ftl b/continuum-webapp/src/main/resources/template/default/datepicker.ftl
deleted file mode 100644
index 23fe4be..0000000
--- a/continuum-webapp/src/main/resources/template/default/datepicker.ftl
+++ /dev/null
@@ -1,3 +0,0 @@
-<#include "/${parameters.templateDir}/${parameters.theme}/controlheader.ftl" />
-<#include "/${parameters.templateDir}/simple/datepicker.ftl" />
-<#include "/${parameters.templateDir}/${parameters.theme}/controlfooter.ftl" />
diff --git a/continuum-webapp/src/main/resources/template/default/debug.ftl b/continuum-webapp/src/main/resources/template/default/debug.ftl
deleted file mode 100644
index 99bc91a..0000000
--- a/continuum-webapp/src/main/resources/template/default/debug.ftl
+++ /dev/null
@@ -1 +0,0 @@
-<#include "/${parameters.templateDir}/simple/debug.ftl" />
diff --git a/continuum-webapp/src/main/resources/template/default/doubleselect.ftl b/continuum-webapp/src/main/resources/template/default/doubleselect.ftl
deleted file mode 100644
index 4a2bd0e..0000000
--- a/continuum-webapp/src/main/resources/template/default/doubleselect.ftl
+++ /dev/null
@@ -1,4 +0,0 @@
-<#include "/${parameters.templateDir}/${parameters.theme}/controlheader.ftl" />
-
-<#include "/${parameters.templateDir}/simple/doubleselect.ftl" />
-    <#include "/${parameters.templateDir}/${parameters.theme}/controlfooter.ftl" /><#nt/>
diff --git a/continuum-webapp/src/main/resources/template/default/file.ftl b/continuum-webapp/src/main/resources/template/default/file.ftl
deleted file mode 100644
index e86be6c..0000000
--- a/continuum-webapp/src/main/resources/template/default/file.ftl
+++ /dev/null
@@ -1,35 +0,0 @@
-<#include "/${parameters.templateDir}/${parameters.theme}/controlheader.ftl" />
-<input type="file"<#rt/>
- name="${parameters.name?default("")?html}"<#rt/>
-<#if parameters.get("size")?exists>
- size="${parameters.get("size")?html}"<#rt/>
-<#else>
- size="100"<#rt/>
-</#if>
-<#if parameters.nameValue?exists>
- value="<@s.property value="parameters.nameValue"/>"<#rt/>
-</#if>
-<#if parameters.disabled?default(false)>
- disabled="disabled"<#rt/>
-</#if>
-<#if parameters.accept?exists>
- accept="${parameters.accept?html}"<#rt/>
-</#if>
-<#if parameters.tabindex?exists>
- tabindex="${parameters.tabindex?html}"<#rt/>
-</#if>
-<#if parameters.id?exists>
- id="${parameters.id?html}"<#rt/>
-</#if>
-<#if parameters.cssClass?exists>
- class="${parameters.cssClass?html}"<#rt/>
-</#if>
-<#if parameters.cssStyle?exists>
- style="${parameters.cssStyle?html}"<#rt/>
-</#if>
-<#if parameters.title?exists>
- title="${parameters.title?html}"<#rt/>
-</#if>
-<#include "/${parameters.templateDir}/simple/scripting-events.ftl" />
-/>
-<#include "/${parameters.templateDir}/${parameters.theme}/controlfooter.ftl" />
diff --git a/continuum-webapp/src/main/resources/template/default/form-close-validate.ftl b/continuum-webapp/src/main/resources/template/default/form-close-validate.ftl
deleted file mode 100644
index 749577f..0000000
--- a/continuum-webapp/src/main/resources/template/default/form-close-validate.ftl
+++ /dev/null
@@ -1,105 +0,0 @@
-<#--
-START SNIPPET: supported-validators
-Only the following validators are supported:
-* required validator
-* requiredstring validator
-* stringlength validator
-* regex validator
-* email validator
-* url validator
-* int validator
-* double validator
-END SNIPPET: supported-validators
--->
-<#if parameters.validate?default(false) == true>
-<script>
-    function validateForm_${parameters.id}() {
-        form = document.getElementById("${parameters.id}");
-        clearErrorMessages(form);
-        clearErrorLabels(form);
-
-        var errors = false;
-    <#list parameters.tagNames as tagName>
-        <#list tag.getValidators("${tagName}") as validator>
-        // field name: ${validator.fieldName}
-        // validator name: ${validator.validatorType}
-        if (form.elements['${validator.fieldName}']) {
-            field = form.elements['${validator.fieldName}'];
-            var error = "${validator.getMessage(action)?js_string}";
-            <#if validator.validatorType = "required">
-            if (field.value == "") {
-                addError(field, error);
-                errors = true;
-            }
-            <#elseif validator.validatorType = "requiredstring">
-            if (field.value != null && (field.value == "" || field.value.replace(/^\s+|\s+$/g,"").length == 0)) {
-                addError(field, error);
-                errors = true;
-            }
-            <#elseif validator.validatorType = "stringlength">
-            if (field.value != null) {
-                var value = field.value;
-                <#if validator.trim>
-                    //trim field value
-                    while (value.substring(0,1) == ' ')
-                        value = value.substring(1, value.length);
-                    while (value.substring(value.length-1, value.length) == ' ')
-                        value = value.substring(0, value.length-1);
-                </#if>
-                if((${validator.minLength} > -1 && value.length < ${validator.minLength}) ||
-                        (${validator.maxLength} > -1 && value.length > ${validator.maxLength})) {
-                    addError(field, error);
-                    errors = true;
-                }
-            }
-            <#elseif validator.validatorType = "regex">
-            if (field.value != null && !field.value.match("${validator.expression?js_string}")) {
-                addError(field, error);
-                errors = true;
-            }
-            <#elseif validator.validatorType = "stringregex">
-			if (field.value != null && !field.value.match(/${validator.regex}/)) {
-				addError(field, error);
-				errors = true;
-			}
-            <#elseif validator.validatorType = "email">
-            <#--if (field.value != null && field.value.length > 0 && field.value.match(/^\S+@\S+\.(com|net|org|info|edu|mil|gov|biz|ws|us|tv|cc|aero|arpa|coop|int|jobs|museum|name|pro|travel|nato|.{2,2})$/gi) == null) { -->
-            if (field.value != null && field.value.length > 0 && field.value.match(/(^[_A-Za-z0-9-]+(\.[_A-Za-z0-9-]+)*@([A-Za-z0-9-])+(\.[A-Za-z0-9-]+)*((\.com)|(\.net)|(\.org)|(\.info)|(\.edu)|(\.mil)|(\.gov)|(\.biz)|(\.ws)|(\.us)|(\.tv)|(\.cc)|(\.aero)|(\.arpa)|(\.coop)|(\.int)|(\.jobs)|(\.museum)|(\.name)|(\.pro)|(\.travel)|(\.nato)|(\.[A-Za-z0-9]{2,3})|(\.[A-Za-z0-9]{2,3}\.[A-Za-z0-9]{2,3}))$)/gi) == null) { 
-                addError(field, error);
-                errors = true;
-            }
-            <#elseif validator.validatorType = "url">
-            if (field.value != null && field.value.length > 0 && field.value.match(/^((file:\/\/\S+)|(ftp|http|https):\/\/\S+\.(com|net|org|info|edu|mil|gov|biz|ws|us|tv|cc|aero|arpa|coop|int|jobs|museum|name|pro|travel|nato|.{2,2}))$/ig) == null) {
-                addError(field, error);
-                errors = true;
-            }
-            <#elseif validator.validatorType = "int">
-            if (field.value != null) {
-                if (<#if validator.min?exists>parseInt(field.value) <
-                     ${validator.min}<#else>false</#if> ||
-                        <#if validator.max?exists>parseInt(field.value) >
-                           ${validator.max}<#else>false</#if>) {
-                    addError(field, error);
-                    errors = true;
-                }
-            }
-            <#elseif validator.validatorType = "double">
-            if (field.value != null) {
-                var value = parseFloat(field.value);
-                if (<#if validator.minInclusive?exists>value < ${validator.minInclusive}<#else>false</#if> ||
-                        <#if validator.maxInclusive?exists>value > ${validator.maxInclusive}<#else>false</#if> ||
-                        <#if validator.minExclusive?exists>value <= ${validator.minExclusive}<#else>false</#if> ||
-                        <#if validator.maxExclusive?exists>value >= ${validator.maxExclusive}<#else>false</#if>) {
-                    addError(field, error);
-                    errors = true;
-                }
-            }
-            </#if>
-        }
-        </#list>
-    </#list>
-
-        return !errors;
-    }
-</script>
-</#if>
diff --git a/continuum-webapp/src/main/resources/template/default/form-close.ftl b/continuum-webapp/src/main/resources/template/default/form-close.ftl
deleted file mode 100644
index d5777d1..0000000
--- a/continuum-webapp/src/main/resources/template/default/form-close.ftl
+++ /dev/null
@@ -1,2 +0,0 @@
-<#include "/${parameters.templateDir}/simple/form-close.ftl" />
-<#include "/${parameters.templateDir}/${parameters.theme}/form-close-validate.ftl" />
diff --git a/continuum-webapp/src/main/resources/template/default/form-validate.ftl b/continuum-webapp/src/main/resources/template/default/form-validate.ftl
deleted file mode 100644
index 8c27a57..0000000
--- a/continuum-webapp/src/main/resources/template/default/form-validate.ftl
+++ /dev/null
@@ -1,8 +0,0 @@
-<#if parameters.validate?default(false) == true>
-	<script src="${base}/struts/validation.js"></script>
-	<#if parameters.onsubmit?exists>
-		${tag.addParameter('onsubmit', "${parameters.onsubmit}; customOnsubmit(); return validateForm_${parameters.id}();")}
-	<#else>
-		${tag.addParameter('onsubmit', "customOnsubmit(); return validateForm_${parameters.id}();")}
-	</#if>
-</#if>
diff --git a/continuum-webapp/src/main/resources/template/default/form.ftl b/continuum-webapp/src/main/resources/template/default/form.ftl
deleted file mode 100644
index bd7cfc0..0000000
--- a/continuum-webapp/src/main/resources/template/default/form.ftl
+++ /dev/null
@@ -1,2 +0,0 @@
-<#include "/${parameters.templateDir}/${parameters.theme}/form-validate.ftl" />
-<#include "/${parameters.templateDir}/simple/form.ftl" />
diff --git a/continuum-webapp/src/main/resources/template/default/head.ftl b/continuum-webapp/src/main/resources/template/default/head.ftl
deleted file mode 100644
index 0b01ce4..0000000
--- a/continuum-webapp/src/main/resources/template/default/head.ftl
+++ /dev/null
@@ -1,34 +0,0 @@
-<#--
-/*
- *
- * 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.
- */
--->
-<script type="text/javascript">
-    // Dojo configuration
-    djConfig = {
-        baseRelativePath: "<@s.url includeParams='none' value='/struts/dojo' includeParams="none" encode='false'/>",
-        isDebug: ${parameters.debug?default(false)},
-        bindEncoding: "${parameters.encoding}",
-        debugAtAllCosts: true // not needed, but allows the Venkman debugger to work with the includes
-    };
-</script>
-<script type="text/javascript"
-        src="<@s.url includeParams='none' value='/struts/dojo/dojo.js' includeParams="none" encode='false'/>"></script>
-<script type="text/javascript"
-        src="<@s.url includeParams='none' value='/struts/dojoRequire.js' includeParams="none" encode='false'/>"></script>
\ No newline at end of file
diff --git a/continuum-webapp/src/main/resources/template/default/hidden.ftl b/continuum-webapp/src/main/resources/template/default/hidden.ftl
deleted file mode 100644
index 2a22f1c..0000000
--- a/continuum-webapp/src/main/resources/template/default/hidden.ftl
+++ /dev/null
@@ -1 +0,0 @@
-<#include "/${parameters.templateDir}/simple/hidden.ftl" />
\ No newline at end of file
diff --git a/continuum-webapp/src/main/resources/template/default/label.ftl b/continuum-webapp/src/main/resources/template/default/label.ftl
deleted file mode 100644
index d4527d5..0000000
--- a/continuum-webapp/src/main/resources/template/default/label.ftl
+++ /dev/null
@@ -1,3 +0,0 @@
-<#include "/${parameters.templateDir}/${parameters.theme}/controlheader.ftl" />
-<#include "/${parameters.templateDir}/simple/label.ftl" />
-<#include "/${parameters.templateDir}/${parameters.theme}/controlfooter.ftl" />
diff --git a/continuum-webapp/src/main/resources/template/default/optiontransferselect.ftl b/continuum-webapp/src/main/resources/template/default/optiontransferselect.ftl
deleted file mode 100644
index 408c006..0000000
--- a/continuum-webapp/src/main/resources/template/default/optiontransferselect.ftl
+++ /dev/null
@@ -1,3 +0,0 @@
-<#include "/${parameters.templateDir}/${parameters.theme}/controlheader.ftl" />
-<#include "/${parameters.templateDir}/simple/optiontransferselect.ftl" />
-<#include "/${parameters.templateDir}/${parameters.theme}/controlfooter.ftl" /><#nt/>
diff --git a/continuum-webapp/src/main/resources/template/default/password.ftl b/continuum-webapp/src/main/resources/template/default/password.ftl
deleted file mode 100644
index 37992a8..0000000
--- a/continuum-webapp/src/main/resources/template/default/password.ftl
+++ /dev/null
@@ -1,38 +0,0 @@
-<#include "/${parameters.templateDir}/${parameters.theme}/controlheader.ftl" />
-<input type="password"<#rt/>
- name="${parameters.name?default("")?html}"<#rt/>
-<#if parameters.get("size")?exists>
- size="${parameters.get("size")?html}"<#rt/>
-<#else>
- size="100"<#rt/>
-</#if>
-<#if parameters.maxlength?exists>
- maxlength="${parameters.maxlength?html}"<#rt/>
-</#if>
-<#if parameters.nameValue?exists && parameters.showPassword?default(false)>
- value="<@s.property value="parameters.nameValue"/>"<#rt/>
-</#if>
-<#if parameters.disabled?default(false)>
- disabled="disabled"<#rt/>
-</#if>
-<#if parameters.readonly?exists>
- readonly="readonly"<#rt/>
-</#if>
-<#if parameters.tabindex?exists>
- tabindex="${parameters.tabindex?html}"<#rt/>
-</#if>
-<#if parameters.id?exists>
- id="${parameters.id?html}"<#rt/>
-</#if>
-<#if parameters.cssClass?exists>
- class="${parameters.cssClass?html}"<#rt/>
-</#if>
-<#if parameters.cssStyle?exists>
- style="${parameters.cssStyle?html}"<#rt/>
-</#if>
-<#if parameters.title?exists>
- title="${parameters.title?html}"<#rt/>
-</#if>
-<#include "/${parameters.templateDir}/simple/scripting-events.ftl" />
-/>
-<#include "/${parameters.templateDir}/${parameters.theme}/controlfooter.ftl" />
diff --git a/continuum-webapp/src/main/resources/template/default/radiomap.ftl b/continuum-webapp/src/main/resources/template/default/radiomap.ftl
deleted file mode 100644
index 871da3f..0000000
--- a/continuum-webapp/src/main/resources/template/default/radiomap.ftl
+++ /dev/null
@@ -1,4 +0,0 @@
-<#include "/${parameters.templateDir}/${parameters.theme}/controlheader.ftl" />
-
-<#include "/${parameters.templateDir}/simple/radiomap.ftl" />
-    <#include "/${parameters.templateDir}/${parameters.theme}/controlfooter.ftl" /><#nt/>
diff --git a/continuum-webapp/src/main/resources/template/default/reset.ftl b/continuum-webapp/src/main/resources/template/default/reset.ftl
deleted file mode 100644
index 0999203..0000000
--- a/continuum-webapp/src/main/resources/template/default/reset.ftl
+++ /dev/null
@@ -1,9 +0,0 @@
-<tr>
-    <td colspan="2"><div <#rt/>
-<#if parameters.align?exists>
-    align="${parameters.align?html}"<#t/>
-</#if>
-><#t/>
-<#include "/${parameters.templateDir}/simple/reset.ftl" />
-</div><#t/>
-<#include "/${parameters.templateDir}/${parameters.theme}/controlfooter.ftl" />
diff --git a/continuum-webapp/src/main/resources/template/default/richtexteditor.ftl b/continuum-webapp/src/main/resources/template/default/richtexteditor.ftl
deleted file mode 100644
index b5cf8c8..0000000
--- a/continuum-webapp/src/main/resources/template/default/richtexteditor.ftl
+++ /dev/null
@@ -1,3 +0,0 @@
-<#include "/${parameters.templateDir}/${parameters.theme}/controlheader.ftl" />
-<#include "/${parameters.templateDir}/simple/richtexteditor.ftl" />
-<#include "/${parameters.templateDir}/${parameters.theme}/controlfooter.ftl" />
diff --git a/continuum-webapp/src/main/resources/template/default/select.ftl b/continuum-webapp/src/main/resources/template/default/select.ftl
deleted file mode 100644
index c01331d..0000000
--- a/continuum-webapp/src/main/resources/template/default/select.ftl
+++ /dev/null
@@ -1,3 +0,0 @@
-<#include "/${parameters.templateDir}/${parameters.theme}/controlheader.ftl" />
-<#include "/${parameters.templateDir}/simple/select.ftl" />
-<#include "/${parameters.templateDir}/${parameters.theme}/controlfooter.ftl" />
diff --git a/continuum-webapp/src/main/resources/template/default/styles.css b/continuum-webapp/src/main/resources/template/default/styles.css
deleted file mode 100644
index 66a8374..0000000
--- a/continuum-webapp/src/main/resources/template/default/styles.css
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.
- */
-
-.wwFormTable {}
-.label {font-style:italic; }
-.errorLabel {font-style:italic; color:red; }
-.errorMessage {font-weight:bold; text-align: center; color:red; }
-.checkboxLabel {}
-.checkboxErrorLabel {color:red; }
-.required {color:red;}
-.tdLabel {text-align:right; vertical-align:top; } 
diff --git a/continuum-webapp/src/main/resources/template/default/submit.ftl b/continuum-webapp/src/main/resources/template/default/submit.ftl
deleted file mode 100644
index 50460be..0000000
--- a/continuum-webapp/src/main/resources/template/default/submit.ftl
+++ /dev/null
@@ -1,8 +0,0 @@
-<#if parameters.before?exists>
-${parameters.before}
-</#if>
-<#include "/${parameters.templateDir}/simple/submit.ftl" />
-<#if parameters.after?exists>
-${parameters.after}
-</#if>
-
diff --git a/continuum-webapp/src/main/resources/template/default/submitCancel.ftl b/continuum-webapp/src/main/resources/template/default/submitCancel.ftl
deleted file mode 100644
index 5af9695..0000000
--- a/continuum-webapp/src/main/resources/template/default/submitCancel.ftl
+++ /dev/null
@@ -1,5 +0,0 @@
-<#include "/${parameters.templateDir}/simple/submit.ftl" />
-<#if parameters.cancel?exists>
-&nbsp;<input type="button" name="Cancel" value="${parameters.cancel}" onClick="history.back()"/>
-</#if>
-
diff --git a/continuum-webapp/src/main/resources/template/default/text.ftl b/continuum-webapp/src/main/resources/template/default/text.ftl
deleted file mode 100644
index e33c004..0000000
--- a/continuum-webapp/src/main/resources/template/default/text.ftl
+++ /dev/null
@@ -1,38 +0,0 @@
-<#include "/${parameters.templateDir}/${parameters.theme}/controlheader.ftl" />
-<input type="text"<#rt/>
- name="${parameters.name?default("")?html}"<#rt/>
-<#if parameters.get("size")?exists>
- size="${parameters.get("size")?html}"<#rt/>
-<#else>
- size="100"<#rt/>
-</#if>
-<#if parameters.maxlength?exists>
- maxlength="${parameters.maxlength?html}"<#rt/>
-</#if>
-<#if parameters.nameValue?exists>
- value="<@s.property value="parameters.nameValue"/>"<#rt/>
-</#if>
-<#if parameters.disabled?default(false)>
- disabled="disabled"<#rt/>
-</#if>
-<#if parameters.readonly?exists>
- readonly="readonly"<#rt/>
-</#if>
-<#if parameters.tabindex?exists>
- tabindex="${parameters.tabindex?html}"<#rt/>
-</#if>
-<#if parameters.id?exists>
- id="${parameters.id?html}"<#rt/>
-</#if>
-<#if parameters.cssClass?exists>
- class="${parameters.cssClass?html}"<#rt/>
-</#if>
-<#if parameters.cssStyle?exists>
- style="${parameters.cssStyle?html}"<#rt/>
-</#if>
-<#if parameters.title?exists>
- title="${parameters.title?html}"<#rt/>
-</#if>
-<#include "/${parameters.templateDir}/simple/scripting-events.ftl" />
-/>
-<#include "/${parameters.templateDir}/${parameters.theme}/controlfooter.ftl" />
diff --git a/continuum-webapp/src/main/resources/template/default/textarea.ftl b/continuum-webapp/src/main/resources/template/default/textarea.ftl
deleted file mode 100644
index 0b84f10..0000000
--- a/continuum-webapp/src/main/resources/template/default/textarea.ftl
+++ /dev/null
@@ -1,3 +0,0 @@
-<#include "/${parameters.templateDir}/${parameters.theme}/controlheader.ftl" />
-<#include "/${parameters.templateDir}/simple/textarea.ftl" />
-<#include "/${parameters.templateDir}/${parameters.theme}/controlfooter.ftl" />
diff --git a/continuum-webapp/src/main/resources/template/default/theme.properties b/continuum-webapp/src/main/resources/template/default/theme.properties
deleted file mode 100644
index 0f2fddc..0000000
--- a/continuum-webapp/src/main/resources/template/default/theme.properties
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# 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.
-#
-
-parent = xhtml
diff --git a/continuum-webapp/src/main/resources/template/default/tooltip.ftl b/continuum-webapp/src/main/resources/template/default/tooltip.ftl
deleted file mode 100644
index 0afd6b3..0000000
--- a/continuum-webapp/src/main/resources/template/default/tooltip.ftl
+++ /dev/null
@@ -1,87 +0,0 @@
-<#if parameters.tooltip?exists><#t/>
-      <img 
-      <#if parameters.tooltipIcon?exists><#t/>
-      	src='<@s.url value="${parameters.tooltipIcon}" />' 
-      <#else><#t/>
-      	src='<@s.url value="/webwork/tooltip/tooltip.gif" />'
-      </#if><#t/>
-      	alt="${parameters.tooltip?html}" 
-      	title="${parameters.tooltip?html}" 
-      	onmouseover="<#rt/>
-      <#if parameters.tooltipAboveMousePointer?exists><#t/>
-    	<#t/>this.T_ABOVE=${parameters.tooltipAboveMousePointer};<#t/>
-      </#if><#t/>
-      <#if parameters.tooltipBgColor?exists><#t/>
-        <#t/>this.T_BGCOLOR='${parameters.tooltipBgColor}';<#t/>
-      </#if><#t/>
-      <#if parameters.tooltipBgImg?exists><#t/>
-        <#t/>this.T_BGIMG='<@s.url value="${parameters.tooltipBgImg}" />';<#t/>
-      </#if><#t/>
-      <#if parameters.tooltipBorderWidth?exists><#t/>
-        <#t/>this.T_BORDERWIDTH=${parameters.tooltipBorderWidth};<#t/>
-      </#if><#t/>
-      <#if parameters.tooltipBorderColor?exists><#t/>
-        <#t/>this.T_BORDERCOLOR='${parameters.tooltipBorderColor}';<#t/>
-      </#if><#t/>
-      <#if parameters.tooltipDelay?exists><#t/>
-      	<#t/>this.T_DELAY=${parameters.tooltipDelay};<#t/>
-      </#if><#t/>
-      <#if parameters.tooltipFixCoordinateX?exists && parameters.tooltipFixCoordinateY?exists><#t/>
-      	<#t/>this.T_FIX=[${parameters.tooltipFixCoordinateX}, ${parameters.tooltipFixCoordinateY}];<#t/>
-      </#if><#t/>
-      <#if parameters.tooltipFontColor?exists><#t/>
-      	<#t/>this.T_FONTCOLOR='${parameters.tooltipFontColor}';<#t/>
-      </#if><#t/>
-      <#if parameters.tooltipFontFace?exists><#t/>
-        <#t/>this.T_FONTFACE='${parameters.tooltipFontFace}';<#t/>
-      </#if><#t/>
-      <#if parameters.tooltipFontSize?exists><#t/>
-      	<#t/>this.T_FONTSIZE='${parameters.tooltipFontSize}';<#t/>
-      </#if><#t/>
-      <#if parameters.tooltipFontWeight?exists><#t/>
-      	<#t/>this.T_FONTWEIGHT='${parameters.tooltipFontWeight}';<#t/>
-      </#if><#t/>
-      <#if parameters.tooltipLeftOfMousePointer?exists><#t/><#t/>
-      	<#t/>this.T_LEFT=${parameters.tooltipLeftOfMousePointer};<#t/>
-      </#if><#t/>
-      <#if parameters.tooltipOffsetX?exists><#t/>
-      	<#t/>this.T_OFFSETX=${parameters.tooltipOffsetX};<#t/>
-      </#if><#t/>
-      <#if parameters.tooltipOffsetY?exists><#t/>
-      	<#t/>this.T_OFFSETY=${parameters.tooltipOffsetY};<#t/>
-      </#if><#t/>
-      <#if parameters.tooltipOpacity?exists><#t/>
-      	<#t/>this.T_OPACITY=${parameters.tooltipOpacity};<#t/>
-      </#if><#t/>
-      <#if parameters.tooltipPadding?exists><#t/>
-      	<#t/>this.T_PADDING=${parameters.tooltipPadding};<#t/>
-      </#if><#t/>
-      <#if parameters.tooltipShadowColor?exists><#t/>
-      	<#t/>this.T_SHADOWCOLOR='${parameters.tooltipShadowColor}';<#t/>
-      </#if><#t/>
-      <#if parameters.tooltipShadowWidth?exists><#t/>
-      	<#t/>this.T_SHADOWWIDTH=${parameters.tooltipShadowWidth};<#t/>
-      </#if><#t/>
-      <#if parameters.tooltipStatic?exists><#t/>
-        <#t/>this.T_STATIC=${parameters.tooltipStatic};<#t/>
-      </#if><#t/>
-      <#if parameters.tooltipSticky?exists>
-      	<#t/>this.T_STICKY=${parameters.tooltipSticky};<#t/>
-      </#if><#t/>
-      <#if parameters.tooltipStayAppearTime?exists><#t/>
-      	<#t/>this.T_TEMP=${parameters.tooltipStayAppearTime};<#t/>
-      </#if><#t/>
-      <#if parameters.tooltipTextAlign?exists><#t/>
-      	<#t/>this.T_TEXTALIGN='${parameters.tooltipTextAlign}';<#t/>
-      </#if><#t/>
-      <#if parameters.tooltipTitle?exists><#t/>
-      	<#t/>this.T_TITLE='${parameters.tooltipTitle?js_string}';<#t/>
-      </#if><#t/>
-      <#if parameters.tooltipTitleColor?exists><#t/>
-        <#t/>this.T_TITLECOLOR='${parameters.tooltipTitleColor}';<#t/>
-      </#if><#t/>
-      <#if parameters.tooltipWidth?exists><#t/>
-      	<#t/>this.T_WIDTH=${parameters.tooltipWidth};<#t/>
-      </#if><#t/>
-      	<#t/>return escape('${parameters.tooltip?js_string}');" />
-</#if><#t/>
diff --git a/continuum-webapp/src/main/resources/template/default/updownselect.ftl b/continuum-webapp/src/main/resources/template/default/updownselect.ftl
deleted file mode 100644
index 00fe5a0..0000000
--- a/continuum-webapp/src/main/resources/template/default/updownselect.ftl
+++ /dev/null
@@ -1,3 +0,0 @@
-<#include "/${parameters.templateDir}/${parameters.theme}/controlheader.ftl" />
-<#include "/${parameters.templateDir}/simple/updownselect.ftl" />
-<#include "/${parameters.templateDir}/${parameters.theme}/controlfooter.ftl" /><#nt/>
diff --git a/continuum-webapp/src/main/resources/template/default/validation.js b/continuum-webapp/src/main/resources/template/default/validation.js
deleted file mode 100644
index 38fdfe3..0000000
--- a/continuum-webapp/src/main/resources/template/default/validation.js
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * 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.
- */
-
-function clearErrorMessages(form) {
-
-    //var table = form.childNodes[1];
-    //if( typeof table == "undefined" ) {
-    //    table = form.childNodes[0];
-    //}
-    // ie fix
-    var table = form.getElementsByTagName("table")[0];
-    
-
-    // clear out any rows with an "errorFor" attribute
-    var rows = table.rows;
-    var rowsToDelete = new Array();
-    if (rows == null){
-        return;
-    }
-
-    for(var i = 0; i < rows.length; i++) {
-        var r = rows[i];
-        if (r.getAttribute("errorFor")) {
-            rowsToDelete.push(r);
-        }
-    }
-
-    // now delete the rows
-    for (var i = 0; i < rowsToDelete.length; i++) {
-        var r = rowsToDelete[i];
-        table.deleteRow(r.rowIndex);
-        //table.removeChild(rowsToDelete[i]); 
-    }
-}
-
-function clearErrorLabels(form) {
-    // set all labels back to the normal class
-    var elements = form.elements;
-    for (var i = 0; i < elements.length; i++) {
-        var e = elements[i];
-        var cells = e.parentNode.parentNode.cells;
-        if (cells && cells.length >= 2) {
-            var label = cells[0].getElementsByTagName("label")[0];
-            if (label) {
-                label.setAttribute("class", "label");
-                label.setAttribute("className", "label"); //ie hack cause ie does not support setAttribute
-            }
-        }
-    }
-
-}
-
-function addError(e, errorText) {
-    try {
-        // clear out any rows with an "errorFor" of e.id
-        var row = e.parentNode.parentNode;
-        var table = row.parentNode;
-        var error = document.createTextNode(errorText);
-        var tr = document.createElement("tr");
-        var td = document.createElement("td");
-        var span = document.createElement("span");
-        td.align = "center";
-        td.valign = "top";
-        td.colSpan = 2;
-        span.setAttribute("class", "errorMessage");
-        span.setAttribute("className", "errorMessage"); //ie hack cause ie does not support setAttribute
-        span.appendChild(error);
-        td.appendChild(span);
-        tr.appendChild(td);
-        tr.setAttribute("errorFor", e.id);;
-        table.insertBefore(tr, row);
-
-        // updat the label too
-        var label = row.cells[0].getElementsByTagName("label")[0];
-        label.setAttribute("class", "errorLabel");
-        label.setAttribute("className", "errorLabel"); //ie hack cause ie does not support setAttribute
-    } catch (e) {
-        alert(e);
-    }
-}
diff --git a/continuum-webapp/src/main/resources/template/profile/select.ftl b/continuum-webapp/src/main/resources/template/profile/select.ftl
deleted file mode 100644
index c8160d4..0000000
--- a/continuum-webapp/src/main/resources/template/profile/select.ftl
+++ /dev/null
@@ -1 +0,0 @@
-<#include "/${parameters.templateDir}/simple/select.ftl" />

diff --git a/continuum-webapp/src/main/resources/template/xhtml/hidden.ftl b/continuum-webapp/src/main/resources/template/xhtml/hidden.ftl
new file mode 100644
index 0000000..640aa48
--- /dev/null
+++ b/continuum-webapp/src/main/resources/template/xhtml/hidden.ftl
@@ -0,0 +1,23 @@
+<#--
+/*
+ * $Id$
+ *
+ * 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.
+ */
+-->
+<#include "/${parameters.templateDir}/simple/hidden.ftl" />
diff --git a/continuum-webapp/src/main/resources/validators.xml b/continuum-webapp/src/main/resources/validators.xml
index 0bae596..abb4d78 100644
--- a/continuum-webapp/src/main/resources/validators.xml
+++ b/continuum-webapp/src/main/resources/validators.xml
@@ -16,9 +16,10 @@
   ~ specific language governing permissions and limitations
   ~ under the License.
   -->
-<!DOCTYPE validators PUBLIC
-         "-//OpenSymphony Group//XWork Validator Config 1.0//EN"      
-         "http://www.opensymphony.com/xwork/xwork-validator-config-1.0.dtd">
+
+<!DOCTYPE validators PUBLIC 
+  "-//Apache Struts//XWork Validator Config 1.0//EN"
+  "http://struts.apache.org/dtds/xwork-validator-config-1.0.dtd">
 
 
 <validators>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/applicationContext.xml b/continuum-webapp/src/main/webapp/WEB-INF/applicationContext.xml
index b79e1f7..94d5c47 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/applicationContext.xml
+++ b/continuum-webapp/src/main/webapp/WEB-INF/applicationContext.xml
@@ -25,27 +25,27 @@
            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
 
   <bean id="loggerManager" class="org.codehaus.plexus.logging.slf4j.Slf4jLoggerManager"
-    init-method="initialize"/>
+        init-method="initialize"/>
 
-  <bean id="propertyConfigurer" 
-         class="org.codehaus.plexus.spring.PlexusServletContextPropertyPlaceholderConfigurer">
+  <bean id="propertyConfigurer"
+        class="org.codehaus.plexus.spring.PlexusServletContextPropertyPlaceholderConfigurer">
     <property name="locations">
       <list>
         <value>classpath:plexus.properties</value>
       </list>
-    </property> 
+    </property>
     <!-- ignore if plexus.properties not found -->
     <property name="ignoreResourceNotFound">
       <value>true</value>
-    </property>  
+    </property>
     <!-- ignore if a interpolated key not exists -->
     <property name="ignoreUnresolvablePlaceholders">
       <value>true</value>
-    </property> 
+    </property>
   </bean>
 
   <!-- to run builds in a chroot jail environment
-       note this is not secure yet, see http://jira.codehaus.org/browse/CONTINUUM-1731 
+       note this is not secure yet, see http://jira.codehaus.org/browse/CONTINUUM-1731
   <bean name="chrootJailDirectory" class="java.io.File">
     <constructor-arg value="/home/jail"/>
   </bean>
@@ -55,20 +55,21 @@
   <bean id="mailSession" class="org.springframework.jndi.JndiObjectFactoryBean">
     <property name="jndiName" value="java:comp/env/mail/Session">
     </property>
-  </bean>  
-  
+  </bean>
+
   <bean name="mailSender#continuum" class="org.springframework.mail.javamail.JavaMailSenderImpl">
     <property name="session" ref="mailSession"/>
-  </bean>   
-	
+  </bean>
+
   <bean name="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
     <property name="session" ref="mailSession"/>
-  </bean>	
-  
-  <bean id="masterBuildAgentTransportServer" class="org.apache.continuum.distributed.transport.master.MasterBuildAgentTransportServer">
-    <constructor-arg ref="distributedBuildManager"/>
   </bean>
-  
+
+  <bean id="masterBuildAgentTransportServer"
+        class="org.apache.continuum.distributed.transport.master.MasterBuildAgentTransportServer">
+    <constructor-arg ref="distributedBuildService"/>
+  </bean>
+
   <bean name="xmlrpcServicesList" class="java.util.ArrayList">
     <constructor-arg>
       <list>
@@ -76,5 +77,73 @@
       </list>
     </constructor-arg>
   </bean>
-    
+
+  <!-- Redback Web Services -->
+  <bean name="redbackRoleService" lazy-init="true" scope="singleton"
+        class="org.codehaus.redback.xmlrpc.service.RoleServiceImpl">
+    <constructor-arg ref="rBACManager#cached"/>
+    <constructor-arg ref="roleManager"/>
+  </bean>
+
+  <bean name="redbackOperationService" lazy-init="true" scope="singleton"
+        class="org.codehaus.redback.xmlrpc.service.OperationServiceImpl">
+    <constructor-arg ref="rBACManager#cached"/>
+  </bean>
+
+  <bean name="redbackPermissionService" lazy-init="true" scope="singleton"
+        class="org.codehaus.redback.xmlrpc.service.PermissionServiceImpl">
+    <constructor-arg ref="rBACManager#cached"/>
+  </bean>
+
+  <bean name="redbackResourceService" lazy-init="true" scope="singleton"
+        class="org.codehaus.redback.xmlrpc.service.ResourceServiceImpl">
+    <constructor-arg ref="rBACManager#cached"/>
+  </bean>
+
+  <bean name="redbackUserService" lazy-init="true" scope="singleton"
+        class="org.codehaus.redback.xmlrpc.service.UserServiceImpl">
+    <constructor-arg ref="userManager#cached"/>
+  </bean>
+
+  <bean name="redbackXmlrpcServicesList" class="java.util.ArrayList">
+    <constructor-arg>
+      <list>
+        <ref bean="redbackOperationService"/>
+        <ref bean="redbackPermissionService"/>
+        <ref bean="redbackResourceService"/>
+        <ref bean="redbackRoleService"/>
+        <ref bean="redbackUserService"/>
+      </list>
+    </constructor-arg>
+  </bean>
+
+  <bean name="redbackXmlRpcAuthenticator" class="org.codehaus.redback.xmlrpc.security.XmlRpcAuthenticator">
+    <constructor-arg ref="securitySystem"/>
+  </bean>
+
+  <!-- triggers -->
+  <bean id="continuumBuildTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
+    <property name="jobDetail" ref="continuumBuildJob"/>
+    <property name="cronExpression" value="0 * * * * ?"/>
+  </bean>
+
+  <!-- scheduler -->
+  <bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
+    <property name="triggers">
+      <list>
+        <ref bean="continuumBuildTrigger"/>
+      </list>
+    </property>
+    <property name="schedulerName" value="Continuum Scheduler"/>
+    <property name="waitForJobsToCompleteOnShutdown" value="true"/>
+    <property name="quartzProperties">
+      <props>
+        <prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
+        <prop key="org.quartz.plugin.shutdownhook.class">org.quartz.plugins.management.ShutdownHookPlugin
+        </prop>
+        <prop key="org.quartz.plugin.shutdownhook.cleanShutdown">true</prop>
+      </props>
+    </property>
+  </bean>
+
 </beans>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/continuum.tld b/continuum-webapp/src/main/webapp/WEB-INF/continuum.tld
index cf4a560..ce3a120 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/continuum.tld
+++ b/continuum-webapp/src/main/webapp/WEB-INF/continuum.tld
@@ -18,7 +18,8 @@
   ~ under the License.
   -->
 
-<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
+<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
+    "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
 <taglib>
   <tlibversion>1.1</tlibversion>
   <jspversion>1.2</jspversion>
@@ -48,87 +49,15 @@
   </tag>
 
   <tag>
-    <name>data</name>
-    <tagclass>org.apache.maven.continuum.web.view.jsp.ui.DataTag</tagclass>
+    <name>ifBuildTypeEnabled</name>
+    <tagclass>org.apache.maven.continuum.web.view.jsp.ui.IfBuildTypeEnabledTag</tagclass>
     <bodycontent>JSP</bodycontent>
-    <info>data tag</info>
+    <info>build type tag</info>
     <attribute>
-      <name>label</name>
-      <required>false</required>
-      <rtexprvalue>true</rtexprvalue>
-    </attribute>
-    <attribute>
-      <name>name</name>
-      <required>false</required>
-      <rtexprvalue>false</rtexprvalue>
-    </attribute>
-    <attribute>
-      <name>valueLink</name>
-      <required>false</required>
-      <rtexprvalue>true</rtexprvalue>
-    </attribute>    
-  </tag>
-
-  <tag>
-    <name>submitcancel</name>
-    <tagclass>org.apache.maven.continuum.web.view.jsp.ui.SubmitCancelTag</tagclass>
-    <bodycontent>JSP</bodycontent>
-    <info>An HTML Submit-Cancel UI widget</info>
-    <attribute>
-      <name>id</name>
-      <required>false</required>
-      <rtexprvalue>false</rtexprvalue>
-    </attribute>
-    <attribute>
-      <name>cssClass</name>
-      <required>false</required>
-      <rtexprvalue>true</rtexprvalue>
-    </attribute>
-    <attribute>
-      <name>cssStyle</name>
-      <required>false</required>
-      <rtexprvalue>true</rtexprvalue>
-    </attribute>
-    <attribute>
-      <name>label</name>
-      <required>false</required>
-      <rtexprvalue>true</rtexprvalue>
-    </attribute>
-    <attribute>
-      <name>labelposition</name>
-      <required>false</required>
-      <rtexprvalue>false</rtexprvalue>
-    </attribute>
-    <attribute>
-      <name>theme</name>
-      <required>false</required>
-      <rtexprvalue>true</rtexprvalue>
-    </attribute>
-    <attribute>
-      <name>template</name>
-      <required>false</required>
-      <rtexprvalue>true</rtexprvalue>
-    </attribute>
-    <attribute>
-      <name>name</name>
-      <required>false</required>
-      <rtexprvalue>true</rtexprvalue>
-    </attribute>
-    <attribute>
-      <name>value</name>
+      <name>buildType</name>
       <required>true</required>
       <rtexprvalue>true</rtexprvalue>
     </attribute>
-    <attribute>
-      <name>align</name>
-      <required>false</required>
-      <rtexprvalue>true</rtexprvalue>
-    </attribute>
-    <attribute>
-      <name>cancel</name>
-      <required>false</required>
-      <rtexprvalue>true</rtexprvalue>
-    </attribute>
   </tag>
 
 </taglib>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jboss-web.xml b/continuum-webapp/src/main/webapp/WEB-INF/jboss-web.xml
index 045ac7e..a66a82e 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jboss-web.xml
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jboss-web.xml
@@ -1,21 +1,50 @@
 <?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<!DOCTYPE jboss-web PUBLIC
+    "-//JBoss//DTD Web Application 5.0//EN"
+    "http://www.jboss.org/j2ee/dtd/jboss-web_5_0.dtd">
 <jboss-web>
 
+  <class-loading java2ClassLoadingCompliance='false'>
+    <loader-repository>
+      org.apache.continuum:loader=continuum
+      <loader-repository-config>java2ParentDelegation=false</loader-repository-config>
+    </loader-repository>
+
+  </class-loading>
+
+  <context-root>continuum</context-root>
+
   <resource-ref>
     <res-ref-name>jdbc/continuum</res-ref-name>
-    <res-type>javax.sql.DataSource</res-type>
     <jndi-name>java:/continuum</jndi-name>
   </resource-ref>
 
   <resource-ref>
     <res-ref-name>jdbc/users</res-ref-name>
-    <res-type>javax.sql.DataSource</res-type>
     <jndi-name>java:/users</jndi-name>
   </resource-ref>
 
   <resource-ref>
     <res-ref-name>mail/Session</res-ref-name>
-    <res-type>javax.mail.Session</res-type>
     <jndi-name>java:/Mail</jndi-name>
   </resource-ref>
 
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/about.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/about.jsp
index b4c835e..469fe71 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/about.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/about.jsp
@@ -18,7 +18,6 @@
   --%>
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <html>
   <s:i18n name="localization.Continuum">
     <head>
@@ -29,12 +28,14 @@
         <h3><s:text name="about.section.title"/></h3>
         <div class="axial">
           <table border="1" cellspacing="2" cellpadding="3" width="100%">
-            <c1:data label="%{getText('about.version.label')}">
-                <s:param name="after"><s:text name="about.version.number"/></s:param>
-            </c1:data>
-            <c1:data label="%{getText('about.buildnumber.label')}">
-                <s:param name="after"><s:text name="about.buildnumber"/></s:param>
-            </c1:data>
+            <tr class="b">
+              <th><label class="label"><s:text name='about.version.label'/>:</label></th>
+              <td><s:text name="about.version.number"/></td>
+            </tr>
+            <tr class="b">
+              <th><label class="label"><s:text name='about.buildnumber.label'/>:</label></th>
+              <td><s:text name="about.buildnumber"/></td>
+            </tr>
           </table>
         </div>
       </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/addMavenOneProject.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/addMavenOneProject.jsp
index c5b26a7..1f0a73b 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/addMavenOneProject.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/addMavenOneProject.jsp
@@ -19,7 +19,6 @@
 
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <s:i18n name="localization.Continuum">
 <html>
     <head>
@@ -31,17 +30,20 @@
             <h3><s:text name="add.m1.project.section.title"/></h3>
                 <div class="axial">
                     <s:form method="post" action="addMavenOneProject.action" name="addMavenOneProject" enctype="multipart/form-data">
-                        <c:if test="${!empty actionErrors}">
+                        <c:if test="${!empty actionErrors || !empty errorMessages}">
                           <div class="errormessage">
                             <s:iterator value="actionErrors">
                               <p><s:property/></p>
                             </s:iterator>
+                            <c:forEach items="${errorMessages}" var="errorMessage">
+                              <p><c:out value="${errorMessage}"/></p>
+                            </c:forEach>
                           </div>
                         </c:if>
                         <table>
                           <tbody>
-                            <s:textfield label="%{getText('add.m1.project.m1PomUrl.label')}" name="m1PomUrl">
-                                <s:param name="desc">
+                            <s:textfield label="%{getText('add.m1.project.m1PomUrl.label')}" name="m1PomUrl" size="100">
+                                <s:param name="after">
                                 <table cellspacing="0" cellpadding="0">
                                   <tbody>
                                     <tr>
@@ -64,14 +66,14 @@
                             <s:label>
                               <s:param name="after"><strong><s:text name="or"/></strong></s:param>
                             </s:label>
-                            <s:file label="%{getText('add.m1.project.m1PomFile.label')}" name="m1PomFile">
-                                <s:param name="desc"><p><s:text name="add.m1.project.m1PomFile.message"/></p></s:param>
+                            <s:file label="%{getText('add.m1.project.m1PomFile.label')}" name="m1PomFile" size="100">
+                                <s:param name="after"><p><s:text name="add.m1.project.m1PomFile.message"/></p></s:param>
                             </s:file>
                             <c:choose>
                             <c:when test="${disableGroupSelection == true}">
                               <s:hidden name="selectedProjectGroup"/>
                               <s:hidden name="disableGroupSelection"/>
-                              <s:textfield label="%{getText('add.m1.project.projectGroup')}" name="projectGroupName" disabled="true"/>
+                              <s:textfield label="%{getText('add.m1.project.projectGroup')}" name="projectGroupName" disabled="true" size="100"/>
                             </c:when>
                             <c:otherwise>
                               <s:select label="%{getText('add.m1.project.projectGroup')}" name="selectedProjectGroup" list="projectGroups" listKey="id" listValue="name"/>
@@ -83,7 +85,8 @@
                           </tbody>
                         </table>
                         <div class="functnbar3">
-                          <c1:submitcancel value="%{getText('add')}" cancel="%{getText('cancel')}"/>
+                          <s:submit value="%{getText('add')}" theme="simple"/>
+                          <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
                         </div>
                   </s:form>
                 </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/addMavenTwoProject.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/addMavenTwoProject.jsp
index e04a64a..646e15b 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/addMavenTwoProject.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/addMavenTwoProject.jsp
@@ -19,7 +19,6 @@
 
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <s:i18n name="localization.Continuum">
 <html>
     <head>
@@ -37,14 +36,14 @@
                               <p><s:property/></p>
                             </s:iterator>
                             <c:forEach items="${errorMessages}" var="errorMessage">
-                              <p>${errorMessage}</p>
+                              <p><c:out value="${errorMessage}"/></p>
                             </c:forEach>
                           </div>
                         </c:if>
                         <table>
                           <tbody>
-                            <s:textfield label="%{getText('add.m2.project.m2PomUrl.label')}" required="true" name="m2PomUrl">
-	                            <s:param name="desc">
+                            <s:textfield label="%{getText('add.m2.project.m2PomUrl.label')}" requiredLabel="true" name="m2PomUrl" size="100">
+	                            <s:param name="after">
 		                            <table cellspacing="0" cellpadding="0">
 		                              <tbody>
 		                                <tr>
@@ -67,28 +66,50 @@
                             <s:label>
                               <s:param name="after"><strong><s:text name="or"/></strong></s:param>
                             </s:label>
-                            <s:file label="%{getText('add.m2.project.m2PomFile.label')}" name="m2PomFile">
-                                <s:param name="desc"><p><s:text name="add.m2.project.m2PomFile.message"/></p></s:param>
+                            <s:file label="%{getText('add.m2.project.m2PomFile.label')}" name="m2PomFile" size="100">
+                                <s:param name="after"><p><s:text name="add.m2.project.m2PomFile.message"/></p></s:param>
                             </s:file>
                             <c:choose>
                             <c:when test="${disableGroupSelection == true}">
                               <s:hidden name="selectedProjectGroup"/>
                               <s:hidden name="disableGroupSelection"/>
-                              <s:textfield label="%{getText('add.m2.project.projectGroup')}" name="projectGroupName" disabled="true"/>
+                              <s:textfield label="%{getText('add.m2.project.projectGroup')}" name="projectGroupName" disabled="true" size="100"/>
                             </c:when>
                             <c:otherwise>
                               <s:select label="%{getText('add.m2.project.projectGroup')}" name="selectedProjectGroup"
                                          list="projectGroups" listKey="id" listValue="name"/>
                             </c:otherwise>
                             </c:choose>
-                            <s:checkbox label="%{getText('add.m2.project.nonRecursiveProject')}" name="nonRecursiveProject" />
+                            
+                            <s:label>
+                              <s:param name="after">
+                                <table cellspacing="0" cellpadding="0">
+	                              <tbody>
+	                                <tr>
+	                                  <td><input name="checkoutOption" type="radio" value="checkoutInSeparateDirectories" checked /></td>
+                                      <td><s:text name="add.m2.project.checkoutInSeparateDirectories"/></td>
+	                                </tr>
+	                                <tr>
+	                                  <td><input name="checkoutOption" type="radio" value="checkoutInSingleDirectory"/></td>
+                                      <td><s:text name="add.m2.project.checkoutInSingleDirectory"/></td>
+	                                </tr>
+	                                <tr>
+	                                  <td><input name="checkoutOption" type="radio" value="nonRecursiveProject"/></td>
+                                      <td><s:text name="add.m2.project.nonRecursiveProject"/></td>
+	                                </tr>
+	                              </tbody>
+	                            </table>
+                              </s:param>
+                            </s:label>	 
+                            
                             <s:select label="%{getText('add.m2.project.buildDefinitionTemplate')}" name="buildDefinitionTemplateId"
                                        list="buildDefinitionTemplates" listKey="id" listValue="name" headerKey="-1" 
                                        headerValue="%{getText('add.m2.project.defaultBuildDefinition')}"/> 
                           </tbody>
                         </table>
                         <div class="functnbar3">
-                          <c1:submitcancel value="%{getText('add')}" cancel="%{getText('cancel')}"/>
+                          <s:submit value="%{getText('add')}" theme="simple"/>
+                          <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
                         </div>
                     </s:form>
                 </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/addProject.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/addProject.jsp
index e0feac9..77f61e7 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/addProject.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/addProject.jsp
@@ -18,7 +18,6 @@
   --%>
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
 <s:i18n name="localization.Continuum">
 <html>
@@ -54,35 +53,46 @@
                         </c:if>
                         <table>
                           <tbody>
-                            <s:textfield label="%{getText('projectName.label')}" name="projectName" required="true">
-                                <s:param name="desc"><p><s:text name="projectName.message"/></p></s:param>
+                            <s:textfield label="%{getText('projectName.label')}" name="projectName" requiredLabel="true" size="100">
+                                <s:param name="after"><p><s:text name="projectName.message"/></p></s:param>
                             </s:textfield>
-                            <s:textfield label="%{getText('projectVersion.label')}" name="projectVersion" required="true">
-                                <s:param name="desc"><p><s:text name="projectVersion.message"/></p></s:param>
+                            <s:textfield label="%{getText('projectDescription.label')}" name="projectDescription" size="100">
+                                <s:param name="after"><p><s:text name="projectDescription.message"/></p></s:param>
                             </s:textfield>
-                            <s:textfield label="%{getText('projectScmUrl.label')}" name="projectScmUrl" required="true">
-                                <s:param name="desc"><p><s:text name="projectScmUrl.message"/></p></s:param>
+                            <s:textfield label="%{getText('projectVersion.label')}" name="projectVersion" requiredLabel="true" size="100">
+                                <s:param name="after"><p><s:text name="projectVersion.message"/></p></s:param>
                             </s:textfield>
-                            <s:textfield label="%{getText('projectScmUsername.label')}" name="projectScmUsername">
-                                <s:param name="desc"><p><s:text name="projectScmUsername.message"/></p></s:param>
+                            <s:textfield label="%{getText('projectScmUrl.label')}" name="projectScmUrl" requiredLabel="true" size="100">
+                                <s:param name="after"><p><s:text name="projectScmUrl.message"/></p></s:param>
                             </s:textfield>
-                            <s:password label="%{getText('projectScmPassword.label')}" name="projectScmPassword">
-                                <s:param name="desc"><p><s:text name="projectScmPassword.message"/></p></s:param>
+                            <s:textfield label="%{getText('projectScmUsername.label')}" name="projectScmUsername" size="100">
+                                <s:param name="after"><p><s:text name="projectScmUsername.message"/></p></s:param>
+                            </s:textfield>
+                            <s:password label="%{getText('projectScmPassword.label')}" name="projectScmPassword" size="100">
+                                <s:param name="after"><p><s:text name="projectScmPassword.message"/></p></s:param>
                             </s:password>
-                            <s:textfield label="%{getText('projectScmTag.label')}" name="projectScmTag">
-                                <s:param name="desc"><p><s:text name="projectScmTag.message"/></p></s:param>
+                            <s:textfield label="%{getText('projectScmTag.label')}" name="projectScmTag" size="100">
+                                <s:param name="after"><p><s:text name="projectScmTag.message"/></p></s:param>
                             </s:textfield>
                             <s:checkbox label="%{getText('projectScmUseCache.label')}" name="projectScmUseCache"/>
                             <c:choose>
                             <c:when test="${disableGroupSelection == true}">
                               <s:hidden name="selectedProjectGroup"/>
                               <s:hidden name="disableGroupSelection"/>
-                              <s:textfield label="%{getText('projectGroup.name.label')}" name="projectGroupName" disabled="true"/>
+                              <s:textfield label="%{getText('projectGroup.name.label')}" name="projectGroupName" disabled="true" size="100"/>
                             </c:when>
                             <c:otherwise>
                               <s:select label="%{getText('projectGroup.name.label')}" name="selectedProjectGroup" list="projectGroups" listKey="id" listValue="name"/>
                             </c:otherwise>
                             </c:choose>
+                            <c:choose>
+                              <c:when test="${!empty projectGroups}">
+                                <s:hidden name="emptyProjectGroups" value="false"/>
+                              </c:when>
+                              <c:otherwise>
+                                <s:hidden name="emptyProjectGroups" value="true"/>
+                              </c:otherwise>
+                            </c:choose>
                             <s:select label="%{getText('add.project.buildDefinitionTemplate')}" name="buildDefinitionTemplateId"
                                        list="buildDefinitionTemplates" listKey="id" listValue="name" headerKey="-1" 
                                        headerValue="%{getText('add.project.defaultBuildDefinition')}"/>                             
@@ -90,7 +100,8 @@
                         </table>
                         <input type="hidden" name="projectType" value="<s:property value="projectType"/>">
                         <div class="functnbar3">
-                          <c1:submitcancel value="%{getText('add')}" cancel="%{getText('cancel')}"/>
+                          <s:submit value="%{getText('add')}" theme="simple"/>
+                          <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
                         </div>
                     </s:form>
                 </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/appearance.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/appearance.jsp
index 827e2f9..3df2030 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/appearance.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/appearance.jsp
@@ -19,12 +19,10 @@
 
 <%@ taglib prefix="s" uri="/struts-tags" %>
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <html>
 <s:i18n name="localization.Continuum">
 <head>
   <title><s:text name="appearance.page.title"/></title>
-  <s:head/>
 </head>
 
 <body>
@@ -72,29 +70,37 @@
       <table>
         <tr>
           <th><s:text name="appearance.companyPom.organizationName.label"/></th>
-          <td>${companyModel.organization.name}</td>
+          <td><c:out value="${companyModel.organization.name}"/></td>
         </tr>
         <tr>
           <th><s:text name="appearance.companyPom.organizationUrl.label"/></th>
-          <td><a href="${companyModel.organization.url}" target="_blank">
-            <code>${companyModel.organization.url}</code>
+          <c:set var="companyOrgUrl"><c:out value="${companyModel.organization.url}"/></c:set>
+          <td><a href="${companyOrgUrl}" target="_blank">
+            <code><c:out value="${companyModel.organization.url}"/></code>
           </a></td>
         </tr>
         <tr>
           <th><s:text name="appearance.companyPom.organizationLogoUrl.label"/></th>
           <td>
-            <code>${companyModel.properties['organization.logo']}</code>
+            <code><c:out value="${companyModel.properties['organization.logo']}"/></code>
           </td>
         </tr>
       </table>
     </c:when>
     <c:otherwise>
-      <s:text name="appearance.companyPomDoesNotExist"><s:param>${companyPom.groupId}:${companyPom.artifactId}</s:param></s:text>
+      <s:text name="appearance.companyPomDoesNotExist">
+        <s:param>
+          <c:out value="${companyPom.groupId}"/>:<c:out value="${companyPom.artifactId}"/>
+        </s:param>
+      </s:text>
       <a href="<s:url action='editCompanyPom' />"><s:text name="appearance.createCompanyPom"/></a>
     </c:otherwise>
   </c:choose>
 </c:if>
-<s:form action="saveFooter!saveFooter.action" method="get" namespace="/admin">
+
+<s:actionmessage/>
+<s:form action="saveFooter.action" method="post" namespace="/admin">
+  <s:token/>
   <div id="axial" class="h3">
     <h3><s:text name="appearance.footerContent"/></h3>
     <div class="axial">
@@ -104,7 +110,8 @@
         </tbody>
       </table>
       <div class="functnbar3">
-        <c1:submitcancel value="%{getText('save')}" cancel="%{getText('cancel')}"/>
+        <s:submit value="%{getText('save')}" theme="simple"/>
+        <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
       </div>      
     </div>
   </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/buildAgentsList.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/buildAgentsList.jsp
index 6abd19d..27e650e 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/buildAgentsList.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/buildAgentsList.jsp
@@ -31,13 +31,14 @@
         <c:if test="${!empty actionErrors}">
           <div class="errormessage">
             <s:iterator value="actionErrors">
-              <p><s:text name="<s:property/>" /></p>
+              <p><s:property/></p>
             </s:iterator>
           </div>
         </c:if>
         <s:set name="buildAgents" value="buildAgents" scope="request"/>
         <ec:table items="buildAgents"
                   var="buildAgent"
+                  autoIncludeParameters="false"
                   showExports="false"
                   showPagination="false"
                   showStatusBar="false"
@@ -46,23 +47,26 @@
           <ec:row>
             <ec:column property="url" title="buildAgents.table.url">
               <s:url id="viewBuildAgentUrl" action="viewBuildAgent">
-                <s:param name="buildAgent.url">${pageScope.buildAgent.url}</s:param>
+                <s:param name="buildAgent.url"><c:out value="${pageScope.buildAgent.url}"/></s:param>
               </s:url>
-              <s:a href="%{viewBuildAgentUrl}">${pageScope.buildAgent.url}</s:a>
+              <s:a href="%{viewBuildAgentUrl}"><c:out value="${pageScope.buildAgent.url}"/></s:a>
             </ec:column>
             <ec:column property="enabled" title="buildAgents.table.enabled"/>
             <ec:column property="description" title="buildAgents.table.description"/>
             <ec:column property="editActions" title="&nbsp;" width="1%">
               <s:url id="editBuildAgentUrl" action="editBuildAgent">
-                <s:param name="buildAgent.url">${pageScope.buildAgent.url}</s:param>
+                <s:param name="buildAgent.url"><c:out value="${pageScope.buildAgent.url}"/></s:param>
               </s:url>
               <s:a href="%{editBuildAgentUrl}">
                 <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:token/>
               <s:url id="removeBuildAgentUrl" action="deleteBuildAgent">
-                <s:param name="buildAgent.url">${pageScope.buildAgent.url}</s:param>
+                <s:param name="buildAgent.url"><c:out value="${pageScope.buildAgent.url}"/></s:param>
+                <s:param name="struts.token.name">token</s:param>
+                <s:param name="token"><s:property value="token"/></s:param>
               </s:url>
               <s:a href="%{removeBuildAgentUrl}">
                 <img src="<s:url value='/images/delete.gif' includeParams="none"/>" alt="<s:text name='delete'/>" title="<s:text name='delete'/>" border="0"/>
@@ -73,9 +77,58 @@
       </div>
       <div class="functnbar3">
         <s:form name="addBuildAgent" action="editBuildAgent" method="post">
-          <s:submit value="%{getText('add')}"/>
+          <s:submit value="%{getText('add')}" theme="simple"/>
+        </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"
+                  autoIncludeParameters="false"
+                  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"><c:out value="${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:token/>
+              <s:url id="removeBuildAgentGroupUrl" action="deleteBuildAgentGroup">
+                <s:param name="buildAgentGroup.name"><c:out value="${pageScope.buildAgentGroup.name}"/></s:param>
+                <s:param name="struts.token.name">token</s:param>
+                <s:param name="token"><s:property value="token"/></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')}" theme="simple"/>
         </s:form>
       </div>
     </body>
   </s:i18n>
-</html>
\ No newline at end of file
+</html>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/buildDefinitionTemplateSummary.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/buildDefinitionTemplateSummary.jsp
index 5accb51..f245445 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/buildDefinitionTemplateSummary.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/buildDefinitionTemplateSummary.jsp
@@ -19,7 +19,6 @@
 
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <%@ taglib uri="http://www.extremecomponents.org" prefix="ec" %>
 
 <html>
@@ -36,6 +35,7 @@
       </h3>
       <ec:table items="templates"
                 var="template"
+                autoIncludeParameters="false"
                 showExports="false"
                 showPagination="false"
                 showStatusBar="false"
@@ -44,8 +44,8 @@
         <ec:row>
           <ec:column property="name" title="buildDefinition.template.name"/>
           <ec:column property="editAction" title="&nbsp;" width="1%">
-            <s:url id="editUrl" action="editBuildDefinitionTemplate" method="edit" namespace="/">
-              <s:param name="buildDefinitionTemplate.id">${pageScope.template.id}</s:param>
+            <s:url id="editUrl" action="editBuildDefinitionTemplate" namespace="/">
+              <s:param name="buildDefinitionTemplate.id"><c:out value="${pageScope.template.id}"/></s:param>
             </s:url>
             <s:a href="%{editUrl}"><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>  
@@ -55,9 +55,13 @@
             <c:when test="${template.continuumDefault == true}">
               <img src="<s:url value='/images/delete_disabled.gif' includeParams="none"/>" alt="<s:text name='disabled'/>" title="<s:text name='disabled'/>" border="0" />
             </c:when>
-            <c:otherwise>${template.continuumDefault}
-              <s:url id="deleteUrl" action="deleteDefinitionTemplate" method="delete" namespace="/">
-                <s:param name="buildDefinitionTemplate.id">${pageScope.template.id}</s:param>
+            <c:otherwise>
+              <s:token/>
+              <s:url id="deleteUrl" action="deleteDefinitionTemplate" namespace="/">
+                <s:param name="buildDefinitionTemplate.id"><c:out value="${pageScope.template.id}"/></s:param>
+                <s:param name="buildDefinitionTemplate.name"><c:out value="${pageScope.template.name}"/></s:param>
+                <s:param name="struts.token.name">token</s:param>
+                <s:param name="token"><s:property value="token"/></s:param>
               </s:url>
               <s:a href="%{deleteUrl}"><img src="<s:url value='/images/delete.gif' includeParams="none"/>" alt="<s:text name='delete'/>" title="<s:text name='delete'/>" border="0"></s:a>
             </c:otherwise>
@@ -66,8 +70,8 @@
         </ec:row>  
       </ec:table> 
       <div class="functnbar3">
-        <s:form action="buildDefinitionTemplate!input.action" method="post">
-          <s:submit value="%{getText('add')}"/>
+        <s:form action="buildDefinitionTemplate.action" method="post">
+          <s:submit value="%{getText('add')}" theme="simple"/>
         </s:form>
       </div>      
       <h3>
@@ -75,6 +79,7 @@
       </h3>
       <ec:table items="buildDefinitionSummaries"
                 var="buildDefinitionSummary"
+                autoIncludeParameters="false"
                 showExports="false"
                 showPagination="false"
                 showStatusBar="false"
@@ -92,8 +97,8 @@
           <ec:column property="description" title="buildDefinition.template.buildDefinition.description"/>
           <ec:column property="type" title="buildDefinition.template.buildDefinition.type"/>
           <ec:column property="editAction" title="&nbsp;" width="1%">
-            <s:url id="editUrl" action="editBuildDefinitionAsTemplate" method="editBuildDefinition" namespace="/">
-              <s:param name="buildDefinition.id">${pageScope.buildDefinitionSummary.id}</s:param>
+            <s:url id="editUrl" action="editBuildDefinitionAsTemplate" namespace="/">
+              <s:param name="buildDefinition.id"><c:out value="${pageScope.buildDefinitionSummary.id}"/></s:param>
             </s:url>
             <s:a href="%{editUrl}"><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>          
@@ -103,8 +108,9 @@
               <img src="<s:url value='/images/delete_disabled.gif' includeParams="none"/>" alt="<s:text name='disabled'/>" title="<s:text name='disabled'/>" border="0" />
             </c:when>
             <c:otherwise>
-              <s:url id="deleteUrl" action="deleteBuildDefinitionAsTemplate" method="deleteBuildDefinition" namespace="/">
-                <s:param name="buildDefinition.id">${pageScope.buildDefinitionSummary.id}</s:param>
+              <s:url id="deleteUrl" action="deleteBuildDefinitionAsTemplate" namespace="/">
+                <s:param name="buildDefinition.id"><c:out value="${pageScope.buildDefinitionSummary.id}"/></s:param>
+                <s:param name="buildDefinition.description"><c:out value="${pageScope.buildDefinitionSummary.description}"/></s:param>
               </s:url>
               <s:a href="%{deleteUrl}"><img src="<s:url value='/images/delete.gif' includeParams="none"/>" alt="<s:text name='delete'/>" title="<s:text name='delete'/>" border="0"></s:a>
             </c:otherwise>
@@ -114,8 +120,8 @@
       </ec:table>      
       
       <div class="functnbar3">
-        <s:form action="buildDefinitionAsTemplate!inputBuildDefinition.action" method="post">
-          <s:submit value="%{getText('add')}"/>
+        <s:form action="buildDefinitionAsTemplate_input.action" method="post">
+          <s:submit value="%{getText('add')}" theme="simple"/>
         </s:form>
       </div>           
       
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/buildQueueView.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/buildQueueView.jsp
index aeb9154..1753d2a 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/buildQueueView.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/buildQueueView.jsp
@@ -19,7 +19,6 @@
 
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <%@ taglib uri="http://www.extremecomponents.org" prefix="ec" %>
 <%@ taglib uri="http://plexus.codehaus.org/redback/taglib-1.0" prefix="redback" %>
 
@@ -30,178 +29,108 @@
       <meta http-equiv="refresh" content="60"/>
     </head>
     <body>
-      <s:form id="removeForm" action="none" method="post">
+      
         <div id="h3">
           <h3>
             <s:text name="buildQueue.currentTask.section.title"/>
-          </h3>  
-          <table width="100%">
-            <s:if test="%{currentBuildProjectTask != null}">
-            <tbody>
-              <tr>
-                <th><s:text name="buildQueue.currentTask.projectName"/></th>
-                <th><s:text name="buildQueue.currentTask.buildDefinition"/></th>
-                <th>&nbsp;</th>
-              </tr>
-              <tr>
-                <td width="50%"><s:property value="currentBuildProjectTask.projectName"/></td>
-                <td width="49%"><s:property value="currentBuildProjectTask.buildDefinitionLabel"/></td>
-                <td width="1%">
-                <redback:ifAuthorized permission="continuum-manage-queues">
-                  <s:url id="cancelUrl" action="cancelCurrentBuildTask" method="cancelCurrent" namespace="/">
-                    <s:param name="projectId"><s:property value="currentBuildProjectTask.projectId"/></s:param>
+          </h3>
+          <c:if test="${not empty currentBuildProjectTasks}">
+            <s:set name="currentBuildProjectTasks" value="currentBuildProjectTasks" scope="request"/>
+            <ec:table items="currentBuildProjectTasks"
+                      autoIncludeParameters="false"
+                      var="queue"
+                      showExports="false"
+                      showPagination="false"
+                      showStatusBar="false"
+                      sortable="false"
+                      filterable="false">
+              <ec:row>
+                <ec:column property="name" title="buildQueue.currentTask.buildQueue" width="29%"/>
+                <ec:column property="projectUrl" title="buildQueue.currentTask.projectName" width="50%">
+                  <s:url id="viewUrl" action="buildResults">
+                    <s:param name="projectId"><c:out value="${queue.task.projectId}"/></s:param>
                   </s:url>
-                  <s:a href="%{cancelUrl}"><img src="<s:url value='/images/cancelbuild.gif' includeParams="none"/>" alt="<s:text name='cancel'/>" title="<s:text name='cancel'/>" border="0"></s:a>
-                </redback:ifAuthorized>
-                <redback:elseAuthorized>
-                  <img src="<s:url value='/images/cancelbuild_disabled.gif' includeParams="none"/>" alt="<s:text name='cancel'/>" title="<s:text name='cancel'/>" border="0">
-                </redback:elseAuthorized>
-                </td>
-              </tr>
-            </tbody>
-            </s:if>
-            <s:else>
-              <s:text name="buildQueue.no.currentTaks" />
-            </s:else>
-          </table>
-        </div>    
-        <div id="h3">
-          <h3>
-            <s:text name="buildQueue.section.title"/>
-          </h3>  
-            <c:if test="${not empty buildProjectTasks}">
-              <ec:table items="buildProjectTasks"
-                        var="buildProjectTask"
-                        showExports="false"
-                        showPagination="false"
-                        showStatusBar="false"
-                        sortable="false"
-                        filterable="false">
-                <ec:row highlightRow="true">
+                  <s:a href="%{viewUrl}"><c:out value="${queue.task.projectName}"/></s:a>
+                </ec:column>
+                <ec:column property="task.buildDefinitionLabel" title="buildQueue.currentTask.buildDefinition" width="19%"/>
+                <ec:column property="cancelAction" title="&nbsp;" width="1%">
                   <redback:ifAuthorized permission="continuum-manage-queues">
-                  <ec:column alias="selectedBuildTaskHashCodes" title="&nbsp;" style="width:5px" filterable="false" sortable="false" width="1%" headerCell="selectAll">
-                    <input type="checkbox" name="selectedBuildTaskHashCodes" value="${buildProjectTask.hashCode}" />
-                  </ec:column>              
-                  </redback:ifAuthorized>
-                  <ec:column property="projectName" title="buildQueue.currentTask.projectName" style="white-space: nowrap" width="49%"/>
-                  <ec:column property="buildDefinitionLabel" title="buildQueue.currentTask.buildDefinition" style="white-space: nowrap" width="49%"/>
-                  <ec:column property="cancelEntry" title="&nbsp;" width="1%">
-                    <redback:ifAuthorized permission="continuum-manage-queues">
-                    <s:url id="cancelUrl" action="removeBuildQueueEntry" method="remove" namespace="/">
-                      <s:param name="projectId">${pageScope.buildProjectTask.projectId}</s:param>
-                      <s:param name="buildDefinitionId">${pageScope.buildProjectTask.buildDefinitionId}</s:param>
-                      <s:param name="trigger">${pageScope.buildProjectTask.trigger}</s:param>
-                      <s:param name="projectName">${pageScope.buildProjectTask.projectName}</s:param>
-                    </s:url>
-                    <s:a href="%{cancelUrl}"><img src="<s:url value='/images/cancelbuild.gif' includeParams="none"/>" alt="<s:text name='cancel'/>" title="<s:text name='cancel'/>" border="0"></s:a>
-                    </redback:ifAuthorized>
-                    <redback:elseAuthorized>
-                      <img src="<s:url value='/images/cancelbuild_disabled.gif' includeParams="none"/>" alt="<s:text name='cancel'/>" title="<s:text name='cancel'/>" border="0">
-                    </redback:elseAuthorized>    
-                  </ec:column>             
-                </ec:row>
-              </ec:table>
-            </c:if>
-            <c:if test="${empty buildProjectTasks}">
-              <s:text name="buildQueue.empty"/>
-            </c:if>
-        </div>
-        <c:if test="${not empty buildProjectTasks}">
-          <div class="functnbar3">
-            <table>
-              <tbody>
-                <tr>
-                  <td>
-                    <input type="submit" value="<s:text name="buildQueue.removeEntries"/>"
-                           onclick="$('removeForm').action='removeBuildQueueEntries!removeBuildEntries.action';$('removeForm').submit();" /> 
-                  </td>
-                </tr>
-              </tbody>
-            </table>
-          </div>
-        </c:if>
-        
-        
-        <!-- checkout queue -->
-        <div id="h3">
-          <h3>
-            <s:text name="checkoutQueue.currentTask.section.title"/>
-          </h3>  
-          <table width="100%">
-            <s:if test="%{currentCheckOutTask != null}">
-            <tbody>
-              <tr>
-                <th><s:text name="checkoutQueue.currentTask.projectName"/></th>
-                <th>&nbsp;</th>
-              </tr>
-              <tr>
-                <td width="99%"><s:property value="currentCheckOutTask.projectName"/></td>
-                <td width="1%">
-                <redback:ifAuthorized permission="continuum-manage-queues">
-                  <s:url id="cancelUrl" action="cancelCurrentQueueTask" method="cancelCurrentCheckout" namespace="/">
-                    <s:param name="projectId"><s:property value="currentCheckOutTask.projectId"/></s:param>
-                  </s:url>
-                  <s:a href="%{cancelUrl}"><img src="<s:url value='/images/cancelbuild.gif' includeParams="none"/>" alt="<s:text name='cancel'/>" title="<s:text name='cancel'/>" border="0"></s:a>
-                </redback:ifAuthorized>
-                <redback:elseAuthorized>
-                  <img src="<s:url value='/images/cancelbuild_disabled.gif' includeParams="none"/>" alt="<s:text name='cancel'/>" title="<s:text name='cancel'/>" border="0">
-                </redback:elseAuthorized>              
-                </td>
-              </tr>
-            </tbody>
-            </s:if>
-            <s:else>
-              <s:text name="checkoutQueue.no.currentTaks" />
-            </s:else>
-          </table>
-        </div>    
-        <div id="h3">
-          <h3>
-            <s:text name="checkoutQueue.section.title"/>
-          </h3>  
-            <c:if test="${!empty currentCheckOutTasks}">
-              <ec:table items="currentCheckOutTasks"
-                        var="currentCheckOutTask"
-                        showExports="false"
-                        showPagination="false"
-                        showStatusBar="false"
-                        sortable="false"
-                        filterable="false">
-                <ec:row highlightRow="true">
-                  <redback:ifAuthorized permission="continuum-manage-queues">
-                  <ec:column alias="selectedCheckOutTaskHashCodes" title="&nbsp;" style="width:5px" filterable="false" sortable="false" width="1%" headerCell="selectAll">
-                    <input type="checkbox" name="selectedCheckOutTaskHashCodes" value="${currentCheckOutTask.hashCode}" />
-                  </ec:column>              
-                  </redback:ifAuthorized>
-                  <ec:column property="projectName" title="Project Name" style="white-space: nowrap" width="98%"/>
-                  <ec:column property="cancelEntry" title="&nbsp;" width="1%">
-                  <redback:ifAuthorized permission="continuum-manage-queues">
-                    <s:url id="cancelUrl" action="removeCheckoutQueueEntry" method="removeCheckout">
-                      <s:param name="projectId">${pageScope.currentCheckOutTask.projectId}</s:param>
+                    <s:url id="cancelUrl" action="cancelCurrentBuildTask" namespace="/">
+                      <s:param name="projectId"><c:out value="${queue.task.projectId}"/></s:param>
                     </s:url>
                     <s:a href="%{cancelUrl}"><img src="<s:url value='/images/cancelbuild.gif' includeParams="none"/>" alt="<s:text name='cancel'/>" title="<s:text name='cancel'/>" border="0"></s:a>
                   </redback:ifAuthorized>
                   <redback:elseAuthorized>
                     <img src="<s:url value='/images/cancelbuild_disabled.gif' includeParams="none"/>" alt="<s:text name='cancel'/>" title="<s:text name='cancel'/>" border="0">
-                  </redback:elseAuthorized>    
-                  </ec:column>             
-                </ec:row>
-              </ec:table>
-            </c:if>
-            <c:if test="${empty currentCheckOutTasks}">
-              <s:text name="checkoutQueue.empty"/>
-            </c:if>
+                  </redback:elseAuthorized>
+                </ec:column>
+              </ec:row>
+            </ec:table>
+          </c:if>
+          <c:if test="${empty currentBuildProjectTasks}">
+            <s:text name="buildQueue.no.currentTaks" />
+          </c:if>
         </div>
-        <c:if test="${not empty currentCheckOutTasks}">
+      
+      
+      <s:form id="removeBuildForm" action="removeBuildQueueEntries.action" method="post" theme="simple">
+        <div id="h3">
+          <h3>
+            <s:text name="buildQueue.section.title"/>
+          </h3>
+          <c:if test="${not empty buildsInQueue}">
+            <s:set name="buildsInQueue" value="buildsInQueue" scope="request"/>
+            <ec:table items="buildsInQueue"
+                      var="queue"
+                      autoIncludeParameters="false"
+                      showExports="false"
+                      showPagination="false"
+                      showStatusBar="false"
+                      sortable="false"
+                      filterable="false">
+              <ec:row>
+                <redback:ifAuthorized permission="continuum-manage-queues">
+                  <ec:column alias="selectedBuildTaskHashCodes" title=" " style="width:5px" filterable="false" sortable="false" headerCell="selectAll">
+                    <input type="checkbox" name="selectedBuildTaskHashCodes" value="${queue.task.hashCode}" />
+                  </ec:column>
+                </redback:ifAuthorized>
+                <ec:column property="name" title="buildQueue.currentTask.buildQueue" width="29%"/>
+                <ec:column property="projectUrl" title="buildQueue.currentTask.projectName" width="50%">
+                  <s:url id="viewUrl" action="buildResults">
+                    <s:param name="projectId"><c:out value="${queue.task.projectId}"/></s:param>
+                  </s:url>
+                  <s:a href="%{viewUrl}"><c:out value="${queue.task.projectName}"/></s:a>
+                </ec:column>
+                <ec:column property="task.buildDefinitionLabel" title="buildQueue.currentTask.buildDefinition" width="19%"/>
+                <ec:column property="cancelAction" title="&nbsp;" width="1%">
+                  <redback:ifAuthorized permission="continuum-manage-queues">
+                    <s:url id="cancelUrl" action="removeBuildQueueEntry" namespace="/">
+                      <s:param name="projectId"><c:out value="${queue.task.projectId}"/></s:param>
+                      <s:param name="buildDefinitionId"><c:out value="${queue.task.buildDefinitionId}"/></s:param>
+                      <s:param name="trigger"><c:out value="${queue.task.buildTrigger.trigger}"/></s:param>
+                      <s:param name="projectName"><c:out value="${queue.task.projectName}"/></s:param>
+                      <s:param name="projectGroupId"><c:out value="${queue.task.projectGroupId}"/></s:param>
+                    </s:url>
+                    <s:a href="%{cancelUrl}"><img src="<s:url value='/images/cancelbuild.gif' includeParams="none"/>" alt="<s:text name='cancel'/>" title="<s:text name='cancel'/>" border="0"></s:a>
+                  </redback:ifAuthorized>
+                  <redback:elseAuthorized>
+                    <img src="<s:url value='/images/cancelbuild_disabled.gif' includeParams="none"/>" alt="<s:text name='cancel'/>" title="<s:text name='cancel'/>" border="0">
+                  </redback:elseAuthorized>
+                </ec:column>
+              </ec:row>
+            </ec:table>
+          </c:if>
+          <c:if test="${empty buildsInQueue}">
+            <s:text name="buildQueue.empty"/>
+          </c:if>
+        </div>
+        <c:if test="${not empty buildsInQueue}">
           <div class="functnbar3">
             <table>
               <tbody>
                 <tr>
                   <td>
-                    <redback:ifAuthorized permission="continuum-manage-queues">
-                    <input type="submit" value="<s:text name="checkoutQueue.removeEntries"/>"
-                           onclick="$('removeForm').action='removeCheckoutQueueEntries!removeCheckoutEntries.action';$('removeForm').submit();" />
-                    </redback:ifAuthorized>
+                    <input type="button" value="<s:text name="buildQueue.removeEntries"/>" onclick="document.forms.removeBuildForm.submit();" />
                   </td>
                 </tr>
               </tbody>
@@ -209,6 +138,207 @@
           </div>
         </c:if>
       </s:form>
+
+      
+        <%-- checkout queue --%>
+        <div id="h3">
+          <h3>
+            <s:text name="checkoutQueue.currentTask.section.title"/>
+          </h3>
+          <c:if test="${not empty currentCheckoutTasks}">
+            <s:set name="currentCheckoutTasks" value="currentCheckoutTasks" scope="request"/>
+            <ec:table items="currentCheckoutTasks"
+                      var="queue"
+                      autoIncludeParameters="false"
+                      showExports="false"
+                      showPagination="false"
+                      showStatusBar="false"
+                      sortable="false"
+                      filterable="false">
+              <ec:row>
+                <ec:column property="name" title="checkoutQueue.currentTask.buildQueue" width="29%"/>
+                <ec:column property="projectUrl" title="checkoutQueue.currentTask.projectName" width="69%">
+                  <s:url id="viewUrl" action="projectView">
+                    <s:param name="projectId"><c:out value="${queue.task.projectId}"/></s:param>
+                  </s:url>
+                  <s:a href="%{viewUrl}"><c:out value="${queue.task.projectName}"/></s:a>
+                </ec:column>
+                <ec:column property="cancelAction" title="&nbsp;" width="1%">
+                  <redback:ifAuthorized permission="continuum-manage-queues">
+                    <s:url id="cancelUrl" action="cancelCurrentQueueTask" namespace="/">
+                      <s:param name="projectId"><c:out value="${queue.task.projectId}"/></s:param>
+                    </s:url>
+                    <s:a href="%{cancelUrl}"><img src="<s:url value='/images/cancelbuild.gif' includeParams="none"/>" alt="<s:text name='cancel'/>" title="<s:text name='cancel'/>" border="0"></s:a>
+                  </redback:ifAuthorized>
+                  <redback:elseAuthorized>
+                    <img src="<s:url value='/images/cancelbuild_disabled.gif' includeParams="none"/>" alt="<s:text name='cancel'/>" title="<s:text name='cancel'/>" border="0">
+                  </redback:elseAuthorized>
+                </ec:column>
+              </ec:row>
+            </ec:table>
+          </c:if>
+          <c:if test="${empty currentCheckoutTasks}">
+            <s:text name="checkoutQueue.no.currentTaks" />
+          </c:if>
+        </div>
+      
+        
+      <s:form id="removeCheckoutForm" action="removeCheckoutQueueEntries.action" method="post" theme="simple">
+        <div id="h3">
+          <h3>
+            <s:text name="checkoutQueue.section.title"/>
+          </h3>
+          <c:if test="${not empty checkoutsInQueue}">
+            <s:set name="checkoutsInQueue" value="checkoutsInQueue" scope="request"/>
+            <ec:table items="checkoutsInQueue"
+                      var="queue"
+                      autoIncludeParameters="false"
+                      showExports="false"
+                      showPagination="false"
+                      showStatusBar="false"
+                      sortable="false"
+                      filterable="false">
+              <ec:row>
+                <redback:ifAuthorized permission="continuum-manage-queues">
+                  <ec:column alias="selectedCheckOutTaskHashCodes" title=" " style="width:5px" filterable="false" sortable="false" headerCell="selectAll">
+                    <input type="checkbox" name="selectedCheckOutTaskHashCodes" value="${queue.task.hashCode}" />
+                  </ec:column>
+                </redback:ifAuthorized>
+                <ec:column property="name" title="checkoutQueue.currentTask.buildQueue" width="29%"/>
+                <ec:column property="projectUrl" title="checkoutQueue.currentTask.projectName" width="69%">
+                  <s:url id="viewUrl" action="projectView">
+                    <s:param name="projectId"><c:out value="${queue.task.projectId}"/></s:param>
+                  </s:url>
+                  <s:a href="%{viewUrl}"><c:out value="${queue.task.projectName}"/></s:a>
+                </ec:column>
+                <ec:column property="cancelAction" title="&nbsp;" width="1%">
+                  <redback:ifAuthorized permission="continuum-manage-queues">
+                    <s:url id="cancelUrl" action="removeCheckoutQueueEntry" namespace="/">
+                      <s:param name="projectId"><c:out value="${queue.task.projectId}"/></s:param>
+                    </s:url>
+                    <s:a href="%{cancelUrl}"><img src="<s:url value='/images/cancelbuild.gif' includeParams="none"/>" alt="<s:text name='cancel'/>" title="<s:text name='cancel'/>" border="0"></s:a>
+                  </redback:ifAuthorized>
+                  <redback:elseAuthorized>
+                    <img src="<s:url value='/images/cancelbuild_disabled.gif' includeParams="none"/>" alt="<s:text name='cancel'/>" title="<s:text name='cancel'/>" border="0">
+                  </redback:elseAuthorized>
+                </ec:column>
+              </ec:row>
+            </ec:table>
+          </c:if>
+          <c:if test="${empty checkoutsInQueue}">
+            <s:text name="checkoutQueue.empty" />
+          </c:if>
+        </div>
+        <c:if test="${not empty checkoutsInQueue}">
+          <div class="functnbar3">
+            <table>
+              <tbody>
+                <tr>
+                  <td>
+                    <redback:ifAuthorized permission="continuum-manage-queues">
+                    <input type="submit" value="<s:text name="checkoutQueue.removeEntries"/>" onclick="document.forms.removeCheckoutForm.submit();" />
+                    </redback:ifAuthorized>
+                  </td>
+                </tr>
+              </tbody>
+            </table>
+          </div>
+        </c:if>          
+      </s:form>
+
+      
+      	<div id="h3">
+          <h3><s:text name="prepareBuildQueue.currentTask.section.title"/></h3>
+          <c:if test="${not empty currentPrepareBuilds}">
+            <s:set name="currentPrepareBuilds" value="currentPrepareBuilds" scope="request"/>
+            <ec:table items="currentPrepareBuilds"
+                      var="currentPrepareBuild"
+                      autoIncludeParameters="false"
+                      showExports="false"
+                      showPagination="false"
+                      showStatusBar="false"
+                      sortable="false"
+                      filterable="false">
+              <ec:row>
+                <ec:column property="queueName" title="prepareBuildQueue.currentTask.buildQueue" width="29%"/>
+                <ec:column property="projectGroupUrl" title="prepareBuildQueue.table.projectGroupName">
+                  <s:url id="viewUrl" action="projectGroupSummary">
+                    <s:param name="projectGroupId"><c:out value="${pageScope.currentPrepareBuild.projectGroupId}"/></s:param>
+                  </s:url>
+                  <s:a href="%{viewUrl}"><c:out value="${pageScope.currentPrepareBuild.projectGroupName}"/></s:a>
+                </ec:column>
+                <ec:column property="scmRootAddress" title="prepareBuildQueue.table.scmRootAddress"/>
+              </ec:row>
+            </ec:table>
+          </c:if>
+          <c:if test="${empty currentPrepareBuilds}">
+            <s:text name="prepareBuildQueue.no.currentTasks"/>
+          </c:if>
+        </div>
+      
+       
+      <s:form id="removePrepareBuildForm" action="removePrepareBuildEntries.action" method="post" theme="simple">
+        <div id="h3">
+          <h3>
+            <s:text name="prepareBuildQueue.section.title"/>
+          </h3>
+          <c:if test="${not empty prepareBuildQueues}">
+            <s:set name="prepareBuildQueues" value="prepareBuildQueues" scope="request"/>
+            <ec:table items="prepareBuildQueues"
+                      var="prepareBuildQueue"
+                      autoIncludeParameters="false"
+                      showExports="false"
+                      showPagination="false"
+                      showStatusBar="false"
+                      sortable="false"
+                      filterable="false">
+              <ec:row>
+                <redback:ifAuthorized permission="continuum-manage-queues">
+                  <ec:column alias="selectedPrepareBuildTaskHashCodes" title="&nbsp;" style="width:5px" filterable="false" sortable="false" width="1%" headerCell="selectAll">
+                    <input type="checkbox" name="selectedPrepareBuildTaskHashCodes" value="${pageScope.prepareBuildQueue.hashCode}" />
+                  </ec:column>             
+                </redback:ifAuthorized>
+                <ec:column property="queueName" title="prepareBuildQueue.currentTask.buildQueue" width="29%"/>
+                <ec:column property="projectGroupUrl" title="prepareBuildQueue.table.projectGroupName">
+                  <s:url id="viewUrl" action="projectGroupSummary">
+                    <s:param name="projectGroupId"><c:out value="${pageScope.prepareBuildQueue.projectGroupId}"/></s:param>
+                  </s:url>
+                  <s:a href="%{viewUrl}"><c:out value="${pageScope.prepareBuildQueue.projectGroupName}"/></s:a>
+                </ec:column>
+                <ec:column property="scmRootAddress" title="prepareBuildQueue.table.scmRootAddress"/>
+                <ec:column property="cancelEntry" title="&nbsp;" width="1%">
+                  <redback:ifAuthorized permission="continuum-manage-queues">
+                    <s:url id="cancelUrl" action="removePrepareBuildEntry" namespace="/">
+                      <s:param name="projectGroupId"><c:out value="${pageScope.prepareBuildQueue.projectGroupId}"/></s:param>
+                      <s:param name="scmRootId"><c:out value="${pageScope.prepareBuildQueue.scmRootId}"/></s:param>
+                    </s:url>
+                    <s:a href="%{cancelUrl}"><img src="<s:url value='/images/cancelbuild.gif' includeParams="none"/>" alt="<s:text name='cancel'/>" title="<s:text name='cancel'/>" border="0"></s:a>
+                  </redback:ifAuthorized>
+                  <redback:elseAuthorized>
+                    <img src="<s:url value='/images/cancelbuild_disabled.gif' includeParams="none"/>" alt="<s:text name='cancel'/>" title="<s:text name='cancel'/>" border="0">
+                  </redback:elseAuthorized>
+                </ec:column>
+              </ec:row>
+            </ec:table>
+          </c:if>
+        </div>
+        <c:if test="${not empty prepareBuildQueues}">
+          <div class="functnbar3">
+            <table>
+              <tbody>
+                <tr>
+                  <td>
+                    <input type="button" name="remove-prepare-build-queues" value="<s:text name="prepareBuildQueue.removeEntries"/>" onclick="document.forms.removePrepareBuildForm.submit();" /> 
+                  </td>
+                </tr>
+              </tbody>
+            </table>
+          </div>
+        </c:if>
+        <c:if test="${empty prepareBuildQueues}">
+          <s:text name="prepareBuildQueue.empty"/>
+        </c:if>
+      </s:form>
     </body>
   </s:i18n>
-</html>
\ No newline at end of file
+</html>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/configuration.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/configuration.jsp
index f73c052..08838f5 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/configuration.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/configuration.jsp
@@ -18,7 +18,6 @@
   --%>
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <html>
 <s:i18n name="localization.Continuum">
   <head>
@@ -34,16 +33,37 @@
 
     <div class="axial">
       <table border="1" cellspacing="2" cellpadding="3" width="100%">
-        <c1:data label="%{getText('configuration.workingDirectory.label')}" name="workingDirectory"/>
-        <c1:data label="%{getText('configuration.buildOutputDirectory.label')}" name="buildOutputDirectory"/>
-        <c1:data label="%{getText('configuration.releaseOutputDirectory.label')}" name="releaseOutputDirectory"/>
-        <c1:data label="%{getText('configuration.deploymentRepositoryDirectory.label')}"
-                 name="deploymentRepositoryDirectory"/>
-        <c1:data label="%{getText('configuration.baseUrl.label')}" name="baseUrl"/>
-        <c1:data label="%{getText('configuration.distributedBuildEnabled.label')}" name="distributedBuildEnabled"/>
+        <tr class="b">
+          <th><label class="label"><s:text name='configuration.workingDirectory.label'/>:</label></th>
+          <td><s:property value="workingDirectory"/></td>
+        </tr>
+        <tr class="b">
+          <th><label class="label"><s:text name='configuration.buildOutputDirectory.label'/>:</label></th>
+          <td><s:property value="buildOutputDirectory"/></td>
+        </tr>
+        <tr class="b">
+          <th><label class="label"><s:text name='configuration.releaseOutputDirectory.label'/>:</label></th>
+          <td><s:property value="releaseOutputDirectory"/></td>
+        </tr>
+        <tr class="b">
+          <th><label class="label"><s:text name='configuration.deploymentRepositoryDirectory.label'/>:</label></th>
+          <td><s:property value="deploymentRepositoryDirectory"/></td>
+        </tr>
+        <tr class="b">
+          <th><label class="label"><s:text name='configuration.baseUrl.label'/>:</label></th>
+          <td><s:property value="baseUrl"/></td>
+        </tr>
+        <tr class="b">
+          <th><label class="label"><s:text name='configuration.allowed.build.parallel'/>:</label></th>
+          <td><s:property value="numberOfAllowedBuildsinParallel"/></td>
+        </tr>
+        <tr class="b">
+          <th><label class="label"><s:text name='configuration.distributedBuildEnabled.label'/>:</label></th>
+          <td><s:property value="distributedBuildEnabled"/></td>
+        </tr>
       </table>
       <div class="functnbar3">
-        <s:form action="configuration!input.action" method="post">
+        <s:form action="configuration.action" method="post">
           <s:submit value="%{getText('edit')}"/>
         </s:form>
       </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/configurationEdit.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/configurationEdit.jsp
index d18c1e2..9de3fe0 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/configurationEdit.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/configurationEdit.jsp
@@ -18,7 +18,6 @@
   --%>
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
 <html>
 <s:i18n name="localization.Continuum">
@@ -26,6 +25,21 @@
     <title>
       <s:text name="configuration.page.title"/>
     </title>
+    <script language="javascript">
+      function setSecretPassword()
+      {
+        var form = document.forms[ "editConfiguration" ];
+
+        if ( form.distributedBuildEnabled.checked == true )
+        {
+          form.sharedSecretPassword.disabled = false;
+        }
+        else
+        {
+          form.sharedSecretPassword.disabled = true;
+        }
+      }
+    </script>
   </head>
 
   <body>
@@ -34,7 +48,7 @@
       <s:text name="configuration.section.title"/>
     </h3>
 
-    <s:form action="configuration!save" method="post">
+    <s:form name="editConfiguration" action="configuration_save" method="post">
 
       <c:if test="${!empty actionErrors}">
         <div class="errormessage">
@@ -50,46 +64,65 @@
           <tbody>
 
             <s:textfield label="%{getText('configuration.workingDirectory.label')}" name="workingDirectory"
-                          required="true">
-              <s:param name="desc"><p>
+                          requiredLabel="true" size="100">
+              <s:param name="after"><p>
                 <s:text name="configuration.workingDirectory.message"/>
               </p></s:param>
             </s:textfield>
 
             <s:textfield label="%{getText('configuration.buildOutputDirectory.label')}" name="buildOutputDirectory"
-                          required="true">
-              <s:param name="desc"><p>
+                          requiredLabel="true" size="100">
+              <s:param name="after"><p>
                 <s:text name="configuration.buildOutputDirectory.message"/>
               </p></s:param>
             </s:textfield>
 
             <s:textfield label="%{getText('configuration.releaseOutputDirectory.label')}" name="releaseOutputDirectory"
-            			  required="%{requireReleaseOutput}">
-              <s:param name="desc"><p>
+            			  requiredLabel="%{requireReleaseOutput}" size="100">
+              <s:param name="after"><p>
                 <s:text name="configuration.releaseOutputDirectory.message"/>
               </s:param>
             </s:textfield>
 
             <s:textfield label="%{getText('configuration.deploymentRepositoryDirectory.label')}"
-                          name="deploymentRepositoryDirectory">
-              <s:param name="desc"><p>
+                          name="deploymentRepositoryDirectory" size="100">
+              <s:param name="after"><p>
                 <s:text name="configuration.deploymentRepositoryDirectory.message"/>
               </p></s:param>
             </s:textfield>
 
-            <s:textfield label="%{getText('configuration.baseUrl.label')}" name="baseUrl" required="true">
-              <s:param name="desc"><p>
+            <s:textfield label="%{getText('configuration.baseUrl.label')}" name="baseUrl" requiredLabel="true" size="100">
+              <s:param name="after"><p>
                 <s:text name="configuration.baseUrl.message"/>
               </p></s:param>
             </s:textfield>
 
-		    <s:checkbox label="%{getText('configuration.distributedBuildEnabled.label')}" name="distributedBuildEnabled"/>
+            <s:textfield label="%{getText('configuration.allowed.build.parallel')}" name="numberOfAllowedBuildsinParallel" size="10">
+              <s:param name="after"><p>
+                <s:text name="configuration.allowed.build.paralle.message"/>
+              </p></s:param>
+            </s:textfield>
+
+            <%--
+            <s:checkbox label="%{getText('configuration.disable.parallel.builds')}" name="requireParallelBuilds" requiredLabel="true"/>
+            --%>
+
+            <s:checkbox label="%{getText('configuration.distributedBuildEnabled.label')}" name="distributedBuildEnabled" onclick="setSecretPassword();"/>
+
+            <s:password label="%{getText('configuration.sharedSecretPassword.label')}" name="sharedSecretPassword" disabled="%{!distributedBuildEnabled}" showPassword="true" size="100">
+              <s:param name="after">
+                <p>
+                  <s:text name="configuration.sharedSecretPassword.message"/>
+                </p>
+              </s:param>
+            </s:password>
 
             <s:hidden name="requireReleaseOutput"/>
           </tbody>
         </table>
         <div class="functnbar3">
-          <c1:submitcancel value="%{getText('save')}" cancel="%{getText('cancel')}"/>
+          <s:submit value="%{getText('save')}" theme="simple"/>
+          <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
         </div>
 
       </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteBuildAgent.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteBuildAgent.jsp
index 6750f9e..842c199 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteBuildAgent.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteBuildAgent.jsp
@@ -18,7 +18,6 @@
   --%>
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 
 <html>
   <s:i18n name="localization.Continuum">
@@ -39,10 +38,12 @@
           </p>
         </div>
         <div class="functnbar3">
-          <s:form action="deleteBuildAgent!delete.action" method="post">
+          <s:form action="deleteBuildAgent.action" method="post">
+            <s:token/>
             <input type="hidden" name="buildAgent.url" value="${buildAgent.url}" />
             <s:hidden name="confirmed" value="true"/>
-            <c1:submitcancel value="%{getText('delete')}" cancel="%{getText('cancel')}"/>
+            <s:submit value="%{getText('delete')}" theme="simple"/>
+            <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
           </s:form>
         </div>
       </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteBuildAgentGroup.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteBuildAgentGroup.jsp
new file mode 100644
index 0000000..c6c95e7
--- /dev/null
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteBuildAgentGroup.jsp
@@ -0,0 +1,52 @@
+<%--
+  ~ 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" %>
+
+<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.action" method="post">
+            <s:token/>
+            <input type="hidden" name="buildAgentGroup.name" value="${buildAgentGroup.name}" />
+            <s:hidden name="confirmed" value="true"/>
+            <s:submit value="%{getText('delete')}" theme="simple"/>
+            <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
+          </s:form>
+        </div>
+      </div>
+    </body>
+  </s:i18n>
+</html>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteBuildDefinitionAsTemplate.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteBuildDefinitionAsTemplate.jsp
new file mode 100644
index 0000000..120a080
--- /dev/null
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteBuildDefinitionAsTemplate.jsp
@@ -0,0 +1,50 @@
+<%--
+  ~ 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" %>
+<html>
+  <s:i18n name="localization.Continuum">
+    <head>
+        <title><s:text name="deletebuildDefinition.template.page.title"/></title>
+    </head>
+    <body>
+      <div id="axial" class="h3">
+        <h3><s:text name="deletebuildDefinition.template.section.title"/></h3>
+
+        <div class="warningmessage">
+          <p>
+            <strong>
+                <s:text name="deletebuildDefinition.template.confirmation.message">
+                    <s:param><s:property value="%{buildDefinition.description}"/></s:param>
+                </s:text>
+            </strong>
+          </p>
+        </div>
+        <div class="functnbar3">
+          <s:form action="deleteBuildDefinitionAsTemplate" method="post">
+            <s:hidden name="buildDefinition.id"/>
+            <s:hidden name="confirmed" value="true"/>
+            <s:submit value="%{getText('delete')}" theme="simple"/>
+            <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
+          </s:form>
+        </div>
+      </div>
+    </body>
+  </s:i18n>
+</html>
\ No newline at end of file
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteBuildDefinitionTemplate.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteBuildDefinitionTemplate.jsp
new file mode 100644
index 0000000..1f2ed7b
--- /dev/null
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteBuildDefinitionTemplate.jsp
@@ -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" %>
+<html>
+  <s:i18n name="localization.Continuum">
+    <head>
+        <title><s:text name="deletebuildDefinition.template.page.title"/></title>
+    </head>
+    <body>
+      <div id="axial" class="h3">
+        <h3><s:text name="deletebuildDefinition.template.section.title"/></h3>
+
+        <div class="warningmessage">
+          <p>
+            <strong>
+                <s:text name="deletebuildDefinition.template.confirmation.message">
+                    <s:param><s:property value="%{buildDefinitionTemplate.name}"/></s:param>
+                </s:text>
+            </strong>
+          </p>
+        </div>
+        <div class="functnbar3">
+          <s:form action="deleteDefinitionTemplate" method="post">
+            <s:token/>
+            <s:hidden name="buildDefinitionTemplate.id"/>
+            <s:hidden name="confirmed" value="true"/>
+            <s:submit value="%{getText('delete')}" theme="simple"/>
+            <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
+          </s:form>
+        </div>
+      </div>
+    </body>
+  </s:i18n>
+</html>
\ No newline at end of file
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteBuildEnv.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteBuildEnv.jsp
index 027fae2..2484911 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteBuildEnv.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteBuildEnv.jsp
@@ -18,7 +18,6 @@
   --%>
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <html>
   <s:i18n name="localization.Continuum">
     <head>
@@ -38,9 +37,11 @@
           </p>
         </div>
         <div class="functnbar3">
-          <s:form action="deleteBuildEnv!delete.action" method="post">
+          <s:form action="deleteBuildEnv.action" method="post">
+            <s:token/>
             <input type="hidden" name="profile.id" value="${profile.id}" />
-            <c1:submitcancel value="%{getText('delete')}" cancel="%{getText('cancel')}"/>
+            <s:submit value="%{getText('delete')}" theme="simple"/>
+            <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
           </s:form>
         </div>
       </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteBuildQueue.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteBuildQueue.jsp
new file mode 100644
index 0000000..cf74a3f
--- /dev/null
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteBuildQueue.jsp
@@ -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" %>
+<html>
+  <s:i18n name="localization.Continuum">
+    <head>
+        <title><s:text name="deleteBuildQueue.page.title"/></title>
+    </head>
+    <body>
+      <div id="axial" class="h3">
+        <h3><s:text name="deleteBuildQueue.section.title"/></h3>
+
+        <div class="warningmessage">
+          <p>
+            <strong>
+                <s:text name="deleteBuildQueue.confirmation.message">
+                    <s:param><s:property value="%{buildQueue.name}"/></s:param>
+                </s:text>
+            </strong>
+          </p>
+        </div>
+        <div class="functnbar3">
+          <s:form action="deleteBuildQueue" method="post">
+            <s:token/>
+            <s:hidden name="buildQueue.id"/>
+            <s:hidden name="confirmed" value="true"/>
+            <s:submit value="%{getText('delete')}" theme="simple"/>
+            <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
+          </s:form>
+        </div>
+      </div>
+    </body>
+  </s:i18n>
+</html>
\ No newline at end of file
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteDistributedPurgeConfiguration.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteDistributedPurgeConfiguration.jsp
new file mode 100644
index 0000000..a25589f
--- /dev/null
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteDistributedPurgeConfiguration.jsp
@@ -0,0 +1,56 @@
+<%--
+  ~ 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='http://java.sun.com/jsp/jstl/core' prefix='c'%>
+<html>
+  <s:i18n name="localization.Continuum">
+    <head>
+        <title><s:text name="deletePurgeConfiguration.page.title"/></title>
+    </head>
+    <body>
+      <div id="axial" class="h3">
+        <h3><s:text name="deletePurgeConfiguration.section.title"/></h3>
+        <div class="axial">
+        <s:form action="removeDistributedPurgeConfig" method="post">
+          <s:token/>
+          <s:hidden name="purgeConfigId"/>
+          <s:hidden name="confirmed" value="true"/>
+          <s:actionerror/>
+
+          <div class="warningmessage">
+            <p>
+              <strong>
+                <s:text name="deletePurgeConfiguration.confirmation.message">
+                  <s:param><s:property value="%{description}"/></s:param>
+                </s:text>
+              </strong>
+            </p>
+          </div>
+
+          <div class="functnbar3">
+            <s:submit value="%{getText('delete')}" theme="simple"/>
+            <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
+          </div>
+        </s:form>
+        </div>
+      </div>
+    </body>
+  </s:i18n>
+</html>
\ No newline at end of file
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteInstallation.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteInstallation.jsp
new file mode 100644
index 0000000..7a34b7c
--- /dev/null
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteInstallation.jsp
@@ -0,0 +1,50 @@
+<%--
+  ~ 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" %>
+<html>
+  <s:i18n name="localization.Continuum">
+    <head>
+        <title><s:text name="deleteInstallation.page.title"/></title>
+    </head>
+    <body>
+      <div id="axial" class="h3">
+        <h3><s:text name="deleteInstallation.section.title"/></h3>
+
+        <div class="warningmessage">
+          <p>
+            <strong>
+                <s:text name="deleteInstallation.confirmation.message">
+                    <s:param><s:property value="%{installation.name}"/></s:param>
+                </s:text>
+            </strong>
+          </p>
+        </div>
+        <div class="functnbar3">
+          <s:form action="deleteInstallation" method="post">
+            <input type="hidden" name="installation.installationId" value="${installation.installationId}" />
+            <s:hidden name="confirmed" value="true"/>
+            <s:submit value="%{getText('delete')}" theme="simple"/>
+            <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
+          </s:form>
+        </div>
+      </div>
+    </body>
+  </s:i18n>
+</html>
\ No newline at end of file
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteLocalRepository.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteLocalRepository.jsp
index e1d5fed..db3ab1f 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteLocalRepository.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeleteLocalRepository.jsp
@@ -18,7 +18,6 @@
   --%>
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
 <html>
   <s:i18n name="localization.Continuum">
@@ -30,6 +29,7 @@
         <h3><s:text name="deleteRepository.section.title"/></h3>
         <div class="axial">
         <s:form action="removeRepository" method="post">
+          <s:token/>
           <s:hidden name="repository.id"/>
           <s:hidden name="confirmed" value="true"/>
           <s:actionerror/>
@@ -45,7 +45,8 @@
           </div>
 
           <div class="functnbar3">
-            <c1:submitcancel value="%{getText('delete')}" cancel="%{getText('cancel')}"/>
+            <s:submit value="%{getText('delete')}" theme="simple"/>
+            <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
           </div>
         </s:form>
         </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeletePurgeConfiguration.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeletePurgeConfiguration.jsp
new file mode 100644
index 0000000..619902d
--- /dev/null
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/confirmDeletePurgeConfiguration.jsp
@@ -0,0 +1,56 @@
+<%--
+  ~ 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='http://java.sun.com/jsp/jstl/core' prefix='c'%>
+<html>
+  <s:i18n name="localization.Continuum">
+    <head>
+        <title><s:text name="deletePurgeConfiguration.page.title"/></title>
+    </head>
+    <body>
+      <div id="axial" class="h3">
+        <h3><s:text name="deletePurgeConfiguration.section.title"/></h3>
+        <div class="axial">
+        <s:form action="removePurgeConfig" method="post">
+          <s:token/>
+          <s:hidden name="purgeConfigId"/>
+          <s:hidden name="confirmed" value="true"/>
+          <s:actionerror/>
+
+          <div class="warningmessage">
+            <p>
+              <strong>
+                <s:text name="deletePurgeConfiguration.confirmation.message">
+                  <s:param><s:property value="%{description}"/></s:param>
+                </s:text>
+              </strong>
+            </p>
+          </div>
+
+          <div class="functnbar3">
+            <s:submit value="%{getText('delete')}" theme="simple"/>
+            <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
+          </div>
+        </s:form>
+        </div>
+      </div>
+    </body>
+  </s:i18n>
+</html>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/distributedPurgeConfigurationsList.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/distributedPurgeConfigurationsList.jsp
new file mode 100644
index 0000000..373ee44
--- /dev/null
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/distributedPurgeConfigurationsList.jsp
@@ -0,0 +1,84 @@
+<%--
+  ~ 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="http://www.extremecomponents.org" prefix="ec" %>
+<%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
+<%@ taglib uri="http://plexus.codehaus.org/redback/taglib-1.0" prefix="redback" %>
+
+<html>
+  <s:i18n name="localization.Continuum">
+    <head>
+      <title><s:text name="purgeConfigs.page.title"/></title>
+    </head>
+    <body>
+      <div id="h3">
+        <h3><s:text name="purgeConfigs.dir.section.title"/></h3>
+        <s:set name="distributedDirPurgeConfigs" value="distributedDirPurgeConfigs" scope="request"/>
+        <ec:table items="distributedDirPurgeConfigs"
+                  var="dirPurge"
+                  autoIncludeParameters="false"
+                  showExports="false"
+                  showPagination="false"
+                  showStatusBar="false"
+                  sortable="false"
+                  filterable="false">
+         <ec:row>
+            <ec:column property="directoryType" title="purgeConfigs.table.directoryType"/>
+            <ec:column property="daysOlder" title="purgeConfigs.table.daysOlder"/>
+            <ec:column property="retentionCount" title="purgeConfigs.table.retentionCount"/>
+            <ec:column property="deleteAll" title="purgeConfigs.table.deleteAll"/>
+            <ec:column property="schedule.name" title="purgeConfigs.table.schedule"/>
+            <ec:column property="enabled" title="purgeConfigs.table.enabled"/>
+            <ec:column property="description" title="purgeConfigs.table.description"/>
+            <ec:column property="buildAgentUrl" title="purgeConfigs.table.buildAgent"/>
+            <ec:column property="editActions" title="&nbsp;" width="1%">
+                <s:url id="editPurgeConfigUrl" action="editDistributedPurgeConfig">
+                  <s:param name="purgeConfigId"><c:out value="${pageScope.dirPurge.id}"/></s:param>
+                </s:url>
+                <s:a href="%{editPurgeConfigUrl}"><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="purgeActions" title="&nbsp;" width="1%">
+                <s:url id="purgeUrl" action="doDistributedPurge">
+                  <s:param name="purgeConfigId"><c:out value="${pageScope.dirPurge.id}"/></s:param>
+                </s:url>
+                <s:a href="%{purgeUrl}"><img src="<s:url value='/images/purgenow.gif' includeParams="none"/>" alt="<s:text name='purge'/>" title="<s:text name='purge'/>" border="0" /></s:a>
+            </ec:column>
+            <ec:column property="deleteActions" title="&nbsp;" width="1%">
+                <s:token/>
+                <s:url id="removePurgeConfigUrl" action="removeDistributedPurgeConfig">
+                  <s:param name="purgeConfigId"><c:out value="${pageScope.dirPurge.id}"/></s:param>
+                  <s:param name="description"><c:out value="${pageScope.dirPurge.description}"/></s:param>
+                  <s:param name="struts.token.name">token</s:param>
+                  <s:param name="token"><s:property value="token"/></s:param>
+                </s:url>
+                <s:a href="%{removePurgeConfigUrl}"><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="addDirPurgeConfig" action="editDistributedPurgeConfig" method="post">
+          <s:hidden name="purgeType" value="directory"/>
+          <s:submit value="%{getText('add')}" theme="simple"/>
+        </s:form>
+      </div>
+    </body>
+  </s:i18n>
+</html>
\ No newline at end of file
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editAppearance.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editAppearance.jsp
index 62ae81e..ca2cf1f 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editAppearance.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editAppearance.jsp
@@ -22,7 +22,6 @@
 <s:i18n name="localization.Continuum">
 <head>
   <title><s:text name="appearance.page.title"/></title>
-  <s:head/>
 </head>
 
 <body>
@@ -35,9 +34,9 @@
   </p>
 
   <s:actionmessage/>
-  <s:form method="post" action="saveAppearance" namespace="/admin" validate="true" theme="xhtml">
-    <s:textfield name="companyPom.groupId" label="%{getText('appearance.companyPom.groupId')}"/>
-    <s:textfield name="companyPom.artifactId" label="%{getText('appearance.companyPom.artifactId')}"/>
+  <s:form method="post" action="saveAppearance" namespace="/admin" validate="true">
+    <s:textfield name="companyPom.groupId" label="%{getText('appearance.companyPom.groupId')}" size="100"/>
+    <s:textfield name="companyPom.artifactId" label="%{getText('appearance.companyPom.artifactId')}" size="100"/>
     <s:submit value="%{getText('save')}"/>
   </s:form>
 </body>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editBuildAgent.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editBuildAgent.jsp
index c1e7051..9250efc 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editBuildAgent.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editBuildAgent.jsp
@@ -19,7 +19,6 @@
   
 <%@ 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>
@@ -28,7 +27,7 @@
     <body>
     <div class="app">
       <div id="axial" class="h3">
-        <h3><s:text name="buildAgent.page.title"/></h3>
+        <h3><s:text name="buildAgent.section.title"/></h3>
         
         <div class="axial">
           <s:form action="saveBuildAgent" method="post" validate="true">
@@ -44,18 +43,19 @@
               <s:hidden name="type"/>
               <c:choose>
                 <c:when test="${type=='new'}">
-                  <s:textfield label="%{getText('buildAgent.url.label')}" name="buildAgent.url" required="true"/>
+                  <s:textfield label="%{getText('buildAgent.url.label')}" name="buildAgent.url" requiredLabel="true" size="100"/>
                 </c:when>
                 <c:otherwise>
                   <s:hidden name="buildAgent.url"/>
-                  <s:textfield label="%{getText('buildAgent.url.label')}" name="buildAgent.url" required="true" disabled="true"/>
+                  <s:textfield label="%{getText('buildAgent.url.label')}" name="buildAgent.url" requiredLabel="true" disabled="true" size="100"/>
                 </c:otherwise>
               </c:choose>
-              <s:textfield label="%{getText('buildAgent.description.label')}" name="buildAgent.description"/>
+              <s:textfield label="%{getText('buildAgent.description.label')}" name="buildAgent.description" size="100"/>
               <s:checkbox label="%{getText('buildAgent.enabled.label')}" name="buildAgent.enabled" value="buildAgent.enabled" fieldValue="true"/>
             </table>
             <div class="functnbar3">
-              <c1:submitcancel value="%{getText('save')}" cancel="%{getText('cancel')}"/>
+              <s:submit value="%{getText('save')}" theme="simple"/>
+              <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
             </div>
           </s:form>
         </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editBuildAgentGroup.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editBuildAgentGroup.jsp
new file mode 100644
index 0000000..ee87494
--- /dev/null
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editBuildAgentGroup.jsp
@@ -0,0 +1,100 @@
+<%--
+  ~ 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" %>
+<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" requiredLabel="true" size="100"/>
+                </c:when>
+                <c:otherwise>
+                  <s:hidden name="buildAgentGroup.name"/>
+                  <s:textfield label="%{getText('buildAgentGroup.name.label')}" name="buildAgentGroup.name" requiredLabel="true" disabled="true" size="100"/>
+                </c:otherwise>
+              </c:choose>
+            </table>
+            
+            <c:choose>
+              <c:when test="${not empty buildAgents || not empty selectedBuildAgentIds}">
+                <table>
+                  <s:optiontransferselect
+                        label="%{getText('buildAgentGroup.buildAgents.define')}"    
+                        name="buildAgentIds"
+                        list="buildAgents" 
+                        listKey="url"
+                        listValue="url"
+                        headerKey="hk-1"
+                        headerValue="%{getText('buildAgentGroup.available.buildAgents')}"
+                        multiple="true"
+                        emptyOption="false"
+                        doubleName="selectedBuildAgentIds"
+                        doubleList="buildAgentGroup.buildAgents" 
+                        doubleListKey="url"
+                        doubleListValue="url"
+                        doubleHeaderKey="hk-1"
+                        doubleHeaderValue="%{getText('buildAgentGroup.available.buildAgents.used')}" 
+                        doubleMultiple="true" 
+                        doubleEmptyOption="false"
+                        formName="buildAgentGroup"
+                        addAllToRightOnclick="selectAllOptionsExceptSome(document.getElementById('saveBuildAgentGroup_selectedBuildAgentIds'), 'key', 'hk-1');"
+                        addToRightOnclick="selectAllOptionsExceptSome(document.getElementById('saveBuildAgentGroup_buildAgentIds'), 'key', 'hk-1');selectAllOptionsExceptSome(document.getElementById('saveBuildAgentGroup_selectedBuildAgentIds'), 'key', 'hk-1');"
+                        addAllToLeftOnclick="selectAllOptionsExceptSome(document.getElementById('saveBuildAgentGroup_buildAgentIds'), 'key', 'hk-1');"
+                        addToLeftOnclick="selectAllOptionsExceptSome(document.getElementById('saveBuildAgentGroup_buildAgentIds'), 'key', 'hk-1');selectAllOptionsExceptSome(document.getElementById('saveBuildAgentGroup_selectedBuildAgentIds'), 'key', 'hk-1');"
+                        />
+                </table>
+              </c:when>
+              <c:otherwise>
+                <table>
+                  <s:text name="buildAgents.empty"/>
+                </table>
+              </c:otherwise>
+            </c:choose>                           
+
+            <div class="functnbar3">
+              <s:submit value="%{getText('save')}" theme="simple"/>
+              <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
+            </div>
+          </s:form>
+        </div>
+      </div>
+    </div>
+  </s:i18n>
+ </html>
\ No newline at end of file
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editBuildDefinitionAsTemplate.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editBuildDefinitionAsTemplate.jsp
index 7dc417c..2a43e9f 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editBuildDefinitionAsTemplate.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editBuildDefinitionAsTemplate.jsp
@@ -19,7 +19,6 @@
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
-<%@ taglib uri="continuum" prefix="c1" %>
 <html>
   <s:i18n name="localization.Continuum">
     <head>
@@ -46,25 +45,25 @@
                 <table>
                   <tbody>
                     <s:if test="buildDefinition.type == 'ant'">
-                      <s:textfield label="%{getText('buildDefinition.buildFile.ant.label')}" name="buildDefinition.buildFile"  required="true"/>
+                      <s:textfield label="%{getText('buildDefinition.buildFile.ant.label')}" name="buildDefinition.buildFile"  requiredLabel="true" size="100"/>
                     </s:if>
                     <s:elseif test="buildDefinition.type == 'shell'">
-                      <s:textfield label="%{getText('buildDefinition.buildFile.shell.label')}" name="buildDefinition.buildFile" required="true"/>
+                      <s:textfield label="%{getText('buildDefinition.buildFile.shell.label')}" name="buildDefinition.buildFile" requiredLabel="true" size="100"/>
                     </s:elseif>
                     <s:else>
-                      <s:textfield label="%{getText('buildDefinition.buildFile.maven.label')}" name="buildDefinition.buildFile" required="true"/>
+                      <s:textfield label="%{getText('buildDefinition.buildFile.maven.label')}" name="buildDefinition.buildFile" requiredLabel="true" size="100"/>
                     </s:else>
     
                     <s:if test="buildDefinition.type == 'ant'">
-                      <s:textfield label="%{getText('buildDefinition.goals.ant.label')}" name="buildDefinition.goals"/>
+                      <s:textfield label="%{getText('buildDefinition.goals.ant.label')}" name="buildDefinition.goals" size="100"/>
                     </s:if>
                     <s:elseif test="buildDefinition.type == 'shell'">
                     </s:elseif>
                     <s:else>
-                      <s:textfield label="%{getText('buildDefinition.goals.maven.label')}" name="buildDefinition.goals"/>
+                      <s:textfield label="%{getText('buildDefinition.goals.maven.label')}" name="buildDefinition.goals" requiredLabel="true" size="100"/>
                     </s:else>
     
-                    <s:textfield label="%{getText('buildDefinition.arguments.label')}" name="buildDefinition.arguments"/>
+                    <s:textfield label="%{getText('buildDefinition.arguments.label')}" name="buildDefinition.arguments" size="100"/>
                     <s:checkbox label="%{getText('buildDefinition.buildFresh.label')}" name="buildDefinition.buildFresh"/>
                     <s:checkbox label="%{getText('buildDefinition.alwaysBuild.label')}" name="buildDefinition.alwaysBuild" />
                     <s:checkbox label="%{getText('buildDefinition.defaultForProject.label')}" name="buildDefinition.defaultForProject" />
@@ -79,11 +78,15 @@
                                  listKey="id" headerKey="-1" headerValue=""/>
                     </s:else>
                     <s:select label="%{getText('buildDefinition.type.label')}" name="buildDefinition.type" list="buildDefinitionTypes"/>
-                    <s:textfield label="%{getText('buildDefinition.description.label')}" name="buildDefinition.description" required="true"/>
+                    <s:if test="buildDefinition.type != 'ant' || buildDefinition.type != 'shell'">
+                        <s:select label="%{getText('buildDefinition.updatePolicy.label')}" name="buildDefinition.updatePolicy" list="buildDefinitionUpdatePolicies"/>
+                    </s:if>
+                    <s:textfield label="%{getText('buildDefinition.description.label')}" name="buildDefinition.description" requiredLabel="true" size="100"/>
                   </tbody>
                 </table>
                 <div class="functnbar3">
-                  <c1:submitcancel value="%{getText('save')}" cancel="%{getText('cancel')}"/>
+                  <s:submit value="%{getText('save')}" theme="simple"/>
+                  <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
                 </div>
 
                 <s:hidden name="buildDefinition.id"/>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editBuildDefinitionTemplate.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editBuildDefinitionTemplate.jsp
index 250c9b5..25b9255 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editBuildDefinitionTemplate.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editBuildDefinitionTemplate.jsp
@@ -19,7 +19,6 @@
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
-<%@ taglib uri="continuum" prefix="c1" %>
 <html>
   <s:i18n name="localization.Continuum">
     <head>
@@ -45,14 +44,14 @@
               <c:when test="${empty actionErrors}">
                 <table>
                   <tbody>
-                    <s:textfield label="%{getText('buildDefinitionTemplate.name')}" name="buildDefinitionTemplate.name" required="true"/>
+                    <s:textfield label="%{getText('buildDefinitionTemplate.name')}" name="buildDefinitionTemplate.name" requiredLabel="true" size="100"/>
                     <s:optiontransferselect
                         label="%{getText('buildDefinitionTemplate.builddefinitions.define')}"    
                         name="buildDefinitionIds"
                         list="buildDefinitions" 
                         listKey="id"
                         listValue="description"
-                        headerKey="-1"
+                        headerKey="hk-1"
                         headerValue="%{getText('buildDefinitionTemplate.available.builddefinitions')}"
                         multiple="true"
                         emptyOption="false"
@@ -60,15 +59,21 @@
                         doubleList="buildDefinitionTemplate.buildDefinitions" 
                         doubleListKey="id"
                         doubleListValue="description"
-                        doubleHeaderKey="-1"
+                        doubleHeaderKey="hk-1"
                         doubleHeaderValue="%{getText('buildDefinitionTemplate.available.builddefinitions.used')}" 
                         doubleMultiple="true" 
                         doubleEmptyOption="false"
-                        formName="buildDefinitionTemplate" />                    
+                        formName="buildDefinitionTemplate"
+                        addAllToRightOnclick="selectAllOptionsExceptSome(document.getElementById('saveBuildDefinitionTemplate_selectedBuildDefinitionIds'), 'key', 'hk-1');"
+                        addToRightOnclick="selectAllOptionsExceptSome(document.getElementById('saveBuildDefinitionTemplate_buildDefinitionIds'), 'key', 'hk-1');selectAllOptionsExceptSome(document.getElementById('saveBuildDefinitionTemplate_selectedBuildDefinitionIds'), 'key', 'hk-1');"
+                        addAllToLeftOnclick="selectAllOptionsExceptSome(document.getElementById('saveBuildDefinitionTemplate_buildDefinitionIds'), 'key', 'hk-1');"
+                        addToLeftOnclick="selectAllOptionsExceptSome(document.getElementById('saveBuildDefinitionTemplate_buildDefinitionIds'), 'key', 'hk-1');selectAllOptionsExceptSome(document.getElementById('saveBuildDefinitionTemplate_selectedBuildDefinitionIds'), 'key', 'hk-1');"
+                        />
                   </tbody>
                 </table>
                 <div class="functnbar3">
-                  <c1:submitcancel value="%{getText('save')}" cancel="%{getText('cancel')}"/>
+                  <s:submit value="%{getText('save')}" theme="simple"/>
+                  <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
                 </div>
                 <s:hidden name="buildDefinitionTemplate.id"/>
                 <s:hidden name="buildDefinitionTemplate.continuumDefault"/>
@@ -80,10 +85,5 @@
       </div>
     </body>
   </s:i18n>
-  <script type="text/javascript">
-  customOnsubmit = function(){
-	  // no op
-  }
-  </script>
 </html>
 
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editDistributedPurgeConfiguration.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editDistributedPurgeConfiguration.jsp
new file mode 100644
index 0000000..36c0914
--- /dev/null
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editDistributedPurgeConfiguration.jsp
@@ -0,0 +1,68 @@
+<%--
+  ~ 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" %>
+<html>
+  <s:i18n name="localization.Continuum">
+  <head>
+    <title><s:text name="purgeConfig.page.title"/></title>
+  </head>
+  <body>
+  <div class="app">
+    <div id="axial" class="h3">
+      <h3><s:text name="purgeConfig.section.title"/></h3>
+
+    <div class="axial">
+      <s:form action="saveDistributedPurgeConfig" method="post" validate="true">
+        <c:if test="${!empty actionErrors}">
+          <div class="errormessage">
+            <s:iterator value="actionErrors">
+              <p><s:property/></p>
+            </s:iterator>
+          </div>
+        </c:if>
+          <table>
+            <s:select label="%{getText('purgeConfig.directoryType.label')}" name="directoryType" list="directoryTypes"/>
+            <s:textfield label="%{getText('purgeConfig.daysOlder.label')}" name="daysOlder" size="100"/>
+            <s:textfield label="%{getText('purgeConfig.retentionCount.label')}" name="retentionCount" size="100"/>
+            <s:checkbox label="%{getText('purgeConfig.deleteAll.label')}" name="deleteAll"/>
+            <s:if test="purgeType == 'repository'">
+              <s:checkbox label="%{getText('purgeConfig.deleteReleasedSnapshots.label')}" name="deleteReleasedSnapshots"/>
+            </s:if>
+            <s:select label="%{getText('purgeConfig.buildAgent.label')}" name="buildAgentUrl" list="buildAgentUrls"/>
+            <s:select label="%{getText('purgeConfig.schedule.label')}" name="scheduleId" list="schedules"
+                       headerKey="-1" headerValue=""/>
+            <s:textfield label="%{getText('purgeConfig.description.label')}" name="description" size="100"/>
+            <s:checkbox label="%{getText('purgeConfig.enabled.label')}" name="enabled"/>
+          </table>
+          <s:hidden name="purgeConfigId"/>
+          <s:hidden name="purgeType"/>
+          <div class="functnbar3">
+            <s:submit value="%{getText('save')}" theme="simple"/>
+            <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
+          </div>
+      </s:form>
+    </div>
+  </div>
+</div>
+
+</body>
+</s:i18n>
+</html>
\ No newline at end of file
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editInstallation.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editInstallation.jsp
index f91090e..3ffb5a4 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editInstallation.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editInstallation.jsp
@@ -18,7 +18,6 @@
   --%>
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <html>
 <s:i18n name="localization.Continuum">
   <head>
@@ -33,7 +32,7 @@
       <s:text name="installation.section.title"/>
     </h3>
 
-    <s:form action="saveInstallation!save" method="post">
+    <s:form action="saveInstallation" method="post">
 
       <s:if test="hasActionErrors()">
         <h3>Action Error</h3>
@@ -48,30 +47,34 @@
           <tbody>
             <s:hidden name="installation.installationId" />
             <s:hidden name="installationType" />
+            <s:hidden name="displayTypes" />
+            <s:hidden name="varNameUpdatable" />
+            <s:hidden name="varNameDisplayable" />
             <s:textfield label="%{getText('installation.name.label')}" name="installation.name"
-                            required="true"/>
+                            requiredLabel="true" size="100"/>
             <s:if test="displayTypes">
               <s:select label="%{getText('installation.type.label')}" name="installation.type" list="typesLabels" />
             </s:if>
             <s:if test="varNameUpdatable">
               <s:if test="varNameDisplayable">
-                <s:textfield label="%{getText('installation.varName.label')}" name="installation.varName" required="true" />
+                <s:textfield label="%{getText('installation.varName.label')}" name="installation.varName" requiredLabel="true" size="100" />
               </s:if>
             </s:if>
             <s:else>
               <s:if test="varNameDisplayable">
-                <s:textfield label="%{getText('installation.varName.label')}" name="installation.varName" required="true" readonly="true"/>
+                <s:textfield label="%{getText('installation.varName.label')}" name="installation.varName" requiredLabel="true" readonly="true" size="100"/>
               </s:if>
             </s:else>
             <s:textfield label="%{getText('installation.value.label')}" name="installation.varValue"
-                          required="true"/>
+                          requiredLabel="true" size="100"/>
             <s:if test="%{(automaticProfileDisplayable && installation == null) || (installation.installationId == 0)}">
               <s:checkbox label="%{getText('installation.automaticProfile.label')}" name="automaticProfile" />
             </s:if>
           </tbody>
         </table>
         <div class="functnbar3">
-          <c1:submitcancel value="%{getText('save')}" cancel="%{getText('cancel')}"/>
+          <s:submit value="%{getText('save')}" theme="simple"/>
+          <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
         </div>
 
       </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editLocalRepository.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editLocalRepository.jsp
index e239e3b..2a40b07 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editLocalRepository.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editLocalRepository.jsp
@@ -19,7 +19,6 @@
 
 <%@ 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>
@@ -28,7 +27,7 @@
 <body>
 <div class="app">
   <div id="axial" class="h3">
-    <h3><s:text name="repository.page.title"/></h3>
+    <h3><s:text name="repository.section.title"/></h3>
 
     <div class="axial">
       <s:form action="saveRepository" method="post" validate="true">
@@ -41,8 +40,8 @@
         </c:if>
 
           <table>
-            <s:textfield label="%{getText('repository.name.label')}" name="repository.name" required="true" disabled="%{defaultRepo}"/>
-            <s:textfield label="%{getText('repository.location.label')}" name="repository.location" required="true" disabled="%{defaultRepo}"/>
+            <s:textfield label="%{getText('repository.name.label')}" name="repository.name" requiredLabel="true" disabled="%{defaultRepo}" size="100"/>
+            <s:textfield label="%{getText('repository.location.label')}" name="repository.location" requiredLabel="true" disabled="%{defaultRepo}" size="100"/>
             <s:select label="%{getText('repository.layout.label')}" name="repository.layout" list="layouts" disabled="%{defaultRepo}"/>
           </table>
           <s:hidden name="repository.id"/>
@@ -52,7 +51,8 @@
             <s:hidden name="repository.layout"/>
           </s:if>
           <div class="functnbar3">
-            <c1:submitcancel value="%{getText('save')}" cancel="%{getText('cancel')}"/>
+            <s:submit value="%{getText('save')}" theme="simple"/>
+            <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
           </div>
         
       </s:form>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editParallelBuilds.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editParallelBuilds.jsp
new file mode 100644
index 0000000..5e4c3a1
--- /dev/null
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editParallelBuilds.jsp
@@ -0,0 +1,57 @@
+<%--
+  ~ 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="http://www.extremecomponents.org" prefix="ec" %>
+<%@ taglib uri="http://plexus.codehaus.org/redback/taglib-1.0" prefix="redback" %>
+
+<html>
+  <s:i18n name="localization.Continuum">
+<head>
+<title><s:text name="parallel.build.queue.page.title"/></title>
+</head>
+<body>
+
+<div class="app">
+  <div id="axial" class="h3">
+    <h3><s:text name="parallel.build.queue.section.title"/></h3>
+
+    <c:if test="${!empty actionErrors}">
+      <div class="errormessage">
+        <p><s:actionerror/></p>
+      </div>
+    </c:if>
+    
+    <div class="axial">
+      <s:form action="saveBuildQueue" method="post" validate="true">
+          <table>
+            <s:textfield label="%{getText('parallel.build.queue.name')}" name="name" requiredLabel="true" size="100" />
+          </table>
+          <div class="functnbar3">
+            <s:submit value="%{getText('save')}" theme="simple"/>
+            <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
+          </div>
+      </s:form>
+    </div>
+  </div>
+</div>
+</body>
+</s:i18n>
+</html>
\ No newline at end of file
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editPom.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editPom.jsp
index e85bc21..853760b 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editPom.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editPom.jsp
@@ -22,14 +22,14 @@
 <s:i18n name="localization.Continuum">
 <head>
   <title><s:text name="companyPom.page.title"/></title>
-  <s:head/>
 </head>
 
 <body>
 <h1><s:text name="companyPom.section.title"/></h1>
 
 <s:actionmessage/>
-<s:form method="post" action="saveCompanyPom" namespace="/admin" validate="true" theme="xhtml">
+<s:form method="post" action="saveCompanyPom" namespace="/admin" validate="true">
+  <s:token/>
   <s:label name="companyModel.groupId" label="%{getText('appearance.companyPom.groupId')}"/>
   <s:label name="companyModel.artifactId" label="%{getText('appearance.companyPom.artifactId')}"/>
   <tr>
@@ -45,8 +45,7 @@
   </tr>
   <s:textfield name="companyModel.organization.name" size="40" label="%{getText('appearance.companyPom.organizationName.label')}"/>
   <s:textfield name="companyModel.organization.url" size="70" label="%{getText('appearance.companyPom.organizationUrl.label')}"/>
-  <%-- TODO: how to get it to be a string, not a String[]? --%>
-  <s:textfield name="companyModel.properties['organization.logo']" size="70" label="%{getText('appearance.companyPom.organizationLogoUrl.label')}"/>
+  <s:textfield name="organizationLogo" size="70" label="%{getText('appearance.companyPom.organizationLogoUrl.label')}"/>
   <s:submit value="%{getText('save')}"/>
 </s:form>
 
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editProfile.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editProfile.jsp
index aa2af06..bfb1453 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editProfile.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editProfile.jsp
@@ -38,96 +38,85 @@
       <div class="axial">
         <s:if test="hasActionErrors()">
           <h3><s:text name="profile.actionError"/></h3>
-         <p>
-           <s:actionerror/>
-         </p>
+          <p>
+            <s:actionerror/>
+          </p>
         </s:if>
       </div>
-      <table>
-        <tr>
-          <td>
-          <s:form action="saveBuildEnv!save" method="post">
-
-            <div class="axial">
-              <!--  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" />
-                </tbody>
-              </table>
-              <div class="functnbar3">
-                <c1:submitcancel value="%{getText('save')}" cancel="%{getText('cancel')}"/>
-              </div>
-
-            </div>
-          </s:form>
-          </td>
-        </tr>
-        <s:if test="profile.id != 0">
+      <div class="axial">
+        <s:form action="saveBuildEnv" method="post">
+        <!--  if other fields are added ProfileAction#save must be changed  -->
+        <s:hidden name="profile.id" />
+        <s:textfield label="%{getText('profile.name.label')}" name="profile.name"
+                     requiredLabel="true" size="100" />
+          <c1:ifBuildTypeEnabled buildType="distributed">
+            <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>
+          </c1:ifBuildTypeEnabled>
           <tr>
-            <td>
-              <div class="axial">
-                <table width="100%">
-                  <tbody>
-                    <tr>
-                      <td>
-                        <ec:table items="profileInstallations"
-                                  var="profileInstallation"
-                                  showExports="false"
-                                  showPagination="false"
-                                  showStatusBar="false"
-                                  sortable="false"
-                                  filterable="false"
-                                  width="100%"
-                                  autoIncludeParameters="false">
-                          <ec:row highlightRow="true">
-                            <ec:column property="nameEdit" title="profile.installation.name.label" style="white-space: nowrap" width="50%">
-                              <a href="editInstallation!edit.action?installation.installationId=<c:out value="${profileInstallation.installationId}"/>">
-                                <c:out value="${profileInstallation.name}"/>
-                              </a>
-                               (<c:out value="${profileInstallation.varValue}"/>)
-                            </ec:column>
-                            <ec:column property="type" title="installation.type.label" style="white-space: nowrap" width="49%"/>
-                            <ec:column property="id" title="&nbsp;" width="1%">
-                              <a href="removeBuildEnvInstallation!removeInstallation.action?profile.id=<c:out value="${profile.id}"/>&installationId=<c:out value="${profileInstallation.installationId}"/>">
-                                <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:row>
-                        </ec:table>                
-                      </td>
-                    </tr>
-                  </tbody>
-                </table>
-                <s:if test="allInstallations.size > 0">
-                  <s:form action="addInstallationBuildEnv!addInstallation.action" method="get">
-                    <s:hidden name="profile.id" />
-                    <div class="functnbar3">
-                      <!-- can't use default profile to display this select -->
-                      <s:select theme="profile" name="installationId" list="allInstallations" listKey="installationId" listValue="name" />
-                      <s:submit value="%{getText('add')}"/>
-                    </div>
-                  </s:form>
-                </s:if>
-                <s:else>
-                  <div class="warningmessage" style="color: red"><s:text name="profile.no.installations" /></div>
-                </s:else>
-              </div>              
+            <td colspan="2">
+              <div class="functnbar3">
+                <s:submit value="%{getText('save')}" theme="simple"/>
+                <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
+              </div>
             </td>
           </tr>
-        </s:if>
-        <s:else>
-          <tr>
-            <td>
-              <c:if test="allInstallations.size < 1">
-                <div class="warningmessage" style="color: red"><s:text name="profile.no.installations" /></div>
-              </c:if>
-            </td>
-          </tr> 
-        </s:else>
-      </table>
+        </s:form>
+      </div>
+      <s:if test="profile.id != 0">
+        <div class="axial">
+          <ec:table items="profileInstallations"
+                    var="profileInstallation"
+                    showExports="false"
+                    showPagination="false"
+                    showStatusBar="false"
+                    sortable="false"
+                    filterable="false"
+                    width="100%"
+                    autoIncludeParameters="false">
+            <ec:row highlightRow="true">
+              <ec:column property="nameEdit" title="profile.installation.name.label" style="white-space: nowrap" width="50%">
+                <a href="editInstallation.action?installation.installationId=<c:out value="${profileInstallation.installationId}"/>">
+                  <c:out value="${profileInstallation.name}"/>
+                </a>
+                (<c:out value="${profileInstallation.varValue}"/>)
+              </ec:column>
+              <ec:column property="type" title="installation.type.label" style="white-space: nowrap" width="49%"/>
+              <ec:column property="id" title="&nbsp;" width="1%">
+                <a href="removeBuildEnvInstallation.action?profile.id=<c:out value="${profile.id}"/>&installationId=<c:out value="${profileInstallation.installationId}"/>">
+                  <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:row>
+          </ec:table>
+          <s:if test="allInstallations.size > 0">
+            <s:form action="addInstallationBuildEnv.action" method="get">
+              <s:hidden name="profile.id" />
+              <div class="functnbar3">
+                <!-- can't use default profile to display this select -->
+                <s:select theme="simple" name="installationId" list="allInstallations" listKey="installationId" listValue="name" />
+                <s:submit value="%{getText('add')}" theme="simple"/>
+              </div>
+            </s:form>
+          </s:if>
+          <s:else>
+            <div class="warningmessage" style="color: red"><s:text name="profile.no.installations" /></div>
+          </s:else>
+        </div>
+      </s:if>
+      <s:else>
+        <c:if test="allInstallations.size < 1">
+          <div class="warningmessage" style="color: red"><s:text name="profile.no.installations" /></div>
+        </c:if>
+      </s:else>
     </div>
   </body>
 </s:i18n>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editPurgeConfiguration.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editPurgeConfiguration.jsp
index 8a185dd..0e6bc6e 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editPurgeConfiguration.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/editPurgeConfiguration.jsp
@@ -19,7 +19,6 @@
 
 <%@ 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>
@@ -44,14 +43,14 @@
           <table>
             <c:choose>
               <c:when test="${purgeType == 'repository'}">
-                <s:select label="%{getText('purgeConfig.repository.label')}" name="repositoryId" list="repositories" required="true"/>
+                <s:select label="%{getText('purgeConfig.repository.label')}" name="repositoryId" list="repositories" requiredLabel="true"/>
               </c:when>
               <c:otherwise>
                 <s:select label="%{getText('purgeConfig.directoryType.label')}" name="directoryType" list="directoryTypes"/>
               </c:otherwise>
             </c:choose>
-            <s:textfield label="%{getText('purgeConfig.daysOlder.label')}" name="daysOlder"/>
-            <s:textfield label="%{getText('purgeConfig.retentionCount.label')}" name="retentionCount"/>
+            <s:textfield label="%{getText('purgeConfig.daysOlder.label')}" name="daysOlder" size="100"/>
+            <s:textfield label="%{getText('purgeConfig.retentionCount.label')}" name="retentionCount" size="100"/>
             <s:checkbox label="%{getText('purgeConfig.deleteAll.label')}" name="deleteAll"/>
             <s:if test="purgeType == 'repository'">
               <s:checkbox label="%{getText('purgeConfig.deleteReleasedSnapshots.label')}" name="deleteReleasedSnapshots"/>
@@ -67,12 +66,14 @@
             </c:choose>
             <s:select label="%{getText('purgeConfig.schedule.label')}" name="scheduleId" list="schedules"
                        headerKey="-1" headerValue=""/>
-            <s:textfield label="%{getText('purgeConfig.description.label')}" name="description"/>
+            <s:textfield label="%{getText('purgeConfig.description.label')}" name="description" size="100"/>
+            <s:checkbox label="%{getText('purgeConfig.enabled.label')}" name="enabled"/>
           </table>
           <s:hidden name="purgeConfigId"/>
           <s:hidden name="purgeType"/>
           <div class="functnbar3">
-            <c1:submitcancel value="%{getText('save')}" cancel="%{getText('cancel')}"/>
+            <s:submit value="%{getText('save')}" theme="simple"/>
+            <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
           </div>
         </c:when>
         <c:otherwise>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/installationsList.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/installationsList.jsp
index bafbe5d..3977147 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/installationsList.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/installationsList.jsp
@@ -19,7 +19,6 @@
 
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <%@ taglib uri="http://www.extremecomponents.org" prefix="ec" %>
 
 <html>
@@ -36,6 +35,7 @@
     <c:if test="${not empty installations}">
     <ec:table items="installations"
               var="installation"
+              autoIncludeParameters="false"
               showExports="false"
               showPagination="false"
               showStatusBar="false"
@@ -48,12 +48,12 @@
         <ec:column property="varValue" title="installation.value.label" style="white-space: nowrap" />
         
         <ec:column property="id" title="&nbsp;" width="1%">
-          <a href="editInstallation!edit.action?installation.installationId=<c:out value="${installation.installationId}"/>">
+          <a href="editInstallation.action?installation.installationId=<c:out value="${installation.installationId}"/>">
             <img src="<s:url value='/images/edit.gif' includeParams="none"/>" alt="<s:text name='edit'/>" title="<s:text name='edit'/>" border="0" />
           </a>  
         </ec:column>   
         <ec:column property="id" title="&nbsp;" width="1%">
-          <a href="deleteInstallation!delete.action?installation.installationId=<c:out value="${installation.installationId}"/>">
+          <a href="deleteInstallation.action?installation.installationId=<c:out value="${installation.installationId}"/>&installation.name=<c:out value="${installation.name}"/>">
             <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>             
@@ -61,7 +61,7 @@
     </ec:table>
     </c:if>
     <div class="functnbar3">
-      <s:form action="installationsTypeChoice!listTypes.action" method="post">
+      <s:form action="installationsTypeChoice.action" method="post">
         <s:submit value="%{getText('add')}"/>
       </s:form>
     </div>  
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/installationsTypeChoice.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/installationsTypeChoice.jsp
index 88a042a..5740df2 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/installationsTypeChoice.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/installationsTypeChoice.jsp
@@ -19,7 +19,6 @@
 
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <%@ taglib uri="http://www.extremecomponents.org" prefix="ec" %>
 
 <html>
@@ -32,7 +31,7 @@
     <h3>
       <s:text name="installationTypeChoice.section.title"/>
     </h3>  
-    <form action="editInstallation!input.action">
+    <form action="editInstallation_input.action">
       <div class="axial">
 
         <table>
@@ -42,7 +41,8 @@
           </tbody>
         </table>
         <div class="functnbar3">
-          <c1:submitcancel value="%{getText('add')}" cancel="%{getText('cancel')}"/>
+          <s:submit value="%{getText('add')}" theme="simple"/>
+          <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
         </div>        
       </div>
   
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/localRepositoriesList.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/localRepositoriesList.jsp
index 8ace08f..00808a6 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/localRepositoriesList.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/localRepositoriesList.jsp
@@ -38,6 +38,7 @@
         <s:set name="repositories" value="repositories" scope="request"/>
         <ec:table items="repositories"
                   var="repository"
+                  autoIncludeParameters="false"
                   showExports="false"
                   showPagination="false"
                   showStatusBar="false"
@@ -49,7 +50,7 @@
             <ec:column property="layout" title="repositories.table.layout"/>
             <ec:column property="editActions" title="&nbsp;" width="1%">
                 <s:url id="editRepositoryUrl" action="editRepository">
-                  <s:param name="repository.id">${pageScope.repository.id}</s:param>
+                  <s:param name="repository.id"><c:out value="${pageScope.repository.id}"/></s:param>
                 </s:url>
                 <c:choose>
                   <c:when test="${repository.name == 'DEFAULT'}">
@@ -65,7 +66,7 @@
               <c:choose>
                 <c:when test="${defaultPurgeMap[repositoryName]}">
                   <s:url id="purgeRepositoryUrl" action="purgeRepository">
-                    <s:param name="repository.id">${pageScope.repository.id}</s:param>
+                    <s:param name="repository.id"><c:out value="${pageScope.repository.id}"/></s:param>
                   </s:url>
                   <s:a href="%{purgeRepositoryUrl}"><img src="<s:url value='/images/purgenow.gif' includeParams="none"/>" alt="<s:text name='purge'/>" title="<s:text name='purge'/>" border="0" /></s:a>
                 </c:when>
@@ -75,8 +76,11 @@
               </c:choose>
             </ec:column>
             <ec:column property="deleteActions" title="&nbsp;" width="1%">
+                <s:token/>
                 <s:url id="removeRepositoryUrl" action="removeRepository">
-                  <s:param name="repository.id">${pageScope.repository.id}</s:param>
+                  <s:param name="repository.id"><c:out value="${pageScope.repository.id}"/></s:param>
+                  <s:param name="struts.token.name">token</s:param>
+                  <s:param name="token"><s:property value="token"/></s:param>
                 </s:url>
                 <c:choose>
                   <c:when test="${repository.name == 'DEFAULT'}">
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/parallelbuilds.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/parallelbuilds.jsp
new file mode 100644
index 0000000..04a7577
--- /dev/null
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/parallelbuilds.jsp
@@ -0,0 +1,77 @@
+<%--
+  ~ 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="http://www.extremecomponents.org" prefix="ec" %>
+<%@ taglib uri="http://plexus.codehaus.org/redback/taglib-1.0" prefix="redback" %>
+
+<html>
+  <s:i18n name="localization.Continuum">
+  <head>
+    <title><s:text name="parallel.build.queues.page.title"/></title>
+  </head>  
+  <body>
+    <div id="h3">  
+      <h3>
+        <s:text name="parallel.build.queues.section.title"/>
+      </h3>
+      
+      <c:if test="${not empty buildQueueList}">
+      <ec:table items="buildQueueList"
+              var="buildQueue"
+              autoIncludeParameters="false"
+              showExports="false"
+              showPagination="false"
+              showStatusBar="false"
+              sortable="false"
+              filterable="false">
+        <ec:row highlightRow="true">
+        <ec:column property="name" title="Name" style="white-space: nowrap" />
+           
+        <ec:column property="id" title="&nbsp;" width="1%">
+          <c:if test="${buildQueue.id != 1}">
+            <s:token/>
+            <s:url id="deleteBuildQueueUrl" action="deleteBuildQueue">
+              <s:param name="buildQueue.id"><c:out value="${pageScope.buildQueue.id}"/></s:param>
+              <s:param name="buildQueue.name"><c:out value="${pageScope.buildQueue.name}"/></s:param>
+              <s:param name="struts.token.name">token</s:param>
+              <s:param name="token"><s:property value="token"/></s:param>
+            </s:url>          
+            <s:a href="%{deleteBuildQueueUrl}">
+              <img src="<s:url value='/images/delete.gif' includeParams="none"/>" alt="<s:text name='delete'/>" title="<s:text name='delete'/>" border="0" />
+            </s:a>
+          </c:if>
+          <c:if test="${buildQueue.id == 1}">
+              <img src="<s:url value='/images/delete_disabled.gif' includeParams="none"/>" alt="<s:text name='delete'/>" title="<s:text name='delete'/>" border="0" />
+          </c:if>
+        </ec:column>             
+        </ec:row>
+        </ec:table>
+      </c:if>
+      
+       <div class="functnbar3">
+        <s:form action="addBuildQueue.action" method="post">
+          <s:submit value="%{getText('add')}"/>
+        </s:form>
+      </div> 
+    </div>
+  </body>
+  </s:i18n>
+</html>
\ No newline at end of file
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/profilesList.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/profilesList.jsp
index c872fde..be9e07c 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/profilesList.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/profilesList.jsp
@@ -44,6 +44,7 @@
     <c:if test="${not empty profiles}">
     <ec:table items="profiles"
               var="profile"
+              autoIncludeParameters="false"
               showExports="false"
               showPagination="false"
               showStatusBar="false"
@@ -53,34 +54,37 @@
         <ec:column property="name" title="profile.name.label" style="white-space: nowrap" />
         <ec:column property="Installations" title="profilesList.installations.label" style="white-space: nowrap">
           <ul>
-            <s:if test='profile.jdk != null'>
+            <c:if test="${profile.jdk != null}">
               <li><c:out value="${profile.jdk.name}"/> (<c:out value="${profile.jdk.type}"/>)</li>
-            </s:if>
-            <s:if test='profile.builder != null'>
+            </c:if>
+            <c:if test="${profile.builder != null}">
               <li><c:out value="${profile.builder.name}"/> (<c:out value="${profile.builder.type}"/>)</li>
-            </s:if>
-            <s:if test='profile.environmentVariables != null'>
+            </c:if>
+            <c:if test="${profile.environmentVariables != null}">
               <c:forEach var="envVar" items="${profile.environmentVariables}"> 
                 <li><c:out value="${envVar.name}" /></li>
               </c:forEach>
-            </s:if>
+            </c:if>
           </ul>
         </ec:column>
+        <c1:ifBuildTypeEnabled buildType="distributed">
+          <ec:column property="buildAgentGroup" title="profilesList.buildAgentGroup.label" style="white-space: nowrap" />
+        </c1:ifBuildTypeEnabled>                
         <ec:column property="id" title="&nbsp;" width="1%">
-          <a href="editBuildEnv!edit.action?profile.id=<c:out value="${pageScope.profile.id}"/>">
+          <a href="editBuildEnv.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" />
           </a>                    
         </ec:column>
         <ec:column property="id" title="&nbsp;" width="1%">
-          <a href="confirmDeleteBuildEnv!confirmDelete.action?profile.id=<c:out value="${pageScope.profile.id}"/>">
+          <a href="confirmDeleteBuildEnv.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>
     <div class="functnbar3">
-      <s:form action="addBuildEnv!input.action" method="post">
+      <s:form action="addBuildEnv.action" method="post">
         <s:submit value="%{getText('add')}"/>
       </s:form>
     </div>    
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/purgeConfigurationsList.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/purgeConfigurationsList.jsp
index 7181687..de4fd01 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/purgeConfigurationsList.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/purgeConfigurationsList.jsp
@@ -20,7 +20,6 @@
 <%@ taglib uri="/struts-tags" prefix="s" %>
 <%@ taglib uri="http://www.extremecomponents.org" prefix="ec" %>
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
-<%@ taglib uri="continuum" prefix="c1" %>
 <%@ taglib uri="http://plexus.codehaus.org/redback/taglib-1.0" prefix="redback" %>
 
 <html>
@@ -41,6 +40,7 @@
         <s:set name="repoPurgeConfigs" value="repoPurgeConfigs" scope="request"/>
         <ec:table items="repoPurgeConfigs"
                   var="repoPurge"
+                  autoIncludeParameters="false"
                   showExports="false"
                   showPagination="false"
                   showStatusBar="false"
@@ -50,12 +50,12 @@
             <ec:column property="repository.name" title="purgeConfigs.table.repository">
               <redback:ifAuthorized permission="continuum-manage-repositories">
                 <s:url id="editRepositoryUrl" action="editRepository" namespace="/admin" includeParams="none">
-                  <s:param name="repository.id">${pageScope.repoPurge.repository.id}</s:param>
+                  <s:param name="repository.id"><c:out value="${pageScope.repoPurge.repository.id}"/></s:param>
                 </s:url>
-                <s:a href="%{editRepositoryUrl}">${pageScope.repoPurge.repository.name}</s:a>
+                <s:a href="%{editRepositoryUrl}"><c:out value="${pageScope.repoPurge.repository.name}"/></s:a>
               </redback:ifAuthorized>
               <redback:elseAuthorized>
-                ${pageScope.repoPurge.repository.name}
+                <c:out value="${pageScope.repoPurge.repository.name}"/>
               </redback:elseAuthorized>
             </ec:column>
             <ec:column property="daysOlder" title="purgeConfigs.table.daysOlder"/>
@@ -68,19 +68,23 @@
             <ec:column property="description" title="purgeConfigs.table.description"/>
             <ec:column property="editActions" title="&nbsp;" width="1%">
                 <s:url id="editPurgeConfigUrl" action="editPurgeConfig">
-                  <s:param name="purgeConfigId">${pageScope.repoPurge.id}</s:param>
+                  <s:param name="purgeConfigId"><c:out value="${pageScope.repoPurge.id}"/></s:param>
                 </s:url>
                 <s:a href="%{editPurgeConfigUrl}"><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="purgeActions" title="&nbsp;" width="1%">
                 <s:url id="purgeUrl" action="doPurge">
-                  <s:param name="purgeConfigId">${pageScope.repoPurge.id}</s:param>
+                  <s:param name="purgeConfigId"><c:out value="${pageScope.repoPurge.id}"/></s:param>
                 </s:url>
                 <s:a href="%{purgeUrl}"><img src="<s:url value='/images/purgenow.gif' includeParams="none"/>" alt="<s:text name='purge'/>" title="<s:text name='purge'/>" border="0" /></s:a>
             </ec:column>
             <ec:column property="deleteActions" title="&nbsp;" width="1%">
+                <s:token/>
                 <s:url id="removePurgeConfigUrl" action="removePurgeConfig">
-                  <s:param name="purgeConfigId">${pageScope.repoPurge.id}</s:param>
+                  <s:param name="purgeConfigId"><c:out value="${pageScope.repoPurge.id}"/></s:param>
+                  <s:param name="description"><c:out value="${pageScope.repoPurge.description}"/></s:param>
+                  <s:param name="struts.token.name">token</s:param>
+                  <s:param name="token"><s:property value="token"/></s:param>
                 </s:url>
                 <s:a href="%{removePurgeConfigUrl}"><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>
@@ -90,7 +94,7 @@
       <div class="functnbar3">
         <s:form name="addRepoPurgeConfig" action="editPurgeConfig" method="post">
           <s:hidden name="purgeType" value="repository"/>
-          <s:submit value="%{getText('add')}"/>
+          <s:submit value="%{getText('add')}" theme="simple"/>
         </s:form>
       </div>
         
@@ -99,6 +103,7 @@
         <s:set name="dirPurgeConfigs" value="dirPurgeConfigs" scope="request"/>
         <ec:table items="dirPurgeConfigs"
                   var="dirPurge"
+                  autoIncludeParameters="false"
                   showExports="false"
                   showPagination="false"
                   showStatusBar="false"
@@ -115,19 +120,23 @@
             <ec:column property="description" title="purgeConfigs.table.description"/>
             <ec:column property="editActions" title="&nbsp;" width="1%">
                 <s:url id="editPurgeConfigUrl" action="editPurgeConfig">
-                  <s:param name="purgeConfigId">${pageScope.dirPurge.id}</s:param>
+                  <s:param name="purgeConfigId"><c:out value="${pageScope.dirPurge.id}"/></s:param>
                 </s:url>
                 <s:a href="%{editPurgeConfigUrl}"><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="purgeActions" title="&nbsp;" width="1%">
                 <s:url id="purgeUrl" action="doPurge">
-                  <s:param name="purgeConfigId">${pageScope.dirPurge.id}</s:param>
+                  <s:param name="purgeConfigId"><c:out value="${pageScope.dirPurge.id}"/></s:param>
                 </s:url>
                 <s:a href="%{purgeUrl}"><img src="<s:url value='/images/purgenow.gif' includeParams="none"/>" alt="<s:text name='purge'/>" title="<s:text name='purge'/>" border="0" /></s:a>
             </ec:column>
             <ec:column property="deleteActions" title="&nbsp;" width="1%">
+                <s:token/>
                 <s:url id="removePurgeConfigUrl" action="removePurgeConfig">
-                  <s:param name="purgeConfigId">${pageScope.dirPurge.id}</s:param>
+                  <s:param name="purgeConfigId"><c:out value="${pageScope.dirPurge.id}"/></s:param>
+                  <s:param name="description"><c:out value="${pageScope.dirPurge.description}"/></s:param>
+                  <s:param name="struts.token.name">token</s:param>
+                  <s:param name="token"><s:property value="token"/></s:param>
                 </s:url>
                 <s:a href="%{removePurgeConfigUrl}"><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>
@@ -137,7 +146,7 @@
       <div class="functnbar3">
         <s:form name="addDirPurgeConfig" action="editPurgeConfig" method="post">
           <s:hidden name="purgeType" value="directory"/>
-          <s:submit value="%{getText('add')}"/>
+          <s:submit value="%{getText('add')}" theme="simple"/>
         </s:form>
       </div>
     </body>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/viewBuildAgent.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/viewBuildAgent.jsp
index ed90ca3..713923a 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/viewBuildAgent.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/viewBuildAgent.jsp
@@ -20,7 +20,6 @@
 <%@ taglib uri="/struts-tags" prefix="s" %>
 <%@ taglib uri="http://www.extremecomponents.org" prefix="ec" %>
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
-<%@ taglib uri="continuum" prefix="c1" %>
 
 <html>
   <s:i18n name="localization.Continuum">
@@ -32,25 +31,35 @@
         <h3><s:text name="viewBuildAgent.section.title"/></h3>
         <div class="axial">
           <table border="1" cellspacing="2" cellpadding="3" width="100%">
-            <c1:data label="%{getText('buildAgent.url.label')}" name="buildAgent.url"/>
-            <c1:data label="%{getText('buildAgent.description.label')}" name="buildAgent.description"/>
-            <c1:data label="%{getText('buildAgent.enabled.label')}" name="buildAgent.enabled"/>
+            <tr class="b">
+              <th><label class="label"><s:text name='buildAgent.url.label'/>:</label></th>
+              <td><s:property value="buildAgent.url"/></td>
+            </tr>
+            <tr class="b">
+              <th><label class="label"><s:text name='buildAgent.description.label'/>:</label></th>
+              <td><s:property value="buildAgent.description"/></td>
+            </tr>
+            <tr class="b">
+              <th><label class="label"><s:text name='buildAgent.enabled.label'/>:</label></th>
+              <td><s:property value="buildAgent.enabled"/></td>
+            </tr>
           </table>
         </div>
         
         <h3><s:text name="viewBuildAgent.installations.title"/></h3>
         <ec:table items="installations"
 				  var="installation"
+          autoIncludeParameters="false"
                   showExports="false"
                   showPagination="false"
                   showStatusBar="false"
                   sortable="false"
                   filterable="false">
           <ec:row highlightRow="true">
-            <ec:column property="name" title="Name" style="white-space: nowrap" />
-            <ec:column property="type" title="Type" style="white-space: nowrap" />
-            <ec:column property="varName" title="Env Var Name" style="white-space: nowrap" />
-            <ec:column property="varValue" title="Value/Path" style="white-space: nowrap" />
+            <ec:column property="name" title="viewBuildAgent.installations.name" style="white-space: nowrap" />
+            <ec:column property="type" title="viewBuildAgent.installations.type" style="white-space: nowrap" />
+            <ec:column property="varName" title="viewBuildAgent.installations.varName" style="white-space: nowrap" />
+            <ec:column property="varValue" title="viewBuildAgent.installations.varValue" style="white-space: nowrap" />
           </ec:row>
         </ec:table>        	
       </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/viewDistributedBuilds.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/viewDistributedBuilds.jsp
index d991519..2922d24 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/viewDistributedBuilds.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/admin/viewDistributedBuilds.jsp
@@ -26,65 +26,69 @@
   <s:i18n name="localization.Continuum">
     <head>
       <title><s:text name="distributedBuilds.page.title"/></title>
+      <meta http-equiv="refresh" content="60"/>
     </head>
     <body>
-      <s:form id="removeForm" action="none" method="post">
+      <c:if test="${!empty actionErrors}">
+        <div class="errormessage">
+          <s:iterator value="actionErrors">
+            <p><s:text name="<s:property/>" /></p>
+          </s:iterator>
+        </div>
+      </c:if>
+      
+      
         <div id="h3">
-          <h3><s:text name="distributedBuilds.section.title"/></h3>
-          <c:if test="${!empty actionErrors}">
-            <div class="errormessage">
-              <s:iterator value="actionErrors">
-                <p><s:text name="<s:property/>" /></p>
-              </s:iterator>
-            </div>
-          </c:if>
-          <c:if test="${not empty distributedBuildSummary}">
-            <s:set name="distributedBuildSummary" value="distributedBuildSummary" scope="request"/>
-            <ec:table items="distributedBuildSummary"
-                      var="distributedBuild"
+          <h3><s:text name="distributedBuilds.currentBuild.section.title"/></h3>
+          <c:if test="${not empty currentDistributedBuilds}">
+            <s:set name="currentDistributedBuilds" value="currentDistributedBuilds" scope="request"/>
+            <ec:table items="currentDistributedBuilds"
+                      var="currentBuild"
+                      autoIncludeParameters="false"
                       showExports="false"
                       showPagination="false"
                       showStatusBar="false"
                       sortable="false"
                       filterable="false">
               <ec:row>
+                <ec:column property="projectUrl" title="distributedBuild.table.projectName">
+                  <s:url id="viewUrl" action="buildResults">
+                    <s:param name="projectId"><c:out value="${pageScope.currentBuild.projectId}"/></s:param>
+                  </s:url>
+                  <s:a href="%{viewUrl}"><c:out value="${pageScope.currentBuild.projectName}"/></s:a>
+                </ec:column>
+                <ec:column property="buildDefinitionLabel" title="distributedBuild.table.buildDefinitionLabel"/>
                 <ec:column property="projectGroupName" title="distributedBuild.table.projectGroupName"/>
-                <ec:column property="scmRootAddress" title="distributedBuild.table.scmRootAddress"/>
-                <ec:column property="url" title="distributedBuild.table.agentUrl"/>
+                <ec:column property="buildAgentUrl" title="distributedBuild.table.buildAgentUrl"/>
                 <ec:column property="cancelEntry" title="&nbsp;" width="1%">
-                  <c:choose>
-                    <c:when test="${pageScope.distributedBuild.cancelEnabled}">
-                      <s:url id="cancelUrl" action="cancelDistributedBuild" method="cancelDistributedBuild" namespace="/">
-                        <s:param name="projectGroupId">${pageScope.distributedBuild.projectGroupId}</s:param>
-                        <s:param name="scmRootAddress">${pageScope.distributedBuild.scmRootAddress}</s:param>
-                        <s:param name="buildAgentUrl">${pageScope.distributedBuild.url}</s:param>
-                      </s:url>
-                      <redback:ifAuthorized permission="continuum-manage-queues">
-                        <s:a href="%{cancelUrl}"><img src="<s:url value='/images/cancelbuild.gif' includeParams="none"/>" alt="<s:text name='cancel'/>" title="<s:text name='cancel'/>" border="0"></s:a>
-                      </redback:ifAuthorized>
-                      <redback:elseAuthorized>
-                        <img src="<s:url value='/images/cancelbuild_disabled.gif' includeParams="none"/>" alt="<s:text name='cancel'/>" title="<s:text name='cancel'/>" border="0">
-                      </redback:elseAuthorized>
-                    </c:when>
-                    <c:otherwise>
-                      <img src="<s:url value='/images/cancelbuild_disabled.gif' includeParams="none"/>" alt="<s:text name='cancel'/>" title="<s:text name='cancel'/>" border="0">
-                    </c:otherwise>
-                  </c:choose>
+                  <s:url id="cancelUrl" action="cancelDistributedBuild" namespace="/">
+                    <s:param name="buildAgentUrl"><c:out value="${pageScope.currentBuild.buildAgentUrl}"/></s:param>
+                  </s:url>
+                  <redback:ifAuthorized permission="continuum-manage-queues">
+                    <s:a href="%{cancelUrl}"><img src="<s:url value='/images/cancelbuild.gif' includeParams="none"/>" alt="<s:text name='cancel'/>" title="<s:text name='cancel'/>" border="0"></s:a>
+                  </redback:ifAuthorized>
+                  <redback:elseAuthorized>
+                    <img src="<s:url value='/images/cancelbuild_disabled.gif' includeParams="none"/>" alt="<s:text name='cancel'/>" title="<s:text name='cancel'/>" border="0">
+                  </redback:elseAuthorized>
                 </ec:column>
               </ec:row>
             </ec:table>
           </c:if>
-          <c:if test="${empty distributedBuildSummary}">
-            <s:text name="distributedBuilds.empty"/>
+          <c:if test="${empty currentDistributedBuilds}">
+            <s:text name="distributedBuilds.no.currentTasks"/>
           </c:if>
         </div>
+      
+      <s:form id="removeBuildForm" action="removeDistributedBuildEntries.action" method="post" theme="simple">
         <div id="h3">
           <h3>
             <s:text name="distributedBuilds.buildQueue.section.title"/>
           </h3>
           <c:if test="${not empty distributedBuildQueues}">
+            <s:set name="distributedBuildQueues" value="distributedBuildQueues" scope="request"/>
             <ec:table items="distributedBuildQueues"
-                      var="distributedBuildQueue"
+                      autoIncludeParameters="false"
+                      var="buildQueue"
                       showExports="false"
                       showPagination="false"
                       showStatusBar="false"
@@ -92,17 +96,25 @@
                       filterable="false">
               <ec:row>
                 <redback:ifAuthorized permission="continuum-manage-queues">
-                  <ec:column alias="selectedDistributedBuildTaskHashCodes" title="&nbsp;" style="width:5px" filterable="false" sortable="false" width="1%" headerCell="selectAll">
-                    <input type="checkbox" name="selectedDistributedBuildTaskHashCodes" value="${pageScope.distributedBuildQueue.hashCode}" />
+                  <ec:column alias="selectedBuildTaskHashCodes" title=" " style="width:5px" filterable="false" sortable="false" headerCell="selectAll">
+                    <input type="checkbox" name="selectedBuildTaskHashCodes" value="${pageScope.buildQueue.hashCode}" />
                   </ec:column>              
                 </redback:ifAuthorized>
+                <ec:column property="projectUrl" title="distributedBuild.table.projectName">
+                  <s:url id="viewUrl" action="buildResults">
+                    <s:param name="projectId"><c:out value="${pageScope.buildQueue.projectId}"/></s:param>
+                  </s:url>
+                  <s:a href="%{viewUrl}"><c:out value="${pageScope.buildQueue.projectName}"/></s:a>
+                </ec:column>
+                <ec:column property="buildDefinitionLabel" title="distributedBuild.table.buildDefinitionLabel"/>
                 <ec:column property="projectGroupName" title="distributedBuild.table.projectGroupName"/>
-                <ec:column property="scmRootAddress" title="distributedBuild.table.scmRootAddress"/>
+                <ec:column property="buildAgentUrl" title="distributedBuild.table.buildAgentUrl"/>
                 <ec:column property="cancelEntry" title="&nbsp;" width="1%">
                   <redback:ifAuthorized permission="continuum-manage-queues">
-                    <s:url id="cancelUrl" action="removeDistributedBuildEntry" method="removeDistributedBuildEntry" namespace="/">
-                      <s:param name="projectGroupId">${pageScope.distributedBuildQueue.projectGroupId}</s:param>
-                      <s:param name="scmRootAddress">${pageScope.distributedBuildQueue.scmRootAddress}</s:param>
+                    <s:url id="cancelUrl" action="removeDistributedBuildEntry" namespace="/">
+                      <s:param name="projectId"><c:out value="${pageScope.buildQueue.projectId}"/></s:param>
+                      <s:param name="buildDefinitionId"><c:out value="${pageScope.buildQueue.buildDefinitionId}"/></s:param>
+                      <s:param name="buildAgentUrl"><c:out value="${pageScope.buildQueue.buildAgentUrl}"/></s:param>
                     </s:url>
                     <s:a href="%{cancelUrl}"><img src="<s:url value='/images/cancelbuild.gif' includeParams="none"/>" alt="<s:text name='cancel'/>" title="<s:text name='cancel'/>" border="0"></s:a>
                   </redback:ifAuthorized>
@@ -120,15 +132,112 @@
               <tbody>
                 <tr>
                   <td>
-                    <input type="submit" value="<s:text name="distributedBuilds.removeEntries"/>"
-                           onclick="$('removeForm').action='removeDistributedBuildEntries!removeDistributedBuildEntries.action';$('removeForm').submit();" /> 
+                    <input type="button" name="remove-build-queues" value="<s:text name="distributedBuilds.removeEntries"/>" onclick="document.forms.removeBuildForm.submit();" /> 
                   </td>
                 </tr>
               </tbody>
             </table>
           </div>
         </c:if>
+        <c:if test="${empty distributedBuildQueues}">
+          <s:text name="distributedBuilds.empty"/>
+        </c:if>
       </s:form>
+      
+        <div id="h3">
+          <h3><s:text name="distributedBuilds.currentPrepareBuild.section.title"/></h3>
+          <c:if test="${not empty currentDistributedPrepareBuilds}">
+            <s:set name="currentDistributedPrepareBuilds" value="currentDistributedPrepareBuilds" scope="request"/>
+            <ec:table items="currentDistributedPrepareBuilds"
+                      var="currentPrepareBuild"
+                      autoIncludeParameters="false"
+                      showExports="false"
+                      showPagination="false"
+                      showStatusBar="false"
+                      sortable="false"
+                      filterable="false">
+              <ec:row>
+                <ec:column property="projectGroupUrl" title="distributedPrepareBuild.table.projectGroupName">
+                  <s:url id="viewUrl" action="projectGroupSummary">
+                    <s:param name="projectGroupId"><c:out value="${pageScope.currentPrepareBuild.projectGroupId}"/></s:param>
+                  </s:url>
+                  <s:a href="%{viewUrl}"><c:out value="${pageScope.currentPrepareBuild.projectGroupName}"/></s:a>
+                </ec:column>
+                <ec:column property="scmRootAddress" title="distributedPrepareBuild.table.scmRootAddress"/>
+                <ec:column property="buildAgentUrl" title="distributedPrepareBuild.table.buildAgentUrl"/>
+              </ec:row>
+            </ec:table>
+          </c:if>
+          <c:if test="${empty currentDistributedPrepareBuilds}">
+            <s:text name="distributedPrepareBuilds.no.currentTasks"/>
+          </c:if>
+        </div>
+      
+      
+      <s:form id="removePrepareBuildForm" action="removeDistributedPrepareBuildEntries.action" method="post" theme="simple">
+        <div id="h3">
+          <h3>
+            <s:text name="distributedBuilds.prepareBuildQueue.section.title"/>
+          </h3>
+          <c:if test="${not empty distributedPrepareBuildQueues}">
+            <s:set name="distributedPrepareBuildQueues" value="distributedPrepareBuildQueues" scope="request"/>
+            <ec:table items="distributedPrepareBuildQueues"
+                      var="prepareBuildQueue"
+                      autoIncludeParameters="false"
+                      showExports="false"
+                      showPagination="false"
+                      showStatusBar="false"
+                      sortable="false"
+                      filterable="false">
+              <ec:row>
+                <redback:ifAuthorized permission="continuum-manage-queues">
+                  <ec:column alias="selectedPrepareBuildTaskHashCodes" title="&nbsp;" style="width:5px" filterable="false" sortable="false" width="1%" headerCell="selectAll">
+                    <input type="checkbox" name="selectedPrepareBuildTaskHashCodes" value="${pageScope.prepareBuildQueue.hashCode}" />
+                  </ec:column>              
+                </redback:ifAuthorized>
+                <ec:column property="projectGroupUrl" title="distributedPrepareBuild.table.projectGroupName">
+                  <s:url id="viewUrl" action="projectGroupSummary">
+                    <s:param name="projectGroupId"><c:out value="${pageScope.prepareBuildQueue.projectGroupId}"/></s:param>
+                  </s:url>
+                  <s:a href="%{viewUrl}"><c:out value="${pageScope.prepareBuildQueue.projectGroupName}"/></s:a>
+                </ec:column>
+                <ec:column property="scmRootAddress" title="distributedPrepareBuild.table.scmRootAddress"/>
+                <ec:column property="buildAgentUrl" title="distributedPrepareBuild.table.buildAgentUrl"/>
+                <ec:column property="cancelEntry" title="&nbsp;" width="1%">
+                  <redback:ifAuthorized permission="continuum-manage-queues">
+                    <s:url id="cancelUrl" action="removeDistributedPrepareBuildEntry" namespace="/">
+                      <s:param name="projectGroupId"><c:out value="${pageScope.prepareBuildQueue.projectGroupId}"/></s:param>
+                      <s:param name="scmRootId"><c:out value="${pageScope.prepareBuildQueue.scmRootId}"/></s:param>
+                      <s:param name="buildAgentUrl"><c:out value="${pageScope.prepareBuildQueue.buildAgentUrl}"/></s:param>
+                    </s:url>
+                    <s:a href="%{cancelUrl}"><img src="<s:url value='/images/cancelbuild.gif' includeParams="none"/>" alt="<s:text name='cancel'/>" title="<s:text name='cancel'/>" border="0"></s:a>
+                  </redback:ifAuthorized>
+                  <redback:elseAuthorized>
+                    <img src="<s:url value='/images/cancelbuild_disabled.gif' includeParams="none"/>" alt="<s:text name='cancel'/>" title="<s:text name='cancel'/>" border="0">
+                  </redback:elseAuthorized>
+                </ec:column>
+              </ec:row>
+            </ec:table>
+          </c:if>
+        </div>
+        <c:if test="${not empty distributedPrepareBuildQueues}">
+          <div class="functnbar3">
+            <table>
+              <tbody>
+                <tr>
+                  <td>
+                    <input type="button" name="remove-prepare-build-queues" value="<s:text name="distributedPrepareBuilds.removeEntries"/>" onclick="document.forms.removePrepareBuildForm.submit();" /> 
+                  </td>
+                </tr>
+              </tbody>
+            </table>
+          </div>
+        </c:if>
+        <c:if test="${empty distributedPrepareBuildQueues}">
+          <s:text name="distributedPrepareBuilds.empty"/>
+        </c:if>
+      </s:form>
+      
     </body>
   </s:i18n>
-</html>
\ No newline at end of file
+</html>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/buildDefinitionEdit.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/buildDefinitionEdit.jsp
index 51729ab..dbc2db6 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/buildDefinitionEdit.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/buildDefinitionEdit.jsp
@@ -19,7 +19,6 @@
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
-<%@ taglib uri="continuum" prefix="c1" %>
 <html>
   <s:i18n name="localization.Continuum">
     <head>
@@ -30,7 +29,7 @@
         <h3><s:text name="buildDefinition.section.title"/></h3>
 
         <div class="axial">
-          <s:form action="saveBuildDefinition" method="get">
+          <s:form action="saveBuildDefinition" method="post">
             <c:choose>
             
               <c:when test="${!empty actionErrors}">
@@ -45,51 +44,58 @@
               <c:when test="${empty actionErrors}">
                 <table>
                   <tbody>
-                    <s:if test="executor == 'ant'">
-                      <s:textfield label="%{getText('buildDefinition.buildFile.ant.label')}" name="buildFile"  required="true"/>
+                    <s:if test="executor == 'ant' or buildDefinitionType == 'ant'">
+                      <s:textfield label="%{getText('buildDefinition.buildFile.ant.label')}" name="buildFile"  requiredLabel="true" size="100"/>
                     </s:if>
-                    <s:elseif test="executor == 'shell'">
-                      <s:textfield label="%{getText('buildDefinition.buildFile.shell.label')}" name="buildFile" required="true"/>
+                    <s:elseif test="executor == 'shell' or buildDefinitionType == 'shell'">
+                      <s:textfield label="%{getText('buildDefinition.buildFile.shell.label')}" name="buildFile" requiredLabel="true" size="100"/>
                     </s:elseif>
                     <s:else>
-                      <s:textfield label="%{getText('buildDefinition.buildFile.maven.label')}" name="buildFile" required="true"/>
+                      <s:textfield label="%{getText('buildDefinition.buildFile.maven.label')}" name="buildFile" requiredLabel="true" size="100"/>
                     </s:else>
     
-                    <s:if test="executor == 'ant'">
-                      <s:textfield label="%{getText('buildDefinition.goals.ant.label')}" name="goals"/>
+                    <s:if test="executor == 'ant' or buildDefinitionType == 'ant'">
+                      <s:textfield label="%{getText('buildDefinition.goals.ant.label')}" name="goals" size="100"/>
                     </s:if>
-                    <s:elseif test="executor == 'shell'">
+                    <s:elseif test="executor == 'shell' or buildDefinitionType == 'shell'">
                     </s:elseif>
                     <s:else>
-                      <s:textfield label="%{getText('buildDefinition.goals.maven.label')}" name="goals"/>
+                      <s:textfield label="%{getText('buildDefinition.goals.maven.label')}" name="goals" requiredLabel="true" size="100"/>
                     </s:else>
     
-                    <s:textfield label="%{getText('buildDefinition.arguments.label')}" name="arguments"/>
-                    <s:checkbox label="%{getText('buildDefinition.buildFresh.label')}" name="buildFresh" value="buildFresh" fieldValue="true"/>
-                    <s:checkbox label="%{getText('buildDefinition.alwaysBuild.label')}" name="alwaysBuild" />
+                    <s:textfield label="%{getText('buildDefinition.arguments.label')}" name="arguments" size="100"/>
+                    <s:checkbox label="%{getText('buildDefinition.buildFresh.label')}" id="buildFresh" name="buildFresh" value="buildFresh" fieldValue="true"/>
+                    <s:checkbox label="%{getText('buildDefinition.alwaysBuild.label')}" id="alwaysBuild" name="alwaysBuild" value="alwaysBuild" fieldValue="true"/>
                     <c:choose>
                     <c:when test="${defaultBuildDefinition == true}">
                       <s:label label="%{getText('buildDefinition.defaultForProject.label')}" value="true"/>
                     </c:when>
                     <c:otherwise>
-                      <s:checkbox label="%{getText('buildDefinition.defaultForProject.label')}"  name="defaultBuildDefinition" value="defaultBuildDefinition" fieldValue="true"/>
+                      <s:checkbox label="%{getText('buildDefinition.defaultForProject.label')}" name="defaultBuildDefinition" value="defaultBuildDefinition" fieldValue="true"/>
                     </c:otherwise>
                     </c:choose>
                     <s:select label="%{getText('buildDefinition.schedule.label')}" name="scheduleId" list="schedules"/>
                     <s:select label="%{getText('buildDefinition.profile.label')}" name="profileId" list="profiles" listValue="name"
                                listKey="id" headerKey="-1" headerValue=""/>
                     <s:select label="%{getText('buildDefinition.type.label')}" name="buildDefinitionType" list="buildDefinitionTypes"/>
-                    <s:textfield label="%{getText('buildDefinition.description.label')}" name="description" />
+                    <s:if test="executor != 'ant' && executor != 'shell'">
+                        <s:select label="%{getText('buildDefinition.updatePolicy.label')}" name="updatePolicy" list="buildDefinitionUpdatePolicies"/>
+                    </s:if>
+                    <s:textfield label="%{getText('buildDefinition.description.label')}" name="description" size="100" />
                   </tbody>
                 </table>
                 <div class="functnbar3">
-                  <c1:submitcancel value="%{getText('save')}" cancel="%{getText('cancel')}"/>
+                  <s:submit value="%{getText('save')}" theme="simple"/>
+                  <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
                 </div>
 
                 <s:hidden name="buildDefinitionId"/>
                 <s:hidden name="projectId"/>
                 <s:hidden name="projectGroupId"/>
                 <s:hidden name="groupBuildDefinition"/>
+                <c:if test="${groupBuildView == true}">
+                  <s:hidden name="groupBuildView" value="true"/>
+                </c:if>
                 <c:choose>
                 <c:when test="${defaultBuildDefinition == true}">
                   <s:hidden name="defaultBuildDefinition" value="true"/>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/buildResult.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/buildResult.jsp
index abdd5f7..e33af20 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/buildResult.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/buildResult.jsp
@@ -22,6 +22,7 @@
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
 <%@ taglib prefix="c1" uri="continuum" %>
 <%@ taglib uri="http://plexus.codehaus.org/redback/taglib-1.0" prefix="redback" %>
+
 <html>
   <s:i18n name="localization.Continuum">
     <head>
@@ -40,32 +41,47 @@
 
         <div class="axial">
           <table border="1" cellspacing="2" cellpadding="3" width="100%">
-            <c1:data label="%{getText('buildResult.startTime')}">
-                <s:param name="after"><c1:date name="buildResult.startTime"/></s:param>
-            </c1:data>
-            <c1:data label="%{getText('buildResult.endTime')}">
-                <s:param name="after"><c1:date name="buildResult.endTime"/></s:param>
-            </c1:data>
-            <c1:data label="%{getText('buildResult.duration')}">
-                <s:param name="after">
-                    <s:if test="buildResult.endTime == 0"><s:text name="buildResult.startedSince"/></s:if> <s:property value="buildResult.durationTime"/></s:param>
-            </c1:data>
-            <c1:data label="%{getText('buildResult.trigger')}">
-                <s:param name="after"><s:text name="buildResult.trigger.%{buildResult.trigger}"/></s:param>
-            </c1:data>
-            <c1:data label="%{getText('buildResult.state')}">
-                <s:param name="after" value="state"/>
-            </c1:data>
-            <c1:data label="%{getText('buildResult.buildNumber')}">
-                <s:param name="after">
-                    <s:if test="buildResult.buildNumber != 0">
-                        <s:property value="buildResult.buildNumber"/>
-                    </s:if>
-                    <s:else>
-                        &nbsp;
-                    </s:else>
-                </s:param>
-            </c1:data>
+            <tr class="b">
+              <th><label class="label"><s:text name='buildResult.startTime'/>:</label></th>
+              <td><c1:date name="buildResult.startTime"/></td>
+            </tr>
+            <tr class="b">
+              <th><label class="label"><s:text name='buildResult.endTime'/>:</label></th>
+              <td><c1:date name="buildResult.endTime"/></td>
+            </tr>
+            <tr class="b">
+              <th><label class="label"><s:text name='buildResult.duration'/>:</label></th>
+              <td><s:if test="buildResult.endTime == 0"><s:text name="buildResult.startedSince"/></s:if> <s:property value="buildResult.durationTime"/></td>
+            </tr>
+            <tr class="b">
+              <th><label class="label"><s:text name='buildResult.trigger'/>:</label></th>
+              <td><s:text name="buildResult.trigger.%{buildResult.trigger}"/></td>
+            </tr>
+            <tr class="b">
+              <th><label class="label"><s:text name='buildResult.state'/>:</label></th>
+              <td>${state}</td>
+            </tr>
+            <tr class="b">
+              <th><label class="label"><s:text name='buildResult.buildNumber'/>:</label></th>
+              <td>
+                <s:if test="buildResult.buildNumber != 0">
+                  <s:property value="buildResult.buildNumber"/>
+                </s:if>
+                <s:else>
+                  &nbsp;
+                </s:else>
+              </td>
+            </tr>
+            <tr class="b">
+              <th><label class="label"><s:text name='buildResult.username'/>:</label></th>
+              <td><s:property value="buildResult.username"/></td>
+            </tr>
+            <c:if test="${!empty buildResult.buildUrl}">
+              <tr class="b">
+                <th><label class="label"><s:text name='buildResult.buildUrl'/>:</label></th>
+                <td><s:property value="buildResult.buildUrl"/></td>
+              </tr>
+            </c:if>
           </table>
         </div>
         <div class="functnbar3">
@@ -77,6 +93,7 @@
                   <form action="removeBuildResult.action">
                     <input type="hidden" name="projectId" value="<s:property value="projectId"/>"/>
                     <input type="hidden" name="buildId" value="<s:property value="buildId"/>"/>
+                    <s:token/>
                     <s:if test="canDelete">
                       <input type="submit" name="delete-project" value="<s:text name="delete"/>"/>
                     </s:if>
@@ -95,6 +112,7 @@
         <s:if test="buildResult.scmResult.changes != null && buildResult.scmResult.changes.size() > 0">
             <s:set name="changes" value="buildResult.scmResult.changes" scope="request"/>
             <ec:table items="changes"
+                      autoIncludeParameters="false"
                       var="change"
                       showExports="false"
                       showPagination="false"
@@ -121,6 +139,7 @@
             <h4><s:text name="buildResult.changesSinceLastSuccess"/></h4>
             <s:set name="changes" value="changesSinceLastSuccess" scope="request"/>
             <ec:table items="changes"
+                      autoIncludeParameters="false"
                       var="change"
                       showExports="false"
                       showPagination="false"
@@ -145,6 +164,7 @@
             <s:set name="dependencies" value="buildResult.modifiedDependencies" scope="request"/>
             <ec:table items="dependencies"
                       var="dep"
+                      autoIncludeParameters="false"
                       showExports="false"
                       showPagination="false"
                       showStatusBar="false"
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/buildResults.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/buildResults.jsp
index e29b2bb..0f9200d 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/buildResults.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/buildResults.jsp
@@ -21,6 +21,7 @@
 <%@ taglib uri="http://www.extremecomponents.org" prefix="ec" %>
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
 <%@ taglib uri="http://plexus.codehaus.org/redback/taglib-1.0" prefix="redback" %>
+
 <html>
   <s:i18n name="localization.Continuum">
     <head>
@@ -39,12 +40,23 @@
                 <s:param><s:property value="project.name"/></s:param>
             </s:text>
         </h3>
+        
+        <c:if test="${!empty actionErrors}">
+          <div class="errormessage">
+            <s:iterator value="actionErrors">
+              <p><s:property/></p>
+            </s:iterator>
+          </div>
+        </c:if>
+    
         <form id="buildResultsForm" action="removeBuildResults.action" method="post">
+          <s:token/>
+          <s:set name="buildResults" value="buildResults" scope="request"/>
           <s:hidden name="projectGroupId"/>
           <s:hidden name="projectId"/>
-          <s:set name="buildResults" value="buildResults" scope="request"/>
           <ec:table items="buildResults"
                     var="buildResult"
+                    autoIncludeParameters="false"
                     showExports="false"
                     showPagination="false"
                     showStatusBar="false"
@@ -57,19 +69,19 @@
                 </ec:column>
               </redback:ifAuthorized>
               <ec:column property="buildNumberIfNotZero" title="buildResults.buildNumber">
-                  <s:if test="pageScope.buildResult.state == 2">
-                      <c:out value="${pageScope.buildResult.buildNumber}"/>
-                  </s:if>
+                  <c:if test="${pageScope.buildResult.state == 2}">
+                    <c:out value="${pageScope.buildResult.buildNumber}"/>
+                  </c:if>
               </ec:column>
               <ec:column property="startTime" title="buildResults.startTime" cell="date"/>
               <ec:column property="endTime" title="buildResults.endTime" cell="date"/>
               <ec:column property="duration" title="&nbsp;">
                 <c:choose>
                   <c:when test="${buildResult.endTime gt 0}">
-                    <s:text name="buildResults.duration"/> : ${buildResult.durationTime}
+                    <s:text name="buildResults.duration"/> : <c:out value="${buildResult.durationTime}"/>
                   </c:when>
                   <c:otherwise>
-                    <s:text name="buildResults.startedSince"/> : ${buildResult.elapsedTime}
+                    <s:text name="buildResults.startedSince"/> : <c:out value="${buildResult.elapsedTime}"/>
                   </c:otherwise>
                 </c:choose>
               </ec:column>
@@ -77,10 +89,10 @@
               <ec:column property="buildDefinition.description" title="buildResults.buildDefinition.description" />
               <ec:column property="actions" title="&nbsp;">
                 <s:url id="buildResultUrl" action="buildResult">
-                  <s:param name="projectId">${projectId}</s:param>
-                  <s:param name="projectName">${projectName}</s:param>
-                  <s:param name="buildId">${buildResult.id}</s:param>
-                  <s:param name="projectGroupId">${projectGroupId}</s:param>
+                  <s:param name="projectId"><c:out value="${projectId}"/></s:param>
+                  <s:param name="projectName"><c:out value="${projectName}"/></s:param>
+                  <s:param name="buildId"><c:out value="${buildResult.id}"/></s:param>
+                  <s:param name="projectGroupId"><c:out value="${projectGroupId}"/></s:param>
                 </s:url>
                 <s:a href="%{buildResultUrl}"><s:text name="buildResults.result"/></s:a>
               </ec:column>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/buildDefinitionGroupSummaryComponent.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/buildDefinitionGroupSummaryComponent.jsp
index 5caa7cb..eb42e06 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/buildDefinitionGroupSummaryComponent.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/buildDefinitionGroupSummaryComponent.jsp
@@ -20,15 +20,15 @@
 <%@ taglib uri="/struts-tags" prefix="s" %>
 <%@ taglib uri="http://www.extremecomponents.org" prefix="ec" %>
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
-<%@ taglib uri="continuum" prefix="c1" %>
 <%@ taglib uri="http://plexus.codehaus.org/redback/taglib-1.0" prefix="redback" %>
 
 <s:i18n name="localization.Continuum">
 
-  <h3><s:text name="buildDefinitionSummary.projectGroup.section.title"><s:param>${projectGroup.name}</s:param></s:text></h3>
+  <h3><s:text name="buildDefinitionSummary.projectGroup.section.title"><s:param><c:out value="${projectGroup.name}"/></s:param></s:text></h3>
   <c:if test="${not empty groupBuildDefinitionSummaries}">
   <ec:table items="groupBuildDefinitionSummaries"
             var="buildDefinitionSummary"
+            autoIncludeParameters="false"
             showExports="false"
             showPagination="false"
             showStatusBar="false"
@@ -41,19 +41,19 @@
       <ec:column property="scheduleName" title="projectView.buildDefinition.schedule">
         <redback:ifAuthorized permission="continuum-manage-schedules">
           <s:url id="scheduleUrl" action="schedule" namespace="/" includeParams="none">
-            <s:param name="id">${pageScope.buildDefinitionSummary.scheduleId}</s:param>
+            <s:param name="id"><c:out value="${pageScope.buildDefinitionSummary.scheduleId}"/></s:param>
           </s:url>
-          <s:a href="%{scheduleUrl}">${pageScope.buildDefinitionSummary.scheduleName}</s:a>
+          <s:a href="%{scheduleUrl}"><c:out value="${pageScope.buildDefinitionSummary.scheduleName}"/></s:a>
         </redback:ifAuthorized>
         <redback:elseAuthorized>
-          ${pageScope.buildDefinitionSummary.scheduleName}
+          <c:out value="${pageScope.buildDefinitionSummary.scheduleName}"/>
         </redback:elseAuthorized>
       </ec:column>
       <ec:column property="profileName" title="projectView.buildDefinition.profile">
-        <s:url id="profileUrl" action="editBuildEnv!edit.action" namespace="/" includeParams="none">
-          <s:param name="profile.id">${pageScope.buildDefinitionSummary.profileId}</s:param>
+        <s:url id="profileUrl" action="editBuildEnv.action" namespace="/" includeParams="none">
+          <s:param name="profile.id"><c:out value="${pageScope.buildDefinitionSummary.profileId}"/></s:param>
         </s:url>
-        <s:a href="%{profileUrl}">${pageScope.buildDefinitionSummary.profileName}</s:a>
+        <s:a href="%{profileUrl}"><c:out value="${pageScope.buildDefinitionSummary.profileName}"/></s:a>
       </ec:column>      
       <ec:column property="from" title="projectView.buildDefinition.from"/>
       <ec:column property="isBuildFresh" title="projectView.buildDefinition.buildFresh"/>
@@ -64,8 +64,9 @@
       <ec:column property="buildAction" title="&nbsp;" width="1%">
         <redback:ifAuthorized permission="continuum-build-group" resource="${projectGroupName}">
           <s:url id="buildUrl" action="buildProject" namespace="/">
-            <s:param name="projectGroupId">${pageScope.buildDefinitionSummary.projectGroupId}</s:param>
-            <s:param name="buildDefinitionId">${pageScope.buildDefinitionSummary.id}</s:param>
+            <s:param name="projectGroupId"><c:out value="${pageScope.buildDefinitionSummary.projectGroupId}"/></s:param>
+            <s:param name="buildDefinitionId"><c:out value="${pageScope.buildDefinitionSummary.id}"/></s:param>
+            <s:param name="fromGroupPage" value="true"/>
           </s:url>
           <s:a href="%{buildUrl}"><img src="<s:url value='/images/buildnow.gif' includeParams="none"/>" alt="<s:text name='build'/>" title="<s:text name='build'/>" border="0"></s:a>
         </redback:ifAuthorized>
@@ -76,9 +77,9 @@
       <ec:column property="editActions" title="&nbsp;" width="1%">
         <center>
         <redback:ifAuthorized permission="continuum-modify-group" resource="${projectGroupName}">
-          <s:url id="editUrl" action="buildDefinition" method="input" namespace="/" includeParams="none">
-            <s:param name="projectGroupId">${pageScope.buildDefinitionSummary.projectGroupId}</s:param>
-            <s:param name="buildDefinitionId">${pageScope.buildDefinitionSummary.id}</s:param>
+          <s:url id="editUrl" action="buildDefinition" namespace="/" includeParams="none">
+            <s:param name="projectGroupId"><c:out value="${pageScope.buildDefinitionSummary.projectGroupId}"/></s:param>
+            <s:param name="buildDefinitionId"><c:out value="${pageScope.buildDefinitionSummary.id}"/></s:param>
           </s:url>
           <s:a href="%{editUrl}">
               <img src="<s:url value='/images/edit.gif' includeParams="none"/>" alt="<s:text name='edit'/>" title="<s:text name='edit'/>" border="0">
@@ -96,11 +97,14 @@
           <c:when test="${pageScope.buildDefinitionSummary.isDefault == true}">
             <img src="<s:url value='/images/delete_disabled.gif' includeParams="none"/>" alt="<s:text name='delete'/>" title="<s:text name='delete'/>" border="0">
           </c:when>
-          <c:otherwise>${pageScope.buildDefinitionSummary.isDefault}
+          <c:otherwise>
+            <s:token/>
             <s:url id="removeUrl" action="removeGroupBuildDefinition" namespace="/">
-              <s:param name="projectGroupId">${pageScope.buildDefinitionSummary.projectGroupId}</s:param>
-              <s:param name="buildDefinitionId">${pageScope.buildDefinitionSummary.id}</s:param>
+              <s:param name="projectGroupId"><c:out value="${pageScope.buildDefinitionSummary.projectGroupId}"/></s:param>
+              <s:param name="buildDefinitionId"><c:out value="${pageScope.buildDefinitionSummary.id}"/></s:param>
               <s:param name="confirmed" value="false"/>
+              <s:param name="struts.token.name">token</s:param>
+              <s:param name="token"><s:property value="token"/></s:param> 
             </s:url>
             <s:a href="%{removeUrl}">
               <img src="<s:url value='/images/delete.gif' includeParams="none"/>" alt="<s:text name='delete'/>" title="<s:text name='delete'/>" border="0">
@@ -120,27 +124,28 @@
     <div class="functnbar3">
       <s:form action="buildDefinition" method="post">
         <input type="hidden" name="projectGroupId" value="<s:property value="projectGroupId"/>"/>
-        <s:submit value="%{getText('add')}"/>
+        <s:submit value="%{getText('add')}" theme="simple"/>
       </s:form>
     </div>
   </redback:ifAuthorized>
 
   <c:if test="${not empty projectBuildDefinitionSummaries}">
-  <h3>Project Build Definitions</h3>
+  <h3><s:text name="buildDefinitionSummary.project.section.title"/></h3>
 
   <ec:table items="projectBuildDefinitionSummaries"
             var="buildDefinitionSummary"
+            autoIncludeParameters="false"
             showExports="false"
             showPagination="false"
             showStatusBar="false"
             filterable="false"
             sortable="false">
     <ec:row>
-      <ec:column property="projectName" title="Project">
+      <ec:column property="projectName" title="buildDefinitionSummary.project">
         <s:url id="projectUrl" action="projectView" namespace="/" includeParams="none">
-          <s:param name="projectId">${pageScope.buildDefinitionSummary.projectId}</s:param>
+          <s:param name="projectId"><c:out value="${pageScope.buildDefinitionSummary.projectId}"/></s:param>
         </s:url>
-        <s:a href="%{projectUrl}">${pageScope.buildDefinitionSummary.projectName}</s:a>
+        <s:a href="%{projectUrl}"><c:out value="${pageScope.buildDefinitionSummary.projectName}"/></s:a>
       </ec:column>
       <ec:column property="goals" title="projectView.buildDefinition.goals"/>
       <ec:column property="arguments" title="projectView.buildDefinition.arguments"/>
@@ -148,19 +153,19 @@
       <ec:column property="scheduleName" title="projectView.buildDefinition.schedule">
         <redback:ifAuthorized permission="continuum-manage-schedules">
           <s:url id="scheduleUrl" action="schedule" namespace="/" includeParams="none">
-            <s:param name="id">${pageScope.buildDefinitionSummary.scheduleId}</s:param>
+            <s:param name="id"><c:out value="${pageScope.buildDefinitionSummary.scheduleId}"/></s:param>
           </s:url>
-          <s:a href="%{scheduleUrl}">${pageScope.buildDefinitionSummary.scheduleName}</s:a>
+          <s:a href="%{scheduleUrl}"><c:out value="${pageScope.buildDefinitionSummary.scheduleName}"/></s:a>
         </redback:ifAuthorized>
         <redback:elseAuthorized>
-          ${pageScope.buildDefinitionSummary.scheduleName}
+          <c:out value="${pageScope.buildDefinitionSummary.scheduleName}"/>
         </redback:elseAuthorized>
       </ec:column>
       <ec:column property="profileName" title="projectView.buildDefinition.profile">
-        <s:url id="profileUrl" action="editBuildEnv!edit.action" namespace="/" includeParams="none">
-          <s:param name="profile.id">${pageScope.buildDefinitionSummary.profileId}</s:param>
+        <s:url id="profileUrl" action="editBuildEnv.action" namespace="/" includeParams="none">
+          <s:param name="profile.id"><c:out value="${pageScope.buildDefinitionSummary.profileId}"/></s:param>
         </s:url>
-        <s:a href="%{profileUrl}">${pageScope.buildDefinitionSummary.profileName}</s:a>
+        <s:a href="%{profileUrl}"><c:out value="${pageScope.buildDefinitionSummary.profileName}"/></s:a>
       </ec:column>      
       <ec:column property="from" title="projectView.buildDefinition.from"/>
       <ec:column property="isBuildFresh" title="projectView.buildDefinition.buildFresh"/>
@@ -171,8 +176,8 @@
       <ec:column property="buildNowAction" title="&nbsp;" width="1%">
         <redback:ifAuthorized permission="continuum-build-group" resource="${projectGroupName}">
           <s:url id="buildProjectUrl" action="buildProject" namespace="/" includeParams="none">
-            <s:param name="projectId">${pageScope.buildDefinitionSummary.projectId}</s:param>
-            <s:param name="buildDefinitionId">${pageScope.buildDefinitionSummary.id}</s:param>
+            <s:param name="projectId"><c:out value="${pageScope.buildDefinitionSummary.projectId}"/></s:param>
+            <s:param name="buildDefinitionId"><c:out value="${pageScope.buildDefinitionSummary.id}"/></s:param>
           </s:url>
           <s:a href="%{buildProjectUrl}">
             <img src="<s:url value='/images/buildnow.gif' includeParams="none"/>" alt="<s:text name='build'/>" title="<s:text name='build'/>" border="0">
@@ -184,9 +189,11 @@
       </ec:column>
       <ec:column property="editAction" title="&nbsp;" width="1%">
         <redback:ifAuthorized permission="continuum-modify-group" resource="${projectGroupName}">
-          <s:url id="editUrl" action="buildDefinition" method="input" namespace="/">
-            <s:param name="projectId">${pageScope.buildDefinitionSummary.projectId}</s:param>
-            <s:param name="buildDefinitionId">${pageScope.buildDefinitionSummary.id}</s:param>
+          <s:url id="editUrl" action="buildDefinition" namespace="/">
+            <s:param name="projectId"><c:out value="${pageScope.buildDefinitionSummary.projectId}"/></s:param>
+            <s:param name="buildDefinitionId"><c:out value="${pageScope.buildDefinitionSummary.id}"/></s:param>
+            <s:param name="groupBuildView" value="true"/>
+            <s:param name="projectGroupId"><c:out value="${pageScope.buildDefinitionSummary.projectGroupId}"/></s:param>
           </s:url>
           <s:a href="%{editUrl}">
               <img src="<s:url value='/images/edit.gif' includeParams="none"/>" alt="<s:text name='edit'/>" title="<s:text name='edit'/>" border="0">
@@ -198,10 +205,13 @@
       </ec:column>
       <ec:column property="removeAction" title="&nbsp;" width="1%">
         <redback:ifAuthorized permission="continuum-modify-group" resource="${projectGroupName}">
+          <s:token/>
           <s:url id="removeUrl" action="removeProjectBuildDefinition" namespace="/">
-            <s:param name="projectId">${pageScope.buildDefinitionSummary.projectId}</s:param>
-            <s:param name="buildDefinitionId">${pageScope.buildDefinitionSummary.id}</s:param>
+            <s:param name="projectId"><c:out value="${pageScope.buildDefinitionSummary.projectId}"/></s:param>
+            <s:param name="buildDefinitionId"><c:out value="${pageScope.buildDefinitionSummary.id}"/></s:param>
             <s:param name="confirmed" value="false"/>
+            <s:param name="struts.token.name">token</s:param>
+            <s:param name="token"><s:property value="token"/></s:param>
           </s:url>
           <s:a href="%{removeUrl}">
               <img src="<s:url value='/images/delete.gif' includeParams="none"/>" alt="<s:text name='delete'/>" title="<s:text name='delete'/>" border="0">
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/buildDefinitionSummaryComponent.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/buildDefinitionSummaryComponent.jsp
index 01f8fb4..f1d1d58 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/buildDefinitionSummaryComponent.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/buildDefinitionSummaryComponent.jsp
@@ -20,12 +20,12 @@
 <%@ taglib uri="/struts-tags" prefix="s" %>
 <%@ taglib uri="http://www.extremecomponents.org" prefix="ec" %>
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
-<%@ taglib uri="continuum" prefix="c1" %>
 <%@ taglib uri="http://plexus.codehaus.org/redback/taglib-1.0" prefix="redback" %>
 
 <s:i18n name="localization.Continuum">
   <ec:table items="allBuildDefinitionSummaries"
             var="buildDefinitionSummary"
+            autoIncludeParameters="false"
             showExports="false"
             showPagination="false"
             showStatusBar="false"
@@ -38,12 +38,12 @@
       <ec:column property="scheduleName" title="projectView.buildDefinition.schedule">
         <redback:ifAuthorized permission="continuum-manage-schedules">
           <s:url id="scheduleUrl" action="schedule" namespace="/" includeParams="none">
-            <s:param name="id">${pageScope.buildDefinitionSummary.scheduleId}</s:param>
+            <s:param name="id"><c:out value="${pageScope.buildDefinitionSummary.scheduleId}"/></s:param>
           </s:url>
-          <s:a href="%{scheduleUrl}">${pageScope.buildDefinitionSummary.scheduleName}</s:a>
+          <s:a href="%{scheduleUrl}"><c:out value="${pageScope.buildDefinitionSummary.scheduleName}"/></s:a>
         </redback:ifAuthorized>
         <redback:elseAuthorized>
-          ${pageScope.buildDefinitionSummary.scheduleName}
+          <c:out value="${pageScope.buildDefinitionSummary.scheduleName}"/>
         </redback:elseAuthorized>
       </ec:column>
       <ec:column property="profileName" title="projectView.buildDefinition.profile"/>
@@ -55,8 +55,8 @@
       <ec:column property="buildAction" title="&nbsp;" width="1%">
         <redback:ifAuthorized permission="continuum-build-group" resource="${projectGroupName}">
           <s:url id="buildProjectUrl" action="buildProject" namespace="/">
-            <s:param name="projectId">${projectId}</s:param>
-            <s:param name="buildDefinitionId">${pageScope.buildDefinitionSummary.id}</s:param>
+            <s:param name="projectId"><c:out value="${projectId}"/></s:param>
+            <s:param name="buildDefinitionId"><c:out value="${pageScope.buildDefinitionSummary.id}"/></s:param>
             <s:param name="fromProjectPage" value="true"/>
           </s:url>
           <s:a href="%{buildProjectUrl}"><img src="<s:url value='/images/buildnow.gif' includeParams="none"/>" alt="<s:text name='build'/>" title="<s:text name='build'/>" border="0"></s:a>
@@ -67,61 +67,79 @@
       </ec:column>
       <ec:column property="editAction" title="&nbsp;" width="1%">
         <%-- if the from is PROJECT then render the links differently --%>
-        <s:if test="pageScope.buildDefinitionSummary.from == 'PROJECT'">
-          <redback:ifAuthorized permission="continuum-modify-project-build-definition" resource="${projectGroupName}">
-            <s:url id="editUrl" action="buildDefinition" method="input" namespace="/">
-              <s:param name="projectId">${projectId}</s:param>
-              <s:param name="buildDefinitionId">${pageScope.buildDefinitionSummary.id}</s:param>
-            </s:url>
-            <s:a href="%{editUrl}"><img src="<s:url value='/images/edit.gif' includeParams="none"/>" alt="<s:text name='edit'/>" title="<s:text name='edit'/>" border="0"></s:a>
-          </redback:ifAuthorized>
-          <redback:elseAuthorized>
-            <img src="<s:url value='/images/edit_disabled.gif' includeParams="none"/>" alt="<s:text name='edit'/>" title="<s:text name='edit'/>" border="0" />
-          </redback:elseAuthorized>
-        </s:if>
-        <s:else>
-          <redback:ifAuthorized permission="continuum-modify-group-build-definition" resource="${projectGroupName}">
-            <s:url id="editUrl" action="buildDefinition" method="input" namespace="/">
-              <s:param name="projectGroupId">${pageScope.buildDefinitionSummary.projectGroupId}</s:param>
-              <s:param name="buildDefinitionId">${pageScope.buildDefinitionSummary.id}</s:param>
-              <s:param name="groupBuildDefinition">true</s:param>
-            </s:url>
-            <s:a href="%{editUrl}"><img src="<s:url value='/images/edit.gif' includeParams="none"/>" alt="<s:text name='edit'/>" title="<s:text name='edit'/>" border="0"></s:a>
-          </redback:ifAuthorized>
-          <redback:elseAuthorized>
-            <img src="<s:url value='/images/edit_disabled.gif' includeParams="none"/>" alt="<s:text name='edit'/>" title="<s:text name='edit'/>" border="0" />
-          </redback:elseAuthorized>
-        </s:else>
+        <c:choose>
+          <c:when test="${pageScope.buildDefinitionSummary.from=='PROJECT'}">
+            <redback:ifAuthorized permission="continuum-modify-project-build-definition" resource="${projectGroupName}">
+              <s:url id="editUrl" action="buildDefinition" namespace="/">
+                <s:param name="projectId"><c:out value="${projectId}"/></s:param>
+                <s:param name="buildDefinitionId"><c:out value="${pageScope.buildDefinitionSummary.id}"/></s:param>
+              </s:url>
+              <s:a href="%{editUrl}"><img src="<s:url value='/images/edit.gif' includeParams="none"/>" alt="<s:text name='edit'/>" title="<s:text name='edit'/>" border="0"></s:a>
+            </redback:ifAuthorized>
+            <redback:elseAuthorized>
+              <img src="<s:url value='/images/edit_disabled.gif' includeParams="none"/>" alt="<s:text name='edit'/>" title="<s:text name='edit'/>" border="0" />
+            </redback:elseAuthorized>
+          </c:when>
+          <c:otherwise>
+            <redback:ifAuthorized permission="continuum-modify-group-build-definition" resource="${projectGroupName}">
+              <s:url id="editUrl" action="buildDefinition" namespace="/">
+                <s:param name="projectGroupId"><c:out value="${pageScope.buildDefinitionSummary.projectGroupId}"/></s:param>
+                <s:param name="buildDefinitionId"><c:out value="${pageScope.buildDefinitionSummary.id}"/></s:param>
+                <s:param name="groupBuildDefinition">true</s:param>
+              </s:url>
+              <s:a href="%{editUrl}"><img src="<s:url value='/images/edit.gif' includeParams="none"/>" alt="<s:text name='edit'/>" title="<s:text name='edit'/>" border="0"></s:a>
+            </redback:ifAuthorized>
+            <redback:elseAuthorized>
+              <img src="<s:url value='/images/edit_disabled.gif' includeParams="none"/>" alt="<s:text name='edit'/>" title="<s:text name='edit'/>" border="0" />
+            </redback:elseAuthorized>
+          </c:otherwise>
+        </c:choose>
       </ec:column>
       <ec:column property="deleteAction" title="&nbsp;" width="1%">
         <%-- if the from is PROJECT then render the links differently --%>
-        <s:if test="pageScope.buildDefinitionSummary.from == 'PROJECT'">
-          <redback:ifAuthorized permission="continuum-remove-project-build-definition" resource="${projectGroupName}">
-            <s:url id="removeUrl" action="removeProjectBuildDefinition" namespace="/">
-              <s:param name="projectId">${projectId}</s:param>
-              <s:param name="buildDefinitionId">${pageScope.buildDefinitionSummary.id}</s:param>
-              <s:param name="confirmed" value="false"/>
-            </s:url>
-            <s:a href="%{removeUrl}"><img src="<s:url value='/images/delete.gif' includeParams="none"/>" alt="<s:text name='delete'/>" title="<s:text name='delete'/>" border="0"></s:a>
-          </redback:ifAuthorized>
-          <redback:elseAuthorized>
-            <img src="<s:url value='/images/delete_disabled.gif' includeParams="none"/>" alt="<s:text name='delete'/>" title="<s:text name='delete'/>" border="0" />
-          </redback:elseAuthorized>
-        </s:if>
-        <s:else>
-          <redback:ifAuthorized permission="continuum-remove-group-build-definition" resource="${projectGroupName}">
-            <s:url id="removeUrl" action="removeGroupBuildDefinition" namespace="/">
-              <s:param name="projectGroupId">${pageScope.buildDefinitionSummary.projectGroupId}</s:param>
-              <s:param name="buildDefinitionId">${pageScope.buildDefinitionSummary.id}</s:param>
-              <s:param name="groupBuildDefinition">true</s:param>
-              <s:param name="confirmed" value="false"/>
-            </s:url>
-            <s:a href="%{removeUrl}"><img src="<s:url value='/images/delete.gif' includeParams="none"/>" alt="<s:text name='delete'/>" title="<s:text name='delete'/>" border="0"></s:a>
-          </redback:ifAuthorized>
-          <redback:elseAuthorized>
-            <img src="<s:url value='/images/delete_disabled.gif' includeParams="none"/>" alt="<s:text name='delete'/>" title="<s:text name='delete'/>" border="0" />
-          </redback:elseAuthorized>
-        </s:else>
+         <c:choose>
+          <c:when test="${pageScope.buildDefinitionSummary.from=='PROJECT'}">
+            <redback:ifAuthorized permission="continuum-remove-project-build-definition" resource="${projectGroupName}">
+              <s:token/>
+              <s:url id="removeUrl" action="removeProjectBuildDefinition" namespace="/">
+                <s:param name="projectId"><c:out value="${projectId}"/></s:param>
+                <s:param name="buildDefinitionId"><c:out value="${pageScope.buildDefinitionSummary.id}"/></s:param>
+                <s:param name="confirmed" value="false"/>
+                <s:param name="struts.token.name">token</s:param>
+                <s:param name="token"><s:property value="token"/></s:param>
+              </s:url>
+              <s:set id="removeId">remove-build-definition-${pageScope.buildDefinitionSummary.id}</s:set>
+              <s:a href="%{removeUrl}" id="%{removeId}"><img src="<s:url value='/images/delete.gif' includeParams="none"/>" alt="<s:text name='delete'/>" title="<s:text name='delete'/>" border="0"></s:a>
+            </redback:ifAuthorized>
+            <redback:elseAuthorized>
+              <img src="<s:url value='/images/delete_disabled.gif' includeParams="none"/>" alt="<s:text name='delete'/>" title="<s:text name='delete'/>" border="0" />
+            </redback:elseAuthorized>
+          </c:when>
+          <c:otherwise>
+            <redback:ifAuthorized permission="continuum-remove-group-build-definition" resource="${projectGroupName}">
+              <c:choose>              
+                <c:when test="${buildDefinitionSummary.id == defaultGroupDefinitionId || buildDefinitionSummary.isDefault}">                
+                  <img src="<s:url value='/images/delete_disabled.gif' includeParams="none"/>" alt="<s:text name='delete'/>" title="<s:text name='delete'/>" border="0" />
+                </c:when>
+                <c:otherwise>
+                  <s:token/>
+                  <s:url id="removeUrl" action="removeGroupBuildDefinition" namespace="/">
+                    <s:param name="projectGroupId"><c:out value="${pageScope.buildDefinitionSummary.projectGroupId}"/></s:param>
+                    <s:param name="buildDefinitionId"><c:out value="${pageScope.buildDefinitionSummary.id}"/></s:param>
+                    <s:param name="groupBuildDefinition">true</s:param>
+                    <s:param name="confirmed" value="false"/>
+                    <s:param name="struts.token.name">token</s:param>
+                    <s:param name="token"><s:property value="token"/></s:param>
+                  </s:url>
+                  <s:a href="%{removeUrl}"><img src="<s:url value='/images/delete.gif' includeParams="none"/>" alt="<s:text name='delete'/>" title="<s:text name='delete'/>" border="0"></s:a>
+                </c:otherwise>
+              </c:choose>
+            </redback:ifAuthorized>
+            <redback:elseAuthorized>
+              <img src="<s:url value='/images/delete_disabled.gif' includeParams="none"/>" alt="<s:text name='delete'/>" title="<s:text name='delete'/>" border="0" />
+            </redback:elseAuthorized>
+          </c:otherwise>
+        </c:choose>
       </ec:column>
     </ec:row>
   </ec:table>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/companyLogo.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/companyLogo.jsp
index 983595b..4f115d6 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/companyLogo.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/companyLogo.jsp
@@ -19,17 +19,20 @@
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
+
 <s:set name="companyLogo" value="companyLogo"/>
 <c:if test="${!empty (companyLogo)}">
+  <s:set name="companyName" value="companyName"/>
   <s:set name="companyUrl" value="companyUrl"/>
   <c:choose>
     <c:when test="${!empty (companyUrl)}">
-      <a href="${companyUrl}">
-        <img src="${companyLogo}" title="${companyName}" border="0" alt=""/>
+      <a href="${fn:escapeXml(companyUrl)}">
+        <img src="${fn:escapeXml(companyLogo)}" title="${fn:escapeXml(companyName)}" border="0" alt="${fn:escapeXml(companyName)}"/>
       </a>
     </c:when>
     <c:otherwise>
-      <img src="${companyLogo}" title="${companyName}" border="0" alt=""/>
+      <img src="${fn:escapeXml(companyLogo)}" title="${fn:escapeXml(companyName)}" border="0" alt="${fn:escapeXml(companyName)}"/>
     </c:otherwise>
   </c:choose>
 </c:if>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/failureComponent.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/failureComponent.jsp
index 102a37c..eec50ef 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/failureComponent.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/failureComponent.jsp
@@ -20,7 +20,6 @@
 <%@ taglib uri="/struts-tags" prefix="s" %>
 <%@ taglib uri="http://www.extremecomponents.org" prefix="ec" %>
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
-<%@ taglib uri="continuum" prefix="c1" %>
 <s:i18n name="localization.Continuum">
 
   <div class="axial">
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/projectGroupNotifierSummaryComponent.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/projectGroupNotifierSummaryComponent.jsp
index 6e807d3..e1091f2 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/projectGroupNotifierSummaryComponent.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/projectGroupNotifierSummaryComponent.jsp
@@ -20,14 +20,14 @@
 <%@ taglib uri="/struts-tags" prefix="s" %>
 <%@ taglib uri="http://www.extremecomponents.org" prefix="ec" %>
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
-<%@ taglib uri="continuum" prefix="c1" %>
 <%@ taglib uri="http://plexus.codehaus.org/redback/taglib-1.0" prefix="redback" %>
 <s:i18n name="localization.Continuum">
 
-  <h3><s:text name="projectGroupNotifierSummaryComponent.groupNotifiers"><s:param>${projectGroup.name}</s:param></s:text></h3>
+  <h3><s:text name="projectGroupNotifierSummaryComponent.groupNotifiers"><s:param><c:out value="${projectGroup.name}"/></s:param></s:text></h3>
   <c:if test="${not empty projectGroupNotifierSummaries}">
   <ec:table items="projectGroupNotifierSummaries"
             var="projectGroupNotifierSummary"
+            autoIncludeParameters="false"
             showExports="false"
             showPagination="false"
             showStatusBar="false"
@@ -41,9 +41,9 @@
       <ec:column property="editActions" title="&nbsp;" width="1%">
         <redback:ifAuthorized permission="continuum-modify-group" resource="${projectGroup.name}">
           <s:url id="editUrl" action="editProjectGroupNotifier" namespace="/">
-            <s:param name="projectGroupId">${pageScope.projectGroupNotifierSummary.projectGroupId}</s:param>
-            <s:param name="notifierId">${pageScope.projectGroupNotifierSummary.id}</s:param>
-            <s:param name="notifierType">${pageScope.projectGroupNotifierSummary.type}</s:param>
+            <s:param name="projectGroupId"><c:out value="${pageScope.projectGroupNotifierSummary.projectGroupId}"/></s:param>
+            <s:param name="notifierId"><c:out value="${pageScope.projectGroupNotifierSummary.id}"/></s:param>
+            <s:param name="notifierType"><c:out value="${pageScope.projectGroupNotifierSummary.type}"/></s:param>
           </s:url>
           <s:a href="%{editUrl}">
             <img src="<s:url value='/images/edit.gif' includeParams="none"/>" alt="<s:text name="edit"/>" title="<s:text name="edit"/>" border="0">
@@ -55,11 +55,10 @@
       </ec:column>    
       <ec:column property="deleteActions" title="&nbsp;" width="1%">
         <redback:ifAuthorized permission="continuum-modify-group" resource="${projectGroup.name}">
-          <s:url id="removeUrl" action="deleteProjectGroupNotifier!default.action" namespace="/">
-            <s:param name="projectGroupId">${pageScope.projectGroupNotifierSummary.projectGroupId}</s:param>
-            <s:param name="notifierId">${pageScope.projectGroupNotifierSummary.id}</s:param>
-            <s:param name="notifierType">${pageScope.projectGroupNotifierSummary.type}</s:param>
-            <s:param name="confirmed" value="false"/>
+          <s:url id="removeUrl" action="deleteProjectGroupNotifier_default.action" namespace="/">
+            <s:param name="projectGroupId"><c:out value="${pageScope.projectGroupNotifierSummary.projectGroupId}"/></s:param>
+            <s:param name="notifierId"><c:out value="${pageScope.projectGroupNotifierSummary.id}"/></s:param>
+            <s:param name="notifierType"><c:out value="${pageScope.projectGroupNotifierSummary.type}"/></s:param>
           </s:url>
         <s:a href="%{removeUrl}">
           <img src="<s:url value='/images/delete.gif' includeParams="none"/>" alt="<s:text name="delete"/>" title="<s:text name="delete"/>" border="0">
@@ -78,7 +77,7 @@
       <s:url id="addUrl" action="addProjectGroupNotifier" namespace="/"  includeContext="false" includeParams="none" />
       <s:form action="%{addUrl}" method="post">
         <input type="hidden" name="projectGroupId" value="<s:property value="projectGroupId"/>"/>
-        <s:submit value="%{getText('add')}"/>
+        <s:submit value="%{getText('add')}" theme="simple"/>
         </s:form>
     </div>
   </redback:ifAuthorized>
@@ -87,6 +86,7 @@
     <h3><s:text name="projectGroupNotifierSummaryComponent.projectNotifiers"/></h3>
     <ec:table items="projectNotifierSummaries"
               var="projectNotifierSummary"
+              autoIncludeParameters="false"
               showExports="false"
               showPagination="false"
               showStatusBar="false"
@@ -95,9 +95,9 @@
       <ec:row>
         <ec:column property="projectName" title="projectView.project.name">
           <s:url id="projectUrl" action="projectView" namespace="/" includeParams="none">
-            <s:param name="projectId">${pageScope.projectNotifierSummary.projectId}</s:param>
+            <s:param name="projectId"><c:out value="${pageScope.projectNotifierSummary.projectId}"/></s:param>
           </s:url>
-        <s:a href="%{projectUrl}">${pageScope.projectNotifierSummary.projectName}</s:a>
+        <s:a href="%{projectUrl}"><c:out value="${pageScope.projectNotifierSummary.projectName}"/></s:a>
         </ec:column>
         <ec:column property="type" title="projectView.notifier.type"/>
         <ec:column property="recipient" title="projectView.notifier.recipient"/>
@@ -108,10 +108,10 @@
             <c:choose>
               <c:when test="${!pageScope.projectNotifierSummary.fromProject}">
                 <s:url id="editUrl" action="editProjectNotifier" namespace="/" includeParams="none">
-                  <s:param name="projectGroupId">${pageScope.projectNotifierSummary.projectGroupId}</s:param>
-                  <s:param name="projectId">${pageScope.projectNotifierSummary.projectId}</s:param>
-                  <s:param name="notifierId">${pageScope.projectNotifierSummary.id}</s:param>
-                  <s:param name="notifierType">${pageScope.projectNotifierSummary.type}</s:param>
+                  <s:param name="projectGroupId"><c:out value="${pageScope.projectNotifierSummary.projectGroupId}"/></s:param>
+                  <s:param name="projectId"><c:out value="${pageScope.projectNotifierSummary.projectId}"/></s:param>
+                  <s:param name="notifierId"><c:out value="${pageScope.projectNotifierSummary.id}"/></s:param>
+                  <s:param name="notifierType"><c:out value="${pageScope.projectNotifierSummary.type}"/></s:param>
                   <s:param name="fromGroupPage" value="true"/>
                 </s:url>
                 <s:a href="%{editUrl}">
@@ -131,11 +131,10 @@
           <redback:ifAuthorized permission="continuum-modify-group" resource="${projectGroup.name}">
             <c:choose>
               <c:when test="${!pageScope.projectNotifierSummary.fromProject}">
-                <s:url id="removeUrl" action="deleteProjectNotifier" namespace="/">
-                  <s:param name="projectGroupId">${pageScope.projectNotifierSummary.projectGroupId}</s:param>
-                  <s:param name="projectId">${pageScope.projectNotifierSummary.projectId}</s:param>
-                  <s:param name="notifierId">${pageScope.projectNotifierSummary.id}</s:param>
-                  <s:param name="confirmed" value="false"/>
+                <s:url id="removeUrl" action="deleteProjectNotifier_default.action" namespace="/">
+                  <s:param name="projectGroupId"><c:out value="${pageScope.projectNotifierSummary.projectGroupId}"/></s:param>
+                  <s:param name="projectId"><c:out value="${pageScope.projectNotifierSummary.projectId}"/></s:param>
+                  <s:param name="notifierId"><c:out value="${pageScope.projectNotifierSummary.id}"/></s:param>
                   <s:param name="fromGroupPage" value="true"/>
                 </s:url>
                 <s:a href="%{removeUrl}">
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/projectGroupTabComponent.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/projectGroupTabComponent.jsp
index 9eb383d..d554fed 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/projectGroupTabComponent.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/projectGroupTabComponent.jsp
@@ -20,7 +20,6 @@
 <%@ taglib uri="/struts-tags" prefix="s" %>
 <%@ taglib uri="http://www.extremecomponents.org" prefix="ec" %>
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
-<%@ taglib uri="continuum" prefix="c1" %>
 
 <s:i18n name="localization.Continuum">
 
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/projectNotifierSummaryComponent.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/projectNotifierSummaryComponent.jsp
index 7d27940..8be98f6 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/projectNotifierSummaryComponent.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/projectNotifierSummaryComponent.jsp
@@ -20,7 +20,6 @@
 <%@ taglib uri="/struts-tags" prefix="s" %>
 <%@ taglib uri="http://www.extremecomponents.org" prefix="ec" %>
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
-<%@ taglib uri="continuum" prefix="c1" %>
 <%@ taglib uri="http://plexus.codehaus.org/redback/taglib-1.0" prefix="redback" %>
 <s:i18n name="localization.Continuum">
 
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/projectSummaryComponent.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/projectSummaryComponent.jsp
index 3a0e6e5..cb84a03 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/projectSummaryComponent.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/components/projectSummaryComponent.jsp
@@ -20,7 +20,6 @@
 <%@ taglib uri="/struts-tags" prefix="s" %>
 <%@ taglib uri="http://www.extremecomponents.org" prefix="ec" %>
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c' %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <%@ taglib uri="http://plexus.codehaus.org/redback/taglib-1.0" prefix="redback" %>
 
 <s:i18n name="localization.Continuum">
@@ -30,11 +29,11 @@
   <table>
     <tr>
       <td>
-          <s:text name="projectGroup.buildsStatut.success"/> : ${groupSummary.numSuccesses}
+          <s:text name="projectGroup.buildsStatut.success"/> : <c:out value="${groupSummary.numSuccesses}"/>
           &nbsp;<img src="<s:url value='/images/icon_success_sml.gif' includeParams="none"/>" alt="<s:text name="projectGroup.buildsStatut.success"/>">
-          &nbsp; <s:text name="projectGroup.buildsStatut.errors"/> : ${groupSummary.numErrors}
+          &nbsp; <s:text name="projectGroup.buildsStatut.errors"/> : <c:out value="${groupSummary.numErrors}"/>
           &nbsp;<img src="<s:url value='/images/icon_error_sml.gif' includeParams="none"/>" alt="<s:text name="projectGroup.buildsStatut.errors"/>">
-          &nbsp; <s:text name="projectGroup.buildsStatut.failures"/> : ${groupSummary.numFailures}
+          &nbsp; <s:text name="projectGroup.buildsStatut.failures"/> : <c:out value="${groupSummary.numFailures}"/>
           &nbsp;<img src="<s:url value='/images/icon_warning_sml.gif' includeParams="none"/>" alt="<s:text name="projectGroup.buildsStatut.failures"/>">
       <td>      
     </tr>
@@ -44,10 +43,11 @@
 
   <form id="projectsForm" action="ProjectsList.action" method="post">
     <input type="hidden" name="methodToCall" value="" />
-    <input type="hidden" name="projectGroupId" value="${projectGroupId}" />
     <input type="hidden" name="buildDefinitionId" value="-1" />
+    <input type="hidden" name="projectGroupId" value="${projectGroupId}" />
   <ec:table items="projects"
             var="project"
+            autoIncludeParameters="false"
             showExports="false"
             showPagination="false"
             showStatusBar="false"
@@ -69,9 +69,9 @@
       <ec:column property="state" title="&nbsp;" width="1%" cell="org.apache.maven.continuum.web.view.StateCell"/>
       <ec:column property="name" title="summary.projectTable.name" width="50%">
         <s:url id="projectUrl" action="projectView" namespace="/" includeParams="none">
-          <s:param name="projectId">${project.id}</s:param>
+          <s:param name="projectId"><c:out value="${project.id}"/></s:param>
         </s:url>
-        <s:a href="%{projectUrl}">${pageScope.project.name}</s:a>
+        <s:a href="%{projectUrl}"><c:out value="${pageScope.project.name}"/></s:a>
       </ec:column>
       <ec:column property="version" title="summary.projectTable.version" width="12%"/>
       <ec:column property="buildNumber" title="summary.projectTable.build" width="2%" style="text-align: center">
@@ -79,19 +79,19 @@
           <c:when test="${project.buildNumber gt 0 && project.buildInSuccessId gt 0}">
             <redback:ifAuthorized permission="continuum-view-group" resource="${projectGroupName}">
               <s:url id="buildResult" action="buildResult">
-                <s:param name="projecGroupId">${project.projectGroupId}</s:param>
-                <s:param name="projectId">${project.id}</s:param>
-                <s:param name="projectName">${project.name}</s:param>
-                <s:param name="buildId">${project.buildInSuccessId}</s:param>
+                <s:param name="projecGroupId"><c:out value="${project.projectGroupId}"/></s:param>
+                <s:param name="projectId"><c:out value="${project.id}"/></s:param>
+                <s:param name="projectName"><c:out value="${project.name}"/></s:param>
+                <s:param name="buildId"><c:out value="${project.buildInSuccessId}"/></s:param>
               </s:url>
-              <s:a href="%{buildResult}">${project.buildNumber}</s:a>
+              <s:a href="%{buildResult}"><c:out value="${project.buildNumber}"/></s:a>
             </redback:ifAuthorized>
             <redback:elseAuthorized>
-              ${project.buildNumber}
+              <c:out value="${project.buildNumber}"/>
             </redback:elseAuthorized>
           </c:when>
           <c:when test="${project.buildNumber gt 0 && project.buildInSuccessId lt 0}">
-              ${project.buildNumber}
+              <c:out value="${project.buildNumber}"/>
           </c:when>
           <c:otherwise>
             &nbsp;
@@ -109,8 +109,8 @@
               <c:choose>
                 <c:when test="${projectIdle}">
                   <s:url id="buildProjectUrl" action="buildProject" namespace="/" includeParams="none">
-                    <s:param name="projectId">${project.id}</s:param>
-                    <s:param name="projectGroupId">${project.projectGroupId}</s:param>
+                    <s:param name="projectId"><c:out value="${project.id}"/></s:param>
+                    <s:param name="projectGroupId"><c:out value="${project.projectGroupId}"/></s:param>
                     <s:param name="fromGroupPage" value="true"/>
                   </s:url>
                   <s:a href="%{buildProjectUrl}">
@@ -119,8 +119,8 @@
                 </c:when>
                 <c:otherwise>
                   <s:url id="cancelBuildProjectUrl" action="cancelBuild" namespace="/" includeParams="none">
-                    <s:param name="projectId">${project.id}</s:param>
-                    <s:param name="projectGroupId">${project.projectGroupId}</s:param>
+                    <s:param name="projectId"><c:out value="${project.id}"/></s:param>
+                    <s:param name="projectGroupId"><c:out value="${project.projectGroupId}"/></s:param>
                   </s:url>
                   <c:choose>
                     <c:when test="${project.state != 8}">
@@ -153,8 +153,8 @@
         <c:choose>
           <c:when test="${pageScope.project.latestBuildId > 0}">
             <s:url id="buildResultsUrl" action="buildResults" namespace="/">
-              <s:param name="projectId">${project.id}</s:param>
-              <s:param name="projectName">${project.name}</s:param>
+              <s:param name="projectId"><c:out value="${project.id}"/></s:param>
+              <s:param name="projectName"><c:out value="${project.name}"/></s:param>
             </s:url>
             <s:a href="%{buildResultsUrl}"><img src="<s:url value='/images/buildhistory.gif' includeParams="none"/>" alt="<s:text name="legend.buildHistory"/>" title="<s:text name="legend.buildHistory"/>" border="0"></s:a>
           </c:when>
@@ -172,7 +172,7 @@
         <c:choose>
           <c:when test="${pageScope.project.state == 10 || pageScope.project.state == 2 || pageScope.project.state == 3 || pageScope.project.state == 4 || pageScope.project.state == 6}">
             <s:url id="workingCopyUrl" action="workingCopy" namespace="/">
-              <s:param name="projectId">${project.id}</s:param>
+              <s:param name="projectId"><c:out value="${project.id}"/></s:param>
             </s:url>
             <s:a href="%{workingCopyUrl}"><img src="<s:url value='/images/workingcopy.gif' includeParams="none"/>" alt="<s:text name="legend.workingCopy"/>" title="<s:text name="legend.workingCopy"/>" border="0"></s:a>
           </c:when>
@@ -190,7 +190,7 @@
         <c:choose>
           <c:when test="${pageScope.project.state == 2 && pageScope.project.projectType == 'maven2'}">
             <s:url id="releaseProjectUrl" action="releasePromptGoal" namespace="/">
-              <s:param name="projectId">${project.id}</s:param>
+              <s:param name="projectId"><c:out value="${project.id}"/></s:param>
             </s:url>
             <s:a href="%{releaseProjectUrl}">
               <img src="<s:url value='/images/releaseproject.gif' includeParams="none"/>" alt="<s:text name="legend.release"/>" title="<s:text name="legend.release"/>" border="0"/>
@@ -210,8 +210,11 @@
         <c:choose>
           <c:when
               test="${projectIdle}">
-            <s:url id="deleteProjectUrl" value="deleteProject!default.action" namespace="/">
-              <s:param name="projectId">${project.id}</s:param>
+            <s:token/>
+            <s:url id="deleteProjectUrl" value="deleteProject_default.action" namespace="/">
+              <s:param name="projectId"><c:out value="${project.id}"/></s:param>
+              <s:param name="struts.token.name">token</s:param>
+              <s:param name="token"><s:property value="token"/></s:param>
             </s:url>
             <s:a href="%{deleteProjectUrl}">
               <img src="<s:url value='/images/delete.gif' includeParams="none"/>" alt="<s:text name="delete"/>" title="<s:text name="delete"/>" border="0">
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/confirmBuildDefinitionRemoval.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/confirmBuildDefinitionRemoval.jsp
index 08e5040..8ae8ef1 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/confirmBuildDefinitionRemoval.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/confirmBuildDefinitionRemoval.jsp
@@ -18,7 +18,6 @@
   --%>
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <html>
   <s:i18n name="localization.Continuum">
     <head>
@@ -41,11 +40,13 @@
         </div>
         <div class="functnbar3">
           <s:form action="removeGroupBuildDefinition">
+            <s:token/>
             <s:hidden name="buildDefinitionId"/>
             <s:hidden name="projectGroupId"/>
             <s:hidden name="projectId"/>
             <s:hidden name="confirmed" value="true"/>
-            <c1:submitcancel value="%{getText('delete')}" cancel="%{getText('cancel')}"/>
+            <s:submit value="%{getText('delete')}" theme="simple"/>
+            <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
           </s:form>
         </div>
       </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/confirmBuildResultsRemoval.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/confirmBuildResultsRemoval.jsp
index c4bebd2..b41300c 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/confirmBuildResultsRemoval.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/confirmBuildResultsRemoval.jsp
@@ -18,7 +18,6 @@
   --%>
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
 <html>
   <s:i18n name="localization.Continuum">
@@ -44,6 +43,7 @@
           <c:set var="action" value="removeBuildResults.action" />
         </s:else>
         <form action="${action}" method="post">
+          <s:token/>
           <s:hidden name="projectGroupId"/>
           <s:hidden name="projectId"/>
           <s:hidden name="buildId"/>
@@ -71,14 +71,12 @@
 
           <div class="functnbar3">
             <s:if test="buildId > 0">
-              <c1:submitcancel value="%{getText('delete')}" cancel="%{getText('cancel')}"/>
+              <s:submit value="%{getText('delete')}" theme="simple"/>
             </s:if>
             <s:elseif test="selectedBuildResults.size > 0">
-              <c1:submitcancel value="%{getText('delete')}" cancel="%{getText('cancel')}"/>
+              <s:submit value="%{getText('delete')}" theme="simple"/>
             </s:elseif>
-            <s:else>
-              <input type="submit" value="<s:text name="cancel"/>" onClick="history.back()"/>
-            </s:else>
+            <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
           </div>
         </form>
         </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/confirmDeleteProjects.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/confirmDeleteProjects.jsp
index c41ede2..00c7974 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/confirmDeleteProjects.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/confirmDeleteProjects.jsp
@@ -18,7 +18,6 @@
   --%>
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <html>
   <s:i18n name="localization.Continuum">
     <head>
@@ -44,7 +43,8 @@
             </s:iterator>
             <input type="hidden" name="projectGroupId" value="${projectGroupId}" />
             <input type="hidden" name="methodToCall" value="remove" />
-            <c1:submitcancel value="%{getText('delete')}" cancel="%{getText('cancel')}"/>
+            <s:submit value="%{getText('delete')}" theme="simple"/>
+            <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
           </s:form>
         </div>
       </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/confirmGroupRemoval.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/confirmGroupRemoval.jsp
index deaa2ac..1c39bfe 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/confirmGroupRemoval.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/confirmGroupRemoval.jsp
@@ -18,25 +18,24 @@
   --%>
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <html>
   <s:i18n name="localization.Continuum">
     <head>
-        <title>Project Group Removal</title>
+        <title><s:text name="confirmGroupRemoval.page.title"/></title>
     </head>
     <body>
       <div id="axial" class="h3">
-        <h3>Project Group Removal</h3>
+        <h3><s:text name="confirmGroupRemoval.section.title"/></h3>
         <div class="axial">
         <s:form action="removeProjectGroup" method="post">
           <s:hidden name="projectGroupId"/>
-          <s:hidden name="confirmed" value="true"/>
+          <s:token/>
           <s:actionerror/>
 
           <div class="warningmessage">
             <p>
               <strong>
-                <s:text name="groups.confirmation.message">
+                <s:text name="confirmGroupRemoval.confirmation.message">
                   <s:param><s:property value="%{name}"/></s:param>
                 </s:text>
               </strong>
@@ -44,7 +43,8 @@
           </div>
 
           <div class="functnbar3">
-            <c1:submitcancel value="%{getText('delete')}" cancel="%{getText('cancel')}"/>
+            <s:submit value="%{getText('delete')}" theme="simple"/>
+            <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
           </div>
         </s:form>
         </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/confirmReleaseResultsRemoval.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/confirmReleaseResultsRemoval.jsp
index 489d104..e0b544a 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/confirmReleaseResultsRemoval.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/confirmReleaseResultsRemoval.jsp
@@ -18,7 +18,6 @@
   --%>
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
 <html>
   <s:i18n name="localization.Continuum">
@@ -41,12 +40,14 @@
         
         <div class="functnbar3">
           <s:form action="removeReleaseResults" method="post">
+            <s:token/>
             <s:iterator value="selectedReleaseResults">
               <input type="hidden" value="<s:property/>" name="selectedReleaseResults"/>
             </s:iterator>
             <input type="hidden" name="projectGroupId" value="${projectGroupId}" />
             <s:hidden name="confirmed" value="true"/>
-            <c1:submitcancel value="%{getText('delete')}" cancel="%{getText('cancel')}"/>
+            <s:submit value="%{getText('delete')}" theme="simple"/>
+            <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
           </s:form>
         </div>
       </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/confirmScheduleRemoval.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/confirmScheduleRemoval.jsp
index 80a55f5..a4a51cb 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/confirmScheduleRemoval.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/confirmScheduleRemoval.jsp
@@ -18,17 +18,17 @@
   --%>
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <html>
   <s:i18n name="localization.Continuum">
     <head>
-        <title>Schedule Removal</title>
+        <title><s:text name="deleteSchedule.page.title"/></title>
     </head>
     <body>
       <div id="axial" class="h3">
-        <h3>Schedule Removal</h3>
+        <h3><s:text name="deleteSchedule.section.title"/></h3>
         <div class="axial">
         <s:form action="removeSchedule" method="post">
+          <s:token/>
           <s:hidden name="id"/>
           <s:hidden name="confirmed" value="true"/>
           <s:actionerror/>
@@ -36,7 +36,7 @@
           <div class="warningmessage">
             <p>
               <strong>
-                <s:text name="schedules.confirmation.message">
+                <s:text name="deleteSchedule.confirmation.message">
                   <s:param><s:property value="%{name}"/></s:param>
                 </s:text>
               </strong>
@@ -44,7 +44,8 @@
           </div>
 
           <div class="functnbar3">
-            <c1:submitcancel value="%{getText('delete')}" cancel="%{getText('cancel')}"/>
+            <s:submit value="%{getText('delete')}" theme="simple"/>
+            <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
           </div>
         </s:form>
         </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/decorators/default.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/decorators/default.jsp
index 2f7fb22..cd89f75 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/decorators/default.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/decorators/default.jsp
@@ -28,6 +28,7 @@
     <decorator:title/>
   </title>
   <link rel="stylesheet" type="text/css" href="<s:url value="/css/tigris.css" includeParams="none"/>" media="screen"/>
+  <link rel="stylesheet" type="text/css" href="<s:url value="/css/continuum.css" includeParams="none"/>" media="screen"/>
   <link rel="stylesheet" type="text/css" href="<s:url value="/css/print.css" includeParams="none"/>" media="print"/>
   <link rel="stylesheet" type="text/css" href="<s:url value="/css/extremecomponents.css" includeParams="none"/>" media="screen"/>
   <link rel="shortcut icon" href="<s:url value="/favicon.ico" includeParams="none"/>" type="image/x-icon"/>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/deleteBuildDefinition.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/deleteBuildDefinition.jsp
index b840964..7f43908 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/deleteBuildDefinition.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/deleteBuildDefinition.jsp
@@ -18,7 +18,6 @@
   --%>
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <html>
   <s:i18n name="localization.Continuum">
     <head>
@@ -40,10 +39,12 @@
         </div>
         <div class="functnbar3">
           <s:form action="removeProjectBuildDefinition.action" method="post">
+            <s:token/>
             <s:hidden name="projectId"/>
             <s:hidden name="buildDefinitionId"/>
             <s:hidden name="confirmed" value="true"/>
-            <c1:submitcancel value="%{getText('delete')}" cancel="%{getText('cancel')}"/>
+            <s:submit value="%{getText('delete')}" theme="simple"/>
+            <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
           </s:form>
         </div>
       </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/deleteProject.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/deleteProject.jsp
index 010b46e..637dcc3 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/deleteProject.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/deleteProject.jsp
@@ -18,7 +18,6 @@
   --%>
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <html>
   <s:i18n name="localization.Continuum">
     <head>
@@ -39,9 +38,11 @@
         </div>
         <div class="functnbar3">
           <s:form action="deleteProject.action" method="post">
+            <s:token/>
             <s:hidden name="projectId"/>
             <s:hidden name="projectGroupId"/>
-            <c1:submitcancel value="%{getText('delete')}" cancel="%{getText('cancel')}"/>
+            <s:submit value="%{getText('delete')}" theme="simple"/>
+            <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
           </s:form>
         </div>
       </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/editSchedule.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/editSchedule.jsp
index 6e95b05..f785144 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/editSchedule.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/editSchedule.jsp
@@ -20,6 +20,7 @@
 <%@ 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>
@@ -28,10 +29,11 @@
 <body>
 <div class="app">
   <div id="axial" class="h3">
-    <h3><s:text name="editSchedule.page.title"/></h3>
+    <h3><s:text name="editSchedule.section.title"/></h3>
 
     <div class="axial">
-      <s:form action="saveSchedule" method="post" validate="true">
+      <s:form action="saveSchedule" method="post" validate="false" name="scheduleForm">
+        <s:hidden name="id"/>
         <c:if test="${!empty actionErrors}">
           <div class="errormessage">
             <s:iterator value="actionErrors">
@@ -41,15 +43,15 @@
         </c:if>
 
           <table>
-            <s:textfield label="%{getText('schedule.name.label')}" name="name" required="true">
-                <s:param name="desc"><p><s:text name="schedule.name.message"/></p></s:param>
+            <s:textfield label="%{getText('schedule.name.label')}" name="name" requiredLabel="true" size="100">
+                <s:param name="after"><p><s:text name="schedule.name.message"/></p></s:param>
             </s:textfield>
-            <s:textfield label="%{getText('schedule.description.label')}" name="description" required="true">
-                <s:param name="desc"><p><s:text name="schedule.description.message"/></p></s:param>
+            <s:textfield label="%{getText('schedule.description.label')}" name="description" requiredLabel="true" size="100">
+                <s:param name="after"><p><s:text name="schedule.description.message"/></p></s:param>
             </s:textfield>
 
             <tr>
-              <th><s:label theme="simple" value="%{getText('schedule.cronExpression.label')}:"/></th>
+              <td class="tdLabel"><s:label theme="simple" class="label" value="%{getText('schedule.cronExpression.label')}:"/></td>
               <td>
                 <table>
                   <s:textfield label="%{getText('schedule.second.label')}" name="second" size="10"/>
@@ -59,27 +61,59 @@
                   <s:textfield label="%{getText('schedule.month.label')}" name="month" size="10"/>
                   <s:textfield label="%{getText('schedule.dayOfWeek.label')}" name="dayOfWeek" size="10"/>
                   <s:textfield label="%{getText('schedule.year.label')}" name="year"  size="4">
-                    <s:param name="desc"><p><s:text name="schedule.cronExpression.message"/></p></s:param>
+                    <s:param name="after"><p><s:text name="schedule.cronExpression.message"/></p></s:param>
                   </s:textfield>
                 </table>
               </td>
             </tr>
 
-            <s:textfield label="%{getText('schedule.maxJobExecutionTime.label')}" name="maxJobExecutionTime" required="true">
-                <s:param name="desc"><p><s:text name="schedule.maxJobExecutionTime.message"/></p></s:param>
+            <s:textfield label="%{getText('schedule.maxJobExecutionTime.label')}" name="maxJobExecutionTime" requiredLabel="true" size="100">
+                <s:param name="after"><p><s:text name="schedule.maxJobExecutionTime.message"/></p></s:param>
             </s:textfield>
-            <s:textfield label="%{getText('schedule.quietPeriod.label')}" name="delay">
-                <s:param name="desc"><p><s:text name="schedule.quietPeriod.message"/></p></s:param>
+            <s:textfield label="%{getText('schedule.quietPeriod.label')}" name="delay" size="100">
+                <s:param name="after"><p><s:text name="schedule.quietPeriod.message"/></p></s:param>
             </s:textfield>
+
+            <c1:ifBuildTypeEnabled buildType="parallel">          
+              <s:optiontransferselect 
+                label="%{getText('schedule.buildqueues.label')}"
+                name="availableBuildQueuesIds"
+                list="availableBuildQueues"
+                listKey="id"
+                listValue="name"
+                headerKey="hk-1"
+                headerValue="%{getText('schedule.available.buildqueues')}"
+                multiple="true"
+                size="8"
+                emptyOption="false"
+                doubleName="selectedBuildQueuesIds"
+                doubleList="selectedBuildQueues"
+                doubleListKey="id"
+                doubleListValue="name"
+                doubleHeaderKey="hk-1"
+                doubleSize="8"
+                doubleMultiple="true"
+                doubleEmptyOption="false"
+                doubleHeaderValue="%{getText('schedule.available.buildqueues.used')}"
+                formName="scheduleForm"
+                addAllToRightOnclick="selectAllOptionsExceptSome(document.getElementById('saveSchedule_selectedBuildQueuesIds'), 'key', 'hk-1');"
+                addToRightOnclick="selectAllOptionsExceptSome(document.getElementById('saveSchedule_availableBuildQueuesIds'), 'key', 'hk-1');selectAllOptionsExceptSome(document.getElementById('saveSchedule_selectedBuildQueuesIds'), 'key', 'hk-1');"
+                addAllToLeftOnclick="selectAllOptionsExceptSome(document.getElementById('saveSchedule_availableBuildQueuesIds'), 'key', 'hk-1');"
+                addToLeftOnclick="selectAllOptionsExceptSome(document.getElementById('saveSchedule_availableBuildQueuesIds'), 'key', 'hk-1');selectAllOptionsExceptSome(document.getElementById('saveSchedule_selectedBuildQueuesIds'), 'key', 'hk-1');"
+                />
+             </c1:ifBuildTypeEnabled>   
+                                       
             <s:checkbox label="%{getText('schedule.enabled.label')}" name="active" value="active" fieldValue="true">
-                <s:param name="desc"><p><s:text name="schedule.enabled.message"/></p></s:param>
+                <s:param name="after"><p><s:text name="schedule.enabled.message"/></p></s:param>
             </s:checkbox>
+
           </table>
-          <s:hidden name="id"/>
-        <div class="functnbar3">
-          <c1:submitcancel value="%{getText('save')}" cancel="%{getText('cancel')}"/>
-        </div>
+          <div class="functnbar3">
+            <s:submit value="%{getText('save')}" theme="simple"/>
+            <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
+          </div>
       </s:form>
+      
     </div>
   </div>
 </div>
@@ -87,3 +121,4 @@
 </body>
 </s:i18n>
 </html>
+
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/error/authorizationError.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/error/authorizationError.jsp
index 672f0ba..19d51f6 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/error/authorizationError.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/error/authorizationError.jsp
@@ -21,23 +21,23 @@
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 
 <html>
+<s:i18n name="localization.Continuum">
 <head>
-  <title>Authorization Error</title>
+  <title><s:text name="authorizationError.page.title"/></title>
 </head>
 
 <body>
   <div id="h3">
-    <h3>Authorization Error</h3>
+    <h3><s:text name="authorizationError.section.title"/></h3>
     <div class="errors">
       <s:if test="hasActionErrors()">
         <s:actionerror/>
       </s:if>
-
       <s:else>
-        You are not authorized to access this page.
-        Please contact your administrator to be granted the appropriate permissions.
+        <s:text name="authorizationError.not.authorized"/>
       </s:else>
     </div>
   </div>
 </body>
+</s:i18n>
 </html>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/error/buildDefinitionError.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/error/buildDefinitionError.jsp
new file mode 100644
index 0000000..f4bbc24
--- /dev/null
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/error/buildDefinitionError.jsp
@@ -0,0 +1,44 @@
+<%--
+  ~ 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 prefix="s" uri="/struts-tags" %>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+
+<html>
+<s:i18n name="localization.Continuum">
+<head>
+  <title><s:text name="buildDefinitionError.page.title"/></title>
+</head>
+
+<body>
+  <div id="h3">
+    <h3><s:text name="buildDefinitionError.section.title"/></h3>
+    <div class="errors">
+      <c:if test="${!empty actionErrors}">
+        <div class="errormessage">
+          <s:iterator value="actionErrors">
+            <p><s:property/></p>
+          </s:iterator>
+        </div>
+      </c:if>
+    </div>
+  </div>
+</body>
+</s:i18n>
+</html>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/error/error.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/error/error.jsp
index bf51e8c..d7eadba 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/error/error.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/error/error.jsp
@@ -21,9 +21,9 @@
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 
 <html>
+<s:i18n name="localization.Continuum">
 <head>
-  <title>Error Occurred</title>
-  <s:head />
+  <title><s:text name="errorOccured.page.title"/></title>
   <script language=javascript type='text/javascript'>
     <!--
     var state = 'none';
@@ -58,7 +58,7 @@
 
 <body>
   <div id="h3">
-    <h3>Error Occurred</h3>
+    <h3><s:text name="errorOccured.section.title"/></h3>
 
     <div class="errormessage">
       <s:property value="exception"/>
@@ -71,4 +71,5 @@
     </div>
   </div>
 </body>
+</s:i18n>
 </html>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/error/httpError.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/error/httpError.jsp
index d27709b..9845b57 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/error/httpError.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/error/httpError.jsp
@@ -27,68 +27,58 @@
 <head>
   <title>
     <c:choose>
-      <c:when test="${param.errorCode == 403 || param.errorCode == 404 || param.errorCode == 500}">
-        <s:text name="error.%{param.errorCode}.title"/>
+      <c:when test="${param.errorCode == 403}">
+        <s:text name="error.403.title"/>
+      </c:when>
+      <c:when test="${param.errorCode == 404}">
+        <s:text name="error.404.title"/>
+      </c:when>
+      <c:when test="${param.errorCode == 500}">
+        <s:text name="error.500.title"/>
       </c:when>
       <c:otherwise>
         <s:text name="error.page.title"/>
       </c:otherwise>
     </c:choose>
   </title>
-  <link rel="stylesheet" type="text/css" href="<s:url value="/css/tigris.css" includeParams="none"/>" media="screen"/>
-  <link rel="stylesheet" type="text/css" href="<s:url value="/css/print.css" includeParams="none"/>" media="print"/>
-  <link rel="stylesheet" type="text/css" href="<s:url value="/css/extremecomponents.css" includeParams="none"/>" media="screen"/>
-  <link rel="shortcut icon" href="<s:url value="/favicon.ico" includeParams="none"/>" type="image/x-icon"/>
-
-  <script src="<s:url value="/scripts/tigris.js" includeParams="none"/>" type="text/javascript"></script>
 </head>
 
-<body onload="focus()" marginwidth="0" marginheight="0" class="composite">
-<%@ include file="/WEB-INF/jsp/navigations/DefaultTop.jsp" %>
+<body>
+  <div id="h3">
+    <h3>
+      <c:choose>
+        <c:when test="${param.errorCode == 403}">
+          <s:text name="error.403.section.title"/>
+        </c:when>
+        <c:when test="${param.errorCode == 404}">
+          <s:text name="error.404.section.title"/>
+        </c:when>
+        <c:when test="${param.errorCode == 500}">
+          <s:text name="error.500.section.title"/>
+        </c:when>
+        <c:otherwise>
+          The URL requested results to an unknown error (Error <s:property value="errorCode"/>).
+        </c:otherwise>
+      </c:choose>
+    </h3>
 
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-  <tbody>
-    <tr valign="top">
-      <td id="leftcol" width="180">
-        <br/> <br/>
-        <%@ include file="/WEB-INF/jsp/navigations/Menu.jsp" %>
-      </td>
-      <td width="86%">
-        <br/>
-
-        <div id="bodycol">
-          <div class="app">
-            <div id="axial" class="h3">
-              <h3>
-                <c:choose>
-                  <c:when test="${param.errorCode == 403 || param.errorCode == 404 || param.errorCode == 500}">
-                    <s:text name="error.%{param.errorCode}.section.title"/>
-                  </c:when>
-                  <c:otherwise>
-                    The URL requested results to an unknown error.
-                  </c:otherwise>
-                </c:choose>
-              </h3>
-
-              <div class="errormessage">
-                <c:choose>
-                  <c:when test="${param.errorCode == 403 || param.errorCode == 404 || param.errorCode == 500}">
-                    <s:text name="error.%{param.errorCode}.message"/>
-                  </c:when>
-                  <c:otherwise>
-                    The URL requested results to an unknown error.
-                  </c:otherwise>
-                </c:choose>
-              </div>
-            </div>
-          </div>
-        </div>
-      </td>
-    </tr>
-  </tbody>
-</table>
-
-<%@ include file="/WEB-INF/jsp/navigations/DefaultBottom.jsp" %>
+    <div class="errormessage">
+      <c:choose>
+        <c:when test="${param.errorCode == 403}">
+          <s:text name="error.403.message"/>
+        </c:when>
+        <c:when test="${param.errorCode == 404}">
+          <s:text name="error.404.message"/>
+        </c:when>
+        <c:when test="${param.errorCode == 500}">
+          <s:text name="error.500.message"/>
+        </c:when>
+        <c:otherwise>
+          The URL requested results to an unknown error (Error <s:property value="errorCode"/>).
+        </c:otherwise>
+      </c:choose>
+    </div>
+  </div>
 </body>
 </html>
 </s:i18n>
\ No newline at end of file
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/error/releaseError.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/error/releaseError.jsp
new file mode 100644
index 0000000..feb835f
--- /dev/null
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/error/releaseError.jsp
@@ -0,0 +1,44 @@
+<%--
+  ~ 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 prefix="s" uri="/struts-tags" %>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+
+<html>
+<s:i18n name="localization.Continuum">
+<head>
+  <title><s:text name="releaseError.page.title"/></title>
+</head>
+
+<body>
+  <div id="h3">
+    <h3><s:text name="releaseError.section.title"/></h3>
+    <div class="errors">
+      <c:if test="${!empty actionErrors}">
+        <div class="errormessage">
+          <s:iterator value="actionErrors">
+            <p><s:property/></p>
+          </s:iterator>
+        </div>
+      </c:if>
+    </div>
+  </div>
+</body>
+</s:i18n>
+</html>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/groupSummary.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/groupSummary.jsp
index 671b9e1..939be4b 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/groupSummary.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/groupSummary.jsp
@@ -33,12 +33,20 @@
   <div id="h3">
 
     <s:if test="infoMessage != null">
-       <p>${infoMessage}</p>
+       <p><c:out value="${infoMessage}"/></p>
     </s:if>
     <s:else>
        <h3><s:text name="groups.page.section.title"/></h3>
     </s:else>
   
+    <c:if test="${!empty actionErrors}">
+      <div class="errormessage">
+        <s:iterator value="actionErrors">
+          <p><s:property/></p>
+        </s:iterator>
+      </div>
+    </c:if>
+
     <c:if test="${empty groups}">
       <s:text name="groups.page.list.empty"/>
     </c:if>
@@ -47,31 +55,26 @@
 
     <ec:table items="groups"
               var="group"
+              autoIncludeParameters="false"
               showExports="false"
               showPagination="false"
               showStatusBar="false"
               sortable="false"
               filterable="false">
       <ec:row highlightRow="true">
-        <ec:column property="name" title="groups.table.name" width="20%" style="white-space: nowrap">
-          <a href="<s:url  action="projectGroupSummary" namespace="/"><s:param name="projectGroupId">${group.id}</s:param></s:url>">${group.name}</a>
+        <ec:column property="name" title="groups.table.name" width="40%" style="white-space: nowrap">
+          <s:url id="projectGroupSummaryUrl" action="projectGroupSummary" namespace="/">
+            <s:param name="projectGroupId">
+              <c:out value="${group.id}" />
+            </s:param>
+          </s:url>
+          <a href="${projectGroupSummaryUrl}"><c:out value="${group.name}"/></a>
         </ec:column>
-        <ec:column property="groupId" title="groups.table.groupId" width="20%"/>
-        <ec:column property="repositoryName" title="groups.table.repositoryName" width="20%">
-          <redback:ifAuthorized permission="continuum-manage-repositories">
-            <s:url id="editRepositoryUrl" action="editRepository" namespace="/admin" includeParams="none">
-              <s:param name="repository.id">${pageScope.group.repositoryId}</s:param>
-            </s:url>
-            <s:a href="%{editRepositoryUrl}">${pageScope.group.repositoryName}</s:a>
-          </redback:ifAuthorized>
-          <redback:elseAuthorized>
-            ${pageScope.group.repositoryName}
-          </redback:elseAuthorized>
-        </ec:column>
+        <ec:column property="groupId" title="groups.table.groupId" width="40%"/>
         <ec:column property="buildGroupNowAction" title="&nbsp;" width="1%">
           <redback:ifAuthorized permission="continuum-build-group" resource="${group.name}">
             <s:url id="buildProjectGroupUrl" action="buildProjectGroup" namespace="/" includeParams="none">
-              <s:param name="projectGroupId">${group.id}</s:param>
+              <s:param name="projectGroupId"><c:out value="${group.id}"/></s:param>
               <s:param name="buildDefinitionId" value="-1"/>
               <s:param name="fromSummaryPage" value="true"/>
             </s:url>
@@ -86,7 +89,7 @@
         <ec:column property="releaseProjectGroupAction" title="&nbsp;" width="1%">
           <redback:ifAuthorized permission="continuum-build-group" resource="${group.name}">
             <s:url id="releaseProjectGroupUrl" action="releaseProjectGroup" namespace="/" includeParams="none">
-              <s:param name="projectGroupId">${group.id}</s:param>
+              <s:param name="projectGroupId"><c:out value="${group.id}"/></s:param>
             </s:url>
             <s:a href="%{releaseProjectGroupUrl}">
               <img src="<s:url value='/images/releaseproject.gif'/>" alt="<s:text name="projectGroup.releaseNow"/>" title="<s:text name="projectGroup.releaseNow"/>" border="0">
@@ -98,8 +101,9 @@
         </ec:column>
         <ec:column property="removeProjectGroupAction" title="&nbsp;" width="1%">
           <redback:ifAuthorized permission="continuum-remove-group" resource="${group.name}">
-            <s:url id="removeProjectGroupUrl" action="removeProjectGroup" namespace="/" includeParams="none">
-              <s:param name="projectGroupId">${group.id}</s:param>
+            <s:token/>
+            <s:url id="removeProjectGroupUrl" action="confirmRemoveProjectGroup" namespace="/" includeParams="none">
+              <s:param name="projectGroupId"><c:out value="${group.id}"/></s:param>
             </s:url>
             <s:a href="%{removeProjectGroupUrl}">
               <img src="<s:url value='/images/delete.gif'/>" alt="<s:text name="projectGroup.deleteGroup"/>" title="<s:text name="projectGroup.deleteGroup"/>" border="0">
@@ -121,7 +125,7 @@
         <table>
           <tr>
             <td>
-              <form action="<s:url  action='addProjectGroup' method='input' namespace='/' />" method="post">
+              <form action="<s:url  action='addProjectGroup_input' namespace='/' />" method="post">
                 <input type="submit" name="addProjectGroup" value="<s:text name="projectGroup.add.section.title"/>"/>
               </form>
             </td>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/navigations/Menu.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/navigations/Menu.jsp
index cab3148..fe0d56c 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/navigations/Menu.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/navigations/Menu.jsp
@@ -19,12 +19,13 @@
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c' %>
+<%@ taglib uri="continuum" prefix="c1" %>
 <%@ taglib uri="http://plexus.codehaus.org/redback/taglib-1.0" prefix="redback" %>
 
 <s:i18n name="localization.Continuum">
 <div id="navcolumn">
   <div id="projectmenu" class="toolgroup">
-    <div class="label">Continuum</div>
+    <div class="label"><s:text name="menu.continuum"/></div>
     <div>
       <div class="body">
         <s:url id="aboutUrl" action="about" namespace="/" includeParams="none"/>
@@ -48,14 +49,14 @@
       </div>
       <div>
         <div class="body">
-          <s:url id="addMavenTwoProjectUrl" action="addMavenTwoProjectInput" method="input" namespace="/"
+          <s:url id="addMavenTwoProjectUrl" action="addMavenTwoProjectInput" namespace="/"
                   includeParams="none"/>
           <s:a href="%{addMavenTwoProjectUrl}">
             <s:text name="menu.add.m2Project"/>
           </s:a>
         </div>
         <div class="body">
-          <s:url id="addMavenOneProjectUrl" action="addMavenOneProjectInput" method="input" namespace="/"
+          <s:url id="addMavenOneProjectUrl" action="addMavenOneProjectInput" namespace="/"
                   includeParams="none"/>
           <s:a href="%{addMavenOneProjectUrl}">
             <s:text name="menu.add.m1Project"/>
@@ -97,7 +98,7 @@
           </div>
         </redback:ifAuthorized>
         <redback:ifAuthorized permission="continuum-manage-purging">
-          <s:url id="purgeConfigListUrl" action="purgeConfigList" namespace="/admin" includeParams="none"/>
+          <s:url id="purgeConfigListUrl" action="displayPurge" namespace="/admin" includeParams="none"/>
           <div class="body">
             <s:a href="%{purgeConfigListUrl}">
               <s:text name="menu.administration.purge"/>
@@ -113,7 +114,7 @@
           </div>
         </redback:ifAuthorized>
         <redback:ifAuthorized permission="continuum-manage-installations">
-          <s:url id="configurationUrl" action="installationsList" namespace="/admin" method="list" includeParams="none"/>
+          <s:url id="configurationUrl" action="installationsList" namespace="/admin" includeParams="none"/>
           <div class="body">
             <s:a href="%{configurationUrl}">
               <s:text name="menu.administration.installations"/>
@@ -121,7 +122,7 @@
           </div>
         </redback:ifAuthorized>
         <redback:ifAuthorized permission="continuum-manage-profiles">
-          <s:url id="configurationUrl" action="buildEnvList" namespace="/admin" method="list" includeParams="none"/>
+          <s:url id="configurationUrl" action="buildEnvList" namespace="/admin" includeParams="none"/>
           <div class="body">
             <s:a href="%{configurationUrl}">
               <s:text name="menu.administration.profile"/>
@@ -129,13 +130,13 @@
           </div> 
         </redback:ifAuthorized> 
         <redback:ifAuthorized permission="continuum-view-queues">
-          <s:url id="queueUrls" action="displayQueues" namespace="/admin" method="display" includeParams="none"/>
+          <s:url id="queueUrls" action="displayQueues" namespace="/admin" includeParams="none"/>
           <div class="body">
             <s:a href="%{queueUrls}">
               <s:text name="menu.administration.queues"/>
             </s:a>
           </div> 
-        </redback:ifAuthorized> 
+        </redback:ifAuthorized>
         <redback:ifAuthorized permission="continuum-manage-build-templates">
           <s:url id="buildDefinitionTemplatesUrl" action="buildDefinitionTemplates" namespace="/admin" includeParams="none"/>
           <div class="body">
@@ -145,7 +146,7 @@
           </div> 
         </redback:ifAuthorized>        
         <redback:ifAuthorized permission="continuum-manage-configuration">               
-          <s:url id="configurationUrl" action="configuration" namespace="/admin" method="input" includeParams="none"/>
+          <s:url id="configurationUrl" action="configuration" namespace="/admin" includeParams="none"/>
           <div class="body">
             <s:a href="%{configurationUrl}">
               <s:text name="menu.administration.configuration"/>
@@ -158,16 +159,6 @@
             </s:a>
           </div>
         </redback:ifAuthorized>
-        <redback:ifAuthorized permission="continuum-manage-distributed-builds">
-          <s:url id="buildAgentList" action="buildAgentList" namespace="/security" includeParams="none"/>
-          <div class="body">
-            <s:a href="%{buildAgentList}">
-              <s:text name="menu.administration.buildAgents"/>
-            </s:a>
-          </div>
-        </redback:ifAuthorized>
-        <redback:ifAuthorized permission="continuum-manage-distributed-builds">
-        </redback:ifAuthorized>
         <redback:ifAuthorized permission="continuum-manage-users">
           <s:url id="userListUrl" action="userlist" namespace="/security" includeParams="none"/>
           <div class="body">
@@ -186,6 +177,68 @@
     </div>
   </redback:ifAnyAuthorized>
 
+  <redback:ifAuthorized permission="continuum-view-report">
+    <div id="projectmenu" class="toolgroup">
+      <div class="label">
+        <s:text name="menu.reports"/>
+      </div>
+      <div>
+        <div class="body">
+          <s:url id="viewProjectBuildsReportUrl" action="viewProjectBuildsReport" namespace="/" includeParams="none"/>
+          <s:a href="%{viewProjectBuildsReportUrl}">
+            <s:text name="menu.reports.projectBuilds"/>
+          </s:a> 
+        </div>
+      </div>
+    </div>
+  </redback:ifAuthorized>
+
+  <c1:ifBuildTypeEnabled buildType="distributed">
+    <redback:ifAnyAuthorized permissions="continuum-manage-distributed-builds,continuum-view-release">
+      <div id="projectmenu" class="toolgroup">
+        <div class="label">
+          <s:text name="menu.distributedBuilds"/>
+        </div>    
+        <div>
+          <redback:ifAuthorized permission="continuum-manage-distributed-builds">    
+            <s:url id="buildAgentList" action="buildAgentList" namespace="/security" includeParams="none" />
+            <div class="body">
+              <s:a href="%{buildAgentList}">
+                <s:text name="menu.distributedBuilds.buildAgents"/>
+              </s:a>
+            </div>
+          </redback:ifAuthorized>
+          <redback:ifAuthorized permission="continuum-view-release">
+            <s:url id="releasesUrl" action="viewReleases" namespace="/" includeParams="none"/>
+            <div class="body">
+              <s:a href="%{releasesUrl}">
+                <s:text name="menu.distributedBuilds.releases"/>
+              </s:a>
+            </div>
+          </redback:ifAuthorized>            
+        </div>
+      </div>
+    </redback:ifAnyAuthorized>
+  </c1:ifBuildTypeEnabled>
+  
+  <c1:ifBuildTypeEnabled buildType="parallel">
+    <redback:ifAuthorized permission="continuum-manage-parallel-builds">
+      <div id="projectmenu" class="toolgroup">
+        <div class="label">
+          <s:text name="menu.parallelBuilds"/>
+        </div>    
+        <div>
+          <s:url id="buildQueueListUrl" action="buildQueueList" namespace="/admin" includeParams="none"/>
+          <div class="body">
+            <s:a href="%{buildQueueListUrl}">
+              <s:text name="menu.parallelBuilds.build.queue"/>
+            </s:a>
+          </div>          
+        </div>
+      </div>
+    </redback:ifAuthorized>
+  </c1:ifBuildTypeEnabled>
+  
   <div id="projectmenu" class="toolgroup">
     <div class="label"><s:text name="legend.title"/></div>
     <div id="legend">
@@ -205,4 +258,4 @@
     </div>
   </div>
 </div>
-</s:i18n>
+</s:i18n>
\ No newline at end of file
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/navigations/ProjectMenu.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/navigations/ProjectMenu.jsp
index 7c9e1a4..ef64798 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/navigations/ProjectMenu.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/navigations/ProjectMenu.jsp
@@ -19,7 +19,6 @@
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
-<%@ taglib uri="continuum" prefix="c1" %>
 
 <div>
   <p style="border-top: 1px solid transparent; border-bottom: 1px solid #DFDEDE;">
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/navigations/wait.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/navigations/wait.jsp
index 9427702..f7ee150 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/navigations/wait.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/navigations/wait.jsp
@@ -22,11 +22,11 @@
 <html>
   <s:i18n name="localization.Continuum">
     <head>
-				<META HTTP-EQUIV="refresh" CONTENT="2;url=<s:url includeParams="all"/>"/>
+				<META HTTP-EQUIV="refresh" CONTENT="2;url=<s:url includeParams="NONE"/>"/>
     </head>
     <body>
 			<img src="images/wait.gif">
 			<b><s:text name="wait.addprocessing.processing"/></b>
 		</body>
 	</s:i18n>
-</html>
\ No newline at end of file
+</html>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/deleteNotifier.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/deleteNotifier.jsp
index acb5fbe..138444f 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/deleteNotifier.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/deleteNotifier.jsp
@@ -18,7 +18,6 @@
   --%>
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <html>
   <s:i18n name="localization.Continuum">
     <head>
@@ -41,17 +40,22 @@
         <div class="functnbar3">
           <s:if test="projectId == -1">
             <s:form action="deleteProjectGroupNotifier.action" method="post">
+              <s:token/>
               <s:hidden name="notifierId"/>
               <s:hidden name="projectGroupId" />
-              <c1:submitcancel value="%{getText('delete')}" cancel="%{getText('cancel')}"/>
+              <s:submit value="%{getText('delete')}" theme="simple"/>
+              <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
             </s:form>
           </s:if>
           <s:else>
             <s:form action="deleteProjectNotifier.action" method="post">
+              <s:token/>            
               <s:hidden name="notifierId"/>
               <s:hidden name="projectId"/>
               <s:hidden name="projectGroupId" />
-              <c1:submitcancel value="%{getText('delete')}" cancel="%{getText('cancel')}"/>
+              <s:hidden name="fromGroupPage" />
+              <s:submit value="%{getText('delete')}" theme="simple"/>
+              <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
             </s:form>
           </s:else>
         </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/notifierIrc.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/notifierIrc.jsp
index 07ed34d..a02bdc4 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/notifierIrc.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/notifierIrc.jsp
@@ -18,7 +18,6 @@
   --%>
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <html>
   <s:i18n name="localization.Continuum">
     <head>
@@ -51,25 +50,25 @@
             <s:hidden name="fromGroupPage"/>
             <table>
               <tbody>
-                <s:textfield label="%{getText('notifier.irc.host.label')}" name="host" required="true"/>
-                <s:textfield label="%{getText('notifier.irc.port.label')}" name="port"/>
-                <s:textfield label="%{getText('notifier.irc.channel.label')}" name="channel" required="true"/>
-                <s:textfield label="%{getText('notifier.irc.nick.label')}" name="nick"/>
-                <s:textfield label="%{getText('notifier.irc.alternateNick.label')}" name="alternateNick"/>
-                <s:textfield label="%{getText('notifier.irc.username.label')}" name="username"/>
-                <s:textfield label="%{getText('notifier.irc.fullName.label')}" name="fullName"/>
-                <s:password label="%{getText('notifier.irc.password.label')}" name="password"/>
+                <s:textfield label="%{getText('notifier.irc.host.label')}" name="host" requiredLabel="true" size="100"/>
+                <s:textfield label="%{getText('notifier.irc.port.label')}" name="port" size="100"/>
+                <s:textfield label="%{getText('notifier.irc.channel.label')}" name="channel" requiredLabel="true" size="100"/>
+                <s:textfield label="%{getText('notifier.irc.nick.label')}" name="nick" size="100"/>
+                <s:textfield label="%{getText('notifier.irc.alternateNick.label')}" name="alternateNick" size="100"/>
+                <s:textfield label="%{getText('notifier.irc.username.label')}" name="username" size="100"/>
+                <s:textfield label="%{getText('notifier.irc.fullName.label')}" name="fullName" size="100"/>
+                <s:password label="%{getText('notifier.irc.password.label')}" name="password" size="100"/>
                 <s:checkbox label="%{getText('notifier.irc.isSSL.label')}" name="ssl" value="ssl" fieldValue="true"/>
                 <s:checkbox label="%{getText('notifier.event.sendOnSuccess')}" name="sendOnSuccess" value="sendOnSuccess" fieldValue="true"/>
                 <s:checkbox label="%{getText('notifier.event.sendOnFailure')}" name="sendOnFailure" value="sendOnFailure" fieldValue="true"/>
                 <s:checkbox label="%{getText('notifier.event.sendOnError')}" name="sendOnError" value="sendOnError" fieldValue="true"/>
                 <s:checkbox label="%{getText('notifier.event.sendOnWarning')}" name="sendOnWarning" value="sendOnWarning" fieldValue="true"/>
                 <s:checkbox label="%{getText('notifier.event.sendOnScmFailure')}" name="sendOnScmFailure" value="sendOnScmFailure" fieldValue="true"/>
-                <s:checkbox label="%{getText('notifier.event.sendOnScmFailure')}" name="sendOnScmFailure" value="sendOnScmFailure" fieldValue="true"/>
               </tbody>
             </table>
             <div class="functnbar3">
-              <c1:submitcancel value="%{getText('save')}" cancel="%{getText('cancel')}"/>
+              <s:submit value="%{getText('save')}" theme="simple"/>
+              <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
             </div>
           </s:form>
         </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/notifierJabber.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/notifierJabber.jsp
index 398997e..850e3be 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/notifierJabber.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/notifierJabber.jsp
@@ -18,7 +18,6 @@
   --%>
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <html>
   <s:i18n name="localization.Continuum">
     <head>
@@ -51,12 +50,12 @@
             <s:hidden name="fromGroupPage"/>
             <table>
               <tbody>
-                <s:textfield label="%{getText('notifier.jabber.host.label')}" name="host" required="true"/>
-                <s:textfield label="%{getText('notifier.jabber.port.label')}" name="port"/>
-                <s:textfield label="%{getText('notifier.jabber.login.label')}" name="login" required="true"/>
-                <s:password label="%{getText('notifier.jabber.password.label')}" name="password" required="true"/>
-                <s:textfield label="%{getText('notifier.jabber.domainName.label')}" name="domainName"/>
-                <s:textfield label="%{getText('notifier.jabber.address.label')}" name="address" required="true"/>
+                <s:textfield label="%{getText('notifier.jabber.host.label')}" name="host" requiredLabel="true" size="100"/>
+                <s:textfield label="%{getText('notifier.jabber.port.label')}" name="port" size="100"/>
+                <s:textfield label="%{getText('notifier.jabber.login.label')}" name="login" requiredLabel="true" size="100"/>
+                <s:password label="%{getText('notifier.jabber.password.label')}" name="password" requiredLabel="true" size="100"/>
+                <s:textfield label="%{getText('notifier.jabber.domainName.label')}" name="domainName" size="100"/>
+                <s:textfield label="%{getText('notifier.jabber.address.label')}" name="address" requiredLabel="true" size="100"/>
                 <s:checkbox label="%{getText('notifier.jabber.isSslConnection.label')}" name="sslConnection" value="sslConnection" fieldValue="true"/>
                 <s:checkbox label="%{getText('notifier.jabber.isGroup.label')}" name="group" value="group" fieldValue="true"/>
                 <s:checkbox label="%{getText('notifier.event.sendOnSuccess')}" name="sendOnSuccess" value="sendOnSuccess" fieldValue="true"/>
@@ -64,11 +63,11 @@
                 <s:checkbox label="%{getText('notifier.event.sendOnError')}" name="sendOnError" value="sendOnError" fieldValue="true"/>
                 <s:checkbox label="%{getText('notifier.event.sendOnWarning')}" name="sendOnWarning" value="sendOnWarning" fieldValue="true"/>
                 <s:checkbox label="%{getText('notifier.event.sendOnScmFailure')}" name="sendOnScmFailure" value="sendOnScmFailure" fieldValue="true"/>
-                <s:checkbox label="%{getText('notifier.event.sendOnScmFailure')}" name="sendOnScmFailure" value="sendOnScmFailure" fieldValue="true"/>
               </tbody>
             </table>
             <div class="functnbar3">
-              <c1:submitcancel value="%{getText('save')}" cancel="%{getText('cancel')}"/>
+              <s:submit value="%{getText('save')}" theme="simple"/>
+              <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
             </div>
           </s:form>
         </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/notifierMail.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/notifierMail.jsp
index 0644e48..52b7226 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/notifierMail.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/notifierMail.jsp
@@ -18,7 +18,6 @@
   --%>
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <html>
   <s:i18n name="localization.Continuum">
     <head>
@@ -43,6 +42,9 @@
             </s:text>
         </h3>
 
+        <s:actionerror/>
+        <s:actionmessage/>
+
         <div class="axial">
           <s:form action="%{actionUrl}" method="post" validate="true">
             <s:hidden name="notifierId"/>
@@ -52,18 +54,19 @@
             <s:hidden name="fromGroupPage"/>
             <table>
               <tbody>
-                <s:textfield label="%{getText('notifier.mail.recipient.address.label')}" name="address" />
+                <s:textfield label="%{getText('notifier.mail.recipient.address.label')}" name="address"  size="100"/>
                 <s:checkbox label="%{getText('notifier.mail.recipient.committers.label')}" name="committers" value="committers" fieldValue="true"/>
+                <s:checkbox label="%{getText('notifier.mail.recipient.developers.label')}" name="developers" value="developers" fieldValue="true"/>
                 <s:checkbox label="%{getText('notifier.event.sendOnSuccess')}" name="sendOnSuccess" value="sendOnSuccess" fieldValue="true"/>
                 <s:checkbox label="%{getText('notifier.event.sendOnFailure')}" name="sendOnFailure" value="sendOnFailure" fieldValue="true"/>
                 <s:checkbox label="%{getText('notifier.event.sendOnError')}" name="sendOnError" value="sendOnError" fieldValue="true"/>
                 <s:checkbox label="%{getText('notifier.event.sendOnWarning')}" name="sendOnWarning" value="sendOnWarning" fieldValue="true"/>
                 <s:checkbox label="%{getText('notifier.event.sendOnScmFailure')}" name="sendOnScmFailure" value="sendOnScmFailure" fieldValue="true"/>
-                <s:checkbox label="%{getText('notifier.event.sendOnScmFailure')}" name="sendOnScmFailure" value="sendOnScmFailure" fieldValue="true"/>
               </tbody>
             </table>
             <div class="functnbar3">
-              <c1:submitcancel value="%{getText('save')}" cancel="%{getText('cancel')}"/>
+              <s:submit value="%{getText('save')}" theme="simple"/>
+              <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
             </div>
           </s:form>
         </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/notifierMsn.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/notifierMsn.jsp
index 910098b..3f7deab 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/notifierMsn.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/notifierMsn.jsp
@@ -18,7 +18,6 @@
   --%>
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <html>
   <s:i18n name="localization.Continuum">
     <head>
@@ -51,19 +50,19 @@
             <s:hidden name="fromGroupPage"/>
             <table>
               <tbody>
-                <s:textfield label="%{getText('notifier.msn.login.label')}" name="login" required="true"/>
-                <s:password label="%{getText('notifier.msn.password.label')}" name="password" required="true"/>
-                <s:textfield label="%{getText('notifier.msn.address.label')}" name="address" required="true"/>
+                <s:textfield label="%{getText('notifier.msn.login.label')}" name="login" requiredLabel="true" size="100"/>
+                <s:password label="%{getText('notifier.msn.password.label')}" name="password" requiredLabel="true" size="100"/>
+                <s:textfield label="%{getText('notifier.msn.address.label')}" name="address" requiredLabel="true" size="100"/>
                 <s:checkbox label="%{getText('notifier.event.sendOnSuccess')}" name="sendOnSuccess" value="sendOnSuccess" fieldValue="true"/>
                 <s:checkbox label="%{getText('notifier.event.sendOnFailure')}" name="sendOnFailure" value="sendOnFailure" fieldValue="true"/>
                 <s:checkbox label="%{getText('notifier.event.sendOnError')}" name="sendOnError" value="sendOnError" fieldValue="true"/>
                 <s:checkbox label="%{getText('notifier.event.sendOnWarning')}" name="sendOnWarning" value="sendOnWarning" fieldValue="true"/>
                 <s:checkbox label="%{getText('notifier.event.sendOnScmFailure')}" name="sendOnScmFailure" value="sendOnScmFailure" fieldValue="true"/>
-                <s:checkbox label="%{getText('notifier.event.sendOnScmFailure')}" name="sendOnScmFailure" value="sendOnScmFailure" fieldValue="true"/>
               </tbody>
             </table>
             <div class="functnbar3">
-              <c1:submitcancel value="%{getText('save')}" cancel="%{getText('cancel')}"/>
+              <s:submit value="%{getText('save')}" theme="simple"/>
+              <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
             </div>
           </s:form>
         </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/notifierSelectType.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/notifierSelectType.jsp
index 934aecd..0a2de6a 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/notifierSelectType.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/notifierSelectType.jsp
@@ -18,7 +18,6 @@
   --%>
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <html>
   <s:i18n name="localization.Continuum">
     <head>
@@ -28,10 +27,10 @@
       <div id="axial" class="h3">
       
         <s:if test="projectId > 0">
-            <s:url id="actionUrl" value="addProjectNotifier!execute" includeParams="none" />
+            <s:url id="actionUrl" value="addProjectNotifier_submit" includeParams="none" />
         </s:if>
         <s:else>
-            <s:url id="actionUrl" value="addProjectGroupNotifier!execute" includeParams="none" />
+            <s:url id="actionUrl" value="addProjectGroupNotifier_submit" includeParams="none" />
         </s:else>
        
         <h3><s:text name="notifier.section.add.title"/></h3>
@@ -48,7 +47,8 @@
               </tbody>
             </table>
             <div class="functnbar3">
-              <c1:submitcancel value="%{getText('submit')}" cancel="%{getText('cancel')}"/>
+              <s:submit value="%{getText('submit')}" theme="simple"/>
+              <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
             </div>
           </s:form>
         </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/notifierWagon.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/notifierWagon.jsp
index c0077e7..a92598b 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/notifierWagon.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/notifier/notifierWagon.jsp
@@ -18,7 +18,6 @@
   --%>
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <html>
   <s:i18n name="localization.Continuum">
     <head>
@@ -53,8 +52,8 @@
 
             <table>
               <tbody>
-                <s:textfield label="%{getText('notifier.wagon.url.label')}" name="url" required="true" />
-                <s:textfield label="%{getText('notifier.wagon.id.label')}" name="id" required="true" />
+                <s:textfield label="%{getText('notifier.wagon.url.label')}" name="url" requiredLabel="true" size="100" />
+                <s:textfield label="%{getText('notifier.wagon.id.label')}" name="id" requiredLabel="true" size="100" />
                 <s:checkbox label="%{getText('notifier.event.sendOnSuccess')}" name="sendOnSuccess" value="sendOnSuccess" fieldValue="true"/>
                 <s:checkbox label="%{getText('notifier.event.sendOnFailure')}" name="sendOnFailure" value="sendOnFailure" fieldValue="true"/>
                 <s:checkbox label="%{getText('notifier.event.sendOnError')}" name="sendOnError" value="sendOnError" fieldValue="true"/>
@@ -63,7 +62,8 @@
             </table>
 
             <div class="functnbar3">
-              <c1:submitcancel value="%{getText('save')}" cancel="%{getText('cancel')}"/>
+              <s:submit value="%{getText('save')}" theme="simple"/>
+              <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
             </div>
           </s:form>
         </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectEdit.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectEdit.jsp
index 8c3a6db..549c323 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectEdit.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectEdit.jsp
@@ -18,7 +18,6 @@
   --%>
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <html>
   <s:i18n name="localization.Continuum">
     <head>
@@ -56,19 +55,20 @@
           <s:form name="editProject" action="projectSave" method="post" validate="true">
             <table>
               <tbody>
-                <s:textfield label="%{getText('projectEdit.project.name.label')}" name="name" required="true"/>
-                <s:textfield label="%{getText('projectEdit.project.version.label')}" name="version" required="true"/>
-                <s:textfield label="%{getText('projectEdit.project.scmUrl.label')}" name="scmUrl" required="true"
-                             onchange="checkUseCache()"/>
+                <s:textfield label="%{getText('projectEdit.project.name.label')}" name="name" requiredLabel="true" size="100"/>
+                <s:textfield label="%{getText('projectEdit.project.version.label')}" name="version" requiredLabel="true" size="100"/>
+                <s:textfield label="%{getText('projectEdit.project.scmUrl.label')}" name="scmUrl" requiredLabel="true"
+                             onchange="checkUseCache()" size="100"/>
                 <s:checkbox label="%{getText('projectEdit.project.scmUseCache.label')}" name="scmUseCache"
-                             onclick="checkUseCache()"/>
-                <s:textfield label="%{getText('projectEdit.project.scmUsername.label')}" name="scmUsername"/>
-                <s:password label="%{getText('projectEdit.project.scmPassword.label')}" name="scmPassword"/>
-                <s:textfield label="%{getText('projectEdit.project.scmTag.label')}" name="scmTag"/>
+                             onclick="checkUseCache()" size="100"/>
+                <s:textfield label="%{getText('projectEdit.project.scmUsername.label')}" name="scmUsername" size="100"/>
+                <s:password label="%{getText('projectEdit.project.scmPassword.label')}" name="scmPassword" size="100"/>
+                <s:textfield label="%{getText('projectEdit.project.scmTag.label')}" name="scmTag" size="100"/>
               </tbody>
             </table>
             <div class="functnbar3">
-              <c1:submitcancel value="%{getText('save')}" cancel="%{getText('cancel')}"/>
+              <s:submit value="%{getText('save')}" theme="simple"/>
+              <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
             </div>
             <s:hidden name="projectId"/>
           </s:form>
@@ -76,4 +76,4 @@
       </div>
     </body>
   </s:i18n>
-</html>
\ No newline at end of file
+</html>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupAdd.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupAdd.jsp
index 7fae251..d7faa8f 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupAdd.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupAdd.jsp
@@ -19,7 +19,6 @@
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
-<%@ taglib uri="continuum" prefix="c1" %>
 <html>
   <s:i18n name="localization.Continuum">
     <head>
@@ -30,8 +29,7 @@
         <h3><s:text name="projectGroup.add.section.title"/></h3>
 
         <div class="axial">
-          <s:url id="actionUrl" action="addProjectGroup" includeContext="false" />
-          <s:form action="%{actionUrl}" method="post" >
+          <s:form action="addProjectGroup" method="post" validate="true">
             <c:if test="${!empty actionErrors}">
               <div class="errormessage">
                 <s:iterator value="actionErrors">
@@ -41,15 +39,16 @@
             </c:if>
             <table>
               <tbody>
-                <s:textfield label="%{getText('projectGroup.name.label')}" name="name"  required="true"/>
-                <s:textfield label="%{getText('projectGroup.groupId.label')}" name="groupId" required="true"/>
-                <s:textfield label="%{getText('projectGroup.description.label')}" name="description"/>
+                <s:textfield label="%{getText('projectGroup.name.label')}" name="name"  requiredLabel="true" size="100"/>
+                <s:textfield label="%{getText('projectGroup.groupId.label')}" name="groupId" requiredLabel="true" size="100"/>
+                <s:textfield label="%{getText('projectGroup.description.label')}" name="description" size="100"/>
                 <s:select label="%{getText('projectGroup.repository.label')}" name="repositoryId" list="repositories"
                 		   listKey="id" listValue="name"/>
               </tbody>
             </table>
             <div class="functnbar3">
-              <c1:submitcancel value="%{getText('save')}" cancel="%{getText('cancel')}"/>
+              <s:submit value="%{getText('save')}" theme="simple"/>
+              <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
             </div>
           </s:form>
         </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupBuildDefinition.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupBuildDefinition.jsp
index 3362d5c..43b39c6 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupBuildDefinition.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupBuildDefinition.jsp
@@ -20,7 +20,6 @@
 <%@ taglib uri="/struts-tags" prefix="s" %>
 <%@ taglib uri="http://www.extremecomponents.org" prefix="ec" %>
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
-<%@ taglib uri="continuum" prefix="c1" %>
 <html>
   <s:i18n name="localization.Continuum">
     <head>
@@ -35,8 +34,8 @@
         </s:action>
 
         <s:action name="groupBuildDefinitionSummary" executeResult="true" namespace="component">
-          <s:param name="projectGroupId">${projectGroupId}</s:param>
-          <s:param name="projectGroupName">${projectGroup.name}</s:param>
+          <s:param name="projectGroupId"><c:out value="${projectGroupId}"/></s:param>
+          <s:param name="projectGroupName"><c:out value="${projectGroup.name}"/></s:param>
         </s:action>
       </div>
     </body>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupEdit.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupEdit.jsp
index d19245f..9764cd5 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupEdit.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupEdit.jsp
@@ -19,7 +19,6 @@
 
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <%@ taglib uri="http://www.extremecomponents.org" prefix="ec" %>
 <html>
   <s:i18n name="localization.Continuum">
@@ -32,54 +31,52 @@
 
         <div class="axial">
           <s:form action="saveProjectGroup" method="post" validate="true">
-              <s:if test="projectInCOQueue">
-                <div class="label">
-                    <p><s:text name="%{getText('project.in.checkout.queue.error')}"/></p>
-                            </div >
-              </s:if>
-              <c:if test="${!empty actionErrors}">
+            <s:if test="projectInCOQueue">
+              <div class="label">
+                <p><s:text name="%{getText('project.in.checkout.queue.error')}"/></p>
+              </div>
+            </s:if>
+            <c:if test="${!empty actionErrors}">
               <div class="errormessage">
                 <s:iterator value="actionErrors">
                   <p><s:property/></p>
                 </s:iterator>
               </div>
-              </c:if>
+            </c:if>
             <table>
-              <tbody>
-                <s:hidden name="projectGroupId"/>
-                <s:textfield label="%{getText('projectGroup.name.label')}" name="name" required="true" disabled="%{projectInCOQueue}"/>
-                <c1:data label="%{getText('projectGroup.groupId.label')}" name="projectGroup.groupId"/>
-                <s:textfield label="%{getText('projectGroup.description.label')}" name="description" disabled="%{projectInCOQueue}"/>
-                <s:select label="%{getText('projectGroup.repository.label')}" name="repositoryId" list="repositories"
-                           listKey="id" listValue="name" disabled="%{disabledRepositories}"/> 
-                <s:textfield label="%{getText('projectGroup.url.label')}" name="url" disabled="%{projectInCOQueue}"/>
-              </tbody>
+              <s:hidden name="projectGroupId"/>
+              <s:textfield label="%{getText('projectGroup.name.label')}" name="name" requiredLabel="true" disabled="%{projectInCOQueue}" size="100"/>
+              <s:textfield label="%{getText('projectGroup.groupId.label')}" disabled="true" name="projectGroup.groupId" size="100"/>
+              <s:textfield label="%{getText('projectGroup.description.label')}" name="description" disabled="%{projectInCOQueue}" size="100"/>
+              <s:select label="%{getText('projectGroup.repository.label')}" name="repositoryId" list="repositories"
+                         listKey="id" listValue="name" disabled="%{disabledRepositories}"/>
+              <s:textfield label="%{getText('projectGroup.url.label')}" name="url" disabled="%{projectInCOQueue}" size="100"/>
             </table>
-            
             <c:if test="${!empty projectList}">
-            <h3><s:text name="projectGroup.edit.section.projects.title"/></h3>
-            <div class="eXtremeTable">
-              <table id="projects_table" border="1" cellspacing="2" cellpadding="3" class="tableRegion" width="100%">
-                <thead>
-                  <tr>
-                    <td class="tableHeader"><s:text name="projectGroup.edit.project.name"/></td>
-                    <td class="tableHeader"><s:text name="projectGroup.edit.move.to.group"/></td>
-                  </tr>
-                </thead>
-                <tbody class="tableBody">
-                  <s:iterator value="projectList" status="rowCounter">
-                    <tr class="<s:if test="#rowCounter.odd == true">odd</s:if><s:else>even</s:else>">
-                      <td><s:select cssStyle="width:200px" label="%{name}" name="projects[%{id}]" list="projectGroups" value="%{projectGroup.id}" disabled="%{projectInCOQueue}"/></td>
+              <h3><s:text name="projectGroup.edit.section.projects.title"/></h3>
+              <div class="eXtremeTable">
+                <table id="projects_table" border="1" cellspacing="2" cellpadding="3" class="tableRegion" width="100%">
+                  <thead>
+                    <tr>
+                      <td class="tableHeader"><s:text name="projectGroup.edit.project.name"/></td>
+                      <td class="tableHeader"><s:text name="projectGroup.edit.move.to.group"/></td>
                     </tr>
-                  </s:iterator>
-                </tbody>
-              </table>
-            </div>
+                  </thead>
+                  <tbody class="tableBody">
+                    <s:iterator value="projectList" status="rowCounter">
+                      <tr class="<s:if test="#rowCounter.odd == true">odd</s:if><s:else>even</s:else>">
+                        <td><s:select cssStyle="width:200px" label="%{name}" name="projects[%{id}]" list="projectGroups" value="%{projectGroup.id}" disabled="%{projectInCOQueue}"/></td>
+                      </tr>
+                    </s:iterator>
+                  </tbody>
+                </table>
+              </div>
             </c:if>
             <div class="functnbar3">
               <c:choose>
                 <c:when test="${!projectInCOQueue}">
-                  <c1:submitcancel value="%{getText('save')}" cancel="%{getText('cancel')}"/>
+                  <s:submit value="%{getText('save')}" theme="simple"/>
+                  <input type="button" name="Cancel" value="<s:text name='cancel'/>" onclick="history.back();"/>
                 </c:when>
                 <c:otherwise>
                   <input type="button" value="<s:text name="back"/>" onClick="history.go(-1)">
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupMembers.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupMembers.jsp
index 1127296..dea0454 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupMembers.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupMembers.jsp
@@ -20,7 +20,6 @@
 <%@ taglib uri="/struts-tags" prefix="s" %>
 <%@ taglib uri="http://www.extremecomponents.org" prefix="ec" %>
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c' %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <%@ taglib uri="http://plexus.codehaus.org/redback/taglib-1.0" prefix="redback" %>
 
 <html>
@@ -41,10 +40,11 @@
       -->
     </div>
 
-    <h3><s:text name="projectGroup.members.section.title"><s:param>${projectGroup.name}</s:param></s:text></h3>
+    <h3><s:text name="projectGroup.members.section.title"><s:param><c:out value="${projectGroup.name}"/></s:param></s:text></h3>
 
     <ec:table items="groupProjects"
               var="project"
+              autoIncludeParameters="false"
               showExports="false"
               showPagination="false"
               showStatusBar="false"
@@ -53,9 +53,9 @@
       <ec:row highlightRow="true">
         <ec:column property="name" title="summary.projectTable.name" width="48%">
           <s:url id="projectViewUrl" action="projectView">
-            <s:param name="projectId">${pageScope.project.id}</s:param>
+            <s:param name="projectId"><c:out value="${pageScope.project.id}"/></s:param>
           </s:url>
-          <s:a href="%{projectViewUrl}">${pageScope.project.name}</s:a>
+          <s:a href="%{projectViewUrl}"><c:out value="${pageScope.project.name}"/></s:a>
         </ec:column>
         <ec:column property="editAction" title="&nbsp;" width="1%" sortable="false">
           <center>
@@ -64,8 +64,8 @@
               <c:when
                   test="${pageScope.project.state == 1 || pageScope.project.state == 10 || pageScope.project.state == 2 || pageScope.project.state == 3 || pageScope.project.state == 4}">
                 <s:url id="editProjectUrl" action="projectEdit">
-                  <s:param name="projectId">${pageScope.project.id}</s:param>
-                  <s:param name="projectName">${project.name}</s:param>
+                  <s:param name="projectId"><c:out value="${pageScope.project.id}"/></s:param>
+                  <s:param name="projectName"><c:out value="${project.name}"/></s:param>
                 </s:url>
                 <s:a href="%{editProjectUrl}">
                   <img src="<s:url value='/images/edit.gif' includeParams="none"/>" alt="<s:text name="edit"/>" title="<s:text name="edit"/>" border="0">
@@ -85,16 +85,21 @@
           <center>
             <redback:ifAuthorized permission="continuum-modify-group" resource="${projectGroup.name}">
             <c:choose>
+              <%-- NEW, OK, FAILED, ERROR, CHECKEDOUT --%>
               <c:when
                   test="${pageScope.project.state == 1 || pageScope.project.state == 10 || pageScope.project.state == 2 || pageScope.project.state == 3 || pageScope.project.state == 4}">
-                <s:url id="removeProjectUrl" action="deleteProject!default.action">
-                  <s:param name="projectId">${pageScope.project.id}</s:param>
-                  <s:param name="projectName">${pageScope.project.name}</s:param>
+                <s:token/>  
+                <s:url id="removeProjectUrl" action="deleteProject_default.action">
+                  <s:param name="projectId"><c:out value="${pageScope.project.id}"/></s:param>
+                  <s:param name="projectName"><c:out value="${pageScope.project.name}"/></s:param>
+                  <s:param name="struts.token.name">token</s:param>
+                  <s:param name="token"><s:property value="token"/></s:param>
                 </s:url>
                 <s:a href="%{removeProjectUrl}">
                   <img src="<s:url value='/images/delete.gif' includeParams="none"/>" alt="<s:text name="delete"/>" title="<s:text name="delete"/>" border="0">
                 </s:a>
               </c:when>
+              <%-- BUILDING, CHECKING_OUT, UPDATING, WARNING, UPDATED, CANCELLED --%>
               <c:otherwise>
                 <img src="<s:url value='/images/delete_disabled.gif' includeParams="none"/>" alt="<s:text name="delete"/>" title="<s:text name="delete"/>" border="0">
               </c:otherwise>
@@ -111,7 +116,7 @@
   <redback:ifAuthorized permission="continuum-manage-users">
   <h3><s:text name="projectGroup.members.users.title"/></h3>
     
-  <s:form action="projectGroupMembers" theme="xhtml" method="post">
+  <s:form action="projectGroupMembers" method="post">
     <s:hidden name="ascending" />
     <s:hidden name="projectGroupId" />
     <tr>
@@ -125,13 +130,11 @@
       </td>               
       <td>
         <table cellpadding="0" cellspacing="0">
-          <s:textfield name="filterKey" />
+          <s:textfield name="filterKey" size="100" />
         </table>
       </td>  
       <td colspan="2" align="right">
-        <table cellpadding="0" cellspacing="0">
-          <s:submit value="%{getText('projectGroup.members.users.search.button')}"/>
-        </table>
+        <s:submit value="%{getText('projectGroup.members.users.search.button')}" theme="simple"/>
       </td>
     </tr>             
   </s:form>
@@ -142,17 +145,18 @@
     <thead>
       <tr>
         <th nowrap="true">
-          <s:form id="sortlist" name="sortlist" action="projectGroupMembers" theme="xhtml" method="post">
+          <s:form id="sortlist" name="sortlist" action="projectGroupMembers" method="post">
             <s:if test="ascending">
               <s:a href="javascript:document.forms['sortlist'].submit()"><img src="<s:url value='/images/icon_sortdown.gif' includeParams="none"/>" title="<s:text name='sort.descending'/>" border="0"></s:a> <s:text name="user.username.label"/>
             </s:if>
             <s:else>
               <s:a href="javascript:document.forms['sortlist'].submit()"><img src="<s:url value='/images/icon_sortup.gif' includeParams="none"/>" title="<s:text name='sort.ascending'/>" border="0"></s:a> <s:text name="user.username.label"/>
             </s:else>
-            <s:hidden name="ascending">${!ascending}</s:hidden>
+            <s:hidden name="ascending" value="%{!ascending}"/>
             <s:hidden name="projectGroupId" />
-            <s:hidden name="filterProperty" />
-            <s:hidden name="filterKey" />
+            <s:hidden name="sorterProperty" value="username"/>
+            <s:hidden name="filterKey" value="%{filterKey}"/>
+            <s:hidden name="filterProperty" value="%{filterProperty}"/>
           </s:form>
         </th>   
         <th><s:text name="user.fullName.label"/></th>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupNotifier.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupNotifier.jsp
index 20dd686..71bdf9f 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupNotifier.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupNotifier.jsp
@@ -20,7 +20,6 @@
 <%@ taglib uri="/struts-tags" prefix="s" %>
 <%@ taglib uri="http://www.extremecomponents.org" prefix="ec" %>
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c' %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <html>
   <s:i18n name="localization.Continuum">
     <head>
@@ -35,7 +34,7 @@
         </s:action>
     
         <s:action name="projectGroupNotifierSummary" executeResult="true" namespace="component">
-          <s:param name="projectGroupId">${projectGroupId}</s:param>
+          <s:param name="projectGroupId"><c:out value="${projectGroupId}"/></s:param>
         </s:action>
       </div>
     </body>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupReleaseResults.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupReleaseResults.jsp
index 35670bb..4b64051 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupReleaseResults.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupReleaseResults.jsp
@@ -20,7 +20,6 @@
 <%@ taglib uri="/struts-tags" prefix="s" %>
 <%@ taglib uri="http://www.extremecomponents.org" prefix="ec" %>
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c' %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt" %>
 <%@ taglib uri="http://plexus.codehaus.org/redback/taglib-1.0" prefix="redback" %>
 
@@ -37,12 +36,13 @@
         <s:param name="tabName" value="'ReleaseResults'"/>
       </s:action>
     
-      <h3><s:text name="projectGroup.releaseResults.section.title"><s:param>${projectGroup.name}</s:param></s:text></h3>
+      <h3><s:text name="projectGroup.releaseResults.section.title"><s:param><c:out value="${projectGroup.name}"/></s:param></s:text></h3>
       
       <form id="releaseResultsForm" action="removeReleaseResults.action" method="post">
-        <s:hidden name="projectGroupId"/>
+        <s:token/>
         <ec:table items="releaseResults"
                 var="result"
+                autoIncludeParameters="false"
                 showExports="false"
                 showPagination="false"
                 showStatusBar="false"
@@ -59,17 +59,19 @@
             <ec:column property="startTime" title="releaseResults.startTime" cell="date"/>
             <ec:column property="endTime" title="releaseResults.endTime" cell="date"/>
             <ec:column property="resultCode" title="releaseResults.state">
-              <s:if test="pageScope.result.resultCode == 0">
-                <s:text name="releaseViewResult.success"/>
-              </s:if>
-              <s:else>
-                <s:text name="releaseViewResult.error"/>
-              </s:else>
+              <c:choose>
+                <c:when test="${pageScope.result.resultCode == 0}">
+                  <s:text name="releaseViewResult.success"/>
+                </c:when>
+                <c:otherwise>
+                  <s:text name="releaseViewResult.error"/>
+                </c:otherwise>
+              </c:choose>
             </ec:column>
             <ec:column property="actions" title="&nbsp;">
                <s:url id="viewReleaseResultUrl" action="viewReleaseResult">
-                 <s:param name="releaseResultId">${pageScope.result.id}</s:param>
-                 <s:param name="projectGroupId">${projectGroupId}</s:param>
+                 <s:param name="releaseResultId"><c:out value="${pageScope.result.id}"/></s:param>
+                 <s:param name="projectGroupId"><c:out value="${projectGroupId}"/></s:param>
                </s:url>
                <s:a href="%{viewReleaseResultUrl}"><s:text name="releaseResults.viewResult"/></s:a>
              </ec:column>
@@ -82,6 +84,7 @@
                 <tr>
                   <td>
                     <redback:ifAuthorized permission="continuum-modify-group" resource="${projectGroup.name}">
+                      <s:hidden name="projectGroupId"/>
                       <input type="button" name="delete-release-results" value="<s:text name="delete"/>" onclick="document.forms.releaseResultsForm.submit();" />
                     </redback:ifAuthorized>
                   </td>
@@ -94,4 +97,4 @@
       </div>
     </body>
   </s:i18n>
-</html>
\ No newline at end of file
+</html>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupSummary.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupSummary.jsp
index b93b72c..c95a4e5 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupSummary.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectGroupSummary.jsp
@@ -20,7 +20,6 @@
 <%@ taglib uri="/struts-tags" prefix="s" %>
 <%@ taglib uri="http://www.extremecomponents.org" prefix="ec" %>
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c' %>
-<%@ taglib uri="continuum" prefix="c1" %>
 <%@ taglib uri="http://plexus.codehaus.org/redback/taglib-1.0" prefix="redback" %>
 
 <html>
@@ -33,8 +32,8 @@
     <meta http-equiv="refresh" content="30"/>
     <script type="text/javascript">
 
-      <c:url var="addM2ProjectUrl" value="/addMavenTwoProjectInput!input.action" />
-      <c:url var="addM1ProjectUrl" value="/addMavenOneProjectInput!input.action" />
+      <c:url var="addM2ProjectUrl" value="/addMavenTwoProjectInput.action" />
+      <c:url var="addM1ProjectUrl" value="/addMavenOneProjectInput.action" />
       <c:url var="addProjectUrl" value="/addProjectInput.action" />
 
       function goToAddProject()
@@ -82,16 +81,31 @@
       <s:param name="tabName" value="'Summary'"/>
     </s:action>
 
-    <h3><s:text name="projectGroup.information.title"/></h3>
+    <h3><s:text name="projectGroup.information.title"><s:param><c:out value="${projectGroup.name}"/></s:param></s:text></h3>
     <div class="axial">
       <table border="1" cellspacing="2" cellpadding="3" width="100%">
-        <c1:data label="%{getText('projectGroup.name.label')}" name="projectGroup.name"/>
-        <c1:data label="%{getText('projectGroup.groupId.label')}" name="projectGroup.groupId"/>
-        <c1:data label="%{getText('projectGroup.description.label')}" name="projectGroup.description"/>
-        <c1:data label="%{getText('projectGroup.repository.label')}" name="projectGroup.localRepository.name"/>
+        <tr class="b">
+          <th><label class="label"><s:text name='projectGroup.name.label'/>:</label></th>
+          <td><s:property value="projectGroup.name"/></td>
+        </tr>
+        <tr class="b">
+          <th><label class="label"><s:text name='projectGroup.groupId.label'/>:</label></th>
+          <td><s:property value="projectGroup.groupId"/></td>
+        </tr>
+        <tr class="b">
+          <th><label class="label"><s:text name='projectGroup.description.label'/>:</label></th>
+          <td><s:property value="projectGroup.description"/></td>
+        </tr>
+        <tr class="b">
+          <th><label class="label"><s:text name='projectGroup.repository.label'/>:</label></th>
+          <td><s:property value="projectGroup.localRepository.name"/></td>
+        </tr>
         <s:if test="url != null">
             <s:url id="projectHomepageUrl" value="%{url}" includeContext="false" includeParams="none"/>
-        	<c1:data label="%{getText('projectGroup.url.label')}" name="url" valueLink="%{'${projectHomepageUrl}'}"/>  
+            <tr class="b">
+              <th><label class="label"><s:text name='projectGroup.url.label'/>:</label></th>
+              <td><a href="${projectHomepageUrl}"><s:property value="url"/></a></td>
+            </tr>
         </s:if>
       </table>
     </div>
@@ -99,6 +113,7 @@
     <h3><s:text name="projectGroup.scmRoot.title"/></h3>
     <ec:table items="projectScmRoots"
               var="projectScmRoot"
+              autoIncludeParameters="false"
               showExports="false"
               showPagination="false"
               showStatusBar="false"
@@ -164,12 +179,12 @@
                 <s:select theme="simple" name="preferredExecutor" list="#@java.util.HashMap@{'maven2' : 'Add M2 Project', 'maven-1' : 'Add M1 Project', 'ant' : 'Add Ant Project', 'shell' : 'Add Shell Project'}"
                     headerValue="Choose the project type" headerKey="" emptyOption="true" />
 
-                <input type="button" value="Add" onclick="goToAddProject()"/>
+                <input type="button" value="<s:text name="add"/>" onclick="goToAddProject()"/>
               </redback:ifAnyAuthorized>
             </td>
             <td>
               <redback:ifAuthorized permission="continuum-remove-group" resource="${projectGroup.name}">
-                <form action="removeProjectGroup.action" method="post">
+                <form action="confirmRemoveProjectGroup.action" method="post">
                   <input type="hidden" name="projectGroupId" value="<s:property value="projectGroupId"/>"/>
                   <input type="submit" name="remove" value="<s:text name="projectGroup.deleteGroup"/>"/>
                 </form>
@@ -189,8 +204,8 @@
     </redback:ifAnyAuthorized>
 
     <s:action name="projectSummary" executeResult="true" namespace="component">
-      <s:param name="projectGroupId">${projectGroupId}</s:param>
-      <s:param name="projectGroupName">${projectGroup.name}</s:param>
+      <s:param name="projectGroupId"><c:out value="${projectGroupId}"/></s:param>
+      <s:param name="projectGroupName"><c:out value="${projectGroup.name}"/></s:param>
     </s:action>
 
   </div>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectView.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectView.jsp
index a7734ce..6176f94 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectView.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/projectView.jsp
@@ -20,7 +20,6 @@
 <%@ taglib uri="/struts-tags" prefix="s" %>
 <%@ taglib uri="http://www.extremecomponents.org" prefix="ec" %>
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
-<%@ taglib uri="continuum" prefix="c1" %>
 <%@ taglib uri="http://plexus.codehaus.org/redback/taglib-1.0" prefix="redback" %>
 
 <html>
@@ -35,19 +34,41 @@
           <jsp:param name="tab" value="view"/>
         </jsp:include>
 
-        <h3><s:text name="projectView.section.title"/></h3>
+        <h3><s:text name="projectView.section.title"><s:param><c:out value="${project.name}"/></s:param></s:text></h3>
 
         <div class="axial">
           <table border="1" cellspacing="2" cellpadding="3" width="100%">
-            <c1:data label="%{getText('projectView.project.name')}" name="project.name"/>
-            <c1:data label="%{getText('projectView.project.version')}" name="project.version"/>
-            <c1:data label="%{getText('projectView.project.scmUrl')}" name="project.scmUrl"/>
-            <c1:data label="%{getText('projectView.project.scmTag')}" name="project.scmTag"/>
+            <tr class="b">
+              <th><label class="label"><s:text name='projectView.project.name'/>:</label></th>
+              <td><s:property value="project.name"/></td>
+            </tr>
+            <tr class="b">
+              <th><label class="label"><s:text name='projectView.project.description'/>:</label></th>
+              <td><s:property value="project.description"/></td>
+            </tr>
+            <tr class="b">
+              <th><label class="label"><s:text name='projectView.project.version'/>:</label></th>
+              <td><s:property value="project.version"/></td>
+            </tr>
+            <tr class="b">
+              <th><label class="label"><s:text name='projectView.project.scmUrl'/>:</label></th>
+              <td><s:property value="project.scmUrl"/></td>
+            </tr>
+            <tr class="b">
+              <th><label class="label"><s:text name='projectView.project.scmTag'/>:</label></th>
+              <td><s:property value="project.scmTag"/></td>
+            </tr>
             <s:url id="projectGroupSummaryUrl" value="/projectGroupSummary.action">
-                <s:param name="projectGroupId">${project.projectGroup.id}</s:param>
+                <s:param name="projectGroupId"><c:out value="${project.projectGroup.id}"/></s:param>
             </s:url>
-            <c1:data label="%{getText('projectView.project.group')}" name="project.projectGroup.name" valueLink="%{'${projectGroupSummaryUrl}'}"/>
-            <c1:data label="%{getText('projectView.project.lastBuildDateTime')}" name="lastBuildDateTime" />
+            <tr class="b">
+              <th><label class="label"><s:text name='projectView.project.group'/>:</label></th>
+              <td><a href="${projectGroupSummaryUrl}"><s:property value="project.projectGroup.name"/></a></td>
+            </tr>
+            <tr class="b">
+              <th><label class="label"><s:text name='projectView.project.lastBuildDateTime'/>:</label></th>
+              <td><s:property value="lastBuildDateTime"/></td>
+            </tr>
           </table>
 
           <redback:ifAuthorized permission="continuum-modify-group" resource="${project.projectGroup.name}">
@@ -78,8 +99,8 @@
         <h3><s:text name="projectView.buildDefinitions"/></h3>
 
         <s:action name="buildDefinitionSummary" id="summary" namespace="component" executeResult="true">
-          <s:param name="projectId">${project.id}</s:param>
-          <s:param name="projectGroupId">${project.projectGroup.id}</s:param>
+          <s:param name="projectId"><c:out value="${project.id}"/></s:param>
+          <s:param name="projectGroupId"><c:out value="${project.projectGroup.id}"/></s:param>
         </s:action>
 
         <div class="functnbar3">
@@ -87,7 +108,7 @@
           <s:form action="buildDefinition" method="post">
             <input type="hidden" name="projectId" value="<s:property value="project.id"/>"/>
             <input type="hidden" name="projectGroupId" value="<s:property value="project.projectGroup.id"/>"/>
-            <s:submit value="%{getText('add')}"/>
+            <s:submit value="%{getText('add')}" theme="simple"/>
           </s:form>
           </redback:ifAuthorized>
         </div>
@@ -97,6 +118,7 @@
           <s:set name="notifiers" value="project.notifiers" scope="request"/>
           <ec:table items="notifiers"
                     var="notifier"
+                    autoIncludeParameters="false"
                     showExports="false"
                     showPagination="false"
                     showStatusBar="false"
@@ -112,10 +134,10 @@
                   <c:choose>
                     <c:when test="${!pageScope.notifier.fromProject}">
                       <s:url id="editUrl" action="editProjectNotifier" namespace="/" includeParams="none">
-                        <s:param name="notifierId">${notifier.id}</s:param>
-                        <s:param name="projectId" value="project.id"/>
-                        <s:param name="projectGroupId">${project.projectGroup.id}</s:param>
-                        <s:param name="notifierType">${notifier.type}</s:param>
+                        <s:param name="notifierId"><c:out value="${notifier.id}"/></s:param>
+                        <s:param name="projectId"><c:out value="${project.id}"/></s:param>
+                        <s:param name="projectGroupId"><c:out value="${project.projectGroup.id}"/></s:param>
+                        <s:param name="notifierType"><c:out value="${notifier.type}"/></s:param>
                       </s:url>
                       <s:a href="%{editUrl}">
                         <img src="<s:url value='/images/edit.gif' includeParams="none"/>" alt="<s:text name="edit"/>" title="<s:text name="edit"/>" border="0">
@@ -134,11 +156,11 @@
                 <redback:ifAuthorized permission="continuum-modify-group" resource="${project.projectGroup.name}">
                   <c:choose>
                     <c:when test="${!pageScope.notifier.fromProject}">
-                      <s:url id="removeUrl" action="deleteProjectNotifier" namespace="/">
-                        <s:param name="projectId" value="project.id"/>
-                        <s:param name="projectGroupId">${project.projectGroup.id}</s:param>
-                        <s:param name="notifierType">${notifier.type}</s:param>
-                        <s:param name="notifierId">${notifier.id}</s:param>
+                      <s:url id="removeUrl" action="deleteProjectNotifier_default.action" namespace="/">
+                        <s:param name="projectId"><c:out value="${project.id}"/></s:param>
+                        <s:param name="projectGroupId"><c:out value="${project.projectGroup.id}"/></s:param>
+                        <s:param name="notifierType"><c:out value="${notifier.type}"/></s:param>
+                        <s:param name="notifierId"><c:out value="${notifier.id}"/></s:param>
                     </s:url>
                     <s:a href="%{removeUrl}">
                       <img src="<s:url value='/images/delete.gif' includeParams="none"/>" alt="<s:text name="delete"/>" title="<s:text name="delete"/>" border="0">
@@ -158,10 +180,10 @@
         </c:if>
         <div class="functnbar3">
            <redback:ifAuthorized permission="continuum-modify-group" resource="${project.projectGroup.name}">
-          <s:form action="addProjectNotifier!default.action" method="post">
+          <s:form action="addProjectNotifier.action" method="post">
             <input type="hidden" name="projectId" value="<s:property value="project.id"/>"/>
             <input type="hidden" name="projectGroupId" value="<s:property value="project.projectGroup.id"/>"/>
-            <s:submit value="%{getText('add')}"/>
+            <s:submit value="%{getText('add')}" theme="simple"/>
           </s:form>
           </redback:ifAuthorized>
         </div>
@@ -170,6 +192,7 @@
         <s:set name="dependencies" value="project.dependencies" scope="request"/>
         <ec:table items="dependencies"
                   var="dep"
+                  autoIncludeParameters="false"
                   showExports="false"
                   showPagination="false"
                   showStatusBar="false"
@@ -185,6 +208,7 @@
         <h3><s:text name="projectView.developers"/></h3>
         <s:set name="developers" value="project.developers" scope="request"/>
         <ec:table items="developers"
+                  autoIncludeParameters="false"
                   showExports="false"
                   showPagination="false"
                   showStatusBar="false"
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/releaseFinished.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/releaseFinished.jsp
index 84fe93f..ded8241 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/releaseFinished.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/releaseFinished.jsp
@@ -32,21 +32,21 @@
             <th><s:text name="releaseInProgress.status"/></th>
             <th width="100%"><s:text name="releaseInProgress.phase"/></th>
           </tr>
-          <s:iterator value="listener.phases">
+          <s:iterator value="listenerSummary.phases">
             <tr>
               <td>
-              <s:if test="listener.completedPhases.contains( top )">
+              <s:if test="listenerSummary.completedPhases.contains( top )">
                 <img src="<s:url value='/images/icon_success_sml.gif' includeParams="none"/>"
-                     alt="Done" title="Done" border="0">
+                     alt="<s:text name="done"/>" title="<s:text name="done"/>" border="0">
               </s:if>
-              <s:elseif test="listener.inProgress.equals( top )">
-                <s:if test="listener.error == null">
+              <s:elseif test="listenerSummary.inProgress.equals( top )">
+                <s:if test="listenerSummary.error == null">
                   <img src="<s:url value='/images/building.gif' includeParams="none"/>"
-                       alt="In Progress" title="In Progress" border="0">
+                       alt="<s:text name="in.progress"/>" title="<s:text name="in.progress"/>" border="0">
                 </s:if>
                 <s:else>
                   <img src="<s:url value='/images/icon_error_sml.gif' includeParams="none"/>"
-                       alt="Error" title="Error" border="0">
+                       alt="<s:text name="error"/>" title="<s:text name="error"/>" border="0">
                 </s:else>
               </s:elseif>
               </td>
@@ -59,6 +59,7 @@
       <p>
         <s:url id="releaseViewResultUrl" action="releaseViewResult" namespace="/">
           <s:param name="releaseId" value="releaseId"/>
+          <s:param name="projectId" value="projectId"/>
         </s:url>
         <s:a href="%{releaseViewResultUrl}"><s:text name="releaseInProgress.viewOutput"/></s:a>
       </p>
@@ -70,14 +71,14 @@
               <s:hidden name="projectId"/>
               <s:hidden name="releaseId"/>
               <s:hidden name="releaseGoal"/>
-              <s:submit value="Rollback Changes"/>
+              <s:submit value="%{getText('rollback')}" theme="simple"/>
             </s:form>
           </td>
           <td>
             <s:form action="releaseCleanup" method="post">
               <s:hidden name="projectId"/>
               <s:hidden name="releaseId"/>
-              <s:submit value="Done"/>
+              <s:submit value="%{getText('done')}" theme="simple"/>
             </s:form>
           </td>
         </tr>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/releaseInProgress.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/releaseInProgress.jsp
index 6ea46b7..2203b66 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/releaseInProgress.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/releaseInProgress.jsp
@@ -33,26 +33,26 @@
             <th><s:text name="releaseInProgress.status"/></th>
             <th width="100%"><s:text name="releaseInProgress.phase"/></th>
           </tr>
-          <s:iterator value="listener.phases">
+          <s:iterator value="listenerSummary.phases">
             <tr>
               <td>
-              <s:if test="listener.completedPhases.contains( top )">
+              <s:if test="listenerSummary.completedPhases.contains( top )">
                 <img src="<s:url value='/images/icon_success_sml.gif' includeParams="none"/>"
-                     alt="Done" title="Done" border="0">
+                     alt="<s:text name="done"/>" title="<s:text name="done"/>" border="0">
               </s:if>
-              <s:elseif test="listener.inProgress.equals( top )">
-                <s:if test="listener.error == null">
+              <s:elseif test="listenerSummary.inProgress.equals( top )">
+                <s:if test="listenerSummary.error == null">
                   <img src="<s:url value='/images/building.gif' includeParams="none"/>"
-                       alt="In Progress" title="In Progress" border="0">
+                       alt="<s:text name="in.progress"/>" title="<s:text name="in.progress"/>" border="0">
                 </s:if>
                 <s:else>
                   <img src="<s:url value='/images/icon_error_sml.gif' includeParams="none"/>"
-                       alt="Error" title="Error" border="0">
+                       alt="<s:text name="error"/>" title="<s:text name="error"/>" border="0">
                 </s:else>
               </s:elseif>
               <s:else>
                 <img src="<s:url value='/images/inqueue.gif' includeParams="none"/>"
-                     alt="Queued" title="Queued" border="0">
+                     alt="<s:text name="queued"/>" title="<s:text name="queued"/>" border="0">
               </s:else>
               </td>
               <td><s:property/></td>
@@ -65,7 +65,7 @@
         <s:hidden name="projectId"/>
         <s:hidden name="releaseId"/>
         <s:hidden name="releaseGoal"/>
-        <s:submit value="Refresh"/>
+        <s:submit value="%{getText('refresh')}"/>
       </s:form>
     </body>
   </s:i18n>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/releaseInitialized.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/releaseInitialized.jsp
index 87b7edd..1be5ba7 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/releaseInitialized.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/releaseInitialized.jsp
@@ -27,17 +27,13 @@
     <body>
       <h2><s:text name="releaseInProgress.section.title"/></h2>
       <h3><s:property value="name"/></h3>
-      <p>
-        The release goal is currently initializing...
-      </p>
-      <p>
-        Please wait while the server prepares your project for release.
-      </p>
+      <p><s:text name="releaseInProgress.currently.initializing"/></p>
+      <p><s:text name="releaseInProgress.please.wait"/></p>
       <s:form action="releaseInProgress" method="get">
         <s:hidden name="projectId"/>
         <s:hidden name="releaseId"/>
         <s:hidden name="releaseGoal"/>
-        <s:submit value="Refresh"/>
+        <s:submit value="%{getText('refresh')}"/>
       </s:form>
     </body>
   </s:i18n>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/releasePerform.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/releasePerform.jsp
index c833cfa..281e224 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/releasePerform.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/releasePerform.jsp
@@ -31,8 +31,9 @@
         <s:hidden name="releaseId"/>
         <div class="axial">
           <table border="1" cellspacing="2" cellpadding="3" width="100%">
-            <s:textfield label="Maven Arguments" name="goals" value="clean deploy"/>
-            <s:checkbox label="Use Release Profile" name="useReleaseProfile" value="true"/>
+            <s:textfield label="%{getText('releasePerformFromScm.goals.label')}" name="goals" size="100"/>
+            <s:textfield label="%{getText('releasePrepare.arguments.label')}" name="arguments" size="100"/>
+            <s:checkbox label="%{getText('releasePerformFromScm.useReleaseProfile.label')}" name="useReleaseProfile"/>
           </table>
         </div>
         <s:submit/>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/releasePerformFromScm.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/releasePerformFromScm.jsp
index 72f8ccb..869077b 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/releasePerformFromScm.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/releasePerformFromScm.jsp
@@ -22,29 +22,30 @@
 <html>
   <s:i18n name="localization.Continuum">
     <head>
-        <title><s:text name="releaseProject.page.title"/></title>
+        <title><s:text name="releasePerformFromScm.page.title"/></title>
     </head>
     <body>
-      <h2>Perform Project Release</h2>
+      <h2><s:text name="releasePerformFromScm.section.title"/></h2>
       <s:form action="releasePerformFromScm" method="post" validate="true">
-        <h3>Release Perform Parameters</h3>
+        <h3><s:text name="releasePerformFromScm.parameters.section.title"/></h3>
         <s:hidden name="projectId"/>
         <div class="axial">
           <table border="1" cellspacing="2" cellpadding="3" width="100%">
-            <s:textfield label="%{getText('releasePerformFromScm.scmUrl.label')}" name="scmUrl"/>
-            <s:textfield label="%{getText('releasePerformFromScm.scmUsername.label')}" name="scmUsername"/>
-            <s:password label="%{getText('releasePerformFromScm.scmPassword.label')}" name="scmPassword"/>
-            <s:textfield label="%{getText('releasePerformFromScm.scmTag.label')}" name="scmTag"/>
+            <s:textfield label="%{getText('releasePerformFromScm.scmUrl.label')}" name="scmUrl" size="100"/>
+            <s:textfield label="%{getText('releasePerformFromScm.scmUsername.label')}" name="scmUsername" size="100"/>
+            <s:password label="%{getText('releasePerformFromScm.scmPassword.label')}" name="scmPassword" size="100"/>
+            <s:textfield label="%{getText('releasePerformFromScm.scmTag.label')}" name="scmTag" size="100"/>
             <c:if test="${!empty (scmTagBase)}">
-              <s:textfield label="%{getText('releasePerformFromScm.scmTagBase.label')}" name="scmTagBase"/>
+              <s:textfield label="%{getText('releasePerformFromScm.scmTagBase.label')}" name="scmTagBase" size="100"/>
             </c:if>
-            <s:textfield label="%{getText('releasePerformFromScm.goals.label')}" name="goals" value="clean deploy"/>
-            <s:checkbox label="%{getText('releasePerformFromScm.useReleaseProfile.label')}" name="useReleaseProfile" value="true"/>
+            <s:textfield label="%{getText('releasePerformFromScm.goals.label')}" name="goals" size="100"/>
+            <s:textfield label="%{getText('releasePrepare.arguments.label')}" name="arguments" size="100"/>
+            <s:checkbox label="%{getText('releasePerformFromScm.useReleaseProfile.label')}" name="useReleaseProfile"/>
             <s:select label="%{getText('releasePerformFromScm.buildEnvironment.label')}" name="profileId" list="profiles" listValue="name"
                        listKey="id" headerKey="-1" headerValue=""/>
           </table>
         </div>
-        <s:submit/>
+        <s:submit value="%{getText('submit')}"/>
       </s:form>
     </body>
   </s:i18n>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/releasePrepare.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/releasePrepare.jsp
index 15186db..a6b8c7e 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/releasePrepare.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/releasePrepare.jsp
@@ -23,25 +23,31 @@
   <s:i18n name="localization.Continuum">
     <head>
       <title><s:text name="releaseProject.page.title"/></title>
-      <s:head />
     </head>
     <body>
       <h2><s:text name="releasePrepare.section.title"/></h2>
       <s:form action="releasePrepare" method="post">
         <h3><s:text name="releasePrepare.parameters"/></h3>
         <input type="hidden" name="projectId" value="<s:property value="projectId"/>"/>
+        <input type="hidden" name="autoVersionSubmodules" value="<s:property value="autoVersionSubmodules"/>"/>
         <div class="axial">
           <table border="1" cellspacing="2" cellpadding="3" width="100%">
-            <s:textfield label="%{getText('releasePrepare.scmUsername.label')}" name="scmUsername" required="true"/>
-            <s:password label="%{getText('releasePrepare.scmPassword.label')}" name="scmPassword" required="true"/>
-            <s:textfield label="%{getText('releasePrepare.scmTag.label')}" name="scmTag" required="true"/>
+            <s:textfield label="%{getText('releasePrepare.scmUsername.label')}" name="scmUsername" size="100"/>
+            <s:password label="%{getText('releasePrepare.scmPassword.label')}" name="scmPassword" size="100"/>
+            <s:textfield label="%{getText('releasePrepare.scmTag.label')}" name="scmTag" requiredLabel="true" size="100"/>
             <c:if test="${!empty (scmTagBase)}">
-              <s:textfield label="%{getText('releasePrepare.scmTagBase.label')}" name="scmTagBase"/>
+              <s:textfield label="%{getText('releasePrepare.scmTagBase.label')}" name="scmTagBase" size="100"/>
             </c:if>
-            <s:textfield label="%{getText('releasePrepare.prepareGoals.label')}" name="prepareGoals" required="true"/>
+            <s:textfield label="%{getText('releasePrepare.scmCommentPrefix.label')}" name="scmCommentPrefix" size="100"/>
+            <s:textfield label="%{getText('releasePrepare.prepareGoals.label')}" name="prepareGoals" requiredLabel="true" size="100"/>
+            <s:textfield label="%{getText('releasePrepare.arguments.label')}" name="arguments" size="100"/>
             <s:select label="%{getText('releasePrepare.buildEnvironment.label')}" name="profileId" list="profiles" listValue="name"
                        listKey="id" headerKey="-1" headerValue=""/>
 			      <s:checkbox label="%{getText('releasePrepare.useEditMode.label')}" name="scmUseEditMode" fieldValue="false"/>
+            <s:checkbox label="%{getText('releasePrepare.addSchema.label')}" name="addSchema" fieldValue="false"/>
+            <c:if test="${autoVersionSubmodules}">
+              <s:checkbox label="%{getText('releasePrepare.autoVersionSubmodules.label')}" name="autoVersionSubmodules" disabled="true" fieldValue="false"/>
+            </c:if>
           </table>
         </div>
 
@@ -68,7 +74,7 @@
            </div>
         </s:iterator>
 
-        <s:submit/>
+        <s:submit value="%{getText('submit')}"/>
       </s:form>
     </body>
   </s:i18n>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/releaseProject.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/releaseProject.jsp
index a2e244d..f3224ea 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/releaseProject.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/releaseProject.jsp
@@ -18,6 +18,7 @@
   --%>
 
 <%@ taglib uri="/struts-tags" prefix="s" %>
+<%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
 <html>
   <s:i18n name="localization.Continuum">
     <head>
@@ -37,17 +38,17 @@
           <br/>
           &nbsp;&nbsp;&nbsp;
           <select name="preparedReleaseId">
-            <s:if test="preparedReleaseName != null">
-              <option selected value="<s:property value="preparedReleaseId"/>">
-                <s:property value="preparedReleaseName"/>
+            <c:forEach var="preparedRelease" items="${preparedReleases}">
+              <option selected value="<c:out value="${preparedRelease.key}"/>">
+                <c:out value="${preparedRelease.value}"/>
               </option>
-            </s:if>
+            </c:forEach>
             <option value=""><s:text name="releaseProject.provideReleaseParameters"/></option>
           </select>
           <br/>
         </p>
         <input name="projectId" type="hidden" value="<s:property value="projectId"/>"/>
-        <s:submit value="Submit"/>
+        <s:submit value="%{getText('submit')}"/>
       </s:form>
     </body>
   </s:i18n>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/releaseRollbackWarning.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/releaseRollbackWarning.jsp
index 597aea2..eacb665 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/releaseRollbackWarning.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/releaseRollbackWarning.jsp
@@ -25,18 +25,16 @@
     </head>
     <body>
       <h3>
-        <s:text name="releaseProject.section.title">
-          <s:param><s:property value="projectName"/></s:param>
-        </s:text>
+        <s:text name="releaseProject.rollbackWarning.section.title"/>
       </h3>
-      <p>This will revert all changes made by the previous release?</p>
+      <p><s:text name="releaseProject.rollbackWarning"/></p>
       <table>
         <tr>
           <td>
             <s:form action="releaseRollback" method="post">
               <s:hidden name="projectId"/>
               <s:hidden name="releaseId"/>
-              <s:submit value="Rollback Changes"/>
+              <s:submit value="%{getText('rollback')}" theme="simple"/>
             </s:form>
           </td>
           <td>
@@ -44,7 +42,7 @@
               <s:hidden name="projectId"/>
               <s:hidden name="releaseId"/>
               <s:hidden name="releaseGoal"/>
-              <s:submit value="Cancel"/>
+              <s:submit value="%{getText('cancel')}" theme="simple"/>
             </s:form>
           </td>
         </tr>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/releaseViewResult.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/releaseViewResult.jsp
index 424a1f4..83815ed 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/releaseViewResult.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/releaseViewResult.jsp
@@ -30,28 +30,37 @@
       <h4><s:text name="releaseViewResult.summary"/></h4>
       <div class="axial">
         <table border="1" cellspacing="2" cellpadding="3" width="100%">
-          <c1:data label="%{getText('releaseViewResult.projectName')}">
-            <s:param name="after"><s:property value="projectName"/></s:param>
-          </c1:data>
-          <c1:data label="%{getText('releaseViewResult.releaseGoal')}">
-            <s:param name="after"><s:property value="releaseGoal"/></s:param>
-          </c1:data>
-          <c1:data label="%{getText('releaseViewResult.startTime')}">
-              <s:param name="after"><c1:date name="result.startTime"/></s:param>
-          </c1:data>
-          <c1:data label="%{getText('releaseViewResult.endTime')}">
-              <s:param name="after"><c1:date name="result.endTime"/></s:param>
-          </c1:data>
-          <c1:data label="%{getText('releaseViewResult.state')}">
-            <s:param name="after">
+          <tr class="b">
+            <th><label class="label"><s:text name='releaseViewResult.projectName'/>:</label></th>
+            <td><s:property value="projectName"/></td>
+          </tr>
+          <tr class="b">
+            <th><label class="label"><s:text name='releaseViewResult.releaseGoal'/>:</label></th>
+            <td><s:property value="releaseGoal"/></td>
+          </tr>
+          <tr class="b">
+            <th><label class="label"><s:text name='releaseViewResult.startTime'/>:</label></th>
+            <td><c1:date name="result.startTime"/></td>
+          </tr>
+          <tr class="b">
+            <th><label class="label"><s:text name='releaseViewResult.endTime'/>:</label></th>
+            <td><c1:date name="result.endTime"/></td>
+          </tr>
+          <tr class="b">
+            <th><label class="label"><s:text name='releaseViewResult.state'/>:</label></th>
+            <td>
               <s:if test="result.resultCode == 0">
                 <s:text name="releaseViewResult.success"/>
               </s:if>
               <s:else>
                 <s:text name="releaseViewResult.error"/>
               </s:else>
-            </s:param>
-          </c1:data>
+            </td>
+          </tr>
+          <tr class="b">
+            <th><label class="label"><s:text name='releaseViewResult.username'/>:</label></th>
+            <td><s:property value="username"/></td>
+          </tr>
         </table>
       </div>
 
@@ -66,7 +75,7 @@
           </div>
         </s:else>
       </p>
-      <input type="button" value="Back" onClick="history.go(-1)">
+      <input type="button" value="<s:text name="back"/>" onClick="history.go(-1)">
 
     </body>
   </s:i18n>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/releases.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/releases.jsp
new file mode 100644
index 0000000..3754f76
--- /dev/null
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/releases.jsp
@@ -0,0 +1,64 @@
+<%--
+  ~ 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="http://www.extremecomponents.org" prefix="ec" %>
+<%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
+
+<html>
+  <s:i18n name="localization.Continuum">
+    <head>
+      <title><s:text name="releases.page.title"/></title>
+    </head>
+    <body>
+      <div id="h3">
+        <h3><s:text name="releases.section.title"/></h3>
+        <c:if test="${!empty actionErrors}">
+          <div class="errormessage">
+            <s:iterator value="actionErrors">
+              <p><s:text name="<s:property/>" /></p>
+            </s:iterator>
+          </div>
+        </c:if>
+        <s:set name="releasesSummary" value="releasesSummary" scope="request"/>
+        <ec:table items="releasesSummary"
+                  var="releaseSummary"
+                  autoIncludeParameters="false"
+                  showExports="false"
+                  showPagination="false"
+                  showStatusBar="false"
+                  sortable="false"
+                  filterable="false">
+          <ec:row>
+            <ec:column property="releaseId" title="releaseSummary.table.releaseId">
+              <s:url id="viewReleaseUrl" action="releaseInProgress">
+                <s:param name="releaseId"><c:out value="${pageScope.releaseSummary.releaseId}"/></s:param>
+                <s:param name="projectId"><c:out value="${pageScope.releaseSummary.projectId}"/></s:param>
+                <s:param name="releaseGoal"><c:out value="${pageScope.releaseSummary.releaseGoal}"/></s:param>
+              </s:url>
+              <s:a href="%{viewReleaseUrl}"><c:out value="${pageScope.releaseSummary.releaseId}"/></s:a>
+            </ec:column>
+            <ec:column property="releaseGoal" title="releaseSummary.table.releaseGoal"/>
+            <ec:column property="buildAgentUrl" title="releaseSummary.table.buildAgentUrl"/>
+          </ec:row>
+        </ec:table>
+      </div>
+    </body>
+  </s:i18n>
+</html>
\ No newline at end of file
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/schedules.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/schedules.jsp
index 7f91a9d..be19788 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/schedules.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/schedules.jsp
@@ -31,6 +31,7 @@
         <s:set name="schedules" value="schedules" scope="request"/>
         <ec:table items="schedules"
                   var="schedule"
+                  autoIncludeParameters="false"
                   showExports="false"
                   showPagination="false"
                   showStatusBar="false"
@@ -45,14 +46,17 @@
             <ec:column property="active" title="schedules.table.active"/>
             <ec:column property="editActions" title="&nbsp;" width="1%">
                 <s:url id="editScheduleUrl" action="schedule">
-                  <s:param name="id">${pageScope.schedule.id}</s:param>
+                  <s:param name="id"><c:out value="${pageScope.schedule.id}"/></s:param>
                 </s:url>
                 <s:a href="%{editScheduleUrl}"><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="editActions" title="&nbsp;" width="1%">
+                <s:token/>
                 <s:url id="removeScheduleUrl" action="removeSchedule">
-                  <s:param name="id">${pageScope.schedule.id}</s:param>
-                  <s:param name="name">${pageScope.schedule.name}</s:param>
+                  <s:param name="id"><c:out value="${pageScope.schedule.id}"/></s:param>
+                  <s:param name="name"><c:out value="${pageScope.schedule.name}"/></s:param>
+                  <s:param name="struts.token.name">token</s:param>
+                  <s:param name="token"><s:property value="token"/></s:param>
                 </s:url>
                 <s:a href="%{removeScheduleUrl}"><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>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/scmResult.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/scmResult.jsp
index e869492..fece1df 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/scmResult.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/scmResult.jsp
@@ -17,7 +17,6 @@
   ~ under the License.
   --%>
 <%@ taglib uri="/struts-tags" prefix="s" %>
-<%@ taglib prefix="c1" uri="continuum" %>
 <html>
   <s:i18n name="localization.Continuum">
     <head>
@@ -31,9 +30,18 @@
         </h3>
         <div class="axial">
           <table border="1" cellspacing="2" cellpadding="3" width="100%">
-            <c1:data label="%{getText('scmResult.projectGroupName')}" name="projectGroupName"/>
-            <c1:data label="%{getText('scmResult.scmRootAddress')}" name="projectScmRoot.scmRootAddress"/>
-            <c1:data label="%{getText('scmResult.state')}" name="state"/>
+            <tr class="b">
+              <th><label class="label"><s:text name='scmResult.projectGroupName'/>:</label></th>
+              <td><s:property value="projectGroupName"/></td>
+            </tr>
+            <tr class="b">
+              <th><label class="label"><s:text name='scmResult.scmRootAddress'/>:</label></th>
+              <td><s:property value="projectScmRoot.scmRootAddress"/></td>
+            </tr>
+            <tr class="b">
+              <th><label class="label"><s:text name='scmResult.state'/>:</label></th>
+              <td>${state}</td>
+            </tr>
           </table>
         </div>
         
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/surefireReport.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/surefireReport.jsp
index 95461a3..de18617 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/surefireReport.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/surefireReport.jsp
@@ -20,7 +20,6 @@
 <%@ taglib uri="/struts-tags" prefix="s" %>
 <%@ taglib uri="http://www.extremecomponents.org" prefix="ec" %>
 <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
-<%@ taglib prefix="c1" uri="continuum" %>
 <html>
   <s:i18n name="localization.Continuum">
     <head>
@@ -43,6 +42,7 @@
         <h4><s:text name="surefireReport.summary"/></h4>
         <ec:table items="testSummaryList"
                   var="summary"
+                  autoIncludeParameters="false"
                   showExports="false"
                   showPagination="false"
                   showStatusBar="false"
@@ -60,6 +60,7 @@
         <h4><s:text name="surefireReport.packageList"/></h4>
         <ec:table items="testPackageList"
                   var="report"
+                  autoIncludeParameters="false"
                   showExports="false"
                   showPagination="false"
                   showStatusBar="false"
@@ -81,6 +82,7 @@
           <h5><a name="<s:property value="name"/>"><s:property value="name"/></a></h5>
           <ec:table items="children"
                     var="report"
+                    autoIncludeParameters="false"
                     showExports="false"
                     showPagination="false"
                     showStatusBar="false"
@@ -116,6 +118,7 @@
             <h5><a name="<s:property value="id"/>"><s:property value="name"/></a></h5>
             <ec:table items="children"
                       var="testCase"
+                      autoIncludeParameters="false"
                       showExports="false"
                       showPagination="false"
                       showStatusBar="false"
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/jsp/viewProjectBuildsReport.jsp b/continuum-webapp/src/main/webapp/WEB-INF/jsp/viewProjectBuildsReport.jsp
new file mode 100644
index 0000000..4ede7e8
--- /dev/null
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/viewProjectBuildsReport.jsp
@@ -0,0 +1,222 @@
+<%--
+  ~ 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='http://java.sun.com/jsp/jstl/core' prefix='c'%>
+<%@ taglib uri="http://www.extremecomponents.org" prefix="ec" %>
+
+<html>
+  <s:i18n name="localization.Continuum">
+  <head>
+    <title><s:text name="projectBuilds.report.title"/></title>
+    <s:head/>
+    <link rel="stylesheet" href="<c:url value='/css/no-theme/jquery-ui-1.7.2.custom.css'/>" type="text/css" />
+    <script type="text/javascript" src="<c:url value='/js/jquery-1.3.2.min.js'/>"></script>
+    <script type="text/javascript" src="<c:url value='/js/jquery-ui-1.7.2.custom.min.js'/>"></script>
+    <script type="text/javascript">
+      $(document).ready(function()
+      {
+        $('#startDate').datepicker()
+        $('#endDate').datepicker()
+
+        $('#resetFilter').click(function()
+        {
+          $('#startDate').val('')
+          $('#endDate').val('')
+          $('#triggeredBy').val('')
+          $('#rowCount').val('30')
+          $("#buildStatus option[value='0']").attr('selected', 'selected')
+          $("#projectGroupId option[value='0']").attr('selected', 'selected')
+        });
+      });
+    </script>
+  </head>
+  
+  <body>
+    <h3><s:text name="projectBuilds.report.section.title"/></h3>
+ 
+    <s:form name="generateReportForm" action="generateProjectBuildsReport.action">
+      <c:if test="${!empty actionErrors || !empty errorMessages}">
+        <div class="errormessage">
+          <s:iterator value="actionErrors">
+            <p><s:property/></p>
+          </s:iterator>
+          <c:forEach items="${errorMessages}" var="errorMessage">
+            <p><c:out value="${errorMessage}"/></p>
+          </c:forEach>
+        </div>
+      </c:if>
+      
+      <div class="axial">
+        <table>
+            <s:select label="%{getText('projectBuilds.report.project.group')}" name="projectGroupId" id="projectGroupId" list="projectGroups"/>
+            <s:textfield label="%{getText('projectBuilds.report.startDate')}" name="startDate" id="startDate" size="20"/>
+            <s:textfield label="%{getText('projectBuilds.report.endDate')}" name="endDate" id="endDate" size="20"/>
+            <s:select label="%{getText('projectBuilds.report.buildStatus')}" name="buildStatus" id="buildStatus" list="buildStatuses"/>
+            <s:textfield label="%{getText('projectBuilds.report.triggeredBy')}" name="triggeredBy" id="triggeredBy" size="40"/>
+            <s:textfield label="%{getText('projectBuilds.report.rowCount')}" name="rowCount" id="rowCount" size="10"/>
+        </table>
+        <div class="functnbar3">
+          <s:submit value="%{getText('projectBuilds.report.view')}" theme="simple" />
+          <input type="button" id="resetFilter" value="<s:text name='projectBuilds.report.button.reset' />" />
+        </div>
+      </div>
+    </s:form>
+    
+    </p>
+
+    <c:if test="${projectBuilds != null}">
+      <div id="h3">
+     	  <h3>Results</h3>
+     	  <c:choose>
+       	  <c:when test="${not empty projectBuilds}">
+       	    
+       	    <table>
+         	    <tr>
+           	    <td>
+             	    <%-- Pagination --%>
+                  <c:set var="prevPageUrl">
+                    <s:url action="generateProjectBuildsReport">    
+                      <s:param name="projectGroupId" value="%{#attr.projectGroupId}"/>
+                      <s:param name="triggeredBy" value="%{#attr.triggeredBy}"/>
+                      <s:param name="buildStatus" value="%{#attr.buildStatus}"/>
+                      <s:param name="rowCount" value="%{#attr.rowCount}"/>
+                      <s:param name="startDate" value="%{#attr.startDate}"/>                      
+                      <s:param name="endDate" value="%{#attr.endDate}"/>
+                      <s:param name="page" value="%{#attr.page - 1}"/>
+                    </s:url>
+                  </c:set>
+                  <c:set var="nextPageUrl">
+                    <s:url action="generateProjectBuildsReport">    
+                      <s:param name="projectGroupId" value="%{#attr.projectGroupId}"/>
+                      <s:param name="triggeredBy" value="%{#attr.triggeredBy}"/>
+                      <s:param name="buildStatus" value="%{#attr.buildStatus}"/>
+                      <s:param name="rowCount" value="%{#attr.rowCount}"/>
+                      <s:param name="startDate" value="%{#attr.startDate}"/>                      
+                      <s:param name="endDate" value="%{#attr.endDate}"/>          
+                      <s:param name="page" value="%{#attr.page + 1}"/>
+                    </s:url>
+                  </c:set>
+                  <c:choose>
+                    <c:when test="${page == 1}">                               
+                      <s:text name="projectBuilds.report.prev"/>
+                    </c:when>
+                    <c:otherwise>
+                      <a href="${prevPageUrl}">
+                        <s:text name="projectBuilds.report.prev"/>
+                      </a>
+                    </c:otherwise>
+                  </c:choose>
+
+                  <c:choose>
+                    <c:when test="${numPages > 11}">
+                      <c:choose>
+                        <c:when test="${(page - 5) < 0}">
+                          <c:set var="beginVal">0</c:set>
+                          <c:set var="endVal">10</c:set> 
+                        </c:when>			        
+                        <c:when test="${(page + 5) > (numPages - 1)}">
+                          <c:set var="beginVal">${(numPages - 1) - 10}</c:set>
+                          <c:set var="endVal">${numPages - 1}</c:set>
+                        </c:when>
+                        <c:otherwise>
+                          <c:set var="beginVal">${page - 5}</c:set>
+                          <c:set var="endVal">${page + 5}</c:set>
+                        </c:otherwise>
+                      </c:choose>  
+                    </c:when>
+                    <c:otherwise>
+                      <c:set var="beginVal">0</c:set>
+                      <c:set var="endVal">${numPages - 1}</c:set>
+                    </c:otherwise>
+                  </c:choose>
+
+                  <c:forEach var="i" begin="${beginVal}" end="${endVal}">      
+                    <c:choose>                   			    
+                      <c:when test="${i != (page - 1)}">
+                        <c:set var="specificPageUrl">
+                          <s:url action="generateProjectBuildsReport">    
+                            <s:param name="projectGroupId" value="%{#attr.projectGroupId}"/>
+                            <s:param name="triggeredBy" value="%{#attr.triggeredBy}"/>
+                            <s:param name="buildStatus" value="%{#attr.buildStatus}"/>
+                            <s:param name="rowCount" value="%{#attr.rowCount}"/>
+                            <s:param name="startDate" value="%{#attr.startDate}"/>                      
+                            <s:param name="endDate" value="%{#attr.endDate}"/>          
+                            <s:param name="page" value="%{#attr.i + 1}"/>
+                          </s:url>
+                        </c:set>
+                        <a href="${specificPageUrl}">${i + 1}</a>
+                      </c:when>
+                      <c:otherwise>		
+                        <b>${i + 1}</b>   
+                      </c:otherwise>				  			    
+                    </c:choose>      
+                  </c:forEach>
+
+                  <c:choose>
+                    <c:when test="${page == numPages}">
+                      <s:text name="projectBuilds.report.next"/>
+                    </c:when>
+            	      <c:otherwise>
+                      <a href="${nextPageUrl}">
+                        <s:text name="projectBuilds.report.next"/>
+                      </a>
+                    </c:otherwise>   
+                  </c:choose>
+           	    </td>
+           	    <td>
+                  <%-- Export to CSV link --%>
+                  <s:url id="downloadProjectBuildsReportUrl" action="downloadProjectBuildsReport" namespace="/">
+                    <s:param name="projectGroupId" value="%{#attr.projectGroupId}"/>
+                    <s:param name="triggeredBy" value="%{#attr.triggeredBy}"/>
+                    <s:param name="buildStatus" value="%{#attr.buildStatus}"/>
+                    <s:param name="startDate" value="%{#attr.startDate}"/>
+                    <s:param name="endDate" value="%{#attr.endDate}"/>
+                  </s:url>
+                  <s:a href="%{downloadProjectBuildsReportUrl}">Export to CSV</s:a>
+                </td>
+              </tr>
+            </table>
+
+            <s:set name="projectBuilds" value="projectBuilds" scope="request"/>
+            <ec:table items="projectBuilds"
+                        var="projectBuild"
+                        showExports="false"
+                        showPagination="false"
+                        showStatusBar="false"
+                        sortable="false"
+                        filterable="false">
+              <ec:row highlightRow="true">
+                <ec:column property="projectGroupName" title="projectBuilds.report.projectGroup"/>
+                <ec:column property="projectName" title="projectBuilds.report.project"/>
+                <ec:column property="buildDate" title="projectBuilds.report.buildDate" cell="date"/>
+                <ec:column property="buildTriggeredBy" title="projectBuilds.report.triggeredBy"/>
+                <ec:column property="buildState" title="projectBuilds.report.buildStatus" cell="org.apache.maven.continuum.web.view.buildresults.StateCell"/>
+              </ec:row>
+            </ec:table>
+          </c:when>
+          <c:otherwise>
+            <s:text name="projectBuilds.report.noResult"/></p>
+          </c:otherwise>
+        </c:choose>
+      </div>
+    </c:if>
+  </body>
+  </s:i18n>
+</html>
diff --git a/continuum-webapp/src/main/webapp/WEB-INF/web.xml b/continuum-webapp/src/main/webapp/WEB-INF/web.xml
index 739bd18..1b0ed8b 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/web.xml
+++ b/continuum-webapp/src/main/webapp/WEB-INF/web.xml
@@ -37,20 +37,40 @@
 
 
   <filter>
-    <filter-name>struts-cleanup</filter-name>
-    <filter-class>org.apache.struts2.dispatcher.ActionContextCleanUp</filter-class>
-  </filter>
-  <filter>
-    <filter-name>sitemesh</filter-name>
-    <filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class>
-  </filter>
-  <filter>
-    <filter-name>struts</filter-name>
-    <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
+    <filter-name>struts-prepare</filter-name>
+    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareFilter</filter-class>
   </filter>
 
+  <filter>
+    <filter-name>sitemesh</filter-name>
+    <filter-class>com.opensymphony.sitemesh.webapp.SiteMeshFilter</filter-class>
+  </filter>
+
+  <filter>
+    <filter-name>struts-execute</filter-name>
+    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsExecuteFilter</filter-class>
+  </filter>
+
+  <filter>
+    <filter-name>encodingFilter</filter-name>
+    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
+    <init-param>
+      <param-name>encoding</param-name>
+      <param-value>UTF-8</param-value>
+    </init-param>
+    <init-param>
+      <param-name>forceEncoding</param-name>
+      <param-value>true</param-value>
+    </init-param>
+  </filter>
+
+
   <filter-mapping>
-    <filter-name>struts-cleanup</filter-name>
+    <filter-name>encodingFilter</filter-name>
+    <url-pattern>/*</url-pattern>
+  </filter-mapping>
+  <filter-mapping>
+    <filter-name>struts-prepare</filter-name>
     <url-pattern>/*</url-pattern>
   </filter-mapping>
   <filter-mapping>
@@ -58,18 +78,21 @@
     <url-pattern>/*</url-pattern>
   </filter-mapping>
   <filter-mapping>
-    <filter-name>struts</filter-name>
+    <filter-name>struts-execute</filter-name>
     <url-pattern>/*</url-pattern>
   </filter-mapping>
 
+
   <listener>
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
   </listener>
   <listener>
     <!-- TODO: some Spring technique for this? -->
-  	<listener-class>org.apache.continuum.web.startup.ContinuumStartup</listener-class>
+    <listener-class>org.apache.continuum.web.startup.ContinuumStartup</listener-class>
   </listener>
-
+  <listener>
+    <listener-class>org.apache.struts2.dispatcher.ng.listener.StrutsListener</listener-class>
+  </listener>
   <context-param>
     <param-name>contextClass</param-name>
     <param-value>org.codehaus.plexus.spring.PlexusWebApplicationContext</param-value>
@@ -78,11 +101,11 @@
   <context-param>
     <param-name>contextConfigLocation</param-name>
     <param-value>
-        classpath*:/META-INF/plexus/components.xml
-        classpath*:/META-INF/spring-context.xml
-        /WEB-INF/classes/META-INF/plexus/application.xml
-        /WEB-INF/classes/META-INF/plexus/components.xml
-        /WEB-INF/applicationContext.xml
+      classpath*:/META-INF/plexus/components.xml
+      classpath*:/META-INF/spring-context.xml
+      /WEB-INF/classes/META-INF/plexus/application.xml
+      /WEB-INF/classes/META-INF/plexus/components.xml
+      /WEB-INF/applicationContext.xml
     </param-value>
   </context-param>
 
@@ -106,7 +129,27 @@
     </init-param>
     <load-on-startup>1</load-on-startup>
   </servlet>
-  
+
+  <servlet>
+    <servlet-name>RedbackXmlRpcServlet</servlet-name>
+    <servlet-class>
+      com.atlassian.xmlrpc.spring.BinderSpringXmlRpcServlet
+    </servlet-class>
+    <init-param>
+      <param-name>serviceListBeanName</param-name>
+      <param-value>redbackXmlrpcServicesList</param-value>
+    </init-param>
+    <init-param>
+      <param-name>authHandlerBeanName</param-name>
+      <param-value>redbackXmlRpcAuthenticator</param-value>
+    </init-param>
+    <init-param>
+      <param-name>enabledForExtensions</param-name>
+      <param-value>true</param-value>
+    </init-param>
+    <load-on-startup>1</load-on-startup>
+  </servlet>
+
   <servlet-mapping>
     <servlet-name>XmlRpcServlet</servlet-name>
     <url-pattern>/xmlrpc</url-pattern>
@@ -116,18 +159,23 @@
     <servlet-name>MasterXmlRpcServlet</servlet-name>
     <url-pattern>/master-xmlrpc</url-pattern>
   </servlet-mapping>
-  
+
+  <servlet-mapping>
+    <servlet-name>RedbackXmlRpcServlet</servlet-name>
+    <url-pattern>/redback-xmlrpc</url-pattern>
+  </servlet-mapping>
+
   <error-page>
     <error-code>403</error-code>
-    <location>/WEB-INF/jsp/error/httpError.jsp?errorCode=403</location>
+    <location>/httpError.jsp?errorCode=403</location>
   </error-page>
   <error-page>
     <error-code>404</error-code>
-    <location>/WEB-INF/jsp/error/httpError.jsp?errorCode=404</location>
+    <location>/httpError.jsp?errorCode=404</location>
   </error-page>
   <error-page>
     <error-code>500</error-code>
-    <location>/WEB-INF/jsp/error/httpError.jsp?errorCode=500</location>
+    <location>/httpError.jsp?errorCode=500</location>
   </error-page>
 
   <!-- [jspc-maven-plugin:post-compiled-jsps-as-servlets] -->
diff --git a/continuum-webapp/src/main/webapp/css/continuum.css b/continuum-webapp/src/main/webapp/css/continuum.css
new file mode 100644
index 0000000..16b5906
--- /dev/null
+++ b/continuum-webapp/src/main/webapp/css/continuum.css
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+/* Cleanup oddball redback labels (compare to .axial th in tigris.css) */
+td.tdLabel {
+  width: 12em;
+}
\ No newline at end of file
diff --git a/continuum-webapp/src/main/webapp/css/no-theme/jquery-ui-1.7.2.custom.css b/continuum-webapp/src/main/webapp/css/no-theme/jquery-ui-1.7.2.custom.css
new file mode 100644
index 0000000..9d7aa08
--- /dev/null
+++ b/continuum-webapp/src/main/webapp/css/no-theme/jquery-ui-1.7.2.custom.css
@@ -0,0 +1,406 @@
+/*
+* jQuery UI CSS Framework
+* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
+*/
+
+/* Layout helpers
+----------------------------------*/
+.ui-helper-hidden { display: none; }
+.ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
+.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
+.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
+.ui-helper-clearfix { display: inline-block; }
+/* required comment for clearfix to work in Opera \*/
+* html .ui-helper-clearfix { height:1%; }
+.ui-helper-clearfix { display:block; }
+/* end clearfix */
+.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
+
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-disabled { cursor: default !important; }
+
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Overlays */
+.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
+
+
+
+/*
+* jQuery UI CSS Framework
+* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
+* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS,%20Tahoma,%20Verdana,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=03_highlight_soft.png&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=02_glass.png&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=03_highlight_soft.png&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=08_diagonals_thick.png&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=08_diagonals_thick.png&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=01_flat.png&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px
+*/
+
+
+/* Component containers
+----------------------------------*/
+.ui-widget { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1.1em; }
+.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1em; }
+.ui-widget-content { border: 1px solid #dddddd; background: #eeeeee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x; color: #333333; }
+.ui-widget-content a { color: #333333; }
+.ui-widget-header { border: 1px solid #e78f08; background: #f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; }
+.ui-widget-header a { color: #ffffff; }
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #cccccc; background: #f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1c94c4; outline: none; }
+.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #1c94c4; text-decoration: none; outline: none; }
+.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #fbcb09; background: #fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #c77405; outline: none; }
+.ui-state-hover a, .ui-state-hover a:hover { color: #c77405; text-decoration: none; outline: none; }
+.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #fbd850; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #eb8f00; outline: none; }
+.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #eb8f00; outline: none; text-decoration: none; }
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fed22f; background: #ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x; color: #363636; }
+.ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #363636; }
+.ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a; background: #b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat; color: #ffffff; }
+.ui-state-error a, .ui-widget-content .ui-state-error a { color: #ffffff; }
+.ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #ffffff; }
+.ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
+.ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; }
+.ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
+.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
+.ui-widget-header .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); }
+.ui-state-default .ui-icon { background-image: url(images/ui-icons_ef8c08_256x240.png); }
+.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); }
+.ui-state-active .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); }
+.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_228ef1_256x240.png); }
+.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_ffd27a_256x240.png); }
+
+/* positioning */
+.ui-icon-carat-1-n { background-position: 0 0; }
+.ui-icon-carat-1-ne { background-position: -16px 0; }
+.ui-icon-carat-1-e { background-position: -32px 0; }
+.ui-icon-carat-1-se { background-position: -48px 0; }
+.ui-icon-carat-1-s { background-position: -64px 0; }
+.ui-icon-carat-1-sw { background-position: -80px 0; }
+.ui-icon-carat-1-w { background-position: -96px 0; }
+.ui-icon-carat-1-nw { background-position: -112px 0; }
+.ui-icon-carat-2-n-s { background-position: -128px 0; }
+.ui-icon-carat-2-e-w { background-position: -144px 0; }
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
+.ui-icon-triangle-1-s { background-position: -64px -16px; }
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
+.ui-icon-arrow-1-s { background-position: -64px -32px; }
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
+.ui-icon-arrow-4 { background-position: 0 -80px; }
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
+.ui-icon-extlink { background-position: -32px -80px; }
+.ui-icon-newwin { background-position: -48px -80px; }
+.ui-icon-refresh { background-position: -64px -80px; }
+.ui-icon-shuffle { background-position: -80px -80px; }
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
+.ui-icon-folder-open { background-position: -16px -96px; }
+.ui-icon-document { background-position: -32px -96px; }
+.ui-icon-document-b { background-position: -48px -96px; }
+.ui-icon-note { background-position: -64px -96px; }
+.ui-icon-mail-closed { background-position: -80px -96px; }
+.ui-icon-mail-open { background-position: -96px -96px; }
+.ui-icon-suitcase { background-position: -112px -96px; }
+.ui-icon-comment { background-position: -128px -96px; }
+.ui-icon-person { background-position: -144px -96px; }
+.ui-icon-print { background-position: -160px -96px; }
+.ui-icon-trash { background-position: -176px -96px; }
+.ui-icon-locked { background-position: -192px -96px; }
+.ui-icon-unlocked { background-position: -208px -96px; }
+.ui-icon-bookmark { background-position: -224px -96px; }
+.ui-icon-tag { background-position: -240px -96px; }
+.ui-icon-home { background-position: 0 -112px; }
+.ui-icon-flag { background-position: -16px -112px; }
+.ui-icon-calendar { background-position: -32px -112px; }
+.ui-icon-cart { background-position: -48px -112px; }
+.ui-icon-pencil { background-position: -64px -112px; }
+.ui-icon-clock { background-position: -80px -112px; }
+.ui-icon-disk { background-position: -96px -112px; }
+.ui-icon-calculator { background-position: -112px -112px; }
+.ui-icon-zoomin { background-position: -128px -112px; }
+.ui-icon-zoomout { background-position: -144px -112px; }
+.ui-icon-search { background-position: -160px -112px; }
+.ui-icon-wrench { background-position: -176px -112px; }
+.ui-icon-gear { background-position: -192px -112px; }
+.ui-icon-heart { background-position: -208px -112px; }
+.ui-icon-star { background-position: -224px -112px; }
+.ui-icon-link { background-position: -240px -112px; }
+.ui-icon-cancel { background-position: 0 -128px; }
+.ui-icon-plus { background-position: -16px -128px; }
+.ui-icon-plusthick { background-position: -32px -128px; }
+.ui-icon-minus { background-position: -48px -128px; }
+.ui-icon-minusthick { background-position: -64px -128px; }
+.ui-icon-close { background-position: -80px -128px; }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-key { background-position: -112px -128px; }
+.ui-icon-lightbulb { background-position: -128px -128px; }
+.ui-icon-scissors { background-position: -144px -128px; }
+.ui-icon-clipboard { background-position: -160px -128px; }
+.ui-icon-copy { background-position: -176px -128px; }
+.ui-icon-contact { background-position: -192px -128px; }
+.ui-icon-image { background-position: -208px -128px; }
+.ui-icon-video { background-position: -224px -128px; }
+.ui-icon-script { background-position: -240px -128px; }
+.ui-icon-alert { background-position: 0 -144px; }
+.ui-icon-info { background-position: -16px -144px; }
+.ui-icon-notice { background-position: -32px -144px; }
+.ui-icon-help { background-position: -48px -144px; }
+.ui-icon-check { background-position: -64px -144px; }
+.ui-icon-bullet { background-position: -80px -144px; }
+.ui-icon-radio-off { background-position: -96px -144px; }
+.ui-icon-radio-on { background-position: -112px -144px; }
+.ui-icon-pin-w { background-position: -128px -144px; }
+.ui-icon-pin-s { background-position: -144px -144px; }
+.ui-icon-play { background-position: 0 -160px; }
+.ui-icon-pause { background-position: -16px -160px; }
+.ui-icon-seek-next { background-position: -32px -160px; }
+.ui-icon-seek-prev { background-position: -48px -160px; }
+.ui-icon-seek-end { background-position: -64px -160px; }
+.ui-icon-seek-first { background-position: -80px -160px; }
+.ui-icon-stop { background-position: -96px -160px; }
+.ui-icon-eject { background-position: -112px -160px; }
+.ui-icon-volume-off { background-position: -128px -160px; }
+.ui-icon-volume-on { background-position: -144px -160px; }
+.ui-icon-power { background-position: 0 -176px; }
+.ui-icon-signal-diag { background-position: -16px -176px; }
+.ui-icon-signal { background-position: -32px -176px; }
+.ui-icon-battery-0 { background-position: -48px -176px; }
+.ui-icon-battery-1 { background-position: -64px -176px; }
+.ui-icon-battery-2 { background-position: -80px -176px; }
+.ui-icon-battery-3 { background-position: -96px -176px; }
+.ui-icon-circle-plus { background-position: 0 -192px; }
+.ui-icon-circle-minus { background-position: -16px -192px; }
+.ui-icon-circle-close { background-position: -32px -192px; }
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
+.ui-icon-circle-check { background-position: -208px -192px; }
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; }
+.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; }
+.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; }
+.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
+.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; }
+.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
+.ui-corner-right {  -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
+.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; }
+.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; }
+
+/* Overlays */
+.ui-widget-overlay { background: #666666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat; opacity: .50;filter:Alpha(Opacity=50); }
+.ui-widget-shadow { margin: -5px 0 0 -5px; padding: 5px; background: #000000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 5px; -webkit-border-radius: 5px; }/* Accordion
+----------------------------------*/
+.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
+.ui-accordion .ui-accordion-li-fix { display: inline; }
+.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
+.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em 2.2em; }
+.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
+.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; }
+.ui-accordion .ui-accordion-content-active { display: block; }/* Datepicker
+----------------------------------*/
+.ui-datepicker { width: 17em; padding: .2em .2em 0; }
+.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
+.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
+.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
+.ui-datepicker .ui-datepicker-prev { left:2px; }
+.ui-datepicker .ui-datepicker-next { right:2px; }
+.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
+.ui-datepicker .ui-datepicker-next-hover { right:1px; }
+.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px;  }
+.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
+.ui-datepicker .ui-datepicker-title select { float:left; font-size:1em; margin:1px 0; }
+.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
+.ui-datepicker select.ui-datepicker-month, 
+.ui-datepicker select.ui-datepicker-year { width: 49%;}
+.ui-datepicker .ui-datepicker-title select.ui-datepicker-year { float: right; }
+.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
+.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0;  }
+.ui-datepicker td { border: 0; padding: 1px; }
+.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
+.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
+.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
+
+/* with multiple calendars */
+.ui-datepicker.ui-datepicker-multi { width:auto; }
+.ui-datepicker-multi .ui-datepicker-group { float:left; }
+.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
+.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
+.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
+.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
+.ui-datepicker-row-break { clear:both; width:100%; }
+
+/* RTL support */
+.ui-datepicker-rtl { direction: rtl; }
+.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+
+/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
+.ui-datepicker-cover {
+    display: none; /*sorry for IE5*/
+    display/**/: block; /*sorry for IE5*/
+    position: absolute; /*must have*/
+    z-index: -1; /*must have*/
+    filter: mask(); /*must have*/
+    top: -4px; /*must have*/
+    left: -4px; /*must have*/
+    width: 200px; /*must have*/
+    height: 200px; /*must have*/
+}/* Dialog
+----------------------------------*/
+.ui-dialog { position: relative; padding: .2em; width: 300px; }
+.ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative;  }
+.ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; } 
+.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
+.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
+.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
+.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
+.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
+.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; }
+.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
+.ui-draggable .ui-dialog-titlebar { cursor: move; }
+/* Progressbar
+----------------------------------*/
+.ui-progressbar { height:2em; text-align: left; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }/* Resizable
+----------------------------------*/
+.ui-resizable { position: relative;}
+.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
+.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
+.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0px; }
+.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; }
+.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; }
+.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; height: 100%; }
+.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
+.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
+.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
+.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Slider
+----------------------------------*/
+.ui-slider { position: relative; text-align: left; }
+.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
+.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; }
+
+.ui-slider-horizontal { height: .8em; }
+.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
+.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
+.ui-slider-horizontal .ui-slider-range-min { left: 0; }
+.ui-slider-horizontal .ui-slider-range-max { right: 0; }
+
+.ui-slider-vertical { width: .8em; height: 100px; }
+.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
+.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
+.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
+.ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs
+----------------------------------*/
+.ui-tabs { padding: .2em; zoom: 1; }
+.ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: .2em .2em 0; }
+.ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; }
+.ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 0; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
+.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
+.ui-tabs .ui-tabs-panel { padding: 1em 1.4em; display: block; border-width: 0; background: none; }
+.ui-tabs .ui-tabs-hide { display: none !important; }
diff --git a/continuum-webapp/src/main/webapp/css/tigris.css b/continuum-webapp/src/main/webapp/css/tigris.css
index 6795d4f..9f7b942 100644
--- a/continuum-webapp/src/main/webapp/css/tigris.css
+++ b/continuum-webapp/src/main/webapp/css/tigris.css
@@ -278,7 +278,7 @@
 }
 
 .warningmessage {
-  height: 48px;
+  height: auto;
   background-position: 0px 0px;
   background-color: white;
   border: 0px 0px 0px 0px;
@@ -422,7 +422,7 @@
   font-size: small;
 }
 
-small,div#footer,div#login,div.tabs th,div.tabs td,input,select,.paginate,.functnbar,.functnbar2,.functnbar3,#breadcrumbs,.courtesylinks,#rightcol div.help,.colbar,.tasknav,body.docs div#toc,#leftcol,.legend,.bars
+small,div#footer,div#login,div.tabs th,div.tabs td,input,select,button,.paginate,.functnbar,.functnbar2,.functnbar3,#breadcrumbs,.courtesylinks,#rightcol div.help,.colbar,.tasknav,body.docs div#toc,#leftcol,.legend,.bars
   {
   font-size: xx-small;
   voice-family: "\"}\"";
@@ -797,6 +797,7 @@
   color: gray;
   font-weight: bold;
   font-size: 11px;
+  font-style: normal;
   padding: 0px 0px 1px 19px;
 }
 
diff --git a/continuum-webapp/src/main/webapp/httpError.jsp b/continuum-webapp/src/main/webapp/httpError.jsp
new file mode 100644
index 0000000..26bd9c5
--- /dev/null
+++ b/continuum-webapp/src/main/webapp/httpError.jsp
@@ -0,0 +1,20 @@
+<%--
+  ~ 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.
+  --%>
+
+<% response.sendRedirect(  request.getContextPath() + "/httpError.action?errorCode="+ request.getParameter( "errorCode" ) ); %>
diff --git a/continuum-webapp/src/main/webapp/js/jquery-1.3.2.min.js b/continuum-webapp/src/main/webapp/js/jquery-1.3.2.min.js
new file mode 100644
index 0000000..b1ae21d
--- /dev/null
+++ b/continuum-webapp/src/main/webapp/js/jquery-1.3.2.min.js
@@ -0,0 +1,19 @@
+/*
+ * jQuery JavaScript Library v1.3.2
+ * http://jquery.com/
+ *
+ * Copyright (c) 2009 John Resig
+ * Dual licensed under the MIT and GPL licenses.
+ * http://docs.jquery.com/License
+ *
+ * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
+ * Revision: 6246
+ */
+(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F<J;F++){var G=M[F];if(G.selected){K=o(G).val();if(H){return K}L.push(K)}}return L}return(E.value||"").replace(/\r/g,"")}return g}if(typeof K==="number"){K+=""}return this.each(function(){if(this.nodeType!=1){return}if(o.isArray(K)&&/radio|checkbox/.test(this.type)){this.checked=(o.inArray(this.value,K)>=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G<E;G++){L.call(K(this[G],H),this.length>1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H<I;H++){if((G=arguments[H])!=null){for(var F in G){var K=J[F],L=G[F];if(J===L){continue}if(E&&L&&typeof L==="object"&&!L.nodeType){J[F]=o.extend(E,K||(L.length!=null?[]:{}),L)}else{if(L!==g){J[F]=L}}}}}return J};var b=/z-?index|font-?weight|opacity|zoom|line-?height/i,q=document.defaultView||{},s=Object.prototype.toString;o.extend({noConflict:function(E){l.$=p;if(E){l.jQuery=y}return o},isFunction:function(E){return s.call(E)==="[object Function]"},isArray:function(E){return s.call(E)==="[object Array]"},isXMLDoc:function(E){return E.nodeType===9&&E.documentElement.nodeName!=="HTML"||!!E.ownerDocument&&o.isXMLDoc(E.ownerDocument)},globalEval:function(G){if(G&&/\S/.test(G)){var F=document.getElementsByTagName("head")[0]||document.documentElement,E=document.createElement("script");E.type="text/javascript";if(o.support.scriptEval){E.appendChild(document.createTextNode(G))}else{E.text=G}F.insertBefore(E,F.firstChild);F.removeChild(E)}},nodeName:function(F,E){return F.nodeName&&F.nodeName.toUpperCase()==E.toUpperCase()},each:function(G,K,F){var E,H=0,I=G.length;if(F){if(I===g){for(E in G){if(K.apply(G[E],F)===false){break}}}else{for(;H<I;){if(K.apply(G[H++],F)===false){break}}}}else{if(I===g){for(E in G){if(K.call(G[E],E,G[E])===false){break}}}else{for(var J=G[0];H<I&&K.call(J,H,J)!==false;J=G[++H]){}}}return G},prop:function(H,I,G,F,E){if(o.isFunction(I)){I=I.call(H,F)}return typeof I==="number"&&G=="curCSS"&&!b.test(E)?I+"px":I},className:{add:function(E,F){o.each((F||"").split(/\s+/),function(G,H){if(E.nodeType==1&&!o.className.has(E.className,H)){E.className+=(E.className?" ":"")+H}})},remove:function(E,F){if(E.nodeType==1){E.className=F!==g?o.grep(E.className.split(/\s+/),function(G){return !o.className.has(F,G)}).join(" "):""}},has:function(F,E){return F&&o.inArray(E,(F.className||F).toString().split(/\s+/))>-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+"></"+T+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("<opt")&&[1,"<select multiple='multiple'>","</select>"]||!O.indexOf("<leg")&&[1,"<fieldset>","</fieldset>"]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"<table>","</table>"]||!O.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!O.indexOf("<td")||!O.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||!O.indexOf("<col")&&[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]||!o.support.htmlSerialize&&[1,"div<div>","</div>"]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/<tbody/i.test(S),N=!O.indexOf("<table")&&!R?L.firstChild&&L.firstChild.childNodes:Q[1]=="<table>"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E<F;E++){if(H[E]===G){return E}}return -1},merge:function(H,E){var F=0,G,I=H.length;if(!o.support.getAll){while((G=E[F++])!=null){if(G.nodeType!=8){H[I++]=G}}}else{while((G=E[F++])!=null){H[I++]=G}}return H},unique:function(K){var F=[],E={};try{for(var G=0,H=K.length;G<H;G++){var J=o.data(K[G]);if(!E[J]){E[J]=true;F.push(K[G])}}}catch(I){F=K}return F},grep:function(F,J,E){var G=[];for(var H=0,I=F.length;H<I;H++){if(!E!=!J(F[H],H)){G.push(F[H])}}return G},map:function(E,J){var F=[];for(var G=0,H=E.length;G<H;G++){var I=J(E[G],G);if(I!=null){F[F.length]=I}}return F.concat.apply([],F)}});var C=navigator.userAgent.toLowerCase();o.browser={version:(C.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[0,"0"])[1],safari:/webkit/.test(C),opera:/opera/.test(C),msie:/msie/.test(C)&&!/opera/.test(C),mozilla:/mozilla/.test(C)&&!/(compatible|webkit)/.test(C)};o.each({parent:function(E){return E.parentNode},parents:function(E){return o.dir(E,"parentNode")},next:function(E){return o.nth(E,2,"nextSibling")},prev:function(E){return o.nth(E,2,"previousSibling")},nextAll:function(E){return o.dir(E,"nextSibling")},prevAll:function(E){return o.dir(E,"previousSibling")},siblings:function(E){return o.sibling(E.parentNode.firstChild,E)},children:function(E){return o.sibling(E.firstChild)},contents:function(E){return o.nodeName(E,"iframe")?E.contentDocument||E.contentWindow.document:o.makeArray(E.childNodes)}},function(E,F){o.fn[E]=function(G){var H=o.map(this,F);if(G&&typeof G=="string"){H=o.multiFilter(G,H)}return this.pushStack(o.unique(H),E,G)}});o.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(E,F){o.fn[E]=function(G){var J=[],L=o(G);for(var K=0,H=L.length;K<H;K++){var I=(K>0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}});
+/*
+ * Sizzle CSS Selector Engine - v0.9.3
+ *  Copyright 2009, The Dojo Foundation
+ *  Released under the MIT, BSD, and GPL Licenses.
+ *  More information: http://sizzlejs.com/
+ */
+(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa<ab.length;aa++){if(ab[aa]===ab[aa-1]){ab.splice(aa--,1)}}}}}return ab};F.matches=function(T,U){return F(T,null,null,U)};F.find=function(aa,T,ab){var Z,X;if(!aa){return[]}for(var W=0,V=I.order.length;W<V;W++){var Y=I.order[W],X;if((X=I.match[Y].exec(aa))){var U=RegExp.leftContext;if(U.substr(U.length-1)!=="\\"){X[1]=(X[1]||"").replace(/\\/g,"");Z=I.find[Y](X,T,ab);if(Z!=null){aa=aa.replace(I.match[Y],"");break}}}}if(!Z){Z=T.getElementsByTagName("*")}return{set:Z,expr:aa}};F.filter=function(ad,ac,ag,W){var V=ad,ai=[],aa=ac,Y,T,Z=ac&&ac[0]&&Q(ac[0]);while(ad&&ac.length){for(var ab in I.filter){if((Y=I.match[ab].exec(ad))!=null){var U=I.filter[ab],ah,af;T=false;if(aa==ai){ai=[]}if(I.preFilter[ab]){Y=I.preFilter[ab](Y,aa,ag,ai,W,Z);if(!Y){T=ah=true}else{if(Y===true){continue}}}if(Y){for(var X=0;(af=aa[X])!=null;X++){if(af){ah=U(af,Y,X,aa);var ae=W^!!ah;if(ag&&ah!=null){if(ae){T=true}else{aa[X]=false}}else{if(ae){ai.push(af);T=true}}}}}if(ah!==g){if(!ag){aa=ai}ad=ad.replace(I.match[ab],"");if(!T){return[]}break}}}if(ad==V){if(T==null){throw"Syntax error, unrecognized expression: "+ad}else{break}}V=ad}return aa};var I=F.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(T){return T.getAttribute("href")}},relative:{"+":function(aa,T,Z){var X=typeof T==="string",ab=X&&!/\W/.test(T),Y=X&&!ab;if(ab&&!Z){T=T.toUpperCase()}for(var W=0,V=aa.length,U;W<V;W++){if((U=aa[W])){while((U=U.previousSibling)&&U.nodeType!==1){}aa[W]=Y||U&&U.nodeName===T?U||false:U===T}}if(Y){F.filter(T,aa,true)}},">":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V<T;V++){var Y=Z[V];if(Y){var W=Y.parentNode;Z[V]=W.nodeName===U?W:false}}}else{for(var V=0,T=Z.length;V<T;V++){var Y=Z[V];if(Y){Z[V]=X?Y.parentNode:Y.parentNode===U}}if(X){F.filter(U,Z,true)}}},"":function(W,U,Y){var V=L++,T=S;if(!U.match(/\W/)){var X=U=Y?U:U.toUpperCase();T=P}T("parentNode",U,V,W,X,Y)},"~":function(W,U,Y){var V=L++,T=S;if(typeof U==="string"&&!U.match(/\W/)){var X=U=Y?U:U.toUpperCase();T=P}T("previousSibling",U,V,W,X,Y)}},find:{ID:function(U,V,W){if(typeof V.getElementById!=="undefined"&&!W){var T=V.getElementById(U[1]);return T?[T]:[]}},NAME:function(V,Y,Z){if(typeof Y.getElementsByName!=="undefined"){var U=[],X=Y.getElementsByName(V[1]);for(var W=0,T=X.length;W<T;W++){if(X[W].getAttribute("name")===V[1]){U.push(X[W])}}return U.length===0?null:U}},TAG:function(T,U){return U.getElementsByTagName(T[1])}},preFilter:{CLASS:function(W,U,V,T,Z,aa){W=" "+W[1].replace(/\\/g,"")+" ";if(aa){return W}for(var X=0,Y;(Y=U[X])!=null;X++){if(Y){if(Z^(Y.className&&(" "+Y.className+" ").indexOf(W)>=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return U<T[3]-0},gt:function(V,U,T){return U>T[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W<T;W++){if(Y[W]===Z){return false}}return true}}}},CHILD:function(T,W){var Z=W[1],U=T;switch(Z){case"only":case"first":while(U=U.previousSibling){if(U.nodeType===1){return false}}if(Z=="first"){return true}U=T;case"last":while(U=U.nextSibling){if(U.nodeType===1){return false}}return true;case"nth":var V=W[2],ac=W[3];if(V==1&&ac==0){return true}var Y=W[0],ab=T.parentNode;if(ab&&(ab.sizcache!==Y||!T.nodeIndex)){var X=0;for(U=ab.firstChild;U;U=U.nextSibling){if(U.nodeType===1){U.nodeIndex=++X}}ab.sizcache=Y}var aa=T.nodeIndex-ac;if(V==0){return aa==0}else{return(aa%V==0&&aa/V>=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V<T;V++){U.push(X[V])}}else{for(var V=0;X[V];V++){U.push(X[V])}}}return U}}var G;if(document.documentElement.compareDocumentPosition){G=function(U,T){var V=U.compareDocumentPosition(T)&4?-1:U===T?0:1;if(V===0){hasDuplicate=true}return V}}else{if("sourceIndex" in document.documentElement){G=function(U,T){var V=U.sourceIndex-T.sourceIndex;if(V===0){hasDuplicate=true}return V}}else{if(document.createRange){G=function(W,U){var V=W.ownerDocument.createRange(),T=U.ownerDocument.createRange();V.selectNode(W);V.collapse(true);T.selectNode(U);T.collapse(true);var X=V.compareBoundaryPoints(Range.START_TO_END,T);if(X===0){hasDuplicate=true}return X}}}}(function(){var U=document.createElement("form"),V="script"+(new Date).getTime();U.innerHTML="<input name='"+V+"'/>";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="<a href='#'></a>";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="<p class='TEST'></p>";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="<div class='test e'></div><div class='test'></div>";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W<V;W++){var T=ad[W];if(T){if(ab&&T.nodeType===1){T.sizcache=Y;T.sizset=W}T=T[U];var X=false;while(T){if(T.sizcache===Y){X=ad[T.sizset];break}if(T.nodeType===1&&!ac){T.sizcache=Y;T.sizset=W}if(T.nodeName===Z){X=T;break}T=T[U]}ad[W]=X}}}function S(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W<V;W++){var T=ad[W];if(T){if(ab&&T.nodeType===1){T.sizcache=Y;T.sizset=W}T=T[U];var X=false;while(T){if(T.sizcache===Y){X=ad[T.sizset];break}if(T.nodeType===1){if(!ac){T.sizcache=Y;T.sizset=W}if(typeof Z!=="string"){if(T===Z){X=true;break}}else{if(F.filter(Z,[T]).length>0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z<U;Z++){F(T,V[Z],W)}return F.filter(X,W)};o.find=F;o.filter=F.filter;o.expr=F.selectors;o.expr[":"]=o.expr.filters;F.selectors.filters.hidden=function(T){return T.offsetWidth===0||T.offsetHeight===0};F.selectors.filters.visible=function(T){return T.offsetWidth>0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F<E.length){o.event.proxy(G,E[F++])}return this.click(o.event.proxy(G,function(H){this.lastToggle=(this.lastToggle||0)%F;H.preventDefault();return E[this.lastToggle++].apply(this,arguments)||false}))},hover:function(E,F){return this.mouseenter(E).mouseleave(F)},ready:function(E){B();if(o.isReady){E.call(document,o)}else{o.readyList.push(E)}return this},live:function(G,F){var E=o.event.proxy(F);E.guid+=this.selector+G;o(document).bind(i(G,this.selector),this.selector,E);return this},die:function(F,E){o(document).unbind(i(F,this.selector),E?{guid:E.guid+this.selector+F}:null);return this}});function c(H){var E=RegExp("(^|\\.)"+H.type+"(\\.|$)"),G=true,F=[];o.each(o.data(this,"events").live||[],function(I,J){if(E.test(J.type)){var K=o(H.target).closest(J.data)[0];if(K){F.push({elem:K,fn:J})}}});F.sort(function(J,I){return o.data(J.elem,"closest")-o.data(I.elem,"closest")});o.each(F,function(){if(this.fn.call(this.elem,H,this.fn.data)===false){return(G=false)}});return G}function i(F,E){return["live",F,E.replace(/\./g,"`").replace(/ /g,"|")].join(".")}o.extend({isReady:false,readyList:[],ready:function(){if(!o.isReady){o.isReady=true;if(o.readyList){o.each(o.readyList,function(){this.call(document,o)});o.readyList=null}o(document).triggerHandler("ready")}}});var x=false;function B(){if(x){return}x=true;if(document.addEventListener){document.addEventListener("DOMContentLoaded",function(){document.removeEventListener("DOMContentLoaded",arguments.callee,false);o.ready()},false)}else{if(document.attachEvent){document.attachEvent("onreadystatechange",function(){if(document.readyState==="complete"){document.detachEvent("onreadystatechange",arguments.callee);o.ready()}});if(document.documentElement.doScroll&&l==l.top){(function(){if(o.isReady){return}try{document.documentElement.doScroll("left")}catch(E){setTimeout(arguments.callee,0);return}o.ready()})()}}}o.event.add(l,"load",o.ready)}o.each(("blur,focus,load,resize,scroll,unload,click,dblclick,mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave,change,select,submit,keydown,keypress,keyup,error").split(","),function(F,E){o.fn[E]=function(G){return G?this.bind(E,G):this.trigger(E)}});o(l).bind("unload",function(){for(var E in o.cache){if(E!=1&&o.cache[E].handle){o.event.remove(o.cache[E].handle.elem)}}});(function(){o.support={};var F=document.documentElement,G=document.createElement("script"),K=document.createElement("div"),J="script"+(new Date).getTime();K.style.display="none";K.innerHTML='   <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';var H=K.getElementsByTagName("*"),E=K.getElementsByTagName("a")[0];if(!H||!H.length||!E){return}o.support={leadingWhitespace:K.firstChild.nodeType==3,tbody:!K.getElementsByTagName("tbody").length,objectAll:!!K.getElementsByTagName("object")[0].getElementsByTagName("*").length,htmlSerialize:!!K.getElementsByTagName("link").length,style:/red/.test(E.getAttribute("style")),hrefNormalized:E.getAttribute("href")==="/a",opacity:E.style.opacity==="0.5",cssFloat:!!E.style.cssFloat,scriptEval:false,noCloneEvent:true,boxModel:null};G.type="text/javascript";try{G.appendChild(document.createTextNode("window."+J+"=1;"))}catch(I){}F.insertBefore(G,F.firstChild);if(l[J]){o.support.scriptEval=true;delete l[J]}F.removeChild(G);if(K.attachEvent&&K.fireEvent){K.attachEvent("onclick",function(){o.support.noCloneEvent=false;K.detachEvent("onclick",arguments.callee)});K.cloneNode(true).fireEvent("onclick")}o(function(){var L=document.createElement("div");L.style.width=L.style.paddingLeft="1px";document.body.appendChild(L);o.boxModel=o.support.boxModel=L.offsetWidth===2;document.body.removeChild(L).style.display="none"})})();var w=o.support.cssFloat?"cssFloat":"styleFloat";o.props={"for":"htmlFor","class":"className","float":w,cssFloat:w,styleFloat:w,readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",tabindex:"tabIndex"};o.fn.extend({_load:o.fn.load,load:function(G,J,K){if(typeof G!=="string"){return this._load(G)}var I=G.indexOf(" ");if(I>=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("<div/>").append(M.responseText.replace(/<script(.|\s)*?\/script>/g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H<F;H++){var E=o.data(this[H],"olddisplay");this[H].style.display=E||"";if(o.css(this[H],"display")==="none"){var G=this[H].tagName,K;if(m[G]){K=m[G]}else{var I=o("<"+G+" />").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H<F;H++){this[H].style.display=o.data(this[H],"olddisplay")||""}return this}},hide:function(H,I){if(H){return this.animate(t("hide",3),H,I)}else{for(var G=0,F=this.length;G<F;G++){var E=o.data(this[G],"olddisplay");if(!E&&E!=="none"){o.data(this[G],"olddisplay",o.css(this[G],"display"))}}for(var G=0,F=this.length;G<F;G++){this[G].style.display="none"}return this}},_toggle:o.fn.toggle,toggle:function(G,F){var E=typeof G==="boolean";return o.isFunction(G)&&o.isFunction(F)?this._toggle.apply(this,arguments):G==null||E?this.each(function(){var H=E?G:o(this).is(":hidden");o(this)[H?"show":"hide"]()}):this.animate(t("toggle",3),G,F)},fadeTo:function(E,G,F){return this.animate({opacity:G},E,F)},animate:function(I,F,H,G){var E=o.speed(F,H,G);return this[E.queue===false?"each":"queue"](function(){var K=o.extend({},E),M,L=this.nodeType==1&&o(this).is(":hidden"),J=this;for(M in I){if(I[M]=="hide"&&L||I[M]=="show"&&!L){return K.complete.call(this)}if((M=="height"||M=="width")&&this.style){K.display=o.css(this,"display");K.overflow=this.style.overflow}}if(K.overflow!=null){this.style.overflow="hidden"}K.curAnim=o.extend({},I);o.each(I,function(O,S){var R=new o.fx(J,K,O);if(/toggle|show|hide/.test(S)){R[S=="toggle"?L?"show":"hide":S](I)}else{var Q=S.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),T=R.cur(true)||0;if(Q){var N=parseFloat(Q[2]),P=Q[3]||"px";if(P!="px"){J.style[O]=(N||1)+P;T=((N||1)/R.cur(true))*T;J.style[O]=T+P}if(Q[1]){N=((Q[1]=="-="?-1:1)*N)+T}R.custom(T,N,P)}else{R.custom(T,S,"")}}});return true})},stop:function(F,E){var G=o.timers;if(F){this.queue([])}this.each(function(){for(var H=G.length-1;H>=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J<K.length;J++){if(!K[J]()){K.splice(J--,1)}}if(!K.length){clearInterval(n);n=g}},13)}},show:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.show=true;this.custom(this.prop=="width"||this.prop=="height"?1:0,this.cur());o(this.elem).show()},hide:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(H){var G=e();if(H||G>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})();
\ No newline at end of file
diff --git a/continuum-webapp/src/main/webapp/js/jquery-ui-1.7.2.custom.min.js b/continuum-webapp/src/main/webapp/js/jquery-ui-1.7.2.custom.min.js
new file mode 100644
index 0000000..edaae88
--- /dev/null
+++ b/continuum-webapp/src/main/webapp/js/jquery-ui-1.7.2.custom.min.js
@@ -0,0 +1,34 @@
+/*
+ * jQuery UI 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI
+ */
+jQuery.ui||(function(c){var i=c.fn.remove,d=c.browser.mozilla&&(parseFloat(c.browser.version)<1.9);c.ui={version:"1.7.2",plugin:{add:function(k,l,n){var m=c.ui[k].prototype;for(var j in n){m.plugins[j]=m.plugins[j]||[];m.plugins[j].push([l,n[j]])}},call:function(j,l,k){var n=j.plugins[l];if(!n||!j.element[0].parentNode){return}for(var m=0;m<n.length;m++){if(j.options[n[m][0]]){n[m][1].apply(j.element,k)}}}},contains:function(k,j){return document.compareDocumentPosition?k.compareDocumentPosition(j)&16:k!==j&&k.contains(j)},hasScroll:function(m,k){if(c(m).css("overflow")=="hidden"){return false}var j=(k&&k=="left")?"scrollLeft":"scrollTop",l=false;if(m[j]>0){return true}m[j]=1;l=(m[j]>0);m[j]=0;return l},isOverAxis:function(k,j,l){return(k>j)&&(k<(j+l))},isOver:function(o,k,n,m,j,l){return c.ui.isOverAxis(o,n,j)&&c.ui.isOverAxis(k,m,l)},keyCode:{BACKSPACE:8,CAPS_LOCK:20,COMMA:188,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38}};if(d){var f=c.attr,e=c.fn.removeAttr,h="http://www.w3.org/2005/07/aaa",a=/^aria-/,b=/^wairole:/;c.attr=function(k,j,l){var m=l!==undefined;return(j=="role"?(m?f.call(this,k,j,"wairole:"+l):(f.apply(this,arguments)||"").replace(b,"")):(a.test(j)?(m?k.setAttributeNS(h,j.replace(a,"aaa:"),l):f.call(this,k,j.replace(a,"aaa:"))):f.apply(this,arguments)))};c.fn.removeAttr=function(j){return(a.test(j)?this.each(function(){this.removeAttributeNS(h,j.replace(a,""))}):e.call(this,j))}}c.fn.extend({remove:function(){c("*",this).add(this).each(function(){c(this).triggerHandler("remove")});return i.apply(this,arguments)},enableSelection:function(){return this.attr("unselectable","off").css("MozUserSelect","").unbind("selectstart.ui")},disableSelection:function(){return this.attr("unselectable","on").css("MozUserSelect","none").bind("selectstart.ui",function(){return false})},scrollParent:function(){var j;if((c.browser.msie&&(/(static|relative)/).test(this.css("position")))||(/absolute/).test(this.css("position"))){j=this.parents().filter(function(){return(/(relative|absolute|fixed)/).test(c.curCSS(this,"position",1))&&(/(auto|scroll)/).test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0)}else{j=this.parents().filter(function(){return(/(auto|scroll)/).test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0)}return(/fixed/).test(this.css("position"))||!j.length?c(document):j}});c.extend(c.expr[":"],{data:function(l,k,j){return !!c.data(l,j[3])},focusable:function(k){var l=k.nodeName.toLowerCase(),j=c.attr(k,"tabindex");return(/input|select|textarea|button|object/.test(l)?!k.disabled:"a"==l||"area"==l?k.href||!isNaN(j):!isNaN(j))&&!c(k)["area"==l?"parents":"closest"](":hidden").length},tabbable:function(k){var j=c.attr(k,"tabindex");return(isNaN(j)||j>=0)&&c(k).is(":focusable")}});function g(m,n,o,l){function k(q){var p=c[m][n][q]||[];return(typeof p=="string"?p.split(/,?\s+/):p)}var j=k("getter");if(l.length==1&&typeof l[0]=="string"){j=j.concat(k("getterSetter"))}return(c.inArray(o,j)!=-1)}c.widget=function(k,j){var l=k.split(".")[0];k=k.split(".")[1];c.fn[k]=function(p){var n=(typeof p=="string"),o=Array.prototype.slice.call(arguments,1);if(n&&p.substring(0,1)=="_"){return this}if(n&&g(l,k,p,o)){var m=c.data(this[0],k);return(m?m[p].apply(m,o):undefined)}return this.each(function(){var q=c.data(this,k);(!q&&!n&&c.data(this,k,new c[l][k](this,p))._init());(q&&n&&c.isFunction(q[p])&&q[p].apply(q,o))})};c[l]=c[l]||{};c[l][k]=function(o,n){var m=this;this.namespace=l;this.widgetName=k;this.widgetEventPrefix=c[l][k].eventPrefix||k;this.widgetBaseClass=l+"-"+k;this.options=c.extend({},c.widget.defaults,c[l][k].defaults,c.metadata&&c.metadata.get(o)[k],n);this.element=c(o).bind("setData."+k,function(q,p,r){if(q.target==o){return m._setData(p,r)}}).bind("getData."+k,function(q,p){if(q.target==o){return m._getData(p)}}).bind("remove",function(){return m.destroy()})};c[l][k].prototype=c.extend({},c.widget.prototype,j);c[l][k].getterSetter="option"};c.widget.prototype={_init:function(){},destroy:function(){this.element.removeData(this.widgetName).removeClass(this.widgetBaseClass+"-disabled "+this.namespace+"-state-disabled").removeAttr("aria-disabled")},option:function(l,m){var k=l,j=this;if(typeof l=="string"){if(m===undefined){return this._getData(l)}k={};k[l]=m}c.each(k,function(n,o){j._setData(n,o)})},_getData:function(j){return this.options[j]},_setData:function(j,k){this.options[j]=k;if(j=="disabled"){this.element[k?"addClass":"removeClass"](this.widgetBaseClass+"-disabled "+this.namespace+"-state-disabled").attr("aria-disabled",k)}},enable:function(){this._setData("disabled",false)},disable:function(){this._setData("disabled",true)},_trigger:function(l,m,n){var p=this.options[l],j=(l==this.widgetEventPrefix?l:this.widgetEventPrefix+l);m=c.Event(m);m.type=j;if(m.originalEvent){for(var k=c.event.props.length,o;k;){o=c.event.props[--k];m[o]=m.originalEvent[o]}}this.element.trigger(m,n);return !(c.isFunction(p)&&p.call(this.element[0],m,n)===false||m.isDefaultPrevented())}};c.widget.defaults={disabled:false};c.ui.mouse={_mouseInit:function(){var j=this;this.element.bind("mousedown."+this.widgetName,function(k){return j._mouseDown(k)}).bind("click."+this.widgetName,function(k){if(j._preventClickEvent){j._preventClickEvent=false;k.stopImmediatePropagation();return false}});if(c.browser.msie){this._mouseUnselectable=this.element.attr("unselectable");this.element.attr("unselectable","on")}this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName);(c.browser.msie&&this.element.attr("unselectable",this._mouseUnselectable))},_mouseDown:function(l){l.originalEvent=l.originalEvent||{};if(l.originalEvent.mouseHandled){return}(this._mouseStarted&&this._mouseUp(l));this._mouseDownEvent=l;var k=this,m=(l.which==1),j=(typeof this.options.cancel=="string"?c(l.target).parents().add(l.target).filter(this.options.cancel).length:false);if(!m||j||!this._mouseCapture(l)){return true}this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet){this._mouseDelayTimer=setTimeout(function(){k.mouseDelayMet=true},this.options.delay)}if(this._mouseDistanceMet(l)&&this._mouseDelayMet(l)){this._mouseStarted=(this._mouseStart(l)!==false);if(!this._mouseStarted){l.preventDefault();return true}}this._mouseMoveDelegate=function(n){return k._mouseMove(n)};this._mouseUpDelegate=function(n){return k._mouseUp(n)};c(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);(c.browser.safari||l.preventDefault());l.originalEvent.mouseHandled=true;return true},_mouseMove:function(j){if(c.browser.msie&&!j.button){return this._mouseUp(j)}if(this._mouseStarted){this._mouseDrag(j);return j.preventDefault()}if(this._mouseDistanceMet(j)&&this._mouseDelayMet(j)){this._mouseStarted=(this._mouseStart(this._mouseDownEvent,j)!==false);(this._mouseStarted?this._mouseDrag(j):this._mouseUp(j))}return !this._mouseStarted},_mouseUp:function(j){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._preventClickEvent=(j.target==this._mouseDownEvent.target);this._mouseStop(j)}return false},_mouseDistanceMet:function(j){return(Math.max(Math.abs(this._mouseDownEvent.pageX-j.pageX),Math.abs(this._mouseDownEvent.pageY-j.pageY))>=this.options.distance)},_mouseDelayMet:function(j){return this.mouseDelayMet},_mouseStart:function(j){},_mouseDrag:function(j){},_mouseStop:function(j){},_mouseCapture:function(j){return true}};c.ui.mouse.defaults={cancel:null,distance:1,delay:0}})(jQuery);;/*
+ * jQuery UI Accordion 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Accordion
+ *
+ * Depends:
+ *	ui.core.js
+ */
+(function(a){a.widget("ui.accordion",{_init:function(){var d=this.options,b=this;this.running=0;if(d.collapsible==a.ui.accordion.defaults.collapsible&&d.alwaysOpen!=a.ui.accordion.defaults.alwaysOpen){d.collapsible=!d.alwaysOpen}if(d.navigation){var c=this.element.find("a").filter(d.navigationFilter);if(c.length){if(c.filter(d.header).length){this.active=c}else{this.active=c.parent().parent().prev();c.addClass("ui-accordion-content-active")}}}this.element.addClass("ui-accordion ui-widget ui-helper-reset");if(this.element[0].nodeName=="UL"){this.element.children("li").addClass("ui-accordion-li-fix")}this.headers=this.element.find(d.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){a(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){a(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){a(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){a(this).removeClass("ui-state-focus")});this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");this.active=this._findActive(this.active||d.active).toggleClass("ui-state-default").toggleClass("ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");this.active.next().addClass("ui-accordion-content-active");a("<span/>").addClass("ui-icon "+d.icons.header).prependTo(this.headers);this.active.find(".ui-icon").toggleClass(d.icons.header).toggleClass(d.icons.headerSelected);if(a.browser.msie){this.element.find("a").css("zoom","1")}this.resize();this.element.attr("role","tablist");this.headers.attr("role","tab").bind("keydown",function(e){return b._keydown(e)}).next().attr("role","tabpanel");this.headers.not(this.active||"").attr("aria-expanded","false").attr("tabIndex","-1").next().hide();if(!this.active.length){this.headers.eq(0).attr("tabIndex","0")}else{this.active.attr("aria-expanded","true").attr("tabIndex","0")}if(!a.browser.safari){this.headers.find("a").attr("tabIndex","-1")}if(d.event){this.headers.bind((d.event)+".accordion",function(e){return b._clickHandler.call(b,e,this)})}},destroy:function(){var c=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role").unbind(".accordion").removeData("accordion");this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("tabindex");this.headers.find("a").removeAttr("tabindex");this.headers.children(".ui-icon").remove();var b=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active");if(c.autoHeight||c.fillHeight){b.css("height","")}},_setData:function(b,c){if(b=="alwaysOpen"){b="collapsible";c=!c}a.widget.prototype._setData.apply(this,arguments)},_keydown:function(e){var g=this.options,f=a.ui.keyCode;if(g.disabled||e.altKey||e.ctrlKey){return}var d=this.headers.length;var b=this.headers.index(e.target);var c=false;switch(e.keyCode){case f.RIGHT:case f.DOWN:c=this.headers[(b+1)%d];break;case f.LEFT:case f.UP:c=this.headers[(b-1+d)%d];break;case f.SPACE:case f.ENTER:return this._clickHandler({target:e.target},e.target)}if(c){a(e.target).attr("tabIndex","-1");a(c).attr("tabIndex","0");c.focus();return false}return true},resize:function(){var e=this.options,d;if(e.fillSpace){if(a.browser.msie){var b=this.element.parent().css("overflow");this.element.parent().css("overflow","hidden")}d=this.element.parent().height();if(a.browser.msie){this.element.parent().css("overflow",b)}this.headers.each(function(){d-=a(this).outerHeight()});var c=0;this.headers.next().each(function(){c=Math.max(c,a(this).innerHeight()-a(this).height())}).height(Math.max(0,d-c)).css("overflow","auto")}else{if(e.autoHeight){d=0;this.headers.next().each(function(){d=Math.max(d,a(this).outerHeight())}).height(d)}}},activate:function(b){var c=this._findActive(b)[0];this._clickHandler({target:c},c)},_findActive:function(b){return b?typeof b=="number"?this.headers.filter(":eq("+b+")"):this.headers.not(this.headers.not(b)):b===false?a([]):this.headers.filter(":eq(0)")},_clickHandler:function(b,f){var d=this.options;if(d.disabled){return false}if(!b.target&&d.collapsible){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").find(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);this.active.next().addClass("ui-accordion-content-active");var h=this.active.next(),e={options:d,newHeader:a([]),oldHeader:d.active,newContent:a([]),oldContent:h},c=(this.active=a([]));this._toggle(c,h,e);return false}var g=a(b.currentTarget||f);var i=g[0]==this.active[0];if(this.running||(!d.collapsible&&i)){return false}this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").find(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);this.active.next().addClass("ui-accordion-content-active");if(!i){g.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").find(".ui-icon").removeClass(d.icons.header).addClass(d.icons.headerSelected);g.next().addClass("ui-accordion-content-active")}var c=g.next(),h=this.active.next(),e={options:d,newHeader:i&&d.collapsible?a([]):g,oldHeader:this.active,newContent:i&&d.collapsible?a([]):c.find("> *"),oldContent:h.find("> *")},j=this.headers.index(this.active[0])>this.headers.index(g[0]);this.active=i?a([]):g;this._toggle(c,h,e,i,j);return false},_toggle:function(b,i,g,j,k){var d=this.options,m=this;this.toShow=b;this.toHide=i;this.data=g;var c=function(){if(!m){return}return m._completed.apply(m,arguments)};this._trigger("changestart",null,this.data);this.running=i.size()===0?b.size():i.size();if(d.animated){var f={};if(d.collapsible&&j){f={toShow:a([]),toHide:i,complete:c,down:k,autoHeight:d.autoHeight||d.fillSpace}}else{f={toShow:b,toHide:i,complete:c,down:k,autoHeight:d.autoHeight||d.fillSpace}}if(!d.proxied){d.proxied=d.animated}if(!d.proxiedDuration){d.proxiedDuration=d.duration}d.animated=a.isFunction(d.proxied)?d.proxied(f):d.proxied;d.duration=a.isFunction(d.proxiedDuration)?d.proxiedDuration(f):d.proxiedDuration;var l=a.ui.accordion.animations,e=d.duration,h=d.animated;if(!l[h]){l[h]=function(n){this.slide(n,{easing:h,duration:e||700})}}l[h](f)}else{if(d.collapsible&&j){b.toggle()}else{i.hide();b.show()}c(true)}i.prev().attr("aria-expanded","false").attr("tabIndex","-1").blur();b.prev().attr("aria-expanded","true").attr("tabIndex","0").focus()},_completed:function(b){var c=this.options;this.running=b?0:--this.running;if(this.running){return}if(c.clearStyle){this.toShow.add(this.toHide).css({height:"",overflow:""})}this._trigger("change",null,this.data)}});a.extend(a.ui.accordion,{version:"1.7.2",defaults:{active:null,alwaysOpen:true,animated:"slide",autoHeight:true,clearStyle:false,collapsible:false,event:"click",fillSpace:false,header:"> li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:false,navigationFilter:function(){return this.href.toLowerCase()==location.href.toLowerCase()}},animations:{slide:function(j,h){j=a.extend({easing:"swing",duration:300},j,h);if(!j.toHide.size()){j.toShow.animate({height:"show"},j);return}if(!j.toShow.size()){j.toHide.animate({height:"hide"},j);return}var c=j.toShow.css("overflow"),g,d={},f={},e=["height","paddingTop","paddingBottom"],b;var i=j.toShow;b=i[0].style.width;i.width(parseInt(i.parent().width(),10)-parseInt(i.css("paddingLeft"),10)-parseInt(i.css("paddingRight"),10)-(parseInt(i.css("borderLeftWidth"),10)||0)-(parseInt(i.css("borderRightWidth"),10)||0));a.each(e,function(k,m){f[m]="hide";var l=(""+a.css(j.toShow[0],m)).match(/^([\d+-.]+)(.*)$/);d[m]={value:l[1],unit:l[2]||"px"}});j.toShow.css({height:0,overflow:"hidden"}).show();j.toHide.filter(":hidden").each(j.complete).end().filter(":visible").animate(f,{step:function(k,l){if(l.prop=="height"){g=(l.now-l.start)/(l.end-l.start)}j.toShow[0].style[l.prop]=(g*d[l.prop].value)+d[l.prop].unit},duration:j.duration,easing:j.easing,complete:function(){if(!j.autoHeight){j.toShow.css("height","")}j.toShow.css("width",b);j.toShow.css({overflow:c});j.complete()}})},bounceslide:function(b){this.slide(b,{easing:b.down?"easeOutBounce":"swing",duration:b.down?1000:200})},easeslide:function(b){this.slide(b,{easing:"easeinout",duration:700})}}})})(jQuery);;/*
+ * jQuery UI Datepicker 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Datepicker
+ *
+ * Depends:
+ *	ui.core.js
+ */
+(function($){$.extend($.ui,{datepicker:{version:"1.7.2"}});var PROP_NAME="datepicker";function Datepicker(){this.debug=false;this._curInst=null;this._keyEvent=false;this._disabledInputs=[];this._datepickerShowing=false;this._inDialog=false;this._mainDivId="ui-datepicker-div";this._inlineClass="ui-datepicker-inline";this._appendClass="ui-datepicker-append";this._triggerClass="ui-datepicker-trigger";this._dialogClass="ui-datepicker-dialog";this._disableClass="ui-datepicker-disabled";this._unselectableClass="ui-datepicker-unselectable";this._currentClass="ui-datepicker-current-day";this._dayOverClass="ui-datepicker-days-cell-over";this.regional=[];this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],dateFormat:"mm/dd/yy",firstDay:0,isRTL:false};this._defaults={showOn:"focus",showAnim:"show",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:false,hideIfNoPrevNext:false,navigationAsDateFormat:false,gotoCurrent:false,changeMonth:false,changeYear:false,showMonthAfterYear:false,yearRange:"-10:+10",showOtherMonths:false,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"normal",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:true,showButtonPanel:false};$.extend(this._defaults,this.regional[""]);this.dpDiv=$('<div id="'+this._mainDivId+'" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>')}$.extend(Datepicker.prototype,{markerClassName:"hasDatepicker",log:function(){if(this.debug){console.log.apply("",arguments)}},setDefaults:function(settings){extendRemove(this._defaults,settings||{});return this},_attachDatepicker:function(target,settings){var inlineSettings=null;for(var attrName in this._defaults){var attrValue=target.getAttribute("date:"+attrName);if(attrValue){inlineSettings=inlineSettings||{};try{inlineSettings[attrName]=eval(attrValue)}catch(err){inlineSettings[attrName]=attrValue}}}var nodeName=target.nodeName.toLowerCase();var inline=(nodeName=="div"||nodeName=="span");if(!target.id){target.id="dp"+(++this.uuid)}var inst=this._newInst($(target),inline);inst.settings=$.extend({},settings||{},inlineSettings||{});if(nodeName=="input"){this._connectDatepicker(target,inst)}else{if(inline){this._inlineDatepicker(target,inst)}}},_newInst:function(target,inline){var id=target[0].id.replace(/([:\[\]\.])/g,"\\\\$1");return{id:id,input:target,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:inline,dpDiv:(!inline?this.dpDiv:$('<div class="'+this._inlineClass+' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))}},_connectDatepicker:function(target,inst){var input=$(target);inst.append=$([]);inst.trigger=$([]);if(input.hasClass(this.markerClassName)){return}var appendText=this._get(inst,"appendText");var isRTL=this._get(inst,"isRTL");if(appendText){inst.append=$('<span class="'+this._appendClass+'">'+appendText+"</span>");input[isRTL?"before":"after"](inst.append)}var showOn=this._get(inst,"showOn");if(showOn=="focus"||showOn=="both"){input.focus(this._showDatepicker)}if(showOn=="button"||showOn=="both"){var buttonText=this._get(inst,"buttonText");var buttonImage=this._get(inst,"buttonImage");inst.trigger=$(this._get(inst,"buttonImageOnly")?$("<img/>").addClass(this._triggerClass).attr({src:buttonImage,alt:buttonText,title:buttonText}):$('<button type="button"></button>').addClass(this._triggerClass).html(buttonImage==""?buttonText:$("<img/>").attr({src:buttonImage,alt:buttonText,title:buttonText})));input[isRTL?"before":"after"](inst.trigger);inst.trigger.click(function(){if($.datepicker._datepickerShowing&&$.datepicker._lastInput==target){$.datepicker._hideDatepicker()}else{$.datepicker._showDatepicker(target)}return false})}input.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).bind("setData.datepicker",function(event,key,value){inst.settings[key]=value}).bind("getData.datepicker",function(event,key){return this._get(inst,key)});$.data(target,PROP_NAME,inst)},_inlineDatepicker:function(target,inst){var divSpan=$(target);if(divSpan.hasClass(this.markerClassName)){return}divSpan.addClass(this.markerClassName).append(inst.dpDiv).bind("setData.datepicker",function(event,key,value){inst.settings[key]=value}).bind("getData.datepicker",function(event,key){return this._get(inst,key)});$.data(target,PROP_NAME,inst);this._setDate(inst,this._getDefaultDate(inst));this._updateDatepicker(inst);this._updateAlternate(inst)},_dialogDatepicker:function(input,dateText,onSelect,settings,pos){var inst=this._dialogInst;if(!inst){var id="dp"+(++this.uuid);this._dialogInput=$('<input type="text" id="'+id+'" size="1" style="position: absolute; top: -100px;"/>');this._dialogInput.keydown(this._doKeyDown);$("body").append(this._dialogInput);inst=this._dialogInst=this._newInst(this._dialogInput,false);inst.settings={};$.data(this._dialogInput[0],PROP_NAME,inst)}extendRemove(inst.settings,settings||{});this._dialogInput.val(dateText);this._pos=(pos?(pos.length?pos:[pos.pageX,pos.pageY]):null);if(!this._pos){var browserWidth=window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth;var browserHeight=window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight;var scrollX=document.documentElement.scrollLeft||document.body.scrollLeft;var scrollY=document.documentElement.scrollTop||document.body.scrollTop;this._pos=[(browserWidth/2)-100+scrollX,(browserHeight/2)-150+scrollY]}this._dialogInput.css("left",this._pos[0]+"px").css("top",this._pos[1]+"px");inst.settings.onSelect=onSelect;this._inDialog=true;this.dpDiv.addClass(this._dialogClass);this._showDatepicker(this._dialogInput[0]);if($.blockUI){$.blockUI(this.dpDiv)}$.data(this._dialogInput[0],PROP_NAME,inst);return this},_destroyDatepicker:function(target){var $target=$(target);var inst=$.data(target,PROP_NAME);if(!$target.hasClass(this.markerClassName)){return}var nodeName=target.nodeName.toLowerCase();$.removeData(target,PROP_NAME);if(nodeName=="input"){inst.append.remove();inst.trigger.remove();$target.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress)}else{if(nodeName=="div"||nodeName=="span"){$target.removeClass(this.markerClassName).empty()}}},_enableDatepicker:function(target){var $target=$(target);var inst=$.data(target,PROP_NAME);if(!$target.hasClass(this.markerClassName)){return}var nodeName=target.nodeName.toLowerCase();if(nodeName=="input"){target.disabled=false;inst.trigger.filter("button").each(function(){this.disabled=false}).end().filter("img").css({opacity:"1.0",cursor:""})}else{if(nodeName=="div"||nodeName=="span"){var inline=$target.children("."+this._inlineClass);inline.children().removeClass("ui-state-disabled")}}this._disabledInputs=$.map(this._disabledInputs,function(value){return(value==target?null:value)})},_disableDatepicker:function(target){var $target=$(target);var inst=$.data(target,PROP_NAME);if(!$target.hasClass(this.markerClassName)){return}var nodeName=target.nodeName.toLowerCase();if(nodeName=="input"){target.disabled=true;inst.trigger.filter("button").each(function(){this.disabled=true}).end().filter("img").css({opacity:"0.5",cursor:"default"})}else{if(nodeName=="div"||nodeName=="span"){var inline=$target.children("."+this._inlineClass);inline.children().addClass("ui-state-disabled")}}this._disabledInputs=$.map(this._disabledInputs,function(value){return(value==target?null:value)});this._disabledInputs[this._disabledInputs.length]=target},_isDisabledDatepicker:function(target){if(!target){return false}for(var i=0;i<this._disabledInputs.length;i++){if(this._disabledInputs[i]==target){return true}}return false},_getInst:function(target){try{return $.data(target,PROP_NAME)}catch(err){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(target,name,value){var inst=this._getInst(target);if(arguments.length==2&&typeof name=="string"){return(name=="defaults"?$.extend({},$.datepicker._defaults):(inst?(name=="all"?$.extend({},inst.settings):this._get(inst,name)):null))}var settings=name||{};if(typeof name=="string"){settings={};settings[name]=value}if(inst){if(this._curInst==inst){this._hideDatepicker(null)}var date=this._getDateDatepicker(target);extendRemove(inst.settings,settings);this._setDateDatepicker(target,date);this._updateDatepicker(inst)}},_changeDatepicker:function(target,name,value){this._optionDatepicker(target,name,value)},_refreshDatepicker:function(target){var inst=this._getInst(target);if(inst){this._updateDatepicker(inst)}},_setDateDatepicker:function(target,date,endDate){var inst=this._getInst(target);if(inst){this._setDate(inst,date,endDate);this._updateDatepicker(inst);this._updateAlternate(inst)}},_getDateDatepicker:function(target){var inst=this._getInst(target);if(inst&&!inst.inline){this._setDateFromField(inst)}return(inst?this._getDate(inst):null)},_doKeyDown:function(event){var inst=$.datepicker._getInst(event.target);var handled=true;var isRTL=inst.dpDiv.is(".ui-datepicker-rtl");inst._keyEvent=true;if($.datepicker._datepickerShowing){switch(event.keyCode){case 9:$.datepicker._hideDatepicker(null,"");break;case 13:var sel=$("td."+$.datepicker._dayOverClass+", td."+$.datepicker._currentClass,inst.dpDiv);if(sel[0]){$.datepicker._selectDay(event.target,inst.selectedMonth,inst.selectedYear,sel[0])}else{$.datepicker._hideDatepicker(null,$.datepicker._get(inst,"duration"))}return false;break;case 27:$.datepicker._hideDatepicker(null,$.datepicker._get(inst,"duration"));break;case 33:$.datepicker._adjustDate(event.target,(event.ctrlKey?-$.datepicker._get(inst,"stepBigMonths"):-$.datepicker._get(inst,"stepMonths")),"M");break;case 34:$.datepicker._adjustDate(event.target,(event.ctrlKey?+$.datepicker._get(inst,"stepBigMonths"):+$.datepicker._get(inst,"stepMonths")),"M");break;case 35:if(event.ctrlKey||event.metaKey){$.datepicker._clearDate(event.target)}handled=event.ctrlKey||event.metaKey;break;case 36:if(event.ctrlKey||event.metaKey){$.datepicker._gotoToday(event.target)}handled=event.ctrlKey||event.metaKey;break;case 37:if(event.ctrlKey||event.metaKey){$.datepicker._adjustDate(event.target,(isRTL?+1:-1),"D")}handled=event.ctrlKey||event.metaKey;if(event.originalEvent.altKey){$.datepicker._adjustDate(event.target,(event.ctrlKey?-$.datepicker._get(inst,"stepBigMonths"):-$.datepicker._get(inst,"stepMonths")),"M")}break;case 38:if(event.ctrlKey||event.metaKey){$.datepicker._adjustDate(event.target,-7,"D")}handled=event.ctrlKey||event.metaKey;break;case 39:if(event.ctrlKey||event.metaKey){$.datepicker._adjustDate(event.target,(isRTL?-1:+1),"D")}handled=event.ctrlKey||event.metaKey;if(event.originalEvent.altKey){$.datepicker._adjustDate(event.target,(event.ctrlKey?+$.datepicker._get(inst,"stepBigMonths"):+$.datepicker._get(inst,"stepMonths")),"M")}break;case 40:if(event.ctrlKey||event.metaKey){$.datepicker._adjustDate(event.target,+7,"D")}handled=event.ctrlKey||event.metaKey;break;default:handled=false}}else{if(event.keyCode==36&&event.ctrlKey){$.datepicker._showDatepicker(this)}else{handled=false}}if(handled){event.preventDefault();event.stopPropagation()}},_doKeyPress:function(event){var inst=$.datepicker._getInst(event.target);if($.datepicker._get(inst,"constrainInput")){var chars=$.datepicker._possibleChars($.datepicker._get(inst,"dateFormat"));var chr=String.fromCharCode(event.charCode==undefined?event.keyCode:event.charCode);return event.ctrlKey||(chr<" "||!chars||chars.indexOf(chr)>-1)}},_showDatepicker:function(input){input=input.target||input;if(input.nodeName.toLowerCase()!="input"){input=$("input",input.parentNode)[0]}if($.datepicker._isDisabledDatepicker(input)||$.datepicker._lastInput==input){return}var inst=$.datepicker._getInst(input);var beforeShow=$.datepicker._get(inst,"beforeShow");extendRemove(inst.settings,(beforeShow?beforeShow.apply(input,[input,inst]):{}));$.datepicker._hideDatepicker(null,"");$.datepicker._lastInput=input;$.datepicker._setDateFromField(inst);if($.datepicker._inDialog){input.value=""}if(!$.datepicker._pos){$.datepicker._pos=$.datepicker._findPos(input);$.datepicker._pos[1]+=input.offsetHeight}var isFixed=false;$(input).parents().each(function(){isFixed|=$(this).css("position")=="fixed";return !isFixed});if(isFixed&&$.browser.opera){$.datepicker._pos[0]-=document.documentElement.scrollLeft;$.datepicker._pos[1]-=document.documentElement.scrollTop}var offset={left:$.datepicker._pos[0],top:$.datepicker._pos[1]};$.datepicker._pos=null;inst.rangeStart=null;inst.dpDiv.css({position:"absolute",display:"block",top:"-1000px"});$.datepicker._updateDatepicker(inst);offset=$.datepicker._checkOffset(inst,offset,isFixed);inst.dpDiv.css({position:($.datepicker._inDialog&&$.blockUI?"static":(isFixed?"fixed":"absolute")),display:"none",left:offset.left+"px",top:offset.top+"px"});if(!inst.inline){var showAnim=$.datepicker._get(inst,"showAnim")||"show";var duration=$.datepicker._get(inst,"duration");var postProcess=function(){$.datepicker._datepickerShowing=true;if($.browser.msie&&parseInt($.browser.version,10)<7){$("iframe.ui-datepicker-cover").css({width:inst.dpDiv.width()+4,height:inst.dpDiv.height()+4})}};if($.effects&&$.effects[showAnim]){inst.dpDiv.show(showAnim,$.datepicker._get(inst,"showOptions"),duration,postProcess)}else{inst.dpDiv[showAnim](duration,postProcess)}if(duration==""){postProcess()}if(inst.input[0].type!="hidden"){inst.input[0].focus()}$.datepicker._curInst=inst}},_updateDatepicker:function(inst){var dims={width:inst.dpDiv.width()+4,height:inst.dpDiv.height()+4};var self=this;inst.dpDiv.empty().append(this._generateHTML(inst)).find("iframe.ui-datepicker-cover").css({width:dims.width,height:dims.height}).end().find("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a").bind("mouseout",function(){$(this).removeClass("ui-state-hover");if(this.className.indexOf("ui-datepicker-prev")!=-1){$(this).removeClass("ui-datepicker-prev-hover")}if(this.className.indexOf("ui-datepicker-next")!=-1){$(this).removeClass("ui-datepicker-next-hover")}}).bind("mouseover",function(){if(!self._isDisabledDatepicker(inst.inline?inst.dpDiv.parent()[0]:inst.input[0])){$(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");$(this).addClass("ui-state-hover");if(this.className.indexOf("ui-datepicker-prev")!=-1){$(this).addClass("ui-datepicker-prev-hover")}if(this.className.indexOf("ui-datepicker-next")!=-1){$(this).addClass("ui-datepicker-next-hover")}}}).end().find("."+this._dayOverClass+" a").trigger("mouseover").end();var numMonths=this._getNumberOfMonths(inst);var cols=numMonths[1];var width=17;if(cols>1){inst.dpDiv.addClass("ui-datepicker-multi-"+cols).css("width",(width*cols)+"em")}else{inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("")}inst.dpDiv[(numMonths[0]!=1||numMonths[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi");inst.dpDiv[(this._get(inst,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl");if(inst.input&&inst.input[0].type!="hidden"&&inst==$.datepicker._curInst){$(inst.input[0]).focus()}},_checkOffset:function(inst,offset,isFixed){var dpWidth=inst.dpDiv.outerWidth();var dpHeight=inst.dpDiv.outerHeight();var inputWidth=inst.input?inst.input.outerWidth():0;var inputHeight=inst.input?inst.input.outerHeight():0;var viewWidth=(window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth)+$(document).scrollLeft();var viewHeight=(window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight)+$(document).scrollTop();offset.left-=(this._get(inst,"isRTL")?(dpWidth-inputWidth):0);offset.left-=(isFixed&&offset.left==inst.input.offset().left)?$(document).scrollLeft():0;offset.top-=(isFixed&&offset.top==(inst.input.offset().top+inputHeight))?$(document).scrollTop():0;offset.left-=(offset.left+dpWidth>viewWidth&&viewWidth>dpWidth)?Math.abs(offset.left+dpWidth-viewWidth):0;offset.top-=(offset.top+dpHeight>viewHeight&&viewHeight>dpHeight)?Math.abs(offset.top+dpHeight+inputHeight*2-viewHeight):0;return offset},_findPos:function(obj){while(obj&&(obj.type=="hidden"||obj.nodeType!=1)){obj=obj.nextSibling}var position=$(obj).offset();return[position.left,position.top]},_hideDatepicker:function(input,duration){var inst=this._curInst;if(!inst||(input&&inst!=$.data(input,PROP_NAME))){return}if(inst.stayOpen){this._selectDate("#"+inst.id,this._formatDate(inst,inst.currentDay,inst.currentMonth,inst.currentYear))}inst.stayOpen=false;if(this._datepickerShowing){duration=(duration!=null?duration:this._get(inst,"duration"));var showAnim=this._get(inst,"showAnim");var postProcess=function(){$.datepicker._tidyDialog(inst)};if(duration!=""&&$.effects&&$.effects[showAnim]){inst.dpDiv.hide(showAnim,$.datepicker._get(inst,"showOptions"),duration,postProcess)}else{inst.dpDiv[(duration==""?"hide":(showAnim=="slideDown"?"slideUp":(showAnim=="fadeIn"?"fadeOut":"hide")))](duration,postProcess)}if(duration==""){this._tidyDialog(inst)}var onClose=this._get(inst,"onClose");if(onClose){onClose.apply((inst.input?inst.input[0]:null),[(inst.input?inst.input.val():""),inst])}this._datepickerShowing=false;this._lastInput=null;if(this._inDialog){this._dialogInput.css({position:"absolute",left:"0",top:"-100px"});if($.blockUI){$.unblockUI();$("body").append(this.dpDiv)}}this._inDialog=false}this._curInst=null},_tidyDialog:function(inst){inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(event){if(!$.datepicker._curInst){return}var $target=$(event.target);if(($target.parents("#"+$.datepicker._mainDivId).length==0)&&!$target.hasClass($.datepicker.markerClassName)&&!$target.hasClass($.datepicker._triggerClass)&&$.datepicker._datepickerShowing&&!($.datepicker._inDialog&&$.blockUI)){$.datepicker._hideDatepicker(null,"")}},_adjustDate:function(id,offset,period){var target=$(id);var inst=this._getInst(target[0]);if(this._isDisabledDatepicker(target[0])){return}this._adjustInstDate(inst,offset+(period=="M"?this._get(inst,"showCurrentAtPos"):0),period);this._updateDatepicker(inst)},_gotoToday:function(id){var target=$(id);var inst=this._getInst(target[0]);if(this._get(inst,"gotoCurrent")&&inst.currentDay){inst.selectedDay=inst.currentDay;inst.drawMonth=inst.selectedMonth=inst.currentMonth;inst.drawYear=inst.selectedYear=inst.currentYear}else{var date=new Date();inst.selectedDay=date.getDate();inst.drawMonth=inst.selectedMonth=date.getMonth();inst.drawYear=inst.selectedYear=date.getFullYear()}this._notifyChange(inst);this._adjustDate(target)},_selectMonthYear:function(id,select,period){var target=$(id);var inst=this._getInst(target[0]);inst._selectingMonthYear=false;inst["selected"+(period=="M"?"Month":"Year")]=inst["draw"+(period=="M"?"Month":"Year")]=parseInt(select.options[select.selectedIndex].value,10);this._notifyChange(inst);this._adjustDate(target)},_clickMonthYear:function(id){var target=$(id);var inst=this._getInst(target[0]);if(inst.input&&inst._selectingMonthYear&&!$.browser.msie){inst.input[0].focus()}inst._selectingMonthYear=!inst._selectingMonthYear},_selectDay:function(id,month,year,td){var target=$(id);if($(td).hasClass(this._unselectableClass)||this._isDisabledDatepicker(target[0])){return}var inst=this._getInst(target[0]);inst.selectedDay=inst.currentDay=$("a",td).html();inst.selectedMonth=inst.currentMonth=month;inst.selectedYear=inst.currentYear=year;if(inst.stayOpen){inst.endDay=inst.endMonth=inst.endYear=null}this._selectDate(id,this._formatDate(inst,inst.currentDay,inst.currentMonth,inst.currentYear));if(inst.stayOpen){inst.rangeStart=this._daylightSavingAdjust(new Date(inst.currentYear,inst.currentMonth,inst.currentDay));this._updateDatepicker(inst)}},_clearDate:function(id){var target=$(id);var inst=this._getInst(target[0]);inst.stayOpen=false;inst.endDay=inst.endMonth=inst.endYear=inst.rangeStart=null;this._selectDate(target,"")},_selectDate:function(id,dateStr){var target=$(id);var inst=this._getInst(target[0]);dateStr=(dateStr!=null?dateStr:this._formatDate(inst));if(inst.input){inst.input.val(dateStr)}this._updateAlternate(inst);var onSelect=this._get(inst,"onSelect");if(onSelect){onSelect.apply((inst.input?inst.input[0]:null),[dateStr,inst])}else{if(inst.input){inst.input.trigger("change")}}if(inst.inline){this._updateDatepicker(inst)}else{if(!inst.stayOpen){this._hideDatepicker(null,this._get(inst,"duration"));this._lastInput=inst.input[0];if(typeof(inst.input[0])!="object"){inst.input[0].focus()}this._lastInput=null}}},_updateAlternate:function(inst){var altField=this._get(inst,"altField");if(altField){var altFormat=this._get(inst,"altFormat")||this._get(inst,"dateFormat");var date=this._getDate(inst);dateStr=this.formatDate(altFormat,date,this._getFormatConfig(inst));$(altField).each(function(){$(this).val(dateStr)})}},noWeekends:function(date){var day=date.getDay();return[(day>0&&day<6),""]},iso8601Week:function(date){var checkDate=new Date(date.getFullYear(),date.getMonth(),date.getDate());var firstMon=new Date(checkDate.getFullYear(),1-1,4);var firstDay=firstMon.getDay()||7;firstMon.setDate(firstMon.getDate()+1-firstDay);if(firstDay<4&&checkDate<firstMon){checkDate.setDate(checkDate.getDate()-3);return $.datepicker.iso8601Week(checkDate)}else{if(checkDate>new Date(checkDate.getFullYear(),12-1,28)){firstDay=new Date(checkDate.getFullYear()+1,1-1,4).getDay()||7;if(firstDay>4&&(checkDate.getDay()||7)<firstDay-3){return 1}}}return Math.floor(((checkDate-firstMon)/86400000)/7)+1},parseDate:function(format,value,settings){if(format==null||value==null){throw"Invalid arguments"}value=(typeof value=="object"?value.toString():value+"");if(value==""){return null}var shortYearCutoff=(settings?settings.shortYearCutoff:null)||this._defaults.shortYearCutoff;var dayNamesShort=(settings?settings.dayNamesShort:null)||this._defaults.dayNamesShort;var dayNames=(settings?settings.dayNames:null)||this._defaults.dayNames;var monthNamesShort=(settings?settings.monthNamesShort:null)||this._defaults.monthNamesShort;var monthNames=(settings?settings.monthNames:null)||this._defaults.monthNames;var year=-1;var month=-1;var day=-1;var doy=-1;var literal=false;var lookAhead=function(match){var matches=(iFormat+1<format.length&&format.charAt(iFormat+1)==match);if(matches){iFormat++}return matches};var getNumber=function(match){lookAhead(match);var origSize=(match=="@"?14:(match=="y"?4:(match=="o"?3:2)));var size=origSize;var num=0;while(size>0&&iValue<value.length&&value.charAt(iValue)>="0"&&value.charAt(iValue)<="9"){num=num*10+parseInt(value.charAt(iValue++),10);size--}if(size==origSize){throw"Missing number at position "+iValue}return num};var getName=function(match,shortNames,longNames){var names=(lookAhead(match)?longNames:shortNames);var size=0;for(var j=0;j<names.length;j++){size=Math.max(size,names[j].length)}var name="";var iInit=iValue;while(size>0&&iValue<value.length){name+=value.charAt(iValue++);for(var i=0;i<names.length;i++){if(name==names[i]){return i+1}}size--}throw"Unknown name at position "+iInit};var checkLiteral=function(){if(value.charAt(iValue)!=format.charAt(iFormat)){throw"Unexpected literal at position "+iValue}iValue++};var iValue=0;for(var iFormat=0;iFormat<format.length;iFormat++){if(literal){if(format.charAt(iFormat)=="'"&&!lookAhead("'")){literal=false}else{checkLiteral()}}else{switch(format.charAt(iFormat)){case"d":day=getNumber("d");break;case"D":getName("D",dayNamesShort,dayNames);break;case"o":doy=getNumber("o");break;case"m":month=getNumber("m");break;case"M":month=getName("M",monthNamesShort,monthNames);break;case"y":year=getNumber("y");break;case"@":var date=new Date(getNumber("@"));year=date.getFullYear();month=date.getMonth()+1;day=date.getDate();break;case"'":if(lookAhead("'")){checkLiteral()}else{literal=true}break;default:checkLiteral()}}}if(year==-1){year=new Date().getFullYear()}else{if(year<100){year+=new Date().getFullYear()-new Date().getFullYear()%100+(year<=shortYearCutoff?0:-100)}}if(doy>-1){month=1;day=doy;do{var dim=this._getDaysInMonth(year,month-1);if(day<=dim){break}month++;day-=dim}while(true)}var date=this._daylightSavingAdjust(new Date(year,month-1,day));if(date.getFullYear()!=year||date.getMonth()+1!=month||date.getDate()!=day){throw"Invalid date"}return date},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TIMESTAMP:"@",W3C:"yy-mm-dd",formatDate:function(format,date,settings){if(!date){return""}var dayNamesShort=(settings?settings.dayNamesShort:null)||this._defaults.dayNamesShort;var dayNames=(settings?settings.dayNames:null)||this._defaults.dayNames;var monthNamesShort=(settings?settings.monthNamesShort:null)||this._defaults.monthNamesShort;var monthNames=(settings?settings.monthNames:null)||this._defaults.monthNames;var lookAhead=function(match){var matches=(iFormat+1<format.length&&format.charAt(iFormat+1)==match);if(matches){iFormat++}return matches};var formatNumber=function(match,value,len){var num=""+value;if(lookAhead(match)){while(num.length<len){num="0"+num}}return num};var formatName=function(match,value,shortNames,longNames){return(lookAhead(match)?longNames[value]:shortNames[value])};var output="";var literal=false;if(date){for(var iFormat=0;iFormat<format.length;iFormat++){if(literal){if(format.charAt(iFormat)=="'"&&!lookAhead("'")){literal=false}else{output+=format.charAt(iFormat)}}else{switch(format.charAt(iFormat)){case"d":output+=formatNumber("d",date.getDate(),2);break;case"D":output+=formatName("D",date.getDay(),dayNamesShort,dayNames);break;case"o":var doy=date.getDate();for(var m=date.getMonth()-1;m>=0;m--){doy+=this._getDaysInMonth(date.getFullYear(),m)}output+=formatNumber("o",doy,3);break;case"m":output+=formatNumber("m",date.getMonth()+1,2);break;case"M":output+=formatName("M",date.getMonth(),monthNamesShort,monthNames);break;case"y":output+=(lookAhead("y")?date.getFullYear():(date.getYear()%100<10?"0":"")+date.getYear()%100);break;case"@":output+=date.getTime();break;case"'":if(lookAhead("'")){output+="'"}else{literal=true}break;default:output+=format.charAt(iFormat)}}}}return output},_possibleChars:function(format){var chars="";var literal=false;for(var iFormat=0;iFormat<format.length;iFormat++){if(literal){if(format.charAt(iFormat)=="'"&&!lookAhead("'")){literal=false}else{chars+=format.charAt(iFormat)}}else{switch(format.charAt(iFormat)){case"d":case"m":case"y":case"@":chars+="0123456789";break;case"D":case"M":return null;case"'":if(lookAhead("'")){chars+="'"}else{literal=true}break;default:chars+=format.charAt(iFormat)}}}return chars},_get:function(inst,name){return inst.settings[name]!==undefined?inst.settings[name]:this._defaults[name]},_setDateFromField:function(inst){var dateFormat=this._get(inst,"dateFormat");var dates=inst.input?inst.input.val():null;inst.endDay=inst.endMonth=inst.endYear=null;var date=defaultDate=this._getDefaultDate(inst);var settings=this._getFormatConfig(inst);try{date=this.parseDate(dateFormat,dates,settings)||defaultDate}catch(event){this.log(event);date=defaultDate}inst.selectedDay=date.getDate();inst.drawMonth=inst.selectedMonth=date.getMonth();inst.drawYear=inst.selectedYear=date.getFullYear();inst.currentDay=(dates?date.getDate():0);inst.currentMonth=(dates?date.getMonth():0);inst.currentYear=(dates?date.getFullYear():0);this._adjustInstDate(inst)},_getDefaultDate:function(inst){var date=this._determineDate(this._get(inst,"defaultDate"),new Date());var minDate=this._getMinMaxDate(inst,"min",true);var maxDate=this._getMinMaxDate(inst,"max");date=(minDate&&date<minDate?minDate:date);date=(maxDate&&date>maxDate?maxDate:date);return date},_determineDate:function(date,defaultDate){var offsetNumeric=function(offset){var date=new Date();date.setDate(date.getDate()+offset);return date};var offsetString=function(offset,getDaysInMonth){var date=new Date();var year=date.getFullYear();var month=date.getMonth();var day=date.getDate();var pattern=/([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;var matches=pattern.exec(offset);while(matches){switch(matches[2]||"d"){case"d":case"D":day+=parseInt(matches[1],10);break;case"w":case"W":day+=parseInt(matches[1],10)*7;break;case"m":case"M":month+=parseInt(matches[1],10);day=Math.min(day,getDaysInMonth(year,month));break;case"y":case"Y":year+=parseInt(matches[1],10);day=Math.min(day,getDaysInMonth(year,month));break}matches=pattern.exec(offset)}return new Date(year,month,day)};date=(date==null?defaultDate:(typeof date=="string"?offsetString(date,this._getDaysInMonth):(typeof date=="number"?(isNaN(date)?defaultDate:offsetNumeric(date)):date)));date=(date&&date.toString()=="Invalid Date"?defaultDate:date);if(date){date.setHours(0);date.setMinutes(0);date.setSeconds(0);date.setMilliseconds(0)}return this._daylightSavingAdjust(date)},_daylightSavingAdjust:function(date){if(!date){return null}date.setHours(date.getHours()>12?date.getHours()+2:0);return date},_setDate:function(inst,date,endDate){var clear=!(date);var origMonth=inst.selectedMonth;var origYear=inst.selectedYear;date=this._determineDate(date,new Date());inst.selectedDay=inst.currentDay=date.getDate();inst.drawMonth=inst.selectedMonth=inst.currentMonth=date.getMonth();inst.drawYear=inst.selectedYear=inst.currentYear=date.getFullYear();if(origMonth!=inst.selectedMonth||origYear!=inst.selectedYear){this._notifyChange(inst)}this._adjustInstDate(inst);if(inst.input){inst.input.val(clear?"":this._formatDate(inst))}},_getDate:function(inst){var startDate=(!inst.currentYear||(inst.input&&inst.input.val()=="")?null:this._daylightSavingAdjust(new Date(inst.currentYear,inst.currentMonth,inst.currentDay)));return startDate},_generateHTML:function(inst){var today=new Date();today=this._daylightSavingAdjust(new Date(today.getFullYear(),today.getMonth(),today.getDate()));var isRTL=this._get(inst,"isRTL");var showButtonPanel=this._get(inst,"showButtonPanel");var hideIfNoPrevNext=this._get(inst,"hideIfNoPrevNext");var navigationAsDateFormat=this._get(inst,"navigationAsDateFormat");var numMonths=this._getNumberOfMonths(inst);var showCurrentAtPos=this._get(inst,"showCurrentAtPos");var stepMonths=this._get(inst,"stepMonths");var stepBigMonths=this._get(inst,"stepBigMonths");var isMultiMonth=(numMonths[0]!=1||numMonths[1]!=1);var currentDate=this._daylightSavingAdjust((!inst.currentDay?new Date(9999,9,9):new Date(inst.currentYear,inst.currentMonth,inst.currentDay)));var minDate=this._getMinMaxDate(inst,"min",true);var maxDate=this._getMinMaxDate(inst,"max");var drawMonth=inst.drawMonth-showCurrentAtPos;var drawYear=inst.drawYear;if(drawMonth<0){drawMonth+=12;drawYear--}if(maxDate){var maxDraw=this._daylightSavingAdjust(new Date(maxDate.getFullYear(),maxDate.getMonth()-numMonths[1]+1,maxDate.getDate()));maxDraw=(minDate&&maxDraw<minDate?minDate:maxDraw);while(this._daylightSavingAdjust(new Date(drawYear,drawMonth,1))>maxDraw){drawMonth--;if(drawMonth<0){drawMonth=11;drawYear--}}}inst.drawMonth=drawMonth;inst.drawYear=drawYear;var prevText=this._get(inst,"prevText");prevText=(!navigationAsDateFormat?prevText:this.formatDate(prevText,this._daylightSavingAdjust(new Date(drawYear,drawMonth-stepMonths,1)),this._getFormatConfig(inst)));var prev=(this._canAdjustMonth(inst,-1,drawYear,drawMonth)?'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#'+inst.id+"', -"+stepMonths+", 'M');\" title=\""+prevText+'"><span class="ui-icon ui-icon-circle-triangle-'+(isRTL?"e":"w")+'">'+prevText+"</span></a>":(hideIfNoPrevNext?"":'<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+prevText+'"><span class="ui-icon ui-icon-circle-triangle-'+(isRTL?"e":"w")+'">'+prevText+"</span></a>"));var nextText=this._get(inst,"nextText");nextText=(!navigationAsDateFormat?nextText:this.formatDate(nextText,this._daylightSavingAdjust(new Date(drawYear,drawMonth+stepMonths,1)),this._getFormatConfig(inst)));var next=(this._canAdjustMonth(inst,+1,drawYear,drawMonth)?'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#'+inst.id+"', +"+stepMonths+", 'M');\" title=\""+nextText+'"><span class="ui-icon ui-icon-circle-triangle-'+(isRTL?"w":"e")+'">'+nextText+"</span></a>":(hideIfNoPrevNext?"":'<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+nextText+'"><span class="ui-icon ui-icon-circle-triangle-'+(isRTL?"w":"e")+'">'+nextText+"</span></a>"));var currentText=this._get(inst,"currentText");var gotoDate=(this._get(inst,"gotoCurrent")&&inst.currentDay?currentDate:today);currentText=(!navigationAsDateFormat?currentText:this.formatDate(currentText,gotoDate,this._getFormatConfig(inst)));var controls=(!inst.inline?'<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery.datepicker._hideDatepicker();">'+this._get(inst,"closeText")+"</button>":"");var buttonPanel=(showButtonPanel)?'<div class="ui-datepicker-buttonpane ui-widget-content">'+(isRTL?controls:"")+(this._isInRange(inst,gotoDate)?'<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery.datepicker._gotoToday(\'#'+inst.id+"');\">"+currentText+"</button>":"")+(isRTL?"":controls)+"</div>":"";var firstDay=parseInt(this._get(inst,"firstDay"),10);firstDay=(isNaN(firstDay)?0:firstDay);var dayNames=this._get(inst,"dayNames");var dayNamesShort=this._get(inst,"dayNamesShort");var dayNamesMin=this._get(inst,"dayNamesMin");var monthNames=this._get(inst,"monthNames");var monthNamesShort=this._get(inst,"monthNamesShort");var beforeShowDay=this._get(inst,"beforeShowDay");var showOtherMonths=this._get(inst,"showOtherMonths");var calculateWeek=this._get(inst,"calculateWeek")||this.iso8601Week;var endDate=inst.endDay?this._daylightSavingAdjust(new Date(inst.endYear,inst.endMonth,inst.endDay)):currentDate;var defaultDate=this._getDefaultDate(inst);var html="";for(var row=0;row<numMonths[0];row++){var group="";for(var col=0;col<numMonths[1];col++){var selectedDate=this._daylightSavingAdjust(new Date(drawYear,drawMonth,inst.selectedDay));var cornerClass=" ui-corner-all";var calender="";if(isMultiMonth){calender+='<div class="ui-datepicker-group ui-datepicker-group-';switch(col){case 0:calender+="first";cornerClass=" ui-corner-"+(isRTL?"right":"left");break;case numMonths[1]-1:calender+="last";cornerClass=" ui-corner-"+(isRTL?"left":"right");break;default:calender+="middle";cornerClass="";break}calender+='">'}calender+='<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix'+cornerClass+'">'+(/all|left/.test(cornerClass)&&row==0?(isRTL?next:prev):"")+(/all|right/.test(cornerClass)&&row==0?(isRTL?prev:next):"")+this._generateMonthYearHeader(inst,drawMonth,drawYear,minDate,maxDate,selectedDate,row>0||col>0,monthNames,monthNamesShort)+'</div><table class="ui-datepicker-calendar"><thead><tr>';var thead="";for(var dow=0;dow<7;dow++){var day=(dow+firstDay)%7;thead+="<th"+((dow+firstDay+6)%7>=5?' class="ui-datepicker-week-end"':"")+'><span title="'+dayNames[day]+'">'+dayNamesMin[day]+"</span></th>"}calender+=thead+"</tr></thead><tbody>";var daysInMonth=this._getDaysInMonth(drawYear,drawMonth);if(drawYear==inst.selectedYear&&drawMonth==inst.selectedMonth){inst.selectedDay=Math.min(inst.selectedDay,daysInMonth)}var leadDays=(this._getFirstDayOfMonth(drawYear,drawMonth)-firstDay+7)%7;var numRows=(isMultiMonth?6:Math.ceil((leadDays+daysInMonth)/7));var printDate=this._daylightSavingAdjust(new Date(drawYear,drawMonth,1-leadDays));for(var dRow=0;dRow<numRows;dRow++){calender+="<tr>";var tbody="";for(var dow=0;dow<7;dow++){var daySettings=(beforeShowDay?beforeShowDay.apply((inst.input?inst.input[0]:null),[printDate]):[true,""]);var otherMonth=(printDate.getMonth()!=drawMonth);var unselectable=otherMonth||!daySettings[0]||(minDate&&printDate<minDate)||(maxDate&&printDate>maxDate);tbody+='<td class="'+((dow+firstDay+6)%7>=5?" ui-datepicker-week-end":"")+(otherMonth?" ui-datepicker-other-month":"")+((printDate.getTime()==selectedDate.getTime()&&drawMonth==inst.selectedMonth&&inst._keyEvent)||(defaultDate.getTime()==printDate.getTime()&&defaultDate.getTime()==selectedDate.getTime())?" "+this._dayOverClass:"")+(unselectable?" "+this._unselectableClass+" ui-state-disabled":"")+(otherMonth&&!showOtherMonths?"":" "+daySettings[1]+(printDate.getTime()>=currentDate.getTime()&&printDate.getTime()<=endDate.getTime()?" "+this._currentClass:"")+(printDate.getTime()==today.getTime()?" ui-datepicker-today":""))+'"'+((!otherMonth||showOtherMonths)&&daySettings[2]?' title="'+daySettings[2]+'"':"")+(unselectable?"":" onclick=\"DP_jQuery.datepicker._selectDay('#"+inst.id+"',"+drawMonth+","+drawYear+', this);return false;"')+">"+(otherMonth?(showOtherMonths?printDate.getDate():"&#xa0;"):(unselectable?'<span class="ui-state-default">'+printDate.getDate()+"</span>":'<a class="ui-state-default'+(printDate.getTime()==today.getTime()?" ui-state-highlight":"")+(printDate.getTime()>=currentDate.getTime()&&printDate.getTime()<=endDate.getTime()?" ui-state-active":"")+'" href="#">'+printDate.getDate()+"</a>"))+"</td>";printDate.setDate(printDate.getDate()+1);printDate=this._daylightSavingAdjust(printDate)}calender+=tbody+"</tr>"}drawMonth++;if(drawMonth>11){drawMonth=0;drawYear++}calender+="</tbody></table>"+(isMultiMonth?"</div>"+((numMonths[0]>0&&col==numMonths[1]-1)?'<div class="ui-datepicker-row-break"></div>':""):"");group+=calender}html+=group}html+=buttonPanel+($.browser.msie&&parseInt($.browser.version,10)<7&&!inst.inline?'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>':"");inst._keyEvent=false;return html},_generateMonthYearHeader:function(inst,drawMonth,drawYear,minDate,maxDate,selectedDate,secondary,monthNames,monthNamesShort){minDate=(inst.rangeStart&&minDate&&selectedDate<minDate?selectedDate:minDate);var changeMonth=this._get(inst,"changeMonth");var changeYear=this._get(inst,"changeYear");var showMonthAfterYear=this._get(inst,"showMonthAfterYear");var html='<div class="ui-datepicker-title">';var monthHtml="";if(secondary||!changeMonth){monthHtml+='<span class="ui-datepicker-month">'+monthNames[drawMonth]+"</span> "}else{var inMinYear=(minDate&&minDate.getFullYear()==drawYear);var inMaxYear=(maxDate&&maxDate.getFullYear()==drawYear);monthHtml+='<select class="ui-datepicker-month" onchange="DP_jQuery.datepicker._selectMonthYear(\'#'+inst.id+"', this, 'M');\" onclick=\"DP_jQuery.datepicker._clickMonthYear('#"+inst.id+"');\">";for(var month=0;month<12;month++){if((!inMinYear||month>=minDate.getMonth())&&(!inMaxYear||month<=maxDate.getMonth())){monthHtml+='<option value="'+month+'"'+(month==drawMonth?' selected="selected"':"")+">"+monthNamesShort[month]+"</option>"}}monthHtml+="</select>"}if(!showMonthAfterYear){html+=monthHtml+((secondary||changeMonth||changeYear)&&(!(changeMonth&&changeYear))?"&#xa0;":"")}if(secondary||!changeYear){html+='<span class="ui-datepicker-year">'+drawYear+"</span>"}else{var years=this._get(inst,"yearRange").split(":");var year=0;var endYear=0;if(years.length!=2){year=drawYear-10;endYear=drawYear+10}else{if(years[0].charAt(0)=="+"||years[0].charAt(0)=="-"){year=drawYear+parseInt(years[0],10);endYear=drawYear+parseInt(years[1],10)}else{year=parseInt(years[0],10);endYear=parseInt(years[1],10)}}year=(minDate?Math.max(year,minDate.getFullYear()):year);endYear=(maxDate?Math.min(endYear,maxDate.getFullYear()):endYear);html+='<select class="ui-datepicker-year" onchange="DP_jQuery.datepicker._selectMonthYear(\'#'+inst.id+"', this, 'Y');\" onclick=\"DP_jQuery.datepicker._clickMonthYear('#"+inst.id+"');\">";for(;year<=endYear;year++){html+='<option value="'+year+'"'+(year==drawYear?' selected="selected"':"")+">"+year+"</option>"}html+="</select>"}if(showMonthAfterYear){html+=(secondary||changeMonth||changeYear?"&#xa0;":"")+monthHtml}html+="</div>";return html},_adjustInstDate:function(inst,offset,period){var year=inst.drawYear+(period=="Y"?offset:0);var month=inst.drawMonth+(period=="M"?offset:0);var day=Math.min(inst.selectedDay,this._getDaysInMonth(year,month))+(period=="D"?offset:0);var date=this._daylightSavingAdjust(new Date(year,month,day));var minDate=this._getMinMaxDate(inst,"min",true);var maxDate=this._getMinMaxDate(inst,"max");date=(minDate&&date<minDate?minDate:date);date=(maxDate&&date>maxDate?maxDate:date);inst.selectedDay=date.getDate();inst.drawMonth=inst.selectedMonth=date.getMonth();inst.drawYear=inst.selectedYear=date.getFullYear();if(period=="M"||period=="Y"){this._notifyChange(inst)}},_notifyChange:function(inst){var onChange=this._get(inst,"onChangeMonthYear");if(onChange){onChange.apply((inst.input?inst.input[0]:null),[inst.selectedYear,inst.selectedMonth+1,inst])}},_getNumberOfMonths:function(inst){var numMonths=this._get(inst,"numberOfMonths");return(numMonths==null?[1,1]:(typeof numMonths=="number"?[1,numMonths]:numMonths))},_getMinMaxDate:function(inst,minMax,checkRange){var date=this._determineDate(this._get(inst,minMax+"Date"),null);return(!checkRange||!inst.rangeStart?date:(!date||inst.rangeStart>date?inst.rangeStart:date))},_getDaysInMonth:function(year,month){return 32-new Date(year,month,32).getDate()},_getFirstDayOfMonth:function(year,month){return new Date(year,month,1).getDay()},_canAdjustMonth:function(inst,offset,curYear,curMonth){var numMonths=this._getNumberOfMonths(inst);var date=this._daylightSavingAdjust(new Date(curYear,curMonth+(offset<0?offset:numMonths[1]),1));if(offset<0){date.setDate(this._getDaysInMonth(date.getFullYear(),date.getMonth()))}return this._isInRange(inst,date)},_isInRange:function(inst,date){var newMinDate=(!inst.rangeStart?null:this._daylightSavingAdjust(new Date(inst.selectedYear,inst.selectedMonth,inst.selectedDay)));newMinDate=(newMinDate&&inst.rangeStart<newMinDate?inst.rangeStart:newMinDate);var minDate=newMinDate||this._getMinMaxDate(inst,"min");var maxDate=this._getMinMaxDate(inst,"max");return((!minDate||date>=minDate)&&(!maxDate||date<=maxDate))},_getFormatConfig:function(inst){var shortYearCutoff=this._get(inst,"shortYearCutoff");shortYearCutoff=(typeof shortYearCutoff!="string"?shortYearCutoff:new Date().getFullYear()%100+parseInt(shortYearCutoff,10));return{shortYearCutoff:shortYearCutoff,dayNamesShort:this._get(inst,"dayNamesShort"),dayNames:this._get(inst,"dayNames"),monthNamesShort:this._get(inst,"monthNamesShort"),monthNames:this._get(inst,"monthNames")}},_formatDate:function(inst,day,month,year){if(!day){inst.currentDay=inst.selectedDay;inst.currentMonth=inst.selectedMonth;inst.currentYear=inst.selectedYear}var date=(day?(typeof day=="object"?day:this._daylightSavingAdjust(new Date(year,month,day))):this._daylightSavingAdjust(new Date(inst.currentYear,inst.currentMonth,inst.currentDay)));return this.formatDate(this._get(inst,"dateFormat"),date,this._getFormatConfig(inst))}});function extendRemove(target,props){$.extend(target,props);for(var name in props){if(props[name]==null||props[name]==undefined){target[name]=props[name]}}return target}function isArray(a){return(a&&(($.browser.safari&&typeof a=="object"&&a.length)||(a.constructor&&a.constructor.toString().match(/\Array\(\)/))))}$.fn.datepicker=function(options){if(!$.datepicker.initialized){$(document).mousedown($.datepicker._checkExternalClick).find("body").append($.datepicker.dpDiv);$.datepicker.initialized=true}var otherArgs=Array.prototype.slice.call(arguments,1);if(typeof options=="string"&&(options=="isDisabled"||options=="getDate")){return $.datepicker["_"+options+"Datepicker"].apply($.datepicker,[this[0]].concat(otherArgs))}if(options=="option"&&arguments.length==2&&typeof arguments[1]=="string"){return $.datepicker["_"+options+"Datepicker"].apply($.datepicker,[this[0]].concat(otherArgs))}return this.each(function(){typeof options=="string"?$.datepicker["_"+options+"Datepicker"].apply($.datepicker,[this].concat(otherArgs)):$.datepicker._attachDatepicker(this,options)})};$.datepicker=new Datepicker();$.datepicker.initialized=false;$.datepicker.uuid=new Date().getTime();$.datepicker.version="1.7.2";window.DP_jQuery=$})(jQuery);;
\ No newline at end of file
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/AdapterRegistry.js b/continuum-webapp/src/main/webapp/struts/dojo/AdapterRegistry.js
deleted file mode 100644
index 23b8589..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/AdapterRegistry.js
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
-	Copyright (c) 2004-2006, The Dojo Foundation
-	All Rights Reserved.
-
-	Licensed under the Academic Free License version 2.1 or above OR the
-	modified BSD license. For more information on Dojo licensing, see:
-
-		http://dojotoolkit.org/community/licensing.shtml
-*/
-
-dojo.provide("dojo.AdapterRegistry");
-dojo.require("dojo.lang.func");
-
-dojo.AdapterRegistry = function(/*boolean, optional*/returnWrappers){
-	// summary:
-	//		A registry to make contextual calling/searching easier.
-	// description:
-	//		Objects of this class keep list of arrays in the form [name, check,
-	//		wrap, directReturn] that are used to determine what the contextual
-	//		result of a set of checked arguments is. All check/wrap functions
-	//		in this registry should be of the same arity.
-	this.pairs = [];
-	this.returnWrappers = returnWrappers || false;
-}
-
-dojo.lang.extend(dojo.AdapterRegistry, {
-	register: function(	/*string*/ name, /*function*/ check, /*function*/ wrap, 
-						/*boolean, optional*/ directReturn, 
-						/*boolean, optional*/ override){
-		// summary: 
-		//		register a check function to determine if the wrap function or
-		//		object gets selected
-		// name: a way to identify this matcher.
-		// check:
-		//		a function that arguments are passed to from the adapter's
-		//		match() function.  The check function should return true if the
-		//		given arguments are appropriate for the wrap function.
-		// directReturn:
-		//		If directReturn is true, the value passed in for wrap will be
-		//		returned instead of being called. Alternately, the
-		//		AdapterRegistry can be set globally to "return not call" using
-		//		the returnWrappers property. Either way, this behavior allows
-		//		the registry to act as a "search" function instead of a
-		//		function interception library.
-		// override:
-		//		If override is given and true, the check function will be given
-		//		highest priority. Otherwise, it will be the lowest priority
-		//		adapter.
-
-		var type = (override) ? "unshift" : "push";
-		this.pairs[type]([name, check, wrap, directReturn]);
-	},
-
-	match: function(/* ... */){
-        // summary:
-		//		Find an adapter for the given arguments. If no suitable adapter
-		//		is found, throws an exception. match() accepts any number of
-		//		arguments, all of which are passed to all matching functions
-		//		from the registered pairs.
-		for(var i = 0; i < this.pairs.length; i++){
-			var pair = this.pairs[i];
-			if(pair[1].apply(this, arguments)){
-				if((pair[3])||(this.returnWrappers)){
-					return pair[2];
-				}else{
-					return pair[2].apply(this, arguments);
-				}
-			}
-		}
-		throw new Error("No match found");
-		// dojo.raise("No match found");
-	},
-
-	unregister: function(name){
-		// summary: Remove a named adapter from the registry
-
-		// FIXME: this is kind of a dumb way to handle this. On a large
-		// registry this will be slow-ish and we can use the name as a lookup
-		// should we choose to trade memory for speed.
-		for(var i = 0; i < this.pairs.length; i++){
-			var pair = this.pairs[i];
-			if(pair[0] == name){
-				this.pairs.splice(i, 1);
-				return true;
-			}
-		}
-		return false;
-	}
-});
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/debug.js b/continuum-webapp/src/main/webapp/struts/dojo/debug.js
deleted file mode 100644
index d68706e..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/debug.js
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
-	Copyright (c) 2004-2006, The Dojo Foundation
-	All Rights Reserved.
-
-	Licensed under the Academic Free License version 2.1 or above OR the
-	modified BSD license. For more information on Dojo licensing, see:
-
-		http://dojotoolkit.org/community/licensing.shtml
-*/
-
-dojo.debug = function(/*...*/){
-	// summary:
-	//		Produce a line of debug output. Does nothing unless
-	//		djConfig.isDebug is true. Accepts any nubmer of args, joined with
-	//		'' to produce a single line of debugging output.  Caller should not
-	//		supply a trailing "\n".
-	if (!djConfig.isDebug) { return; }
-	var args = arguments;
-	if(dj_undef("println", dojo.hostenv)){
-		dojo.raise("dojo.debug not available (yet?)");
-	}
-	var isJUM = dj_global["jum"] && !dj_global["jum"].isBrowser;
-	var s = [(isJUM ? "": "DEBUG: ")];
-	for(var i=0;i<args.length;++i){
-		if(!false && args[i] && args[i] instanceof Error){
-			var msg = "[" + args[i].name + ": " + dojo.errorToString(args[i]) +
-				(args[i].fileName ? ", file: " + args[i].fileName : "") +
-				(args[i].lineNumber ? ", line: " + args[i].lineNumber : "") + "]";
-		} else {
-			try {
-				var msg = String(args[i]);
-			} catch(e) {
-				if(dojo.render.html.ie) {
-					var msg = "[ActiveXObject]";
-				} else {
-					var msg = "[unknown]";
-				}
-			}
-		}
-		s.push(msg);
-	}
-	
-	dojo.hostenv.println(s.join(" "));
-}
-
-/**
- * this is really hacky for now - just 
- * display the properties of the object
-**/
-
-dojo.debugShallow = function(/*Object*/obj){
-	// summary:
-	//		outputs a "name: value" style listing of all enumerable properties
-	//		in obj. Does nothing if djConfig.isDebug == false.
-	// obj: the object to be enumerated
-	if (!djConfig.isDebug) { return; }
-	dojo.debug('------------------------------------------------------------');
-	dojo.debug('Object: '+obj);
-	var props = [];
-	for(var prop in obj){
-		try {
-			props.push(prop + ': ' + obj[prop]);
-		} catch(E) {
-			props.push(prop + ': ERROR - ' + E.message);
-		}
-	}
-	props.sort();
-	for(var i = 0; i < props.length; i++) {
-		dojo.debug(props[i]);
-	}
-	dojo.debug('------------------------------------------------------------');
-}
-
-dojo.debugDeep = function(/*Object*/obj){
-	// summary:
-	//		provides an "object explorer" view of the passed obj in a popup
-	//		window.
-	// obj: the object to be examined
-	if (!djConfig.isDebug) { return; }
-	if (!dojo.uri || !dojo.uri.dojoUri){ return dojo.debug("You'll need to load dojo.uri.* for deep debugging - sorry!"); }
-	if (!window.open){ return dojo.debug('Deep debugging is only supported in host environments with window.open'); }
-	var idx = dojo.debugDeep.debugVars.length;
-	dojo.debugDeep.debugVars.push(obj);
-	// dojo.undo.browser back and forward breaks relpaths
-	var url = new dojo.uri.Uri(location, dojo.uri.dojoUri("src/debug/deep.html?var="+idx)).toString();
-	var win = window.open(url, '_blank', 'width=600, height=400, resizable=yes, scrollbars=yes, status=yes');
-	try{
-		win.debugVar = obj;
-	}catch(e){}
-}
-dojo.debugDeep.debugVars = [];
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/debug/Firebug.js b/continuum-webapp/src/main/webapp/struts/dojo/debug/Firebug.js
deleted file mode 100644
index c90e51d..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/debug/Firebug.js
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
-	Copyright (c) 2004-2006, The Dojo Foundation
-	All Rights Reserved.
-
-	Licensed under the Academic Free License version 2.1 or above OR the
-	modified BSD license. For more information on Dojo licensing, see:
-
-		http://dojotoolkit.org/community/licensing.shtml
-*/
-
-dojo.provide("dojo.debug.Firebug");
-dojo.deprecated("dojo.debug.Firebug is slated for removal in 0.5; use dojo.debug.console instead.", "0.5");
-
-// summary
-// Firebug Console logger.
-// This package redirects the normal dojo debugging output to the firebug console.  It does
-// so by sending the entire object to the console, rather than just overriding dojo.hostenv.println
-// so that firebugs object inspector can be taken advantage of.
-
-if (dojo.render.html.moz) {
-	if (console && console.log) {
-		var consoleLog = function() {
-			if (!djConfig.isDebug) { return ; }
-
-			var args = dojo.lang.toArray(arguments);
-			args.splice(0,0, "DEBUG: ");
-			console.log.apply(console, args);
-		}
-
-		dojo.debug = consoleLog;
-
-		dojo.debugDeep=consoleLog;
-
-		dojo.debugShallow=function(obj) {
-			if (!djConfig.isDebug) { return; }
-
-			if (dojo.lang.isArray(obj)) {
-				console.log('Array: ', obj);
-				for (var i=0; x<obj.length; i++) {
-					console.log('    ', '['+i+']', obj[i]);
-				}
-			} else {
-				console.log('Object: ', obj);
-				var propNames = [];
-				for (var prop in obj) {
-					propNames.push(prop);
-				}
-				propNames.sort();
-				dojo.lang.forEach(propNames, function(prop) {
-					try {
-						console.log('    ', prop, obj[prop]);
-					} catch(e) {
-						console.log('    ', prop, 'ERROR', e.message, e);
-					}
-				});
-			}
-		}
-
-	} else {
-		dojo.debug("dojo.debug.Firebug requires Firebug > 0.4");
-	}
-}
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/debug/arrow_hide.gif b/continuum-webapp/src/main/webapp/struts/dojo/debug/arrow_hide.gif
deleted file mode 100644
index 8bd6b34..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/debug/arrow_hide.gif
+++ /dev/null
Binary files differ
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/debug/arrow_show.gif b/continuum-webapp/src/main/webapp/struts/dojo/debug/arrow_show.gif
deleted file mode 100644
index 4246b50..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/debug/arrow_show.gif
+++ /dev/null
Binary files differ
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/debug/console.js b/continuum-webapp/src/main/webapp/struts/dojo/debug/console.js
deleted file mode 100644
index 99bf32b..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/debug/console.js
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
-	Copyright (c) 2004-2006, The Dojo Foundation
-	All Rights Reserved.
-
-	Licensed under the Academic Free License version 2.1 or above OR the
-	modified BSD license. For more information on Dojo licensing, see:
-
-		http://dojotoolkit.org/community/licensing.shtml
-*/
-
-dojo.provide("dojo.debug.console");
-dojo.require("dojo.logging.ConsoleLogger");
-
-// summary:
-// 	Console logger, for use with FireFox Firebug, Safari and Opera's consoles.
-// description:
-//  This package redirects the normal dojo debugging output to the console log in modern browsers.
-//  When using Firebug, it does this  by sending the entire object to the console, 
-//	rather than just overriding dojo.hostenv.println, so that Firebug's interactive 
-//	object inspector is available.
-// see: http://www.joehewitt.com/software/firebug/docs.php
-
-if (window.console) {
-	if (console.info != null) {
-		// using a later version of Firebug -- lots of fun stuff!
-		
-		dojo.hostenv.println = function() {
-			// summary: Write all of the arguments to the Firebug console
-			// description: Uses console.info() so that the (i) icon prints next to the debug line
-			//	rather than munging the arguments by adding "DEBUG:" in front of them.
-			//	This allows us to use Firebug's string handling to do interesting things
-			if (!djConfig.isDebug)	{	 return;	}
-			console.info.apply(console, arguments);
-		}
-		dojo.debug=dojo.hostenv.println;
-		dojo.debugDeep = dojo.debug;
-
-		dojo.debugShallow = function(/*Object*/ obj, /*Boolean?*/showMethods, /*Boolean?*/sort) {
-			// summary:  Write first-level properties of obj to the console.
-			//	obj:			Object or Array to debug
-			//	showMethods:	Pass false to skip outputing methods of object, any other value will output them.
-			//	sort:			Pass false to skip sorting properties, any other value will sort.
-			if (!djConfig.isDebug) { return; }
-
-			showMethods = (showMethods != false);
-			sort = (sort != false);
-
-			// handle null or something without a constructor (in which case we don't know the type)
-			if (obj == null || obj.constructor == null) {
-				return dojo.debug(obj);
-			}
-	
-			// figure out type via a standard constructor (Object, String, Date, etc)
-			var type = obj.declaredClass;
-			if (type == null) {
-				type = obj.constructor.toString().match(/function\s*(.*)\(/);
-				if (type) {	type = type[1]	};
-			}
-			// if we got a viable type, use Firebug's interactive property dump feature
-			if (type) {
-				if (type == "String" || type == "Number") {
-					return dojo.debug(type+": ", obj);
-				}
-				if (showMethods && !sort) {
-					var sortedObj = obj;
-				} else {
-					var propNames = [];
-					if (showMethods) {
-						for (var prop in obj) {	
-							propNames.push(prop);
-						}
-					} else {
-						for (var prop in obj) {	
-							if (typeof obj[prop] != "function") { propNames.push(prop);	}
-							else dojo.debug(prop);
-						}					
-					}
-					if (sort) propNames.sort();
-					var sortedObj = {};
-					dojo.lang.forEach(propNames, function(prop) {
-						sortedObj[prop] = obj[prop];
-					});
-				}
-
-				return dojo.debug(type+": %o\n%2.o",obj,sortedObj);
-			}
-		
-			// otherwise just output the constructor + object, 
-			//	which is nice for a DOM element, etc
-			return dojo.debug(obj.constructor + ": ", obj);
-		}
-		
-	} else if (console.log != null) {
-		// using Safari or an old version of Firebug
-		dojo.hostenv.println=function() {
-			if (!djConfig.isDebug) { return ; }
-			// make sure we're only writing a single string to Safari's console
-			var args = dojo.lang.toArray(arguments);
-			console.log("DEBUG: " + args.join(" "));
-		}
-		dojo.debug=dojo.hostenv.println;
-	} else {
-		// not supported
-		dojo.debug("dojo.debug.console requires Firebug > 0.4");
-	}
-} else if (dojo.render.html.opera) {
-	// using Opera 8.0 or later
-	if (opera && opera.postError) {
-		dojo.hostenv.println=opera.postError;
-		// summary:  hook debugging up to Opera's postError routine
-	} else {
-		dojo.debug("dojo.debug.Opera requires Opera > 8.0");
-	}
-}
-
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/debug/deep.html b/continuum-webapp/src/main/webapp/struts/dojo/debug/deep.html
deleted file mode 100644
index 1a22fbf..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/debug/deep.html
+++ /dev/null
@@ -1,362 +0,0 @@
-<html>
-<head>
-<title>Deep Debugger</title>
-<script>
-
-var tableRows = {};
-var tableCels = {};
-var tableObjs = {};
-var tablesBuilt = {};
-var tableShows = {};
-var tableHides = {};
-
-// IE: nodes w/id need to be redeclared or getElementById is b0rked
-var frame = null;
-
-window.onload = function(){
-	// if IE loads this page too quickly (instantly) then 
-	// window.debugVar might not have been set
-	window.setTimeout(startMeUp, 100);
-}
-
-function startMeUp(){
-	frame = document.getElementById('frame');
-	// GET string 
-	var index = location.search.split("=").pop();
-	var debugObj = window.opener.dojo.debugDeep;
-	var debugVar = debugObj.debugVars[index] || window.debugVar;
-	buildTable('root', frame, debugVar);
-}
-
-function buildTable(path, parent, obj){
-	var keys = [];
-	var vals = [];
-	for(var prop in obj){
-		keys.push(prop);
-		try {
-			vals[prop] = obj[prop];
-		} catch(E) {
-			vals[prop] = 'ERROR: ' + E.message;
-		}
-	}
-	keys.sort(keySorter);
-
-	if (!keys.length){
-
-		var div = document.createElement('div');
-		div.appendChild(document.createTextNode('Object has no properties.'));
-
-		parent.appendChild(div);
-		return;
-	}
-
-
-	var t = document.createElement('table');
-	t.border = "1";
-
-	var tb = document.createElement('tbody');
-	t.appendChild(tb);
-
-
-	for(var i = 0; i < keys.length; i++) {
-		buildTableRow(path+'-'+keys[i], tb, keys[i], vals[keys[i]]);
-	}
-
-	if (path == 'root'){
-		//t.style.width = '90%';
-	}
-	t.style.width = '100%';
-
-	parent.appendChild(t);
-
-	tablesBuilt[path] = true;
-}
-
-function buildTableRow(path, tb, name, value) {
-
-	var simpleType = typeof(value);
-	var createSubrow = (simpleType == 'object');
-	var complexType = simpleType;
-
-	if (simpleType == 'object'){
-		var cls = getConstructorClass(value);
-		if (cls){
-			if (cls == 'Object'){
-			}else if (cls == 'Array'){
-				complexType = 'array';
-			}else{
-				complexType += ' ('+cls+')';
-			}
-		}
-	}
-
-/*var tr1 = document.createElement('tr');
-	var td1 = document.createElement('td');
-	var td2 = document.createElement('td');
-	var td3 = document.createElement('td');
-	var td4 = document.createElement('td');*/
-
-	var row = tb.rows.length;
-	var tr1 = tb.insertRow(row++);
-	var td1 = tr1.insertCell(0);
-	var td2 = tr1.insertCell(1);
-	var td3 = tr1.insertCell(2);
-	var td4 = tr1.insertCell(3);
-	
-	tr1.style.verticalAlign = 'top';
-	td1.style.verticalAlign = 'middle';
-
-	td1.className = 'propPlus';
-	td2.className = 'propName';
-	td3.className = 'propType';
-	td4.className = 'propVal';
-
-	//tr1.appendChild(td1);
-	//tr1.appendChild(td2);
-	//tr1.appendChild(td3);
-	//tr1.appendChild(td4);
-
-	if (createSubrow){
-		var img1 = document.createElement('img');
-		img1.width = 9;
-		img1.height = 9;
-		img1.src = 'arrow_show.gif';
-		var a1 = document.createElement('a');
-		a1.appendChild(img1);
-		a1.href = '#';
-		a1.onclick = function(){ showTableRow(path); return false; };
-
-		var img2 = document.createElement('img');
-		img2.width = 9;
-		img2.height = 9;
-		img2.src = 'arrow_hide.gif';
-		var a2 = document.createElement('a');
-		a2.appendChild(img2);
-		a2.href = '#';
-		a2.onclick = function(){ hideTableRow(path); return false; };
-		a2.style.display = 'none';
-
-		tableShows[path] = a1;
-		tableHides[path] = a2;
-
-		td1.appendChild(a1);
-		td1.appendChild(a2);
-	}else{
-		var img = document.createElement('img');
-		img.width = 9;
-		img.height = 9;
-		img.src = 'spacer.gif';
-
-		td1.appendChild(img);
-	}
-
-	td2.appendChild(document.createTextNode(name));
-	td3.appendChild(document.createTextNode(complexType));
-	td4.appendChild(buildPreBlock(value));
-
-	//tb.appendChild(tr1);
-
-	if (createSubrow){
-		var tr2 = tb.insertRow(row++);
-		var td5 = tr2.insertCell(0);
-		var td6 = tr2.insertCell(1);
-		
-		//var tr2 = document.createElement('tr');
-		//var td5 = document.createElement('td');
-		//var td6 = document.createElement('td');
-
-		td5.innerHTML = '&nbsp;';
-		//td6.innerHTML = '&nbsp;';
-
-		td6.colSpan = '3';
-
-		tr2.appendChild(td5);
-		tr2.appendChild(td6);
-
-		tr2.style.display = 'none';
-
-		tb.appendChild(tr2);
-
-		tableRows[path] = tr2;
-		tableCels[path] = td6;
-		tableObjs[path] = value;
-	}
-}
-
-function showTableRow(path){
-
-	var tr = tableRows[path];
-	var td = tableCels[path];
-	var a1 = tableShows[path];
-	var a2 = tableHides[path];
-
-	if (!tablesBuilt[path]){
-
-		//alert('building table for '+path);
-		buildTable(path, td, tableObjs[path]);
-	}
-
-	tr.style.display = 'table-row';
-
-	a1.style.display = 'none';
-	a2.style.display = 'inline';
-}
-
-function hideTableRow(path){
-
-	var tr = tableRows[path];
-	var a1 = tableShows[path];
-	var a2 = tableHides[path];
-
-	tr.style.display = 'none';
-
-	a1.style.display = 'inline';
-	a2.style.display = 'none';
-}
-
-function buildPreBlock(value){
-
-	//
-	// how many lines ?
-	//
-
-	var s = ''+value;
-	s = s.replace("\r\n", "\n");
-	s = s.replace("\r", "");
-	var lines = s.split("\n");
-
-
-	if (lines.length < 2){
-
-		if (lines[0].length < 60){
-
-			var pre = document.createElement('pre');
-			pre.appendChild(document.createTextNode(s));
-			return pre;
-		}
-	}
-
-
-	//
-	// multiple lines :(
-	//
-
-	var preview = lines[0].substr(0, 60) + ' ...';
-
-	var pre1 = document.createElement('pre');
-	pre1.appendChild(document.createTextNode(preview));
-	pre1.className = 'clicky';
-
-	var pre2 = document.createElement('pre');
-	pre2.appendChild(document.createTextNode(s));
-	pre2.style.display = 'none';
-	pre2.className = 'clicky';
-
-	pre1.onclick = function(){
-		pre1.style.display = 'none';
-		pre2.style.display = 'block';
-	}
-
-	pre2.onclick = function(){
-		pre1.style.display = 'block';
-		pre2.style.display = 'none';
-	}
-
-	var pre = document.createElement('div');
-
-	pre.appendChild(pre1);
-	pre.appendChild(pre2);
-
-	return pre;
-}
-
-function getConstructorClass(obj){
-
-	if (!obj.constructor || !obj.constructor.toString) return;
-
-	var m = obj.constructor.toString().match(/function\s*(\w+)/);
-
-	if (m && m.length == 2) return m[1];
-
-	return null;
-}
-
-function keySorter(a, b){
-
-	if (a == parseInt(a) && b == parseInt(b)){
-
-		return (parseInt(a) > parseInt(b)) ? 1 : ((parseInt(a) < parseInt(b)) ? -1 : 0);
-	}
-
-	// sort by lowercase string
-
-	var a2 = String(a).toLowerCase();
-	var b2 = String(b).toLowerCase();
-
-	return (a2 > b2) ? 1 : ((a2 < b2) ? -1 : 0);
-}
-
-</script>
-<style>
-
-body {
-	font-family: arial, helvetica, sans-serif;
-}
-
-table {
-	border-width: 0px;
-	border-spacing: 1px;
-	border-collapse: separate;
-}
-
-td {
-	border-width: 0px;
-	padding: 2px;
-}
-
-img {
-	border: 0;
-}
-
-pre {
-	margin: 0;
-	padding: 0;
-	white-space: -moz-pre-wrap;  /* Mozilla, supported since 1999 */
-	white-space: -pre-wrap;      /* Opera 4 - 6 */
-	white-space: -o-pre-wrap;    /* Opera 7 */
-	white-space: pre-wrap;       /* CSS3 - Text module (Candidate Recommendation) http://www.w3.org/TR/css3-text/#white-space */
-	word-wrap: break-word;       /* IE 5.5+ */
-}
-
-pre.clicky {
-	cursor: hand;
-	cursor: pointer;
-}
-
-td.propPlus {
-	width: 9px;
-	background-color: #ddd;
-}
-
-td.propName {
-	background-color: #ddd;
-}
-
-td.propType {
-	background-color: #ddd;
-}
-
-td.propVal {
-	background-color: #ddd;
-}
-
-</style>
-</head>
-<body>
-
-<h2>Javascript Object Browser</h2>
-
-<div id="frame"></div>
-
-</body>
-</html>
\ No newline at end of file
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/debug/spacer.gif b/continuum-webapp/src/main/webapp/struts/dojo/debug/spacer.gif
deleted file mode 100644
index 2ce50b5..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/debug/spacer.gif
+++ /dev/null
Binary files differ
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/dojo.js b/continuum-webapp/src/main/webapp/struts/dojo/dojo.js
deleted file mode 100644
index ec38b8c..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/dojo.js
+++ /dev/null
@@ -1,11190 +0,0 @@
-/*
-	Copyright (c) 2004-2006, The Dojo Foundation
-	All Rights Reserved.
-
-	Licensed under the Academic Free License version 2.1 or above OR the
-	modified BSD license. For more information on Dojo licensing, see:
-
-		http://dojotoolkit.org/community/licensing.shtml
-*/
-
-/*
-	This is a compiled version of Dojo, built for deployment and not for
-	development. To get an editable version, please visit:
-
-		http://dojotoolkit.org
-
-	for documentation and information on getting the source.
-*/
-
-if(typeof dojo=="undefined"){
-var dj_global=this;
-var dj_currentContext=this;
-function dj_undef(_1,_2){
-return (typeof (_2||dj_currentContext)[_1]=="undefined");
-}
-if(dj_undef("djConfig",this)){
-var djConfig={};
-}
-if(dj_undef("dojo",this)){
-var dojo={};
-}
-dojo.global=function(){
-return dj_currentContext;
-};
-dojo.locale=djConfig.locale;
-dojo.version={major:0,minor:4,patch:0,flag:"",revision:Number("$Rev$".match(/[0-9]+/)[0]),toString:function(){
-with(dojo.version){
-return major+"."+minor+"."+patch+flag+" ("+revision+")";
-}
-}};
-dojo.evalProp=function(_3,_4,_5){
-if((!_4)||(!_3)){
-return undefined;
-}
-if(!dj_undef(_3,_4)){
-return _4[_3];
-}
-return (_5?(_4[_3]={}):undefined);
-};
-dojo.parseObjPath=function(_6,_7,_8){
-var _9=(_7||dojo.global());
-var _a=_6.split(".");
-var _b=_a.pop();
-for(var i=0,l=_a.length;i<l&&_9;i++){
-_9=dojo.evalProp(_a[i],_9,_8);
-}
-return {obj:_9,prop:_b};
-};
-dojo.evalObjPath=function(_e,_f){
-if(typeof _e!="string"){
-return dojo.global();
-}
-if(_e.indexOf(".")==-1){
-return dojo.evalProp(_e,dojo.global(),_f);
-}
-var ref=dojo.parseObjPath(_e,dojo.global(),_f);
-if(ref){
-return dojo.evalProp(ref.prop,ref.obj,_f);
-}
-return null;
-};
-dojo.errorToString=function(_11){
-if(!dj_undef("message",_11)){
-return _11.message;
-}else{
-if(!dj_undef("description",_11)){
-return _11.description;
-}else{
-return _11;
-}
-}
-};
-dojo.raise=function(_12,_13){
-if(_13){
-_12=_12+": "+dojo.errorToString(_13);
-}
-try{
-if(djConfig.isDebug){
-dojo.hostenv.println("FATAL exception raised: "+_12);
-}
-}
-catch(e){
-}
-throw _13||Error(_12);
-};
-dojo.debug=function(){
-};
-dojo.debugShallow=function(obj){
-};
-dojo.profile={start:function(){
-},end:function(){
-},stop:function(){
-},dump:function(){
-}};
-function dj_eval(_15){
-return dj_global.eval?dj_global.eval(_15):eval(_15);
-}
-dojo.unimplemented=function(_16,_17){
-var _18="'"+_16+"' not implemented";
-if(_17!=null){
-_18+=" "+_17;
-}
-dojo.raise(_18);
-};
-dojo.deprecated=function(_19,_1a,_1b){
-var _1c="DEPRECATED: "+_19;
-if(_1a){
-_1c+=" "+_1a;
-}
-if(_1b){
-_1c+=" -- will be removed in version: "+_1b;
-}
-dojo.debug(_1c);
-};
-dojo.render=(function(){
-function vscaffold(_1d,_1e){
-var tmp={capable:false,support:{builtin:false,plugin:false},prefixes:_1d};
-for(var i=0;i<_1e.length;i++){
-tmp[_1e[i]]=false;
-}
-return tmp;
-}
-return {name:"",ver:dojo.version,os:{win:false,linux:false,osx:false},html:vscaffold(["html"],["ie","opera","khtml","safari","moz"]),svg:vscaffold(["svg"],["corel","adobe","batik"]),vml:vscaffold(["vml"],["ie"]),swf:vscaffold(["Swf","Flash","Mm"],["mm"]),swt:vscaffold(["Swt"],["ibm"])};
-})();
-dojo.hostenv=(function(){
-var _21={isDebug:false,allowQueryConfig:false,baseScriptUri:"",baseRelativePath:"",libraryScriptUri:"",iePreventClobber:false,ieClobberMinimal:true,preventBackButtonFix:true,delayMozLoadingFix:false,searchIds:[],parseWidgets:true};
-if(typeof djConfig=="undefined"){
-djConfig=_21;
-}else{
-for(var _22 in _21){
-if(typeof djConfig[_22]=="undefined"){
-djConfig[_22]=_21[_22];
-}
-}
-}
-return {name_:"(unset)",version_:"(unset)",getName:function(){
-return this.name_;
-},getVersion:function(){
-return this.version_;
-},getText:function(uri){
-dojo.unimplemented("getText","uri="+uri);
-}};
-})();
-dojo.hostenv.getBaseScriptUri=function(){
-if(djConfig.baseScriptUri.length){
-return djConfig.baseScriptUri;
-}
-var uri=new String(djConfig.libraryScriptUri||djConfig.baseRelativePath);
-if(!uri){
-dojo.raise("Nothing returned by getLibraryScriptUri(): "+uri);
-}
-var _25=uri.lastIndexOf("/");
-djConfig.baseScriptUri=djConfig.baseRelativePath;
-return djConfig.baseScriptUri;
-};
-(function(){
-var _26={pkgFileName:"__package__",loading_modules_:{},loaded_modules_:{},addedToLoadingCount:[],removedFromLoadingCount:[],inFlightCount:0,modulePrefixes_:{dojo:{name:"dojo",value:"src"}},setModulePrefix:function(_27,_28){
-this.modulePrefixes_[_27]={name:_27,value:_28};
-},moduleHasPrefix:function(_29){
-var mp=this.modulePrefixes_;
-return Boolean(mp[_29]&&mp[_29].value);
-},getModulePrefix:function(_2b){
-if(this.moduleHasPrefix(_2b)){
-return this.modulePrefixes_[_2b].value;
-}
-return _2b;
-},getTextStack:[],loadUriStack:[],loadedUris:[],post_load_:false,modulesLoadedListeners:[],unloadListeners:[],loadNotifying:false};
-for(var _2c in _26){
-dojo.hostenv[_2c]=_26[_2c];
-}
-})();
-dojo.hostenv.loadPath=function(_2d,_2e,cb){
-var uri;
-if(_2d.charAt(0)=="/"||_2d.match(/^\w+:/)){
-uri=_2d;
-}else{
-uri=this.getBaseScriptUri()+_2d;
-}
-if(djConfig.cacheBust&&dojo.render.html.capable){
-uri+="?"+String(djConfig.cacheBust).replace(/\W+/g,"");
-}
-try{
-return !_2e?this.loadUri(uri,cb):this.loadUriAndCheck(uri,_2e,cb);
-}
-catch(e){
-dojo.debug(e);
-return false;
-}
-};
-dojo.hostenv.loadUri=function(uri,cb){
-if(this.loadedUris[uri]){
-return true;
-}
-var _33=this.getText(uri,null,true);
-if(!_33){
-return false;
-}
-this.loadedUris[uri]=true;
-if(cb){
-_33="("+_33+")";
-}
-var _34=dj_eval(_33);
-if(cb){
-cb(_34);
-}
-return true;
-};
-dojo.hostenv.loadUriAndCheck=function(uri,_36,cb){
-var ok=true;
-try{
-ok=this.loadUri(uri,cb);
-}
-catch(e){
-dojo.debug("failed loading ",uri," with error: ",e);
-}
-return Boolean(ok&&this.findModule(_36,false));
-};
-dojo.loaded=function(){
-};
-dojo.unloaded=function(){
-};
-dojo.hostenv.loaded=function(){
-this.loadNotifying=true;
-this.post_load_=true;
-var mll=this.modulesLoadedListeners;
-for(var x=0;x<mll.length;x++){
-mll[x]();
-}
-this.modulesLoadedListeners=[];
-this.loadNotifying=false;
-dojo.loaded();
-};
-dojo.hostenv.unloaded=function(){
-var mll=this.unloadListeners;
-while(mll.length){
-(mll.pop())();
-}
-dojo.unloaded();
-};
-dojo.addOnLoad=function(obj,_3d){
-var dh=dojo.hostenv;
-if(arguments.length==1){
-dh.modulesLoadedListeners.push(obj);
-}else{
-if(arguments.length>1){
-dh.modulesLoadedListeners.push(function(){
-obj[_3d]();
-});
-}
-}
-if(dh.post_load_&&dh.inFlightCount==0&&!dh.loadNotifying){
-dh.callLoaded();
-}
-};
-dojo.addOnUnload=function(obj,_40){
-var dh=dojo.hostenv;
-if(arguments.length==1){
-dh.unloadListeners.push(obj);
-}else{
-if(arguments.length>1){
-dh.unloadListeners.push(function(){
-obj[_40]();
-});
-}
-}
-};
-dojo.hostenv.modulesLoaded=function(){
-if(this.post_load_){
-return;
-}
-if(this.loadUriStack.length==0&&this.getTextStack.length==0){
-if(this.inFlightCount>0){
-dojo.debug("files still in flight!");
-return;
-}
-dojo.hostenv.callLoaded();
-}
-};
-dojo.hostenv.callLoaded=function(){
-if(typeof setTimeout=="object"){
-setTimeout("dojo.hostenv.loaded();",0);
-}else{
-dojo.hostenv.loaded();
-}
-};
-dojo.hostenv.getModuleSymbols=function(_42){
-var _43=_42.split(".");
-for(var i=_43.length;i>0;i--){
-var _45=_43.slice(0,i).join(".");
-if((i==1)&&!this.moduleHasPrefix(_45)){
-_43[0]="../"+_43[0];
-}else{
-var _46=this.getModulePrefix(_45);
-if(_46!=_45){
-_43.splice(0,i,_46);
-break;
-}
-}
-}
-return _43;
-};
-dojo.hostenv._global_omit_module_check=false;
-dojo.hostenv.loadModule=function(_47,_48,_49){
-if(!_47){
-return;
-}
-_49=this._global_omit_module_check||_49;
-var _4a=this.findModule(_47,false);
-if(_4a){
-return _4a;
-}
-if(dj_undef(_47,this.loading_modules_)){
-this.addedToLoadingCount.push(_47);
-}
-this.loading_modules_[_47]=1;
-var _4b=_47.replace(/\./g,"/")+".js";
-var _4c=_47.split(".");
-var _4d=this.getModuleSymbols(_47);
-var _4e=((_4d[0].charAt(0)!="/")&&!_4d[0].match(/^\w+:/));
-var _4f=_4d[_4d.length-1];
-var ok;
-if(_4f=="*"){
-_47=_4c.slice(0,-1).join(".");
-while(_4d.length){
-_4d.pop();
-_4d.push(this.pkgFileName);
-_4b=_4d.join("/")+".js";
-if(_4e&&_4b.charAt(0)=="/"){
-_4b=_4b.slice(1);
-}
-ok=this.loadPath(_4b,!_49?_47:null);
-if(ok){
-break;
-}
-_4d.pop();
-}
-}else{
-_4b=_4d.join("/")+".js";
-_47=_4c.join(".");
-var _51=!_49?_47:null;
-ok=this.loadPath(_4b,_51);
-if(!ok&&!_48){
-_4d.pop();
-while(_4d.length){
-_4b=_4d.join("/")+".js";
-ok=this.loadPath(_4b,_51);
-if(ok){
-break;
-}
-_4d.pop();
-_4b=_4d.join("/")+"/"+this.pkgFileName+".js";
-if(_4e&&_4b.charAt(0)=="/"){
-_4b=_4b.slice(1);
-}
-ok=this.loadPath(_4b,_51);
-if(ok){
-break;
-}
-}
-}
-if(!ok&&!_49){
-dojo.raise("Could not load '"+_47+"'; last tried '"+_4b+"'");
-}
-}
-if(!_49&&!this["isXDomain"]){
-_4a=this.findModule(_47,false);
-if(!_4a){
-dojo.raise("symbol '"+_47+"' is not defined after loading '"+_4b+"'");
-}
-}
-return _4a;
-};
-dojo.hostenv.startPackage=function(_52){
-var _53=String(_52);
-var _54=_53;
-var _55=_52.split(/\./);
-if(_55[_55.length-1]=="*"){
-_55.pop();
-_54=_55.join(".");
-}
-var _56=dojo.evalObjPath(_54,true);
-this.loaded_modules_[_53]=_56;
-this.loaded_modules_[_54]=_56;
-return _56;
-};
-dojo.hostenv.findModule=function(_57,_58){
-var lmn=String(_57);
-if(this.loaded_modules_[lmn]){
-return this.loaded_modules_[lmn];
-}
-if(_58){
-dojo.raise("no loaded module named '"+_57+"'");
-}
-return null;
-};
-dojo.kwCompoundRequire=function(_5a){
-var _5b=_5a["common"]||[];
-var _5c=_5a[dojo.hostenv.name_]?_5b.concat(_5a[dojo.hostenv.name_]||[]):_5b.concat(_5a["default"]||[]);
-for(var x=0;x<_5c.length;x++){
-var _5e=_5c[x];
-if(_5e.constructor==Array){
-dojo.hostenv.loadModule.apply(dojo.hostenv,_5e);
-}else{
-dojo.hostenv.loadModule(_5e);
-}
-}
-};
-dojo.require=function(_5f){
-dojo.hostenv.loadModule.apply(dojo.hostenv,arguments);
-};
-dojo.requireIf=function(_60,_61){
-var _62=arguments[0];
-if((_62===true)||(_62=="common")||(_62&&dojo.render[_62].capable)){
-var _63=[];
-for(var i=1;i<arguments.length;i++){
-_63.push(arguments[i]);
-}
-dojo.require.apply(dojo,_63);
-}
-};
-dojo.requireAfterIf=dojo.requireIf;
-dojo.provide=function(_65){
-return dojo.hostenv.startPackage.apply(dojo.hostenv,arguments);
-};
-dojo.registerModulePath=function(_66,_67){
-return dojo.hostenv.setModulePrefix(_66,_67);
-};
-dojo.setModulePrefix=function(_68,_69){
-dojo.deprecated("dojo.setModulePrefix(\""+_68+"\", \""+_69+"\")","replaced by dojo.registerModulePath","0.5");
-return dojo.registerModulePath(_68,_69);
-};
-dojo.exists=function(obj,_6b){
-var p=_6b.split(".");
-for(var i=0;i<p.length;i++){
-if(!obj[p[i]]){
-return false;
-}
-obj=obj[p[i]];
-}
-return true;
-};
-dojo.hostenv.normalizeLocale=function(_6e){
-return _6e?_6e.toLowerCase():dojo.locale;
-};
-dojo.hostenv.searchLocalePath=function(_6f,_70,_71){
-_6f=dojo.hostenv.normalizeLocale(_6f);
-var _72=_6f.split("-");
-var _73=[];
-for(var i=_72.length;i>0;i--){
-_73.push(_72.slice(0,i).join("-"));
-}
-_73.push(false);
-if(_70){
-_73.reverse();
-}
-for(var j=_73.length-1;j>=0;j--){
-var loc=_73[j]||"ROOT";
-var _77=_71(loc);
-if(_77){
-break;
-}
-}
-};
-dojo.hostenv.localesGenerated;
-dojo.hostenv.registerNlsPrefix=function(){
-dojo.registerModulePath("nls","nls");
-};
-dojo.hostenv.preloadLocalizations=function(){
-if(dojo.hostenv.localesGenerated){
-dojo.hostenv.registerNlsPrefix();
-function preload(_78){
-_78=dojo.hostenv.normalizeLocale(_78);
-dojo.hostenv.searchLocalePath(_78,true,function(loc){
-for(var i=0;i<dojo.hostenv.localesGenerated.length;i++){
-if(dojo.hostenv.localesGenerated[i]==loc){
-dojo["require"]("nls.dojo_"+loc);
-return true;
-}
-}
-return false;
-});
-}
-preload();
-var _7b=djConfig.extraLocale||[];
-for(var i=0;i<_7b.length;i++){
-preload(_7b[i]);
-}
-}
-dojo.hostenv.preloadLocalizations=function(){
-};
-};
-dojo.requireLocalization=function(_7d,_7e,_7f){
-dojo.hostenv.preloadLocalizations();
-var _80=[_7d,"nls",_7e].join(".");
-var _81=dojo.hostenv.findModule(_80);
-if(_81){
-if(djConfig.localizationComplete&&_81._built){
-return;
-}
-var _82=dojo.hostenv.normalizeLocale(_7f).replace("-","_");
-var _83=_80+"."+_82;
-if(dojo.hostenv.findModule(_83)){
-return;
-}
-}
-_81=dojo.hostenv.startPackage(_80);
-var _84=dojo.hostenv.getModuleSymbols(_7d);
-var _85=_84.concat("nls").join("/");
-var _86;
-dojo.hostenv.searchLocalePath(_7f,false,function(loc){
-var _88=loc.replace("-","_");
-var _89=_80+"."+_88;
-var _8a=false;
-if(!dojo.hostenv.findModule(_89)){
-dojo.hostenv.startPackage(_89);
-var _8b=[_85];
-if(loc!="ROOT"){
-_8b.push(loc);
-}
-_8b.push(_7e);
-var _8c=_8b.join("/")+".js";
-_8a=dojo.hostenv.loadPath(_8c,null,function(_8d){
-var _8e=function(){
-};
-_8e.prototype=_86;
-_81[_88]=new _8e();
-for(var j in _8d){
-_81[_88][j]=_8d[j];
-}
-});
-}else{
-_8a=true;
-}
-if(_8a&&_81[_88]){
-_86=_81[_88];
-}else{
-_81[_88]=_86;
-}
-});
-};
-(function(){
-var _90=djConfig.extraLocale;
-if(_90){
-if(!_90 instanceof Array){
-_90=[_90];
-}
-var req=dojo.requireLocalization;
-dojo.requireLocalization=function(m,b,_94){
-req(m,b,_94);
-if(_94){
-return;
-}
-for(var i=0;i<_90.length;i++){
-req(m,b,_90[i]);
-}
-};
-}
-})();
-}
-if(typeof window!="undefined"){
-(function(){
-if(djConfig.allowQueryConfig){
-var _96=document.location.toString();
-var _97=_96.split("?",2);
-if(_97.length>1){
-var _98=_97[1];
-var _99=_98.split("&");
-for(var x in _99){
-var sp=_99[x].split("=");
-if((sp[0].length>9)&&(sp[0].substr(0,9)=="djConfig.")){
-var opt=sp[0].substr(9);
-try{
-djConfig[opt]=eval(sp[1]);
-}
-catch(e){
-djConfig[opt]=sp[1];
-}
-}
-}
-}
-}
-if(((djConfig["baseScriptUri"]=="")||(djConfig["baseRelativePath"]==""))&&(document&&document.getElementsByTagName)){
-var _9d=document.getElementsByTagName("script");
-var _9e=/(__package__|dojo|bootstrap1)\.js([\?\.]|$)/i;
-for(var i=0;i<_9d.length;i++){
-var src=_9d[i].getAttribute("src");
-if(!src){
-continue;
-}
-var m=src.match(_9e);
-if(m){
-var _a2=src.substring(0,m.index);
-if(src.indexOf("bootstrap1")>-1){
-_a2+="../";
-}
-if(!this["djConfig"]){
-djConfig={};
-}
-if(djConfig["baseScriptUri"]==""){
-djConfig["baseScriptUri"]=_a2;
-}
-if(djConfig["baseRelativePath"]==""){
-djConfig["baseRelativePath"]=_a2;
-}
-break;
-}
-}
-}
-var dr=dojo.render;
-var drh=dojo.render.html;
-var drs=dojo.render.svg;
-var dua=(drh.UA=navigator.userAgent);
-var dav=(drh.AV=navigator.appVersion);
-var t=true;
-var f=false;
-drh.capable=t;
-drh.support.builtin=t;
-dr.ver=parseFloat(drh.AV);
-dr.os.mac=dav.indexOf("Macintosh")>=0;
-dr.os.win=dav.indexOf("Windows")>=0;
-dr.os.linux=dav.indexOf("X11")>=0;
-drh.opera=dua.indexOf("Opera")>=0;
-drh.khtml=(dav.indexOf("Konqueror")>=0)||(dav.indexOf("Safari")>=0);
-drh.safari=dav.indexOf("Safari")>=0;
-var _aa=dua.indexOf("Gecko");
-drh.mozilla=drh.moz=(_aa>=0)&&(!drh.khtml);
-if(drh.mozilla){
-drh.geckoVersion=dua.substring(_aa+6,_aa+14);
-}
-drh.ie=(document.all)&&(!drh.opera);
-drh.ie50=drh.ie&&dav.indexOf("MSIE 5.0")>=0;
-drh.ie55=drh.ie&&dav.indexOf("MSIE 5.5")>=0;
-drh.ie60=drh.ie&&dav.indexOf("MSIE 6.0")>=0;
-drh.ie70=drh.ie&&dav.indexOf("MSIE 7.0")>=0;
-var cm=document["compatMode"];
-drh.quirks=(cm=="BackCompat")||(cm=="QuirksMode")||drh.ie55||drh.ie50;
-dojo.locale=dojo.locale||(drh.ie?navigator.userLanguage:navigator.language).toLowerCase();
-dr.vml.capable=drh.ie;
-drs.capable=f;
-drs.support.plugin=f;
-drs.support.builtin=f;
-var _ac=window["document"];
-var tdi=_ac["implementation"];
-if((tdi)&&(tdi["hasFeature"])&&(tdi.hasFeature("org.w3c.dom.svg","1.0"))){
-drs.capable=t;
-drs.support.builtin=t;
-drs.support.plugin=f;
-}
-if(drh.safari){
-var tmp=dua.split("AppleWebKit/")[1];
-var ver=parseFloat(tmp.split(" ")[0]);
-if(ver>=420){
-drs.capable=t;
-drs.support.builtin=t;
-drs.support.plugin=f;
-}
-}
-})();
-dojo.hostenv.startPackage("dojo.hostenv");
-dojo.render.name=dojo.hostenv.name_="browser";
-dojo.hostenv.searchIds=[];
-dojo.hostenv._XMLHTTP_PROGIDS=["Msxml2.XMLHTTP","Microsoft.XMLHTTP","Msxml2.XMLHTTP.4.0"];
-dojo.hostenv.getXmlhttpObject=function(){
-var _b0=null;
-var _b1=null;
-try{
-_b0=new XMLHttpRequest();
-}
-catch(e){
-}
-if(!_b0){
-for(var i=0;i<3;++i){
-var _b3=dojo.hostenv._XMLHTTP_PROGIDS[i];
-try{
-_b0=new ActiveXObject(_b3);
-}
-catch(e){
-_b1=e;
-}
-if(_b0){
-dojo.hostenv._XMLHTTP_PROGIDS=[_b3];
-break;
-}
-}
-}
-if(!_b0){
-return dojo.raise("XMLHTTP not available",_b1);
-}
-return _b0;
-};
-dojo.hostenv._blockAsync=false;
-dojo.hostenv.getText=function(uri,_b5,_b6){
-if(!_b5){
-this._blockAsync=true;
-}
-var _b7=this.getXmlhttpObject();
-function isDocumentOk(_b8){
-var _b9=_b8["status"];
-return Boolean((!_b9)||((200<=_b9)&&(300>_b9))||(_b9==304));
-}
-if(_b5){
-var _ba=this,_bb=null,gbl=dojo.global();
-var xhr=dojo.evalObjPath("dojo.io.XMLHTTPTransport");
-_b7.onreadystatechange=function(){
-if(_bb){
-gbl.clearTimeout(_bb);
-_bb=null;
-}
-if(_ba._blockAsync||(xhr&&xhr._blockAsync)){
-_bb=gbl.setTimeout(function(){
-_b7.onreadystatechange.apply(this);
-},10);
-}else{
-if(4==_b7.readyState){
-if(isDocumentOk(_b7)){
-_b5(_b7.responseText);
-}
-}
-}
-};
-}
-_b7.open("GET",uri,_b5?true:false);
-try{
-_b7.send(null);
-if(_b5){
-return null;
-}
-if(!isDocumentOk(_b7)){
-var err=Error("Unable to load "+uri+" status:"+_b7.status);
-err.status=_b7.status;
-err.responseText=_b7.responseText;
-throw err;
-}
-}
-catch(e){
-this._blockAsync=false;
-if((_b6)&&(!_b5)){
-return null;
-}else{
-throw e;
-}
-}
-this._blockAsync=false;
-return _b7.responseText;
-};
-dojo.hostenv.defaultDebugContainerId="dojoDebug";
-dojo.hostenv._println_buffer=[];
-dojo.hostenv._println_safe=false;
-dojo.hostenv.println=function(_bf){
-if(!dojo.hostenv._println_safe){
-dojo.hostenv._println_buffer.push(_bf);
-}else{
-try{
-var _c0=document.getElementById(djConfig.debugContainerId?djConfig.debugContainerId:dojo.hostenv.defaultDebugContainerId);
-if(!_c0){
-_c0=dojo.body();
-}
-var div=document.createElement("div");
-div.appendChild(document.createTextNode(_bf));
-_c0.appendChild(div);
-}
-catch(e){
-try{
-document.write("<div>"+_bf+"</div>");
-}
-catch(e2){
-window.status=_bf;
-}
-}
-}
-};
-dojo.addOnLoad(function(){
-dojo.hostenv._println_safe=true;
-while(dojo.hostenv._println_buffer.length>0){
-dojo.hostenv.println(dojo.hostenv._println_buffer.shift());
-}
-});
-function dj_addNodeEvtHdlr(_c2,_c3,fp,_c5){
-var _c6=_c2["on"+_c3]||function(){
-};
-_c2["on"+_c3]=function(){
-fp.apply(_c2,arguments);
-_c6.apply(_c2,arguments);
-};
-return true;
-}
-function dj_load_init(e){
-var _c8=(e&&e.type)?e.type.toLowerCase():"load";
-if(arguments.callee.initialized||(_c8!="domcontentloaded"&&_c8!="load")){
-return;
-}
-arguments.callee.initialized=true;
-if(typeof (_timer)!="undefined"){
-clearInterval(_timer);
-delete _timer;
-}
-var _c9=function(){
-if(dojo.render.html.ie){
-dojo.hostenv.makeWidgets();
-}
-};
-if(dojo.hostenv.inFlightCount==0){
-_c9();
-dojo.hostenv.modulesLoaded();
-}else{
-dojo.addOnLoad(_c9);
-}
-}
-if(document.addEventListener){
-if(dojo.render.html.opera||(dojo.render.html.moz&&!djConfig.delayMozLoadingFix)){
-document.addEventListener("DOMContentLoaded",dj_load_init,null);
-}
-window.addEventListener("load",dj_load_init,null);
-}
-if(dojo.render.html.ie&&dojo.render.os.win){
-document.attachEvent("onreadystatechange",function(e){
-if(document.readyState=="complete"){
-dj_load_init();
-}
-});
-}
-if(/(WebKit|khtml)/i.test(navigator.userAgent)){
-var _timer=setInterval(function(){
-if(/loaded|complete/.test(document.readyState)){
-dj_load_init();
-}
-},10);
-}
-if(dojo.render.html.ie){
-dj_addNodeEvtHdlr(window,"beforeunload",function(){
-dojo.hostenv._unloading=true;
-window.setTimeout(function(){
-dojo.hostenv._unloading=false;
-},0);
-});
-}
-dj_addNodeEvtHdlr(window,"unload",function(){
-dojo.hostenv.unloaded();
-if((!dojo.render.html.ie)||(dojo.render.html.ie&&dojo.hostenv._unloading)){
-dojo.hostenv.unloaded();
-}
-});
-dojo.hostenv.makeWidgets=function(){
-var _cb=[];
-if(djConfig.searchIds&&djConfig.searchIds.length>0){
-_cb=_cb.concat(djConfig.searchIds);
-}
-if(dojo.hostenv.searchIds&&dojo.hostenv.searchIds.length>0){
-_cb=_cb.concat(dojo.hostenv.searchIds);
-}
-if((djConfig.parseWidgets)||(_cb.length>0)){
-if(dojo.evalObjPath("dojo.widget.Parse")){
-var _cc=new dojo.xml.Parse();
-if(_cb.length>0){
-for(var x=0;x<_cb.length;x++){
-var _ce=document.getElementById(_cb[x]);
-if(!_ce){
-continue;
-}
-var _cf=_cc.parseElement(_ce,null,true);
-dojo.widget.getParser().createComponents(_cf);
-}
-}else{
-if(djConfig.parseWidgets){
-var _cf=_cc.parseElement(dojo.body(),null,true);
-dojo.widget.getParser().createComponents(_cf);
-}
-}
-}
-}
-};
-dojo.addOnLoad(function(){
-if(!dojo.render.html.ie){
-dojo.hostenv.makeWidgets();
-}
-});
-try{
-if(dojo.render.html.ie){
-document.namespaces.add("v","urn:schemas-microsoft-com:vml");
-document.createStyleSheet().addRule("v\\:*","behavior:url(#default#VML)");
-}
-}
-catch(e){
-}
-dojo.hostenv.writeIncludes=function(){
-};
-if(!dj_undef("document",this)){
-dj_currentDocument=this.document;
-}
-dojo.doc=function(){
-return dj_currentDocument;
-};
-dojo.body=function(){
-return dojo.doc().body||dojo.doc().getElementsByTagName("body")[0];
-};
-dojo.byId=function(id,doc){
-if((id)&&((typeof id=="string")||(id instanceof String))){
-if(!doc){
-doc=dj_currentDocument;
-}
-var ele=doc.getElementById(id);
-if(ele&&(ele.id!=id)&&doc.all){
-ele=null;
-eles=doc.all[id];
-if(eles){
-if(eles.length){
-for(var i=0;i<eles.length;i++){
-if(eles[i].id==id){
-ele=eles[i];
-break;
-}
-}
-}else{
-ele=eles;
-}
-}
-}
-return ele;
-}
-return id;
-};
-dojo.setContext=function(_d4,_d5){
-dj_currentContext=_d4;
-dj_currentDocument=_d5;
-};
-dojo._fireCallback=function(_d6,_d7,_d8){
-if((_d7)&&((typeof _d6=="string")||(_d6 instanceof String))){
-_d6=_d7[_d6];
-}
-return (_d7?_d6.apply(_d7,_d8||[]):_d6());
-};
-dojo.withGlobal=function(_d9,_da,_db,_dc){
-var _dd;
-var _de=dj_currentContext;
-var _df=dj_currentDocument;
-try{
-dojo.setContext(_d9,_d9.document);
-_dd=dojo._fireCallback(_da,_db,_dc);
-}
-finally{
-dojo.setContext(_de,_df);
-}
-return _dd;
-};
-dojo.withDoc=function(_e0,_e1,_e2,_e3){
-var _e4;
-var _e5=dj_currentDocument;
-try{
-dj_currentDocument=_e0;
-_e4=dojo._fireCallback(_e1,_e2,_e3);
-}
-finally{
-dj_currentDocument=_e5;
-}
-return _e4;
-};
-}
-(function(){
-if(typeof dj_usingBootstrap!="undefined"){
-return;
-}
-var _e6=false;
-var _e7=false;
-var _e8=false;
-if((typeof this["load"]=="function")&&((typeof this["Packages"]=="function")||(typeof this["Packages"]=="object"))){
-_e6=true;
-}else{
-if(typeof this["load"]=="function"){
-_e7=true;
-}else{
-if(window.widget){
-_e8=true;
-}
-}
-}
-var _e9=[];
-if((this["djConfig"])&&((djConfig["isDebug"])||(djConfig["debugAtAllCosts"]))){
-_e9.push("debug.js");
-}
-if((this["djConfig"])&&(djConfig["debugAtAllCosts"])&&(!_e6)&&(!_e8)){
-_e9.push("browser_debug.js");
-}
-var _ea=djConfig["baseScriptUri"];
-if((this["djConfig"])&&(djConfig["baseLoaderUri"])){
-_ea=djConfig["baseLoaderUri"];
-}
-for(var x=0;x<_e9.length;x++){
-var _ec=_ea+"src/"+_e9[x];
-if(_e6||_e7){
-load(_ec);
-}else{
-try{
-document.write("<scr"+"ipt type='text/javascript' src='"+_ec+"'></scr"+"ipt>");
-}
-catch(e){
-var _ed=document.createElement("script");
-_ed.src=_ec;
-document.getElementsByTagName("head")[0].appendChild(_ed);
-}
-}
-}
-})();
-dojo.provide("dojo.lang.common");
-dojo.lang.inherits=function(_ee,_ef){
-if(typeof _ef!="function"){
-dojo.raise("dojo.inherits: superclass argument ["+_ef+"] must be a function (subclass: ["+_ee+"']");
-}
-_ee.prototype=new _ef();
-_ee.prototype.constructor=_ee;
-_ee.superclass=_ef.prototype;
-_ee["super"]=_ef.prototype;
-};
-dojo.lang._mixin=function(obj,_f1){
-var _f2={};
-for(var x in _f1){
-if((typeof _f2[x]=="undefined")||(_f2[x]!=_f1[x])){
-obj[x]=_f1[x];
-}
-}
-if(dojo.render.html.ie&&(typeof (_f1["toString"])=="function")&&(_f1["toString"]!=obj["toString"])&&(_f1["toString"]!=_f2["toString"])){
-obj.toString=_f1.toString;
-}
-return obj;
-};
-dojo.lang.mixin=function(obj,_f5){
-for(var i=1,l=arguments.length;i<l;i++){
-dojo.lang._mixin(obj,arguments[i]);
-}
-return obj;
-};
-dojo.lang.extend=function(_f8,_f9){
-for(var i=1,l=arguments.length;i<l;i++){
-dojo.lang._mixin(_f8.prototype,arguments[i]);
-}
-return _f8;
-};
-dojo.inherits=dojo.lang.inherits;
-dojo.mixin=dojo.lang.mixin;
-dojo.extend=dojo.lang.extend;
-dojo.lang.find=function(_fc,_fd,_fe,_ff){
-if(!dojo.lang.isArrayLike(_fc)&&dojo.lang.isArrayLike(_fd)){
-dojo.deprecated("dojo.lang.find(value, array)","use dojo.lang.find(array, value) instead","0.5");
-var temp=_fc;
-_fc=_fd;
-_fd=temp;
-}
-var _101=dojo.lang.isString(_fc);
-if(_101){
-_fc=_fc.split("");
-}
-if(_ff){
-var step=-1;
-var i=_fc.length-1;
-var end=-1;
-}else{
-var step=1;
-var i=0;
-var end=_fc.length;
-}
-if(_fe){
-while(i!=end){
-if(_fc[i]===_fd){
-return i;
-}
-i+=step;
-}
-}else{
-while(i!=end){
-if(_fc[i]==_fd){
-return i;
-}
-i+=step;
-}
-}
-return -1;
-};
-dojo.lang.indexOf=dojo.lang.find;
-dojo.lang.findLast=function(_105,_106,_107){
-return dojo.lang.find(_105,_106,_107,true);
-};
-dojo.lang.lastIndexOf=dojo.lang.findLast;
-dojo.lang.inArray=function(_108,_109){
-return dojo.lang.find(_108,_109)>-1;
-};
-dojo.lang.isObject=function(it){
-if(typeof it=="undefined"){
-return false;
-}
-return (typeof it=="object"||it===null||dojo.lang.isArray(it)||dojo.lang.isFunction(it));
-};
-dojo.lang.isArray=function(it){
-return (it&&it instanceof Array||typeof it=="array");
-};
-dojo.lang.isArrayLike=function(it){
-if((!it)||(dojo.lang.isUndefined(it))){
-return false;
-}
-if(dojo.lang.isString(it)){
-return false;
-}
-if(dojo.lang.isFunction(it)){
-return false;
-}
-if(dojo.lang.isArray(it)){
-return true;
-}
-if((it.tagName)&&(it.tagName.toLowerCase()=="form")){
-return false;
-}
-if(dojo.lang.isNumber(it.length)&&isFinite(it.length)){
-return true;
-}
-return false;
-};
-dojo.lang.isFunction=function(it){
-if(!it){
-return false;
-}
-if((typeof (it)=="function")&&(it=="[object NodeList]")){
-return false;
-}
-return (it instanceof Function||typeof it=="function");
-};
-dojo.lang.isString=function(it){
-return (typeof it=="string"||it instanceof String);
-};
-dojo.lang.isAlien=function(it){
-if(!it){
-return false;
-}
-return !dojo.lang.isFunction()&&/\{\s*\[native code\]\s*\}/.test(String(it));
-};
-dojo.lang.isBoolean=function(it){
-return (it instanceof Boolean||typeof it=="boolean");
-};
-dojo.lang.isNumber=function(it){
-return (it instanceof Number||typeof it=="number");
-};
-dojo.lang.isUndefined=function(it){
-return ((typeof (it)=="undefined")&&(it==undefined));
-};
-dojo.provide("dojo.lang");
-dojo.deprecated("dojo.lang","replaced by dojo.lang.common","0.5");
-dojo.provide("dojo.dom");
-dojo.dom.ELEMENT_NODE=1;
-dojo.dom.ATTRIBUTE_NODE=2;
-dojo.dom.TEXT_NODE=3;
-dojo.dom.CDATA_SECTION_NODE=4;
-dojo.dom.ENTITY_REFERENCE_NODE=5;
-dojo.dom.ENTITY_NODE=6;
-dojo.dom.PROCESSING_INSTRUCTION_NODE=7;
-dojo.dom.COMMENT_NODE=8;
-dojo.dom.DOCUMENT_NODE=9;
-dojo.dom.DOCUMENT_TYPE_NODE=10;
-dojo.dom.DOCUMENT_FRAGMENT_NODE=11;
-dojo.dom.NOTATION_NODE=12;
-dojo.dom.dojoml="http://www.dojotoolkit.org/2004/dojoml";
-dojo.dom.xmlns={svg:"http://www.w3.org/2000/svg",smil:"http://www.w3.org/2001/SMIL20/",mml:"http://www.w3.org/1998/Math/MathML",cml:"http://www.xml-cml.org",xlink:"http://www.w3.org/1999/xlink",xhtml:"http://www.w3.org/1999/xhtml",xul:"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",xbl:"http://www.mozilla.org/xbl",fo:"http://www.w3.org/1999/XSL/Format",xsl:"http://www.w3.org/1999/XSL/Transform",xslt:"http://www.w3.org/1999/XSL/Transform",xi:"http://www.w3.org/2001/XInclude",xforms:"http://www.w3.org/2002/01/xforms",saxon:"http://icl.com/saxon",xalan:"http://xml.apache.org/xslt",xsd:"http://www.w3.org/2001/XMLSchema",dt:"http://www.w3.org/2001/XMLSchema-datatypes",xsi:"http://www.w3.org/2001/XMLSchema-instance",rdf:"http://www.w3.org/1999/02/22-rdf-syntax-ns#",rdfs:"http://www.w3.org/2000/01/rdf-schema#",dc:"http://purl.org/dc/elements/1.1/",dcq:"http://purl.org/dc/qualifiers/1.0","soap-env":"http://schemas.xmlsoap.org/soap/envelope/",wsdl:"http://schemas.xmlsoap.org/wsdl/",AdobeExtensions:"http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"};
-dojo.dom.isNode=function(wh){
-if(typeof Element=="function"){
-try{
-return wh instanceof Element;
-}
-catch(E){
-}
-}else{
-return wh&&!isNaN(wh.nodeType);
-}
-};
-dojo.dom.getUniqueId=function(){
-var _114=dojo.doc();
-do{
-var id="dj_unique_"+(++arguments.callee._idIncrement);
-}while(_114.getElementById(id));
-return id;
-};
-dojo.dom.getUniqueId._idIncrement=0;
-dojo.dom.firstElement=dojo.dom.getFirstChildElement=function(_116,_117){
-var node=_116.firstChild;
-while(node&&node.nodeType!=dojo.dom.ELEMENT_NODE){
-node=node.nextSibling;
-}
-if(_117&&node&&node.tagName&&node.tagName.toLowerCase()!=_117.toLowerCase()){
-node=dojo.dom.nextElement(node,_117);
-}
-return node;
-};
-dojo.dom.lastElement=dojo.dom.getLastChildElement=function(_119,_11a){
-var node=_119.lastChild;
-while(node&&node.nodeType!=dojo.dom.ELEMENT_NODE){
-node=node.previousSibling;
-}
-if(_11a&&node&&node.tagName&&node.tagName.toLowerCase()!=_11a.toLowerCase()){
-node=dojo.dom.prevElement(node,_11a);
-}
-return node;
-};
-dojo.dom.nextElement=dojo.dom.getNextSiblingElement=function(node,_11d){
-if(!node){
-return null;
-}
-do{
-node=node.nextSibling;
-}while(node&&node.nodeType!=dojo.dom.ELEMENT_NODE);
-if(node&&_11d&&_11d.toLowerCase()!=node.tagName.toLowerCase()){
-return dojo.dom.nextElement(node,_11d);
-}
-return node;
-};
-dojo.dom.prevElement=dojo.dom.getPreviousSiblingElement=function(node,_11f){
-if(!node){
-return null;
-}
-if(_11f){
-_11f=_11f.toLowerCase();
-}
-do{
-node=node.previousSibling;
-}while(node&&node.nodeType!=dojo.dom.ELEMENT_NODE);
-if(node&&_11f&&_11f.toLowerCase()!=node.tagName.toLowerCase()){
-return dojo.dom.prevElement(node,_11f);
-}
-return node;
-};
-dojo.dom.moveChildren=function(_120,_121,trim){
-var _123=0;
-if(trim){
-while(_120.hasChildNodes()&&_120.firstChild.nodeType==dojo.dom.TEXT_NODE){
-_120.removeChild(_120.firstChild);
-}
-while(_120.hasChildNodes()&&_120.lastChild.nodeType==dojo.dom.TEXT_NODE){
-_120.removeChild(_120.lastChild);
-}
-}
-while(_120.hasChildNodes()){
-_121.appendChild(_120.firstChild);
-_123++;
-}
-return _123;
-};
-dojo.dom.copyChildren=function(_124,_125,trim){
-var _127=_124.cloneNode(true);
-return this.moveChildren(_127,_125,trim);
-};
-dojo.dom.removeChildren=function(node){
-var _129=node.childNodes.length;
-while(node.hasChildNodes()){
-node.removeChild(node.firstChild);
-}
-return _129;
-};
-dojo.dom.replaceChildren=function(node,_12b){
-dojo.dom.removeChildren(node);
-node.appendChild(_12b);
-};
-dojo.dom.removeNode=function(node){
-if(node&&node.parentNode){
-return node.parentNode.removeChild(node);
-}
-};
-dojo.dom.getAncestors=function(node,_12e,_12f){
-var _130=[];
-var _131=(_12e&&(_12e instanceof Function||typeof _12e=="function"));
-while(node){
-if(!_131||_12e(node)){
-_130.push(node);
-}
-if(_12f&&_130.length>0){
-return _130[0];
-}
-node=node.parentNode;
-}
-if(_12f){
-return null;
-}
-return _130;
-};
-dojo.dom.getAncestorsByTag=function(node,tag,_134){
-tag=tag.toLowerCase();
-return dojo.dom.getAncestors(node,function(el){
-return ((el.tagName)&&(el.tagName.toLowerCase()==tag));
-},_134);
-};
-dojo.dom.getFirstAncestorByTag=function(node,tag){
-return dojo.dom.getAncestorsByTag(node,tag,true);
-};
-dojo.dom.isDescendantOf=function(node,_139,_13a){
-if(_13a&&node){
-node=node.parentNode;
-}
-while(node){
-if(node==_139){
-return true;
-}
-node=node.parentNode;
-}
-return false;
-};
-dojo.dom.innerXML=function(node){
-if(node.innerXML){
-return node.innerXML;
-}else{
-if(node.xml){
-return node.xml;
-}else{
-if(typeof XMLSerializer!="undefined"){
-return (new XMLSerializer()).serializeToString(node);
-}
-}
-}
-};
-dojo.dom.createDocument=function(){
-var doc=null;
-var _13d=dojo.doc();
-if(!dj_undef("ActiveXObject")){
-var _13e=["MSXML2","Microsoft","MSXML","MSXML3"];
-for(var i=0;i<_13e.length;i++){
-try{
-doc=new ActiveXObject(_13e[i]+".XMLDOM");
-}
-catch(e){
-}
-if(doc){
-break;
-}
-}
-}else{
-if((_13d.implementation)&&(_13d.implementation.createDocument)){
-doc=_13d.implementation.createDocument("","",null);
-}
-}
-return doc;
-};
-dojo.dom.createDocumentFromText=function(str,_141){
-if(!_141){
-_141="text/xml";
-}
-if(!dj_undef("DOMParser")){
-var _142=new DOMParser();
-return _142.parseFromString(str,_141);
-}else{
-if(!dj_undef("ActiveXObject")){
-var _143=dojo.dom.createDocument();
-if(_143){
-_143.async=false;
-_143.loadXML(str);
-return _143;
-}else{
-dojo.debug("toXml didn't work?");
-}
-}else{
-var _144=dojo.doc();
-if(_144.createElement){
-var tmp=_144.createElement("xml");
-tmp.innerHTML=str;
-if(_144.implementation&&_144.implementation.createDocument){
-var _146=_144.implementation.createDocument("foo","",null);
-for(var i=0;i<tmp.childNodes.length;i++){
-_146.importNode(tmp.childNodes.item(i),true);
-}
-return _146;
-}
-return ((tmp.document)&&(tmp.document.firstChild?tmp.document.firstChild:tmp));
-}
-}
-}
-return null;
-};
-dojo.dom.prependChild=function(node,_149){
-if(_149.firstChild){
-_149.insertBefore(node,_149.firstChild);
-}else{
-_149.appendChild(node);
-}
-return true;
-};
-dojo.dom.insertBefore=function(node,ref,_14c){
-if(_14c!=true&&(node===ref||node.nextSibling===ref)){
-return false;
-}
-var _14d=ref.parentNode;
-_14d.insertBefore(node,ref);
-return true;
-};
-dojo.dom.insertAfter=function(node,ref,_150){
-var pn=ref.parentNode;
-if(ref==pn.lastChild){
-if((_150!=true)&&(node===ref)){
-return false;
-}
-pn.appendChild(node);
-}else{
-return this.insertBefore(node,ref.nextSibling,_150);
-}
-return true;
-};
-dojo.dom.insertAtPosition=function(node,ref,_154){
-if((!node)||(!ref)||(!_154)){
-return false;
-}
-switch(_154.toLowerCase()){
-case "before":
-return dojo.dom.insertBefore(node,ref);
-case "after":
-return dojo.dom.insertAfter(node,ref);
-case "first":
-if(ref.firstChild){
-return dojo.dom.insertBefore(node,ref.firstChild);
-}else{
-ref.appendChild(node);
-return true;
-}
-break;
-default:
-ref.appendChild(node);
-return true;
-}
-};
-dojo.dom.insertAtIndex=function(node,_156,_157){
-var _158=_156.childNodes;
-if(!_158.length){
-_156.appendChild(node);
-return true;
-}
-var _159=null;
-for(var i=0;i<_158.length;i++){
-var _15b=_158.item(i)["getAttribute"]?parseInt(_158.item(i).getAttribute("dojoinsertionindex")):-1;
-if(_15b<_157){
-_159=_158.item(i);
-}
-}
-if(_159){
-return dojo.dom.insertAfter(node,_159);
-}else{
-return dojo.dom.insertBefore(node,_158.item(0));
-}
-};
-dojo.dom.textContent=function(node,text){
-if(arguments.length>1){
-var _15e=dojo.doc();
-dojo.dom.replaceChildren(node,_15e.createTextNode(text));
-return text;
-}else{
-if(node.textContent!=undefined){
-return node.textContent;
-}
-var _15f="";
-if(node==null){
-return _15f;
-}
-for(var i=0;i<node.childNodes.length;i++){
-switch(node.childNodes[i].nodeType){
-case 1:
-case 5:
-_15f+=dojo.dom.textContent(node.childNodes[i]);
-break;
-case 3:
-case 2:
-case 4:
-_15f+=node.childNodes[i].nodeValue;
-break;
-default:
-break;
-}
-}
-return _15f;
-}
-};
-dojo.dom.hasParent=function(node){
-return node&&node.parentNode&&dojo.dom.isNode(node.parentNode);
-};
-dojo.dom.isTag=function(node){
-if(node&&node.tagName){
-for(var i=1;i<arguments.length;i++){
-if(node.tagName==String(arguments[i])){
-return String(arguments[i]);
-}
-}
-}
-return "";
-};
-dojo.dom.setAttributeNS=function(elem,_165,_166,_167){
-if(elem==null||((elem==undefined)&&(typeof elem=="undefined"))){
-dojo.raise("No element given to dojo.dom.setAttributeNS");
-}
-if(!((elem.setAttributeNS==undefined)&&(typeof elem.setAttributeNS=="undefined"))){
-elem.setAttributeNS(_165,_166,_167);
-}else{
-var _168=elem.ownerDocument;
-var _169=_168.createNode(2,_166,_165);
-_169.nodeValue=_167;
-elem.setAttributeNode(_169);
-}
-};
-dojo.provide("dojo.html.common");
-dojo.lang.mixin(dojo.html,dojo.dom);
-dojo.html.body=function(){
-dojo.deprecated("dojo.html.body() moved to dojo.body()","0.5");
-return dojo.body();
-};
-dojo.html.getEventTarget=function(evt){
-if(!evt){
-evt=dojo.global().event||{};
-}
-var t=(evt.srcElement?evt.srcElement:(evt.target?evt.target:null));
-while((t)&&(t.nodeType!=1)){
-t=t.parentNode;
-}
-return t;
-};
-dojo.html.getViewport=function(){
-var _16c=dojo.global();
-var _16d=dojo.doc();
-var w=0;
-var h=0;
-if(dojo.render.html.mozilla){
-w=_16d.documentElement.clientWidth;
-h=_16c.innerHeight;
-}else{
-if(!dojo.render.html.opera&&_16c.innerWidth){
-w=_16c.innerWidth;
-h=_16c.innerHeight;
-}else{
-if(!dojo.render.html.opera&&dojo.exists(_16d,"documentElement.clientWidth")){
-var w2=_16d.documentElement.clientWidth;
-if(!w||w2&&w2<w){
-w=w2;
-}
-h=_16d.documentElement.clientHeight;
-}else{
-if(dojo.body().clientWidth){
-w=dojo.body().clientWidth;
-h=dojo.body().clientHeight;
-}
-}
-}
-}
-return {width:w,height:h};
-};
-dojo.html.getScroll=function(){
-var _171=dojo.global();
-var _172=dojo.doc();
-var top=_171.pageYOffset||_172.documentElement.scrollTop||dojo.body().scrollTop||0;
-var left=_171.pageXOffset||_172.documentElement.scrollLeft||dojo.body().scrollLeft||0;
-return {top:top,left:left,offset:{x:left,y:top}};
-};
-dojo.html.getParentByType=function(node,type){
-var _177=dojo.doc();
-var _178=dojo.byId(node);
-type=type.toLowerCase();
-while((_178)&&(_178.nodeName.toLowerCase()!=type)){
-if(_178==(_177["body"]||_177["documentElement"])){
-return null;
-}
-_178=_178.parentNode;
-}
-return _178;
-};
-dojo.html.getAttribute=function(node,attr){
-node=dojo.byId(node);
-if((!node)||(!node.getAttribute)){
-return null;
-}
-var ta=typeof attr=="string"?attr:new String(attr);
-var v=node.getAttribute(ta.toUpperCase());
-if((v)&&(typeof v=="string")&&(v!="")){
-return v;
-}
-if(v&&v.value){
-return v.value;
-}
-if((node.getAttributeNode)&&(node.getAttributeNode(ta))){
-return (node.getAttributeNode(ta)).value;
-}else{
-if(node.getAttribute(ta)){
-return node.getAttribute(ta);
-}else{
-if(node.getAttribute(ta.toLowerCase())){
-return node.getAttribute(ta.toLowerCase());
-}
-}
-}
-return null;
-};
-dojo.html.hasAttribute=function(node,attr){
-return dojo.html.getAttribute(dojo.byId(node),attr)?true:false;
-};
-dojo.html.getCursorPosition=function(e){
-e=e||dojo.global().event;
-var _180={x:0,y:0};
-if(e.pageX||e.pageY){
-_180.x=e.pageX;
-_180.y=e.pageY;
-}else{
-var de=dojo.doc().documentElement;
-var db=dojo.body();
-_180.x=e.clientX+((de||db)["scrollLeft"])-((de||db)["clientLeft"]);
-_180.y=e.clientY+((de||db)["scrollTop"])-((de||db)["clientTop"]);
-}
-return _180;
-};
-dojo.html.isTag=function(node){
-node=dojo.byId(node);
-if(node&&node.tagName){
-for(var i=1;i<arguments.length;i++){
-if(node.tagName.toLowerCase()==String(arguments[i]).toLowerCase()){
-return String(arguments[i]).toLowerCase();
-}
-}
-}
-return "";
-};
-if(dojo.render.html.ie&&!dojo.render.html.ie70){
-if(window.location.href.substr(0,6).toLowerCase()!="https:"){
-(function(){
-var _185=dojo.doc().createElement("script");
-_185.src="javascript:'dojo.html.createExternalElement=function(doc, tag){ return doc.createElement(tag); }'";
-dojo.doc().getElementsByTagName("head")[0].appendChild(_185);
-})();
-}
-}else{
-dojo.html.createExternalElement=function(doc,tag){
-return doc.createElement(tag);
-};
-}
-dojo.html._callDeprecated=function(_188,_189,args,_18b,_18c){
-dojo.deprecated("dojo.html."+_188,"replaced by dojo.html."+_189+"("+(_18b?"node, {"+_18b+": "+_18b+"}":"")+")"+(_18c?"."+_18c:""),"0.5");
-var _18d=[];
-if(_18b){
-var _18e={};
-_18e[_18b]=args[1];
-_18d.push(args[0]);
-_18d.push(_18e);
-}else{
-_18d=args;
-}
-var ret=dojo.html[_189].apply(dojo.html,args);
-if(_18c){
-return ret[_18c];
-}else{
-return ret;
-}
-};
-dojo.html.getViewportWidth=function(){
-return dojo.html._callDeprecated("getViewportWidth","getViewport",arguments,null,"width");
-};
-dojo.html.getViewportHeight=function(){
-return dojo.html._callDeprecated("getViewportHeight","getViewport",arguments,null,"height");
-};
-dojo.html.getViewportSize=function(){
-return dojo.html._callDeprecated("getViewportSize","getViewport",arguments);
-};
-dojo.html.getScrollTop=function(){
-return dojo.html._callDeprecated("getScrollTop","getScroll",arguments,null,"top");
-};
-dojo.html.getScrollLeft=function(){
-return dojo.html._callDeprecated("getScrollLeft","getScroll",arguments,null,"left");
-};
-dojo.html.getScrollOffset=function(){
-return dojo.html._callDeprecated("getScrollOffset","getScroll",arguments,null,"offset");
-};
-dojo.provide("dojo.uri.Uri");
-dojo.uri=new function(){
-this.dojoUri=function(uri){
-return new dojo.uri.Uri(dojo.hostenv.getBaseScriptUri(),uri);
-};
-this.moduleUri=function(_191,uri){
-var loc=dojo.hostenv.getModulePrefix(_191);
-if(!loc){
-return null;
-}
-if(loc.lastIndexOf("/")!=loc.length-1){
-loc+="/";
-}
-return new dojo.uri.Uri(dojo.hostenv.getBaseScriptUri()+loc,uri);
-};
-this.Uri=function(){
-var uri=arguments[0];
-for(var i=1;i<arguments.length;i++){
-if(!arguments[i]){
-continue;
-}
-var _196=new dojo.uri.Uri(arguments[i].toString());
-var _197=new dojo.uri.Uri(uri.toString());
-if((_196.path=="")&&(_196.scheme==null)&&(_196.authority==null)&&(_196.query==null)){
-if(_196.fragment!=null){
-_197.fragment=_196.fragment;
-}
-_196=_197;
-}else{
-if(_196.scheme==null){
-_196.scheme=_197.scheme;
-if(_196.authority==null){
-_196.authority=_197.authority;
-if(_196.path.charAt(0)!="/"){
-var path=_197.path.substring(0,_197.path.lastIndexOf("/")+1)+_196.path;
-var segs=path.split("/");
-for(var j=0;j<segs.length;j++){
-if(segs[j]=="."){
-if(j==segs.length-1){
-segs[j]="";
-}else{
-segs.splice(j,1);
-j--;
-}
-}else{
-if(j>0&&!(j==1&&segs[0]=="")&&segs[j]==".."&&segs[j-1]!=".."){
-if(j==segs.length-1){
-segs.splice(j,1);
-segs[j-1]="";
-}else{
-segs.splice(j-1,2);
-j-=2;
-}
-}
-}
-}
-_196.path=segs.join("/");
-}
-}
-}
-}
-uri="";
-if(_196.scheme!=null){
-uri+=_196.scheme+":";
-}
-if(_196.authority!=null){
-uri+="//"+_196.authority;
-}
-uri+=_196.path;
-if(_196.query!=null){
-uri+="?"+_196.query;
-}
-if(_196.fragment!=null){
-uri+="#"+_196.fragment;
-}
-}
-this.uri=uri.toString();
-var _19b="^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$";
-var r=this.uri.match(new RegExp(_19b));
-this.scheme=r[2]||(r[1]?"":null);
-this.authority=r[4]||(r[3]?"":null);
-this.path=r[5];
-this.query=r[7]||(r[6]?"":null);
-this.fragment=r[9]||(r[8]?"":null);
-if(this.authority!=null){
-_19b="^((([^:]+:)?([^@]+))@)?([^:]*)(:([0-9]+))?$";
-r=this.authority.match(new RegExp(_19b));
-this.user=r[3]||null;
-this.password=r[4]||null;
-this.host=r[5];
-this.port=r[7]||null;
-}
-this.toString=function(){
-return this.uri;
-};
-};
-};
-dojo.provide("dojo.html.style");
-dojo.html.getClass=function(node){
-node=dojo.byId(node);
-if(!node){
-return "";
-}
-var cs="";
-if(node.className){
-cs=node.className;
-}else{
-if(dojo.html.hasAttribute(node,"class")){
-cs=dojo.html.getAttribute(node,"class");
-}
-}
-return cs.replace(/^\s+|\s+$/g,"");
-};
-dojo.html.getClasses=function(node){
-var c=dojo.html.getClass(node);
-return (c=="")?[]:c.split(/\s+/g);
-};
-dojo.html.hasClass=function(node,_1a2){
-return (new RegExp("(^|\\s+)"+_1a2+"(\\s+|$)")).test(dojo.html.getClass(node));
-};
-dojo.html.prependClass=function(node,_1a4){
-_1a4+=" "+dojo.html.getClass(node);
-return dojo.html.setClass(node,_1a4);
-};
-dojo.html.addClass=function(node,_1a6){
-if(dojo.html.hasClass(node,_1a6)){
-return false;
-}
-_1a6=(dojo.html.getClass(node)+" "+_1a6).replace(/^\s+|\s+$/g,"");
-return dojo.html.setClass(node,_1a6);
-};
-dojo.html.setClass=function(node,_1a8){
-node=dojo.byId(node);
-var cs=new String(_1a8);
-try{
-if(typeof node.className=="string"){
-node.className=cs;
-}else{
-if(node.setAttribute){
-node.setAttribute("class",_1a8);
-node.className=cs;
-}else{
-return false;
-}
-}
-}
-catch(e){
-dojo.debug("dojo.html.setClass() failed",e);
-}
-return true;
-};
-dojo.html.removeClass=function(node,_1ab,_1ac){
-try{
-if(!_1ac){
-var _1ad=dojo.html.getClass(node).replace(new RegExp("(^|\\s+)"+_1ab+"(\\s+|$)"),"$1$2");
-}else{
-var _1ad=dojo.html.getClass(node).replace(_1ab,"");
-}
-dojo.html.setClass(node,_1ad);
-}
-catch(e){
-dojo.debug("dojo.html.removeClass() failed",e);
-}
-return true;
-};
-dojo.html.replaceClass=function(node,_1af,_1b0){
-dojo.html.removeClass(node,_1b0);
-dojo.html.addClass(node,_1af);
-};
-dojo.html.classMatchType={ContainsAll:0,ContainsAny:1,IsOnly:2};
-dojo.html.getElementsByClass=function(_1b1,_1b2,_1b3,_1b4,_1b5){
-_1b5=false;
-var _1b6=dojo.doc();
-_1b2=dojo.byId(_1b2)||_1b6;
-var _1b7=_1b1.split(/\s+/g);
-var _1b8=[];
-if(_1b4!=1&&_1b4!=2){
-_1b4=0;
-}
-var _1b9=new RegExp("(\\s|^)(("+_1b7.join(")|(")+"))(\\s|$)");
-var _1ba=_1b7.join(" ").length;
-var _1bb=[];
-if(!_1b5&&_1b6.evaluate){
-var _1bc=".//"+(_1b3||"*")+"[contains(";
-if(_1b4!=dojo.html.classMatchType.ContainsAny){
-_1bc+="concat(' ',@class,' '), ' "+_1b7.join(" ') and contains(concat(' ',@class,' '), ' ")+" ')";
-if(_1b4==2){
-_1bc+=" and string-length(@class)="+_1ba+"]";
-}else{
-_1bc+="]";
-}
-}else{
-_1bc+="concat(' ',@class,' '), ' "+_1b7.join(" ') or contains(concat(' ',@class,' '), ' ")+" ')]";
-}
-var _1bd=_1b6.evaluate(_1bc,_1b2,null,XPathResult.ANY_TYPE,null);
-var _1be=_1bd.iterateNext();
-while(_1be){
-try{
-_1bb.push(_1be);
-_1be=_1bd.iterateNext();
-}
-catch(e){
-break;
-}
-}
-return _1bb;
-}else{
-if(!_1b3){
-_1b3="*";
-}
-_1bb=_1b2.getElementsByTagName(_1b3);
-var node,i=0;
-outer:
-while(node=_1bb[i++]){
-var _1c1=dojo.html.getClasses(node);
-if(_1c1.length==0){
-continue outer;
-}
-var _1c2=0;
-for(var j=0;j<_1c1.length;j++){
-if(_1b9.test(_1c1[j])){
-if(_1b4==dojo.html.classMatchType.ContainsAny){
-_1b8.push(node);
-continue outer;
-}else{
-_1c2++;
-}
-}else{
-if(_1b4==dojo.html.classMatchType.IsOnly){
-continue outer;
-}
-}
-}
-if(_1c2==_1b7.length){
-if((_1b4==dojo.html.classMatchType.IsOnly)&&(_1c2==_1c1.length)){
-_1b8.push(node);
-}else{
-if(_1b4==dojo.html.classMatchType.ContainsAll){
-_1b8.push(node);
-}
-}
-}
-}
-return _1b8;
-}
-};
-dojo.html.getElementsByClassName=dojo.html.getElementsByClass;
-dojo.html.toCamelCase=function(_1c4){
-var arr=_1c4.split("-"),cc=arr[0];
-for(var i=1;i<arr.length;i++){
-cc+=arr[i].charAt(0).toUpperCase()+arr[i].substring(1);
-}
-return cc;
-};
-dojo.html.toSelectorCase=function(_1c8){
-return _1c8.replace(/([A-Z])/g,"-$1").toLowerCase();
-};
-dojo.html.getComputedStyle=function(node,_1ca,_1cb){
-node=dojo.byId(node);
-var _1ca=dojo.html.toSelectorCase(_1ca);
-var _1cc=dojo.html.toCamelCase(_1ca);
-if(!node||!node.style){
-return _1cb;
-}else{
-if(document.defaultView&&dojo.html.isDescendantOf(node,node.ownerDocument)){
-try{
-var cs=document.defaultView.getComputedStyle(node,"");
-if(cs){
-return cs.getPropertyValue(_1ca);
-}
-}
-catch(e){
-if(node.style.getPropertyValue){
-return node.style.getPropertyValue(_1ca);
-}else{
-return _1cb;
-}
-}
-}else{
-if(node.currentStyle){
-return node.currentStyle[_1cc];
-}
-}
-}
-if(node.style.getPropertyValue){
-return node.style.getPropertyValue(_1ca);
-}else{
-return _1cb;
-}
-};
-dojo.html.getStyleProperty=function(node,_1cf){
-node=dojo.byId(node);
-return (node&&node.style?node.style[dojo.html.toCamelCase(_1cf)]:undefined);
-};
-dojo.html.getStyle=function(node,_1d1){
-var _1d2=dojo.html.getStyleProperty(node,_1d1);
-return (_1d2?_1d2:dojo.html.getComputedStyle(node,_1d1));
-};
-dojo.html.setStyle=function(node,_1d4,_1d5){
-node=dojo.byId(node);
-if(node&&node.style){
-var _1d6=dojo.html.toCamelCase(_1d4);
-node.style[_1d6]=_1d5;
-}
-};
-dojo.html.setStyleText=function(_1d7,text){
-try{
-_1d7.style.cssText=text;
-}
-catch(e){
-_1d7.setAttribute("style",text);
-}
-};
-dojo.html.copyStyle=function(_1d9,_1da){
-if(!_1da.style.cssText){
-_1d9.setAttribute("style",_1da.getAttribute("style"));
-}else{
-_1d9.style.cssText=_1da.style.cssText;
-}
-dojo.html.addClass(_1d9,dojo.html.getClass(_1da));
-};
-dojo.html.getUnitValue=function(node,_1dc,_1dd){
-var s=dojo.html.getComputedStyle(node,_1dc);
-if((!s)||((s=="auto")&&(_1dd))){
-return {value:0,units:"px"};
-}
-var _1df=s.match(/(\-?[\d.]+)([a-z%]*)/i);
-if(!_1df){
-return dojo.html.getUnitValue.bad;
-}
-return {value:Number(_1df[1]),units:_1df[2].toLowerCase()};
-};
-dojo.html.getUnitValue.bad={value:NaN,units:""};
-dojo.html.getPixelValue=function(node,_1e1,_1e2){
-var _1e3=dojo.html.getUnitValue(node,_1e1,_1e2);
-if(isNaN(_1e3.value)){
-return 0;
-}
-if((_1e3.value)&&(_1e3.units!="px")){
-return NaN;
-}
-return _1e3.value;
-};
-dojo.html.setPositivePixelValue=function(node,_1e5,_1e6){
-if(isNaN(_1e6)){
-return false;
-}
-node.style[_1e5]=Math.max(0,_1e6)+"px";
-return true;
-};
-dojo.html.styleSheet=null;
-dojo.html.insertCssRule=function(_1e7,_1e8,_1e9){
-if(!dojo.html.styleSheet){
-if(document.createStyleSheet){
-dojo.html.styleSheet=document.createStyleSheet();
-}else{
-if(document.styleSheets[0]){
-dojo.html.styleSheet=document.styleSheets[0];
-}else{
-return null;
-}
-}
-}
-if(arguments.length<3){
-if(dojo.html.styleSheet.cssRules){
-_1e9=dojo.html.styleSheet.cssRules.length;
-}else{
-if(dojo.html.styleSheet.rules){
-_1e9=dojo.html.styleSheet.rules.length;
-}else{
-return null;
-}
-}
-}
-if(dojo.html.styleSheet.insertRule){
-var rule=_1e7+" { "+_1e8+" }";
-return dojo.html.styleSheet.insertRule(rule,_1e9);
-}else{
-if(dojo.html.styleSheet.addRule){
-return dojo.html.styleSheet.addRule(_1e7,_1e8,_1e9);
-}else{
-return null;
-}
-}
-};
-dojo.html.removeCssRule=function(_1eb){
-if(!dojo.html.styleSheet){
-dojo.debug("no stylesheet defined for removing rules");
-return false;
-}
-if(dojo.render.html.ie){
-if(!_1eb){
-_1eb=dojo.html.styleSheet.rules.length;
-dojo.html.styleSheet.removeRule(_1eb);
-}
-}else{
-if(document.styleSheets[0]){
-if(!_1eb){
-_1eb=dojo.html.styleSheet.cssRules.length;
-}
-dojo.html.styleSheet.deleteRule(_1eb);
-}
-}
-return true;
-};
-dojo.html._insertedCssFiles=[];
-dojo.html.insertCssFile=function(URI,doc,_1ee,_1ef){
-if(!URI){
-return;
-}
-if(!doc){
-doc=document;
-}
-var _1f0=dojo.hostenv.getText(URI,false,_1ef);
-if(_1f0===null){
-return;
-}
-_1f0=dojo.html.fixPathsInCssText(_1f0,URI);
-if(_1ee){
-var idx=-1,node,ent=dojo.html._insertedCssFiles;
-for(var i=0;i<ent.length;i++){
-if((ent[i].doc==doc)&&(ent[i].cssText==_1f0)){
-idx=i;
-node=ent[i].nodeRef;
-break;
-}
-}
-if(node){
-var _1f5=doc.getElementsByTagName("style");
-for(var i=0;i<_1f5.length;i++){
-if(_1f5[i]==node){
-return;
-}
-}
-dojo.html._insertedCssFiles.shift(idx,1);
-}
-}
-var _1f6=dojo.html.insertCssText(_1f0);
-dojo.html._insertedCssFiles.push({"doc":doc,"cssText":_1f0,"nodeRef":_1f6});
-if(_1f6&&djConfig.isDebug){
-_1f6.setAttribute("dbgHref",URI);
-}
-return _1f6;
-};
-dojo.html.insertCssText=function(_1f7,doc,URI){
-if(!_1f7){
-return;
-}
-if(!doc){
-doc=document;
-}
-if(URI){
-_1f7=dojo.html.fixPathsInCssText(_1f7,URI);
-}
-var _1fa=doc.createElement("style");
-_1fa.setAttribute("type","text/css");
-var head=doc.getElementsByTagName("head")[0];
-if(!head){
-dojo.debug("No head tag in document, aborting styles");
-return;
-}else{
-head.appendChild(_1fa);
-}
-if(_1fa.styleSheet){
-_1fa.styleSheet.cssText=_1f7;
-}else{
-var _1fc=doc.createTextNode(_1f7);
-_1fa.appendChild(_1fc);
-}
-return _1fa;
-};
-dojo.html.fixPathsInCssText=function(_1fd,URI){
-function iefixPathsInCssText(){
-var _1ff=/AlphaImageLoader\(src\=['"]([\t\s\w()\/.\\'"-:#=&?~]*)['"]/;
-while(_200=_1ff.exec(_1fd)){
-url=_200[1].replace(_202,"$2");
-if(!_203.exec(url)){
-url=(new dojo.uri.Uri(URI,url).toString());
-}
-str+=_1fd.substring(0,_200.index)+"AlphaImageLoader(src='"+url+"'";
-_1fd=_1fd.substr(_200.index+_200[0].length);
-}
-return str+_1fd;
-}
-if(!_1fd||!URI){
-return;
-}
-var _200,str="",url="";
-var _205=/url\(\s*([\t\s\w()\/.\\'"-:#=&?]+)\s*\)/;
-var _203=/(file|https?|ftps?):\/\//;
-var _202=/^[\s]*(['"]?)([\w()\/.\\'"-:#=&?]*)\1[\s]*?$/;
-if(dojo.render.html.ie55||dojo.render.html.ie60){
-_1fd=iefixPathsInCssText();
-}
-while(_200=_205.exec(_1fd)){
-url=_200[1].replace(_202,"$2");
-if(!_203.exec(url)){
-url=(new dojo.uri.Uri(URI,url).toString());
-}
-str+=_1fd.substring(0,_200.index)+"url("+url+")";
-_1fd=_1fd.substr(_200.index+_200[0].length);
-}
-return str+_1fd;
-};
-dojo.html.setActiveStyleSheet=function(_206){
-var i=0,a,els=dojo.doc().getElementsByTagName("link");
-while(a=els[i++]){
-if(a.getAttribute("rel").indexOf("style")!=-1&&a.getAttribute("title")){
-a.disabled=true;
-if(a.getAttribute("title")==_206){
-a.disabled=false;
-}
-}
-}
-};
-dojo.html.getActiveStyleSheet=function(){
-var i=0,a,els=dojo.doc().getElementsByTagName("link");
-while(a=els[i++]){
-if(a.getAttribute("rel").indexOf("style")!=-1&&a.getAttribute("title")&&!a.disabled){
-return a.getAttribute("title");
-}
-}
-return null;
-};
-dojo.html.getPreferredStyleSheet=function(){
-var i=0,a,els=dojo.doc().getElementsByTagName("link");
-while(a=els[i++]){
-if(a.getAttribute("rel").indexOf("style")!=-1&&a.getAttribute("rel").indexOf("alt")==-1&&a.getAttribute("title")){
-return a.getAttribute("title");
-}
-}
-return null;
-};
-dojo.html.applyBrowserClass=function(node){
-var drh=dojo.render.html;
-var _212={dj_ie:drh.ie,dj_ie55:drh.ie55,dj_ie6:drh.ie60,dj_ie7:drh.ie70,dj_iequirks:drh.ie&&drh.quirks,dj_opera:drh.opera,dj_opera8:drh.opera&&(Math.floor(dojo.render.version)==8),dj_opera9:drh.opera&&(Math.floor(dojo.render.version)==9),dj_khtml:drh.khtml,dj_safari:drh.safari,dj_gecko:drh.mozilla};
-for(var p in _212){
-if(_212[p]){
-dojo.html.addClass(node,p);
-}
-}
-};
-dojo.provide("dojo.html.*");
-dojo.provide("dojo.html.display");
-dojo.html._toggle=function(node,_215,_216){
-node=dojo.byId(node);
-_216(node,!_215(node));
-return _215(node);
-};
-dojo.html.show=function(node){
-node=dojo.byId(node);
-if(dojo.html.getStyleProperty(node,"display")=="none"){
-dojo.html.setStyle(node,"display",(node.dojoDisplayCache||""));
-node.dojoDisplayCache=undefined;
-}
-};
-dojo.html.hide=function(node){
-node=dojo.byId(node);
-if(typeof node["dojoDisplayCache"]=="undefined"){
-var d=dojo.html.getStyleProperty(node,"display");
-if(d!="none"){
-node.dojoDisplayCache=d;
-}
-}
-dojo.html.setStyle(node,"display","none");
-};
-dojo.html.setShowing=function(node,_21b){
-dojo.html[(_21b?"show":"hide")](node);
-};
-dojo.html.isShowing=function(node){
-return (dojo.html.getStyleProperty(node,"display")!="none");
-};
-dojo.html.toggleShowing=function(node){
-return dojo.html._toggle(node,dojo.html.isShowing,dojo.html.setShowing);
-};
-dojo.html.displayMap={tr:"",td:"",th:"",img:"inline",span:"inline",input:"inline",button:"inline"};
-dojo.html.suggestDisplayByTagName=function(node){
-node=dojo.byId(node);
-if(node&&node.tagName){
-var tag=node.tagName.toLowerCase();
-return (tag in dojo.html.displayMap?dojo.html.displayMap[tag]:"block");
-}
-};
-dojo.html.setDisplay=function(node,_221){
-dojo.html.setStyle(node,"display",((_221 instanceof String||typeof _221=="string")?_221:(_221?dojo.html.suggestDisplayByTagName(node):"none")));
-};
-dojo.html.isDisplayed=function(node){
-return (dojo.html.getComputedStyle(node,"display")!="none");
-};
-dojo.html.toggleDisplay=function(node){
-return dojo.html._toggle(node,dojo.html.isDisplayed,dojo.html.setDisplay);
-};
-dojo.html.setVisibility=function(node,_225){
-dojo.html.setStyle(node,"visibility",((_225 instanceof String||typeof _225=="string")?_225:(_225?"visible":"hidden")));
-};
-dojo.html.isVisible=function(node){
-return (dojo.html.getComputedStyle(node,"visibility")!="hidden");
-};
-dojo.html.toggleVisibility=function(node){
-return dojo.html._toggle(node,dojo.html.isVisible,dojo.html.setVisibility);
-};
-dojo.html.setOpacity=function(node,_229,_22a){
-node=dojo.byId(node);
-var h=dojo.render.html;
-if(!_22a){
-if(_229>=1){
-if(h.ie){
-dojo.html.clearOpacity(node);
-return;
-}else{
-_229=0.999999;
-}
-}else{
-if(_229<0){
-_229=0;
-}
-}
-}
-if(h.ie){
-if(node.nodeName.toLowerCase()=="tr"){
-var tds=node.getElementsByTagName("td");
-for(var x=0;x<tds.length;x++){
-tds[x].style.filter="Alpha(Opacity="+_229*100+")";
-}
-}
-node.style.filter="Alpha(Opacity="+_229*100+")";
-}else{
-if(h.moz){
-node.style.opacity=_229;
-node.style.MozOpacity=_229;
-}else{
-if(h.safari){
-node.style.opacity=_229;
-node.style.KhtmlOpacity=_229;
-}else{
-node.style.opacity=_229;
-}
-}
-}
-};
-dojo.html.clearOpacity=function(node){
-node=dojo.byId(node);
-var ns=node.style;
-var h=dojo.render.html;
-if(h.ie){
-try{
-if(node.filters&&node.filters.alpha){
-ns.filter="";
-}
-}
-catch(e){
-}
-}else{
-if(h.moz){
-ns.opacity=1;
-ns.MozOpacity=1;
-}else{
-if(h.safari){
-ns.opacity=1;
-ns.KhtmlOpacity=1;
-}else{
-ns.opacity=1;
-}
-}
-}
-};
-dojo.html.getOpacity=function(node){
-node=dojo.byId(node);
-var h=dojo.render.html;
-if(h.ie){
-var opac=(node.filters&&node.filters.alpha&&typeof node.filters.alpha.opacity=="number"?node.filters.alpha.opacity:100)/100;
-}else{
-var opac=node.style.opacity||node.style.MozOpacity||node.style.KhtmlOpacity||1;
-}
-return opac>=0.999999?1:Number(opac);
-};
-dojo.provide("dojo.html.layout");
-dojo.html.sumAncestorProperties=function(node,prop){
-node=dojo.byId(node);
-if(!node){
-return 0;
-}
-var _236=0;
-while(node){
-if(dojo.html.getComputedStyle(node,"position")=="fixed"){
-return 0;
-}
-var val=node[prop];
-if(val){
-_236+=val-0;
-if(node==dojo.body()){
-break;
-}
-}
-node=node.parentNode;
-}
-return _236;
-};
-dojo.html.setStyleAttributes=function(node,_239){
-node=dojo.byId(node);
-var _23a=_239.replace(/(;)?\s*$/,"").split(";");
-for(var i=0;i<_23a.length;i++){
-var _23c=_23a[i].split(":");
-var name=_23c[0].replace(/\s*$/,"").replace(/^\s*/,"").toLowerCase();
-var _23e=_23c[1].replace(/\s*$/,"").replace(/^\s*/,"");
-switch(name){
-case "opacity":
-dojo.html.setOpacity(node,_23e);
-break;
-case "content-height":
-dojo.html.setContentBox(node,{height:_23e});
-break;
-case "content-width":
-dojo.html.setContentBox(node,{width:_23e});
-break;
-case "outer-height":
-dojo.html.setMarginBox(node,{height:_23e});
-break;
-case "outer-width":
-dojo.html.setMarginBox(node,{width:_23e});
-break;
-default:
-node.style[dojo.html.toCamelCase(name)]=_23e;
-}
-}
-};
-dojo.html.boxSizing={MARGIN_BOX:"margin-box",BORDER_BOX:"border-box",PADDING_BOX:"padding-box",CONTENT_BOX:"content-box"};
-dojo.html.getAbsolutePosition=dojo.html.abs=function(node,_240,_241){
-node=dojo.byId(node,node.ownerDocument);
-var ret={x:0,y:0};
-var bs=dojo.html.boxSizing;
-if(!_241){
-_241=bs.CONTENT_BOX;
-}
-var _244=2;
-var _245;
-switch(_241){
-case bs.MARGIN_BOX:
-_245=3;
-break;
-case bs.BORDER_BOX:
-_245=2;
-break;
-case bs.PADDING_BOX:
-default:
-_245=1;
-break;
-case bs.CONTENT_BOX:
-_245=0;
-break;
-}
-var h=dojo.render.html;
-var db=document["body"]||document["documentElement"];
-if(h.ie){
-with(node.getBoundingClientRect()){
-ret.x=left-2;
-ret.y=top-2;
-}
-}else{
-if(document.getBoxObjectFor){
-_244=1;
-try{
-var bo=document.getBoxObjectFor(node);
-ret.x=bo.x-dojo.html.sumAncestorProperties(node,"scrollLeft");
-ret.y=bo.y-dojo.html.sumAncestorProperties(node,"scrollTop");
-}
-catch(e){
-}
-}else{
-if(node["offsetParent"]){
-var _249;
-if((h.safari)&&(node.style.getPropertyValue("position")=="absolute")&&(node.parentNode==db)){
-_249=db;
-}else{
-_249=db.parentNode;
-}
-if(node.parentNode!=db){
-var nd=node;
-if(dojo.render.html.opera){
-nd=db;
-}
-ret.x-=dojo.html.sumAncestorProperties(nd,"scrollLeft");
-ret.y-=dojo.html.sumAncestorProperties(nd,"scrollTop");
-}
-var _24b=node;
-do{
-var n=_24b["offsetLeft"];
-if(!h.opera||n>0){
-ret.x+=isNaN(n)?0:n;
-}
-var m=_24b["offsetTop"];
-ret.y+=isNaN(m)?0:m;
-_24b=_24b.offsetParent;
-}while((_24b!=_249)&&(_24b!=null));
-}else{
-if(node["x"]&&node["y"]){
-ret.x+=isNaN(node.x)?0:node.x;
-ret.y+=isNaN(node.y)?0:node.y;
-}
-}
-}
-}
-if(_240){
-var _24e=dojo.html.getScroll();
-ret.y+=_24e.top;
-ret.x+=_24e.left;
-}
-var _24f=[dojo.html.getPaddingExtent,dojo.html.getBorderExtent,dojo.html.getMarginExtent];
-if(_244>_245){
-for(var i=_245;i<_244;++i){
-ret.y+=_24f[i](node,"top");
-ret.x+=_24f[i](node,"left");
-}
-}else{
-if(_244<_245){
-for(var i=_245;i>_244;--i){
-ret.y-=_24f[i-1](node,"top");
-ret.x-=_24f[i-1](node,"left");
-}
-}
-}
-ret.top=ret.y;
-ret.left=ret.x;
-return ret;
-};
-dojo.html.isPositionAbsolute=function(node){
-return (dojo.html.getComputedStyle(node,"position")=="absolute");
-};
-dojo.html._sumPixelValues=function(node,_253,_254){
-var _255=0;
-for(var x=0;x<_253.length;x++){
-_255+=dojo.html.getPixelValue(node,_253[x],_254);
-}
-return _255;
-};
-dojo.html.getMargin=function(node){
-return {width:dojo.html._sumPixelValues(node,["margin-left","margin-right"],(dojo.html.getComputedStyle(node,"position")=="absolute")),height:dojo.html._sumPixelValues(node,["margin-top","margin-bottom"],(dojo.html.getComputedStyle(node,"position")=="absolute"))};
-};
-dojo.html.getBorder=function(node){
-return {width:dojo.html.getBorderExtent(node,"left")+dojo.html.getBorderExtent(node,"right"),height:dojo.html.getBorderExtent(node,"top")+dojo.html.getBorderExtent(node,"bottom")};
-};
-dojo.html.getBorderExtent=function(node,side){
-return (dojo.html.getStyle(node,"border-"+side+"-style")=="none"?0:dojo.html.getPixelValue(node,"border-"+side+"-width"));
-};
-dojo.html.getMarginExtent=function(node,side){
-return dojo.html._sumPixelValues(node,["margin-"+side],dojo.html.isPositionAbsolute(node));
-};
-dojo.html.getPaddingExtent=function(node,side){
-return dojo.html._sumPixelValues(node,["padding-"+side],true);
-};
-dojo.html.getPadding=function(node){
-return {width:dojo.html._sumPixelValues(node,["padding-left","padding-right"],true),height:dojo.html._sumPixelValues(node,["padding-top","padding-bottom"],true)};
-};
-dojo.html.getPadBorder=function(node){
-var pad=dojo.html.getPadding(node);
-var _262=dojo.html.getBorder(node);
-return {width:pad.width+_262.width,height:pad.height+_262.height};
-};
-dojo.html.getBoxSizing=function(node){
-var h=dojo.render.html;
-var bs=dojo.html.boxSizing;
-if((h.ie)||(h.opera)){
-var cm=document["compatMode"];
-if((cm=="BackCompat")||(cm=="QuirksMode")){
-return bs.BORDER_BOX;
-}else{
-return bs.CONTENT_BOX;
-}
-}else{
-if(arguments.length==0){
-node=document.documentElement;
-}
-var _267=dojo.html.getStyle(node,"-moz-box-sizing");
-if(!_267){
-_267=dojo.html.getStyle(node,"box-sizing");
-}
-return (_267?_267:bs.CONTENT_BOX);
-}
-};
-dojo.html.isBorderBox=function(node){
-return (dojo.html.getBoxSizing(node)==dojo.html.boxSizing.BORDER_BOX);
-};
-dojo.html.getBorderBox=function(node){
-node=dojo.byId(node);
-return {width:node.offsetWidth,height:node.offsetHeight};
-};
-dojo.html.getPaddingBox=function(node){
-var box=dojo.html.getBorderBox(node);
-var _26c=dojo.html.getBorder(node);
-return {width:box.width-_26c.width,height:box.height-_26c.height};
-};
-dojo.html.getContentBox=function(node){
-node=dojo.byId(node);
-var _26e=dojo.html.getPadBorder(node);
-return {width:node.offsetWidth-_26e.width,height:node.offsetHeight-_26e.height};
-};
-dojo.html.setContentBox=function(node,args){
-node=dojo.byId(node);
-var _271=0;
-var _272=0;
-var isbb=dojo.html.isBorderBox(node);
-var _274=(isbb?dojo.html.getPadBorder(node):{width:0,height:0});
-var ret={};
-if(typeof args.width!="undefined"){
-_271=args.width+_274.width;
-ret.width=dojo.html.setPositivePixelValue(node,"width",_271);
-}
-if(typeof args.height!="undefined"){
-_272=args.height+_274.height;
-ret.height=dojo.html.setPositivePixelValue(node,"height",_272);
-}
-return ret;
-};
-dojo.html.getMarginBox=function(node){
-var _277=dojo.html.getBorderBox(node);
-var _278=dojo.html.getMargin(node);
-return {width:_277.width+_278.width,height:_277.height+_278.height};
-};
-dojo.html.setMarginBox=function(node,args){
-node=dojo.byId(node);
-var _27b=0;
-var _27c=0;
-var isbb=dojo.html.isBorderBox(node);
-var _27e=(!isbb?dojo.html.getPadBorder(node):{width:0,height:0});
-var _27f=dojo.html.getMargin(node);
-var ret={};
-if(typeof args.width!="undefined"){
-_27b=args.width-_27e.width;
-_27b-=_27f.width;
-ret.width=dojo.html.setPositivePixelValue(node,"width",_27b);
-}
-if(typeof args.height!="undefined"){
-_27c=args.height-_27e.height;
-_27c-=_27f.height;
-ret.height=dojo.html.setPositivePixelValue(node,"height",_27c);
-}
-return ret;
-};
-dojo.html.getElementBox=function(node,type){
-var bs=dojo.html.boxSizing;
-switch(type){
-case bs.MARGIN_BOX:
-return dojo.html.getMarginBox(node);
-case bs.BORDER_BOX:
-return dojo.html.getBorderBox(node);
-case bs.PADDING_BOX:
-return dojo.html.getPaddingBox(node);
-case bs.CONTENT_BOX:
-default:
-return dojo.html.getContentBox(node);
-}
-};
-dojo.html.toCoordinateObject=dojo.html.toCoordinateArray=function(_284,_285,_286){
-if(_284 instanceof Array||typeof _284=="array"){
-dojo.deprecated("dojo.html.toCoordinateArray","use dojo.html.toCoordinateObject({left: , top: , width: , height: }) instead","0.5");
-while(_284.length<4){
-_284.push(0);
-}
-while(_284.length>4){
-_284.pop();
-}
-var ret={left:_284[0],top:_284[1],width:_284[2],height:_284[3]};
-}else{
-if(!_284.nodeType&&!(_284 instanceof String||typeof _284=="string")&&("width" in _284||"height" in _284||"left" in _284||"x" in _284||"top" in _284||"y" in _284)){
-var ret={left:_284.left||_284.x||0,top:_284.top||_284.y||0,width:_284.width||0,height:_284.height||0};
-}else{
-var node=dojo.byId(_284);
-var pos=dojo.html.abs(node,_285,_286);
-var _28a=dojo.html.getMarginBox(node);
-var ret={left:pos.left,top:pos.top,width:_28a.width,height:_28a.height};
-}
-}
-ret.x=ret.left;
-ret.y=ret.top;
-return ret;
-};
-dojo.html.setMarginBoxWidth=dojo.html.setOuterWidth=function(node,_28c){
-return dojo.html._callDeprecated("setMarginBoxWidth","setMarginBox",arguments,"width");
-};
-dojo.html.setMarginBoxHeight=dojo.html.setOuterHeight=function(){
-return dojo.html._callDeprecated("setMarginBoxHeight","setMarginBox",arguments,"height");
-};
-dojo.html.getMarginBoxWidth=dojo.html.getOuterWidth=function(){
-return dojo.html._callDeprecated("getMarginBoxWidth","getMarginBox",arguments,null,"width");
-};
-dojo.html.getMarginBoxHeight=dojo.html.getOuterHeight=function(){
-return dojo.html._callDeprecated("getMarginBoxHeight","getMarginBox",arguments,null,"height");
-};
-dojo.html.getTotalOffset=function(node,type,_28f){
-return dojo.html._callDeprecated("getTotalOffset","getAbsolutePosition",arguments,null,type);
-};
-dojo.html.getAbsoluteX=function(node,_291){
-return dojo.html._callDeprecated("getAbsoluteX","getAbsolutePosition",arguments,null,"x");
-};
-dojo.html.getAbsoluteY=function(node,_293){
-return dojo.html._callDeprecated("getAbsoluteY","getAbsolutePosition",arguments,null,"y");
-};
-dojo.html.totalOffsetLeft=function(node,_295){
-return dojo.html._callDeprecated("totalOffsetLeft","getAbsolutePosition",arguments,null,"left");
-};
-dojo.html.totalOffsetTop=function(node,_297){
-return dojo.html._callDeprecated("totalOffsetTop","getAbsolutePosition",arguments,null,"top");
-};
-dojo.html.getMarginWidth=function(node){
-return dojo.html._callDeprecated("getMarginWidth","getMargin",arguments,null,"width");
-};
-dojo.html.getMarginHeight=function(node){
-return dojo.html._callDeprecated("getMarginHeight","getMargin",arguments,null,"height");
-};
-dojo.html.getBorderWidth=function(node){
-return dojo.html._callDeprecated("getBorderWidth","getBorder",arguments,null,"width");
-};
-dojo.html.getBorderHeight=function(node){
-return dojo.html._callDeprecated("getBorderHeight","getBorder",arguments,null,"height");
-};
-dojo.html.getPaddingWidth=function(node){
-return dojo.html._callDeprecated("getPaddingWidth","getPadding",arguments,null,"width");
-};
-dojo.html.getPaddingHeight=function(node){
-return dojo.html._callDeprecated("getPaddingHeight","getPadding",arguments,null,"height");
-};
-dojo.html.getPadBorderWidth=function(node){
-return dojo.html._callDeprecated("getPadBorderWidth","getPadBorder",arguments,null,"width");
-};
-dojo.html.getPadBorderHeight=function(node){
-return dojo.html._callDeprecated("getPadBorderHeight","getPadBorder",arguments,null,"height");
-};
-dojo.html.getBorderBoxWidth=dojo.html.getInnerWidth=function(){
-return dojo.html._callDeprecated("getBorderBoxWidth","getBorderBox",arguments,null,"width");
-};
-dojo.html.getBorderBoxHeight=dojo.html.getInnerHeight=function(){
-return dojo.html._callDeprecated("getBorderBoxHeight","getBorderBox",arguments,null,"height");
-};
-dojo.html.getContentBoxWidth=dojo.html.getContentWidth=function(){
-return dojo.html._callDeprecated("getContentBoxWidth","getContentBox",arguments,null,"width");
-};
-dojo.html.getContentBoxHeight=dojo.html.getContentHeight=function(){
-return dojo.html._callDeprecated("getContentBoxHeight","getContentBox",arguments,null,"height");
-};
-dojo.html.setContentBoxWidth=dojo.html.setContentWidth=function(node,_2a1){
-return dojo.html._callDeprecated("setContentBoxWidth","setContentBox",arguments,"width");
-};
-dojo.html.setContentBoxHeight=dojo.html.setContentHeight=function(node,_2a3){
-return dojo.html._callDeprecated("setContentBoxHeight","setContentBox",arguments,"height");
-};
-dojo.provide("dojo.html.util");
-dojo.html.getElementWindow=function(_2a4){
-return dojo.html.getDocumentWindow(_2a4.ownerDocument);
-};
-dojo.html.getDocumentWindow=function(doc){
-if(dojo.render.html.safari&&!doc._parentWindow){
-var fix=function(win){
-win.document._parentWindow=win;
-for(var i=0;i<win.frames.length;i++){
-fix(win.frames[i]);
-}
-};
-fix(window.top);
-}
-if(dojo.render.html.ie&&window!==document.parentWindow&&!doc._parentWindow){
-doc.parentWindow.execScript("document._parentWindow = window;","Javascript");
-var win=doc._parentWindow;
-doc._parentWindow=null;
-return win;
-}
-return doc._parentWindow||doc.parentWindow||doc.defaultView;
-};
-dojo.html.gravity=function(node,e){
-node=dojo.byId(node);
-var _2ac=dojo.html.getCursorPosition(e);
-with(dojo.html){
-var _2ad=getAbsolutePosition(node,true);
-var bb=getBorderBox(node);
-var _2af=_2ad.x+(bb.width/2);
-var _2b0=_2ad.y+(bb.height/2);
-}
-with(dojo.html.gravity){
-return ((_2ac.x<_2af?WEST:EAST)|(_2ac.y<_2b0?NORTH:SOUTH));
-}
-};
-dojo.html.gravity.NORTH=1;
-dojo.html.gravity.SOUTH=1<<1;
-dojo.html.gravity.EAST=1<<2;
-dojo.html.gravity.WEST=1<<3;
-dojo.html.overElement=function(_2b1,e){
-_2b1=dojo.byId(_2b1);
-var _2b3=dojo.html.getCursorPosition(e);
-var bb=dojo.html.getBorderBox(_2b1);
-var _2b5=dojo.html.getAbsolutePosition(_2b1,true,dojo.html.boxSizing.BORDER_BOX);
-var top=_2b5.y;
-var _2b7=top+bb.height;
-var left=_2b5.x;
-var _2b9=left+bb.width;
-return (_2b3.x>=left&&_2b3.x<=_2b9&&_2b3.y>=top&&_2b3.y<=_2b7);
-};
-dojo.html.renderedTextContent=function(node){
-node=dojo.byId(node);
-var _2bb="";
-if(node==null){
-return _2bb;
-}
-for(var i=0;i<node.childNodes.length;i++){
-switch(node.childNodes[i].nodeType){
-case 1:
-case 5:
-var _2bd="unknown";
-try{
-_2bd=dojo.html.getStyle(node.childNodes[i],"display");
-}
-catch(E){
-}
-switch(_2bd){
-case "block":
-case "list-item":
-case "run-in":
-case "table":
-case "table-row-group":
-case "table-header-group":
-case "table-footer-group":
-case "table-row":
-case "table-column-group":
-case "table-column":
-case "table-cell":
-case "table-caption":
-_2bb+="\n";
-_2bb+=dojo.html.renderedTextContent(node.childNodes[i]);
-_2bb+="\n";
-break;
-case "none":
-break;
-default:
-if(node.childNodes[i].tagName&&node.childNodes[i].tagName.toLowerCase()=="br"){
-_2bb+="\n";
-}else{
-_2bb+=dojo.html.renderedTextContent(node.childNodes[i]);
-}
-break;
-}
-break;
-case 3:
-case 2:
-case 4:
-var text=node.childNodes[i].nodeValue;
-var _2bf="unknown";
-try{
-_2bf=dojo.html.getStyle(node,"text-transform");
-}
-catch(E){
-}
-switch(_2bf){
-case "capitalize":
-var _2c0=text.split(" ");
-for(var i=0;i<_2c0.length;i++){
-_2c0[i]=_2c0[i].charAt(0).toUpperCase()+_2c0[i].substring(1);
-}
-text=_2c0.join(" ");
-break;
-case "uppercase":
-text=text.toUpperCase();
-break;
-case "lowercase":
-text=text.toLowerCase();
-break;
-default:
-break;
-}
-switch(_2bf){
-case "nowrap":
-break;
-case "pre-wrap":
-break;
-case "pre-line":
-break;
-case "pre":
-break;
-default:
-text=text.replace(/\s+/," ");
-if(/\s$/.test(_2bb)){
-text.replace(/^\s/,"");
-}
-break;
-}
-_2bb+=text;
-break;
-default:
-break;
-}
-}
-return _2bb;
-};
-dojo.html.createNodesFromText=function(txt,trim){
-if(trim){
-txt=txt.replace(/^\s+|\s+$/g,"");
-}
-var tn=dojo.doc().createElement("div");
-tn.style.visibility="hidden";
-dojo.body().appendChild(tn);
-var _2c4="none";
-if((/^<t[dh][\s\r\n>]/i).test(txt.replace(/^\s+/))){
-txt="<table><tbody><tr>"+txt+"</tr></tbody></table>";
-_2c4="cell";
-}else{
-if((/^<tr[\s\r\n>]/i).test(txt.replace(/^\s+/))){
-txt="<table><tbody>"+txt+"</tbody></table>";
-_2c4="row";
-}else{
-if((/^<(thead|tbody|tfoot)[\s\r\n>]/i).test(txt.replace(/^\s+/))){
-txt="<table>"+txt+"</table>";
-_2c4="section";
-}
-}
-}
-tn.innerHTML=txt;
-if(tn["normalize"]){
-tn.normalize();
-}
-var _2c5=null;
-switch(_2c4){
-case "cell":
-_2c5=tn.getElementsByTagName("tr")[0];
-break;
-case "row":
-_2c5=tn.getElementsByTagName("tbody")[0];
-break;
-case "section":
-_2c5=tn.getElementsByTagName("table")[0];
-break;
-default:
-_2c5=tn;
-break;
-}
-var _2c6=[];
-for(var x=0;x<_2c5.childNodes.length;x++){
-_2c6.push(_2c5.childNodes[x].cloneNode(true));
-}
-tn.style.display="none";
-dojo.body().removeChild(tn);
-return _2c6;
-};
-dojo.html.placeOnScreen=function(node,_2c9,_2ca,_2cb,_2cc,_2cd,_2ce){
-if(_2c9 instanceof Array||typeof _2c9=="array"){
-_2ce=_2cd;
-_2cd=_2cc;
-_2cc=_2cb;
-_2cb=_2ca;
-_2ca=_2c9[1];
-_2c9=_2c9[0];
-}
-if(_2cd instanceof String||typeof _2cd=="string"){
-_2cd=_2cd.split(",");
-}
-if(!isNaN(_2cb)){
-_2cb=[Number(_2cb),Number(_2cb)];
-}else{
-if(!(_2cb instanceof Array||typeof _2cb=="array")){
-_2cb=[0,0];
-}
-}
-var _2cf=dojo.html.getScroll().offset;
-var view=dojo.html.getViewport();
-node=dojo.byId(node);
-var _2d1=node.style.display;
-node.style.display="";
-var bb=dojo.html.getBorderBox(node);
-var w=bb.width;
-var h=bb.height;
-node.style.display=_2d1;
-if(!(_2cd instanceof Array||typeof _2cd=="array")){
-_2cd=["TL"];
-}
-var _2d5,_2d6,_2d7=Infinity,_2d8;
-for(var _2d9=0;_2d9<_2cd.length;++_2d9){
-var _2da=_2cd[_2d9];
-var _2db=true;
-var tryX=_2c9-(_2da.charAt(1)=="L"?0:w)+_2cb[0]*(_2da.charAt(1)=="L"?1:-1);
-var tryY=_2ca-(_2da.charAt(0)=="T"?0:h)+_2cb[1]*(_2da.charAt(0)=="T"?1:-1);
-if(_2cc){
-tryX-=_2cf.x;
-tryY-=_2cf.y;
-}
-if(tryX<0){
-tryX=0;
-_2db=false;
-}
-if(tryY<0){
-tryY=0;
-_2db=false;
-}
-var x=tryX+w;
-if(x>view.width){
-x=view.width-w;
-_2db=false;
-}else{
-x=tryX;
-}
-x=Math.max(_2cb[0],x)+_2cf.x;
-var y=tryY+h;
-if(y>view.height){
-y=view.height-h;
-_2db=false;
-}else{
-y=tryY;
-}
-y=Math.max(_2cb[1],y)+_2cf.y;
-if(_2db){
-_2d5=x;
-_2d6=y;
-_2d7=0;
-_2d8=_2da;
-break;
-}else{
-var dist=Math.pow(x-tryX-_2cf.x,2)+Math.pow(y-tryY-_2cf.y,2);
-if(_2d7>dist){
-_2d7=dist;
-_2d5=x;
-_2d6=y;
-_2d8=_2da;
-}
-}
-}
-if(!_2ce){
-node.style.left=_2d5+"px";
-node.style.top=_2d6+"px";
-}
-return {left:_2d5,top:_2d6,x:_2d5,y:_2d6,dist:_2d7,corner:_2d8};
-};
-dojo.html.placeOnScreenPoint=function(node,_2e2,_2e3,_2e4,_2e5){
-dojo.deprecated("dojo.html.placeOnScreenPoint","use dojo.html.placeOnScreen() instead","0.5");
-return dojo.html.placeOnScreen(node,_2e2,_2e3,_2e4,_2e5,["TL","TR","BL","BR"]);
-};
-dojo.html.placeOnScreenAroundElement=function(node,_2e7,_2e8,_2e9,_2ea,_2eb){
-var best,_2ed=Infinity;
-_2e7=dojo.byId(_2e7);
-var _2ee=_2e7.style.display;
-_2e7.style.display="";
-var mb=dojo.html.getElementBox(_2e7,_2e9);
-var _2f0=mb.width;
-var _2f1=mb.height;
-var _2f2=dojo.html.getAbsolutePosition(_2e7,true,_2e9);
-_2e7.style.display=_2ee;
-for(var _2f3 in _2ea){
-var pos,_2f5,_2f6;
-var _2f7=_2ea[_2f3];
-_2f5=_2f2.x+(_2f3.charAt(1)=="L"?0:_2f0);
-_2f6=_2f2.y+(_2f3.charAt(0)=="T"?0:_2f1);
-pos=dojo.html.placeOnScreen(node,_2f5,_2f6,_2e8,true,_2f7,true);
-if(pos.dist==0){
-best=pos;
-break;
-}else{
-if(_2ed>pos.dist){
-_2ed=pos.dist;
-best=pos;
-}
-}
-}
-if(!_2eb){
-node.style.left=best.left+"px";
-node.style.top=best.top+"px";
-}
-return best;
-};
-dojo.html.scrollIntoView=function(node){
-if(!node){
-return;
-}
-if(dojo.render.html.ie){
-if(dojo.html.getBorderBox(node.parentNode).height<node.parentNode.scrollHeight){
-node.scrollIntoView(false);
-}
-}else{
-if(dojo.render.html.mozilla){
-node.scrollIntoView(false);
-}else{
-var _2f9=node.parentNode;
-var _2fa=_2f9.scrollTop+dojo.html.getBorderBox(_2f9).height;
-var _2fb=node.offsetTop+dojo.html.getMarginBox(node).height;
-if(_2fa<_2fb){
-_2f9.scrollTop+=(_2fb-_2fa);
-}else{
-if(_2f9.scrollTop>node.offsetTop){
-_2f9.scrollTop-=(_2f9.scrollTop-node.offsetTop);
-}
-}
-}
-}
-};
-dojo.provide("dojo.lang.array");
-dojo.lang.has=function(obj,name){
-try{
-return typeof obj[name]!="undefined";
-}
-catch(e){
-return false;
-}
-};
-dojo.lang.isEmpty=function(obj){
-if(dojo.lang.isObject(obj)){
-var tmp={};
-var _300=0;
-for(var x in obj){
-if(obj[x]&&(!tmp[x])){
-_300++;
-break;
-}
-}
-return _300==0;
-}else{
-if(dojo.lang.isArrayLike(obj)||dojo.lang.isString(obj)){
-return obj.length==0;
-}
-}
-};
-dojo.lang.map=function(arr,obj,_304){
-var _305=dojo.lang.isString(arr);
-if(_305){
-arr=arr.split("");
-}
-if(dojo.lang.isFunction(obj)&&(!_304)){
-_304=obj;
-obj=dj_global;
-}else{
-if(dojo.lang.isFunction(obj)&&_304){
-var _306=obj;
-obj=_304;
-_304=_306;
-}
-}
-if(Array.map){
-var _307=Array.map(arr,_304,obj);
-}else{
-var _307=[];
-for(var i=0;i<arr.length;++i){
-_307.push(_304.call(obj,arr[i]));
-}
-}
-if(_305){
-return _307.join("");
-}else{
-return _307;
-}
-};
-dojo.lang.reduce=function(arr,_30a,obj,_30c){
-var _30d=_30a;
-var ob=obj?obj:dj_global;
-dojo.lang.map(arr,function(val){
-_30d=_30c.call(ob,_30d,val);
-});
-return _30d;
-};
-dojo.lang.forEach=function(_310,_311,_312){
-if(dojo.lang.isString(_310)){
-_310=_310.split("");
-}
-if(Array.forEach){
-Array.forEach(_310,_311,_312);
-}else{
-if(!_312){
-_312=dj_global;
-}
-for(var i=0,l=_310.length;i<l;i++){
-_311.call(_312,_310[i],i,_310);
-}
-}
-};
-dojo.lang._everyOrSome=function(_315,arr,_317,_318){
-if(dojo.lang.isString(arr)){
-arr=arr.split("");
-}
-if(Array.every){
-return Array[_315?"every":"some"](arr,_317,_318);
-}else{
-if(!_318){
-_318=dj_global;
-}
-for(var i=0,l=arr.length;i<l;i++){
-var _31b=_317.call(_318,arr[i],i,arr);
-if(_315&&!_31b){
-return false;
-}else{
-if((!_315)&&(_31b)){
-return true;
-}
-}
-}
-return Boolean(_315);
-}
-};
-dojo.lang.every=function(arr,_31d,_31e){
-return this._everyOrSome(true,arr,_31d,_31e);
-};
-dojo.lang.some=function(arr,_320,_321){
-return this._everyOrSome(false,arr,_320,_321);
-};
-dojo.lang.filter=function(arr,_323,_324){
-var _325=dojo.lang.isString(arr);
-if(_325){
-arr=arr.split("");
-}
-var _326;
-if(Array.filter){
-_326=Array.filter(arr,_323,_324);
-}else{
-if(!_324){
-if(arguments.length>=3){
-dojo.raise("thisObject doesn't exist!");
-}
-_324=dj_global;
-}
-_326=[];
-for(var i=0;i<arr.length;i++){
-if(_323.call(_324,arr[i],i,arr)){
-_326.push(arr[i]);
-}
-}
-}
-if(_325){
-return _326.join("");
-}else{
-return _326;
-}
-};
-dojo.lang.unnest=function(){
-var out=[];
-for(var i=0;i<arguments.length;i++){
-if(dojo.lang.isArrayLike(arguments[i])){
-var add=dojo.lang.unnest.apply(this,arguments[i]);
-out=out.concat(add);
-}else{
-out.push(arguments[i]);
-}
-}
-return out;
-};
-dojo.lang.toArray=function(_32b,_32c){
-var _32d=[];
-for(var i=_32c||0;i<_32b.length;i++){
-_32d.push(_32b[i]);
-}
-return _32d;
-};
-dojo.provide("dojo.gfx.color");
-dojo.gfx.color.Color=function(r,g,b,a){
-if(dojo.lang.isArray(r)){
-this.r=r[0];
-this.g=r[1];
-this.b=r[2];
-this.a=r[3]||1;
-}else{
-if(dojo.lang.isString(r)){
-var rgb=dojo.gfx.color.extractRGB(r);
-this.r=rgb[0];
-this.g=rgb[1];
-this.b=rgb[2];
-this.a=g||1;
-}else{
-if(r instanceof dojo.gfx.color.Color){
-this.r=r.r;
-this.b=r.b;
-this.g=r.g;
-this.a=r.a;
-}else{
-this.r=r;
-this.g=g;
-this.b=b;
-this.a=a;
-}
-}
-}
-};
-dojo.gfx.color.Color.fromArray=function(arr){
-return new dojo.gfx.color.Color(arr[0],arr[1],arr[2],arr[3]);
-};
-dojo.extend(dojo.gfx.color.Color,{toRgb:function(_335){
-if(_335){
-return this.toRgba();
-}else{
-return [this.r,this.g,this.b];
-}
-},toRgba:function(){
-return [this.r,this.g,this.b,this.a];
-},toHex:function(){
-return dojo.gfx.color.rgb2hex(this.toRgb());
-},toCss:function(){
-return "rgb("+this.toRgb().join()+")";
-},toString:function(){
-return this.toHex();
-},blend:function(_336,_337){
-var rgb=null;
-if(dojo.lang.isArray(_336)){
-rgb=_336;
-}else{
-if(_336 instanceof dojo.gfx.color.Color){
-rgb=_336.toRgb();
-}else{
-rgb=new dojo.gfx.color.Color(_336).toRgb();
-}
-}
-return dojo.gfx.color.blend(this.toRgb(),rgb,_337);
-}});
-dojo.gfx.color.named={white:[255,255,255],black:[0,0,0],red:[255,0,0],green:[0,255,0],lime:[0,255,0],blue:[0,0,255],navy:[0,0,128],gray:[128,128,128],silver:[192,192,192]};
-dojo.gfx.color.blend=function(a,b,_33b){
-if(typeof a=="string"){
-return dojo.gfx.color.blendHex(a,b,_33b);
-}
-if(!_33b){
-_33b=0;
-}
-_33b=Math.min(Math.max(-1,_33b),1);
-_33b=((_33b+1)/2);
-var c=[];
-for(var x=0;x<3;x++){
-c[x]=parseInt(b[x]+((a[x]-b[x])*_33b));
-}
-return c;
-};
-dojo.gfx.color.blendHex=function(a,b,_340){
-return dojo.gfx.color.rgb2hex(dojo.gfx.color.blend(dojo.gfx.color.hex2rgb(a),dojo.gfx.color.hex2rgb(b),_340));
-};
-dojo.gfx.color.extractRGB=function(_341){
-var hex="0123456789abcdef";
-_341=_341.toLowerCase();
-if(_341.indexOf("rgb")==0){
-var _343=_341.match(/rgba*\((\d+), *(\d+), *(\d+)/i);
-var ret=_343.splice(1,3);
-return ret;
-}else{
-var _345=dojo.gfx.color.hex2rgb(_341);
-if(_345){
-return _345;
-}else{
-return dojo.gfx.color.named[_341]||[255,255,255];
-}
-}
-};
-dojo.gfx.color.hex2rgb=function(hex){
-var _347="0123456789ABCDEF";
-var rgb=new Array(3);
-if(hex.indexOf("#")==0){
-hex=hex.substring(1);
-}
-hex=hex.toUpperCase();
-if(hex.replace(new RegExp("["+_347+"]","g"),"")!=""){
-return null;
-}
-if(hex.length==3){
-rgb[0]=hex.charAt(0)+hex.charAt(0);
-rgb[1]=hex.charAt(1)+hex.charAt(1);
-rgb[2]=hex.charAt(2)+hex.charAt(2);
-}else{
-rgb[0]=hex.substring(0,2);
-rgb[1]=hex.substring(2,4);
-rgb[2]=hex.substring(4);
-}
-for(var i=0;i<rgb.length;i++){
-rgb[i]=_347.indexOf(rgb[i].charAt(0))*16+_347.indexOf(rgb[i].charAt(1));
-}
-return rgb;
-};
-dojo.gfx.color.rgb2hex=function(r,g,b){
-if(dojo.lang.isArray(r)){
-g=r[1]||0;
-b=r[2]||0;
-r=r[0]||0;
-}
-var ret=dojo.lang.map([r,g,b],function(x){
-x=new Number(x);
-var s=x.toString(16);
-while(s.length<2){
-s="0"+s;
-}
-return s;
-});
-ret.unshift("#");
-return ret.join("");
-};
-dojo.provide("dojo.lang.func");
-dojo.lang.hitch=function(_350,_351){
-var fcn=(dojo.lang.isString(_351)?_350[_351]:_351)||function(){
-};
-return function(){
-return fcn.apply(_350,arguments);
-};
-};
-dojo.lang.anonCtr=0;
-dojo.lang.anon={};
-dojo.lang.nameAnonFunc=function(_353,_354,_355){
-var nso=(_354||dojo.lang.anon);
-if((_355)||((dj_global["djConfig"])&&(djConfig["slowAnonFuncLookups"]==true))){
-for(var x in nso){
-try{
-if(nso[x]===_353){
-return x;
-}
-}
-catch(e){
-}
-}
-}
-var ret="__"+dojo.lang.anonCtr++;
-while(typeof nso[ret]!="undefined"){
-ret="__"+dojo.lang.anonCtr++;
-}
-nso[ret]=_353;
-return ret;
-};
-dojo.lang.forward=function(_359){
-return function(){
-return this[_359].apply(this,arguments);
-};
-};
-dojo.lang.curry=function(ns,func){
-var _35c=[];
-ns=ns||dj_global;
-if(dojo.lang.isString(func)){
-func=ns[func];
-}
-for(var x=2;x<arguments.length;x++){
-_35c.push(arguments[x]);
-}
-var _35e=(func["__preJoinArity"]||func.length)-_35c.length;
-function gather(_35f,_360,_361){
-var _362=_361;
-var _363=_360.slice(0);
-for(var x=0;x<_35f.length;x++){
-_363.push(_35f[x]);
-}
-_361=_361-_35f.length;
-if(_361<=0){
-var res=func.apply(ns,_363);
-_361=_362;
-return res;
-}else{
-return function(){
-return gather(arguments,_363,_361);
-};
-}
-}
-return gather([],_35c,_35e);
-};
-dojo.lang.curryArguments=function(ns,func,args,_369){
-var _36a=[];
-var x=_369||0;
-for(x=_369;x<args.length;x++){
-_36a.push(args[x]);
-}
-return dojo.lang.curry.apply(dojo.lang,[ns,func].concat(_36a));
-};
-dojo.lang.tryThese=function(){
-for(var x=0;x<arguments.length;x++){
-try{
-if(typeof arguments[x]=="function"){
-var ret=(arguments[x]());
-if(ret){
-return ret;
-}
-}
-}
-catch(e){
-dojo.debug(e);
-}
-}
-};
-dojo.lang.delayThese=function(farr,cb,_370,_371){
-if(!farr.length){
-if(typeof _371=="function"){
-_371();
-}
-return;
-}
-if((typeof _370=="undefined")&&(typeof cb=="number")){
-_370=cb;
-cb=function(){
-};
-}else{
-if(!cb){
-cb=function(){
-};
-if(!_370){
-_370=0;
-}
-}
-}
-setTimeout(function(){
-(farr.shift())();
-cb();
-dojo.lang.delayThese(farr,cb,_370,_371);
-},_370);
-};
-dojo.provide("dojo.lfx.Animation");
-dojo.lfx.Line=function(_372,end){
-this.start=_372;
-this.end=end;
-if(dojo.lang.isArray(_372)){
-var diff=[];
-dojo.lang.forEach(this.start,function(s,i){
-diff[i]=this.end[i]-s;
-},this);
-this.getValue=function(n){
-var res=[];
-dojo.lang.forEach(this.start,function(s,i){
-res[i]=(diff[i]*n)+s;
-},this);
-return res;
-};
-}else{
-var diff=end-_372;
-this.getValue=function(n){
-return (diff*n)+this.start;
-};
-}
-};
-dojo.lfx.easeDefault=function(n){
-if(dojo.render.html.khtml){
-return (parseFloat("0.5")+((Math.sin((n+parseFloat("1.5"))*Math.PI))/2));
-}else{
-return (0.5+((Math.sin((n+1.5)*Math.PI))/2));
-}
-};
-dojo.lfx.easeIn=function(n){
-return Math.pow(n,3);
-};
-dojo.lfx.easeOut=function(n){
-return (1-Math.pow(1-n,3));
-};
-dojo.lfx.easeInOut=function(n){
-return ((3*Math.pow(n,2))-(2*Math.pow(n,3)));
-};
-dojo.lfx.IAnimation=function(){
-};
-dojo.lang.extend(dojo.lfx.IAnimation,{curve:null,duration:1000,easing:null,repeatCount:0,rate:25,handler:null,beforeBegin:null,onBegin:null,onAnimate:null,onEnd:null,onPlay:null,onPause:null,onStop:null,play:null,pause:null,stop:null,connect:function(evt,_381,_382){
-if(!_382){
-_382=_381;
-_381=this;
-}
-_382=dojo.lang.hitch(_381,_382);
-var _383=this[evt]||function(){
-};
-this[evt]=function(){
-var ret=_383.apply(this,arguments);
-_382.apply(this,arguments);
-return ret;
-};
-return this;
-},fire:function(evt,args){
-if(this[evt]){
-this[evt].apply(this,(args||[]));
-}
-return this;
-},repeat:function(_387){
-this.repeatCount=_387;
-return this;
-},_active:false,_paused:false});
-dojo.lfx.Animation=function(_388,_389,_38a,_38b,_38c,rate){
-dojo.lfx.IAnimation.call(this);
-if(dojo.lang.isNumber(_388)||(!_388&&_389.getValue)){
-rate=_38c;
-_38c=_38b;
-_38b=_38a;
-_38a=_389;
-_389=_388;
-_388=null;
-}else{
-if(_388.getValue||dojo.lang.isArray(_388)){
-rate=_38b;
-_38c=_38a;
-_38b=_389;
-_38a=_388;
-_389=null;
-_388=null;
-}
-}
-if(dojo.lang.isArray(_38a)){
-this.curve=new dojo.lfx.Line(_38a[0],_38a[1]);
-}else{
-this.curve=_38a;
-}
-if(_389!=null&&_389>0){
-this.duration=_389;
-}
-if(_38c){
-this.repeatCount=_38c;
-}
-if(rate){
-this.rate=rate;
-}
-if(_388){
-dojo.lang.forEach(["handler","beforeBegin","onBegin","onEnd","onPlay","onStop","onAnimate"],function(item){
-if(_388[item]){
-this.connect(item,_388[item]);
-}
-},this);
-}
-if(_38b&&dojo.lang.isFunction(_38b)){
-this.easing=_38b;
-}
-};
-dojo.inherits(dojo.lfx.Animation,dojo.lfx.IAnimation);
-dojo.lang.extend(dojo.lfx.Animation,{_startTime:null,_endTime:null,_timer:null,_percent:0,_startRepeatCount:0,play:function(_38f,_390){
-if(_390){
-clearTimeout(this._timer);
-this._active=false;
-this._paused=false;
-this._percent=0;
-}else{
-if(this._active&&!this._paused){
-return this;
-}
-}
-this.fire("handler",["beforeBegin"]);
-this.fire("beforeBegin");
-if(_38f>0){
-setTimeout(dojo.lang.hitch(this,function(){
-this.play(null,_390);
-}),_38f);
-return this;
-}
-this._startTime=new Date().valueOf();
-if(this._paused){
-this._startTime-=(this.duration*this._percent/100);
-}
-this._endTime=this._startTime+this.duration;
-this._active=true;
-this._paused=false;
-var step=this._percent/100;
-var _392=this.curve.getValue(step);
-if(this._percent==0){
-if(!this._startRepeatCount){
-this._startRepeatCount=this.repeatCount;
-}
-this.fire("handler",["begin",_392]);
-this.fire("onBegin",[_392]);
-}
-this.fire("handler",["play",_392]);
-this.fire("onPlay",[_392]);
-this._cycle();
-return this;
-},pause:function(){
-clearTimeout(this._timer);
-if(!this._active){
-return this;
-}
-this._paused=true;
-var _393=this.curve.getValue(this._percent/100);
-this.fire("handler",["pause",_393]);
-this.fire("onPause",[_393]);
-return this;
-},gotoPercent:function(pct,_395){
-clearTimeout(this._timer);
-this._active=true;
-this._paused=true;
-this._percent=pct;
-if(_395){
-this.play();
-}
-return this;
-},stop:function(_396){
-clearTimeout(this._timer);
-var step=this._percent/100;
-if(_396){
-step=1;
-}
-var _398=this.curve.getValue(step);
-this.fire("handler",["stop",_398]);
-this.fire("onStop",[_398]);
-this._active=false;
-this._paused=false;
-return this;
-},status:function(){
-if(this._active){
-return this._paused?"paused":"playing";
-}else{
-return "stopped";
-}
-return this;
-},_cycle:function(){
-clearTimeout(this._timer);
-if(this._active){
-var curr=new Date().valueOf();
-var step=(curr-this._startTime)/(this._endTime-this._startTime);
-if(step>=1){
-step=1;
-this._percent=100;
-}else{
-this._percent=step*100;
-}
-if((this.easing)&&(dojo.lang.isFunction(this.easing))){
-step=this.easing(step);
-}
-var _39b=this.curve.getValue(step);
-this.fire("handler",["animate",_39b]);
-this.fire("onAnimate",[_39b]);
-if(step<1){
-this._timer=setTimeout(dojo.lang.hitch(this,"_cycle"),this.rate);
-}else{
-this._active=false;
-this.fire("handler",["end"]);
-this.fire("onEnd");
-if(this.repeatCount>0){
-this.repeatCount--;
-this.play(null,true);
-}else{
-if(this.repeatCount==-1){
-this.play(null,true);
-}else{
-if(this._startRepeatCount){
-this.repeatCount=this._startRepeatCount;
-this._startRepeatCount=0;
-}
-}
-}
-}
-}
-return this;
-}});
-dojo.lfx.Combine=function(_39c){
-dojo.lfx.IAnimation.call(this);
-this._anims=[];
-this._animsEnded=0;
-var _39d=arguments;
-if(_39d.length==1&&(dojo.lang.isArray(_39d[0])||dojo.lang.isArrayLike(_39d[0]))){
-_39d=_39d[0];
-}
-dojo.lang.forEach(_39d,function(anim){
-this._anims.push(anim);
-anim.connect("onEnd",dojo.lang.hitch(this,"_onAnimsEnded"));
-},this);
-};
-dojo.inherits(dojo.lfx.Combine,dojo.lfx.IAnimation);
-dojo.lang.extend(dojo.lfx.Combine,{_animsEnded:0,play:function(_39f,_3a0){
-if(!this._anims.length){
-return this;
-}
-this.fire("beforeBegin");
-if(_39f>0){
-setTimeout(dojo.lang.hitch(this,function(){
-this.play(null,_3a0);
-}),_39f);
-return this;
-}
-if(_3a0||this._anims[0].percent==0){
-this.fire("onBegin");
-}
-this.fire("onPlay");
-this._animsCall("play",null,_3a0);
-return this;
-},pause:function(){
-this.fire("onPause");
-this._animsCall("pause");
-return this;
-},stop:function(_3a1){
-this.fire("onStop");
-this._animsCall("stop",_3a1);
-return this;
-},_onAnimsEnded:function(){
-this._animsEnded++;
-if(this._animsEnded>=this._anims.length){
-this.fire("onEnd");
-}
-return this;
-},_animsCall:function(_3a2){
-var args=[];
-if(arguments.length>1){
-for(var i=1;i<arguments.length;i++){
-args.push(arguments[i]);
-}
-}
-var _3a5=this;
-dojo.lang.forEach(this._anims,function(anim){
-anim[_3a2](args);
-},_3a5);
-return this;
-}});
-dojo.lfx.Chain=function(_3a7){
-dojo.lfx.IAnimation.call(this);
-this._anims=[];
-this._currAnim=-1;
-var _3a8=arguments;
-if(_3a8.length==1&&(dojo.lang.isArray(_3a8[0])||dojo.lang.isArrayLike(_3a8[0]))){
-_3a8=_3a8[0];
-}
-var _3a9=this;
-dojo.lang.forEach(_3a8,function(anim,i,_3ac){
-this._anims.push(anim);
-if(i<_3ac.length-1){
-anim.connect("onEnd",dojo.lang.hitch(this,"_playNext"));
-}else{
-anim.connect("onEnd",dojo.lang.hitch(this,function(){
-this.fire("onEnd");
-}));
-}
-},this);
-};
-dojo.inherits(dojo.lfx.Chain,dojo.lfx.IAnimation);
-dojo.lang.extend(dojo.lfx.Chain,{_currAnim:-1,play:function(_3ad,_3ae){
-if(!this._anims.length){
-return this;
-}
-if(_3ae||!this._anims[this._currAnim]){
-this._currAnim=0;
-}
-var _3af=this._anims[this._currAnim];
-this.fire("beforeBegin");
-if(_3ad>0){
-setTimeout(dojo.lang.hitch(this,function(){
-this.play(null,_3ae);
-}),_3ad);
-return this;
-}
-if(_3af){
-if(this._currAnim==0){
-this.fire("handler",["begin",this._currAnim]);
-this.fire("onBegin",[this._currAnim]);
-}
-this.fire("onPlay",[this._currAnim]);
-_3af.play(null,_3ae);
-}
-return this;
-},pause:function(){
-if(this._anims[this._currAnim]){
-this._anims[this._currAnim].pause();
-this.fire("onPause",[this._currAnim]);
-}
-return this;
-},playPause:function(){
-if(this._anims.length==0){
-return this;
-}
-if(this._currAnim==-1){
-this._currAnim=0;
-}
-var _3b0=this._anims[this._currAnim];
-if(_3b0){
-if(!_3b0._active||_3b0._paused){
-this.play();
-}else{
-this.pause();
-}
-}
-return this;
-},stop:function(){
-var _3b1=this._anims[this._currAnim];
-if(_3b1){
-_3b1.stop();
-this.fire("onStop",[this._currAnim]);
-}
-return _3b1;
-},_playNext:function(){
-if(this._currAnim==-1||this._anims.length==0){
-return this;
-}
-this._currAnim++;
-if(this._anims[this._currAnim]){
-this._anims[this._currAnim].play(null,true);
-}
-return this;
-}});
-dojo.lfx.combine=function(_3b2){
-var _3b3=arguments;
-if(dojo.lang.isArray(arguments[0])){
-_3b3=arguments[0];
-}
-if(_3b3.length==1){
-return _3b3[0];
-}
-return new dojo.lfx.Combine(_3b3);
-};
-dojo.lfx.chain=function(_3b4){
-var _3b5=arguments;
-if(dojo.lang.isArray(arguments[0])){
-_3b5=arguments[0];
-}
-if(_3b5.length==1){
-return _3b5[0];
-}
-return new dojo.lfx.Chain(_3b5);
-};
-dojo.provide("dojo.html.color");
-dojo.html.getBackgroundColor=function(node){
-node=dojo.byId(node);
-var _3b7;
-do{
-_3b7=dojo.html.getStyle(node,"background-color");
-if(_3b7.toLowerCase()=="rgba(0, 0, 0, 0)"){
-_3b7="transparent";
-}
-if(node==document.getElementsByTagName("body")[0]){
-node=null;
-break;
-}
-node=node.parentNode;
-}while(node&&dojo.lang.inArray(["transparent",""],_3b7));
-if(_3b7=="transparent"){
-_3b7=[255,255,255,0];
-}else{
-_3b7=dojo.gfx.color.extractRGB(_3b7);
-}
-return _3b7;
-};
-dojo.provide("dojo.lfx.html");
-dojo.lfx.html._byId=function(_3b8){
-if(!_3b8){
-return [];
-}
-if(dojo.lang.isArrayLike(_3b8)){
-if(!_3b8.alreadyChecked){
-var n=[];
-dojo.lang.forEach(_3b8,function(node){
-n.push(dojo.byId(node));
-});
-n.alreadyChecked=true;
-return n;
-}else{
-return _3b8;
-}
-}else{
-var n=[];
-n.push(dojo.byId(_3b8));
-n.alreadyChecked=true;
-return n;
-}
-};
-dojo.lfx.html.propertyAnimation=function(_3bb,_3bc,_3bd,_3be,_3bf){
-_3bb=dojo.lfx.html._byId(_3bb);
-var _3c0={"propertyMap":_3bc,"nodes":_3bb,"duration":_3bd,"easing":_3be||dojo.lfx.easeDefault};
-var _3c1=function(args){
-if(args.nodes.length==1){
-var pm=args.propertyMap;
-if(!dojo.lang.isArray(args.propertyMap)){
-var parr=[];
-for(var _3c5 in pm){
-pm[_3c5].property=_3c5;
-parr.push(pm[_3c5]);
-}
-pm=args.propertyMap=parr;
-}
-dojo.lang.forEach(pm,function(prop){
-if(dj_undef("start",prop)){
-if(prop.property!="opacity"){
-prop.start=parseInt(dojo.html.getComputedStyle(args.nodes[0],prop.property));
-}else{
-prop.start=dojo.html.getOpacity(args.nodes[0]);
-}
-}
-});
-}
-};
-var _3c7=function(_3c8){
-var _3c9=[];
-dojo.lang.forEach(_3c8,function(c){
-_3c9.push(Math.round(c));
-});
-return _3c9;
-};
-var _3cb=function(n,_3cd){
-n=dojo.byId(n);
-if(!n||!n.style){
-return;
-}
-for(var s in _3cd){
-if(s=="opacity"){
-dojo.html.setOpacity(n,_3cd[s]);
-}else{
-n.style[s]=_3cd[s];
-}
-}
-};
-var _3cf=function(_3d0){
-this._properties=_3d0;
-this.diffs=new Array(_3d0.length);
-dojo.lang.forEach(_3d0,function(prop,i){
-if(dojo.lang.isFunction(prop.start)){
-prop.start=prop.start(prop,i);
-}
-if(dojo.lang.isFunction(prop.end)){
-prop.end=prop.end(prop,i);
-}
-if(dojo.lang.isArray(prop.start)){
-this.diffs[i]=null;
-}else{
-if(prop.start instanceof dojo.gfx.color.Color){
-prop.startRgb=prop.start.toRgb();
-prop.endRgb=prop.end.toRgb();
-}else{
-this.diffs[i]=prop.end-prop.start;
-}
-}
-},this);
-this.getValue=function(n){
-var ret={};
-dojo.lang.forEach(this._properties,function(prop,i){
-var _3d7=null;
-if(dojo.lang.isArray(prop.start)){
-}else{
-if(prop.start instanceof dojo.gfx.color.Color){
-_3d7=(prop.units||"rgb")+"(";
-for(var j=0;j<prop.startRgb.length;j++){
-_3d7+=Math.round(((prop.endRgb[j]-prop.startRgb[j])*n)+prop.startRgb[j])+(j<prop.startRgb.length-1?",":"");
-}
-_3d7+=")";
-}else{
-_3d7=((this.diffs[i])*n)+prop.start+(prop.property!="opacity"?prop.units||"px":"");
-}
-}
-ret[dojo.html.toCamelCase(prop.property)]=_3d7;
-},this);
-return ret;
-};
-};
-var anim=new dojo.lfx.Animation({beforeBegin:function(){
-_3c1(_3c0);
-anim.curve=new _3cf(_3c0.propertyMap);
-},onAnimate:function(_3da){
-dojo.lang.forEach(_3c0.nodes,function(node){
-_3cb(node,_3da);
-});
-}},_3c0.duration,null,_3c0.easing);
-if(_3bf){
-for(var x in _3bf){
-if(dojo.lang.isFunction(_3bf[x])){
-anim.connect(x,anim,_3bf[x]);
-}
-}
-}
-return anim;
-};
-dojo.lfx.html._makeFadeable=function(_3dd){
-var _3de=function(node){
-if(dojo.render.html.ie){
-if((node.style.zoom.length==0)&&(dojo.html.getStyle(node,"zoom")=="normal")){
-node.style.zoom="1";
-}
-if((node.style.width.length==0)&&(dojo.html.getStyle(node,"width")=="auto")){
-node.style.width="auto";
-}
-}
-};
-if(dojo.lang.isArrayLike(_3dd)){
-dojo.lang.forEach(_3dd,_3de);
-}else{
-_3de(_3dd);
-}
-};
-dojo.lfx.html.fade=function(_3e0,_3e1,_3e2,_3e3,_3e4){
-_3e0=dojo.lfx.html._byId(_3e0);
-var _3e5={property:"opacity"};
-if(!dj_undef("start",_3e1)){
-_3e5.start=_3e1.start;
-}else{
-_3e5.start=function(){
-return dojo.html.getOpacity(_3e0[0]);
-};
-}
-if(!dj_undef("end",_3e1)){
-_3e5.end=_3e1.end;
-}else{
-dojo.raise("dojo.lfx.html.fade needs an end value");
-}
-var anim=dojo.lfx.propertyAnimation(_3e0,[_3e5],_3e2,_3e3);
-anim.connect("beforeBegin",function(){
-dojo.lfx.html._makeFadeable(_3e0);
-});
-if(_3e4){
-anim.connect("onEnd",function(){
-_3e4(_3e0,anim);
-});
-}
-return anim;
-};
-dojo.lfx.html.fadeIn=function(_3e7,_3e8,_3e9,_3ea){
-return dojo.lfx.html.fade(_3e7,{end:1},_3e8,_3e9,_3ea);
-};
-dojo.lfx.html.fadeOut=function(_3eb,_3ec,_3ed,_3ee){
-return dojo.lfx.html.fade(_3eb,{end:0},_3ec,_3ed,_3ee);
-};
-dojo.lfx.html.fadeShow=function(_3ef,_3f0,_3f1,_3f2){
-_3ef=dojo.lfx.html._byId(_3ef);
-dojo.lang.forEach(_3ef,function(node){
-dojo.html.setOpacity(node,0);
-});
-var anim=dojo.lfx.html.fadeIn(_3ef,_3f0,_3f1,_3f2);
-anim.connect("beforeBegin",function(){
-if(dojo.lang.isArrayLike(_3ef)){
-dojo.lang.forEach(_3ef,dojo.html.show);
-}else{
-dojo.html.show(_3ef);
-}
-});
-return anim;
-};
-dojo.lfx.html.fadeHide=function(_3f5,_3f6,_3f7,_3f8){
-var anim=dojo.lfx.html.fadeOut(_3f5,_3f6,_3f7,function(){
-if(dojo.lang.isArrayLike(_3f5)){
-dojo.lang.forEach(_3f5,dojo.html.hide);
-}else{
-dojo.html.hide(_3f5);
-}
-if(_3f8){
-_3f8(_3f5,anim);
-}
-});
-return anim;
-};
-dojo.lfx.html.wipeIn=function(_3fa,_3fb,_3fc,_3fd){
-_3fa=dojo.lfx.html._byId(_3fa);
-var _3fe=[];
-dojo.lang.forEach(_3fa,function(node){
-var _400={};
-dojo.html.show(node);
-var _401=dojo.html.getBorderBox(node).height;
-dojo.html.hide(node);
-var anim=dojo.lfx.propertyAnimation(node,{"height":{start:1,end:function(){
-return _401;
-}}},_3fb,_3fc);
-anim.connect("beforeBegin",function(){
-_400.overflow=node.style.overflow;
-_400.height=node.style.height;
-with(node.style){
-overflow="hidden";
-_401="1px";
-}
-dojo.html.show(node);
-});
-anim.connect("onEnd",function(){
-with(node.style){
-overflow=_400.overflow;
-_401=_400.height;
-}
-if(_3fd){
-_3fd(node,anim);
-}
-});
-_3fe.push(anim);
-});
-return dojo.lfx.combine(_3fe);
-};
-dojo.lfx.html.wipeOut=function(_403,_404,_405,_406){
-_403=dojo.lfx.html._byId(_403);
-var _407=[];
-dojo.lang.forEach(_403,function(node){
-var _409={};
-var anim=dojo.lfx.propertyAnimation(node,{"height":{start:function(){
-return dojo.html.getContentBox(node).height;
-},end:1}},_404,_405,{"beforeBegin":function(){
-_409.overflow=node.style.overflow;
-_409.height=node.style.height;
-with(node.style){
-overflow="hidden";
-}
-dojo.html.show(node);
-},"onEnd":function(){
-dojo.html.hide(node);
-with(node.style){
-overflow=_409.overflow;
-height=_409.height;
-}
-if(_406){
-_406(node,anim);
-}
-}});
-_407.push(anim);
-});
-return dojo.lfx.combine(_407);
-};
-dojo.lfx.html.slideTo=function(_40b,_40c,_40d,_40e,_40f){
-_40b=dojo.lfx.html._byId(_40b);
-var _410=[];
-var _411=dojo.html.getComputedStyle;
-if(dojo.lang.isArray(_40c)){
-dojo.deprecated("dojo.lfx.html.slideTo(node, array)","use dojo.lfx.html.slideTo(node, {top: value, left: value});","0.5");
-_40c={top:_40c[0],left:_40c[1]};
-}
-dojo.lang.forEach(_40b,function(node){
-var top=null;
-var left=null;
-var init=(function(){
-var _416=node;
-return function(){
-var pos=_411(_416,"position");
-top=(pos=="absolute"?node.offsetTop:parseInt(_411(node,"top"))||0);
-left=(pos=="absolute"?node.offsetLeft:parseInt(_411(node,"left"))||0);
-if(!dojo.lang.inArray(["absolute","relative"],pos)){
-var ret=dojo.html.abs(_416,true);
-dojo.html.setStyleAttributes(_416,"position:absolute;top:"+ret.y+"px;left:"+ret.x+"px;");
-top=ret.y;
-left=ret.x;
-}
-};
-})();
-init();
-var anim=dojo.lfx.propertyAnimation(node,{"top":{start:top,end:(_40c.top||0)},"left":{start:left,end:(_40c.left||0)}},_40d,_40e,{"beforeBegin":init});
-if(_40f){
-anim.connect("onEnd",function(){
-_40f(_40b,anim);
-});
-}
-_410.push(anim);
-});
-return dojo.lfx.combine(_410);
-};
-dojo.lfx.html.slideBy=function(_41a,_41b,_41c,_41d,_41e){
-_41a=dojo.lfx.html._byId(_41a);
-var _41f=[];
-var _420=dojo.html.getComputedStyle;
-if(dojo.lang.isArray(_41b)){
-dojo.deprecated("dojo.lfx.html.slideBy(node, array)","use dojo.lfx.html.slideBy(node, {top: value, left: value});","0.5");
-_41b={top:_41b[0],left:_41b[1]};
-}
-dojo.lang.forEach(_41a,function(node){
-var top=null;
-var left=null;
-var init=(function(){
-var _425=node;
-return function(){
-var pos=_420(_425,"position");
-top=(pos=="absolute"?node.offsetTop:parseInt(_420(node,"top"))||0);
-left=(pos=="absolute"?node.offsetLeft:parseInt(_420(node,"left"))||0);
-if(!dojo.lang.inArray(["absolute","relative"],pos)){
-var ret=dojo.html.abs(_425,true);
-dojo.html.setStyleAttributes(_425,"position:absolute;top:"+ret.y+"px;left:"+ret.x+"px;");
-top=ret.y;
-left=ret.x;
-}
-};
-})();
-init();
-var anim=dojo.lfx.propertyAnimation(node,{"top":{start:top,end:top+(_41b.top||0)},"left":{start:left,end:left+(_41b.left||0)}},_41c,_41d).connect("beforeBegin",init);
-if(_41e){
-anim.connect("onEnd",function(){
-_41e(_41a,anim);
-});
-}
-_41f.push(anim);
-});
-return dojo.lfx.combine(_41f);
-};
-dojo.lfx.html.explode=function(_429,_42a,_42b,_42c,_42d){
-var h=dojo.html;
-_429=dojo.byId(_429);
-_42a=dojo.byId(_42a);
-var _42f=h.toCoordinateObject(_429,true);
-var _430=document.createElement("div");
-h.copyStyle(_430,_42a);
-if(_42a.explodeClassName){
-_430.className=_42a.explodeClassName;
-}
-with(_430.style){
-position="absolute";
-display="none";
-}
-dojo.body().appendChild(_430);
-with(_42a.style){
-visibility="hidden";
-display="block";
-}
-var _431=h.toCoordinateObject(_42a,true);
-with(_42a.style){
-display="none";
-visibility="visible";
-}
-var _432={opacity:{start:0.5,end:1}};
-dojo.lang.forEach(["height","width","top","left"],function(type){
-_432[type]={start:_42f[type],end:_431[type]};
-});
-var anim=new dojo.lfx.propertyAnimation(_430,_432,_42b,_42c,{"beforeBegin":function(){
-h.setDisplay(_430,"block");
-},"onEnd":function(){
-h.setDisplay(_42a,"block");
-_430.parentNode.removeChild(_430);
-}});
-if(_42d){
-anim.connect("onEnd",function(){
-_42d(_42a,anim);
-});
-}
-return anim;
-};
-dojo.lfx.html.implode=function(_435,end,_437,_438,_439){
-var h=dojo.html;
-_435=dojo.byId(_435);
-end=dojo.byId(end);
-var _43b=dojo.html.toCoordinateObject(_435,true);
-var _43c=dojo.html.toCoordinateObject(end,true);
-var _43d=document.createElement("div");
-dojo.html.copyStyle(_43d,_435);
-if(_435.explodeClassName){
-_43d.className=_435.explodeClassName;
-}
-dojo.html.setOpacity(_43d,0.3);
-with(_43d.style){
-position="absolute";
-display="none";
-backgroundColor=h.getStyle(_435,"background-color").toLowerCase();
-}
-dojo.body().appendChild(_43d);
-var _43e={opacity:{start:1,end:0.5}};
-dojo.lang.forEach(["height","width","top","left"],function(type){
-_43e[type]={start:_43b[type],end:_43c[type]};
-});
-var anim=new dojo.lfx.propertyAnimation(_43d,_43e,_437,_438,{"beforeBegin":function(){
-dojo.html.hide(_435);
-dojo.html.show(_43d);
-},"onEnd":function(){
-_43d.parentNode.removeChild(_43d);
-}});
-if(_439){
-anim.connect("onEnd",function(){
-_439(_435,anim);
-});
-}
-return anim;
-};
-dojo.lfx.html.highlight=function(_441,_442,_443,_444,_445){
-_441=dojo.lfx.html._byId(_441);
-var _446=[];
-dojo.lang.forEach(_441,function(node){
-var _448=dojo.html.getBackgroundColor(node);
-var bg=dojo.html.getStyle(node,"background-color").toLowerCase();
-var _44a=dojo.html.getStyle(node,"background-image");
-var _44b=(bg=="transparent"||bg=="rgba(0, 0, 0, 0)");
-while(_448.length>3){
-_448.pop();
-}
-var rgb=new dojo.gfx.color.Color(_442);
-var _44d=new dojo.gfx.color.Color(_448);
-var anim=dojo.lfx.propertyAnimation(node,{"background-color":{start:rgb,end:_44d}},_443,_444,{"beforeBegin":function(){
-if(_44a){
-node.style.backgroundImage="none";
-}
-node.style.backgroundColor="rgb("+rgb.toRgb().join(",")+")";
-},"onEnd":function(){
-if(_44a){
-node.style.backgroundImage=_44a;
-}
-if(_44b){
-node.style.backgroundColor="transparent";
-}
-if(_445){
-_445(node,anim);
-}
-}});
-_446.push(anim);
-});
-return dojo.lfx.combine(_446);
-};
-dojo.lfx.html.unhighlight=function(_44f,_450,_451,_452,_453){
-_44f=dojo.lfx.html._byId(_44f);
-var _454=[];
-dojo.lang.forEach(_44f,function(node){
-var _456=new dojo.gfx.color.Color(dojo.html.getBackgroundColor(node));
-var rgb=new dojo.gfx.color.Color(_450);
-var _458=dojo.html.getStyle(node,"background-image");
-var anim=dojo.lfx.propertyAnimation(node,{"background-color":{start:_456,end:rgb}},_451,_452,{"beforeBegin":function(){
-if(_458){
-node.style.backgroundImage="none";
-}
-node.style.backgroundColor="rgb("+_456.toRgb().join(",")+")";
-},"onEnd":function(){
-if(_453){
-_453(node,anim);
-}
-}});
-_454.push(anim);
-});
-return dojo.lfx.combine(_454);
-};
-dojo.lang.mixin(dojo.lfx,dojo.lfx.html);
-dojo.provide("dojo.lfx.*");
-dojo.provide("dojo.lang.extras");
-dojo.lang.setTimeout=function(func,_45b){
-var _45c=window,_45d=2;
-if(!dojo.lang.isFunction(func)){
-_45c=func;
-func=_45b;
-_45b=arguments[2];
-_45d++;
-}
-if(dojo.lang.isString(func)){
-func=_45c[func];
-}
-var args=[];
-for(var i=_45d;i<arguments.length;i++){
-args.push(arguments[i]);
-}
-return dojo.global().setTimeout(function(){
-func.apply(_45c,args);
-},_45b);
-};
-dojo.lang.clearTimeout=function(_460){
-dojo.global().clearTimeout(_460);
-};
-dojo.lang.getNameInObj=function(ns,item){
-if(!ns){
-ns=dj_global;
-}
-for(var x in ns){
-if(ns[x]===item){
-return new String(x);
-}
-}
-return null;
-};
-dojo.lang.shallowCopy=function(obj,deep){
-var i,ret;
-if(obj===null){
-return null;
-}
-if(dojo.lang.isObject(obj)){
-ret=new obj.constructor();
-for(i in obj){
-if(dojo.lang.isUndefined(ret[i])){
-ret[i]=deep?dojo.lang.shallowCopy(obj[i],deep):obj[i];
-}
-}
-}else{
-if(dojo.lang.isArray(obj)){
-ret=[];
-for(i=0;i<obj.length;i++){
-ret[i]=deep?dojo.lang.shallowCopy(obj[i],deep):obj[i];
-}
-}else{
-ret=obj;
-}
-}
-return ret;
-};
-dojo.lang.firstValued=function(){
-for(var i=0;i<arguments.length;i++){
-if(typeof arguments[i]!="undefined"){
-return arguments[i];
-}
-}
-return undefined;
-};
-dojo.lang.getObjPathValue=function(_469,_46a,_46b){
-with(dojo.parseObjPath(_469,_46a,_46b)){
-return dojo.evalProp(prop,obj,_46b);
-}
-};
-dojo.lang.setObjPathValue=function(_46c,_46d,_46e,_46f){
-if(arguments.length<4){
-_46f=true;
-}
-with(dojo.parseObjPath(_46c,_46e,_46f)){
-if(obj&&(_46f||(prop in obj))){
-obj[prop]=_46d;
-}
-}
-};
-dojo.provide("dojo.event.common");
-dojo.event=new function(){
-this._canTimeout=dojo.lang.isFunction(dj_global["setTimeout"])||dojo.lang.isAlien(dj_global["setTimeout"]);
-function interpolateArgs(args,_471){
-var dl=dojo.lang;
-var ao={srcObj:dj_global,srcFunc:null,adviceObj:dj_global,adviceFunc:null,aroundObj:null,aroundFunc:null,adviceType:(args.length>2)?args[0]:"after",precedence:"last",once:false,delay:null,rate:0,adviceMsg:false};
-switch(args.length){
-case 0:
-return;
-case 1:
-return;
-case 2:
-ao.srcFunc=args[0];
-ao.adviceFunc=args[1];
-break;
-case 3:
-if((dl.isObject(args[0]))&&(dl.isString(args[1]))&&(dl.isString(args[2]))){
-ao.adviceType="after";
-ao.srcObj=args[0];
-ao.srcFunc=args[1];
-ao.adviceFunc=args[2];
-}else{
-if((dl.isString(args[1]))&&(dl.isString(args[2]))){
-ao.srcFunc=args[1];
-ao.adviceFunc=args[2];
-}else{
-if((dl.isObject(args[0]))&&(dl.isString(args[1]))&&(dl.isFunction(args[2]))){
-ao.adviceType="after";
-ao.srcObj=args[0];
-ao.srcFunc=args[1];
-var _474=dl.nameAnonFunc(args[2],ao.adviceObj,_471);
-ao.adviceFunc=_474;
-}else{
-if((dl.isFunction(args[0]))&&(dl.isObject(args[1]))&&(dl.isString(args[2]))){
-ao.adviceType="after";
-ao.srcObj=dj_global;
-var _474=dl.nameAnonFunc(args[0],ao.srcObj,_471);
-ao.srcFunc=_474;
-ao.adviceObj=args[1];
-ao.adviceFunc=args[2];
-}
-}
-}
-}
-break;
-case 4:
-if((dl.isObject(args[0]))&&(dl.isObject(args[2]))){
-ao.adviceType="after";
-ao.srcObj=args[0];
-ao.srcFunc=args[1];
-ao.adviceObj=args[2];
-ao.adviceFunc=args[3];
-}else{
-if((dl.isString(args[0]))&&(dl.isString(args[1]))&&(dl.isObject(args[2]))){
-ao.adviceType=args[0];
-ao.srcObj=dj_global;
-ao.srcFunc=args[1];
-ao.adviceObj=args[2];
-ao.adviceFunc=args[3];
-}else{
-if((dl.isString(args[0]))&&(dl.isFunction(args[1]))&&(dl.isObject(args[2]))){
-ao.adviceType=args[0];
-ao.srcObj=dj_global;
-var _474=dl.nameAnonFunc(args[1],dj_global,_471);
-ao.srcFunc=_474;
-ao.adviceObj=args[2];
-ao.adviceFunc=args[3];
-}else{
-if((dl.isString(args[0]))&&(dl.isObject(args[1]))&&(dl.isString(args[2]))&&(dl.isFunction(args[3]))){
-ao.srcObj=args[1];
-ao.srcFunc=args[2];
-var _474=dl.nameAnonFunc(args[3],dj_global,_471);
-ao.adviceObj=dj_global;
-ao.adviceFunc=_474;
-}else{
-if(dl.isObject(args[1])){
-ao.srcObj=args[1];
-ao.srcFunc=args[2];
-ao.adviceObj=dj_global;
-ao.adviceFunc=args[3];
-}else{
-if(dl.isObject(args[2])){
-ao.srcObj=dj_global;
-ao.srcFunc=args[1];
-ao.adviceObj=args[2];
-ao.adviceFunc=args[3];
-}else{
-ao.srcObj=ao.adviceObj=ao.aroundObj=dj_global;
-ao.srcFunc=args[1];
-ao.adviceFunc=args[2];
-ao.aroundFunc=args[3];
-}
-}
-}
-}
-}
-}
-break;
-case 6:
-ao.srcObj=args[1];
-ao.srcFunc=args[2];
-ao.adviceObj=args[3];
-ao.adviceFunc=args[4];
-ao.aroundFunc=args[5];
-ao.aroundObj=dj_global;
-break;
-default:
-ao.srcObj=args[1];
-ao.srcFunc=args[2];
-ao.adviceObj=args[3];
-ao.adviceFunc=args[4];
-ao.aroundObj=args[5];
-ao.aroundFunc=args[6];
-ao.once=args[7];
-ao.delay=args[8];
-ao.rate=args[9];
-ao.adviceMsg=args[10];
-break;
-}
-if(dl.isFunction(ao.aroundFunc)){
-var _474=dl.nameAnonFunc(ao.aroundFunc,ao.aroundObj,_471);
-ao.aroundFunc=_474;
-}
-if(dl.isFunction(ao.srcFunc)){
-ao.srcFunc=dl.getNameInObj(ao.srcObj,ao.srcFunc);
-}
-if(dl.isFunction(ao.adviceFunc)){
-ao.adviceFunc=dl.getNameInObj(ao.adviceObj,ao.adviceFunc);
-}
-if((ao.aroundObj)&&(dl.isFunction(ao.aroundFunc))){
-ao.aroundFunc=dl.getNameInObj(ao.aroundObj,ao.aroundFunc);
-}
-if(!ao.srcObj){
-dojo.raise("bad srcObj for srcFunc: "+ao.srcFunc);
-}
-if(!ao.adviceObj){
-dojo.raise("bad adviceObj for adviceFunc: "+ao.adviceFunc);
-}
-if(!ao.adviceFunc){
-dojo.debug("bad adviceFunc for srcFunc: "+ao.srcFunc);
-dojo.debugShallow(ao);
-}
-return ao;
-}
-this.connect=function(){
-if(arguments.length==1){
-var ao=arguments[0];
-}else{
-var ao=interpolateArgs(arguments,true);
-}
-if(dojo.lang.isString(ao.srcFunc)&&(ao.srcFunc.toLowerCase()=="onkey")){
-if(dojo.render.html.ie){
-ao.srcFunc="onkeydown";
-this.connect(ao);
-}
-ao.srcFunc="onkeypress";
-}
-if(dojo.lang.isArray(ao.srcObj)&&ao.srcObj!=""){
-var _476={};
-for(var x in ao){
-_476[x]=ao[x];
-}
-var mjps=[];
-dojo.lang.forEach(ao.srcObj,function(src){
-if((dojo.render.html.capable)&&(dojo.lang.isString(src))){
-src=dojo.byId(src);
-}
-_476.srcObj=src;
-mjps.push(dojo.event.connect.call(dojo.event,_476));
-});
-return mjps;
-}
-var mjp=dojo.event.MethodJoinPoint.getForMethod(ao.srcObj,ao.srcFunc);
-if(ao.adviceFunc){
-var mjp2=dojo.event.MethodJoinPoint.getForMethod(ao.adviceObj,ao.adviceFunc);
-}
-mjp.kwAddAdvice(ao);
-return mjp;
-};
-this.log=function(a1,a2){
-var _47e;
-if((arguments.length==1)&&(typeof a1=="object")){
-_47e=a1;
-}else{
-_47e={srcObj:a1,srcFunc:a2};
-}
-_47e.adviceFunc=function(){
-var _47f=[];
-for(var x=0;x<arguments.length;x++){
-_47f.push(arguments[x]);
-}
-dojo.debug("("+_47e.srcObj+")."+_47e.srcFunc,":",_47f.join(", "));
-};
-this.kwConnect(_47e);
-};
-this.connectBefore=function(){
-var args=["before"];
-for(var i=0;i<arguments.length;i++){
-args.push(arguments[i]);
-}
-return this.connect.apply(this,args);
-};
-this.connectAround=function(){
-var args=["around"];
-for(var i=0;i<arguments.length;i++){
-args.push(arguments[i]);
-}
-return this.connect.apply(this,args);
-};
-this.connectOnce=function(){
-var ao=interpolateArgs(arguments,true);
-ao.once=true;
-return this.connect(ao);
-};
-this._kwConnectImpl=function(_486,_487){
-var fn=(_487)?"disconnect":"connect";
-if(typeof _486["srcFunc"]=="function"){
-_486.srcObj=_486["srcObj"]||dj_global;
-var _489=dojo.lang.nameAnonFunc(_486.srcFunc,_486.srcObj,true);
-_486.srcFunc=_489;
-}
-if(typeof _486["adviceFunc"]=="function"){
-_486.adviceObj=_486["adviceObj"]||dj_global;
-var _489=dojo.lang.nameAnonFunc(_486.adviceFunc,_486.adviceObj,true);
-_486.adviceFunc=_489;
-}
-_486.srcObj=_486["srcObj"]||dj_global;
-_486.adviceObj=_486["adviceObj"]||_486["targetObj"]||dj_global;
-_486.adviceFunc=_486["adviceFunc"]||_486["targetFunc"];
-return dojo.event[fn](_486);
-};
-this.kwConnect=function(_48a){
-return this._kwConnectImpl(_48a,false);
-};
-this.disconnect=function(){
-if(arguments.length==1){
-var ao=arguments[0];
-}else{
-var ao=interpolateArgs(arguments,true);
-}
-if(!ao.adviceFunc){
-return;
-}
-if(dojo.lang.isString(ao.srcFunc)&&(ao.srcFunc.toLowerCase()=="onkey")){
-if(dojo.render.html.ie){
-ao.srcFunc="onkeydown";
-this.disconnect(ao);
-}
-ao.srcFunc="onkeypress";
-}
-var mjp=dojo.event.MethodJoinPoint.getForMethod(ao.srcObj,ao.srcFunc);
-return mjp.removeAdvice(ao.adviceObj,ao.adviceFunc,ao.adviceType,ao.once);
-};
-this.kwDisconnect=function(_48d){
-return this._kwConnectImpl(_48d,true);
-};
-};
-dojo.event.MethodInvocation=function(_48e,obj,args){
-this.jp_=_48e;
-this.object=obj;
-this.args=[];
-for(var x=0;x<args.length;x++){
-this.args[x]=args[x];
-}
-this.around_index=-1;
-};
-dojo.event.MethodInvocation.prototype.proceed=function(){
-this.around_index++;
-if(this.around_index>=this.jp_.around.length){
-return this.jp_.object[this.jp_.methodname].apply(this.jp_.object,this.args);
-}else{
-var ti=this.jp_.around[this.around_index];
-var mobj=ti[0]||dj_global;
-var meth=ti[1];
-return mobj[meth].call(mobj,this);
-}
-};
-dojo.event.MethodJoinPoint=function(obj,_496){
-this.object=obj||dj_global;
-this.methodname=_496;
-this.methodfunc=this.object[_496];
-this.squelch=false;
-};
-dojo.event.MethodJoinPoint.getForMethod=function(obj,_498){
-if(!obj){
-obj=dj_global;
-}
-if(!obj[_498]){
-obj[_498]=function(){
-};
-if(!obj[_498]){
-dojo.raise("Cannot set do-nothing method on that object "+_498);
-}
-}else{
-if((!dojo.lang.isFunction(obj[_498]))&&(!dojo.lang.isAlien(obj[_498]))){
-return null;
-}
-}
-var _499=_498+"$joinpoint";
-var _49a=_498+"$joinpoint$method";
-var _49b=obj[_499];
-if(!_49b){
-var _49c=false;
-if(dojo.event["browser"]){
-if((obj["attachEvent"])||(obj["nodeType"])||(obj["addEventListener"])){
-_49c=true;
-dojo.event.browser.addClobberNodeAttrs(obj,[_499,_49a,_498]);
-}
-}
-var _49d=obj[_498].length;
-obj[_49a]=obj[_498];
-_49b=obj[_499]=new dojo.event.MethodJoinPoint(obj,_49a);
-obj[_498]=function(){
-var args=[];
-if((_49c)&&(!arguments.length)){
-var evt=null;
-try{
-if(obj.ownerDocument){
-evt=obj.ownerDocument.parentWindow.event;
-}else{
-if(obj.documentElement){
-evt=obj.documentElement.ownerDocument.parentWindow.event;
-}else{
-if(obj.event){
-evt=obj.event;
-}else{
-evt=window.event;
-}
-}
-}
-}
-catch(e){
-evt=window.event;
-}
-if(evt){
-args.push(dojo.event.browser.fixEvent(evt,this));
-}
-}else{
-for(var x=0;x<arguments.length;x++){
-if((x==0)&&(_49c)&&(dojo.event.browser.isEvent(arguments[x]))){
-args.push(dojo.event.browser.fixEvent(arguments[x],this));
-}else{
-args.push(arguments[x]);
-}
-}
-}
-return _49b.run.apply(_49b,args);
-};
-obj[_498].__preJoinArity=_49d;
-}
-return _49b;
-};
-dojo.lang.extend(dojo.event.MethodJoinPoint,{unintercept:function(){
-this.object[this.methodname]=this.methodfunc;
-this.before=[];
-this.after=[];
-this.around=[];
-},disconnect:dojo.lang.forward("unintercept"),run:function(){
-var obj=this.object||dj_global;
-var args=arguments;
-var _4a3=[];
-for(var x=0;x<args.length;x++){
-_4a3[x]=args[x];
-}
-var _4a5=function(marr){
-if(!marr){
-dojo.debug("Null argument to unrollAdvice()");
-return;
-}
-var _4a7=marr[0]||dj_global;
-var _4a8=marr[1];
-if(!_4a7[_4a8]){
-dojo.raise("function \""+_4a8+"\" does not exist on \""+_4a7+"\"");
-}
-var _4a9=marr[2]||dj_global;
-var _4aa=marr[3];
-var msg=marr[6];
-var _4ac;
-var to={args:[],jp_:this,object:obj,proceed:function(){
-return _4a7[_4a8].apply(_4a7,to.args);
-}};
-to.args=_4a3;
-var _4ae=parseInt(marr[4]);
-var _4af=((!isNaN(_4ae))&&(marr[4]!==null)&&(typeof marr[4]!="undefined"));
-if(marr[5]){
-var rate=parseInt(marr[5]);
-var cur=new Date();
-var _4b2=false;
-if((marr["last"])&&((cur-marr.last)<=rate)){
-if(dojo.event._canTimeout){
-if(marr["delayTimer"]){
-clearTimeout(marr.delayTimer);
-}
-var tod=parseInt(rate*2);
-var mcpy=dojo.lang.shallowCopy(marr);
-marr.delayTimer=setTimeout(function(){
-mcpy[5]=0;
-_4a5(mcpy);
-},tod);
-}
-return;
-}else{
-marr.last=cur;
-}
-}
-if(_4aa){
-_4a9[_4aa].call(_4a9,to);
-}else{
-if((_4af)&&((dojo.render.html)||(dojo.render.svg))){
-dj_global["setTimeout"](function(){
-if(msg){
-_4a7[_4a8].call(_4a7,to);
-}else{
-_4a7[_4a8].apply(_4a7,args);
-}
-},_4ae);
-}else{
-if(msg){
-_4a7[_4a8].call(_4a7,to);
-}else{
-_4a7[_4a8].apply(_4a7,args);
-}
-}
-}
-};
-var _4b5=function(){
-if(this.squelch){
-try{
-return _4a5.apply(this,arguments);
-}
-catch(e){
-dojo.debug(e);
-}
-}else{
-return _4a5.apply(this,arguments);
-}
-};
-if((this["before"])&&(this.before.length>0)){
-dojo.lang.forEach(this.before.concat(new Array()),_4b5);
-}
-var _4b6;
-try{
-if((this["around"])&&(this.around.length>0)){
-var mi=new dojo.event.MethodInvocation(this,obj,args);
-_4b6=mi.proceed();
-}else{
-if(this.methodfunc){
-_4b6=this.object[this.methodname].apply(this.object,args);
-}
-}
-}
-catch(e){
-if(!this.squelch){
-dojo.raise(e);
-}
-}
-if((this["after"])&&(this.after.length>0)){
-dojo.lang.forEach(this.after.concat(new Array()),_4b5);
-}
-return (this.methodfunc)?_4b6:null;
-},getArr:function(kind){
-var type="after";
-if((typeof kind=="string")&&(kind.indexOf("before")!=-1)){
-type="before";
-}else{
-if(kind=="around"){
-type="around";
-}
-}
-if(!this[type]){
-this[type]=[];
-}
-return this[type];
-},kwAddAdvice:function(args){
-this.addAdvice(args["adviceObj"],args["adviceFunc"],args["aroundObj"],args["aroundFunc"],args["adviceType"],args["precedence"],args["once"],args["delay"],args["rate"],args["adviceMsg"]);
-},addAdvice:function(_4bb,_4bc,_4bd,_4be,_4bf,_4c0,once,_4c2,rate,_4c4){
-var arr=this.getArr(_4bf);
-if(!arr){
-dojo.raise("bad this: "+this);
-}
-var ao=[_4bb,_4bc,_4bd,_4be,_4c2,rate,_4c4];
-if(once){
-if(this.hasAdvice(_4bb,_4bc,_4bf,arr)>=0){
-return;
-}
-}
-if(_4c0=="first"){
-arr.unshift(ao);
-}else{
-arr.push(ao);
-}
-},hasAdvice:function(_4c7,_4c8,_4c9,arr){
-if(!arr){
-arr=this.getArr(_4c9);
-}
-var ind=-1;
-for(var x=0;x<arr.length;x++){
-var aao=(typeof _4c8=="object")?(new String(_4c8)).toString():_4c8;
-var a1o=(typeof arr[x][1]=="object")?(new String(arr[x][1])).toString():arr[x][1];
-if((arr[x][0]==_4c7)&&(a1o==aao)){
-ind=x;
-}
-}
-return ind;
-},removeAdvice:function(_4cf,_4d0,_4d1,once){
-var arr=this.getArr(_4d1);
-var ind=this.hasAdvice(_4cf,_4d0,_4d1,arr);
-if(ind==-1){
-return false;
-}
-while(ind!=-1){
-arr.splice(ind,1);
-if(once){
-break;
-}
-ind=this.hasAdvice(_4cf,_4d0,_4d1,arr);
-}
-return true;
-}});
-dojo.provide("dojo.event.topic");
-dojo.event.topic=new function(){
-this.topics={};
-this.getTopic=function(_4d5){
-if(!this.topics[_4d5]){
-this.topics[_4d5]=new this.TopicImpl(_4d5);
-}
-return this.topics[_4d5];
-};
-this.registerPublisher=function(_4d6,obj,_4d8){
-var _4d6=this.getTopic(_4d6);
-_4d6.registerPublisher(obj,_4d8);
-};
-this.subscribe=function(_4d9,obj,_4db){
-var _4d9=this.getTopic(_4d9);
-_4d9.subscribe(obj,_4db);
-};
-this.unsubscribe=function(_4dc,obj,_4de){
-var _4dc=this.getTopic(_4dc);
-_4dc.unsubscribe(obj,_4de);
-};
-this.destroy=function(_4df){
-this.getTopic(_4df).destroy();
-delete this.topics[_4df];
-};
-this.publishApply=function(_4e0,args){
-var _4e0=this.getTopic(_4e0);
-_4e0.sendMessage.apply(_4e0,args);
-};
-this.publish=function(_4e2,_4e3){
-var _4e2=this.getTopic(_4e2);
-var args=[];
-for(var x=1;x<arguments.length;x++){
-args.push(arguments[x]);
-}
-_4e2.sendMessage.apply(_4e2,args);
-};
-};
-dojo.event.topic.TopicImpl=function(_4e6){
-this.topicName=_4e6;
-this.subscribe=function(_4e7,_4e8){
-var tf=_4e8||_4e7;
-var to=(!_4e8)?dj_global:_4e7;
-return dojo.event.kwConnect({srcObj:this,srcFunc:"sendMessage",adviceObj:to,adviceFunc:tf});
-};
-this.unsubscribe=function(_4eb,_4ec){
-var tf=(!_4ec)?_4eb:_4ec;
-var to=(!_4ec)?null:_4eb;
-return dojo.event.kwDisconnect({srcObj:this,srcFunc:"sendMessage",adviceObj:to,adviceFunc:tf});
-};
-this._getJoinPoint=function(){
-return dojo.event.MethodJoinPoint.getForMethod(this,"sendMessage");
-};
-this.setSquelch=function(_4ef){
-this._getJoinPoint().squelch=_4ef;
-};
-this.destroy=function(){
-this._getJoinPoint().disconnect();
-};
-this.registerPublisher=function(_4f0,_4f1){
-dojo.event.connect(_4f0,_4f1,this,"sendMessage");
-};
-this.sendMessage=function(_4f2){
-};
-};
-dojo.provide("dojo.event.browser");
-dojo._ie_clobber=new function(){
-this.clobberNodes=[];
-function nukeProp(node,prop){
-try{
-node[prop]=null;
-}
-catch(e){
-}
-try{
-delete node[prop];
-}
-catch(e){
-}
-try{
-node.removeAttribute(prop);
-}
-catch(e){
-}
-}
-this.clobber=function(_4f5){
-var na;
-var tna;
-if(_4f5){
-tna=_4f5.all||_4f5.getElementsByTagName("*");
-na=[_4f5];
-for(var x=0;x<tna.length;x++){
-if(tna[x]["__doClobber__"]){
-na.push(tna[x]);
-}
-}
-}else{
-try{
-window.onload=null;
-}
-catch(e){
-}
-na=(this.clobberNodes.length)?this.clobberNodes:document.all;
-}
-tna=null;
-var _4f9={};
-for(var i=na.length-1;i>=0;i=i-1){
-var el=na[i];
-try{
-if(el&&el["__clobberAttrs__"]){
-for(var j=0;j<el.__clobberAttrs__.length;j++){
-nukeProp(el,el.__clobberAttrs__[j]);
-}
-nukeProp(el,"__clobberAttrs__");
-nukeProp(el,"__doClobber__");
-}
-}
-catch(e){
-}
-}
-na=null;
-};
-};
-if(dojo.render.html.ie){
-dojo.addOnUnload(function(){
-dojo._ie_clobber.clobber();
-try{
-if((dojo["widget"])&&(dojo.widget["manager"])){
-dojo.widget.manager.destroyAll();
-}
-}
-catch(e){
-}
-try{
-window.onload=null;
-}
-catch(e){
-}
-try{
-window.onunload=null;
-}
-catch(e){
-}
-dojo._ie_clobber.clobberNodes=[];
-});
-}
-dojo.event.browser=new function(){
-var _4fd=0;
-this.normalizedEventName=function(_4fe){
-switch(_4fe){
-case "CheckboxStateChange":
-case "DOMAttrModified":
-case "DOMMenuItemActive":
-case "DOMMenuItemInactive":
-case "DOMMouseScroll":
-case "DOMNodeInserted":
-case "DOMNodeRemoved":
-case "RadioStateChange":
-return _4fe;
-break;
-default:
-return _4fe.toLowerCase();
-break;
-}
-};
-this.clean=function(node){
-if(dojo.render.html.ie){
-dojo._ie_clobber.clobber(node);
-}
-};
-this.addClobberNode=function(node){
-if(!dojo.render.html.ie){
-return;
-}
-if(!node["__doClobber__"]){
-node.__doClobber__=true;
-dojo._ie_clobber.clobberNodes.push(node);
-node.__clobberAttrs__=[];
-}
-};
-this.addClobberNodeAttrs=function(node,_502){
-if(!dojo.render.html.ie){
-return;
-}
-this.addClobberNode(node);
-for(var x=0;x<_502.length;x++){
-node.__clobberAttrs__.push(_502[x]);
-}
-};
-this.removeListener=function(node,_505,fp,_507){
-if(!_507){
-var _507=false;
-}
-_505=dojo.event.browser.normalizedEventName(_505);
-if((_505=="onkey")||(_505=="key")){
-if(dojo.render.html.ie){
-this.removeListener(node,"onkeydown",fp,_507);
-}
-_505="onkeypress";
-}
-if(_505.substr(0,2)=="on"){
-_505=_505.substr(2);
-}
-if(node.removeEventListener){
-node.removeEventListener(_505,fp,_507);
-}
-};
-this.addListener=function(node,_509,fp,_50b,_50c){
-if(!node){
-return;
-}
-if(!_50b){
-var _50b=false;
-}
-_509=dojo.event.browser.normalizedEventName(_509);
-if((_509=="onkey")||(_509=="key")){
-if(dojo.render.html.ie){
-this.addListener(node,"onkeydown",fp,_50b,_50c);
-}
-_509="onkeypress";
-}
-if(_509.substr(0,2)!="on"){
-_509="on"+_509;
-}
-if(!_50c){
-var _50d=function(evt){
-if(!evt){
-evt=window.event;
-}
-var ret=fp(dojo.event.browser.fixEvent(evt,this));
-if(_50b){
-dojo.event.browser.stopEvent(evt);
-}
-return ret;
-};
-}else{
-_50d=fp;
-}
-if(node.addEventListener){
-node.addEventListener(_509.substr(2),_50d,_50b);
-return _50d;
-}else{
-if(typeof node[_509]=="function"){
-var _510=node[_509];
-node[_509]=function(e){
-_510(e);
-return _50d(e);
-};
-}else{
-node[_509]=_50d;
-}
-if(dojo.render.html.ie){
-this.addClobberNodeAttrs(node,[_509]);
-}
-return _50d;
-}
-};
-this.isEvent=function(obj){
-return (typeof obj!="undefined")&&(typeof Event!="undefined")&&(obj.eventPhase);
-};
-this.currentEvent=null;
-this.callListener=function(_513,_514){
-if(typeof _513!="function"){
-dojo.raise("listener not a function: "+_513);
-}
-dojo.event.browser.currentEvent.currentTarget=_514;
-return _513.call(_514,dojo.event.browser.currentEvent);
-};
-this._stopPropagation=function(){
-dojo.event.browser.currentEvent.cancelBubble=true;
-};
-this._preventDefault=function(){
-dojo.event.browser.currentEvent.returnValue=false;
-};
-this.keys={KEY_BACKSPACE:8,KEY_TAB:9,KEY_CLEAR:12,KEY_ENTER:13,KEY_SHIFT:16,KEY_CTRL:17,KEY_ALT:18,KEY_PAUSE:19,KEY_CAPS_LOCK:20,KEY_ESCAPE:27,KEY_SPACE:32,KEY_PAGE_UP:33,KEY_PAGE_DOWN:34,KEY_END:35,KEY_HOME:36,KEY_LEFT_ARROW:37,KEY_UP_ARROW:38,KEY_RIGHT_ARROW:39,KEY_DOWN_ARROW:40,KEY_INSERT:45,KEY_DELETE:46,KEY_HELP:47,KEY_LEFT_WINDOW:91,KEY_RIGHT_WINDOW:92,KEY_SELECT:93,KEY_NUMPAD_0:96,KEY_NUMPAD_1:97,KEY_NUMPAD_2:98,KEY_NUMPAD_3:99,KEY_NUMPAD_4:100,KEY_NUMPAD_5:101,KEY_NUMPAD_6:102,KEY_NUMPAD_7:103,KEY_NUMPAD_8:104,KEY_NUMPAD_9:105,KEY_NUMPAD_MULTIPLY:106,KEY_NUMPAD_PLUS:107,KEY_NUMPAD_ENTER:108,KEY_NUMPAD_MINUS:109,KEY_NUMPAD_PERIOD:110,KEY_NUMPAD_DIVIDE:111,KEY_F1:112,KEY_F2:113,KEY_F3:114,KEY_F4:115,KEY_F5:116,KEY_F6:117,KEY_F7:118,KEY_F8:119,KEY_F9:120,KEY_F10:121,KEY_F11:122,KEY_F12:123,KEY_F13:124,KEY_F14:125,KEY_F15:126,KEY_NUM_LOCK:144,KEY_SCROLL_LOCK:145};
-this.revKeys=[];
-for(var key in this.keys){
-this.revKeys[this.keys[key]]=key;
-}
-this.fixEvent=function(evt,_517){
-if(!evt){
-if(window["event"]){
-evt=window.event;
-}
-}
-if((evt["type"])&&(evt["type"].indexOf("key")==0)){
-evt.keys=this.revKeys;
-for(var key in this.keys){
-evt[key]=this.keys[key];
-}
-if(evt["type"]=="keydown"&&dojo.render.html.ie){
-switch(evt.keyCode){
-case evt.KEY_SHIFT:
-case evt.KEY_CTRL:
-case evt.KEY_ALT:
-case evt.KEY_CAPS_LOCK:
-case evt.KEY_LEFT_WINDOW:
-case evt.KEY_RIGHT_WINDOW:
-case evt.KEY_SELECT:
-case evt.KEY_NUM_LOCK:
-case evt.KEY_SCROLL_LOCK:
-case evt.KEY_NUMPAD_0:
-case evt.KEY_NUMPAD_1:
-case evt.KEY_NUMPAD_2:
-case evt.KEY_NUMPAD_3:
-case evt.KEY_NUMPAD_4:
-case evt.KEY_NUMPAD_5:
-case evt.KEY_NUMPAD_6:
-case evt.KEY_NUMPAD_7:
-case evt.KEY_NUMPAD_8:
-case evt.KEY_NUMPAD_9:
-case evt.KEY_NUMPAD_PERIOD:
-break;
-case evt.KEY_NUMPAD_MULTIPLY:
-case evt.KEY_NUMPAD_PLUS:
-case evt.KEY_NUMPAD_ENTER:
-case evt.KEY_NUMPAD_MINUS:
-case evt.KEY_NUMPAD_DIVIDE:
-break;
-case evt.KEY_PAUSE:
-case evt.KEY_TAB:
-case evt.KEY_BACKSPACE:
-case evt.KEY_ENTER:
-case evt.KEY_ESCAPE:
-case evt.KEY_PAGE_UP:
-case evt.KEY_PAGE_DOWN:
-case evt.KEY_END:
-case evt.KEY_HOME:
-case evt.KEY_LEFT_ARROW:
-case evt.KEY_UP_ARROW:
-case evt.KEY_RIGHT_ARROW:
-case evt.KEY_DOWN_ARROW:
-case evt.KEY_INSERT:
-case evt.KEY_DELETE:
-case evt.KEY_F1:
-case evt.KEY_F2:
-case evt.KEY_F3:
-case evt.KEY_F4:
-case evt.KEY_F5:
-case evt.KEY_F6:
-case evt.KEY_F7:
-case evt.KEY_F8:
-case evt.KEY_F9:
-case evt.KEY_F10:
-case evt.KEY_F11:
-case evt.KEY_F12:
-case evt.KEY_F12:
-case evt.KEY_F13:
-case evt.KEY_F14:
-case evt.KEY_F15:
-case evt.KEY_CLEAR:
-case evt.KEY_HELP:
-evt.key=evt.keyCode;
-break;
-default:
-if(evt.ctrlKey||evt.altKey){
-var _519=evt.keyCode;
-if(_519>=65&&_519<=90&&evt.shiftKey==false){
-_519+=32;
-}
-if(_519>=1&&_519<=26&&evt.ctrlKey){
-_519+=96;
-}
-evt.key=String.fromCharCode(_519);
-}
-}
-}else{
-if(evt["type"]=="keypress"){
-if(dojo.render.html.opera){
-if(evt.which==0){
-evt.key=evt.keyCode;
-}else{
-if(evt.which>0){
-switch(evt.which){
-case evt.KEY_SHIFT:
-case evt.KEY_CTRL:
-case evt.KEY_ALT:
-case evt.KEY_CAPS_LOCK:
-case evt.KEY_NUM_LOCK:
-case evt.KEY_SCROLL_LOCK:
-break;
-case evt.KEY_PAUSE:
-case evt.KEY_TAB:
-case evt.KEY_BACKSPACE:
-case evt.KEY_ENTER:
-case evt.KEY_ESCAPE:
-evt.key=evt.which;
-break;
-default:
-var _519=evt.which;
-if((evt.ctrlKey||evt.altKey||evt.metaKey)&&(evt.which>=65&&evt.which<=90&&evt.shiftKey==false)){
-_519+=32;
-}
-evt.key=String.fromCharCode(_519);
-}
-}
-}
-}else{
-if(dojo.render.html.ie){
-if(!evt.ctrlKey&&!evt.altKey&&evt.keyCode>=evt.KEY_SPACE){
-evt.key=String.fromCharCode(evt.keyCode);
-}
-}else{
-if(dojo.render.html.safari){
-switch(evt.keyCode){
-case 63232:
-evt.key=evt.KEY_UP_ARROW;
-break;
-case 63233:
-evt.key=evt.KEY_DOWN_ARROW;
-break;
-case 63234:
-evt.key=evt.KEY_LEFT_ARROW;
-break;
-case 63235:
-evt.key=evt.KEY_RIGHT_ARROW;
-break;
-default:
-evt.key=evt.charCode>0?String.fromCharCode(evt.charCode):evt.keyCode;
-}
-}else{
-evt.key=evt.charCode>0?String.fromCharCode(evt.charCode):evt.keyCode;
-}
-}
-}
-}
-}
-}
-if(dojo.render.html.ie){
-if(!evt.target){
-evt.target=evt.srcElement;
-}
-if(!evt.currentTarget){
-evt.currentTarget=(_517?_517:evt.srcElement);
-}
-if(!evt.layerX){
-evt.layerX=evt.offsetX;
-}
-if(!evt.layerY){
-evt.layerY=evt.offsetY;
-}
-var doc=(evt.srcElement&&evt.srcElement.ownerDocument)?evt.srcElement.ownerDocument:document;
-var _51b=((dojo.render.html.ie55)||(doc["compatMode"]=="BackCompat"))?doc.body:doc.documentElement;
-if(!evt.pageX){
-evt.pageX=evt.clientX+(_51b.scrollLeft||0);
-}
-if(!evt.pageY){
-evt.pageY=evt.clientY+(_51b.scrollTop||0);
-}
-if(evt.type=="mouseover"){
-evt.relatedTarget=evt.fromElement;
-}
-if(evt.type=="mouseout"){
-evt.relatedTarget=evt.toElement;
-}
-this.currentEvent=evt;
-evt.callListener=this.callListener;
-evt.stopPropagation=this._stopPropagation;
-evt.preventDefault=this._preventDefault;
-}
-return evt;
-};
-this.stopEvent=function(evt){
-if(window.event){
-evt.returnValue=false;
-evt.cancelBubble=true;
-}else{
-evt.preventDefault();
-evt.stopPropagation();
-}
-};
-};
-dojo.provide("dojo.event.*");
-dojo.provide("dojo.logging.Logger");
-dojo.logging.Record=function(lvl,msg){
-this.level=lvl;
-this.message="";
-this.msgArgs=[];
-this.time=new Date();
-if(dojo.lang.isArray(msg)){
-if(msg.length>0&&dojo.lang.isString(msg[0])){
-this.message=msg.shift();
-}
-this.msgArgs=msg;
-}else{
-this.message=msg;
-}
-};
-dojo.logging.LogFilter=function(_51f){
-this.passChain=_51f||"";
-this.filter=function(_520){
-return true;
-};
-};
-dojo.logging.Logger=function(){
-this.cutOffLevel=0;
-this.propagate=true;
-this.parent=null;
-this.data=[];
-this.filters=[];
-this.handlers=[];
-};
-dojo.extend(dojo.logging.Logger,{argsToArr:function(args){
-var ret=[];
-for(var x=0;x<args.length;x++){
-ret.push(args[x]);
-}
-return ret;
-},setLevel:function(lvl){
-this.cutOffLevel=parseInt(lvl);
-},isEnabledFor:function(lvl){
-return parseInt(lvl)>=this.cutOffLevel;
-},getEffectiveLevel:function(){
-if((this.cutOffLevel==0)&&(this.parent)){
-return this.parent.getEffectiveLevel();
-}
-return this.cutOffLevel;
-},addFilter:function(flt){
-this.filters.push(flt);
-return this.filters.length-1;
-},removeFilterByIndex:function(_527){
-if(this.filters[_527]){
-delete this.filters[_527];
-return true;
-}
-return false;
-},removeFilter:function(_528){
-for(var x=0;x<this.filters.length;x++){
-if(this.filters[x]===_528){
-delete this.filters[x];
-return true;
-}
-}
-return false;
-},removeAllFilters:function(){
-this.filters=[];
-},filter:function(rec){
-for(var x=0;x<this.filters.length;x++){
-if((this.filters[x]["filter"])&&(!this.filters[x].filter(rec))||(rec.level<this.cutOffLevel)){
-return false;
-}
-}
-return true;
-},addHandler:function(hdlr){
-this.handlers.push(hdlr);
-return this.handlers.length-1;
-},handle:function(rec){
-if((!this.filter(rec))||(rec.level<this.cutOffLevel)){
-return false;
-}
-for(var x=0;x<this.handlers.length;x++){
-if(this.handlers[x]["handle"]){
-this.handlers[x].handle(rec);
-}
-}
-return true;
-},log:function(lvl,msg){
-if((this.propagate)&&(this.parent)&&(this.parent.rec.level>=this.cutOffLevel)){
-this.parent.log(lvl,msg);
-return false;
-}
-this.handle(new dojo.logging.Record(lvl,msg));
-return true;
-},debug:function(msg){
-return this.logType("DEBUG",this.argsToArr(arguments));
-},info:function(msg){
-return this.logType("INFO",this.argsToArr(arguments));
-},warning:function(msg){
-return this.logType("WARNING",this.argsToArr(arguments));
-},error:function(msg){
-return this.logType("ERROR",this.argsToArr(arguments));
-},critical:function(msg){
-return this.logType("CRITICAL",this.argsToArr(arguments));
-},exception:function(msg,e,_538){
-if(e){
-var _539=[e.name,(e.description||e.message)];
-if(e.fileName){
-_539.push(e.fileName);
-_539.push("line "+e.lineNumber);
-}
-msg+=" "+_539.join(" : ");
-}
-this.logType("ERROR",msg);
-if(!_538){
-throw e;
-}
-},logType:function(type,args){
-return this.log.apply(this,[dojo.logging.log.getLevel(type),args]);
-},warn:function(){
-this.warning.apply(this,arguments);
-},err:function(){
-this.error.apply(this,arguments);
-},crit:function(){
-this.critical.apply(this,arguments);
-}});
-dojo.logging.LogHandler=function(_53c){
-this.cutOffLevel=(_53c)?_53c:0;
-this.formatter=null;
-this.data=[];
-this.filters=[];
-};
-dojo.lang.extend(dojo.logging.LogHandler,{setFormatter:function(_53d){
-dojo.unimplemented("setFormatter");
-},flush:function(){
-},close:function(){
-},handleError:function(){
-},handle:function(_53e){
-if((this.filter(_53e))&&(_53e.level>=this.cutOffLevel)){
-this.emit(_53e);
-}
-},emit:function(_53f){
-dojo.unimplemented("emit");
-}});
-void (function(){
-var _540=["setLevel","addFilter","removeFilterByIndex","removeFilter","removeAllFilters","filter"];
-var tgt=dojo.logging.LogHandler.prototype;
-var src=dojo.logging.Logger.prototype;
-for(var x=0;x<_540.length;x++){
-tgt[_540[x]]=src[_540[x]];
-}
-})();
-dojo.logging.log=new dojo.logging.Logger();
-dojo.logging.log.levels=[{"name":"DEBUG","level":1},{"name":"INFO","level":2},{"name":"WARNING","level":3},{"name":"ERROR","level":4},{"name":"CRITICAL","level":5}];
-dojo.logging.log.loggers={};
-dojo.logging.log.getLogger=function(name){
-if(!this.loggers[name]){
-this.loggers[name]=new dojo.logging.Logger();
-this.loggers[name].parent=this;
-}
-return this.loggers[name];
-};
-dojo.logging.log.getLevelName=function(lvl){
-for(var x=0;x<this.levels.length;x++){
-if(this.levels[x].level==lvl){
-return this.levels[x].name;
-}
-}
-return null;
-};
-dojo.logging.log.addLevelName=function(name,lvl){
-if(this.getLevelName(name)){
-this.err("could not add log level "+name+" because a level with that name already exists");
-return false;
-}
-this.levels.append({"name":name,"level":parseInt(lvl)});
-return true;
-};
-dojo.logging.log.getLevel=function(name){
-for(var x=0;x<this.levels.length;x++){
-if(this.levels[x].name.toUpperCase()==name.toUpperCase()){
-return this.levels[x].level;
-}
-}
-return null;
-};
-dojo.logging.MemoryLogHandler=function(_54b,_54c,_54d,_54e){
-dojo.logging.LogHandler.call(this,_54b);
-this.numRecords=(typeof djConfig["loggingNumRecords"]!="undefined")?djConfig["loggingNumRecords"]:((_54c)?_54c:-1);
-this.postType=(typeof djConfig["loggingPostType"]!="undefined")?djConfig["loggingPostType"]:(_54d||-1);
-this.postInterval=(typeof djConfig["loggingPostInterval"]!="undefined")?djConfig["loggingPostInterval"]:(_54d||-1);
-};
-dojo.lang.inherits(dojo.logging.MemoryLogHandler,dojo.logging.LogHandler);
-dojo.lang.extend(dojo.logging.MemoryLogHandler,{emit:function(_54f){
-if(!djConfig.isDebug){
-return;
-}
-var _550=String(dojo.log.getLevelName(_54f.level)+": "+_54f.time.toLocaleTimeString())+": "+_54f.message;
-if(!dj_undef("println",dojo.hostenv)){
-dojo.hostenv.println(_550);
-}
-this.data.push(_54f);
-if(this.numRecords!=-1){
-while(this.data.length>this.numRecords){
-this.data.shift();
-}
-}
-}});
-dojo.logging.logQueueHandler=new dojo.logging.MemoryLogHandler(0,50,0,10000);
-dojo.logging.log.addHandler(dojo.logging.logQueueHandler);
-dojo.log=dojo.logging.log;
-dojo.provide("dojo.logging.*");
-dojo.provide("dojo.string.common");
-dojo.string.trim=function(str,wh){
-if(!str.replace){
-return str;
-}
-if(!str.length){
-return str;
-}
-var re=(wh>0)?(/^\s+/):(wh<0)?(/\s+$/):(/^\s+|\s+$/g);
-return str.replace(re,"");
-};
-dojo.string.trimStart=function(str){
-return dojo.string.trim(str,1);
-};
-dojo.string.trimEnd=function(str){
-return dojo.string.trim(str,-1);
-};
-dojo.string.repeat=function(str,_557,_558){
-var out="";
-for(var i=0;i<_557;i++){
-out+=str;
-if(_558&&i<_557-1){
-out+=_558;
-}
-}
-return out;
-};
-dojo.string.pad=function(str,len,c,dir){
-var out=String(str);
-if(!c){
-c="0";
-}
-if(!dir){
-dir=1;
-}
-while(out.length<len){
-if(dir>0){
-out=c+out;
-}else{
-out+=c;
-}
-}
-return out;
-};
-dojo.string.padLeft=function(str,len,c){
-return dojo.string.pad(str,len,c,1);
-};
-dojo.string.padRight=function(str,len,c){
-return dojo.string.pad(str,len,c,-1);
-};
-dojo.provide("dojo.string");
-dojo.provide("dojo.io.common");
-dojo.io.transports=[];
-dojo.io.hdlrFuncNames=["load","error","timeout"];
-dojo.io.Request=function(url,_567,_568,_569){
-if((arguments.length==1)&&(arguments[0].constructor==Object)){
-this.fromKwArgs(arguments[0]);
-}else{
-this.url=url;
-if(_567){
-this.mimetype=_567;
-}
-if(_568){
-this.transport=_568;
-}
-if(arguments.length>=4){
-this.changeUrl=_569;
-}
-}
-};
-dojo.lang.extend(dojo.io.Request,{url:"",mimetype:"text/plain",method:"GET",content:undefined,transport:undefined,changeUrl:undefined,formNode:undefined,sync:false,bindSuccess:false,useCache:false,preventCache:false,load:function(type,data,_56c,_56d){
-},error:function(type,_56f,_570,_571){
-},timeout:function(type,_573,_574,_575){
-},handle:function(type,data,_578,_579){
-},timeoutSeconds:0,abort:function(){
-},fromKwArgs:function(_57a){
-if(_57a["url"]){
-_57a.url=_57a.url.toString();
-}
-if(_57a["formNode"]){
-_57a.formNode=dojo.byId(_57a.formNode);
-}
-if(!_57a["method"]&&_57a["formNode"]&&_57a["formNode"].method){
-_57a.method=_57a["formNode"].method;
-}
-if(!_57a["handle"]&&_57a["handler"]){
-_57a.handle=_57a.handler;
-}
-if(!_57a["load"]&&_57a["loaded"]){
-_57a.load=_57a.loaded;
-}
-if(!_57a["changeUrl"]&&_57a["changeURL"]){
-_57a.changeUrl=_57a.changeURL;
-}
-_57a.encoding=dojo.lang.firstValued(_57a["encoding"],djConfig["bindEncoding"],"");
-_57a.sendTransport=dojo.lang.firstValued(_57a["sendTransport"],djConfig["ioSendTransport"],false);
-var _57b=dojo.lang.isFunction;
-for(var x=0;x<dojo.io.hdlrFuncNames.length;x++){
-var fn=dojo.io.hdlrFuncNames[x];
-if(_57a[fn]&&_57b(_57a[fn])){
-continue;
-}
-if(_57a["handle"]&&_57b(_57a["handle"])){
-_57a[fn]=_57a.handle;
-}
-}
-dojo.lang.mixin(this,_57a);
-}});
-dojo.io.Error=function(msg,type,num){
-this.message=msg;
-this.type=type||"unknown";
-this.number=num||0;
-};
-dojo.io.transports.addTransport=function(name){
-this.push(name);
-this[name]=dojo.io[name];
-};
-dojo.io.bind=function(_582){
-if(!(_582 instanceof dojo.io.Request)){
-try{
-_582=new dojo.io.Request(_582);
-}
-catch(e){
-dojo.debug(e);
-}
-}
-var _583="";
-if(_582["transport"]){
-_583=_582["transport"];
-if(!this[_583]){
-dojo.io.sendBindError(_582,"No dojo.io.bind() transport with name '"+_582["transport"]+"'.");
-return _582;
-}
-if(!this[_583].canHandle(_582)){
-dojo.io.sendBindError(_582,"dojo.io.bind() transport with name '"+_582["transport"]+"' cannot handle this type of request.");
-return _582;
-}
-}else{
-for(var x=0;x<dojo.io.transports.length;x++){
-var tmp=dojo.io.transports[x];
-if((this[tmp])&&(this[tmp].canHandle(_582))){
-_583=tmp;
-break;
-}
-}
-if(_583==""){
-dojo.io.sendBindError(_582,"None of the loaded transports for dojo.io.bind()"+" can handle the request.");
-return _582;
-}
-}
-this[_583].bind(_582);
-_582.bindSuccess=true;
-return _582;
-};
-dojo.io.sendBindError=function(_586,_587){
-if((typeof _586.error=="function"||typeof _586.handle=="function")&&(typeof setTimeout=="function"||typeof setTimeout=="object")){
-var _588=new dojo.io.Error(_587);
-setTimeout(function(){
-_586[(typeof _586.error=="function")?"error":"handle"]("error",_588,null,_586);
-},50);
-}else{
-dojo.raise(_587);
-}
-};
-dojo.io.queueBind=function(_589){
-if(!(_589 instanceof dojo.io.Request)){
-try{
-_589=new dojo.io.Request(_589);
-}
-catch(e){
-dojo.debug(e);
-}
-}
-var _58a=_589.load;
-_589.load=function(){
-dojo.io._queueBindInFlight=false;
-var ret=_58a.apply(this,arguments);
-dojo.io._dispatchNextQueueBind();
-return ret;
-};
-var _58c=_589.error;
-_589.error=function(){
-dojo.io._queueBindInFlight=false;
-var ret=_58c.apply(this,arguments);
-dojo.io._dispatchNextQueueBind();
-return ret;
-};
-dojo.io._bindQueue.push(_589);
-dojo.io._dispatchNextQueueBind();
-return _589;
-};
-dojo.io._dispatchNextQueueBind=function(){
-if(!dojo.io._queueBindInFlight){
-dojo.io._queueBindInFlight=true;
-if(dojo.io._bindQueue.length>0){
-dojo.io.bind(dojo.io._bindQueue.shift());
-}else{
-dojo.io._queueBindInFlight=false;
-}
-}
-};
-dojo.io._bindQueue=[];
-dojo.io._queueBindInFlight=false;
-dojo.io.argsFromMap=function(map,_58f,last){
-var enc=/utf/i.test(_58f||"")?encodeURIComponent:dojo.string.encodeAscii;
-var _592=[];
-var _593=new Object();
-for(var name in map){
-var _595=function(elt){
-var val=enc(name)+"="+enc(elt);
-_592[(last==name)?"push":"unshift"](val);
-};
-if(!_593[name]){
-var _598=map[name];
-if(dojo.lang.isArray(_598)){
-dojo.lang.forEach(_598,_595);
-}else{
-_595(_598);
-}
-}
-}
-return _592.join("&");
-};
-dojo.io.setIFrameSrc=function(_599,src,_59b){
-try{
-var r=dojo.render.html;
-if(!_59b){
-if(r.safari){
-_599.location=src;
-}else{
-frames[_599.name].location=src;
-}
-}else{
-var idoc;
-if(r.ie){
-idoc=_599.contentWindow.document;
-}else{
-if(r.safari){
-idoc=_599.document;
-}else{
-idoc=_599.contentWindow;
-}
-}
-if(!idoc){
-_599.location=src;
-return;
-}else{
-idoc.location.replace(src);
-}
-}
-}
-catch(e){
-dojo.debug(e);
-dojo.debug("setIFrameSrc: "+e);
-}
-};
-dojo.provide("dojo.string.extras");
-dojo.string.substituteParams=function(_59e,hash){
-var map=(typeof hash=="object")?hash:dojo.lang.toArray(arguments,1);
-return _59e.replace(/\%\{(\w+)\}/g,function(_5a1,key){
-if(typeof (map[key])!="undefined"&&map[key]!=null){
-return map[key];
-}
-dojo.raise("Substitution not found: "+key);
-});
-};
-dojo.string.capitalize=function(str){
-if(!dojo.lang.isString(str)){
-return "";
-}
-if(arguments.length==0){
-str=this;
-}
-var _5a4=str.split(" ");
-for(var i=0;i<_5a4.length;i++){
-_5a4[i]=_5a4[i].charAt(0).toUpperCase()+_5a4[i].substring(1);
-}
-return _5a4.join(" ");
-};
-dojo.string.isBlank=function(str){
-if(!dojo.lang.isString(str)){
-return true;
-}
-return (dojo.string.trim(str).length==0);
-};
-dojo.string.encodeAscii=function(str){
-if(!dojo.lang.isString(str)){
-return str;
-}
-var ret="";
-var _5a9=escape(str);
-var _5aa,re=/%u([0-9A-F]{4})/i;
-while((_5aa=_5a9.match(re))){
-var num=Number("0x"+_5aa[1]);
-var _5ad=escape("&#"+num+";");
-ret+=_5a9.substring(0,_5aa.index)+_5ad;
-_5a9=_5a9.substring(_5aa.index+_5aa[0].length);
-}
-ret+=_5a9.replace(/\+/g,"%2B");
-return ret;
-};
-dojo.string.escape=function(type,str){
-var args=dojo.lang.toArray(arguments,1);
-switch(type.toLowerCase()){
-case "xml":
-case "html":
-case "xhtml":
-return dojo.string.escapeXml.apply(this,args);
-case "sql":
-return dojo.string.escapeSql.apply(this,args);
-case "regexp":
-case "regex":
-return dojo.string.escapeRegExp.apply(this,args);
-case "javascript":
-case "jscript":
-case "js":
-return dojo.string.escapeJavaScript.apply(this,args);
-case "ascii":
-return dojo.string.encodeAscii.apply(this,args);
-default:
-return str;
-}
-};
-dojo.string.escapeXml=function(str,_5b2){
-str=str.replace(/&/gm,"&amp;").replace(/</gm,"&lt;").replace(/>/gm,"&gt;").replace(/"/gm,"&quot;");
-if(!_5b2){
-str=str.replace(/'/gm,"&#39;");
-}
-return str;
-};
-dojo.string.escapeSql=function(str){
-return str.replace(/'/gm,"''");
-};
-dojo.string.escapeRegExp=function(str){
-return str.replace(/\\/gm,"\\\\").replace(/([\f\b\n\t\r[\^$|?*+(){}])/gm,"\\$1");
-};
-dojo.string.escapeJavaScript=function(str){
-return str.replace(/(["'\f\b\n\t\r])/gm,"\\$1");
-};
-dojo.string.escapeString=function(str){
-return ("\""+str.replace(/(["\\])/g,"\\$1")+"\"").replace(/[\f]/g,"\\f").replace(/[\b]/g,"\\b").replace(/[\n]/g,"\\n").replace(/[\t]/g,"\\t").replace(/[\r]/g,"\\r");
-};
-dojo.string.summary=function(str,len){
-if(!len||str.length<=len){
-return str;
-}
-return str.substring(0,len).replace(/\.+$/,"")+"...";
-};
-dojo.string.endsWith=function(str,end,_5bb){
-if(_5bb){
-str=str.toLowerCase();
-end=end.toLowerCase();
-}
-if((str.length-end.length)<0){
-return false;
-}
-return str.lastIndexOf(end)==str.length-end.length;
-};
-dojo.string.endsWithAny=function(str){
-for(var i=1;i<arguments.length;i++){
-if(dojo.string.endsWith(str,arguments[i])){
-return true;
-}
-}
-return false;
-};
-dojo.string.startsWith=function(str,_5bf,_5c0){
-if(_5c0){
-str=str.toLowerCase();
-_5bf=_5bf.toLowerCase();
-}
-return str.indexOf(_5bf)==0;
-};
-dojo.string.startsWithAny=function(str){
-for(var i=1;i<arguments.length;i++){
-if(dojo.string.startsWith(str,arguments[i])){
-return true;
-}
-}
-return false;
-};
-dojo.string.has=function(str){
-for(var i=1;i<arguments.length;i++){
-if(str.indexOf(arguments[i])>-1){
-return true;
-}
-}
-return false;
-};
-dojo.string.normalizeNewlines=function(text,_5c6){
-if(_5c6=="\n"){
-text=text.replace(/\r\n/g,"\n");
-text=text.replace(/\r/g,"\n");
-}else{
-if(_5c6=="\r"){
-text=text.replace(/\r\n/g,"\r");
-text=text.replace(/\n/g,"\r");
-}else{
-text=text.replace(/([^\r])\n/g,"$1\r\n").replace(/\r([^\n])/g,"\r\n$1");
-}
-}
-return text;
-};
-dojo.string.splitEscaped=function(str,_5c8){
-var _5c9=[];
-for(var i=0,_5cb=0;i<str.length;i++){
-if(str.charAt(i)=="\\"){
-i++;
-continue;
-}
-if(str.charAt(i)==_5c8){
-_5c9.push(str.substring(_5cb,i));
-_5cb=i+1;
-}
-}
-_5c9.push(str.substr(_5cb));
-return _5c9;
-};
-dojo.provide("dojo.undo.browser");
-try{
-if((!djConfig["preventBackButtonFix"])&&(!dojo.hostenv.post_load_)){
-document.write("<iframe style='border: 0px; width: 1px; height: 1px; position: absolute; bottom: 0px; right: 0px; visibility: visible;' name='djhistory' id='djhistory' src='"+(dojo.hostenv.getBaseScriptUri()+"iframe_history.html")+"'></iframe>");
-}
-}
-catch(e){
-}
-if(dojo.render.html.opera){
-dojo.debug("Opera is not supported with dojo.undo.browser, so back/forward detection will not work.");
-}
-dojo.undo.browser={initialHref:window.location.href,initialHash:window.location.hash,moveForward:false,historyStack:[],forwardStack:[],historyIframe:null,bookmarkAnchor:null,locationTimer:null,setInitialState:function(args){
-this.initialState=this._createState(this.initialHref,args,this.initialHash);
-},addToHistory:function(args){
-this.forwardStack=[];
-var hash=null;
-var url=null;
-if(!this.historyIframe){
-this.historyIframe=window.frames["djhistory"];
-}
-if(!this.bookmarkAnchor){
-this.bookmarkAnchor=document.createElement("a");
-dojo.body().appendChild(this.bookmarkAnchor);
-this.bookmarkAnchor.style.display="none";
-}
-if(args["changeUrl"]){
-hash="#"+((args["changeUrl"]!==true)?args["changeUrl"]:(new Date()).getTime());
-if(this.historyStack.length==0&&this.initialState.urlHash==hash){
-this.initialState=this._createState(url,args,hash);
-return;
-}else{
-if(this.historyStack.length>0&&this.historyStack[this.historyStack.length-1].urlHash==hash){
-this.historyStack[this.historyStack.length-1]=this._createState(url,args,hash);
-return;
-}
-}
-this.changingUrl=true;
-setTimeout("window.location.href = '"+hash+"'; dojo.undo.browser.changingUrl = false;",1);
-this.bookmarkAnchor.href=hash;
-if(dojo.render.html.ie){
-url=this._loadIframeHistory();
-var _5d0=args["back"]||args["backButton"]||args["handle"];
-var tcb=function(_5d2){
-if(window.location.hash!=""){
-setTimeout("window.location.href = '"+hash+"';",1);
-}
-_5d0.apply(this,[_5d2]);
-};
-if(args["back"]){
-args.back=tcb;
-}else{
-if(args["backButton"]){
-args.backButton=tcb;
-}else{
-if(args["handle"]){
-args.handle=tcb;
-}
-}
-}
-var _5d3=args["forward"]||args["forwardButton"]||args["handle"];
-var tfw=function(_5d5){
-if(window.location.hash!=""){
-window.location.href=hash;
-}
-if(_5d3){
-_5d3.apply(this,[_5d5]);
-}
-};
-if(args["forward"]){
-args.forward=tfw;
-}else{
-if(args["forwardButton"]){
-args.forwardButton=tfw;
-}else{
-if(args["handle"]){
-args.handle=tfw;
-}
-}
-}
-}else{
-if(dojo.render.html.moz){
-if(!this.locationTimer){
-this.locationTimer=setInterval("dojo.undo.browser.checkLocation();",200);
-}
-}
-}
-}else{
-url=this._loadIframeHistory();
-}
-this.historyStack.push(this._createState(url,args,hash));
-},checkLocation:function(){
-if(!this.changingUrl){
-var hsl=this.historyStack.length;
-if((window.location.hash==this.initialHash||window.location.href==this.initialHref)&&(hsl==1)){
-this.handleBackButton();
-return;
-}
-if(this.forwardStack.length>0){
-if(this.forwardStack[this.forwardStack.length-1].urlHash==window.location.hash){
-this.handleForwardButton();
-return;
-}
-}
-if((hsl>=2)&&(this.historyStack[hsl-2])){
-if(this.historyStack[hsl-2].urlHash==window.location.hash){
-this.handleBackButton();
-return;
-}
-}
-}
-},iframeLoaded:function(evt,_5d8){
-if(!dojo.render.html.opera){
-var _5d9=this._getUrlQuery(_5d8.href);
-if(_5d9==null){
-if(this.historyStack.length==1){
-this.handleBackButton();
-}
-return;
-}
-if(this.moveForward){
-this.moveForward=false;
-return;
-}
-if(this.historyStack.length>=2&&_5d9==this._getUrlQuery(this.historyStack[this.historyStack.length-2].url)){
-this.handleBackButton();
-}else{
-if(this.forwardStack.length>0&&_5d9==this._getUrlQuery(this.forwardStack[this.forwardStack.length-1].url)){
-this.handleForwardButton();
-}
-}
-}
-},handleBackButton:function(){
-var _5da=this.historyStack.pop();
-if(!_5da){
-return;
-}
-var last=this.historyStack[this.historyStack.length-1];
-if(!last&&this.historyStack.length==0){
-last=this.initialState;
-}
-if(last){
-if(last.kwArgs["back"]){
-last.kwArgs["back"]();
-}else{
-if(last.kwArgs["backButton"]){
-last.kwArgs["backButton"]();
-}else{
-if(last.kwArgs["handle"]){
-last.kwArgs.handle("back");
-}
-}
-}
-}
-this.forwardStack.push(_5da);
-},handleForwardButton:function(){
-var last=this.forwardStack.pop();
-if(!last){
-return;
-}
-if(last.kwArgs["forward"]){
-last.kwArgs.forward();
-}else{
-if(last.kwArgs["forwardButton"]){
-last.kwArgs.forwardButton();
-}else{
-if(last.kwArgs["handle"]){
-last.kwArgs.handle("forward");
-}
-}
-}
-this.historyStack.push(last);
-},_createState:function(url,args,hash){
-return {"url":url,"kwArgs":args,"urlHash":hash};
-},_getUrlQuery:function(url){
-var _5e1=url.split("?");
-if(_5e1.length<2){
-return null;
-}else{
-return _5e1[1];
-}
-},_loadIframeHistory:function(){
-var url=dojo.hostenv.getBaseScriptUri()+"iframe_history.html?"+(new Date()).getTime();
-this.moveForward=true;
-dojo.io.setIFrameSrc(this.historyIframe,url,false);
-return url;
-}};
-dojo.provide("dojo.io.BrowserIO");
-dojo.io.checkChildrenForFile=function(node){
-var _5e4=false;
-var _5e5=node.getElementsByTagName("input");
-dojo.lang.forEach(_5e5,function(_5e6){
-if(_5e4){
-return;
-}
-if(_5e6.getAttribute("type")=="file"){
-_5e4=true;
-}
-});
-return _5e4;
-};
-dojo.io.formHasFile=function(_5e7){
-return dojo.io.checkChildrenForFile(_5e7);
-};
-dojo.io.updateNode=function(node,_5e9){
-node=dojo.byId(node);
-var args=_5e9;
-if(dojo.lang.isString(_5e9)){
-args={url:_5e9};
-}
-args.mimetype="text/html";
-args.load=function(t,d,e){
-while(node.firstChild){
-if(dojo["event"]){
-try{
-dojo.event.browser.clean(node.firstChild);
-}
-catch(e){
-}
-}
-node.removeChild(node.firstChild);
-}
-node.innerHTML=d;
-};
-dojo.io.bind(args);
-};
-dojo.io.formFilter=function(node){
-var type=(node.type||"").toLowerCase();
-return !node.disabled&&node.name&&!dojo.lang.inArray(["file","submit","image","reset","button"],type);
-};
-dojo.io.encodeForm=function(_5f0,_5f1,_5f2){
-if((!_5f0)||(!_5f0.tagName)||(!_5f0.tagName.toLowerCase()=="form")){
-dojo.raise("Attempted to encode a non-form element.");
-}
-if(!_5f2){
-_5f2=dojo.io.formFilter;
-}
-var enc=/utf/i.test(_5f1||"")?encodeURIComponent:dojo.string.encodeAscii;
-var _5f4=[];
-for(var i=0;i<_5f0.elements.length;i++){
-var elm=_5f0.elements[i];
-if(!elm||elm.tagName.toLowerCase()=="fieldset"||!_5f2(elm)){
-continue;
-}
-var name=enc(elm.name);
-var type=elm.type.toLowerCase();
-if(type=="select-multiple"){
-for(var j=0;j<elm.options.length;j++){
-if(elm.options[j].selected){
-_5f4.push(name+"="+enc(elm.options[j].value));
-}
-}
-}else{
-if(dojo.lang.inArray(["radio","checkbox"],type)){
-if(elm.checked){
-_5f4.push(name+"="+enc(elm.value));
-}
-}else{
-_5f4.push(name+"="+enc(elm.value));
-}
-}
-}
-var _5fa=_5f0.getElementsByTagName("input");
-for(var i=0;i<_5fa.length;i++){
-var _5fb=_5fa[i];
-if(_5fb.type.toLowerCase()=="image"&&_5fb.form==_5f0&&_5f2(_5fb)){
-var name=enc(_5fb.name);
-_5f4.push(name+"="+enc(_5fb.value));
-_5f4.push(name+".x=0");
-_5f4.push(name+".y=0");
-}
-}
-return _5f4.join("&")+"&";
-};
-dojo.io.FormBind=function(args){
-this.bindArgs={};
-if(args&&args.formNode){
-this.init(args);
-}else{
-if(args){
-this.init({formNode:args});
-}
-}
-};
-dojo.lang.extend(dojo.io.FormBind,{form:null,bindArgs:null,clickedButton:null,init:function(args){
-var form=dojo.byId(args.formNode);
-if(!form||!form.tagName||form.tagName.toLowerCase()!="form"){
-throw new Error("FormBind: Couldn't apply, invalid form");
-}else{
-if(this.form==form){
-return;
-}else{
-if(this.form){
-throw new Error("FormBind: Already applied to a form");
-}
-}
-}
-dojo.lang.mixin(this.bindArgs,args);
-this.form=form;
-this.connect(form,"onsubmit","submit");
-for(var i=0;i<form.elements.length;i++){
-var node=form.elements[i];
-if(node&&node.type&&dojo.lang.inArray(["submit","button"],node.type.toLowerCase())){
-this.connect(node,"onclick","click");
-}
-}
-var _601=form.getElementsByTagName("input");
-for(var i=0;i<_601.length;i++){
-var _602=_601[i];
-if(_602.type.toLowerCase()=="image"&&_602.form==form){
-this.connect(_602,"onclick","click");
-}
-}
-},onSubmit:function(form){
-return true;
-},submit:function(e){
-e.preventDefault();
-if(this.onSubmit(this.form)){
-dojo.io.bind(dojo.lang.mixin(this.bindArgs,{formFilter:dojo.lang.hitch(this,"formFilter")}));
-}
-},click:function(e){
-var node=e.currentTarget;
-if(node.disabled){
-return;
-}
-this.clickedButton=node;
-},formFilter:function(node){
-var type=(node.type||"").toLowerCase();
-var _609=false;
-if(node.disabled||!node.name){
-_609=false;
-}else{
-if(dojo.lang.inArray(["submit","button","image"],type)){
-if(!this.clickedButton){
-this.clickedButton=node;
-}
-_609=node==this.clickedButton;
-}else{
-_609=!dojo.lang.inArray(["file","submit","reset","button"],type);
-}
-}
-return _609;
-},connect:function(_60a,_60b,_60c){
-if(dojo.evalObjPath("dojo.event.connect")){
-dojo.event.connect(_60a,_60b,this,_60c);
-}else{
-var fcn=dojo.lang.hitch(this,_60c);
-_60a[_60b]=function(e){
-if(!e){
-e=window.event;
-}
-if(!e.currentTarget){
-e.currentTarget=e.srcElement;
-}
-if(!e.preventDefault){
-e.preventDefault=function(){
-window.event.returnValue=false;
-};
-}
-fcn(e);
-};
-}
-}});
-dojo.io.XMLHTTPTransport=new function(){
-var _60f=this;
-var _610={};
-this.useCache=false;
-this.preventCache=false;
-function getCacheKey(url,_612,_613){
-return url+"|"+_612+"|"+_613.toLowerCase();
-}
-function addToCache(url,_615,_616,http){
-_610[getCacheKey(url,_615,_616)]=http;
-}
-function getFromCache(url,_619,_61a){
-return _610[getCacheKey(url,_619,_61a)];
-}
-this.clearCache=function(){
-_610={};
-};
-function doLoad(_61b,http,url,_61e,_61f){
-if(((http.status>=200)&&(http.status<300))||(http.status==304)||(location.protocol=="file:"&&(http.status==0||http.status==undefined))||(location.protocol=="chrome:"&&(http.status==0||http.status==undefined))){
-var ret;
-if(_61b.method.toLowerCase()=="head"){
-var _621=http.getAllResponseHeaders();
-ret={};
-ret.toString=function(){
-return _621;
-};
-var _622=_621.split(/[\r\n]+/g);
-for(var i=0;i<_622.length;i++){
-var pair=_622[i].match(/^([^:]+)\s*:\s*(.+)$/i);
-if(pair){
-ret[pair[1]]=pair[2];
-}
-}
-}else{
-if(_61b.mimetype=="text/javascript"){
-try{
-ret=dj_eval(http.responseText);
-}
-catch(e){
-dojo.debug(e);
-dojo.debug(http.responseText);
-ret=null;
-}
-}else{
-if(_61b.mimetype=="text/json"||_61b.mimetype=="application/json"){
-try{
-ret=dj_eval("("+http.responseText+")");
-}
-catch(e){
-dojo.debug(e);
-dojo.debug(http.responseText);
-ret=false;
-}
-}else{
-if((_61b.mimetype=="application/xml")||(_61b.mimetype=="text/xml")){
-ret=http.responseXML;
-if(!ret||typeof ret=="string"||!http.getResponseHeader("Content-Type")){
-ret=dojo.dom.createDocumentFromText(http.responseText);
-}
-}else{
-ret=http.responseText;
-}
-}
-}
-}
-if(_61f){
-addToCache(url,_61e,_61b.method,http);
-}
-_61b[(typeof _61b.load=="function")?"load":"handle"]("load",ret,http,_61b);
-}else{
-var _625=new dojo.io.Error("XMLHttpTransport Error: "+http.status+" "+http.statusText);
-_61b[(typeof _61b.error=="function")?"error":"handle"]("error",_625,http,_61b);
-}
-}
-function setHeaders(http,_627){
-if(_627["headers"]){
-for(var _628 in _627["headers"]){
-if(_628.toLowerCase()=="content-type"&&!_627["contentType"]){
-_627["contentType"]=_627["headers"][_628];
-}else{
-http.setRequestHeader(_628,_627["headers"][_628]);
-}
-}
-}
-}
-this.inFlight=[];
-this.inFlightTimer=null;
-this.startWatchingInFlight=function(){
-if(!this.inFlightTimer){
-this.inFlightTimer=setTimeout("dojo.io.XMLHTTPTransport.watchInFlight();",10);
-}
-};
-this.watchInFlight=function(){
-var now=null;
-if(!dojo.hostenv._blockAsync&&!_60f._blockAsync){
-for(var x=this.inFlight.length-1;x>=0;x--){
-try{
-var tif=this.inFlight[x];
-if(!tif||tif.http._aborted||!tif.http.readyState){
-this.inFlight.splice(x,1);
-continue;
-}
-if(4==tif.http.readyState){
-this.inFlight.splice(x,1);
-doLoad(tif.req,tif.http,tif.url,tif.query,tif.useCache);
-}else{
-if(tif.startTime){
-if(!now){
-now=(new Date()).getTime();
-}
-if(tif.startTime+(tif.req.timeoutSeconds*1000)<now){
-if(typeof tif.http.abort=="function"){
-tif.http.abort();
-}
-this.inFlight.splice(x,1);
-tif.req[(typeof tif.req.timeout=="function")?"timeout":"handle"]("timeout",null,tif.http,tif.req);
-}
-}
-}
-}
-catch(e){
-try{
-var _62c=new dojo.io.Error("XMLHttpTransport.watchInFlight Error: "+e);
-tif.req[(typeof tif.req.error=="function")?"error":"handle"]("error",_62c,tif.http,tif.req);
-}
-catch(e2){
-dojo.debug("XMLHttpTransport error callback failed: "+e2);
-}
-}
-}
-}
-clearTimeout(this.inFlightTimer);
-if(this.inFlight.length==0){
-this.inFlightTimer=null;
-return;
-}
-this.inFlightTimer=setTimeout("dojo.io.XMLHTTPTransport.watchInFlight();",10);
-};
-var _62d=dojo.hostenv.getXmlhttpObject()?true:false;
-this.canHandle=function(_62e){
-return _62d&&dojo.lang.inArray(["text/plain","text/html","application/xml","text/xml","text/javascript","text/json","application/json"],(_62e["mimetype"].toLowerCase()||""))&&!(_62e["formNode"]&&dojo.io.formHasFile(_62e["formNode"]));
-};
-this.multipartBoundary="45309FFF-BD65-4d50-99C9-36986896A96F";
-this.bind=function(_62f){
-if(!_62f["url"]){
-if(!_62f["formNode"]&&(_62f["backButton"]||_62f["back"]||_62f["changeUrl"]||_62f["watchForURL"])&&(!djConfig.preventBackButtonFix)){
-dojo.deprecated("Using dojo.io.XMLHTTPTransport.bind() to add to browser history without doing an IO request","Use dojo.undo.browser.addToHistory() instead.","0.4");
-dojo.undo.browser.addToHistory(_62f);
-return true;
-}
-}
-var url=_62f.url;
-var _631="";
-if(_62f["formNode"]){
-var ta=_62f.formNode.getAttribute("action");
-if((ta)&&(!_62f["url"])){
-url=ta;
-}
-var tp=_62f.formNode.getAttribute("method");
-if((tp)&&(!_62f["method"])){
-_62f.method=tp;
-}
-_631+=dojo.io.encodeForm(_62f.formNode,_62f.encoding,_62f["formFilter"]);
-}
-if(url.indexOf("#")>-1){
-dojo.debug("Warning: dojo.io.bind: stripping hash values from url:",url);
-url=url.split("#")[0];
-}
-if(_62f["file"]){
-_62f.method="post";
-}
-if(!_62f["method"]){
-_62f.method="get";
-}
-if(_62f.method.toLowerCase()=="get"){
-_62f.multipart=false;
-}else{
-if(_62f["file"]){
-_62f.multipart=true;
-}else{
-if(!_62f["multipart"]){
-_62f.multipart=false;
-}
-}
-}
-if(_62f["backButton"]||_62f["back"]||_62f["changeUrl"]){
-dojo.undo.browser.addToHistory(_62f);
-}
-var _634=_62f["content"]||{};
-if(_62f.sendTransport){
-_634["dojo.transport"]="xmlhttp";
-}
-do{
-if(_62f.postContent){
-_631=_62f.postContent;
-break;
-}
-if(_634){
-_631+=dojo.io.argsFromMap(_634,_62f.encoding);
-}
-if(_62f.method.toLowerCase()=="get"||!_62f.multipart){
-break;
-}
-var t=[];
-if(_631.length){
-var q=_631.split("&");
-for(var i=0;i<q.length;++i){
-if(q[i].length){
-var p=q[i].split("=");
-t.push("--"+this.multipartBoundary,"Content-Disposition: form-data; name=\""+p[0]+"\"","",p[1]);
-}
-}
-}
-if(_62f.file){
-if(dojo.lang.isArray(_62f.file)){
-for(var i=0;i<_62f.file.length;++i){
-var o=_62f.file[i];
-t.push("--"+this.multipartBoundary,"Content-Disposition: form-data; name=\""+o.name+"\"; filename=\""+("fileName" in o?o.fileName:o.name)+"\"","Content-Type: "+("contentType" in o?o.contentType:"application/octet-stream"),"",o.content);
-}
-}else{
-var o=_62f.file;
-t.push("--"+this.multipartBoundary,"Content-Disposition: form-data; name=\""+o.name+"\"; filename=\""+("fileName" in o?o.fileName:o.name)+"\"","Content-Type: "+("contentType" in o?o.contentType:"application/octet-stream"),"",o.content);
-}
-}
-if(t.length){
-t.push("--"+this.multipartBoundary+"--","");
-_631=t.join("\r\n");
-}
-}while(false);
-var _63a=_62f["sync"]?false:true;
-var _63b=_62f["preventCache"]||(this.preventCache==true&&_62f["preventCache"]!=false);
-var _63c=_62f["useCache"]==true||(this.useCache==true&&_62f["useCache"]!=false);
-if(!_63b&&_63c){
-var _63d=getFromCache(url,_631,_62f.method);
-if(_63d){
-doLoad(_62f,_63d,url,_631,false);
-return;
-}
-}
-var http=dojo.hostenv.getXmlhttpObject(_62f);
-var _63f=false;
-if(_63a){
-var _640=this.inFlight.push({"req":_62f,"http":http,"url":url,"query":_631,"useCache":_63c,"startTime":_62f.timeoutSeconds?(new Date()).getTime():0});
-this.startWatchingInFlight();
-}else{
-_60f._blockAsync=true;
-}
-if(_62f.method.toLowerCase()=="post"){
-if(!_62f.user){
-http.open("POST",url,_63a);
-}else{
-http.open("POST",url,_63a,_62f.user,_62f.password);
-}
-setHeaders(http,_62f);
-http.setRequestHeader("Content-Type",_62f.multipart?("multipart/form-data; boundary="+this.multipartBoundary):(_62f.contentType||"application/x-www-form-urlencoded"));
-try{
-http.send(_631);
-}
-catch(e){
-if(typeof http.abort=="function"){
-http.abort();
-}
-doLoad(_62f,{status:404},url,_631,_63c);
-}
-}else{
-var _641=url;
-if(_631!=""){
-_641+=(_641.indexOf("?")>-1?"&":"?")+_631;
-}
-if(_63b){
-_641+=(dojo.string.endsWithAny(_641,"?","&")?"":(_641.indexOf("?")>-1?"&":"?"))+"dojo.preventCache="+new Date().valueOf();
-}
-if(!_62f.user){
-http.open(_62f.method.toUpperCase(),_641,_63a);
-}else{
-http.open(_62f.method.toUpperCase(),_641,_63a,_62f.user,_62f.password);
-}
-setHeaders(http,_62f);
-try{
-http.send(null);
-}
-catch(e){
-if(typeof http.abort=="function"){
-http.abort();
-}
-doLoad(_62f,{status:404},url,_631,_63c);
-}
-}
-if(!_63a){
-doLoad(_62f,http,url,_631,_63c);
-_60f._blockAsync=false;
-}
-_62f.abort=function(){
-try{
-http._aborted=true;
-}
-catch(e){
-}
-return http.abort();
-};
-return;
-};
-dojo.io.transports.addTransport("XMLHTTPTransport");
-};
-dojo.provide("dojo.io.cookie");
-dojo.io.cookie.setCookie=function(name,_643,days,path,_646,_647){
-var _648=-1;
-if(typeof days=="number"&&days>=0){
-var d=new Date();
-d.setTime(d.getTime()+(days*24*60*60*1000));
-_648=d.toGMTString();
-}
-_643=escape(_643);
-document.cookie=name+"="+_643+";"+(_648!=-1?" expires="+_648+";":"")+(path?"path="+path:"")+(_646?"; domain="+_646:"")+(_647?"; secure":"");
-};
-dojo.io.cookie.set=dojo.io.cookie.setCookie;
-dojo.io.cookie.getCookie=function(name){
-var idx=document.cookie.lastIndexOf(name+"=");
-if(idx==-1){
-return null;
-}
-var _64c=document.cookie.substring(idx+name.length+1);
-var end=_64c.indexOf(";");
-if(end==-1){
-end=_64c.length;
-}
-_64c=_64c.substring(0,end);
-_64c=unescape(_64c);
-return _64c;
-};
-dojo.io.cookie.get=dojo.io.cookie.getCookie;
-dojo.io.cookie.deleteCookie=function(name){
-dojo.io.cookie.setCookie(name,"-",0);
-};
-dojo.io.cookie.setObjectCookie=function(name,obj,days,path,_653,_654,_655){
-if(arguments.length==5){
-_655=_653;
-_653=null;
-_654=null;
-}
-var _656=[],_657,_658="";
-if(!_655){
-_657=dojo.io.cookie.getObjectCookie(name);
-}
-if(days>=0){
-if(!_657){
-_657={};
-}
-for(var prop in obj){
-if(prop==null){
-delete _657[prop];
-}else{
-if(typeof obj[prop]=="string"||typeof obj[prop]=="number"){
-_657[prop]=obj[prop];
-}
-}
-}
-prop=null;
-for(var prop in _657){
-_656.push(escape(prop)+"="+escape(_657[prop]));
-}
-_658=_656.join("&");
-}
-dojo.io.cookie.setCookie(name,_658,days,path,_653,_654);
-};
-dojo.io.cookie.getObjectCookie=function(name){
-var _65b=null,_65c=dojo.io.cookie.getCookie(name);
-if(_65c){
-_65b={};
-var _65d=_65c.split("&");
-for(var i=0;i<_65d.length;i++){
-var pair=_65d[i].split("=");
-var _660=pair[1];
-if(isNaN(_660)){
-_660=unescape(pair[1]);
-}
-_65b[unescape(pair[0])]=_660;
-}
-}
-return _65b;
-};
-dojo.io.cookie.isSupported=function(){
-if(typeof navigator.cookieEnabled!="boolean"){
-dojo.io.cookie.setCookie("__TestingYourBrowserForCookieSupport__","CookiesAllowed",90,null);
-var _661=dojo.io.cookie.getCookie("__TestingYourBrowserForCookieSupport__");
-navigator.cookieEnabled=(_661=="CookiesAllowed");
-if(navigator.cookieEnabled){
-this.deleteCookie("__TestingYourBrowserForCookieSupport__");
-}
-}
-return navigator.cookieEnabled;
-};
-if(!dojo.io.cookies){
-dojo.io.cookies=dojo.io.cookie;
-}
-dojo.provide("dojo.io.*");
-dojo.provide("dojo.uri.*");
-dojo.provide("dojo.io.IframeIO");
-dojo.io.createIFrame=function(_662,_663,uri){
-if(window[_662]){
-return window[_662];
-}
-if(window.frames[_662]){
-return window.frames[_662];
-}
-var r=dojo.render.html;
-var _666=null;
-var turi=uri||dojo.uri.dojoUri("iframe_history.html?noInit=true");
-var _668=((r.ie)&&(dojo.render.os.win))?"<iframe name=\""+_662+"\" src=\""+turi+"\" onload=\""+_663+"\">":"iframe";
-_666=document.createElement(_668);
-with(_666){
-name=_662;
-setAttribute("name",_662);
-id=_662;
-}
-dojo.body().appendChild(_666);
-window[_662]=_666;
-with(_666.style){
-if(!r.safari){
-position="absolute";
-}
-left=top="0px";
-height=width="1px";
-visibility="hidden";
-}
-if(!r.ie){
-dojo.io.setIFrameSrc(_666,turi,true);
-_666.onload=new Function(_663);
-}
-return _666;
-};
-dojo.io.IframeTransport=new function(){
-var _669=this;
-this.currentRequest=null;
-this.requestQueue=[];
-this.iframeName="dojoIoIframe";
-this.fireNextRequest=function(){
-try{
-if((this.currentRequest)||(this.requestQueue.length==0)){
-return;
-}
-var cr=this.currentRequest=this.requestQueue.shift();
-cr._contentToClean=[];
-var fn=cr["formNode"];
-var _66c=cr["content"]||{};
-if(cr.sendTransport){
-_66c["dojo.transport"]="iframe";
-}
-if(fn){
-if(_66c){
-for(var x in _66c){
-if(!fn[x]){
-var tn;
-if(dojo.render.html.ie){
-tn=document.createElement("<input type='hidden' name='"+x+"' value='"+_66c[x]+"'>");
-fn.appendChild(tn);
-}else{
-tn=document.createElement("input");
-fn.appendChild(tn);
-tn.type="hidden";
-tn.name=x;
-tn.value=_66c[x];
-}
-cr._contentToClean.push(x);
-}else{
-fn[x].value=_66c[x];
-}
-}
-}
-if(cr["url"]){
-cr._originalAction=fn.getAttribute("action");
-fn.setAttribute("action",cr.url);
-}
-if(!fn.getAttribute("method")){
-fn.setAttribute("method",(cr["method"])?cr["method"]:"post");
-}
-cr._originalTarget=fn.getAttribute("target");
-fn.setAttribute("target",this.iframeName);
-fn.target=this.iframeName;
-fn.submit();
-}else{
-var _66f=dojo.io.argsFromMap(this.currentRequest.content);
-var _670=cr.url+(cr.url.indexOf("?")>-1?"&":"?")+_66f;
-dojo.io.setIFrameSrc(this.iframe,_670,true);
-}
-}
-catch(e){
-this.iframeOnload(e);
-}
-};
-this.canHandle=function(_671){
-return ((dojo.lang.inArray(["text/plain","text/html","text/javascript","text/json","application/json"],_671["mimetype"]))&&(dojo.lang.inArray(["post","get"],_671["method"].toLowerCase()))&&(!((_671["sync"])&&(_671["sync"]==true))));
-};
-this.bind=function(_672){
-if(!this["iframe"]){
-this.setUpIframe();
-}
-this.requestQueue.push(_672);
-this.fireNextRequest();
-return;
-};
-this.setUpIframe=function(){
-this.iframe=dojo.io.createIFrame(this.iframeName,"dojo.io.IframeTransport.iframeOnload();");
-};
-this.iframeOnload=function(_673){
-if(!_669.currentRequest){
-_669.fireNextRequest();
-return;
-}
-var req=_669.currentRequest;
-if(req.formNode){
-var _675=req._contentToClean;
-for(var i=0;i<_675.length;i++){
-var key=_675[i];
-if(dojo.render.html.safari){
-var _678=req.formNode;
-for(var j=0;j<_678.childNodes.length;j++){
-var _67a=_678.childNodes[j];
-if(_67a.name==key){
-var _67b=_67a.parentNode;
-_67b.removeChild(_67a);
-break;
-}
-}
-}else{
-var _67c=req.formNode[key];
-req.formNode.removeChild(_67c);
-req.formNode[key]=null;
-}
-}
-if(req["_originalAction"]){
-req.formNode.setAttribute("action",req._originalAction);
-}
-if(req["_originalTarget"]){
-req.formNode.setAttribute("target",req._originalTarget);
-req.formNode.target=req._originalTarget;
-}
-}
-var _67d=function(_67e){
-var doc=_67e.contentDocument||((_67e.contentWindow)&&(_67e.contentWindow.document))||((_67e.name)&&(document.frames[_67e.name])&&(document.frames[_67e.name].document))||null;
-return doc;
-};
-var _680;
-var _681=false;
-if(_673){
-this._callError(req,"IframeTransport Request Error: "+_673);
-}else{
-var ifd=_67d(_669.iframe);
-try{
-var cmt=req.mimetype;
-if((cmt=="text/javascript")||(cmt=="text/json")||(cmt=="application/json")){
-var js=ifd.getElementsByTagName("textarea")[0].value;
-if(cmt=="text/json"||cmt=="application/json"){
-js="("+js+")";
-}
-_680=dj_eval(js);
-}else{
-if(cmt=="text/html"){
-_680=ifd;
-}else{
-_680=ifd.getElementsByTagName("textarea")[0].value;
-}
-}
-_681=true;
-}
-catch(e){
-this._callError(req,"IframeTransport Error: "+e);
-}
-}
-try{
-if(_681&&dojo.lang.isFunction(req["load"])){
-req.load("load",_680,req);
-}
-}
-catch(e){
-throw e;
-}
-finally{
-_669.currentRequest=null;
-_669.fireNextRequest();
-}
-};
-this._callError=function(req,_686){
-var _687=new dojo.io.Error(_686);
-if(dojo.lang.isFunction(req["error"])){
-req.error("error",_687,req);
-}
-};
-dojo.io.transports.addTransport("IframeTransport");
-};
-dojo.provide("dojo.date");
-dojo.deprecated("dojo.date","use one of the modules in dojo.date.* instead","0.5");
-dojo.provide("dojo.string.Builder");
-dojo.string.Builder=function(str){
-this.arrConcat=(dojo.render.html.capable&&dojo.render.html["ie"]);
-var a=[];
-var b="";
-var _68b=this.length=b.length;
-if(this.arrConcat){
-if(b.length>0){
-a.push(b);
-}
-b="";
-}
-this.toString=this.valueOf=function(){
-return (this.arrConcat)?a.join(""):b;
-};
-this.append=function(){
-for(var x=0;x<arguments.length;x++){
-var s=arguments[x];
-if(dojo.lang.isArrayLike(s)){
-this.append.apply(this,s);
-}else{
-if(this.arrConcat){
-a.push(s);
-}else{
-b+=s;
-}
-_68b+=s.length;
-this.length=_68b;
-}
-}
-return this;
-};
-this.clear=function(){
-a=[];
-b="";
-_68b=this.length=0;
-return this;
-};
-this.remove=function(f,l){
-var s="";
-if(this.arrConcat){
-b=a.join("");
-}
-a=[];
-if(f>0){
-s=b.substring(0,(f-1));
-}
-b=s+b.substring(f+l);
-_68b=this.length=b.length;
-if(this.arrConcat){
-a.push(b);
-b="";
-}
-return this;
-};
-this.replace=function(o,n){
-if(this.arrConcat){
-b=a.join("");
-}
-a=[];
-b=b.replace(o,n);
-_68b=this.length=b.length;
-if(this.arrConcat){
-a.push(b);
-b="";
-}
-return this;
-};
-this.insert=function(idx,s){
-if(this.arrConcat){
-b=a.join("");
-}
-a=[];
-if(idx==0){
-b=s+b;
-}else{
-var t=b.split("");
-t.splice(idx,0,s);
-b=t.join("");
-}
-_68b=this.length=b.length;
-if(this.arrConcat){
-a.push(b);
-b="";
-}
-return this;
-};
-this.append.apply(this,arguments);
-};
-dojo.provide("dojo.string.*");
-if(!this["dojo"]){
-alert("\"dojo/__package__.js\" is now located at \"dojo/dojo.js\". Please update your includes accordingly");
-}
-dojo.provide("dojo.AdapterRegistry");
-dojo.AdapterRegistry=function(_696){
-this.pairs=[];
-this.returnWrappers=_696||false;
-};
-dojo.lang.extend(dojo.AdapterRegistry,{register:function(name,_698,wrap,_69a,_69b){
-var type=(_69b)?"unshift":"push";
-this.pairs[type]([name,_698,wrap,_69a]);
-},match:function(){
-for(var i=0;i<this.pairs.length;i++){
-var pair=this.pairs[i];
-if(pair[1].apply(this,arguments)){
-if((pair[3])||(this.returnWrappers)){
-return pair[2];
-}else{
-return pair[2].apply(this,arguments);
-}
-}
-}
-throw new Error("No match found");
-},unregister:function(name){
-for(var i=0;i<this.pairs.length;i++){
-var pair=this.pairs[i];
-if(pair[0]==name){
-this.pairs.splice(i,1);
-return true;
-}
-}
-return false;
-}});
-dojo.provide("dojo.json");
-dojo.json={jsonRegistry:new dojo.AdapterRegistry(),register:function(name,_6a3,wrap,_6a5){
-dojo.json.jsonRegistry.register(name,_6a3,wrap,_6a5);
-},evalJson:function(json){
-try{
-return eval("("+json+")");
-}
-catch(e){
-dojo.debug(e);
-return json;
-}
-},serialize:function(o){
-var _6a8=typeof (o);
-if(_6a8=="undefined"){
-return "undefined";
-}else{
-if((_6a8=="number")||(_6a8=="boolean")){
-return o+"";
-}else{
-if(o===null){
-return "null";
-}
-}
-}
-if(_6a8=="string"){
-return dojo.string.escapeString(o);
-}
-var me=arguments.callee;
-var _6aa;
-if(typeof (o.__json__)=="function"){
-_6aa=o.__json__();
-if(o!==_6aa){
-return me(_6aa);
-}
-}
-if(typeof (o.json)=="function"){
-_6aa=o.json();
-if(o!==_6aa){
-return me(_6aa);
-}
-}
-if(_6a8!="function"&&typeof (o.length)=="number"){
-var res=[];
-for(var i=0;i<o.length;i++){
-var val=me(o[i]);
-if(typeof (val)!="string"){
-val="undefined";
-}
-res.push(val);
-}
-return "["+res.join(",")+"]";
-}
-try{
-window.o=o;
-_6aa=dojo.json.jsonRegistry.match(o);
-return me(_6aa);
-}
-catch(e){
-}
-if(_6a8=="function"){
-return null;
-}
-res=[];
-for(var k in o){
-var _6af;
-if(typeof (k)=="number"){
-_6af="\""+k+"\"";
-}else{
-if(typeof (k)=="string"){
-_6af=dojo.string.escapeString(k);
-}else{
-continue;
-}
-}
-val=me(o[k]);
-if(typeof (val)!="string"){
-continue;
-}
-res.push(_6af+":"+val);
-}
-return "{"+res.join(",")+"}";
-}};
-dojo.provide("dojo.Deferred");
-dojo.Deferred=function(_6b0){
-this.chain=[];
-this.id=this._nextId();
-this.fired=-1;
-this.paused=0;
-this.results=[null,null];
-this.canceller=_6b0;
-this.silentlyCancelled=false;
-};
-dojo.lang.extend(dojo.Deferred,{getFunctionFromArgs:function(){
-var a=arguments;
-if((a[0])&&(!a[1])){
-if(dojo.lang.isFunction(a[0])){
-return a[0];
-}else{
-if(dojo.lang.isString(a[0])){
-return dj_global[a[0]];
-}
-}
-}else{
-if((a[0])&&(a[1])){
-return dojo.lang.hitch(a[0],a[1]);
-}
-}
-return null;
-},makeCalled:function(){
-var _6b2=new dojo.Deferred();
-_6b2.callback();
-return _6b2;
-},repr:function(){
-var _6b3;
-if(this.fired==-1){
-_6b3="unfired";
-}else{
-if(this.fired==0){
-_6b3="success";
-}else{
-_6b3="error";
-}
-}
-return "Deferred("+this.id+", "+_6b3+")";
-},toString:dojo.lang.forward("repr"),_nextId:(function(){
-var n=1;
-return function(){
-return n++;
-};
-})(),cancel:function(){
-if(this.fired==-1){
-if(this.canceller){
-this.canceller(this);
-}else{
-this.silentlyCancelled=true;
-}
-if(this.fired==-1){
-this.errback(new Error(this.repr()));
-}
-}else{
-if((this.fired==0)&&(this.results[0] instanceof dojo.Deferred)){
-this.results[0].cancel();
-}
-}
-},_pause:function(){
-this.paused++;
-},_unpause:function(){
-this.paused--;
-if((this.paused==0)&&(this.fired>=0)){
-this._fire();
-}
-},_continue:function(res){
-this._resback(res);
-this._unpause();
-},_resback:function(res){
-this.fired=((res instanceof Error)?1:0);
-this.results[this.fired]=res;
-this._fire();
-},_check:function(){
-if(this.fired!=-1){
-if(!this.silentlyCancelled){
-dojo.raise("already called!");
-}
-this.silentlyCancelled=false;
-return;
-}
-},callback:function(res){
-this._check();
-this._resback(res);
-},errback:function(res){
-this._check();
-if(!(res instanceof Error)){
-res=new Error(res);
-}
-this._resback(res);
-},addBoth:function(cb,cbfn){
-var _6bb=this.getFunctionFromArgs(cb,cbfn);
-if(arguments.length>2){
-_6bb=dojo.lang.curryArguments(null,_6bb,arguments,2);
-}
-return this.addCallbacks(_6bb,_6bb);
-},addCallback:function(cb,cbfn){
-var _6be=this.getFunctionFromArgs(cb,cbfn);
-if(arguments.length>2){
-_6be=dojo.lang.curryArguments(null,_6be,arguments,2);
-}
-return this.addCallbacks(_6be,null);
-},addErrback:function(cb,cbfn){
-var _6c1=this.getFunctionFromArgs(cb,cbfn);
-if(arguments.length>2){
-_6c1=dojo.lang.curryArguments(null,_6c1,arguments,2);
-}
-return this.addCallbacks(null,_6c1);
-return this.addCallbacks(null,cbfn);
-},addCallbacks:function(cb,eb){
-this.chain.push([cb,eb]);
-if(this.fired>=0){
-this._fire();
-}
-return this;
-},_fire:function(){
-var _6c4=this.chain;
-var _6c5=this.fired;
-var res=this.results[_6c5];
-var self=this;
-var cb=null;
-while(_6c4.length>0&&this.paused==0){
-var pair=_6c4.shift();
-var f=pair[_6c5];
-if(f==null){
-continue;
-}
-try{
-res=f(res);
-_6c5=((res instanceof Error)?1:0);
-if(res instanceof dojo.Deferred){
-cb=function(res){
-self._continue(res);
-};
-this._pause();
-}
-}
-catch(err){
-_6c5=1;
-res=err;
-}
-}
-this.fired=_6c5;
-this.results[_6c5]=res;
-if((cb)&&(this.paused)){
-res.addBoth(cb);
-}
-}});
-dojo.provide("dojo.rpc.RpcService");
-dojo.rpc.RpcService=function(url){
-if(url){
-this.connect(url);
-}
-};
-dojo.lang.extend(dojo.rpc.RpcService,{strictArgChecks:true,serviceUrl:"",parseResults:function(obj){
-return obj;
-},errorCallback:function(_6ce){
-return function(type,e){
-_6ce.errback(new Error(e.message));
-};
-},resultCallback:function(_6d1){
-var tf=dojo.lang.hitch(this,function(type,obj,e){
-if(obj["error"]!=null){
-var err=new Error(obj.error);
-err.id=obj.id;
-_6d1.errback(err);
-}else{
-var _6d7=this.parseResults(obj);
-_6d1.callback(_6d7);
-}
-});
-return tf;
-},generateMethod:function(_6d8,_6d9,url){
-return dojo.lang.hitch(this,function(){
-var _6db=new dojo.Deferred();
-if((this.strictArgChecks)&&(_6d9!=null)&&(arguments.length!=_6d9.length)){
-dojo.raise("Invalid number of parameters for remote method.");
-}else{
-this.bind(_6d8,arguments,_6db,url);
-}
-return _6db;
-});
-},processSmd:function(_6dc){
-dojo.debug("RpcService: Processing returned SMD.");
-if(_6dc.methods){
-dojo.lang.forEach(_6dc.methods,function(m){
-if(m&&m["name"]){
-dojo.debug("RpcService: Creating Method: this.",m.name,"()");
-this[m.name]=this.generateMethod(m.name,m.parameters,m["url"]||m["serviceUrl"]||m["serviceURL"]);
-if(dojo.lang.isFunction(this[m.name])){
-dojo.debug("RpcService: Successfully created",m.name,"()");
-}else{
-dojo.debug("RpcService: Failed to create",m.name,"()");
-}
-}
-},this);
-}
-this.serviceUrl=_6dc.serviceUrl||_6dc.serviceURL;
-dojo.debug("RpcService: Dojo RpcService is ready for use.");
-},connect:function(_6de){
-dojo.debug("RpcService: Attempting to load SMD document from:",_6de);
-dojo.io.bind({url:_6de,mimetype:"text/json",load:dojo.lang.hitch(this,function(type,_6e0,e){
-return this.processSmd(_6e0);
-}),sync:true});
-}});
-dojo.provide("dojo.rpc.JsonService");
-dojo.rpc.JsonService=function(args){
-if(args){
-if(dojo.lang.isString(args)){
-this.connect(args);
-}else{
-if(args["smdUrl"]){
-this.connect(args.smdUrl);
-}
-if(args["smdStr"]){
-this.processSmd(dj_eval("("+args.smdStr+")"));
-}
-if(args["smdObj"]){
-this.processSmd(args.smdObj);
-}
-if(args["serviceUrl"]){
-this.serviceUrl=args.serviceUrl;
-}
-if(typeof args["strictArgChecks"]!="undefined"){
-this.strictArgChecks=args.strictArgChecks;
-}
-}
-}
-};
-dojo.inherits(dojo.rpc.JsonService,dojo.rpc.RpcService);
-dojo.extend(dojo.rpc.JsonService,{bustCache:false,contentType:"application/json-rpc",lastSubmissionId:0,callRemote:function(_6e3,_6e4){
-var _6e5=new dojo.Deferred();
-this.bind(_6e3,_6e4,_6e5);
-return _6e5;
-},bind:function(_6e6,_6e7,_6e8,url){
-dojo.io.bind({url:url||this.serviceUrl,postContent:this.createRequest(_6e6,_6e7),method:"POST",contentType:this.contentType,mimetype:"text/json",load:this.resultCallback(_6e8),error:this.errorCallback(_6e8),preventCache:this.bustCache});
-},createRequest:function(_6ea,_6eb){
-var req={"params":_6eb,"method":_6ea,"id":++this.lastSubmissionId};
-var data=dojo.json.serialize(req);
-dojo.debug("JsonService: JSON-RPC Request: "+data);
-return data;
-},parseResults:function(obj){
-if(!obj){
-return;
-}
-if(obj["Result"]!=null){
-return obj["Result"];
-}else{
-if(obj["result"]!=null){
-return obj["result"];
-}else{
-if(obj["ResultSet"]){
-return obj["ResultSet"];
-}else{
-return obj;
-}
-}
-}
-}});
-dojo.provide("dojo.rpc.*");
-dojo.provide("dojo.xml.Parse");
-dojo.xml.Parse=function(){
-function getTagName(node){
-return ((node)&&(node.tagName)?node.tagName.toLowerCase():"");
-}
-function getDojoTagName(node){
-var _6f1=getTagName(node);
-if(!_6f1){
-return "";
-}
-if((dojo.widget)&&(dojo.widget.tags[_6f1])){
-return _6f1;
-}
-var p=_6f1.indexOf(":");
-if(p>=0){
-return _6f1;
-}
-if(_6f1.substr(0,5)=="dojo:"){
-return _6f1;
-}
-if(dojo.render.html.capable&&dojo.render.html.ie&&node.scopeName!="HTML"){
-return node.scopeName.toLowerCase()+":"+_6f1;
-}
-if(_6f1.substr(0,4)=="dojo"){
-return "dojo:"+_6f1.substring(4);
-}
-var djt=node.getAttribute("dojoType")||node.getAttribute("dojotype");
-if(djt){
-if(djt.indexOf(":")<0){
-djt="dojo:"+djt;
-}
-return djt.toLowerCase();
-}
-djt=node.getAttributeNS&&node.getAttributeNS(dojo.dom.dojoml,"type");
-if(djt){
-return "dojo:"+djt.toLowerCase();
-}
-try{
-djt=node.getAttribute("dojo:type");
-}
-catch(e){
-}
-if(djt){
-return "dojo:"+djt.toLowerCase();
-}
-if((!dj_global["djConfig"])||(djConfig["ignoreClassNames"])){
-var _6f4=node.className||node.getAttribute("class");
-if((_6f4)&&(_6f4.indexOf)&&(_6f4.indexOf("dojo-")!=-1)){
-var _6f5=_6f4.split(" ");
-for(var x=0,c=_6f5.length;x<c;x++){
-if(_6f5[x].slice(0,5)=="dojo-"){
-return "dojo:"+_6f5[x].substr(5).toLowerCase();
-}
-}
-}
-}
-return "";
-}
-this.parseElement=function(node,_6f9,_6fa,_6fb){
-var _6fc={};
-var _6fd=getTagName(node);
-if((_6fd)&&(_6fd.indexOf("/")==0)){
-return null;
-}
-var _6fe=true;
-if(_6fa){
-var _6ff=getDojoTagName(node);
-_6fd=_6ff||_6fd;
-_6fe=Boolean(_6ff);
-}
-if(node&&node.getAttribute&&node.getAttribute("parseWidgets")&&node.getAttribute("parseWidgets")=="false"){
-return {};
-}
-_6fc[_6fd]=[];
-var pos=_6fd.indexOf(":");
-if(pos>0){
-var ns=_6fd.substring(0,pos);
-_6fc["ns"]=ns;
-if((dojo.ns)&&(!dojo.ns.allow(ns))){
-_6fe=false;
-}
-}
-if(_6fe){
-var _702=this.parseAttributes(node);
-for(var attr in _702){
-if((!_6fc[_6fd][attr])||(typeof _6fc[_6fd][attr]!="array")){
-_6fc[_6fd][attr]=[];
-}
-_6fc[_6fd][attr].push(_702[attr]);
-}
-_6fc[_6fd].nodeRef=node;
-_6fc.tagName=_6fd;
-_6fc.index=_6fb||0;
-}
-var _704=0;
-for(var i=0;i<node.childNodes.length;i++){
-var tcn=node.childNodes.item(i);
-switch(tcn.nodeType){
-case dojo.dom.ELEMENT_NODE:
-_704++;
-var ctn=getDojoTagName(tcn)||getTagName(tcn);
-if(!_6fc[ctn]){
-_6fc[ctn]=[];
-}
-_6fc[ctn].push(this.parseElement(tcn,true,_6fa,_704));
-if((tcn.childNodes.length==1)&&(tcn.childNodes.item(0).nodeType==dojo.dom.TEXT_NODE)){
-_6fc[ctn][_6fc[ctn].length-1].value=tcn.childNodes.item(0).nodeValue;
-}
-break;
-case dojo.dom.TEXT_NODE:
-if(node.childNodes.length==1){
-_6fc[_6fd].push({value:node.childNodes.item(0).nodeValue});
-}
-break;
-default:
-break;
-}
-}
-return _6fc;
-};
-this.parseAttributes=function(node){
-var _709={};
-var atts=node.attributes;
-var _70b,i=0;
-while((_70b=atts[i++])){
-if((dojo.render.html.capable)&&(dojo.render.html.ie)){
-if(!_70b){
-continue;
-}
-if((typeof _70b=="object")&&(typeof _70b.nodeValue=="undefined")||(_70b.nodeValue==null)||(_70b.nodeValue=="")){
-continue;
-}
-}
-var nn=_70b.nodeName.split(":");
-nn=(nn.length==2)?nn[1]:_70b.nodeName;
-_709[nn]={value:_70b.nodeValue};
-}
-return _709;
-};
-};
-dojo.provide("dojo.xml.*");
-dojo.provide("dojo.undo.Manager");
-dojo.undo.Manager=function(_70e){
-this.clear();
-this._parent=_70e;
-};
-dojo.extend(dojo.undo.Manager,{_parent:null,_undoStack:null,_redoStack:null,_currentManager:null,canUndo:false,canRedo:false,isUndoing:false,isRedoing:false,onUndo:function(_70f,item){
-},onRedo:function(_711,item){
-},onUndoAny:function(_713,item){
-},onRedoAny:function(_715,item){
-},_updateStatus:function(){
-this.canUndo=this._undoStack.length>0;
-this.canRedo=this._redoStack.length>0;
-},clear:function(){
-this._undoStack=[];
-this._redoStack=[];
-this._currentManager=this;
-this.isUndoing=false;
-this.isRedoing=false;
-this._updateStatus();
-},undo:function(){
-if(!this.canUndo){
-return false;
-}
-this.endAllTransactions();
-this.isUndoing=true;
-var top=this._undoStack.pop();
-if(top instanceof dojo.undo.Manager){
-top.undoAll();
-}else{
-top.undo();
-}
-if(top.redo){
-this._redoStack.push(top);
-}
-this.isUndoing=false;
-this._updateStatus();
-this.onUndo(this,top);
-if(!(top instanceof dojo.undo.Manager)){
-this.getTop().onUndoAny(this,top);
-}
-return true;
-},redo:function(){
-if(!this.canRedo){
-return false;
-}
-this.isRedoing=true;
-var top=this._redoStack.pop();
-if(top instanceof dojo.undo.Manager){
-top.redoAll();
-}else{
-top.redo();
-}
-this._undoStack.push(top);
-this.isRedoing=false;
-this._updateStatus();
-this.onRedo(this,top);
-if(!(top instanceof dojo.undo.Manager)){
-this.getTop().onRedoAny(this,top);
-}
-return true;
-},undoAll:function(){
-while(this._undoStack.length>0){
-this.undo();
-}
-},redoAll:function(){
-while(this._redoStack.length>0){
-this.redo();
-}
-},push:function(undo,redo,_71b){
-if(!undo){
-return;
-}
-if(this._currentManager==this){
-this._undoStack.push({undo:undo,redo:redo,description:_71b});
-}else{
-this._currentManager.push.apply(this._currentManager,arguments);
-}
-this._redoStack=[];
-this._updateStatus();
-},concat:function(_71c){
-if(!_71c){
-return;
-}
-if(this._currentManager==this){
-for(var x=0;x<_71c._undoStack.length;x++){
-this._undoStack.push(_71c._undoStack[x]);
-}
-if(_71c._undoStack.length>0){
-this._redoStack=[];
-}
-this._updateStatus();
-}else{
-this._currentManager.concat.apply(this._currentManager,arguments);
-}
-},beginTransaction:function(_71e){
-if(this._currentManager==this){
-var mgr=new dojo.undo.Manager(this);
-mgr.description=_71e?_71e:"";
-this._undoStack.push(mgr);
-this._currentManager=mgr;
-return mgr;
-}else{
-this._currentManager=this._currentManager.beginTransaction.apply(this._currentManager,arguments);
-}
-},endTransaction:function(_720){
-if(this._currentManager==this){
-if(this._parent){
-this._parent._currentManager=this._parent;
-if(this._undoStack.length==0||_720){
-var idx=dojo.lang.find(this._parent._undoStack,this);
-if(idx>=0){
-this._parent._undoStack.splice(idx,1);
-if(_720){
-for(var x=0;x<this._undoStack.length;x++){
-this._parent._undoStack.splice(idx++,0,this._undoStack[x]);
-}
-this._updateStatus();
-}
-}
-}
-return this._parent;
-}
-}else{
-this._currentManager=this._currentManager.endTransaction.apply(this._currentManager,arguments);
-}
-},endAllTransactions:function(){
-while(this._currentManager!=this){
-this.endTransaction();
-}
-},getTop:function(){
-if(this._parent){
-return this._parent.getTop();
-}else{
-return this;
-}
-}});
-dojo.provide("dojo.undo.*");
-dojo.provide("dojo.crypto");
-dojo.crypto.cipherModes={ECB:0,CBC:1,PCBC:2,CFB:3,OFB:4,CTR:5};
-dojo.crypto.outputTypes={Base64:0,Hex:1,String:2,Raw:3};
-dojo.provide("dojo.crypto.MD5");
-dojo.crypto.MD5=new function(){
-var _723=8;
-var mask=(1<<_723)-1;
-function toWord(s){
-var wa=[];
-for(var i=0;i<s.length*_723;i+=_723){
-wa[i>>5]|=(s.charCodeAt(i/_723)&mask)<<(i%32);
-}
-return wa;
-}
-function toString(wa){
-var s=[];
-for(var i=0;i<wa.length*32;i+=_723){
-s.push(String.fromCharCode((wa[i>>5]>>>(i%32))&mask));
-}
-return s.join("");
-}
-function toHex(wa){
-var h="0123456789abcdef";
-var s=[];
-for(var i=0;i<wa.length*4;i++){
-s.push(h.charAt((wa[i>>2]>>((i%4)*8+4))&15)+h.charAt((wa[i>>2]>>((i%4)*8))&15));
-}
-return s.join("");
-}
-function toBase64(wa){
-var p="=";
-var tab="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-var s=[];
-for(var i=0;i<wa.length*4;i+=3){
-var t=(((wa[i>>2]>>8*(i%4))&255)<<16)|(((wa[i+1>>2]>>8*((i+1)%4))&255)<<8)|((wa[i+2>>2]>>8*((i+2)%4))&255);
-for(var j=0;j<4;j++){
-if(i*8+j*6>wa.length*32){
-s.push(p);
-}else{
-s.push(tab.charAt((t>>6*(3-j))&63));
-}
-}
-}
-return s.join("");
-}
-function add(x,y){
-var l=(x&65535)+(y&65535);
-var m=(x>>16)+(y>>16)+(l>>16);
-return (m<<16)|(l&65535);
-}
-function R(n,c){
-return (n<<c)|(n>>>(32-c));
-}
-function C(q,a,b,x,s,t){
-return add(R(add(add(a,q),add(x,t)),s),b);
-}
-function FF(a,b,c,d,x,s,t){
-return C((b&c)|((~b)&d),a,b,x,s,t);
-}
-function GG(a,b,c,d,x,s,t){
-return C((b&d)|(c&(~d)),a,b,x,s,t);
-}
-function HH(a,b,c,d,x,s,t){
-return C(b^c^d,a,b,x,s,t);
-}
-function II(a,b,c,d,x,s,t){
-return C(c^(b|(~d)),a,b,x,s,t);
-}
-function core(x,len){
-x[len>>5]|=128<<((len)%32);
-x[(((len+64)>>>9)<<4)+14]=len;
-var a=1732584193;
-var b=-271733879;
-var c=-1732584194;
-var d=271733878;
-for(var i=0;i<x.length;i+=16){
-var olda=a;
-var oldb=b;
-var oldc=c;
-var oldd=d;
-a=FF(a,b,c,d,x[i+0],7,-680876936);
-d=FF(d,a,b,c,x[i+1],12,-389564586);
-c=FF(c,d,a,b,x[i+2],17,606105819);
-b=FF(b,c,d,a,x[i+3],22,-1044525330);
-a=FF(a,b,c,d,x[i+4],7,-176418897);
-d=FF(d,a,b,c,x[i+5],12,1200080426);
-c=FF(c,d,a,b,x[i+6],17,-1473231341);
-b=FF(b,c,d,a,x[i+7],22,-45705983);
-a=FF(a,b,c,d,x[i+8],7,1770035416);
-d=FF(d,a,b,c,x[i+9],12,-1958414417);
-c=FF(c,d,a,b,x[i+10],17,-42063);
-b=FF(b,c,d,a,x[i+11],22,-1990404162);
-a=FF(a,b,c,d,x[i+12],7,1804603682);
-d=FF(d,a,b,c,x[i+13],12,-40341101);
-c=FF(c,d,a,b,x[i+14],17,-1502002290);
-b=FF(b,c,d,a,x[i+15],22,1236535329);
-a=GG(a,b,c,d,x[i+1],5,-165796510);
-d=GG(d,a,b,c,x[i+6],9,-1069501632);
-c=GG(c,d,a,b,x[i+11],14,643717713);
-b=GG(b,c,d,a,x[i+0],20,-373897302);
-a=GG(a,b,c,d,x[i+5],5,-701558691);
-d=GG(d,a,b,c,x[i+10],9,38016083);
-c=GG(c,d,a,b,x[i+15],14,-660478335);
-b=GG(b,c,d,a,x[i+4],20,-405537848);
-a=GG(a,b,c,d,x[i+9],5,568446438);
-d=GG(d,a,b,c,x[i+14],9,-1019803690);
-c=GG(c,d,a,b,x[i+3],14,-187363961);
-b=GG(b,c,d,a,x[i+8],20,1163531501);
-a=GG(a,b,c,d,x[i+13],5,-1444681467);
-d=GG(d,a,b,c,x[i+2],9,-51403784);
-c=GG(c,d,a,b,x[i+7],14,1735328473);
-b=GG(b,c,d,a,x[i+12],20,-1926607734);
-a=HH(a,b,c,d,x[i+5],4,-378558);
-d=HH(d,a,b,c,x[i+8],11,-2022574463);
-c=HH(c,d,a,b,x[i+11],16,1839030562);
-b=HH(b,c,d,a,x[i+14],23,-35309556);
-a=HH(a,b,c,d,x[i+1],4,-1530992060);
-d=HH(d,a,b,c,x[i+4],11,1272893353);
-c=HH(c,d,a,b,x[i+7],16,-155497632);
-b=HH(b,c,d,a,x[i+10],23,-1094730640);
-a=HH(a,b,c,d,x[i+13],4,681279174);
-d=HH(d,a,b,c,x[i+0],11,-358537222);
-c=HH(c,d,a,b,x[i+3],16,-722521979);
-b=HH(b,c,d,a,x[i+6],23,76029189);
-a=HH(a,b,c,d,x[i+9],4,-640364487);
-d=HH(d,a,b,c,x[i+12],11,-421815835);
-c=HH(c,d,a,b,x[i+15],16,530742520);
-b=HH(b,c,d,a,x[i+2],23,-995338651);
-a=II(a,b,c,d,x[i+0],6,-198630844);
-d=II(d,a,b,c,x[i+7],10,1126891415);
-c=II(c,d,a,b,x[i+14],15,-1416354905);
-b=II(b,c,d,a,x[i+5],21,-57434055);
-a=II(a,b,c,d,x[i+12],6,1700485571);
-d=II(d,a,b,c,x[i+3],10,-1894986606);
-c=II(c,d,a,b,x[i+10],15,-1051523);
-b=II(b,c,d,a,x[i+1],21,-2054922799);
-a=II(a,b,c,d,x[i+8],6,1873313359);
-d=II(d,a,b,c,x[i+15],10,-30611744);
-c=II(c,d,a,b,x[i+6],15,-1560198380);
-b=II(b,c,d,a,x[i+13],21,1309151649);
-a=II(a,b,c,d,x[i+4],6,-145523070);
-d=II(d,a,b,c,x[i+11],10,-1120210379);
-c=II(c,d,a,b,x[i+2],15,718787259);
-b=II(b,c,d,a,x[i+9],21,-343485551);
-a=add(a,olda);
-b=add(b,oldb);
-c=add(c,oldc);
-d=add(d,oldd);
-}
-return [a,b,c,d];
-}
-function hmac(data,key){
-var wa=toWord(key);
-if(wa.length>16){
-wa=core(wa,key.length*_723);
-}
-var l=[],r=[];
-for(var i=0;i<16;i++){
-l[i]=wa[i]^909522486;
-r[i]=wa[i]^1549556828;
-}
-var h=core(l.concat(toWord(data)),512+data.length*_723);
-return core(r.concat(h),640);
-}
-this.compute=function(data,_771){
-var out=_771||dojo.crypto.outputTypes.Base64;
-switch(out){
-case dojo.crypto.outputTypes.Hex:
-return toHex(core(toWord(data),data.length*_723));
-case dojo.crypto.outputTypes.String:
-return toString(core(toWord(data),data.length*_723));
-default:
-return toBase64(core(toWord(data),data.length*_723));
-}
-};
-this.getHMAC=function(data,key,_775){
-var out=_775||dojo.crypto.outputTypes.Base64;
-switch(out){
-case dojo.crypto.outputTypes.Hex:
-return toHex(hmac(data,key));
-case dojo.crypto.outputTypes.String:
-return toString(hmac(data,key));
-default:
-return toBase64(hmac(data,key));
-}
-};
-}();
-dojo.provide("dojo.crypto.*");
-dojo.provide("dojo.collections.Collections");
-dojo.collections.DictionaryEntry=function(k,v){
-this.key=k;
-this.value=v;
-this.valueOf=function(){
-return this.value;
-};
-this.toString=function(){
-return String(this.value);
-};
-};
-dojo.collections.Iterator=function(arr){
-var a=arr;
-var _77b=0;
-this.element=a[_77b]||null;
-this.atEnd=function(){
-return (_77b>=a.length);
-};
-this.get=function(){
-if(this.atEnd()){
-return null;
-}
-this.element=a[_77b++];
-return this.element;
-};
-this.map=function(fn,_77d){
-var s=_77d||dj_global;
-if(Array.map){
-return Array.map(a,fn,s);
-}else{
-var arr=[];
-for(var i=0;i<a.length;i++){
-arr.push(fn.call(s,a[i]));
-}
-return arr;
-}
-};
-this.reset=function(){
-_77b=0;
-this.element=a[_77b];
-};
-};
-dojo.collections.DictionaryIterator=function(obj){
-var a=[];
-var _783={};
-for(var p in obj){
-if(!_783[p]){
-a.push(obj[p]);
-}
-}
-var _785=0;
-this.element=a[_785]||null;
-this.atEnd=function(){
-return (_785>=a.length);
-};
-this.get=function(){
-if(this.atEnd()){
-return null;
-}
-this.element=a[_785++];
-return this.element;
-};
-this.map=function(fn,_787){
-var s=_787||dj_global;
-if(Array.map){
-return Array.map(a,fn,s);
-}else{
-var arr=[];
-for(var i=0;i<a.length;i++){
-arr.push(fn.call(s,a[i]));
-}
-return arr;
-}
-};
-this.reset=function(){
-_785=0;
-this.element=a[_785];
-};
-};
-dojo.provide("dojo.collections.ArrayList");
-dojo.collections.ArrayList=function(arr){
-var _78c=[];
-if(arr){
-_78c=_78c.concat(arr);
-}
-this.count=_78c.length;
-this.add=function(obj){
-_78c.push(obj);
-this.count=_78c.length;
-};
-this.addRange=function(a){
-if(a.getIterator){
-var e=a.getIterator();
-while(!e.atEnd()){
-this.add(e.get());
-}
-this.count=_78c.length;
-}else{
-for(var i=0;i<a.length;i++){
-_78c.push(a[i]);
-}
-this.count=_78c.length;
-}
-};
-this.clear=function(){
-_78c.splice(0,_78c.length);
-this.count=0;
-};
-this.clone=function(){
-return new dojo.collections.ArrayList(_78c);
-};
-this.contains=function(obj){
-for(var i=0;i<_78c.length;i++){
-if(_78c[i]==obj){
-return true;
-}
-}
-return false;
-};
-this.forEach=function(fn,_794){
-var s=_794||dj_global;
-if(Array.forEach){
-Array.forEach(_78c,fn,s);
-}else{
-for(var i=0;i<_78c.length;i++){
-fn.call(s,_78c[i],i,_78c);
-}
-}
-};
-this.getIterator=function(){
-return new dojo.collections.Iterator(_78c);
-};
-this.indexOf=function(obj){
-for(var i=0;i<_78c.length;i++){
-if(_78c[i]==obj){
-return i;
-}
-}
-return -1;
-};
-this.insert=function(i,obj){
-_78c.splice(i,0,obj);
-this.count=_78c.length;
-};
-this.item=function(i){
-return _78c[i];
-};
-this.remove=function(obj){
-var i=this.indexOf(obj);
-if(i>=0){
-_78c.splice(i,1);
-}
-this.count=_78c.length;
-};
-this.removeAt=function(i){
-_78c.splice(i,1);
-this.count=_78c.length;
-};
-this.reverse=function(){
-_78c.reverse();
-};
-this.sort=function(fn){
-if(fn){
-_78c.sort(fn);
-}else{
-_78c.sort();
-}
-};
-this.setByIndex=function(i,obj){
-_78c[i]=obj;
-this.count=_78c.length;
-};
-this.toArray=function(){
-return [].concat(_78c);
-};
-this.toString=function(_7a2){
-return _78c.join((_7a2||","));
-};
-};
-dojo.provide("dojo.collections.Queue");
-dojo.collections.Queue=function(arr){
-var q=[];
-if(arr){
-q=q.concat(arr);
-}
-this.count=q.length;
-this.clear=function(){
-q=[];
-this.count=q.length;
-};
-this.clone=function(){
-return new dojo.collections.Queue(q);
-};
-this.contains=function(o){
-for(var i=0;i<q.length;i++){
-if(q[i]==o){
-return true;
-}
-}
-return false;
-};
-this.copyTo=function(arr,i){
-arr.splice(i,0,q);
-};
-this.dequeue=function(){
-var r=q.shift();
-this.count=q.length;
-return r;
-};
-this.enqueue=function(o){
-this.count=q.push(o);
-};
-this.forEach=function(fn,_7ac){
-var s=_7ac||dj_global;
-if(Array.forEach){
-Array.forEach(q,fn,s);
-}else{
-for(var i=0;i<q.length;i++){
-fn.call(s,q[i],i,q);
-}
-}
-};
-this.getIterator=function(){
-return new dojo.collections.Iterator(q);
-};
-this.peek=function(){
-return q[0];
-};
-this.toArray=function(){
-return [].concat(q);
-};
-};
-dojo.provide("dojo.collections.Stack");
-dojo.collections.Stack=function(arr){
-var q=[];
-if(arr){
-q=q.concat(arr);
-}
-this.count=q.length;
-this.clear=function(){
-q=[];
-this.count=q.length;
-};
-this.clone=function(){
-return new dojo.collections.Stack(q);
-};
-this.contains=function(o){
-for(var i=0;i<q.length;i++){
-if(q[i]==o){
-return true;
-}
-}
-return false;
-};
-this.copyTo=function(arr,i){
-arr.splice(i,0,q);
-};
-this.forEach=function(fn,_7b6){
-var s=_7b6||dj_global;
-if(Array.forEach){
-Array.forEach(q,fn,s);
-}else{
-for(var i=0;i<q.length;i++){
-fn.call(s,q[i],i,q);
-}
-}
-};
-this.getIterator=function(){
-return new dojo.collections.Iterator(q);
-};
-this.peek=function(){
-return q[(q.length-1)];
-};
-this.pop=function(){
-var r=q.pop();
-this.count=q.length;
-return r;
-};
-this.push=function(o){
-this.count=q.push(o);
-};
-this.toArray=function(){
-return [].concat(q);
-};
-};
-dojo.provide("dojo.lang.declare");
-dojo.lang.declare=function(_7bb,_7bc,init,_7be){
-if((dojo.lang.isFunction(_7be))||((!_7be)&&(!dojo.lang.isFunction(init)))){
-var temp=_7be;
-_7be=init;
-init=temp;
-}
-var _7c0=[];
-if(dojo.lang.isArray(_7bc)){
-_7c0=_7bc;
-_7bc=_7c0.shift();
-}
-if(!init){
-init=dojo.evalObjPath(_7bb,false);
-if((init)&&(!dojo.lang.isFunction(init))){
-init=null;
-}
-}
-var ctor=dojo.lang.declare._makeConstructor();
-var scp=(_7bc?_7bc.prototype:null);
-if(scp){
-scp.prototyping=true;
-ctor.prototype=new _7bc();
-scp.prototyping=false;
-}
-ctor.superclass=scp;
-ctor.mixins=_7c0;
-for(var i=0,l=_7c0.length;i<l;i++){
-dojo.lang.extend(ctor,_7c0[i].prototype);
-}
-ctor.prototype.initializer=null;
-ctor.prototype.declaredClass=_7bb;
-if(dojo.lang.isArray(_7be)){
-dojo.lang.extend.apply(dojo.lang,[ctor].concat(_7be));
-}else{
-dojo.lang.extend(ctor,(_7be)||{});
-}
-dojo.lang.extend(ctor,dojo.lang.declare._common);
-ctor.prototype.constructor=ctor;
-ctor.prototype.initializer=(ctor.prototype.initializer)||(init)||(function(){
-});
-dojo.lang.setObjPathValue(_7bb,ctor,null,true);
-return ctor;
-};
-dojo.lang.declare._makeConstructor=function(){
-return function(){
-var self=this._getPropContext();
-var s=self.constructor.superclass;
-if((s)&&(s.constructor)){
-if(s.constructor==arguments.callee){
-this._inherited("constructor",arguments);
-}else{
-this._contextMethod(s,"constructor",arguments);
-}
-}
-var ms=(self.constructor.mixins)||([]);
-for(var i=0,m;(m=ms[i]);i++){
-(((m.prototype)&&(m.prototype.initializer))||(m)).apply(this,arguments);
-}
-if((!this.prototyping)&&(self.initializer)){
-self.initializer.apply(this,arguments);
-}
-};
-};
-dojo.lang.declare._common={_getPropContext:function(){
-return (this.___proto||this);
-},_contextMethod:function(_7ca,_7cb,args){
-var _7cd,_7ce=this.___proto;
-this.___proto=_7ca;
-try{
-_7cd=_7ca[_7cb].apply(this,(args||[]));
-}
-catch(e){
-throw e;
-}
-finally{
-this.___proto=_7ce;
-}
-return _7cd;
-},_inherited:function(prop,args){
-var p=this._getPropContext();
-do{
-if((!p.constructor)||(!p.constructor.superclass)){
-return;
-}
-p=p.constructor.superclass;
-}while(!(prop in p));
-return (dojo.lang.isFunction(p[prop])?this._contextMethod(p,prop,args):p[prop]);
-}};
-dojo.declare=dojo.lang.declare;
-dojo.provide("dojo.dnd.DragAndDrop");
-dojo.declare("dojo.dnd.DragSource",null,{type:"",onDragEnd:function(){
-},onDragStart:function(){
-},onSelected:function(){
-},unregister:function(){
-dojo.dnd.dragManager.unregisterDragSource(this);
-},reregister:function(){
-dojo.dnd.dragManager.registerDragSource(this);
-}},function(){
-var dm=dojo.dnd.dragManager;
-if(dm["registerDragSource"]){
-dm.registerDragSource(this);
-}
-});
-dojo.declare("dojo.dnd.DragObject",null,{type:"",onDragStart:function(){
-},onDragMove:function(){
-},onDragOver:function(){
-},onDragOut:function(){
-},onDragEnd:function(){
-},onDragLeave:this.onDragOut,onDragEnter:this.onDragOver,ondragout:this.onDragOut,ondragover:this.onDragOver},function(){
-var dm=dojo.dnd.dragManager;
-if(dm["registerDragObject"]){
-dm.registerDragObject(this);
-}
-});
-dojo.declare("dojo.dnd.DropTarget",null,{acceptsType:function(type){
-if(!dojo.lang.inArray(this.acceptedTypes,"*")){
-if(!dojo.lang.inArray(this.acceptedTypes,type)){
-return false;
-}
-}
-return true;
-},accepts:function(_7d5){
-if(!dojo.lang.inArray(this.acceptedTypes,"*")){
-for(var i=0;i<_7d5.length;i++){
-if(!dojo.lang.inArray(this.acceptedTypes,_7d5[i].type)){
-return false;
-}
-}
-}
-return true;
-},unregister:function(){
-dojo.dnd.dragManager.unregisterDropTarget(this);
-},onDragOver:function(){
-},onDragOut:function(){
-},onDragMove:function(){
-},onDropStart:function(){
-},onDrop:function(){
-},onDropEnd:function(){
-}},function(){
-if(this.constructor==dojo.dnd.DropTarget){
-return;
-}
-this.acceptedTypes=[];
-dojo.dnd.dragManager.registerDropTarget(this);
-});
-dojo.dnd.DragEvent=function(){
-this.dragSource=null;
-this.dragObject=null;
-this.target=null;
-this.eventStatus="success";
-};
-dojo.declare("dojo.dnd.DragManager",null,{selectedSources:[],dragObjects:[],dragSources:[],registerDragSource:function(){
-},dropTargets:[],registerDropTarget:function(){
-},lastDragTarget:null,currentDragTarget:null,onKeyDown:function(){
-},onMouseOut:function(){
-},onMouseMove:function(){
-},onMouseUp:function(){
-}});
-dojo.provide("dojo.dnd.HtmlDragManager");
-dojo.declare("dojo.dnd.HtmlDragManager",dojo.dnd.DragManager,{disabled:false,nestedTargets:false,mouseDownTimer:null,dsCounter:0,dsPrefix:"dojoDragSource",dropTargetDimensions:[],currentDropTarget:null,previousDropTarget:null,_dragTriggered:false,selectedSources:[],dragObjects:[],currentX:null,currentY:null,lastX:null,lastY:null,mouseDownX:null,mouseDownY:null,threshold:7,dropAcceptable:false,cancelEvent:function(e){
-e.stopPropagation();
-e.preventDefault();
-},registerDragSource:function(ds){
-if(ds["domNode"]){
-var dp=this.dsPrefix;
-var _7da=dp+"Idx_"+(this.dsCounter++);
-ds.dragSourceId=_7da;
-this.dragSources[_7da]=ds;
-ds.domNode.setAttribute(dp,_7da);
-if(dojo.render.html.ie){
-dojo.event.browser.addListener(ds.domNode,"ondragstart",this.cancelEvent);
-}
-}
-},unregisterDragSource:function(ds){
-if(ds["domNode"]){
-var dp=this.dsPrefix;
-var _7dd=ds.dragSourceId;
-delete ds.dragSourceId;
-delete this.dragSources[_7dd];
-ds.domNode.setAttribute(dp,null);
-if(dojo.render.html.ie){
-dojo.event.browser.removeListener(ds.domNode,"ondragstart",this.cancelEvent);
-}
-}
-},registerDropTarget:function(dt){
-this.dropTargets.push(dt);
-},unregisterDropTarget:function(dt){
-var _7e0=dojo.lang.find(this.dropTargets,dt,true);
-if(_7e0>=0){
-this.dropTargets.splice(_7e0,1);
-}
-},getDragSource:function(e){
-var tn=e.target;
-if(tn===dojo.body()){
-return;
-}
-var ta=dojo.html.getAttribute(tn,this.dsPrefix);
-while((!ta)&&(tn)){
-tn=tn.parentNode;
-if((!tn)||(tn===dojo.body())){
-return;
-}
-ta=dojo.html.getAttribute(tn,this.dsPrefix);
-}
-return this.dragSources[ta];
-},onKeyDown:function(e){
-},onMouseDown:function(e){
-if(this.disabled){
-return;
-}
-if(dojo.render.html.ie){
-if(e.button!=1){
-return;
-}
-}else{
-if(e.which!=1){
-return;
-}
-}
-var _7e6=e.target.nodeType==dojo.html.TEXT_NODE?e.target.parentNode:e.target;
-if(dojo.html.isTag(_7e6,"button","textarea","input","select","option")){
-return;
-}
-var ds=this.getDragSource(e);
-if(!ds){
-return;
-}
-if(!dojo.lang.inArray(this.selectedSources,ds)){
-this.selectedSources.push(ds);
-ds.onSelected();
-}
-this.mouseDownX=e.pageX;
-this.mouseDownY=e.pageY;
-e.preventDefault();
-dojo.event.connect(document,"onmousemove",this,"onMouseMove");
-},onMouseUp:function(e,_7e9){
-if(this.selectedSources.length==0){
-return;
-}
-this.mouseDownX=null;
-this.mouseDownY=null;
-this._dragTriggered=false;
-e.dragSource=this.dragSource;
-if((!e.shiftKey)&&(!e.ctrlKey)){
-if(this.currentDropTarget){
-this.currentDropTarget.onDropStart();
-}
-dojo.lang.forEach(this.dragObjects,function(_7ea){
-var ret=null;
-if(!_7ea){
-return;
-}
-if(this.currentDropTarget){
-e.dragObject=_7ea;
-var ce=this.currentDropTarget.domNode.childNodes;
-if(ce.length>0){
-e.dropTarget=ce[0];
-while(e.dropTarget==_7ea.domNode){
-e.dropTarget=e.dropTarget.nextSibling;
-}
-}else{
-e.dropTarget=this.currentDropTarget.domNode;
-}
-if(this.dropAcceptable){
-ret=this.currentDropTarget.onDrop(e);
-}else{
-this.currentDropTarget.onDragOut(e);
-}
-}
-e.dragStatus=this.dropAcceptable&&ret?"dropSuccess":"dropFailure";
-dojo.lang.delayThese([function(){
-try{
-_7ea.dragSource.onDragEnd(e);
-}
-catch(err){
-var _7ed={};
-for(var i in e){
-if(i=="type"){
-_7ed.type="mouseup";
-continue;
-}
-_7ed[i]=e[i];
-}
-_7ea.dragSource.onDragEnd(_7ed);
-}
-},function(){
-_7ea.onDragEnd(e);
-}]);
-},this);
-this.selectedSources=[];
-this.dragObjects=[];
-this.dragSource=null;
-if(this.currentDropTarget){
-this.currentDropTarget.onDropEnd();
-}
-}else{
-}
-dojo.event.disconnect(document,"onmousemove",this,"onMouseMove");
-this.currentDropTarget=null;
-},onScroll:function(){
-for(var i=0;i<this.dragObjects.length;i++){
-if(this.dragObjects[i].updateDragOffset){
-this.dragObjects[i].updateDragOffset();
-}
-}
-if(this.dragObjects.length){
-this.cacheTargetLocations();
-}
-},_dragStartDistance:function(x,y){
-if((!this.mouseDownX)||(!this.mouseDownX)){
-return;
-}
-var dx=Math.abs(x-this.mouseDownX);
-var dx2=dx*dx;
-var dy=Math.abs(y-this.mouseDownY);
-var dy2=dy*dy;
-return parseInt(Math.sqrt(dx2+dy2),10);
-},cacheTargetLocations:function(){
-dojo.profile.start("cacheTargetLocations");
-this.dropTargetDimensions=[];
-dojo.lang.forEach(this.dropTargets,function(_7f6){
-var tn=_7f6.domNode;
-if(!tn||dojo.lang.find(_7f6.acceptedTypes,this.dragSource.type)<0){
-return;
-}
-var abs=dojo.html.getAbsolutePosition(tn,true);
-var bb=dojo.html.getBorderBox(tn);
-this.dropTargetDimensions.push([[abs.x,abs.y],[abs.x+bb.width,abs.y+bb.height],_7f6]);
-},this);
-dojo.profile.end("cacheTargetLocations");
-},onMouseMove:function(e){
-if((dojo.render.html.ie)&&(e.button!=1)){
-this.currentDropTarget=null;
-this.onMouseUp(e,true);
-return;
-}
-if((this.selectedSources.length)&&(!this.dragObjects.length)){
-var dx;
-var dy;
-if(!this._dragTriggered){
-this._dragTriggered=(this._dragStartDistance(e.pageX,e.pageY)>this.threshold);
-if(!this._dragTriggered){
-return;
-}
-dx=e.pageX-this.mouseDownX;
-dy=e.pageY-this.mouseDownY;
-}
-this.dragSource=this.selectedSources[0];
-dojo.lang.forEach(this.selectedSources,function(_7fd){
-if(!_7fd){
-return;
-}
-var tdo=_7fd.onDragStart(e);
-if(tdo){
-tdo.onDragStart(e);
-tdo.dragOffset.y+=dy;
-tdo.dragOffset.x+=dx;
-tdo.dragSource=_7fd;
-this.dragObjects.push(tdo);
-}
-},this);
-this.previousDropTarget=null;
-this.cacheTargetLocations();
-}
-dojo.lang.forEach(this.dragObjects,function(_7ff){
-if(_7ff){
-_7ff.onDragMove(e);
-}
-});
-if(this.currentDropTarget){
-var c=dojo.html.toCoordinateObject(this.currentDropTarget.domNode,true);
-var dtp=[[c.x,c.y],[c.x+c.width,c.y+c.height]];
-}
-if((!this.nestedTargets)&&(dtp)&&(this.isInsideBox(e,dtp))){
-if(this.dropAcceptable){
-this.currentDropTarget.onDragMove(e,this.dragObjects);
-}
-}else{
-var _802=this.findBestTarget(e);
-if(_802.target===null){
-if(this.currentDropTarget){
-this.currentDropTarget.onDragOut(e);
-this.previousDropTarget=this.currentDropTarget;
-this.currentDropTarget=null;
-}
-this.dropAcceptable=false;
-return;
-}
-if(this.currentDropTarget!==_802.target){
-if(this.currentDropTarget){
-this.previousDropTarget=this.currentDropTarget;
-this.currentDropTarget.onDragOut(e);
-}
-this.currentDropTarget=_802.target;
-e.dragObjects=this.dragObjects;
-this.dropAcceptable=this.currentDropTarget.onDragOver(e);
-}else{
-if(this.dropAcceptable){
-this.currentDropTarget.onDragMove(e,this.dragObjects);
-}
-}
-}
-},findBestTarget:function(e){
-var _804=this;
-var _805=new Object();
-_805.target=null;
-_805.points=null;
-dojo.lang.every(this.dropTargetDimensions,function(_806){
-if(!_804.isInsideBox(e,_806)){
-return true;
-}
-_805.target=_806[2];
-_805.points=_806;
-return Boolean(_804.nestedTargets);
-});
-return _805;
-},isInsideBox:function(e,_808){
-if((e.pageX>_808[0][0])&&(e.pageX<_808[1][0])&&(e.pageY>_808[0][1])&&(e.pageY<_808[1][1])){
-return true;
-}
-return false;
-},onMouseOver:function(e){
-},onMouseOut:function(e){
-}});
-dojo.dnd.dragManager=new dojo.dnd.HtmlDragManager();
-(function(){
-var d=document;
-var dm=dojo.dnd.dragManager;
-dojo.event.connect(d,"onkeydown",dm,"onKeyDown");
-dojo.event.connect(d,"onmouseover",dm,"onMouseOver");
-dojo.event.connect(d,"onmouseout",dm,"onMouseOut");
-dojo.event.connect(d,"onmousedown",dm,"onMouseDown");
-dojo.event.connect(d,"onmouseup",dm,"onMouseUp");
-dojo.event.connect(window,"onscroll",dm,"onScroll");
-})();
-dojo.provide("dojo.html.selection");
-dojo.html.selectionType={NONE:0,TEXT:1,CONTROL:2};
-dojo.html.clearSelection=function(){
-var _80d=dojo.global();
-var _80e=dojo.doc();
-try{
-if(_80d["getSelection"]){
-if(dojo.render.html.safari){
-_80d.getSelection().collapse();
-}else{
-_80d.getSelection().removeAllRanges();
-}
-}else{
-if(_80e.selection){
-if(_80e.selection.empty){
-_80e.selection.empty();
-}else{
-if(_80e.selection.clear){
-_80e.selection.clear();
-}
-}
-}
-}
-return true;
-}
-catch(e){
-dojo.debug(e);
-return false;
-}
-};
-dojo.html.disableSelection=function(_80f){
-_80f=dojo.byId(_80f)||dojo.body();
-var h=dojo.render.html;
-if(h.mozilla){
-_80f.style.MozUserSelect="none";
-}else{
-if(h.safari){
-_80f.style.KhtmlUserSelect="none";
-}else{
-if(h.ie){
-_80f.unselectable="on";
-}else{
-return false;
-}
-}
-}
-return true;
-};
-dojo.html.enableSelection=function(_811){
-_811=dojo.byId(_811)||dojo.body();
-var h=dojo.render.html;
-if(h.mozilla){
-_811.style.MozUserSelect="";
-}else{
-if(h.safari){
-_811.style.KhtmlUserSelect="";
-}else{
-if(h.ie){
-_811.unselectable="off";
-}else{
-return false;
-}
-}
-}
-return true;
-};
-dojo.html.selectElement=function(_813){
-dojo.deprecated("dojo.html.selectElement","replaced by dojo.html.selection.selectElementChildren",0.5);
-};
-dojo.html.selectInputText=function(_814){
-var _815=dojo.global();
-var _816=dojo.doc();
-_814=dojo.byId(_814);
-if(_816["selection"]&&dojo.body()["createTextRange"]){
-var _817=_814.createTextRange();
-_817.moveStart("character",0);
-_817.moveEnd("character",_814.value.length);
-_817.select();
-}else{
-if(_815["getSelection"]){
-var _818=_815.getSelection();
-_814.setSelectionRange(0,_814.value.length);
-}
-}
-_814.focus();
-};
-dojo.html.isSelectionCollapsed=function(){
-dojo.deprecated("dojo.html.isSelectionCollapsed","replaced by dojo.html.selection.isCollapsed",0.5);
-return dojo.html.selection.isCollapsed();
-};
-dojo.lang.mixin(dojo.html.selection,{getType:function(){
-if(dojo.doc()["selection"]){
-return dojo.html.selectionType[dojo.doc().selection.type.toUpperCase()];
-}else{
-var _819=dojo.html.selectionType.TEXT;
-var oSel;
-try{
-oSel=dojo.global().getSelection();
-}
-catch(e){
-}
-if(oSel&&oSel.rangeCount==1){
-var _81b=oSel.getRangeAt(0);
-if(_81b.startContainer==_81b.endContainer&&(_81b.endOffset-_81b.startOffset)==1&&_81b.startContainer.nodeType!=dojo.dom.TEXT_NODE){
-_819=dojo.html.selectionType.CONTROL;
-}
-}
-return _819;
-}
-},isCollapsed:function(){
-var _81c=dojo.global();
-var _81d=dojo.doc();
-if(_81d["selection"]){
-return _81d.selection.createRange().text=="";
-}else{
-if(_81c["getSelection"]){
-var _81e=_81c.getSelection();
-if(dojo.lang.isString(_81e)){
-return _81e=="";
-}else{
-return _81e.isCollapsed||_81e.toString()=="";
-}
-}
-}
-},getSelectedElement:function(){
-if(dojo.html.selection.getType()==dojo.html.selectionType.CONTROL){
-if(dojo.doc()["selection"]){
-var _81f=dojo.doc().selection.createRange();
-if(_81f&&_81f.item){
-return dojo.doc().selection.createRange().item(0);
-}
-}else{
-var _820=dojo.global().getSelection();
-return _820.anchorNode.childNodes[_820.anchorOffset];
-}
-}
-},getParentElement:function(){
-if(dojo.html.selection.getType()==dojo.html.selectionType.CONTROL){
-var p=dojo.html.selection.getSelectedElement();
-if(p){
-return p.parentNode;
-}
-}else{
-if(dojo.doc()["selection"]){
-return dojo.doc().selection.createRange().parentElement();
-}else{
-var _822=dojo.global().getSelection();
-if(_822){
-var node=_822.anchorNode;
-while(node&&node.nodeType!=dojo.dom.ELEMENT_NODE){
-node=node.parentNode;
-}
-return node;
-}
-}
-}
-},getSelectedText:function(){
-if(dojo.doc()["selection"]){
-if(dojo.html.selection.getType()==dojo.html.selectionType.CONTROL){
-return null;
-}
-return dojo.doc().selection.createRange().text;
-}else{
-var _824=dojo.global().getSelection();
-if(_824){
-return _824.toString();
-}
-}
-},getSelectedHtml:function(){
-if(dojo.doc()["selection"]){
-if(dojo.html.selection.getType()==dojo.html.selectionType.CONTROL){
-return null;
-}
-return dojo.doc().selection.createRange().htmlText;
-}else{
-var _825=dojo.global().getSelection();
-if(_825&&_825.rangeCount){
-var frag=_825.getRangeAt(0).cloneContents();
-var div=document.createElement("div");
-div.appendChild(frag);
-return div.innerHTML;
-}
-return null;
-}
-},hasAncestorElement:function(_828){
-return (dojo.html.selection.getAncestorElement.apply(this,arguments)!=null);
-},getAncestorElement:function(_829){
-var node=dojo.html.selection.getSelectedElement()||dojo.html.selection.getParentElement();
-while(node){
-if(dojo.html.selection.isTag(node,arguments).length>0){
-return node;
-}
-node=node.parentNode;
-}
-return null;
-},isTag:function(node,tags){
-if(node&&node.tagName){
-for(var i=0;i<tags.length;i++){
-if(node.tagName.toLowerCase()==String(tags[i]).toLowerCase()){
-return String(tags[i]).toLowerCase();
-}
-}
-}
-return "";
-},selectElement:function(_82e){
-var _82f=dojo.global();
-var _830=dojo.doc();
-_82e=dojo.byId(_82e);
-if(_830.selection&&dojo.body().createTextRange){
-try{
-var _831=dojo.body().createControlRange();
-_831.addElement(_82e);
-_831.select();
-}
-catch(e){
-dojo.html.selection.selectElementChildren(_82e);
-}
-}else{
-if(_82f["getSelection"]){
-var _832=_82f.getSelection();
-if(_832["removeAllRanges"]){
-var _831=_830.createRange();
-_831.selectNode(_82e);
-_832.removeAllRanges();
-_832.addRange(_831);
-}
-}
-}
-},selectElementChildren:function(_833){
-var _834=dojo.global();
-var _835=dojo.doc();
-_833=dojo.byId(_833);
-if(_835.selection&&dojo.body().createTextRange){
-var _836=dojo.body().createTextRange();
-_836.moveToElementText(_833);
-_836.select();
-}else{
-if(_834["getSelection"]){
-var _837=_834.getSelection();
-if(_837["setBaseAndExtent"]){
-_837.setBaseAndExtent(_833,0,_833,_833.innerText.length-1);
-}else{
-if(_837["selectAllChildren"]){
-_837.selectAllChildren(_833);
-}
-}
-}
-}
-},getBookmark:function(){
-var _838;
-var _839=dojo.doc();
-if(_839["selection"]){
-var _83a=_839.selection.createRange();
-_838=_83a.getBookmark();
-}else{
-var _83b;
-try{
-_83b=dojo.global().getSelection();
-}
-catch(e){
-}
-if(_83b){
-var _83a=_83b.getRangeAt(0);
-_838=_83a.cloneRange();
-}else{
-dojo.debug("No idea how to store the current selection for this browser!");
-}
-}
-return _838;
-},moveToBookmark:function(_83c){
-var _83d=dojo.doc();
-if(_83d["selection"]){
-var _83e=_83d.selection.createRange();
-_83e.moveToBookmark(_83c);
-_83e.select();
-}else{
-var _83f;
-try{
-_83f=dojo.global().getSelection();
-}
-catch(e){
-}
-if(_83f&&_83f["removeAllRanges"]){
-_83f.removeAllRanges();
-_83f.addRange(_83c);
-}else{
-dojo.debug("No idea how to restore selection for this browser!");
-}
-}
-},collapse:function(_840){
-if(dojo.global()["getSelection"]){
-var _841=dojo.global().getSelection();
-if(_841.removeAllRanges){
-if(_840){
-_841.collapseToStart();
-}else{
-_841.collapseToEnd();
-}
-}else{
-dojo.global().getSelection().collapse(_840);
-}
-}else{
-if(dojo.doc().selection){
-var _842=dojo.doc().selection.createRange();
-_842.collapse(_840);
-_842.select();
-}
-}
-},remove:function(){
-if(dojo.doc().selection){
-var _843=dojo.doc().selection;
-if(_843.type.toUpperCase()!="NONE"){
-_843.clear();
-}
-return _843;
-}else{
-var _843=dojo.global().getSelection();
-for(var i=0;i<_843.rangeCount;i++){
-_843.getRangeAt(i).deleteContents();
-}
-return _843;
-}
-}});
-dojo.provide("dojo.html.iframe");
-dojo.html.iframeContentWindow=function(_845){
-var win=dojo.html.getDocumentWindow(dojo.html.iframeContentDocument(_845))||dojo.html.iframeContentDocument(_845).__parent__||(_845.name&&document.frames[_845.name])||null;
-return win;
-};
-dojo.html.iframeContentDocument=function(_847){
-var doc=_847.contentDocument||((_847.contentWindow)&&(_847.contentWindow.document))||((_847.name)&&(document.frames[_847.name])&&(document.frames[_847.name].document))||null;
-return doc;
-};
-dojo.html.BackgroundIframe=function(node){
-if(dojo.render.html.ie55||dojo.render.html.ie60){
-var html="<iframe src='javascript:false'"+"' style='position: absolute; left: 0px; top: 0px; width: 100%; height: 100%;"+"z-index: -1; filter:Alpha(Opacity=\"0\");' "+">";
-this.iframe=dojo.doc().createElement(html);
-this.iframe.tabIndex=-1;
-if(node){
-node.appendChild(this.iframe);
-this.domNode=node;
-}else{
-dojo.body().appendChild(this.iframe);
-this.iframe.style.display="none";
-}
-}
-};
-dojo.lang.extend(dojo.html.BackgroundIframe,{iframe:null,onResized:function(){
-if(this.iframe&&this.domNode&&this.domNode.parentNode){
-var _84b=dojo.html.getMarginBox(this.domNode);
-if(_84b.width==0||_84b.height==0){
-dojo.lang.setTimeout(this,this.onResized,100);
-return;
-}
-this.iframe.style.width=_84b.width+"px";
-this.iframe.style.height=_84b.height+"px";
-}
-},size:function(node){
-if(!this.iframe){
-return;
-}
-var _84d=dojo.html.toCoordinateObject(node,true,dojo.html.boxSizing.BORDER_BOX);
-this.iframe.style.width=_84d.width+"px";
-this.iframe.style.height=_84d.height+"px";
-this.iframe.style.left=_84d.left+"px";
-this.iframe.style.top=_84d.top+"px";
-},setZIndex:function(node){
-if(!this.iframe){
-return;
-}
-if(dojo.dom.isNode(node)){
-this.iframe.style.zIndex=dojo.html.getStyle(node,"z-index")-1;
-}else{
-if(!isNaN(node)){
-this.iframe.style.zIndex=node;
-}
-}
-},show:function(){
-if(!this.iframe){
-return;
-}
-this.iframe.style.display="block";
-},hide:function(){
-if(!this.iframe){
-return;
-}
-this.iframe.style.display="none";
-},remove:function(){
-dojo.html.removeNode(this.iframe);
-}});
-dojo.provide("dojo.dnd.HtmlDragAndDrop");
-dojo.declare("dojo.dnd.HtmlDragSource",dojo.dnd.DragSource,{dragClass:"",onDragStart:function(){
-var _84f=new dojo.dnd.HtmlDragObject(this.dragObject,this.type);
-if(this.dragClass){
-_84f.dragClass=this.dragClass;
-}
-if(this.constrainToContainer){
-_84f.constrainTo(this.constrainingContainer||this.domNode.parentNode);
-}
-return _84f;
-},setDragHandle:function(node){
-node=dojo.byId(node);
-dojo.dnd.dragManager.unregisterDragSource(this);
-this.domNode=node;
-dojo.dnd.dragManager.registerDragSource(this);
-},setDragTarget:function(node){
-this.dragObject=node;
-},constrainTo:function(_852){
-this.constrainToContainer=true;
-if(_852){
-this.constrainingContainer=_852;
-}
-},onSelected:function(){
-for(var i=0;i<this.dragObjects.length;i++){
-dojo.dnd.dragManager.selectedSources.push(new dojo.dnd.HtmlDragSource(this.dragObjects[i]));
-}
-},addDragObjects:function(el){
-for(var i=0;i<arguments.length;i++){
-this.dragObjects.push(arguments[i]);
-}
-}},function(node,type){
-node=dojo.byId(node);
-this.dragObjects=[];
-this.constrainToContainer=false;
-if(node){
-this.domNode=node;
-this.dragObject=node;
-dojo.dnd.DragSource.call(this);
-this.type=(type)||(this.domNode.nodeName.toLowerCase());
-}
-});
-dojo.declare("dojo.dnd.HtmlDragObject",dojo.dnd.DragObject,{dragClass:"",opacity:0.5,createIframe:true,disableX:false,disableY:false,createDragNode:function(){
-var node=this.domNode.cloneNode(true);
-if(this.dragClass){
-dojo.html.addClass(node,this.dragClass);
-}
-if(this.opacity<1){
-dojo.html.setOpacity(node,this.opacity);
-}
-if(node.tagName.toLowerCase()=="tr"){
-var doc=this.domNode.ownerDocument;
-var _85a=doc.createElement("table");
-var _85b=doc.createElement("tbody");
-_85a.appendChild(_85b);
-_85b.appendChild(node);
-var _85c=this.domNode.childNodes;
-var _85d=node.childNodes;
-for(var i=0;i<_85c.length;i++){
-if((_85d[i])&&(_85d[i].style)){
-_85d[i].style.width=dojo.html.getContentBox(_85c[i]).width+"px";
-}
-}
-node=_85a;
-}
-if((dojo.render.html.ie55||dojo.render.html.ie60)&&this.createIframe){
-with(node.style){
-top="0px";
-left="0px";
-}
-var _85f=document.createElement("div");
-_85f.appendChild(node);
-this.bgIframe=new dojo.html.BackgroundIframe(_85f);
-_85f.appendChild(this.bgIframe.iframe);
-node=_85f;
-}
-node.style.zIndex=999;
-return node;
-},onDragStart:function(e){
-dojo.html.clearSelection();
-this.scrollOffset=dojo.html.getScroll().offset;
-this.dragStartPosition=dojo.html.getAbsolutePosition(this.domNode,true);
-this.dragOffset={y:this.dragStartPosition.y-e.pageY,x:this.dragStartPosition.x-e.pageX};
-this.dragClone=this.createDragNode();
-this.containingBlockPosition=this.domNode.offsetParent?dojo.html.getAbsolutePosition(this.domNode.offsetParent,true):{x:0,y:0};
-if(this.constrainToContainer){
-this.constraints=this.getConstraints();
-}
-with(this.dragClone.style){
-position="absolute";
-top=this.dragOffset.y+e.pageY+"px";
-left=this.dragOffset.x+e.pageX+"px";
-}
-dojo.body().appendChild(this.dragClone);
-dojo.event.connect(this.domNode,"onclick",this,"squelchOnClick");
-dojo.event.topic.publish("dragStart",{source:this});
-},getConstraints:function(){
-if(this.constrainingContainer.nodeName.toLowerCase()=="body"){
-var _861=dojo.html.getViewport();
-var _862=_861.width;
-var _863=_861.height;
-var x=0;
-var y=0;
-}else{
-var _866=dojo.html.getContentBox(this.constrainingContainer);
-_862=_866.width;
-_863=_866.height;
-x=this.containingBlockPosition.x+dojo.html.getPixelValue(this.constrainingContainer,"padding-left",true)+dojo.html.getBorderExtent(this.constrainingContainer,"left");
-y=this.containingBlockPosition.y+dojo.html.getPixelValue(this.constrainingContainer,"padding-top",true)+dojo.html.getBorderExtent(this.constrainingContainer,"top");
-}
-var mb=dojo.html.getMarginBox(this.domNode);
-return {minX:x,minY:y,maxX:x+_862-mb.width,maxY:y+_863-mb.height};
-},updateDragOffset:function(){
-var _868=dojo.html.getScroll().offset;
-if(_868.y!=this.scrollOffset.y){
-var diff=_868.y-this.scrollOffset.y;
-this.dragOffset.y+=diff;
-this.scrollOffset.y=_868.y;
-}
-if(_868.x!=this.scrollOffset.x){
-var diff=_868.x-this.scrollOffset.x;
-this.dragOffset.x+=diff;
-this.scrollOffset.x=_868.x;
-}
-},onDragMove:function(e){
-this.updateDragOffset();
-var x=this.dragOffset.x+e.pageX;
-var y=this.dragOffset.y+e.pageY;
-if(this.constrainToContainer){
-if(x<this.constraints.minX){
-x=this.constraints.minX;
-}
-if(y<this.constraints.minY){
-y=this.constraints.minY;
-}
-if(x>this.constraints.maxX){
-x=this.constraints.maxX;
-}
-if(y>this.constraints.maxY){
-y=this.constraints.maxY;
-}
-}
-this.setAbsolutePosition(x,y);
-dojo.event.topic.publish("dragMove",{source:this});
-},setAbsolutePosition:function(x,y){
-if(!this.disableY){
-this.dragClone.style.top=y+"px";
-}
-if(!this.disableX){
-this.dragClone.style.left=x+"px";
-}
-},onDragEnd:function(e){
-switch(e.dragStatus){
-case "dropSuccess":
-dojo.html.removeNode(this.dragClone);
-this.dragClone=null;
-break;
-case "dropFailure":
-var _870=dojo.html.getAbsolutePosition(this.dragClone,true);
-var _871={left:this.dragStartPosition.x+1,top:this.dragStartPosition.y+1};
-var anim=dojo.lfx.slideTo(this.dragClone,_871,500,dojo.lfx.easeOut);
-var _873=this;
-dojo.event.connect(anim,"onEnd",function(e){
-dojo.lang.setTimeout(function(){
-dojo.html.removeNode(_873.dragClone);
-_873.dragClone=null;
-},200);
-});
-anim.play();
-break;
-}
-dojo.event.topic.publish("dragEnd",{source:this});
-},squelchOnClick:function(e){
-dojo.event.browser.stopEvent(e);
-dojo.lang.setTimeout(function(){
-dojo.event.disconnect(this.domNode,"onclick",this,"squelchOnClick");
-},50);
-},constrainTo:function(_876){
-this.constrainToContainer=true;
-if(_876){
-this.constrainingContainer=_876;
-}else{
-this.constrainingContainer=this.domNode.parentNode;
-}
-}},function(node,type){
-this.domNode=dojo.byId(node);
-this.type=type;
-this.constrainToContainer=false;
-this.dragSource=null;
-});
-dojo.declare("dojo.dnd.HtmlDropTarget",dojo.dnd.DropTarget,{vertical:false,onDragOver:function(e){
-if(!this.accepts(e.dragObjects)){
-return false;
-}
-this.childBoxes=[];
-for(var i=0,_87b;i<this.domNode.childNodes.length;i++){
-_87b=this.domNode.childNodes[i];
-if(_87b.nodeType!=dojo.html.ELEMENT_NODE){
-continue;
-}
-var pos=dojo.html.getAbsolutePosition(_87b,true);
-var _87d=dojo.html.getBorderBox(_87b);
-this.childBoxes.push({top:pos.y,bottom:pos.y+_87d.height,left:pos.x,right:pos.x+_87d.width,height:_87d.height,width:_87d.width,node:_87b});
-}
-return true;
-},_getNodeUnderMouse:function(e){
-for(var i=0,_880;i<this.childBoxes.length;i++){
-with(this.childBoxes[i]){
-if(e.pageX>=left&&e.pageX<=right&&e.pageY>=top&&e.pageY<=bottom){
-return i;
-}
-}
-}
-return -1;
-},createDropIndicator:function(){
-this.dropIndicator=document.createElement("div");
-with(this.dropIndicator.style){
-position="absolute";
-zIndex=999;
-if(this.vertical){
-borderLeftWidth="1px";
-borderLeftColor="black";
-borderLeftStyle="solid";
-height=dojo.html.getBorderBox(this.domNode).height+"px";
-top=dojo.html.getAbsolutePosition(this.domNode,true).y+"px";
-}else{
-borderTopWidth="1px";
-borderTopColor="black";
-borderTopStyle="solid";
-width=dojo.html.getBorderBox(this.domNode).width+"px";
-left=dojo.html.getAbsolutePosition(this.domNode,true).x+"px";
-}
-}
-},onDragMove:function(e,_882){
-var i=this._getNodeUnderMouse(e);
-if(!this.dropIndicator){
-this.createDropIndicator();
-}
-var _884=this.vertical?dojo.html.gravity.WEST:dojo.html.gravity.NORTH;
-var hide=false;
-if(i<0){
-if(this.childBoxes.length){
-var _886=(dojo.html.gravity(this.childBoxes[0].node,e)&_884);
-if(_886){
-hide=true;
-}
-}else{
-var _886=true;
-}
-}else{
-var _887=this.childBoxes[i];
-var _886=(dojo.html.gravity(_887.node,e)&_884);
-if(_887.node===_882[0].dragSource.domNode){
-hide=true;
-}else{
-var _888=_886?(i>0?this.childBoxes[i-1]:_887):(i<this.childBoxes.length-1?this.childBoxes[i+1]:_887);
-if(_888.node===_882[0].dragSource.domNode){
-hide=true;
-}
-}
-}
-if(hide){
-this.dropIndicator.style.display="none";
-return;
-}else{
-this.dropIndicator.style.display="";
-}
-this.placeIndicator(e,_882,i,_886);
-if(!dojo.html.hasParent(this.dropIndicator)){
-dojo.body().appendChild(this.dropIndicator);
-}
-},placeIndicator:function(e,_88a,_88b,_88c){
-var _88d=this.vertical?"left":"top";
-var _88e;
-if(_88b<0){
-if(this.childBoxes.length){
-_88e=_88c?this.childBoxes[0]:this.childBoxes[this.childBoxes.length-1];
-}else{
-this.dropIndicator.style[_88d]=dojo.html.getAbsolutePosition(this.domNode,true)[this.vertical?"x":"y"]+"px";
-}
-}else{
-_88e=this.childBoxes[_88b];
-}
-if(_88e){
-this.dropIndicator.style[_88d]=(_88c?_88e[_88d]:_88e[this.vertical?"right":"bottom"])+"px";
-if(this.vertical){
-this.dropIndicator.style.height=_88e.height+"px";
-this.dropIndicator.style.top=_88e.top+"px";
-}else{
-this.dropIndicator.style.width=_88e.width+"px";
-this.dropIndicator.style.left=_88e.left+"px";
-}
-}
-},onDragOut:function(e){
-if(this.dropIndicator){
-dojo.html.removeNode(this.dropIndicator);
-delete this.dropIndicator;
-}
-},onDrop:function(e){
-this.onDragOut(e);
-var i=this._getNodeUnderMouse(e);
-var _892=this.vertical?dojo.html.gravity.WEST:dojo.html.gravity.NORTH;
-if(i<0){
-if(this.childBoxes.length){
-if(dojo.html.gravity(this.childBoxes[0].node,e)&_892){
-return this.insert(e,this.childBoxes[0].node,"before");
-}else{
-return this.insert(e,this.childBoxes[this.childBoxes.length-1].node,"after");
-}
-}
-return this.insert(e,this.domNode,"append");
-}
-var _893=this.childBoxes[i];
-if(dojo.html.gravity(_893.node,e)&_892){
-return this.insert(e,_893.node,"before");
-}else{
-return this.insert(e,_893.node,"after");
-}
-},insert:function(e,_895,_896){
-var node=e.dragObject.domNode;
-if(_896=="before"){
-return dojo.html.insertBefore(node,_895);
-}else{
-if(_896=="after"){
-return dojo.html.insertAfter(node,_895);
-}else{
-if(_896=="append"){
-_895.appendChild(node);
-return true;
-}
-}
-}
-return false;
-}},function(node,_899){
-if(arguments.length==0){
-return;
-}
-this.domNode=dojo.byId(node);
-dojo.dnd.DropTarget.call(this);
-if(_899&&dojo.lang.isString(_899)){
-_899=[_899];
-}
-this.acceptedTypes=_899||[];
-});
-dojo.provide("dojo.dnd.*");
-dojo.provide("dojo.ns");
-dojo.ns={namespaces:{},failed:{},loading:{},loaded:{},register:function(name,_89b,_89c,_89d){
-if(!_89d||!this.namespaces[name]){
-this.namespaces[name]=new dojo.ns.Ns(name,_89b,_89c);
-}
-},allow:function(name){
-if(this.failed[name]){
-return false;
-}
-if((djConfig.excludeNamespace)&&(dojo.lang.inArray(djConfig.excludeNamespace,name))){
-return false;
-}
-return ((name==this.dojo)||(!djConfig.includeNamespace)||(dojo.lang.inArray(djConfig.includeNamespace,name)));
-},get:function(name){
-return this.namespaces[name];
-},require:function(name){
-var ns=this.namespaces[name];
-if((ns)&&(this.loaded[name])){
-return ns;
-}
-if(!this.allow(name)){
-return false;
-}
-if(this.loading[name]){
-dojo.debug("dojo.namespace.require: re-entrant request to load namespace \""+name+"\" must fail.");
-return false;
-}
-var req=dojo.require;
-this.loading[name]=true;
-try{
-if(name=="dojo"){
-req("dojo.namespaces.dojo");
-}else{
-if(!dojo.hostenv.moduleHasPrefix(name)){
-dojo.registerModulePath(name,"../"+name);
-}
-req([name,"manifest"].join("."),false,true);
-}
-if(!this.namespaces[name]){
-this.failed[name]=true;
-}
-}
-finally{
-this.loading[name]=false;
-}
-return this.namespaces[name];
-}};
-dojo.ns.Ns=function(name,_8a4,_8a5){
-this.name=name;
-this.module=_8a4;
-this.resolver=_8a5;
-this._loaded=[];
-this._failed=[];
-};
-dojo.ns.Ns.prototype.resolve=function(name,_8a7,_8a8){
-if(!this.resolver||djConfig["skipAutoRequire"]){
-return false;
-}
-var _8a9=this.resolver(name,_8a7);
-if((_8a9)&&(!this._loaded[_8a9])&&(!this._failed[_8a9])){
-var req=dojo.require;
-req(_8a9,false,true);
-if(dojo.hostenv.findModule(_8a9,false)){
-this._loaded[_8a9]=true;
-}else{
-if(!_8a8){
-dojo.raise("dojo.ns.Ns.resolve: module '"+_8a9+"' not found after loading via namespace '"+this.name+"'");
-}
-this._failed[_8a9]=true;
-}
-}
-return Boolean(this._loaded[_8a9]);
-};
-dojo.registerNamespace=function(name,_8ac,_8ad){
-dojo.ns.register.apply(dojo.ns,arguments);
-};
-dojo.registerNamespaceResolver=function(name,_8af){
-var n=dojo.ns.namespaces[name];
-if(n){
-n.resolver=_8af;
-}
-};
-dojo.registerNamespaceManifest=function(_8b1,path,name,_8b4,_8b5){
-dojo.registerModulePath(name,path);
-dojo.registerNamespace(name,_8b4,_8b5);
-};
-dojo.registerNamespace("dojo","dojo.widget");
-dojo.provide("dojo.widget.Manager");
-dojo.widget.manager=new function(){
-this.widgets=[];
-this.widgetIds=[];
-this.topWidgets={};
-var _8b6={};
-var _8b7=[];
-this.getUniqueId=function(_8b8){
-var _8b9;
-do{
-_8b9=_8b8+"_"+(_8b6[_8b8]!=undefined?++_8b6[_8b8]:_8b6[_8b8]=0);
-}while(this.getWidgetById(_8b9));
-return _8b9;
-};
-this.add=function(_8ba){
-this.widgets.push(_8ba);
-if(!_8ba.extraArgs["id"]){
-_8ba.extraArgs["id"]=_8ba.extraArgs["ID"];
-}
-if(_8ba.widgetId==""){
-if(_8ba["id"]){
-_8ba.widgetId=_8ba["id"];
-}else{
-if(_8ba.extraArgs["id"]){
-_8ba.widgetId=_8ba.extraArgs["id"];
-}else{
-_8ba.widgetId=this.getUniqueId(_8ba.widgetType);
-}
-}
-}
-if(this.widgetIds[_8ba.widgetId]){
-dojo.debug("widget ID collision on ID: "+_8ba.widgetId);
-}
-this.widgetIds[_8ba.widgetId]=_8ba;
-};
-this.destroyAll=function(){
-for(var x=this.widgets.length-1;x>=0;x--){
-try{
-this.widgets[x].destroy(true);
-delete this.widgets[x];
-}
-catch(e){
-}
-}
-};
-this.remove=function(_8bc){
-if(dojo.lang.isNumber(_8bc)){
-var tw=this.widgets[_8bc].widgetId;
-delete this.widgetIds[tw];
-this.widgets.splice(_8bc,1);
-}else{
-this.removeById(_8bc);
-}
-};
-this.removeById=function(id){
-if(!dojo.lang.isString(id)){
-id=id["widgetId"];
-if(!id){
-dojo.debug("invalid widget or id passed to removeById");
-return;
-}
-}
-for(var i=0;i<this.widgets.length;i++){
-if(this.widgets[i].widgetId==id){
-this.remove(i);
-break;
-}
-}
-};
-this.getWidgetById=function(id){
-if(dojo.lang.isString(id)){
-return this.widgetIds[id];
-}
-return id;
-};
-this.getWidgetsByType=function(type){
-var lt=type.toLowerCase();
-var _8c3=(type.indexOf(":")<0?function(x){
-return x.widgetType.toLowerCase();
-}:function(x){
-return x.getNamespacedType();
-});
-var ret=[];
-dojo.lang.forEach(this.widgets,function(x){
-if(_8c3(x)==lt){
-ret.push(x);
-}
-});
-return ret;
-};
-this.getWidgetsByFilter=function(_8c8,_8c9){
-var ret=[];
-dojo.lang.every(this.widgets,function(x){
-if(_8c8(x)){
-ret.push(x);
-if(_8c9){
-return false;
-}
-}
-return true;
-});
-return (_8c9?ret[0]:ret);
-};
-this.getAllWidgets=function(){
-return this.widgets.concat();
-};
-this.getWidgetByNode=function(node){
-var w=this.getAllWidgets();
-node=dojo.byId(node);
-for(var i=0;i<w.length;i++){
-if(w[i].domNode==node){
-return w[i];
-}
-}
-return null;
-};
-this.byId=this.getWidgetById;
-this.byType=this.getWidgetsByType;
-this.byFilter=this.getWidgetsByFilter;
-this.byNode=this.getWidgetByNode;
-var _8cf={};
-var _8d0=["dojo.widget"];
-for(var i=0;i<_8d0.length;i++){
-_8d0[_8d0[i]]=true;
-}
-this.registerWidgetPackage=function(_8d2){
-if(!_8d0[_8d2]){
-_8d0[_8d2]=true;
-_8d0.push(_8d2);
-}
-};
-this.getWidgetPackageList=function(){
-return dojo.lang.map(_8d0,function(elt){
-return (elt!==true?elt:undefined);
-});
-};
-this.getImplementation=function(_8d4,_8d5,_8d6,ns){
-var impl=this.getImplementationName(_8d4,ns);
-if(impl){
-var ret=_8d5?new impl(_8d5):new impl();
-return ret;
-}
-};
-function buildPrefixCache(){
-for(var _8da in dojo.render){
-if(dojo.render[_8da]["capable"]===true){
-var _8db=dojo.render[_8da].prefixes;
-for(var i=0;i<_8db.length;i++){
-_8b7.push(_8db[i].toLowerCase());
-}
-}
-}
-}
-var _8dd=function(_8de,_8df){
-if(!_8df){
-return null;
-}
-for(var i=0,l=_8b7.length,_8e2;i<=l;i++){
-_8e2=(i<l?_8df[_8b7[i]]:_8df);
-if(!_8e2){
-continue;
-}
-for(var name in _8e2){
-if(name.toLowerCase()==_8de){
-return _8e2[name];
-}
-}
-}
-return null;
-};
-var _8e4=function(_8e5,_8e6){
-var _8e7=dojo.evalObjPath(_8e6,false);
-return (_8e7?_8dd(_8e5,_8e7):null);
-};
-this.getImplementationName=function(_8e8,ns){
-var _8ea=_8e8.toLowerCase();
-ns=ns||"dojo";
-var imps=_8cf[ns]||(_8cf[ns]={});
-var impl=imps[_8ea];
-if(impl){
-return impl;
-}
-if(!_8b7.length){
-buildPrefixCache();
-}
-var _8ed=dojo.ns.get(ns);
-if(!_8ed){
-dojo.ns.register(ns,ns+".widget");
-_8ed=dojo.ns.get(ns);
-}
-if(_8ed){
-_8ed.resolve(_8e8);
-}
-impl=_8e4(_8ea,_8ed.module);
-if(impl){
-return (imps[_8ea]=impl);
-}
-_8ed=dojo.ns.require(ns);
-if((_8ed)&&(_8ed.resolver)){
-_8ed.resolve(_8e8);
-impl=_8e4(_8ea,_8ed.module);
-if(impl){
-return (imps[_8ea]=impl);
-}
-}
-dojo.deprecated("dojo.widget.Manager.getImplementationName","Could not locate widget implementation for \""+_8e8+"\" in \""+_8ed.module+"\" registered to namespace \""+_8ed.name+"\". "+"Developers must specify correct namespaces for all non-Dojo widgets","0.5");
-for(var i=0;i<_8d0.length;i++){
-impl=_8e4(_8ea,_8d0[i]);
-if(impl){
-return (imps[_8ea]=impl);
-}
-}
-throw new Error("Could not locate widget implementation for \""+_8e8+"\" in \""+_8ed.module+"\" registered to namespace \""+_8ed.name+"\"");
-};
-this.resizing=false;
-this.onWindowResized=function(){
-if(this.resizing){
-return;
-}
-try{
-this.resizing=true;
-for(var id in this.topWidgets){
-var _8f0=this.topWidgets[id];
-if(_8f0.checkSize){
-_8f0.checkSize();
-}
-}
-}
-catch(e){
-}
-finally{
-this.resizing=false;
-}
-};
-if(typeof window!="undefined"){
-dojo.addOnLoad(this,"onWindowResized");
-dojo.event.connect(window,"onresize",this,"onWindowResized");
-}
-};
-(function(){
-var dw=dojo.widget;
-var dwm=dw.manager;
-var h=dojo.lang.curry(dojo.lang,"hitch",dwm);
-var g=function(_8f5,_8f6){
-dw[(_8f6||_8f5)]=h(_8f5);
-};
-g("add","addWidget");
-g("destroyAll","destroyAllWidgets");
-g("remove","removeWidget");
-g("removeById","removeWidgetById");
-g("getWidgetById");
-g("getWidgetById","byId");
-g("getWidgetsByType");
-g("getWidgetsByFilter");
-g("getWidgetsByType","byType");
-g("getWidgetsByFilter","byFilter");
-g("getWidgetByNode","byNode");
-dw.all=function(n){
-var _8f8=dwm.getAllWidgets.apply(dwm,arguments);
-if(arguments.length>0){
-return _8f8[n];
-}
-return _8f8;
-};
-g("registerWidgetPackage");
-g("getImplementation","getWidgetImplementation");
-g("getImplementationName","getWidgetImplementationName");
-dw.widgets=dwm.widgets;
-dw.widgetIds=dwm.widgetIds;
-dw.root=dwm.root;
-})();
-dojo.provide("dojo.a11y");
-dojo.a11y={imgPath:dojo.uri.dojoUri("src/widget/templates/images"),doAccessibleCheck:true,accessible:null,checkAccessible:function(){
-if(this.accessible===null){
-this.accessible=false;
-if(this.doAccessibleCheck==true){
-this.accessible=this.testAccessible();
-}
-}
-return this.accessible;
-},testAccessible:function(){
-this.accessible=false;
-if(dojo.render.html.ie||dojo.render.html.mozilla){
-var div=document.createElement("div");
-div.style.backgroundImage="url(\""+this.imgPath+"/tab_close.gif\")";
-dojo.body().appendChild(div);
-var _8fa=null;
-if(window.getComputedStyle){
-var _8fb=getComputedStyle(div,"");
-_8fa=_8fb.getPropertyValue("background-image");
-}else{
-_8fa=div.currentStyle.backgroundImage;
-}
-var _8fc=false;
-if(_8fa!=null&&(_8fa=="none"||_8fa=="url(invalid-url:)")){
-this.accessible=true;
-}
-dojo.body().removeChild(div);
-}
-return this.accessible;
-},setCheckAccessible:function(_8fd){
-this.doAccessibleCheck=_8fd;
-},setAccessibleMode:function(){
-if(this.accessible===null){
-if(this.checkAccessible()){
-dojo.render.html.prefixes.unshift("a11y");
-}
-}
-return this.accessible;
-}};
-dojo.provide("dojo.widget.Widget");
-dojo.declare("dojo.widget.Widget",null,function(){
-this.children=[];
-this.extraArgs={};
-},{parent:null,children:[],extraArgs:{},isTopLevel:false,isModal:false,isEnabled:true,isHidden:false,isContainer:false,widgetId:"",widgetType:"Widget",ns:"dojo",getNamespacedType:function(){
-return (this.ns?this.ns+":"+this.widgetType:this.widgetType).toLowerCase();
-},toString:function(){
-return "[Widget "+this.getNamespacedType()+", "+(this.widgetId||"NO ID")+"]";
-},repr:function(){
-return this.toString();
-},enable:function(){
-this.isEnabled=true;
-},disable:function(){
-this.isEnabled=false;
-},hide:function(){
-this.isHidden=true;
-},show:function(){
-this.isHidden=false;
-},onResized:function(){
-this.notifyChildrenOfResize();
-},notifyChildrenOfResize:function(){
-for(var i=0;i<this.children.length;i++){
-var _8ff=this.children[i];
-if(_8ff.onResized){
-_8ff.onResized();
-}
-}
-},create:function(args,_901,_902,ns){
-if(ns){
-this.ns=ns;
-}
-this.satisfyPropertySets(args,_901,_902);
-this.mixInProperties(args,_901,_902);
-this.postMixInProperties(args,_901,_902);
-dojo.widget.manager.add(this);
-this.buildRendering(args,_901,_902);
-this.initialize(args,_901,_902);
-this.postInitialize(args,_901,_902);
-this.postCreate(args,_901,_902);
-return this;
-},destroy:function(_904){
-this.destroyChildren();
-this.uninitialize();
-this.destroyRendering(_904);
-dojo.widget.manager.removeById(this.widgetId);
-},destroyChildren:function(){
-var _905;
-var i=0;
-while(this.children.length>i){
-_905=this.children[i];
-if(_905 instanceof dojo.widget.Widget){
-this.removeChild(_905);
-_905.destroy();
-continue;
-}
-i++;
-}
-},getChildrenOfType:function(type,_908){
-var ret=[];
-var _90a=dojo.lang.isFunction(type);
-if(!_90a){
-type=type.toLowerCase();
-}
-for(var x=0;x<this.children.length;x++){
-if(_90a){
-if(this.children[x] instanceof type){
-ret.push(this.children[x]);
-}
-}else{
-if(this.children[x].widgetType.toLowerCase()==type){
-ret.push(this.children[x]);
-}
-}
-if(_908){
-ret=ret.concat(this.children[x].getChildrenOfType(type,_908));
-}
-}
-return ret;
-},getDescendants:function(){
-var _90c=[];
-var _90d=[this];
-var elem;
-while((elem=_90d.pop())){
-_90c.push(elem);
-if(elem.children){
-dojo.lang.forEach(elem.children,function(elem){
-_90d.push(elem);
-});
-}
-}
-return _90c;
-},isFirstChild:function(){
-return this===this.parent.children[0];
-},isLastChild:function(){
-return this===this.parent.children[this.parent.children.length-1];
-},satisfyPropertySets:function(args){
-return args;
-},mixInProperties:function(args,frag){
-if((args["fastMixIn"])||(frag["fastMixIn"])){
-for(var x in args){
-this[x]=args[x];
-}
-return;
-}
-var _914;
-var _915=dojo.widget.lcArgsCache[this.widgetType];
-if(_915==null){
-_915={};
-for(var y in this){
-_915[((new String(y)).toLowerCase())]=y;
-}
-dojo.widget.lcArgsCache[this.widgetType]=_915;
-}
-var _917={};
-for(var x in args){
-if(!this[x]){
-var y=_915[(new String(x)).toLowerCase()];
-if(y){
-args[y]=args[x];
-x=y;
-}
-}
-if(_917[x]){
-continue;
-}
-_917[x]=true;
-if((typeof this[x])!=(typeof _914)){
-if(typeof args[x]!="string"){
-this[x]=args[x];
-}else{
-if(dojo.lang.isString(this[x])){
-this[x]=args[x];
-}else{
-if(dojo.lang.isNumber(this[x])){
-this[x]=new Number(args[x]);
-}else{
-if(dojo.lang.isBoolean(this[x])){
-this[x]=(args[x].toLowerCase()=="false")?false:true;
-}else{
-if(dojo.lang.isFunction(this[x])){
-if(args[x].search(/[^\w\.]+/i)==-1){
-this[x]=dojo.evalObjPath(args[x],false);
-}else{
-var tn=dojo.lang.nameAnonFunc(new Function(args[x]),this);
-dojo.event.kwConnect({srcObj:this,srcFunc:x,adviceObj:this,adviceFunc:tn});
-}
-}else{
-if(dojo.lang.isArray(this[x])){
-this[x]=args[x].split(";");
-}else{
-if(this[x] instanceof Date){
-this[x]=new Date(Number(args[x]));
-}else{
-if(typeof this[x]=="object"){
-if(this[x] instanceof dojo.uri.Uri){
-this[x]=args[x];
-}else{
-var _919=args[x].split(";");
-for(var y=0;y<_919.length;y++){
-var si=_919[y].indexOf(":");
-if((si!=-1)&&(_919[y].length>si)){
-this[x][_919[y].substr(0,si).replace(/^\s+|\s+$/g,"")]=_919[y].substr(si+1);
-}
-}
-}
-}else{
-this[x]=args[x];
-}
-}
-}
-}
-}
-}
-}
-}
-}else{
-this.extraArgs[x.toLowerCase()]=args[x];
-}
-}
-},postMixInProperties:function(args,frag,_91d){
-},initialize:function(args,frag,_920){
-return false;
-},postInitialize:function(args,frag,_923){
-return false;
-},postCreate:function(args,frag,_926){
-return false;
-},uninitialize:function(){
-return false;
-},buildRendering:function(args,frag,_929){
-dojo.unimplemented("dojo.widget.Widget.buildRendering, on "+this.toString()+", ");
-return false;
-},destroyRendering:function(){
-dojo.unimplemented("dojo.widget.Widget.destroyRendering");
-return false;
-},cleanUp:function(){
-dojo.unimplemented("dojo.widget.Widget.cleanUp");
-return false;
-},addedTo:function(_92a){
-},addChild:function(_92b){
-dojo.unimplemented("dojo.widget.Widget.addChild");
-return false;
-},removeChild:function(_92c){
-for(var x=0;x<this.children.length;x++){
-if(this.children[x]===_92c){
-this.children.splice(x,1);
-break;
-}
-}
-return _92c;
-},resize:function(_92e,_92f){
-this.setWidth(_92e);
-this.setHeight(_92f);
-},setWidth:function(_930){
-if((typeof _930=="string")&&(_930.substr(-1)=="%")){
-this.setPercentageWidth(_930);
-}else{
-this.setNativeWidth(_930);
-}
-},setHeight:function(_931){
-if((typeof _931=="string")&&(_931.substr(-1)=="%")){
-this.setPercentageHeight(_931);
-}else{
-this.setNativeHeight(_931);
-}
-},setPercentageHeight:function(_932){
-return false;
-},setNativeHeight:function(_933){
-return false;
-},setPercentageWidth:function(_934){
-return false;
-},setNativeWidth:function(_935){
-return false;
-},getPreviousSibling:function(){
-var idx=this.getParentIndex();
-if(idx<=0){
-return null;
-}
-return this.parent.children[idx-1];
-},getSiblings:function(){
-return this.parent.children;
-},getParentIndex:function(){
-return dojo.lang.indexOf(this.parent.children,this,true);
-},getNextSibling:function(){
-var idx=this.getParentIndex();
-if(idx==this.parent.children.length-1){
-return null;
-}
-if(idx<0){
-return null;
-}
-return this.parent.children[idx+1];
-}});
-dojo.widget.lcArgsCache={};
-dojo.widget.tags={};
-dojo.widget.tags.addParseTreeHandler=function(type){
-dojo.deprecated("addParseTreeHandler",". ParseTreeHandlers are now reserved for components. Any unfiltered DojoML tag without a ParseTreeHandler is assumed to be a widget","0.5");
-};
-dojo.widget.tags["dojo:propertyset"]=function(_939,_93a,_93b){
-var _93c=_93a.parseProperties(_939["dojo:propertyset"]);
-};
-dojo.widget.tags["dojo:connect"]=function(_93d,_93e,_93f){
-var _940=_93e.parseProperties(_93d["dojo:connect"]);
-};
-dojo.widget.buildWidgetFromParseTree=function(type,frag,_943,_944,_945,_946){
-dojo.a11y.setAccessibleMode();
-var _947=type.split(":");
-_947=(_947.length==2)?_947[1]:type;
-var _948=_946||_943.parseProperties(frag[frag["ns"]+":"+_947]);
-var _949=dojo.widget.manager.getImplementation(_947,null,null,frag["ns"]);
-if(!_949){
-throw new Error("cannot find \""+type+"\" widget");
-}else{
-if(!_949.create){
-throw new Error("\""+type+"\" widget object has no \"create\" method and does not appear to implement *Widget");
-}
-}
-_948["dojoinsertionindex"]=_945;
-var ret=_949.create(_948,frag,_944,frag["ns"]);
-return ret;
-};
-dojo.widget.defineWidget=function(_94b,_94c,_94d,init,_94f){
-if(dojo.lang.isString(arguments[3])){
-dojo.widget._defineWidget(arguments[0],arguments[3],arguments[1],arguments[4],arguments[2]);
-}else{
-var args=[arguments[0]],p=3;
-if(dojo.lang.isString(arguments[1])){
-args.push(arguments[1],arguments[2]);
-}else{
-args.push("",arguments[1]);
-p=2;
-}
-if(dojo.lang.isFunction(arguments[p])){
-args.push(arguments[p],arguments[p+1]);
-}else{
-args.push(null,arguments[p]);
-}
-dojo.widget._defineWidget.apply(this,args);
-}
-};
-dojo.widget.defineWidget.renderers="html|svg|vml";
-dojo.widget._defineWidget=function(_952,_953,_954,init,_956){
-var _957=_952.split(".");
-var type=_957.pop();
-var regx="\\.("+(_953?_953+"|":"")+dojo.widget.defineWidget.renderers+")\\.";
-var r=_952.search(new RegExp(regx));
-_957=(r<0?_957.join("."):_952.substr(0,r));
-dojo.widget.manager.registerWidgetPackage(_957);
-var pos=_957.indexOf(".");
-var _95c=(pos>-1)?_957.substring(0,pos):_957;
-_956=(_956)||{};
-_956.widgetType=type;
-if((!init)&&(_956["classConstructor"])){
-init=_956.classConstructor;
-delete _956.classConstructor;
-}
-dojo.declare(_952,_954,init,_956);
-};
-dojo.provide("dojo.widget.Parse");
-dojo.widget.Parse=function(_95d){
-this.propertySetsList=[];
-this.fragment=_95d;
-this.createComponents=function(frag,_95f){
-var _960=[];
-var _961=false;
-try{
-if((frag)&&(frag["tagName"])&&(frag!=frag["nodeRef"])){
-var _962=dojo.widget.tags;
-var tna=String(frag["tagName"]).split(";");
-for(var x=0;x<tna.length;x++){
-var ltn=(tna[x].replace(/^\s+|\s+$/g,"")).toLowerCase();
-frag.tagName=ltn;
-if(_962[ltn]){
-_961=true;
-var ret=_962[ltn](frag,this,_95f,frag["index"]);
-_960.push(ret);
-}else{
-if(ltn.indexOf(":")==-1){
-ltn="dojo:"+ltn;
-}
-var ret=dojo.widget.buildWidgetFromParseTree(ltn,frag,this,_95f,frag["index"]);
-if(ret){
-_961=true;
-_960.push(ret);
-}
-}
-}
-}
-}
-catch(e){
-dojo.debug("dojo.widget.Parse: error:"+e);
-}
-if(!_961){
-_960=_960.concat(this.createSubComponents(frag,_95f));
-}
-return _960;
-};
-this.createSubComponents=function(_967,_968){
-var frag,_96a=[];
-for(var item in _967){
-frag=_967[item];
-if((frag)&&(typeof frag=="object")&&(frag!=_967.nodeRef)&&(frag!=_967["tagName"])){
-_96a=_96a.concat(this.createComponents(frag,_968));
-}
-}
-return _96a;
-};
-this.parsePropertySets=function(_96c){
-return [];
-};
-this.parseProperties=function(_96d){
-var _96e={};
-for(var item in _96d){
-if((_96d[item]==_96d["tagName"])||(_96d[item]==_96d.nodeRef)){
-}else{
-if((_96d[item]["tagName"])&&(dojo.widget.tags[_96d[item].tagName.toLowerCase()])){
-}else{
-if((_96d[item][0])&&(_96d[item][0].value!="")&&(_96d[item][0].value!=null)){
-try{
-if(item.toLowerCase()=="dataprovider"){
-var _970=this;
-this.getDataProvider(_970,_96d[item][0].value);
-_96e.dataProvider=this.dataProvider;
-}
-_96e[item]=_96d[item][0].value;
-var _971=this.parseProperties(_96d[item]);
-for(var _972 in _971){
-_96e[_972]=_971[_972];
-}
-}
-catch(e){
-dojo.debug(e);
-}
-}
-}
-switch(item.toLowerCase()){
-case "checked":
-case "disabled":
-if(typeof _96e[item]!="boolean"){
-_96e[item]=true;
-}
-break;
-}
-}
-}
-return _96e;
-};
-this.getDataProvider=function(_973,_974){
-dojo.io.bind({url:_974,load:function(type,_976){
-if(type=="load"){
-_973.dataProvider=_976;
-}
-},mimetype:"text/javascript",sync:true});
-};
-this.getPropertySetById=function(_977){
-for(var x=0;x<this.propertySetsList.length;x++){
-if(_977==this.propertySetsList[x]["id"][0].value){
-return this.propertySetsList[x];
-}
-}
-return "";
-};
-this.getPropertySetsByType=function(_979){
-var _97a=[];
-for(var x=0;x<this.propertySetsList.length;x++){
-var cpl=this.propertySetsList[x];
-var cpcc=cpl["componentClass"]||cpl["componentType"]||null;
-var _97e=this.propertySetsList[x]["id"][0].value;
-if((cpcc)&&(_97e==cpcc[0].value)){
-_97a.push(cpl);
-}
-}
-return _97a;
-};
-this.getPropertySets=function(_97f){
-var ppl="dojo:propertyproviderlist";
-var _981=[];
-var _982=_97f["tagName"];
-if(_97f[ppl]){
-var _983=_97f[ppl].value.split(" ");
-for(var _984 in _983){
-if((_984.indexOf("..")==-1)&&(_984.indexOf("://")==-1)){
-var _985=this.getPropertySetById(_984);
-if(_985!=""){
-_981.push(_985);
-}
-}else{
-}
-}
-}
-return (this.getPropertySetsByType(_982)).concat(_981);
-};
-this.createComponentFromScript=function(_986,_987,_988,ns){
-_988.fastMixIn=true;
-var ltn=(ns||"dojo")+":"+_987.toLowerCase();
-if(dojo.widget.tags[ltn]){
-return [dojo.widget.tags[ltn](_988,this,null,null,_988)];
-}
-return [dojo.widget.buildWidgetFromParseTree(ltn,_988,this,null,null,_988)];
-};
-};
-dojo.widget._parser_collection={"dojo":new dojo.widget.Parse()};
-dojo.widget.getParser=function(name){
-if(!name){
-name="dojo";
-}
-if(!this._parser_collection[name]){
-this._parser_collection[name]=new dojo.widget.Parse();
-}
-return this._parser_collection[name];
-};
-dojo.widget.createWidget=function(name,_98d,_98e,_98f){
-var _990=false;
-var _991=(typeof name=="string");
-if(_991){
-var pos=name.indexOf(":");
-var ns=(pos>-1)?name.substring(0,pos):"dojo";
-if(pos>-1){
-name=name.substring(pos+1);
-}
-var _994=name.toLowerCase();
-var _995=ns+":"+_994;
-_990=(dojo.byId(name)&&(!dojo.widget.tags[_995]));
-}
-if((arguments.length==1)&&((_990)||(!_991))){
-var xp=new dojo.xml.Parse();
-var tn=(_990)?dojo.byId(name):name;
-return dojo.widget.getParser().createComponents(xp.parseElement(tn,null,true))[0];
-}
-function fromScript(_998,name,_99a,ns){
-_99a[_995]={dojotype:[{value:_994}],nodeRef:_998,fastMixIn:true};
-_99a.ns=ns;
-return dojo.widget.getParser().createComponentFromScript(_998,name,_99a,ns);
-}
-_98d=_98d||{};
-var _99c=false;
-var tn=null;
-var h=dojo.render.html.capable;
-if(h){
-tn=document.createElement("span");
-}
-if(!_98e){
-_99c=true;
-_98e=tn;
-if(h){
-dojo.body().appendChild(_98e);
-}
-}else{
-if(_98f){
-dojo.dom.insertAtPosition(tn,_98e,_98f);
-}else{
-tn=_98e;
-}
-}
-var _99e=fromScript(tn,name.toLowerCase(),_98d,ns);
-if((!_99e)||(!_99e[0])||(typeof _99e[0].widgetType=="undefined")){
-throw new Error("createWidget: Creation of \""+name+"\" widget failed.");
-}
-try{
-if(_99c){
-if(_99e[0].domNode.parentNode){
-_99e[0].domNode.parentNode.removeChild(_99e[0].domNode);
-}
-}
-}
-catch(e){
-dojo.debug(e);
-}
-return _99e[0];
-};
-dojo.provide("dojo.widget.DomWidget");
-dojo.widget._cssFiles={};
-dojo.widget._cssStrings={};
-dojo.widget._templateCache={};
-dojo.widget.defaultStrings={dojoRoot:dojo.hostenv.getBaseScriptUri(),baseScriptUri:dojo.hostenv.getBaseScriptUri()};
-dojo.widget.fillFromTemplateCache=function(obj,_9a0,_9a1,_9a2){
-var _9a3=_9a0||obj.templatePath;
-var _9a4=dojo.widget._templateCache;
-if(!obj["widgetType"]){
-do{
-var _9a5="__dummyTemplate__"+dojo.widget._templateCache.dummyCount++;
-}while(_9a4[_9a5]);
-obj.widgetType=_9a5;
-}
-var wt=obj.widgetType;
-var ts=_9a4[wt];
-if(!ts){
-_9a4[wt]={"string":null,"node":null};
-if(_9a2){
-ts={};
-}else{
-ts=_9a4[wt];
-}
-}
-if((!obj.templateString)&&(!_9a2)){
-obj.templateString=_9a1||ts["string"];
-}
-if((!obj.templateNode)&&(!_9a2)){
-obj.templateNode=ts["node"];
-}
-if((!obj.templateNode)&&(!obj.templateString)&&(_9a3)){
-var _9a8=dojo.hostenv.getText(_9a3);
-if(_9a8){
-_9a8=_9a8.replace(/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im,"");
-var _9a9=_9a8.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
-if(_9a9){
-_9a8=_9a9[1];
-}
-}else{
-_9a8="";
-}
-obj.templateString=_9a8;
-if(!_9a2){
-_9a4[wt]["string"]=_9a8;
-}
-}
-if((!ts["string"])&&(!_9a2)){
-ts.string=obj.templateString;
-}
-};
-dojo.widget._templateCache.dummyCount=0;
-dojo.widget.attachProperties=["dojoAttachPoint","id"];
-dojo.widget.eventAttachProperty="dojoAttachEvent";
-dojo.widget.onBuildProperty="dojoOnBuild";
-dojo.widget.waiNames=["waiRole","waiState"];
-dojo.widget.wai={waiRole:{name:"waiRole","namespace":"http://www.w3.org/TR/xhtml2",alias:"x2",prefix:"wairole:"},waiState:{name:"waiState","namespace":"http://www.w3.org/2005/07/aaa",alias:"aaa",prefix:""},setAttr:function(node,ns,attr,_9ad){
-if(dojo.render.html.ie){
-node.setAttribute(this[ns].alias+":"+attr,this[ns].prefix+_9ad);
-}else{
-node.setAttributeNS(this[ns]["namespace"],attr,this[ns].prefix+_9ad);
-}
-},getAttr:function(node,ns,attr){
-if(dojo.render.html.ie){
-return node.getAttribute(this[ns].alias+":"+attr);
-}else{
-return node.getAttributeNS(this[ns]["namespace"],attr);
-}
-},removeAttr:function(node,ns,attr){
-var _9b4=true;
-if(dojo.render.html.ie){
-_9b4=node.removeAttribute(this[ns].alias+":"+attr);
-}else{
-node.removeAttributeNS(this[ns]["namespace"],attr);
-}
-return _9b4;
-}};
-dojo.widget.attachTemplateNodes=function(_9b5,_9b6,_9b7){
-var _9b8=dojo.dom.ELEMENT_NODE;
-function trim(str){
-return str.replace(/^\s+|\s+$/g,"");
-}
-if(!_9b5){
-_9b5=_9b6.domNode;
-}
-if(_9b5.nodeType!=_9b8){
-return;
-}
-var _9ba=_9b5.all||_9b5.getElementsByTagName("*");
-var _9bb=_9b6;
-for(var x=-1;x<_9ba.length;x++){
-var _9bd=(x==-1)?_9b5:_9ba[x];
-var _9be=[];
-if(!_9b6.widgetsInTemplate||!_9bd.getAttribute("dojoType")){
-for(var y=0;y<this.attachProperties.length;y++){
-var _9c0=_9bd.getAttribute(this.attachProperties[y]);
-if(_9c0){
-_9be=_9c0.split(";");
-for(var z=0;z<_9be.length;z++){
-if(dojo.lang.isArray(_9b6[_9be[z]])){
-_9b6[_9be[z]].push(_9bd);
-}else{
-_9b6[_9be[z]]=_9bd;
-}
-}
-break;
-}
-}
-var _9c2=_9bd.getAttribute(this.eventAttachProperty);
-if(_9c2){
-var evts=_9c2.split(";");
-for(var y=0;y<evts.length;y++){
-if((!evts[y])||(!evts[y].length)){
-continue;
-}
-var _9c4=null;
-var tevt=trim(evts[y]);
-if(evts[y].indexOf(":")>=0){
-var _9c6=tevt.split(":");
-tevt=trim(_9c6[0]);
-_9c4=trim(_9c6[1]);
-}
-if(!_9c4){
-_9c4=tevt;
-}
-var tf=function(){
-var ntf=new String(_9c4);
-return function(evt){
-if(_9bb[ntf]){
-_9bb[ntf](dojo.event.browser.fixEvent(evt,this));
-}
-};
-}();
-dojo.event.browser.addListener(_9bd,tevt,tf,false,true);
-}
-}
-for(var y=0;y<_9b7.length;y++){
-var _9ca=_9bd.getAttribute(_9b7[y]);
-if((_9ca)&&(_9ca.length)){
-var _9c4=null;
-var _9cb=_9b7[y].substr(4);
-_9c4=trim(_9ca);
-var _9cc=[_9c4];
-if(_9c4.indexOf(";")>=0){
-_9cc=dojo.lang.map(_9c4.split(";"),trim);
-}
-for(var z=0;z<_9cc.length;z++){
-if(!_9cc[z].length){
-continue;
-}
-var tf=function(){
-var ntf=new String(_9cc[z]);
-return function(evt){
-if(_9bb[ntf]){
-_9bb[ntf](dojo.event.browser.fixEvent(evt,this));
-}
-};
-}();
-dojo.event.browser.addListener(_9bd,_9cb,tf,false,true);
-}
-}
-}
-}
-var _9cf=_9bd.getAttribute(this.templateProperty);
-if(_9cf){
-_9b6[_9cf]=_9bd;
-}
-dojo.lang.forEach(dojo.widget.waiNames,function(name){
-var wai=dojo.widget.wai[name];
-var val=_9bd.getAttribute(wai.name);
-if(val){
-if(val.indexOf("-")==-1){
-dojo.widget.wai.setAttr(_9bd,wai.name,"role",val);
-}else{
-var _9d3=val.split("-");
-dojo.widget.wai.setAttr(_9bd,wai.name,_9d3[0],_9d3[1]);
-}
-}
-},this);
-var _9d4=_9bd.getAttribute(this.onBuildProperty);
-if(_9d4){
-eval("var node = baseNode; var widget = targetObj; "+_9d4);
-}
-}
-};
-dojo.widget.getDojoEventsFromStr=function(str){
-var re=/(dojoOn([a-z]+)(\s?))=/gi;
-var evts=str?str.match(re)||[]:[];
-var ret=[];
-var lem={};
-for(var x=0;x<evts.length;x++){
-if(evts[x].length<1){
-continue;
-}
-var cm=evts[x].replace(/\s/,"");
-cm=(cm.slice(0,cm.length-1));
-if(!lem[cm]){
-lem[cm]=true;
-ret.push(cm);
-}
-}
-return ret;
-};
-dojo.declare("dojo.widget.DomWidget",dojo.widget.Widget,function(){
-if((arguments.length>0)&&(typeof arguments[0]=="object")){
-this.create(arguments[0]);
-}
-},{templateNode:null,templateString:null,templateCssString:null,preventClobber:false,domNode:null,containerNode:null,widgetsInTemplate:false,addChild:function(_9dc,_9dd,pos,ref,_9e0){
-if(!this.isContainer){
-dojo.debug("dojo.widget.DomWidget.addChild() attempted on non-container widget");
-return null;
-}else{
-if(_9e0==undefined){
-_9e0=this.children.length;
-}
-this.addWidgetAsDirectChild(_9dc,_9dd,pos,ref,_9e0);
-this.registerChild(_9dc,_9e0);
-}
-return _9dc;
-},addWidgetAsDirectChild:function(_9e1,_9e2,pos,ref,_9e5){
-if((!this.containerNode)&&(!_9e2)){
-this.containerNode=this.domNode;
-}
-var cn=(_9e2)?_9e2:this.containerNode;
-if(!pos){
-pos="after";
-}
-if(!ref){
-if(!cn){
-cn=dojo.body();
-}
-ref=cn.lastChild;
-}
-if(!_9e5){
-_9e5=0;
-}
-_9e1.domNode.setAttribute("dojoinsertionindex",_9e5);
-if(!ref){
-cn.appendChild(_9e1.domNode);
-}else{
-if(pos=="insertAtIndex"){
-dojo.dom.insertAtIndex(_9e1.domNode,ref.parentNode,_9e5);
-}else{
-if((pos=="after")&&(ref===cn.lastChild)){
-cn.appendChild(_9e1.domNode);
-}else{
-dojo.dom.insertAtPosition(_9e1.domNode,cn,pos);
-}
-}
-}
-},registerChild:function(_9e7,_9e8){
-_9e7.dojoInsertionIndex=_9e8;
-var idx=-1;
-for(var i=0;i<this.children.length;i++){
-if(this.children[i].dojoInsertionIndex<=_9e8){
-idx=i;
-}
-}
-this.children.splice(idx+1,0,_9e7);
-_9e7.parent=this;
-_9e7.addedTo(this,idx+1);
-delete dojo.widget.manager.topWidgets[_9e7.widgetId];
-},removeChild:function(_9eb){
-dojo.dom.removeNode(_9eb.domNode);
-return dojo.widget.DomWidget.superclass.removeChild.call(this,_9eb);
-},getFragNodeRef:function(frag){
-if(!frag){
-return null;
-}
-if(!frag[this.getNamespacedType()]){
-dojo.raise("Error: no frag for widget type "+this.getNamespacedType()+", id "+this.widgetId+" (maybe a widget has set it's type incorrectly)");
-}
-return frag[this.getNamespacedType()]["nodeRef"];
-},postInitialize:function(args,frag,_9ef){
-var _9f0=this.getFragNodeRef(frag);
-if(_9ef&&(_9ef.snarfChildDomOutput||!_9f0)){
-_9ef.addWidgetAsDirectChild(this,"","insertAtIndex","",args["dojoinsertionindex"],_9f0);
-}else{
-if(_9f0){
-if(this.domNode&&(this.domNode!==_9f0)){
-var _9f1=_9f0.parentNode.replaceChild(this.domNode,_9f0);
-}
-}
-}
-if(_9ef){
-_9ef.registerChild(this,args.dojoinsertionindex);
-}else{
-dojo.widget.manager.topWidgets[this.widgetId]=this;
-}
-if(this.widgetsInTemplate){
-var _9f2=new dojo.xml.Parse();
-var _9f3;
-var _9f4=this.domNode.getElementsByTagName("*");
-for(var i=0;i<_9f4.length;i++){
-if(_9f4[i].getAttribute("dojoAttachPoint")=="subContainerWidget"){
-_9f3=_9f4[i];
-}
-if(_9f4[i].getAttribute("dojoType")){
-_9f4[i].setAttribute("_isSubWidget",true);
-}
-}
-if(this.isContainer&&!this.containerNode){
-if(_9f3){
-var src=this.getFragNodeRef(frag);
-if(src){
-dojo.dom.moveChildren(src,_9f3);
-frag["dojoDontFollow"]=true;
-}
-}else{
-dojo.debug("No subContainerWidget node can be found in template file for widget "+this);
-}
-}
-var _9f7=_9f2.parseElement(this.domNode,null,true);
-dojo.widget.getParser().createSubComponents(_9f7,this);
-var _9f8=[];
-var _9f9=[this];
-var w;
-while((w=_9f9.pop())){
-for(var i=0;i<w.children.length;i++){
-var _9fb=w.children[i];
-if(_9fb._processedSubWidgets||!_9fb.extraArgs["_issubwidget"]){
-continue;
-}
-_9f8.push(_9fb);
-if(_9fb.isContainer){
-_9f9.push(_9fb);
-}
-}
-}
-for(var i=0;i<_9f8.length;i++){
-var _9fc=_9f8[i];
-if(_9fc._processedSubWidgets){
-dojo.debug("This should not happen: widget._processedSubWidgets is already true!");
-return;
-}
-_9fc._processedSubWidgets=true;
-if(_9fc.extraArgs["dojoattachevent"]){
-var evts=_9fc.extraArgs["dojoattachevent"].split(";");
-for(var j=0;j<evts.length;j++){
-var _9ff=null;
-var tevt=dojo.string.trim(evts[j]);
-if(tevt.indexOf(":")>=0){
-var _a01=tevt.split(":");
-tevt=dojo.string.trim(_a01[0]);
-_9ff=dojo.string.trim(_a01[1]);
-}
-if(!_9ff){
-_9ff=tevt;
-}
-if(dojo.lang.isFunction(_9fc[tevt])){
-dojo.event.kwConnect({srcObj:_9fc,srcFunc:tevt,targetObj:this,targetFunc:_9ff});
-}else{
-alert(tevt+" is not a function in widget "+_9fc);
-}
-}
-}
-if(_9fc.extraArgs["dojoattachpoint"]){
-this[_9fc.extraArgs["dojoattachpoint"]]=_9fc;
-}
-}
-}
-if(this.isContainer&&!frag["dojoDontFollow"]){
-dojo.widget.getParser().createSubComponents(frag,this);
-}
-},buildRendering:function(args,frag){
-var ts=dojo.widget._templateCache[this.widgetType];
-if(args["templatecsspath"]){
-args["templateCssPath"]=args["templatecsspath"];
-}
-var _a05=args["templateCssPath"]||this.templateCssPath;
-if(_a05&&!dojo.widget._cssFiles[_a05.toString()]){
-if((!this.templateCssString)&&(_a05)){
-this.templateCssString=dojo.hostenv.getText(_a05);
-this.templateCssPath=null;
-}
-dojo.widget._cssFiles[_a05.toString()]=true;
-}
-if((this["templateCssString"])&&(!this.templateCssString["loaded"])){
-dojo.html.insertCssText(this.templateCssString,null,_a05);
-if(!this.templateCssString){
-this.templateCssString="";
-}
-this.templateCssString.loaded=true;
-}
-if((!this.preventClobber)&&((this.templatePath)||(this.templateNode)||((this["templateString"])&&(this.templateString.length))||((typeof ts!="undefined")&&((ts["string"])||(ts["node"]))))){
-this.buildFromTemplate(args,frag);
-}else{
-this.domNode=this.getFragNodeRef(frag);
-}
-this.fillInTemplate(args,frag);
-},buildFromTemplate:function(args,frag){
-var _a08=false;
-if(args["templatepath"]){
-_a08=true;
-args["templatePath"]=args["templatepath"];
-}
-dojo.widget.fillFromTemplateCache(this,args["templatePath"],null,_a08);
-var ts=dojo.widget._templateCache[this.widgetType];
-if((ts)&&(!_a08)){
-if(!this.templateString.length){
-this.templateString=ts["string"];
-}
-if(!this.templateNode){
-this.templateNode=ts["node"];
-}
-}
-var _a0a=false;
-var node=null;
-var tstr=this.templateString;
-if((!this.templateNode)&&(this.templateString)){
-_a0a=this.templateString.match(/\$\{([^\}]+)\}/g);
-if(_a0a){
-var hash=this.strings||{};
-for(var key in dojo.widget.defaultStrings){
-if(dojo.lang.isUndefined(hash[key])){
-hash[key]=dojo.widget.defaultStrings[key];
-}
-}
-for(var i=0;i<_a0a.length;i++){
-var key=_a0a[i];
-key=key.substring(2,key.length-1);
-var kval=(key.substring(0,5)=="this.")?dojo.lang.getObjPathValue(key.substring(5),this):hash[key];
-var _a11;
-if((kval)||(dojo.lang.isString(kval))){
-_a11=new String((dojo.lang.isFunction(kval))?kval.call(this,key,this.templateString):kval);
-while(_a11.indexOf("\"")>-1){
-_a11=_a11.replace("\"","&quot;");
-}
-tstr=tstr.replace(_a0a[i],_a11);
-}
-}
-}else{
-this.templateNode=this.createNodesFromText(this.templateString,true)[0];
-if(!_a08){
-ts.node=this.templateNode;
-}
-}
-}
-if((!this.templateNode)&&(!_a0a)){
-dojo.debug("DomWidget.buildFromTemplate: could not create template");
-return false;
-}else{
-if(!_a0a){
-node=this.templateNode.cloneNode(true);
-if(!node){
-return false;
-}
-}else{
-node=this.createNodesFromText(tstr,true)[0];
-}
-}
-this.domNode=node;
-this.attachTemplateNodes();
-if(this.isContainer&&this.containerNode){
-var src=this.getFragNodeRef(frag);
-if(src){
-dojo.dom.moveChildren(src,this.containerNode);
-}
-}
-},attachTemplateNodes:function(_a13,_a14){
-if(!_a13){
-_a13=this.domNode;
-}
-if(!_a14){
-_a14=this;
-}
-return dojo.widget.attachTemplateNodes(_a13,_a14,dojo.widget.getDojoEventsFromStr(this.templateString));
-},fillInTemplate:function(){
-},destroyRendering:function(){
-try{
-delete this.domNode;
-}
-catch(e){
-}
-},cleanUp:function(){
-},getContainerHeight:function(){
-dojo.unimplemented("dojo.widget.DomWidget.getContainerHeight");
-},getContainerWidth:function(){
-dojo.unimplemented("dojo.widget.DomWidget.getContainerWidth");
-},createNodesFromText:function(){
-dojo.unimplemented("dojo.widget.DomWidget.createNodesFromText");
-}});
-dojo.provide("dojo.lfx.toggle");
-dojo.lfx.toggle.plain={show:function(node,_a16,_a17,_a18){
-dojo.html.show(node);
-if(dojo.lang.isFunction(_a18)){
-_a18();
-}
-},hide:function(node,_a1a,_a1b,_a1c){
-dojo.html.hide(node);
-if(dojo.lang.isFunction(_a1c)){
-_a1c();
-}
-}};
-dojo.lfx.toggle.fade={show:function(node,_a1e,_a1f,_a20){
-dojo.lfx.fadeShow(node,_a1e,_a1f,_a20).play();
-},hide:function(node,_a22,_a23,_a24){
-dojo.lfx.fadeHide(node,_a22,_a23,_a24).play();
-}};
-dojo.lfx.toggle.wipe={show:function(node,_a26,_a27,_a28){
-dojo.lfx.wipeIn(node,_a26,_a27,_a28).play();
-},hide:function(node,_a2a,_a2b,_a2c){
-dojo.lfx.wipeOut(node,_a2a,_a2b,_a2c).play();
-}};
-dojo.lfx.toggle.explode={show:function(node,_a2e,_a2f,_a30,_a31){
-dojo.lfx.explode(_a31||{x:0,y:0,width:0,height:0},node,_a2e,_a2f,_a30).play();
-},hide:function(node,_a33,_a34,_a35,_a36){
-dojo.lfx.implode(node,_a36||{x:0,y:0,width:0,height:0},_a33,_a34,_a35).play();
-}};
-dojo.provide("dojo.widget.HtmlWidget");
-dojo.declare("dojo.widget.HtmlWidget",dojo.widget.DomWidget,{widgetType:"HtmlWidget",templateCssPath:null,templatePath:null,lang:"",toggle:"plain",toggleDuration:150,animationInProgress:false,initialize:function(args,frag){
-},postMixInProperties:function(args,frag){
-if(this.lang===""){
-this.lang=null;
-}
-this.toggleObj=dojo.lfx.toggle[this.toggle.toLowerCase()]||dojo.lfx.toggle.plain;
-},getContainerHeight:function(){
-dojo.unimplemented("dojo.widget.HtmlWidget.getContainerHeight");
-},getContainerWidth:function(){
-return this.parent.domNode.offsetWidth;
-},setNativeHeight:function(_a3b){
-var ch=this.getContainerHeight();
-},createNodesFromText:function(txt,wrap){
-return dojo.html.createNodesFromText(txt,wrap);
-},destroyRendering:function(_a3f){
-try{
-if(!_a3f&&this.domNode){
-dojo.event.browser.clean(this.domNode);
-}
-this.domNode.parentNode.removeChild(this.domNode);
-delete this.domNode;
-}
-catch(e){
-}
-},isShowing:function(){
-return dojo.html.isShowing(this.domNode);
-},toggleShowing:function(){
-if(this.isHidden){
-this.show();
-}else{
-this.hide();
-}
-},show:function(){
-this.animationInProgress=true;
-this.isHidden=false;
-this.toggleObj.show(this.domNode,this.toggleDuration,null,dojo.lang.hitch(this,this.onShow),this.explodeSrc);
-},onShow:function(){
-this.animationInProgress=false;
-this.checkSize();
-},hide:function(){
-this.animationInProgress=true;
-this.isHidden=true;
-this.toggleObj.hide(this.domNode,this.toggleDuration,null,dojo.lang.hitch(this,this.onHide),this.explodeSrc);
-},onHide:function(){
-this.animationInProgress=false;
-},_isResized:function(w,h){
-if(!this.isShowing()){
-return false;
-}
-var wh=dojo.html.getMarginBox(this.domNode);
-var _a43=w||wh.width;
-var _a44=h||wh.height;
-if(this.width==_a43&&this.height==_a44){
-return false;
-}
-this.width=_a43;
-this.height=_a44;
-return true;
-},checkSize:function(){
-if(!this._isResized()){
-return;
-}
-this.onResized();
-},resizeTo:function(w,h){
-dojo.html.setMarginBox(this.domNode,{width:w,height:h});
-if(this.isShowing()){
-this.onResized();
-}
-},resizeSoon:function(){
-if(this.isShowing()){
-dojo.lang.setTimeout(this,this.onResized,0);
-}
-},onResized:function(){
-dojo.lang.forEach(this.children,function(_a47){
-if(_a47.checkSize){
-_a47.checkSize();
-}
-});
-}});
-dojo.provide("dojo.widget.*");
-dojo.provide("dojo.math");
-dojo.math.degToRad=function(x){
-return (x*Math.PI)/180;
-};
-dojo.math.radToDeg=function(x){
-return (x*180)/Math.PI;
-};
-dojo.math.factorial=function(n){
-if(n<1){
-return 0;
-}
-var _a4b=1;
-for(var i=1;i<=n;i++){
-_a4b*=i;
-}
-return _a4b;
-};
-dojo.math.permutations=function(n,k){
-if(n==0||k==0){
-return 1;
-}
-return (dojo.math.factorial(n)/dojo.math.factorial(n-k));
-};
-dojo.math.combinations=function(n,r){
-if(n==0||r==0){
-return 1;
-}
-return (dojo.math.factorial(n)/(dojo.math.factorial(n-r)*dojo.math.factorial(r)));
-};
-dojo.math.bernstein=function(t,n,i){
-return (dojo.math.combinations(n,i)*Math.pow(t,i)*Math.pow(1-t,n-i));
-};
-dojo.math.gaussianRandom=function(){
-var k=2;
-do{
-var i=2*Math.random()-1;
-var j=2*Math.random()-1;
-k=i*i+j*j;
-}while(k>=1);
-k=Math.sqrt((-2*Math.log(k))/k);
-return i*k;
-};
-dojo.math.mean=function(){
-var _a57=dojo.lang.isArray(arguments[0])?arguments[0]:arguments;
-var mean=0;
-for(var i=0;i<_a57.length;i++){
-mean+=_a57[i];
-}
-return mean/_a57.length;
-};
-dojo.math.round=function(_a5a,_a5b){
-if(!_a5b){
-var _a5c=1;
-}else{
-var _a5c=Math.pow(10,_a5b);
-}
-return Math.round(_a5a*_a5c)/_a5c;
-};
-dojo.math.sd=dojo.math.standardDeviation=function(){
-var _a5d=dojo.lang.isArray(arguments[0])?arguments[0]:arguments;
-return Math.sqrt(dojo.math.variance(_a5d));
-};
-dojo.math.variance=function(){
-var _a5e=dojo.lang.isArray(arguments[0])?arguments[0]:arguments;
-var mean=0,_a60=0;
-for(var i=0;i<_a5e.length;i++){
-mean+=_a5e[i];
-_a60+=Math.pow(_a5e[i],2);
-}
-return (_a60/_a5e.length)-Math.pow(mean/_a5e.length,2);
-};
-dojo.math.range=function(a,b,step){
-if(arguments.length<2){
-b=a;
-a=0;
-}
-if(arguments.length<3){
-step=1;
-}
-var _a65=[];
-if(step>0){
-for(var i=a;i<b;i+=step){
-_a65.push(i);
-}
-}else{
-if(step<0){
-for(var i=a;i>b;i+=step){
-_a65.push(i);
-}
-}else{
-throw new Error("dojo.math.range: step must be non-zero");
-}
-}
-return _a65;
-};
-dojo.provide("dojo.math.curves");
-dojo.math.curves={Line:function(_a67,end){
-this.start=_a67;
-this.end=end;
-this.dimensions=_a67.length;
-for(var i=0;i<_a67.length;i++){
-_a67[i]=Number(_a67[i]);
-}
-for(var i=0;i<end.length;i++){
-end[i]=Number(end[i]);
-}
-this.getValue=function(n){
-var _a6b=new Array(this.dimensions);
-for(var i=0;i<this.dimensions;i++){
-_a6b[i]=((this.end[i]-this.start[i])*n)+this.start[i];
-}
-return _a6b;
-};
-return this;
-},Bezier:function(pnts){
-this.getValue=function(step){
-if(step>=1){
-return this.p[this.p.length-1];
-}
-if(step<=0){
-return this.p[0];
-}
-var _a6f=new Array(this.p[0].length);
-for(var k=0;j<this.p[0].length;k++){
-_a6f[k]=0;
-}
-for(var j=0;j<this.p[0].length;j++){
-var C=0;
-var D=0;
-for(var i=0;i<this.p.length;i++){
-C+=this.p[i][j]*this.p[this.p.length-1][0]*dojo.math.bernstein(step,this.p.length,i);
-}
-for(var l=0;l<this.p.length;l++){
-D+=this.p[this.p.length-1][0]*dojo.math.bernstein(step,this.p.length,l);
-}
-_a6f[j]=C/D;
-}
-return _a6f;
-};
-this.p=pnts;
-return this;
-},CatmullRom:function(pnts,c){
-this.getValue=function(step){
-var _a79=step*(this.p.length-1);
-var node=Math.floor(_a79);
-var _a7b=_a79-node;
-var i0=node-1;
-if(i0<0){
-i0=0;
-}
-var i=node;
-var i1=node+1;
-if(i1>=this.p.length){
-i1=this.p.length-1;
-}
-var i2=node+2;
-if(i2>=this.p.length){
-i2=this.p.length-1;
-}
-var u=_a7b;
-var u2=_a7b*_a7b;
-var u3=_a7b*_a7b*_a7b;
-var _a83=new Array(this.p[0].length);
-for(var k=0;k<this.p[0].length;k++){
-var x1=(-this.c*this.p[i0][k])+((2-this.c)*this.p[i][k])+((this.c-2)*this.p[i1][k])+(this.c*this.p[i2][k]);
-var x2=(2*this.c*this.p[i0][k])+((this.c-3)*this.p[i][k])+((3-2*this.c)*this.p[i1][k])+(-this.c*this.p[i2][k]);
-var x3=(-this.c*this.p[i0][k])+(this.c*this.p[i1][k]);
-var x4=this.p[i][k];
-_a83[k]=x1*u3+x2*u2+x3*u+x4;
-}
-return _a83;
-};
-if(!c){
-this.c=0.7;
-}else{
-this.c=c;
-}
-this.p=pnts;
-return this;
-},Arc:function(_a89,end,ccw){
-var _a8c=dojo.math.points.midpoint(_a89,end);
-var _a8d=dojo.math.points.translate(dojo.math.points.invert(_a8c),_a89);
-var rad=Math.sqrt(Math.pow(_a8d[0],2)+Math.pow(_a8d[1],2));
-var _a8f=dojo.math.radToDeg(Math.atan(_a8d[1]/_a8d[0]));
-if(_a8d[0]<0){
-_a8f-=90;
-}else{
-_a8f+=90;
-}
-dojo.math.curves.CenteredArc.call(this,_a8c,rad,_a8f,_a8f+(ccw?-180:180));
-},CenteredArc:function(_a90,_a91,_a92,end){
-this.center=_a90;
-this.radius=_a91;
-this.start=_a92||0;
-this.end=end;
-this.getValue=function(n){
-var _a95=new Array(2);
-var _a96=dojo.math.degToRad(this.start+((this.end-this.start)*n));
-_a95[0]=this.center[0]+this.radius*Math.sin(_a96);
-_a95[1]=this.center[1]-this.radius*Math.cos(_a96);
-return _a95;
-};
-return this;
-},Circle:function(_a97,_a98){
-dojo.math.curves.CenteredArc.call(this,_a97,_a98,0,360);
-return this;
-},Path:function(){
-var _a99=[];
-var _a9a=[];
-var _a9b=[];
-var _a9c=0;
-this.add=function(_a9d,_a9e){
-if(_a9e<0){
-dojo.raise("dojo.math.curves.Path.add: weight cannot be less than 0");
-}
-_a99.push(_a9d);
-_a9a.push(_a9e);
-_a9c+=_a9e;
-computeRanges();
-};
-this.remove=function(_a9f){
-for(var i=0;i<_a99.length;i++){
-if(_a99[i]==_a9f){
-_a99.splice(i,1);
-_a9c-=_a9a.splice(i,1)[0];
-break;
-}
-}
-computeRanges();
-};
-this.removeAll=function(){
-_a99=[];
-_a9a=[];
-_a9c=0;
-};
-this.getValue=function(n){
-var _aa2=false,_aa3=0;
-for(var i=0;i<_a9b.length;i++){
-var r=_a9b[i];
-if(n>=r[0]&&n<r[1]){
-var subN=(n-r[0])/r[2];
-_aa3=_a99[i].getValue(subN);
-_aa2=true;
-break;
-}
-}
-if(!_aa2){
-_aa3=_a99[_a99.length-1].getValue(1);
-}
-for(var j=0;j<i;j++){
-_aa3=dojo.math.points.translate(_aa3,_a99[j].getValue(1));
-}
-return _aa3;
-};
-function computeRanges(){
-var _aa8=0;
-for(var i=0;i<_a9a.length;i++){
-var end=_aa8+_a9a[i]/_a9c;
-var len=end-_aa8;
-_a9b[i]=[_aa8,end,len];
-_aa8=end;
-}
-}
-return this;
-}};
-dojo.provide("dojo.math.points");
-dojo.math.points={translate:function(a,b){
-if(a.length!=b.length){
-dojo.raise("dojo.math.translate: points not same size (a:["+a+"], b:["+b+"])");
-}
-var c=new Array(a.length);
-for(var i=0;i<a.length;i++){
-c[i]=a[i]+b[i];
-}
-return c;
-},midpoint:function(a,b){
-if(a.length!=b.length){
-dojo.raise("dojo.math.midpoint: points not same size (a:["+a+"], b:["+b+"])");
-}
-var c=new Array(a.length);
-for(var i=0;i<a.length;i++){
-c[i]=(a[i]+b[i])/2;
-}
-return c;
-},invert:function(a){
-var b=new Array(a.length);
-for(var i=0;i<a.length;i++){
-b[i]=-a[i];
-}
-return b;
-},distance:function(a,b){
-return Math.sqrt(Math.pow(b[0]-a[0],2)+Math.pow(b[1]-a[1],2));
-}};
-dojo.provide("dojo.math.*");
-
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/dom.js b/continuum-webapp/src/main/webapp/struts/dojo/dom.js
deleted file mode 100644
index 7e3230e..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/dom.js
+++ /dev/null
@@ -1,522 +0,0 @@
-/*
-	Copyright (c) 2004-2006, The Dojo Foundation
-	All Rights Reserved.
-
-	Licensed under the Academic Free License version 2.1 or above OR the
-	modified BSD license. For more information on Dojo licensing, see:
-
-		http://dojotoolkit.org/community/licensing.shtml
-*/
-
-dojo.provide("dojo.dom");
-
-dojo.dom.ELEMENT_NODE                  = 1;
-dojo.dom.ATTRIBUTE_NODE                = 2;
-dojo.dom.TEXT_NODE                     = 3;
-dojo.dom.CDATA_SECTION_NODE            = 4;
-dojo.dom.ENTITY_REFERENCE_NODE         = 5;
-dojo.dom.ENTITY_NODE                   = 6;
-dojo.dom.PROCESSING_INSTRUCTION_NODE   = 7;
-dojo.dom.COMMENT_NODE                  = 8;
-dojo.dom.DOCUMENT_NODE                 = 9;
-dojo.dom.DOCUMENT_TYPE_NODE            = 10;
-dojo.dom.DOCUMENT_FRAGMENT_NODE        = 11;
-dojo.dom.NOTATION_NODE                 = 12;
-	
-dojo.dom.dojoml = "http://www.dojotoolkit.org/2004/dojoml";
-
-/**
- *	comprehensive list of XML namespaces
-**/
-dojo.dom.xmlns = {
-	//	summary
-	//	aliases for various common XML namespaces
-	svg : "http://www.w3.org/2000/svg",
-	smil : "http://www.w3.org/2001/SMIL20/",
-	mml : "http://www.w3.org/1998/Math/MathML",
-	cml : "http://www.xml-cml.org",
-	xlink : "http://www.w3.org/1999/xlink",
-	xhtml : "http://www.w3.org/1999/xhtml",
-	xul : "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
-	xbl : "http://www.mozilla.org/xbl",
-	fo : "http://www.w3.org/1999/XSL/Format",
-	xsl : "http://www.w3.org/1999/XSL/Transform",
-	xslt : "http://www.w3.org/1999/XSL/Transform",
-	xi : "http://www.w3.org/2001/XInclude",
-	xforms : "http://www.w3.org/2002/01/xforms",
-	saxon : "http://icl.com/saxon",
-	xalan : "http://xml.apache.org/xslt",
-	xsd : "http://www.w3.org/2001/XMLSchema",
-	dt: "http://www.w3.org/2001/XMLSchema-datatypes",
-	xsi : "http://www.w3.org/2001/XMLSchema-instance",
-	rdf : "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
-	rdfs : "http://www.w3.org/2000/01/rdf-schema#",
-	dc : "http://purl.org/dc/elements/1.1/",
-	dcq: "http://purl.org/dc/qualifiers/1.0",
-	"soap-env" : "http://schemas.xmlsoap.org/soap/envelope/",
-	wsdl : "http://schemas.xmlsoap.org/wsdl/",
-	AdobeExtensions : "http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
-};
-
-dojo.dom.isNode = function(/* object */wh){
-	//	summary
-	//	checks to see if wh is actually a node.
-	if(typeof Element == "function") {
-		try {
-			return wh instanceof Element;	//	boolean
-		} catch(E) {}
-	} else {
-		// best-guess
-		return wh && !isNaN(wh.nodeType);	//	boolean
-	}
-}
-
-dojo.dom.getUniqueId = function(){
-	//	summary
-	//	returns a unique string for use with any DOM element
-	var _document = dojo.doc();
-	do {
-		var id = "dj_unique_" + (++arguments.callee._idIncrement);
-	}while(_document.getElementById(id));
-	return id;	//	string
-}
-dojo.dom.getUniqueId._idIncrement = 0;
-
-dojo.dom.firstElement = dojo.dom.getFirstChildElement = function(/* Element */parentNode, /* string? */tagName){
-	//	summary
-	//	returns the first child element matching tagName
-	var node = parentNode.firstChild;
-	while(node && node.nodeType != dojo.dom.ELEMENT_NODE){
-		node = node.nextSibling;
-	}
-	if(tagName && node && node.tagName && node.tagName.toLowerCase() != tagName.toLowerCase()) {
-		node = dojo.dom.nextElement(node, tagName);
-	}
-	return node;	//	Element
-}
-
-dojo.dom.lastElement = dojo.dom.getLastChildElement = function(/* Element */parentNode, /* string? */tagName){
-	//	summary
-	//	returns the last child element matching tagName
-	var node = parentNode.lastChild;
-	while(node && node.nodeType != dojo.dom.ELEMENT_NODE) {
-		node = node.previousSibling;
-	}
-	if(tagName && node && node.tagName && node.tagName.toLowerCase() != tagName.toLowerCase()) {
-		node = dojo.dom.prevElement(node, tagName);
-	}
-	return node;	//	Element
-}
-
-dojo.dom.nextElement = dojo.dom.getNextSiblingElement = function(/* Node */node, /* string? */tagName){
-	//	summary
-	//	returns the next sibling element matching tagName
-	if(!node) { return null; }
-	do {
-		node = node.nextSibling;
-	} while(node && node.nodeType != dojo.dom.ELEMENT_NODE);
-
-	if(node && tagName && tagName.toLowerCase() != node.tagName.toLowerCase()) {
-		return dojo.dom.nextElement(node, tagName);
-	}
-	return node;	//	Element
-}
-
-dojo.dom.prevElement = dojo.dom.getPreviousSiblingElement = function(/* Node */node, /* string? */tagName){
-	//	summary
-	//	returns the previous sibling element matching tagName
-	if(!node) { return null; }
-	if(tagName) { tagName = tagName.toLowerCase(); }
-	do {
-		node = node.previousSibling;
-	} while(node && node.nodeType != dojo.dom.ELEMENT_NODE);
-
-	if(node && tagName && tagName.toLowerCase() != node.tagName.toLowerCase()) {
-		return dojo.dom.prevElement(node, tagName);
-	}
-	return node;	//	Element
-}
-
-// TODO: hmph
-/*this.forEachChildTag = function(node, unaryFunc) {
-	var child = this.getFirstChildTag(node);
-	while(child) {
-		if(unaryFunc(child) == "break") { break; }
-		child = this.getNextSiblingTag(child);
-	}
-}*/
-
-dojo.dom.moveChildren = function(/* Element */srcNode, /* Element */destNode, /* boolean? */trim){
-	//	summary
-	//	Moves children from srcNode to destNode and returns the count of children moved; 
-	//		will trim off text nodes if trim == true
-	var count = 0;
-	if(trim) {
-		while(srcNode.hasChildNodes() &&
-			srcNode.firstChild.nodeType == dojo.dom.TEXT_NODE) {
-			srcNode.removeChild(srcNode.firstChild);
-		}
-		while(srcNode.hasChildNodes() &&
-			srcNode.lastChild.nodeType == dojo.dom.TEXT_NODE) {
-			srcNode.removeChild(srcNode.lastChild);
-		}
-	}
-	while(srcNode.hasChildNodes()){
-		destNode.appendChild(srcNode.firstChild);
-		count++;
-	}
-	return count;	//	number
-}
-
-dojo.dom.copyChildren = function(/* Element */srcNode, /* Element */destNode, /* boolean? */trim){
-	//	summary
-	//	Copies children from srcNde to destNode and returns the count of children copied;
-	//		will trim off text nodes if trim == true
-	var clonedNode = srcNode.cloneNode(true);
-	return this.moveChildren(clonedNode, destNode, trim);	//	number
-}
-
-dojo.dom.removeChildren = function(/* Element */node){
-	//	summary
-	//	removes all children from node and returns the count of children removed.
-	var count = node.childNodes.length;
-	while(node.hasChildNodes()){ node.removeChild(node.firstChild); }
-	return count;	//	number
-}
-
-dojo.dom.replaceChildren = function(/* Element */node, /* Node */newChild){
-	//	summary
-	//	Removes all children of node and appends newChild
-	// FIXME: what if newChild is an array-like object?
-	dojo.dom.removeChildren(node);
-	node.appendChild(newChild);
-}
-
-dojo.dom.removeNode = function(/* Node */node){
-	//	summary
-	//	if node has a parent, removes node from parent and returns a reference to the removed child.
-	if(node && node.parentNode){
-		// return a ref to the removed child
-		return node.parentNode.removeChild(node);	//	Node
-	}
-}
-
-dojo.dom.getAncestors = function(/* Node */node, /* function? */filterFunction, /* boolean? */returnFirstHit) {
-	//	summary
-	//	returns all ancestors matching optional filterFunction; will return only the first if returnFirstHit
-	var ancestors = [];
-	var isFunction = (filterFunction && (filterFunction instanceof Function || typeof filterFunction == "function"));
-	while(node) {
-		if (!isFunction || filterFunction(node)) {
-			ancestors.push(node);
-		}
-		if (returnFirstHit && ancestors.length > 0) { 
-			return ancestors[0]; 	//	Node
-		}
-		
-		node = node.parentNode;
-	}
-	if (returnFirstHit) { return null; }
-	return ancestors;	//	array
-}
-
-dojo.dom.getAncestorsByTag = function(/* Node */node, /* string */tag, /* boolean? */returnFirstHit) {
-	//	summary
-	//	returns all ancestors matching tag (as tagName), will only return first one if returnFirstHit
-	tag = tag.toLowerCase();
-	return dojo.dom.getAncestors(node, function(el){
-		return ((el.tagName)&&(el.tagName.toLowerCase() == tag));
-	}, returnFirstHit);	//	Node || array
-}
-
-dojo.dom.getFirstAncestorByTag = function(/* Node */node, /* string */tag) {
-	//	summary
-	//	Returns first ancestor of node with tag tagName
-	return dojo.dom.getAncestorsByTag(node, tag, true);	//	Node
-}
-
-dojo.dom.isDescendantOf = function(/* Node */node, /* Node */ancestor, /* boolean? */guaranteeDescendant){
-	//	summary
-	//	Returns boolean if node is a descendant of ancestor
-	// guaranteeDescendant allows us to be a "true" isDescendantOf function
-	if(guaranteeDescendant && node) { node = node.parentNode; }
-	while(node) {
-		if(node == ancestor){ 
-			return true; 	//	boolean
-		}
-		node = node.parentNode;
-	}
-	return false;	//	boolean
-}
-
-dojo.dom.innerXML = function(/* Node */node){
-	//	summary
-	//	Implementation of MS's innerXML function.
-	if(node.innerXML){
-		return node.innerXML;	//	string
-	}else if (node.xml){
-		return node.xml;		//	string
-	}else if(typeof XMLSerializer != "undefined"){
-		return (new XMLSerializer()).serializeToString(node);	//	string
-	}
-}
-
-dojo.dom.createDocument = function(){
-	//	summary
-	//	cross-browser implementation of creating an XML document object.
-	var doc = null;
-	var _document = dojo.doc();
-
-	if(!dj_undef("ActiveXObject")){
-		var prefixes = [ "MSXML2", "Microsoft", "MSXML", "MSXML3" ];
-		for(var i = 0; i<prefixes.length; i++){
-			try{
-				doc = new ActiveXObject(prefixes[i]+".XMLDOM");
-			}catch(e){ /* squelch */ };
-
-			if(doc){ break; }
-		}
-	}else if((_document.implementation)&&
-		(_document.implementation.createDocument)){
-		doc = _document.implementation.createDocument("", "", null);
-	}
-	
-	return doc;	//	DOMDocument
-}
-
-dojo.dom.createDocumentFromText = function(/* string */str, /* string? */mimetype){
-	//	summary
-	//	attempts to create a Document object based on optional mime-type, using str as the contents of the document
-	if(!mimetype){ mimetype = "text/xml"; }
-	if(!dj_undef("DOMParser")){
-		var parser = new DOMParser();
-		return parser.parseFromString(str, mimetype);	//	DOMDocument
-	}else if(!dj_undef("ActiveXObject")){
-		var domDoc = dojo.dom.createDocument();
-		if(domDoc){
-			domDoc.async = false;
-			domDoc.loadXML(str);
-			return domDoc;	//	DOMDocument
-		}else{
-			dojo.debug("toXml didn't work?");
-		}
-	/*
-	}else if((dojo.render.html.capable)&&(dojo.render.html.safari)){
-		// FIXME: this doesn't appear to work!
-		// from: http://web-graphics.com/mtarchive/001606.php
-		// var xml = '<?xml version="1.0"?>'+str;
-		var mtype = "text/xml";
-		var xml = '<?xml version="1.0"?>'+str;
-		var url = "data:"+mtype+";charset=utf-8,"+encodeURIComponent(xml);
-		var req = new XMLHttpRequest();
-		req.open("GET", url, false);
-		req.overrideMimeType(mtype);
-		req.send(null);
-		return req.responseXML;
-	*/
-	}else{
-		var _document = dojo.doc();
-		if(_document.createElement){
-			// FIXME: this may change all tags to uppercase!
-			var tmp = _document.createElement("xml");
-			tmp.innerHTML = str;
-			if(_document.implementation && _document.implementation.createDocument) {
-				var xmlDoc = _document.implementation.createDocument("foo", "", null);
-				for(var i = 0; i < tmp.childNodes.length; i++) {
-					xmlDoc.importNode(tmp.childNodes.item(i), true);
-				}
-				return xmlDoc;	//	DOMDocument
-			}
-			// FIXME: probably not a good idea to have to return an HTML fragment
-			// FIXME: the tmp.doc.firstChild is as tested from IE, so it may not
-			// work that way across the board
-			return ((tmp.document)&&
-				(tmp.document.firstChild ?  tmp.document.firstChild : tmp));	//	DOMDocument
-		}
-	}
-	return null;
-}
-
-dojo.dom.prependChild = function(/* Element */node, /* Element */parent) {
-	// summary
-	//	prepends node to parent's children nodes
-	if(parent.firstChild) {
-		parent.insertBefore(node, parent.firstChild);
-	} else {
-		parent.appendChild(node);
-	}
-	return true;	//	boolean
-}
-
-dojo.dom.insertBefore = function(/* Node */node, /* Node */ref, /* boolean? */force){
-	//	summary
-	//	Try to insert node before ref
-	if (force != true &&
-		(node === ref || node.nextSibling === ref)){ return false; }
-	var parent = ref.parentNode;
-	parent.insertBefore(node, ref);
-	return true;	//	boolean
-}
-
-dojo.dom.insertAfter = function(/* Node */node, /* Node */ref, /* boolean? */force){
-	//	summary
-	//	Try to insert node after ref
-	var pn = ref.parentNode;
-	if(ref == pn.lastChild){
-		if((force != true)&&(node === ref)){
-			return false;	//	boolean
-		}
-		pn.appendChild(node);
-	}else{
-		return this.insertBefore(node, ref.nextSibling, force);	//	boolean
-	}
-	return true;	//	boolean
-}
-
-dojo.dom.insertAtPosition = function(/* Node */node, /* Node */ref, /* string */position){
-	//	summary
-	//	attempt to insert node in relation to ref based on position
-	if((!node)||(!ref)||(!position)){ 
-		return false;	//	boolean 
-	}
-	switch(position.toLowerCase()){
-		case "before":
-			return dojo.dom.insertBefore(node, ref);	//	boolean
-		case "after":
-			return dojo.dom.insertAfter(node, ref);		//	boolean
-		case "first":
-			if(ref.firstChild){
-				return dojo.dom.insertBefore(node, ref.firstChild);	//	boolean
-			}else{
-				ref.appendChild(node);
-				return true;	//	boolean
-			}
-			break;
-		default: // aka: last
-			ref.appendChild(node);
-			return true;	//	boolean
-	}
-}
-
-dojo.dom.insertAtIndex = function(/* Node */node, /* Element */containingNode, /* number */insertionIndex){
-	//	summary
-	//	insert node into child nodes nodelist of containingNode at insertionIndex.
-	var siblingNodes = containingNode.childNodes;
-
-	// if there aren't any kids yet, just add it to the beginning
-
-	if (!siblingNodes.length){
-		containingNode.appendChild(node);
-		return true;	//	boolean
-	}
-
-	// otherwise we need to walk the childNodes
-	// and find our spot
-
-	var after = null;
-
-	for(var i=0; i<siblingNodes.length; i++){
-
-		var sibling_index = siblingNodes.item(i)["getAttribute"] ? parseInt(siblingNodes.item(i).getAttribute("dojoinsertionindex")) : -1;
-
-		if (sibling_index < insertionIndex){
-			after = siblingNodes.item(i);
-		}
-	}
-
-	if (after){
-		// add it after the node in {after}
-
-		return dojo.dom.insertAfter(node, after);	//	boolean
-	}else{
-		// add it to the start
-
-		return dojo.dom.insertBefore(node, siblingNodes.item(0));	//	boolean
-	}
-}
-	
-dojo.dom.textContent = function(/* Node */node, /* string */text){
-	//	summary
-	//	implementation of the DOM Level 3 attribute; scan node for text
-	if (arguments.length>1) {
-		var _document = dojo.doc();
-		dojo.dom.replaceChildren(node, _document.createTextNode(text));
-		return text;	//	string
-	} else {
-		if(node.textContent != undefined){ //FF 1.5
-			return node.textContent;	//	string
-		}
-		var _result = "";
-		if (node == null) { return _result; }
-		for (var i = 0; i < node.childNodes.length; i++) {
-			switch (node.childNodes[i].nodeType) {
-				case 1: // ELEMENT_NODE
-				case 5: // ENTITY_REFERENCE_NODE
-					_result += dojo.dom.textContent(node.childNodes[i]);
-					break;
-				case 3: // TEXT_NODE
-				case 2: // ATTRIBUTE_NODE
-				case 4: // CDATA_SECTION_NODE
-					_result += node.childNodes[i].nodeValue;
-					break;
-				default:
-					break;
-			}
-		}
-		return _result;	//	string
-	}
-}
-
-dojo.dom.hasParent = function (/* Node */node) {
-	//	summary
-	//	returns whether or not node is a child of another node.
-	return node && node.parentNode && dojo.dom.isNode(node.parentNode);	//	boolean
-}
-
-/**
- * Examples:
- *
- * myFooNode = <foo />
- * isTag(myFooNode, "foo"); // returns "foo"
- * isTag(myFooNode, "bar"); // returns ""
- * isTag(myFooNode, "FOO"); // returns ""
- * isTag(myFooNode, "hey", "foo", "bar"); // returns "foo"
-**/
-dojo.dom.isTag = function(/* Node */node /* ... */) {
-	//	summary
-	//	determines if node has any of the provided tag names and returns the tag name that matches, empty string otherwise.
-	if(node && node.tagName) {
-		for(var i=1; i<arguments.length; i++){
-			if(node.tagName==String(arguments[i])){
-				return String(arguments[i]);	//	string
-			}
-		}
-	}
-	return "";	//	string
-}
-
-dojo.dom.setAttributeNS = function(/* Element */elem, /* string */namespaceURI, /* string */attrName, /* string */attrValue){
-	//	summary
-	//	implementation of DOM2 setAttributeNS that works cross browser.
-	if(elem == null || ((elem == undefined)&&(typeof elem == "undefined"))){
-		dojo.raise("No element given to dojo.dom.setAttributeNS");
-	}
-	
-	if(!((elem.setAttributeNS == undefined)&&(typeof elem.setAttributeNS == "undefined"))){ // w3c
-		elem.setAttributeNS(namespaceURI, attrName, attrValue);
-	}else{ // IE
-		// get a root XML document
-		var ownerDoc = elem.ownerDocument;
-		var attribute = ownerDoc.createNode(
-			2, // node type
-			attrName,
-			namespaceURI
-		);
-		
-		// set value
-		attribute.nodeValue = attrValue;
-		
-		// attach to element
-		elem.setAttributeNode(attribute);
-	}
-}
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/event/__package__.js b/continuum-webapp/src/main/webapp/struts/dojo/event/__package__.js
deleted file mode 100644
index 8d470ef..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/event/__package__.js
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
-	Copyright (c) 2004-2006, The Dojo Foundation
-	All Rights Reserved.
-
-	Licensed under the Academic Free License version 2.1 or above OR the
-	modified BSD license. For more information on Dojo licensing, see:
-
-		http://dojotoolkit.org/community/licensing.shtml
-*/
-
-dojo.kwCompoundRequire({
-	common: ["dojo.event.common", "dojo.event.topic"],
-	browser: ["dojo.event.browser"],
-	dashboard: ["dojo.event.browser"]
-});
-dojo.provide("dojo.event.*");
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/event/browser.js b/continuum-webapp/src/main/webapp/struts/dojo/event/browser.js
deleted file mode 100644
index d11753f..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/event/browser.js
+++ /dev/null
@@ -1,514 +0,0 @@
-/*
-	Copyright (c) 2004-2006, The Dojo Foundation
-	All Rights Reserved.
-
-	Licensed under the Academic Free License version 2.1 or above OR the
-	modified BSD license. For more information on Dojo licensing, see:
-
-		http://dojotoolkit.org/community/licensing.shtml
-*/
-
-dojo.provide("dojo.event.browser");
-dojo.require("dojo.event.common");
-
-// FIXME: any particular reason this is in the global scope?
-dojo._ie_clobber = new function(){
-	this.clobberNodes = [];
-
-	function nukeProp(node, prop){
-		// try{ node.removeAttribute(prop); 	}catch(e){ /* squelch */ }
-		try{ node[prop] = null; 			}catch(e){ /* squelch */ }
-		try{ delete node[prop]; 			}catch(e){ /* squelch */ }
-		// FIXME: JotLive needs this, but I'm not sure if it's too slow or not
-		try{ node.removeAttribute(prop);	}catch(e){ /* squelch */ }
-	}
-
-	this.clobber = function(nodeRef){
-		var na;
-		var tna;
-		if(nodeRef){
-			tna = nodeRef.all || nodeRef.getElementsByTagName("*");
-			na = [nodeRef];
-			for(var x=0; x<tna.length; x++){
-				// if we're gonna be clobbering the thing, at least make sure
-				// we aren't trying to do it twice
-				if(tna[x]["__doClobber__"]){
-					na.push(tna[x]);
-				}
-			}
-		}else{
-			try{ window.onload = null; }catch(e){}
-			na = (this.clobberNodes.length) ? this.clobberNodes : document.all;
-		}
-		tna = null;
-		var basis = {};
-		for(var i = na.length-1; i>=0; i=i-1){
-			var el = na[i];
-			try{
-				if(el && el["__clobberAttrs__"]){
-					for(var j=0; j<el.__clobberAttrs__.length; j++){
-						nukeProp(el, el.__clobberAttrs__[j]);
-					}
-					nukeProp(el, "__clobberAttrs__");
-					nukeProp(el, "__doClobber__");
-				}
-			}catch(e){ /* squelch! */};
-		}
-		na = null;
-	}
-}
-
-if(dojo.render.html.ie){
-	dojo.addOnUnload(function(){
-		dojo._ie_clobber.clobber();
-		try{
-			if((dojo["widget"])&&(dojo.widget["manager"])){
-				dojo.widget.manager.destroyAll();
-			}
-		}catch(e){}
-		try{ window.onload = null; }catch(e){}
-		try{ window.onunload = null; }catch(e){}
-		dojo._ie_clobber.clobberNodes = [];
-		// CollectGarbage();
-	});
-}
-
-dojo.event.browser = new function(){
-
-	var clobberIdx = 0;
-
-	this.normalizedEventName = function(/*String*/eventName){
-		switch(eventName){
-			case "CheckboxStateChange":
-			case "DOMAttrModified":
-			case "DOMMenuItemActive":
-			case "DOMMenuItemInactive":
-			case "DOMMouseScroll":
-			case "DOMNodeInserted":
-			case "DOMNodeRemoved":
-			case "RadioStateChange":
-				return eventName;
-				break;
-			default:
-				return eventName.toLowerCase();
-				break;
-		}
-	}
-	
-	this.clean = function(/*DOMNode*/node){
-		// summary:
-		//		removes native event handlers so that destruction of the node
-		//		will not leak memory. On most browsers this is a no-op, but
-		//		it's critical for manual node removal on IE.
-		// node:
-		//		A DOM node. All of it's children will also be cleaned.
-		if(dojo.render.html.ie){ 
-			dojo._ie_clobber.clobber(node);
-		}
-	}
-
-	this.addClobberNode = function(/*DOMNode*/node){
-		// summary:
-		//		register the passed node to support event stripping
-		// node:
-		//		A DOM node
-		if(!dojo.render.html.ie){ return; }
-		if(!node["__doClobber__"]){
-			node.__doClobber__ = true;
-			dojo._ie_clobber.clobberNodes.push(node);
-			// this might not be the most efficient thing to do, but it's
-			// much less error prone than other approaches which were
-			// previously tried and failed
-			node.__clobberAttrs__ = [];
-		}
-	}
-
-	this.addClobberNodeAttrs = function(/*DOMNode*/node, /*Array*/props){
-		// summary:
-		//		register the passed node to support event stripping
-		// node:
-		//		A DOM node to stip properties from later
-		// props:
-		//		A list of propeties to strip from the node
-		if(!dojo.render.html.ie){ return; }
-		this.addClobberNode(node);
-		for(var x=0; x<props.length; x++){
-			node.__clobberAttrs__.push(props[x]);
-		}
-	}
-
-	this.removeListener = function(	/*DOMNode*/ node, 
-									/*String*/	evtName, 
-									/*Function*/fp, 
-									/*Boolean*/	capture){
-		// summary:
-		//		clobbers the listener from the node
-		// evtName:
-		//		the name of the handler to remove the function from
-		// node:
-		//		DOM node to attach the event to
-		// fp:
-		//		the function to register
-		// capture:
-		//		Optional. should this listener prevent propigation?
-		if(!capture){ var capture = false; }
-		evtName = dojo.event.browser.normalizedEventName(evtName);
-		if( (evtName == "onkey") || (evtName == "key") ){
-			if(dojo.render.html.ie){
-				this.removeListener(node, "onkeydown", fp, capture);
-			}
-			evtName = "onkeypress";
-		}
-		if(evtName.substr(0,2)=="on"){ evtName = evtName.substr(2); }
-		// FIXME: this is mostly a punt, we aren't actually doing anything on IE
-		if(node.removeEventListener){
-			node.removeEventListener(evtName, fp, capture);
-		}
-	}
-
-	this.addListener = function(/*DOMNode*/node, /*String*/evtName, /*Function*/fp, /*Boolean*/capture, /*Boolean*/dontFix){
-		// summary:
-		//		adds a listener to the node
-		// evtName:
-		//		the name of the handler to add the listener to can be either of
-		//		the form "onclick" or "click"
-		// node:
-		//		DOM node to attach the event to
-		// fp:
-		//		the function to register
-		// capture:
-		//		Optional. Should this listener prevent propigation?
-		// dontFix:
-		//		Optional. Should we avoid registering a new closure around the
-		//		listener to enable fixEvent for dispatch of the registered
-		//		function?
-		if(!node){ return; } // FIXME: log and/or bail?
-		if(!capture){ var capture = false; }
-		evtName = dojo.event.browser.normalizedEventName(evtName);
-		if( (evtName == "onkey") || (evtName == "key") ){
-			if(dojo.render.html.ie){
-				this.addListener(node, "onkeydown", fp, capture, dontFix);
-			}
-			evtName = "onkeypress";
-		}
-		if(evtName.substr(0,2)!="on"){ evtName = "on"+evtName; }
-
-		if(!dontFix){
-			// build yet another closure around fp in order to inject fixEvent
-			// around the resulting event
-			var newfp = function(evt){
-				if(!evt){ evt = window.event; }
-				var ret = fp(dojo.event.browser.fixEvent(evt, this));
-				if(capture){
-					dojo.event.browser.stopEvent(evt);
-				}
-				return ret;
-			}
-		}else{
-			newfp = fp;
-		}
-
-		if(node.addEventListener){ 
-			node.addEventListener(evtName.substr(2), newfp, capture);
-			return newfp;
-		}else{
-			if(typeof node[evtName] == "function" ){
-				var oldEvt = node[evtName];
-				node[evtName] = function(e){
-					oldEvt(e);
-					return newfp(e);
-				}
-			}else{
-				node[evtName]=newfp;
-			}
-			if(dojo.render.html.ie){
-				this.addClobberNodeAttrs(node, [evtName]);
-			}
-			return newfp;
-		}
-	}
-
-	this.isEvent = function(/*Object*/obj){
-		// summary: 
-		//		Tries to determine whether or not the object is a DOM event.
-
-		// FIXME: event detection hack ... could test for additional attributes
-		// if necessary
-		return (typeof obj != "undefined")&&(typeof Event != "undefined")&&(obj.eventPhase); // Boolean
-		// Event does not support instanceof in Opera, otherwise:
-		//return (typeof Event != "undefined")&&(obj instanceof Event);
-	}
-
-	this.currentEvent = null;
-	
-	this.callListener = function(/*Function*/listener, /*DOMNode*/curTarget){
-		// summary:
-		//		calls the specified listener in the context of the passed node
-		//		with the current DOM event object as the only parameter
-		// listener:
-		//		the function to call
-		// curTarget:
-		//		the Node to call the function in the scope of
-		if(typeof listener != 'function'){
-			dojo.raise("listener not a function: " + listener);
-		}
-		dojo.event.browser.currentEvent.currentTarget = curTarget;
-		return listener.call(curTarget, dojo.event.browser.currentEvent);
-	}
-
-	this._stopPropagation = function(){
-		dojo.event.browser.currentEvent.cancelBubble = true; 
-	}
-
-	this._preventDefault = function(){
-		dojo.event.browser.currentEvent.returnValue = false;
-	}
-
-	this.keys = {
-		KEY_BACKSPACE: 8,
-		KEY_TAB: 9,
-		KEY_CLEAR: 12,
-		KEY_ENTER: 13,
-		KEY_SHIFT: 16,
-		KEY_CTRL: 17,
-		KEY_ALT: 18,
-		KEY_PAUSE: 19,
-		KEY_CAPS_LOCK: 20,
-		KEY_ESCAPE: 27,
-		KEY_SPACE: 32,
-		KEY_PAGE_UP: 33,
-		KEY_PAGE_DOWN: 34,
-		KEY_END: 35,
-		KEY_HOME: 36,
-		KEY_LEFT_ARROW: 37,
-		KEY_UP_ARROW: 38,
-		KEY_RIGHT_ARROW: 39,
-		KEY_DOWN_ARROW: 40,
-		KEY_INSERT: 45,
-		KEY_DELETE: 46,
-		KEY_HELP: 47,
-		KEY_LEFT_WINDOW: 91,
-		KEY_RIGHT_WINDOW: 92,
-		KEY_SELECT: 93,
-		KEY_NUMPAD_0: 96,
-		KEY_NUMPAD_1: 97,
-		KEY_NUMPAD_2: 98,
-		KEY_NUMPAD_3: 99,
-		KEY_NUMPAD_4: 100,
-		KEY_NUMPAD_5: 101,
-		KEY_NUMPAD_6: 102,
-		KEY_NUMPAD_7: 103,
-		KEY_NUMPAD_8: 104,
-		KEY_NUMPAD_9: 105,
-		KEY_NUMPAD_MULTIPLY: 106,
-		KEY_NUMPAD_PLUS: 107,
-		KEY_NUMPAD_ENTER: 108,
-		KEY_NUMPAD_MINUS: 109,
-		KEY_NUMPAD_PERIOD: 110,
-		KEY_NUMPAD_DIVIDE: 111,
-		KEY_F1: 112,
-		KEY_F2: 113,
-		KEY_F3: 114,
-		KEY_F4: 115,
-		KEY_F5: 116,
-		KEY_F6: 117,
-		KEY_F7: 118,
-		KEY_F8: 119,
-		KEY_F9: 120,
-		KEY_F10: 121,
-		KEY_F11: 122,
-		KEY_F12: 123,
-		KEY_F13: 124,
-		KEY_F14: 125,
-		KEY_F15: 126,
-		KEY_NUM_LOCK: 144,
-		KEY_SCROLL_LOCK: 145
-	};
-
-	// reverse lookup
-	this.revKeys = [];
-	for(var key in this.keys){
-		this.revKeys[this.keys[key]] = key;
-	}
-
-	this.fixEvent = function(/*Event*/evt, /*DOMNode*/sender){
-		// summary:
-		//		normalizes properties on the event object including event
-		//		bubbling methods, keystroke normalization, and x/y positions
-		// evt: the native event object
-		// sender: the node to treat as "currentTarget"
-		if(!evt){
-			if(window["event"]){
-				evt = window.event;
-			}
-		}
-		
-		if((evt["type"])&&(evt["type"].indexOf("key") == 0)){ // key events
-			evt.keys = this.revKeys;
-			// FIXME: how can we eliminate this iteration?
-			for(var key in this.keys){
-				evt[key] = this.keys[key];
-			}
-			if(evt["type"] == "keydown" && dojo.render.html.ie){
-				switch(evt.keyCode){
-					case evt.KEY_SHIFT:
-					case evt.KEY_CTRL:
-					case evt.KEY_ALT:
-					case evt.KEY_CAPS_LOCK:
-					case evt.KEY_LEFT_WINDOW:
-					case evt.KEY_RIGHT_WINDOW:
-					case evt.KEY_SELECT:
-					case evt.KEY_NUM_LOCK:
-					case evt.KEY_SCROLL_LOCK:
-					// I'll get these in keypress after the OS munges them based on numlock
-					case evt.KEY_NUMPAD_0:
-					case evt.KEY_NUMPAD_1:
-					case evt.KEY_NUMPAD_2:
-					case evt.KEY_NUMPAD_3:
-					case evt.KEY_NUMPAD_4:
-					case evt.KEY_NUMPAD_5:
-					case evt.KEY_NUMPAD_6:
-					case evt.KEY_NUMPAD_7:
-					case evt.KEY_NUMPAD_8:
-					case evt.KEY_NUMPAD_9:
-					case evt.KEY_NUMPAD_PERIOD:
-						break; // just ignore the keys that can morph
-					case evt.KEY_NUMPAD_MULTIPLY:
-					case evt.KEY_NUMPAD_PLUS:
-					case evt.KEY_NUMPAD_ENTER:
-					case evt.KEY_NUMPAD_MINUS:
-					case evt.KEY_NUMPAD_DIVIDE:
-						break; // I could handle these but just pick them up in keypress
-					case evt.KEY_PAUSE:
-					case evt.KEY_TAB:
-					case evt.KEY_BACKSPACE:
-					case evt.KEY_ENTER:
-					case evt.KEY_ESCAPE:
-					case evt.KEY_PAGE_UP:
-					case evt.KEY_PAGE_DOWN:
-					case evt.KEY_END:
-					case evt.KEY_HOME:
-					case evt.KEY_LEFT_ARROW:
-					case evt.KEY_UP_ARROW:
-					case evt.KEY_RIGHT_ARROW:
-					case evt.KEY_DOWN_ARROW:
-					case evt.KEY_INSERT:
-					case evt.KEY_DELETE:
-					case evt.KEY_F1:
-					case evt.KEY_F2:
-					case evt.KEY_F3:
-					case evt.KEY_F4:
-					case evt.KEY_F5:
-					case evt.KEY_F6:
-					case evt.KEY_F7:
-					case evt.KEY_F8:
-					case evt.KEY_F9:
-					case evt.KEY_F10:
-					case evt.KEY_F11:
-					case evt.KEY_F12:
-					case evt.KEY_F12:
-					case evt.KEY_F13:
-					case evt.KEY_F14:
-					case evt.KEY_F15:
-					case evt.KEY_CLEAR:
-					case evt.KEY_HELP:
-						evt.key = evt.keyCode;
-						break;
-					default:
-						if(evt.ctrlKey || evt.altKey){
-							var unifiedCharCode = evt.keyCode;
-							// if lower case but keycode is uppercase, convert it
-							if(unifiedCharCode >= 65 && unifiedCharCode <= 90 && evt.shiftKey == false){
-								unifiedCharCode += 32;
-							}
-							if(unifiedCharCode >= 1 && unifiedCharCode <= 26 && evt.ctrlKey){
-								unifiedCharCode += 96; // 001-032 = ctrl+[a-z]
-							}
-							evt.key = String.fromCharCode(unifiedCharCode);
-						}
-				}
-			} else if(evt["type"] == "keypress"){
-				if(dojo.render.html.opera){
-					if(evt.which == 0){
-						evt.key = evt.keyCode;
-					}else if(evt.which > 0){
-						switch(evt.which){
-							case evt.KEY_SHIFT:
-							case evt.KEY_CTRL:
-							case evt.KEY_ALT:
-							case evt.KEY_CAPS_LOCK:
-							case evt.KEY_NUM_LOCK:
-							case evt.KEY_SCROLL_LOCK:
-								break;
-							case evt.KEY_PAUSE:
-							case evt.KEY_TAB:
-							case evt.KEY_BACKSPACE:
-							case evt.KEY_ENTER:
-							case evt.KEY_ESCAPE:
-								evt.key = evt.which;
-								break;
-							default:
-								var unifiedCharCode = evt.which;
-								if((evt.ctrlKey || evt.altKey || evt.metaKey) && (evt.which >= 65 && evt.which <= 90 && evt.shiftKey == false)){
-									unifiedCharCode += 32;
-								}
-								evt.key = String.fromCharCode(unifiedCharCode);
-						}
-					}
-				}else if(dojo.render.html.ie){ // catch some IE keys that are hard to get in keyDown
-					// key combinations were handled in onKeyDown
-					if(!evt.ctrlKey && !evt.altKey && evt.keyCode >= evt.KEY_SPACE){
-						evt.key = String.fromCharCode(evt.keyCode);
-					}
-				}else if(dojo.render.html.safari){
-					switch(evt.keyCode){
-						case 63232: evt.key = evt.KEY_UP_ARROW; break;
-						case 63233: evt.key = evt.KEY_DOWN_ARROW; break;
-						case 63234: evt.key = evt.KEY_LEFT_ARROW; break;
-						case 63235: evt.key = evt.KEY_RIGHT_ARROW; break;
-						default: 
-							evt.key = evt.charCode > 0 ? String.fromCharCode(evt.charCode) : evt.keyCode;
-					}
-				}else{
-					evt.key = evt.charCode > 0 ? String.fromCharCode(evt.charCode) : evt.keyCode;
-				}
-			}
-		}
-		if(dojo.render.html.ie){
-			if(!evt.target){ evt.target = evt.srcElement; }
-			if(!evt.currentTarget){ evt.currentTarget = (sender ? sender : evt.srcElement); }
-			if(!evt.layerX){ evt.layerX = evt.offsetX; }
-			if(!evt.layerY){ evt.layerY = evt.offsetY; }
-			// FIXME: scroll position query is duped from dojo.html to avoid dependency on that entire module
-			// DONOT replace the following to use dojo.body(), in IE, document.documentElement should be used
-			// here rather than document.body
-			var doc = (evt.srcElement && evt.srcElement.ownerDocument) ? evt.srcElement.ownerDocument : document;
-			var docBody = ((dojo.render.html.ie55)||(doc["compatMode"] == "BackCompat")) ? doc.body : doc.documentElement;
-			if(!evt.pageX){ evt.pageX = evt.clientX + (docBody.scrollLeft || 0) }
-			if(!evt.pageY){ evt.pageY = evt.clientY + (docBody.scrollTop || 0) }
-			// mouseover
-			if(evt.type == "mouseover"){ evt.relatedTarget = evt.fromElement; }
-			// mouseout
-			if(evt.type == "mouseout"){ evt.relatedTarget = evt.toElement; }
-			this.currentEvent = evt;
-			evt.callListener = this.callListener;
-			evt.stopPropagation = this._stopPropagation;
-			evt.preventDefault = this._preventDefault;
-		}
-		return evt; // Event
-	}
-
-	this.stopEvent = function(/*Event*/evt){
-		// summary:
-		//		prevents propigation and clobbers the default action of the
-		//		passed event
-		// evt: Optional for IE. The native event object.
-		if(window.event){
-			evt.returnValue = false;
-			evt.cancelBubble = true;
-		}else{
-			evt.preventDefault();
-			evt.stopPropagation();
-		}
-	}
-}
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/event/common.js b/continuum-webapp/src/main/webapp/struts/dojo/event/common.js
deleted file mode 100644
index 6a3a657..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/event/common.js
+++ /dev/null
@@ -1,878 +0,0 @@
-/*
-	Copyright (c) 2004-2006, The Dojo Foundation
-	All Rights Reserved.
-
-	Licensed under the Academic Free License version 2.1 or above OR the
-	modified BSD license. For more information on Dojo licensing, see:
-
-		http://dojotoolkit.org/community/licensing.shtml
-*/
-
-dojo.provide("dojo.event.common");
-
-dojo.require("dojo.lang.array");
-dojo.require("dojo.lang.extras");
-dojo.require("dojo.lang.func");
-
-// TODO: connection filter functions
-//			these are functions that accept a method invocation (like around
-//			advice) and return a boolean based on it. That value determines
-//			whether or not the connection proceeds. It could "feel" like around
-//			advice for those who know what it is (calling proceed() or not),
-//			but I think presenting it as a "filter" and/or calling it with the
-//			function args and not the MethodInvocation might make it more
-//			palletable to "normal" users than around-advice currently is
-// TODO: execution scope mangling
-//			YUI's event facility by default executes listeners in the context
-//			of the source object. This is very odd, but should probably be
-//			supported as an option (both for the source and for the dest). It
-//			can be thought of as a connection-specific hitch().
-// TODO: more resiliency for 4+ arguments to connect()
-
-dojo.event = new function(){
-	this._canTimeout = dojo.lang.isFunction(dj_global["setTimeout"])||dojo.lang.isAlien(dj_global["setTimeout"]);
-
-	// FIXME: where should we put this method (not here!)?
-	function interpolateArgs(args, searchForNames){
-		var dl = dojo.lang;
-		var ao = {
-			srcObj: dj_global,
-			srcFunc: null,
-			adviceObj: dj_global,
-			adviceFunc: null,
-			aroundObj: null,
-			aroundFunc: null,
-			adviceType: (args.length>2) ? args[0] : "after",
-			precedence: "last",
-			once: false,
-			delay: null,
-			rate: 0,
-			adviceMsg: false
-		};
-
-		switch(args.length){
-			case 0: return;
-			case 1: return;
-			case 2:
-				ao.srcFunc = args[0];
-				ao.adviceFunc = args[1];
-				break;
-			case 3:
-				if((dl.isObject(args[0]))&&(dl.isString(args[1]))&&(dl.isString(args[2]))){
-					ao.adviceType = "after";
-					ao.srcObj = args[0];
-					ao.srcFunc = args[1];
-					ao.adviceFunc = args[2];
-				}else if((dl.isString(args[1]))&&(dl.isString(args[2]))){
-					ao.srcFunc = args[1];
-					ao.adviceFunc = args[2];
-				}else if((dl.isObject(args[0]))&&(dl.isString(args[1]))&&(dl.isFunction(args[2]))){
-					ao.adviceType = "after";
-					ao.srcObj = args[0];
-					ao.srcFunc = args[1];
-					var tmpName  = dl.nameAnonFunc(args[2], ao.adviceObj, searchForNames);
-					ao.adviceFunc = tmpName;
-				}else if((dl.isFunction(args[0]))&&(dl.isObject(args[1]))&&(dl.isString(args[2]))){
-					ao.adviceType = "after";
-					ao.srcObj = dj_global;
-					var tmpName  = dl.nameAnonFunc(args[0], ao.srcObj, searchForNames);
-					ao.srcFunc = tmpName;
-					ao.adviceObj = args[1];
-					ao.adviceFunc = args[2];
-				}
-				break;
-			case 4:
-				if((dl.isObject(args[0]))&&(dl.isObject(args[2]))){
-					// we can assume that we've got an old-style "connect" from
-					// the sigslot school of event attachment. We therefore
-					// assume after-advice.
-					ao.adviceType = "after";
-					ao.srcObj = args[0];
-					ao.srcFunc = args[1];
-					ao.adviceObj = args[2];
-					ao.adviceFunc = args[3];
-				}else if((dl.isString(args[0]))&&(dl.isString(args[1]))&&(dl.isObject(args[2]))){
-					ao.adviceType = args[0];
-					ao.srcObj = dj_global;
-					ao.srcFunc = args[1];
-					ao.adviceObj = args[2];
-					ao.adviceFunc = args[3];
-				}else if((dl.isString(args[0]))&&(dl.isFunction(args[1]))&&(dl.isObject(args[2]))){
-					ao.adviceType = args[0];
-					ao.srcObj = dj_global;
-					var tmpName  = dl.nameAnonFunc(args[1], dj_global, searchForNames);
-					ao.srcFunc = tmpName;
-					ao.adviceObj = args[2];
-					ao.adviceFunc = args[3];
-				}else if((dl.isString(args[0]))&&(dl.isObject(args[1]))&&(dl.isString(args[2]))&&(dl.isFunction(args[3]))){
-					ao.srcObj = args[1];
-					ao.srcFunc = args[2];
-					var tmpName  = dl.nameAnonFunc(args[3], dj_global, searchForNames);
-					ao.adviceObj = dj_global;
-					ao.adviceFunc = tmpName;
-				}else if(dl.isObject(args[1])){
-					ao.srcObj = args[1];
-					ao.srcFunc = args[2];
-					ao.adviceObj = dj_global;
-					ao.adviceFunc = args[3];
-				}else if(dl.isObject(args[2])){
-					ao.srcObj = dj_global;
-					ao.srcFunc = args[1];
-					ao.adviceObj = args[2];
-					ao.adviceFunc = args[3];
-				}else{
-					ao.srcObj = ao.adviceObj = ao.aroundObj = dj_global;
-					ao.srcFunc = args[1];
-					ao.adviceFunc = args[2];
-					ao.aroundFunc = args[3];
-				}
-				break;
-			case 6:
-				ao.srcObj = args[1];
-				ao.srcFunc = args[2];
-				ao.adviceObj = args[3]
-				ao.adviceFunc = args[4];
-				ao.aroundFunc = args[5];
-				ao.aroundObj = dj_global;
-				break;
-			default:
-				ao.srcObj = args[1];
-				ao.srcFunc = args[2];
-				ao.adviceObj = args[3]
-				ao.adviceFunc = args[4];
-				ao.aroundObj = args[5];
-				ao.aroundFunc = args[6];
-				ao.once = args[7];
-				ao.delay = args[8];
-				ao.rate = args[9];
-				ao.adviceMsg = args[10];
-				break;
-		}
-
-		if(dl.isFunction(ao.aroundFunc)){
-			var tmpName  = dl.nameAnonFunc(ao.aroundFunc, ao.aroundObj, searchForNames);
-			ao.aroundFunc = tmpName;
-		}
-
-		if(dl.isFunction(ao.srcFunc)){
-			ao.srcFunc = dl.getNameInObj(ao.srcObj, ao.srcFunc);
-		}
-
-		if(dl.isFunction(ao.adviceFunc)){
-			ao.adviceFunc = dl.getNameInObj(ao.adviceObj, ao.adviceFunc);
-		}
-
-		if((ao.aroundObj)&&(dl.isFunction(ao.aroundFunc))){
-			ao.aroundFunc = dl.getNameInObj(ao.aroundObj, ao.aroundFunc);
-		}
-
-		if(!ao.srcObj){
-			dojo.raise("bad srcObj for srcFunc: "+ao.srcFunc);
-		}
-		if(!ao.adviceObj){
-			dojo.raise("bad adviceObj for adviceFunc: "+ao.adviceFunc);
-		}
-		
-		if(!ao.adviceFunc){
-			dojo.debug("bad adviceFunc for srcFunc: "+ao.srcFunc);
-			dojo.debugShallow(ao);
-		} 
-		
-		return ao;
-	}
-
-	this.connect = function(/*...*/){
-		// summary:
-		//		dojo.event.connect is the glue that holds most Dojo-based
-		//		applications together. Most combinations of arguments are
-		//		supported, with the connect() method attempting to disambiguate
-		//		the implied types of positional parameters. The following will
-		//		all work:
-		//			dojo.event.connect("globalFunctionName1", "globalFunctionName2");
-		//			dojo.event.connect(functionReference1, functionReference2);
-		//			dojo.event.connect("globalFunctionName1", functionReference2);
-		//			dojo.event.connect(functionReference1, "globalFunctionName2");
-		//			dojo.event.connect(scope1, "functionName1", "globalFunctionName2");
-		//			dojo.event.connect("globalFunctionName1", scope2, "functionName2");
-		//			dojo.event.connect(scope1, "functionName1", scope2, "functionName2");
-		//			dojo.event.connect("after", scope1, "functionName1", scope2, "functionName2");
-		//			dojo.event.connect("before", scope1, "functionName1", scope2, "functionName2");
-		//			dojo.event.connect("around", 	scope1, "functionName1", 
-		//											scope2, "functionName2",
-		//											aroundFunctionReference);
-		//			dojo.event.connect("around", 	scope1, "functionName1", 
-		//											scope2, "functionName2",
-		//											scope3, "aroundFunctionName");
-		//			dojo.event.connect("before-around", 	scope1, "functionName1", 
-		//													scope2, "functionName2",
-		//													aroundFunctionReference);
-		//			dojo.event.connect("after-around", 		scope1, "functionName1", 
-		//													scope2, "functionName2",
-		//													aroundFunctionReference);
-		//			dojo.event.connect("after-around", 		scope1, "functionName1", 
-		//													scope2, "functionName2",
-		//													scope3, "aroundFunctionName");
-		//			dojo.event.connect("around", 	scope1, "functionName1", 
-		//											scope2, "functionName2",
-		//											scope3, "aroundFunctionName", true, 30);
-		//			dojo.event.connect("around", 	scope1, "functionName1", 
-		//											scope2, "functionName2",
-		//											scope3, "aroundFunctionName", null, null, 10);
-		// adviceType: 
-		//		Optional. String. One of "before", "after", "around",
-		//		"before-around", or "after-around". FIXME
-		// srcObj:
-		//		the scope in which to locate/execute the named srcFunc. Along
-		//		with srcFunc, this creates a way to dereference the function to
-		//		call. So if the function in question is "foo.bar", the
-		//		srcObj/srcFunc pair would be foo and "bar", where "bar" is a
-		//		string and foo is an object reference.
-		// srcFunc:
-		//		the name of the function to connect to. When it is executed,
-		//		the listener being registered with this call will be called.
-		//		The adviceType defines the call order between the source and
-		//		the target functions.
-		// adviceObj:
-		//		the scope in which to locate/execute the named adviceFunc.
-		// adviceFunc:
-		//		the name of the function being conected to srcObj.srcFunc
-		// aroundObj:
-		//		the scope in which to locate/execute the named aroundFunc.
-		// aroundFunc:
-		//		the name of, or a reference to, the function that will be used
-		//		to mediate the advice call. Around advice requires a special
-		//		unary function that will be passed a "MethodInvocation" object.
-		//		These objects have several important properties, namely:
-		//			- args
-		//				a mutable array of arguments to be passed into the
-		//				wrapped function
-		//			- proceed
-		//				a function that "continues" the invocation. The result
-		//				of this function is the return of the wrapped function.
-		//				You can then manipulate this return before passing it
-		//				back out (or take further action based on it).
-		// once:
-		//		boolean that determines whether or not this connect() will
-		//		create a new connection if an identical connect() has already
-		//		been made. Defaults to "false".
-		// delay:
-		//		an optional delay (in ms), as an integer, for dispatch of a
-		//		listener after the source has been fired.
-		// rate:
-		//		an optional rate throttling parameter (integer, in ms). When
-		//		specified, this particular connection will not fire more than
-		//		once in the interval specified by the rate
-		// adviceMsg:
-		//		boolean. Should the listener have all the parameters passed in
-		//		as a single argument?
-
-		/*
-				ao.adviceType = args[0];
-				ao.srcObj = args[1];
-				ao.srcFunc = args[2];
-				ao.adviceObj = args[3]
-				ao.adviceFunc = args[4];
-				ao.aroundObj = args[5];
-				ao.aroundFunc = args[6];
-				ao.once = args[7];
-				ao.delay = args[8];
-				ao.rate = args[9];
-				ao.adviceMsg = args[10];
-		*/
-		if(arguments.length == 1){
-			var ao = arguments[0];
-		}else{
-			var ao = interpolateArgs(arguments, true);
-		}
-		if(dojo.lang.isString(ao.srcFunc) && (ao.srcFunc.toLowerCase() == "onkey") ){
-			if(dojo.render.html.ie){
-				ao.srcFunc = "onkeydown";
-				this.connect(ao);
-			}
-			ao.srcFunc = "onkeypress";
-		}
-
-
-		if(dojo.lang.isArray(ao.srcObj) && ao.srcObj!=""){
-			var tmpAO = {};
-			for(var x in ao){
-				tmpAO[x] = ao[x];
-			}
-			var mjps = [];
-			dojo.lang.forEach(ao.srcObj, function(src){
-				if((dojo.render.html.capable)&&(dojo.lang.isString(src))){
-					src = dojo.byId(src);
-					// dojo.debug(src);
-				}
-				tmpAO.srcObj = src;
-				// dojo.debug(tmpAO.srcObj, tmpAO.srcFunc);
-				// dojo.debug(tmpAO.adviceObj, tmpAO.adviceFunc);
-				mjps.push(dojo.event.connect.call(dojo.event, tmpAO));
-			});
-			return mjps;
-		}
-
-		// FIXME: just doing a "getForMethod()" seems to be enough to put this into infinite recursion!!
-		var mjp = dojo.event.MethodJoinPoint.getForMethod(ao.srcObj, ao.srcFunc);
-		if(ao.adviceFunc){
-			var mjp2 = dojo.event.MethodJoinPoint.getForMethod(ao.adviceObj, ao.adviceFunc);
-		}
-
-		mjp.kwAddAdvice(ao);
-
-		// advanced users might want to fsck w/ the join point manually
-		return mjp; // a MethodJoinPoint object
-	}
-
-	this.log = function(/*object or funcName*/ a1, /*funcName*/ a2){
-		// summary:
-		//		a function that will wrap and log all calls to the specified
-		//		a1.a2() function. If only a1 is passed, it'll be used as a
-		//		function or function name on the global context. Logging will
-		//		be sent to dojo.debug
-		// a1:
-		//		if a2 is passed, this should be an object. If not, it can be a
-		//		function or function name.
-		// a2:
-		//		a function name
-		var kwArgs;
-		if((arguments.length == 1)&&(typeof a1 == "object")){
-			kwArgs = a1;
-		}else{
-			kwArgs = {
-				srcObj: a1,
-				srcFunc: a2
-			};
-		}
-		kwArgs.adviceFunc = function(){
-			var argsStr = [];
-			for(var x=0; x<arguments.length; x++){
-				argsStr.push(arguments[x]);
-			}
-			dojo.debug("("+kwArgs.srcObj+")."+kwArgs.srcFunc, ":", argsStr.join(", "));
-		}
-		this.kwConnect(kwArgs);
-	}
-
-	this.connectBefore = function(){
-		// summary:
-		//	 	takes the same parameters as dojo.event.connect(), except that
-		//	 	the advice type will always be "before"
-		var args = ["before"];
-		for(var i = 0; i < arguments.length; i++){ args.push(arguments[i]); }
-		return this.connect.apply(this, args); // a MethodJoinPoint object
-	}
-
-	this.connectAround = function(){
-		// summary:
-		//	 	takes the same parameters as dojo.event.connect(), except that
-		//	 	the advice type will always be "around"
-		var args = ["around"];
-		for(var i = 0; i < arguments.length; i++){ args.push(arguments[i]); }
-		return this.connect.apply(this, args); // a MethodJoinPoint object
-	}
-
-	this.connectOnce = function(){
-		// summary:
-		//	 	takes the same parameters as dojo.event.connect(), except that
-		//	 	the "once" flag will always be set to "true"
-		var ao = interpolateArgs(arguments, true);
-		ao.once = true;
-		return this.connect(ao); // a MethodJoinPoint object
-	}
-
-	this._kwConnectImpl = function(kwArgs, disconnect){
-		var fn = (disconnect) ? "disconnect" : "connect";
-		if(typeof kwArgs["srcFunc"] == "function"){
-			kwArgs.srcObj = kwArgs["srcObj"]||dj_global;
-			var tmpName  = dojo.lang.nameAnonFunc(kwArgs.srcFunc, kwArgs.srcObj, true);
-			kwArgs.srcFunc = tmpName;
-		}
-		if(typeof kwArgs["adviceFunc"] == "function"){
-			kwArgs.adviceObj = kwArgs["adviceObj"]||dj_global;
-			var tmpName  = dojo.lang.nameAnonFunc(kwArgs.adviceFunc, kwArgs.adviceObj, true);
-			kwArgs.adviceFunc = tmpName;
-		}
-		kwArgs.srcObj = kwArgs["srcObj"]||dj_global;
-		kwArgs.adviceObj = kwArgs["adviceObj"]||kwArgs["targetObj"]||dj_global;
-		kwArgs.adviceFunc = kwArgs["adviceFunc"]||kwArgs["targetFunc"];
-		// pass kwargs to avoid unrolling/repacking
-		return dojo.event[fn](kwArgs);
-	}
-
-	this.kwConnect = function(/*Object*/ kwArgs){
-		// summary:
-		//		A version of dojo.event.connect() that takes a map of named
-		//		parameters instead of the positional parameters that
-		//		dojo.event.connect() uses. For many advanced connection types,
-		//		this can be a much more readable (and potentially faster)
-		//		alternative.
-		// kwArgs:
-		// 		An object that can have the following properties:
-		//			- adviceType
-		//			- srcObj
-		//			- srcFunc
-		//			- adviceObj
-		//			- adviceFunc 
-		//			- aroundObj
-		//			- aroundFunc
-		//			- once
-		//			- delay
-		//			- rate
-		//			- adviceMsg
-		//		As with connect, only srcFunc and adviceFunc are generally
-		//		required
-
-		return this._kwConnectImpl(kwArgs, false); // a MethodJoinPoint object
-
-	}
-
-	this.disconnect = function(){
-		// summary:
-		//		Takes the same parameters as dojo.event.connect() but destroys
-		//		an existing connection instead of building a new one. For
-		//		multiple identical connections, multiple disconnect() calls
-		//		will unroll one each time it's called.
-		if(arguments.length == 1){
-			var ao = arguments[0];
-		}else{
-			var ao = interpolateArgs(arguments, true);
-		}
-		if(!ao.adviceFunc){ return; } // nothing to disconnect
-		if(dojo.lang.isString(ao.srcFunc) && (ao.srcFunc.toLowerCase() == "onkey") ){
-			if(dojo.render.html.ie){
-				ao.srcFunc = "onkeydown";
-				this.disconnect(ao);
-			}
-			ao.srcFunc = "onkeypress";
-		}
-		var mjp = dojo.event.MethodJoinPoint.getForMethod(ao.srcObj, ao.srcFunc);
-		return mjp.removeAdvice(ao.adviceObj, ao.adviceFunc, ao.adviceType, ao.once); // a MethodJoinPoint object
-	}
-
-	this.kwDisconnect = function(kwArgs){
-		// summary:
-		//		Takes the same parameters as dojo.event.kwConnect() but
-		//		destroys an existing connection instead of building a new one.
-		return this._kwConnectImpl(kwArgs, true);
-	}
-}
-
-// exactly one of these is created whenever a method with a joint point is run,
-// if there is at least one 'around' advice.
-dojo.event.MethodInvocation = function(/*dojo.event.MethodJoinPoint*/join_point, /*Object*/obj, /*Array*/args){
-	// summary:
-	//		a class the models the call into a function. This is used under the
-	//		covers for all method invocations on both ends of a
-	//		connect()-wrapped function dispatch. This allows us to "pickle"
-	//		calls, such as in the case of around advice.
-	// join_point:
-	//		a dojo.event.MethodJoinPoint object that represents a connection
-	// obj:
-	//		the scope the call will execute in
-	// args:
-	//		an array of parameters that will get passed to the callee
-	this.jp_ = join_point;
-	this.object = obj;
-	this.args = [];
-	// make sure we don't lock into a mutable object which can change under us.
-	// It's ok if the individual items change, though.
-	for(var x=0; x<args.length; x++){
-		this.args[x] = args[x];
-	}
-	// the index of the 'around' that is currently being executed.
-	this.around_index = -1;
-}
-
-dojo.event.MethodInvocation.prototype.proceed = function(){
-	// summary:
-	//		proceed with the method call that's represented by this invocation
-	//		object
-	this.around_index++;
-	if(this.around_index >= this.jp_.around.length){
-		return this.jp_.object[this.jp_.methodname].apply(this.jp_.object, this.args);
-		// return this.jp_.run_before_after(this.object, this.args);
-	}else{
-		var ti = this.jp_.around[this.around_index];
-		var mobj = ti[0]||dj_global;
-		var meth = ti[1];
-		return mobj[meth].call(mobj, this);
-	}
-} 
-
-
-dojo.event.MethodJoinPoint = function(/*Object*/obj, /*String*/funcName){
-	this.object = obj||dj_global;
-	this.methodname = funcName;
-	this.methodfunc = this.object[funcName];
-	this.squelch = false;
-	// this.before = [];
-	// this.after = [];
-	// this.around = [];
-}
-
-dojo.event.MethodJoinPoint.getForMethod = function(/*Object*/obj, /*String*/funcName){
-	// summary:
-	//		"static" class function for returning a MethodJoinPoint from a
-	//		scoped function. If one doesn't exist, one is created.
-	// obj:
-	//		the scope to search for the function in
-	// funcName:
-	//		the name of the function to return a MethodJoinPoint for
-	if(!obj){ obj = dj_global; }
-	if(!obj[funcName]){
-		// supply a do-nothing method implementation
-		obj[funcName] = function(){};
-		if(!obj[funcName]){
-			// e.g. cannot add to inbuilt objects in IE6
-			dojo.raise("Cannot set do-nothing method on that object "+funcName);
-		}
-	}else if((!dojo.lang.isFunction(obj[funcName]))&&(!dojo.lang.isAlien(obj[funcName]))){
-		// FIXME: should we throw an exception here instead?
-		return null; 
-	}
-	// we hide our joinpoint instance in obj[funcName + '$joinpoint']
-	var jpname = funcName + "$joinpoint";
-	var jpfuncname = funcName + "$joinpoint$method";
-	var joinpoint = obj[jpname];
-	if(!joinpoint){
-		var isNode = false;
-		if(dojo.event["browser"]){
-			if( (obj["attachEvent"])||
-				(obj["nodeType"])||
-				(obj["addEventListener"]) ){
-				isNode = true;
-				dojo.event.browser.addClobberNodeAttrs(obj, [jpname, jpfuncname, funcName]);
-			}
-		}
-		var origArity = obj[funcName].length;
-		obj[jpfuncname] = obj[funcName];
-		// joinpoint = obj[jpname] = new dojo.event.MethodJoinPoint(obj, funcName);
-		joinpoint = obj[jpname] = new dojo.event.MethodJoinPoint(obj, jpfuncname);
-		obj[funcName] = function(){ 
-			var args = [];
-
-			if((isNode)&&(!arguments.length)){
-				var evt = null;
-				try{
-					if(obj.ownerDocument){
-						evt = obj.ownerDocument.parentWindow.event;
-					}else if(obj.documentElement){
-						evt = obj.documentElement.ownerDocument.parentWindow.event;
-					}else if(obj.event){ //obj is a window
-						evt = obj.event;
-					}else{
-						evt = window.event;
-					}
-				}catch(e){
-					evt = window.event;
-				}
-
-				if(evt){
-					args.push(dojo.event.browser.fixEvent(evt, this));
-				}
-			}else{
-				for(var x=0; x<arguments.length; x++){
-					if((x==0)&&(isNode)&&(dojo.event.browser.isEvent(arguments[x]))){
-						args.push(dojo.event.browser.fixEvent(arguments[x], this));
-					}else{
-						args.push(arguments[x]);
-					}
-				}
-			}
-			// return joinpoint.run.apply(joinpoint, arguments); 
-			return joinpoint.run.apply(joinpoint, args); 
-		}
-		obj[funcName].__preJoinArity = origArity;
-	}
-	return joinpoint; // dojo.event.MethodJoinPoint
-}
-
-dojo.lang.extend(dojo.event.MethodJoinPoint, {
-	unintercept: function(){
-		// summary: 
-		//		destroy the connection to all listeners that may have been
-		//		registered on this joinpoint
-		this.object[this.methodname] = this.methodfunc;
-		this.before = [];
-		this.after = [];
-		this.around = [];
-	},
-
-	disconnect: dojo.lang.forward("unintercept"),
-
-	run: function(){
-		// summary:
-		//		execute the connection represented by this join point. The
-		//		arguments passed to run() will be passed to the function and
-		//		its listeners.
-		var obj = this.object||dj_global;
-		var args = arguments;
-
-		// optimization. We only compute once the array version of the arguments
-		// pseudo-arr in order to prevent building it each time advice is unrolled.
-		var aargs = [];
-		for(var x=0; x<args.length; x++){
-			aargs[x] = args[x];
-		}
-
-		var unrollAdvice  = function(marr){ 
-			if(!marr){
-				dojo.debug("Null argument to unrollAdvice()");
-				return;
-			}
-		  
-			var callObj = marr[0]||dj_global;
-			var callFunc = marr[1];
-			
-			if(!callObj[callFunc]){
-				dojo.raise("function \"" + callFunc + "\" does not exist on \"" + callObj + "\"");
-			}
-			
-			var aroundObj = marr[2]||dj_global;
-			var aroundFunc = marr[3];
-			var msg = marr[6];
-			var undef;
-
-			var to = {
-				args: [],
-				jp_: this,
-				object: obj,
-				proceed: function(){
-					return callObj[callFunc].apply(callObj, to.args);
-				}
-			};
-			to.args = aargs;
-
-			var delay = parseInt(marr[4]);
-			var hasDelay = ((!isNaN(delay))&&(marr[4]!==null)&&(typeof marr[4] != "undefined"));
-			if(marr[5]){
-				var rate = parseInt(marr[5]);
-				var cur = new Date();
-				var timerSet = false;
-				if((marr["last"])&&((cur-marr.last)<=rate)){
-					if(dojo.event._canTimeout){
-						if(marr["delayTimer"]){
-							clearTimeout(marr.delayTimer);
-						}
-						var tod = parseInt(rate*2); // is rate*2 naive?
-						var mcpy = dojo.lang.shallowCopy(marr);
-						marr.delayTimer = setTimeout(function(){
-							// FIXME: on IE at least, event objects from the
-							// browser can go out of scope. How (or should?) we
-							// deal with it?
-							mcpy[5] = 0;
-							unrollAdvice(mcpy);
-						}, tod);
-					}
-					return;
-				}else{
-					marr.last = cur;
-				}
-			}
-
-			// FIXME: need to enforce rates for a connection here!
-
-			if(aroundFunc){
-				// NOTE: around advice can't delay since we might otherwise depend
-				// on execution order!
-				aroundObj[aroundFunc].call(aroundObj, to);
-			}else{
-				// var tmjp = dojo.event.MethodJoinPoint.getForMethod(obj, methname);
-				if((hasDelay)&&((dojo.render.html)||(dojo.render.svg))){  // FIXME: the render checks are grotty!
-					dj_global["setTimeout"](function(){
-						if(msg){
-							callObj[callFunc].call(callObj, to); 
-						}else{
-							callObj[callFunc].apply(callObj, args); 
-						}
-					}, delay);
-				}else{ // many environments can't support delay!
-					if(msg){
-						callObj[callFunc].call(callObj, to); 
-					}else{
-						callObj[callFunc].apply(callObj, args); 
-					}
-				}
-			}
-		}
-
-		var unRollSquelch = function(){
-			if(this.squelch){
-				try{
-					return unrollAdvice.apply(this, arguments);
-				}catch(e){ 
-					dojo.debug(e);
-				}
-			}else{
-				return unrollAdvice.apply(this, arguments);
-			}
-		}
-
-		if((this["before"])&&(this.before.length>0)){
-			// pass a cloned array, if this event disconnects this event forEach on this.before wont work
-			dojo.lang.forEach(this.before.concat(new Array()), unRollSquelch);
-		}
-
-		var result;
-		try{
-			if((this["around"])&&(this.around.length>0)){
-				var mi = new dojo.event.MethodInvocation(this, obj, args);
-				result = mi.proceed();
-			}else if(this.methodfunc){
-				result = this.object[this.methodname].apply(this.object, args);
-			}
-		}catch(e){ if(!this.squelch){ dojo.raise(e); } }
-
-		if((this["after"])&&(this.after.length>0)){
-			// see comment on this.before above
-			dojo.lang.forEach(this.after.concat(new Array()), unRollSquelch);
-		}
-
-		return (this.methodfunc) ? result : null;
-	},
-
-	getArr: function(/*String*/kind){
-		// summary: return a list of listeners of the past "kind"
-		// kind:
-		//		can be one of: "before", "after", "around", "before-around", or
-		//		"after-around"
-		var type = "after";
-		// FIXME: we should be able to do this through props or Array.in()
-		if((typeof kind == "string")&&(kind.indexOf("before")!=-1)){
-			type = "before";
-		}else if(kind=="around"){
-			type = "around";
-		}
-		if(!this[type]){ this[type] = []; }
-		return this[type]; // Array
-	},
-
-	kwAddAdvice: function(/*Object*/args){
-		// summary:
-		//		adds advice to the joinpoint with arguments in a map
-		// args:
-		// 		An object that can have the following properties:
-		//			- adviceType
-		//			- adviceObj
-		//			- adviceFunc 
-		//			- aroundObj
-		//			- aroundFunc
-		//			- once
-		//			- delay
-		//			- rate
-		//			- adviceMsg
-		this.addAdvice(	args["adviceObj"], args["adviceFunc"], 
-						args["aroundObj"], args["aroundFunc"], 
-						args["adviceType"], args["precedence"], 
-						args["once"], args["delay"], args["rate"], 
-						args["adviceMsg"]);
-	},
-
-	addAdvice: function(	thisAdviceObj, thisAdvice, 
-							thisAroundObj, thisAround, 
-							adviceType, precedence, 
-							once, delay, rate, asMessage){
-		// summary:
-		//		add advice to this joinpoint using positional parameters
-		// thisAdviceObj:
-		//		the scope in which to locate/execute the named adviceFunc.
-		// thisAdviceFunc:
-		//		the name of the function being conected
-		// thisAroundObj:
-		//		the scope in which to locate/execute the named aroundFunc.
-		// thisAroundFunc:
-		//		the name of the function that will be used to mediate the
-		//		advice call.
-		// adviceType: 
-		//		Optional. String. One of "before", "after", "around",
-		//		"before-around", or "after-around". FIXME
-		// once:
-		//		boolean that determines whether or not this advice will create
-		//		a new connection if an identical advice set has already been
-		//		provided. Defaults to "false".
-		// delay:
-		//		an optional delay (in ms), as an integer, for dispatch of a
-		//		listener after the source has been fired.
-		// rate:
-		//		an optional rate throttling parameter (integer, in ms). When
-		//		specified, this particular connection will not fire more than
-		//		once in the interval specified by the rate
-		// adviceMsg:
-		//		boolean. Should the listener have all the parameters passed in
-		//		as a single argument?
-		var arr = this.getArr(adviceType);
-		if(!arr){
-			dojo.raise("bad this: " + this);
-		}
-
-		var ao = [thisAdviceObj, thisAdvice, thisAroundObj, thisAround, delay, rate, asMessage];
-		
-		if(once){
-			if(this.hasAdvice(thisAdviceObj, thisAdvice, adviceType, arr) >= 0){
-				return;
-			}
-		}
-
-		if(precedence == "first"){
-			arr.unshift(ao);
-		}else{
-			arr.push(ao);
-		}
-	},
-
-	hasAdvice: function(thisAdviceObj, thisAdvice, adviceType, arr){
-		// summary:
-		//		returns the array index of the first existing connection
-		//		betweened the passed advice and this joinpoint. Will be -1 if
-		//		none exists.
-		// thisAdviceObj:
-		//		the scope in which to locate/execute the named adviceFunc.
-		// thisAdviceFunc:
-		//		the name of the function being conected
-		// adviceType: 
-		//		Optional. String. One of "before", "after", "around",
-		//		"before-around", or "after-around". FIXME
-		// arr:
-		//		Optional. The list of advices to search. Will be found via
-		//		adviceType if not passed
-		if(!arr){ arr = this.getArr(adviceType); }
-		var ind = -1;
-		for(var x=0; x<arr.length; x++){
-			var aao = (typeof thisAdvice == "object") ? (new String(thisAdvice)).toString() : thisAdvice;
-			var a1o = (typeof arr[x][1] == "object") ? (new String(arr[x][1])).toString() : arr[x][1];
-			if((arr[x][0] == thisAdviceObj)&&(a1o == aao)){
-				ind = x;
-			}
-		}
-		return ind; // Integer
-	},
-
-	removeAdvice: function(thisAdviceObj, thisAdvice, adviceType, once){
-		// summary:
-		//		returns the array index of the first existing connection
-		//		betweened the passed advice and this joinpoint. Will be -1 if
-		//		none exists.
-		// thisAdviceObj:
-		//		the scope in which to locate/execute the named adviceFunc.
-		// thisAdviceFunc:
-		//		the name of the function being conected
-		// adviceType: 
-		//		Optional. String. One of "before", "after", "around",
-		//		"before-around", or "after-around". FIXME
-		// once:
-		//		Optional. Should this only remove the first occurance of the
-		//		connection?
-		var arr = this.getArr(adviceType);
-		var ind = this.hasAdvice(thisAdviceObj, thisAdvice, adviceType, arr);
-		if(ind == -1){
-			return false;
-		}
-		while(ind != -1){
-			arr.splice(ind, 1);
-			if(once){ break; }
-			ind = this.hasAdvice(thisAdviceObj, thisAdvice, adviceType, arr);
-		}
-		return true;
-	}
-});
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/event/topic.js b/continuum-webapp/src/main/webapp/struts/dojo/event/topic.js
deleted file mode 100644
index 597f1cf..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/event/topic.js
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
-	Copyright (c) 2004-2006, The Dojo Foundation
-	All Rights Reserved.
-
-	Licensed under the Academic Free License version 2.1 or above OR the
-	modified BSD license. For more information on Dojo licensing, see:
-
-		http://dojotoolkit.org/community/licensing.shtml
-*/
-
-dojo.require("dojo.event.common");
-dojo.provide("dojo.event.topic");
-
-dojo.event.topic = new function(){
-	this.topics = {};
-
-	this.getTopic = function(/*String*/topic){
-		// summary:
-		//		returns a topic implementation object of type
-		//		dojo.event.topic.TopicImpl
-		// topic:
-		//		a unique, opaque string that names the topic
-		if(!this.topics[topic]){
-			this.topics[topic] = new this.TopicImpl(topic);
-		}
-		return this.topics[topic]; // a dojo.event.topic.TopicImpl object
-	}
-
-	this.registerPublisher = function(/*String*/topic, /*Object*/obj, /*String*/funcName){
-		// summary:
-		//		registers a function as a publisher on a topic. Subsequent
-		//		calls to the function will cause a publish event on the topic
-		//		with the arguments passed to the function passed to registered
-		//		listeners.
-		// topic: 
-		//		a unique, opaque string that names the topic
-		// obj:
-		//		the scope to locate the function in
-		// funcName:
-		//		the name of the function to register
-		var topic = this.getTopic(topic);
-		topic.registerPublisher(obj, funcName);
-	}
-
-	this.subscribe = function(/*String*/topic, /*Object*/obj, /*String*/funcName){
-		// summary:
-		//		susbscribes the function to the topic. Subsequent events
-		//		dispached to the topic will create a function call for the
-		//		obj.funcName() function.
-		// topic: 
-		//		a unique, opaque string that names the topic
-		// obj:
-		//		the scope to locate the function in
-		// funcName:
-		//		the name of the function to being registered as a listener
-		var topic = this.getTopic(topic);
-		topic.subscribe(obj, funcName);
-	}
-
-	this.unsubscribe = function(/*String*/topic, /*Object*/obj, /*String*/funcName){
-		// summary:
-		//		unsubscribes the obj.funcName() from the topic
-		// topic: 
-		//		a unique, opaque string that names the topic
-		// obj:
-		//		the scope to locate the function in
-		// funcName:
-		//		the name of the function to being unregistered as a listener
-		var topic = this.getTopic(topic);
-		topic.unsubscribe(obj, funcName);
-	}
-
-	this.destroy = function(/*String*/topic){
-		// summary: 
-		//		destroys the topic and unregisters all listeners
-		// topic:
-		//		a unique, opaque string that names the topic
-		this.getTopic(topic).destroy();
-		delete this.topics[topic];
-	}
-
-	this.publishApply = function(/*String*/topic, /*Array*/args){
-		// summary: 
-		//		dispatches an event to the topic using the args array as the
-		//		source for the call arguments to each listener. This is similar
-		//		to JavaScript's built-in Function.apply()
-		// topic:
-		//		a unique, opaque string that names the topic
-		// args:
-		//		the arguments to be passed into listeners of the topic
-		var topic = this.getTopic(topic);
-		topic.sendMessage.apply(topic, args);
-	}
-
-	this.publish = function(/*String*/topic, /*Object*/message){
-		// summary: 
-		//		manually "publish" to the passed topic
-		// topic:
-		//		a unique, opaque string that names the topic
-		// message:
-		//		can be an array of parameters (similar to publishApply), or
-		//		will be treated as one of many arguments to be passed along in
-		//		a "flat" unrolling
-		var topic = this.getTopic(topic);
-		// if message is an array, we treat it as a set of arguments,
-		// otherwise, we just pass on the arguments passed in as-is
-		var args = [];
-		// could we use concat instead here?
-		for(var x=1; x<arguments.length; x++){
-			args.push(arguments[x]);
-		}
-		topic.sendMessage.apply(topic, args);
-	}
-}
-
-dojo.event.topic.TopicImpl = function(topicName){
-	// summary: a class to represent topics
-
-	this.topicName = topicName;
-
-	this.subscribe = function(/*Object*/listenerObject, /*Function or String*/listenerMethod){
-		// summary:
-		//		use dojo.event.connect() to attach the passed listener to the
-		//		topic represented by this object
-		// listenerObject:
-		//		if a string and listenerMethod is ommitted, this is treated as
-		//		the name of a function in the global namespace. If
-		//		listenerMethod is provided, this is the scope to find/execute
-		//		the function in.
-		// listenerMethod:
-		//		Optional. The function to register.
-		var tf = listenerMethod||listenerObject;
-		var to = (!listenerMethod) ? dj_global : listenerObject;
-		return dojo.event.kwConnect({ // dojo.event.MethodJoinPoint
-			srcObj:		this, 
-			srcFunc:	"sendMessage", 
-			adviceObj:	to,
-			adviceFunc: tf
-		});
-	}
-
-	this.unsubscribe = function(/*Object*/listenerObject, /*Function or String*/listenerMethod){
-		// summary:
-		//		use dojo.event.disconnect() to attach the passed listener to the
-		//		topic represented by this object
-		// listenerObject:
-		//		if a string and listenerMethod is ommitted, this is treated as
-		//		the name of a function in the global namespace. If
-		//		listenerMethod is provided, this is the scope to find the
-		//		function in.
-		// listenerMethod:
-		//		Optional. The function to unregister.
-		var tf = (!listenerMethod) ? listenerObject : listenerMethod;
-		var to = (!listenerMethod) ? null : listenerObject;
-		return dojo.event.kwDisconnect({ // dojo.event.MethodJoinPoint
-			srcObj:		this, 
-			srcFunc:	"sendMessage", 
-			adviceObj:	to,
-			adviceFunc: tf
-		});
-	}
-
-	this._getJoinPoint = function(){
-		return dojo.event.MethodJoinPoint.getForMethod(this, "sendMessage");
-	}
-
-	this.setSquelch = function(/*Boolean*/shouldSquelch){
-		// summary: 
-		//		determine whether or not exceptions in the calling of a
-		//		listener in the chain should stop execution of the chain.
-		this._getJoinPoint().squelch = shouldSquelch;
-	}
-
-	this.destroy = function(){
-		// summary: disconnects all listeners from this topic
-		this._getJoinPoint().disconnect();
-	}
-
-	this.registerPublisher = function(	/*Object*/publisherObject, 
-										/*Function or String*/publisherMethod){
-		// summary:
-		//		registers the passed function as a publisher on this topic.
-		//		Each time the function is called, an event will be published on
-		//		this topic.
-		// publisherObject:
-		//		if a string and listenerMethod is ommitted, this is treated as
-		//		the name of a function in the global namespace. If
-		//		listenerMethod is provided, this is the scope to find the
-		//		function in.
-		// publisherMethod:
-		//		Optional. The function to register.
-		dojo.event.connect(publisherObject, publisherMethod, this, "sendMessage");
-	}
-
-	this.sendMessage = function(message){
-		// summary: a stub to be called when a message is sent to the topic.
-
-		// The message has been propagated
-	}
-}
-
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/string/Builder.js b/continuum-webapp/src/main/webapp/struts/dojo/string/Builder.js
deleted file mode 100644
index 4dec5dd..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/string/Builder.js
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
-	Copyright (c) 2004-2006, The Dojo Foundation
-	All Rights Reserved.
-
-	Licensed under the Academic Free License version 2.1 or above OR the
-	modified BSD license. For more information on Dojo licensing, see:
-
-		http://dojotoolkit.org/community/licensing.shtml
-*/
-
-dojo.provide("dojo.string.Builder");
-dojo.require("dojo.string");
-dojo.require("dojo.lang.common");
-
-// NOTE: testing shows that direct "+=" concatenation is *much* faster on
-// Spidermoneky and Rhino, while arr.push()/arr.join() style concatenation is
-// significantly quicker on IE (Jscript/wsh/etc.).
-
-dojo.string.Builder = function(/* string? */str){
-	//	summary
-	this.arrConcat = (dojo.render.html.capable && dojo.render.html["ie"]);
-
-	var a = [];
-	var b = "";
-	var length = this.length = b.length;
-
-	if(this.arrConcat){
-		if(b.length > 0){
-			a.push(b);
-		}
-		b = "";
-	}
-
-	this.toString = this.valueOf = function(){ 
-		//	summary
-		//	Concatenate internal buffer and return as a string
-		return (this.arrConcat) ? a.join("") : b;	//	string
-	};
-
-	this.append = function(){
-		//	summary
-		//	Append all arguments to the end of the internal buffer
-		for(var x=0; x<arguments.length; x++){
-			var s = arguments[x];
-			if(dojo.lang.isArrayLike(s)){
-				this.append.apply(this, s);
-			} else {
-				if(this.arrConcat){
-					a.push(s);
-				}else{
-					b+=s;
-				}
-				length += s.length;
-				this.length = length;
-			}
-		}
-		return this;	//	dojo.string.Builder
-	};
-
-	this.clear = function(){
-		//	summary
-		//	Clear the internal buffer.
-		a = [];
-		b = "";
-		length = this.length = 0;
-		return this;	//	dojo.string.Builder
-	};
-
-	this.remove = function(/* integer */f, /* integer */l){
-		//	summary
-		//	Remove a section of string from the internal buffer.
-		var s = ""; 
-		if(this.arrConcat){
-			b = a.join(""); 
-		}
-		a=[];
-		if(f>0){
-			s = b.substring(0, (f-1));
-		}
-		b = s + b.substring(f + l); 
-		length = this.length = b.length; 
-		if(this.arrConcat){
-			a.push(b);
-			b="";
-		}
-		return this;	//	dojo.string.Builder
-	};
-
-	this.replace = function(/* string */o, /* string */n){
-		//	summary
-		//	replace phrase *o* with phrase *n*.
-		if(this.arrConcat){
-			b = a.join(""); 
-		}
-		a = []; 
-		b = b.replace(o,n); 
-		length = this.length = b.length; 
-		if(this.arrConcat){
-			a.push(b);
-			b="";
-		}
-		return this;	//	dojo.string.Builder
-	};
-
-	this.insert = function(/* integer */idx, /* string */s){
-		//	summary
-		//	Insert string s at index idx.
-		if(this.arrConcat){
-			b = a.join(""); 
-		}
-		a=[];
-		if(idx == 0){
-			b = s + b;
-		}else{
-			var t = b.split("");
-			t.splice(idx,0,s);
-			b = t.join("")
-		}
-		length = this.length = b.length; 
-		if(this.arrConcat){
-			a.push(b); 
-			b="";
-		}
-		return this;	//	dojo.string.Builder
-	};
-
-	this.append.apply(this, arguments);
-};
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/string/__package__.js b/continuum-webapp/src/main/webapp/struts/dojo/string/__package__.js
deleted file mode 100644
index 9a4cded..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/string/__package__.js
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
-	Copyright (c) 2004-2006, The Dojo Foundation
-	All Rights Reserved.
-
-	Licensed under the Academic Free License version 2.1 or above OR the
-	modified BSD license. For more information on Dojo licensing, see:
-
-		http://dojotoolkit.org/community/licensing.shtml
-*/
-
-dojo.kwCompoundRequire({
-	common: [
-		"dojo.string",
-		"dojo.string.common",
-		"dojo.string.extras",
-		"dojo.string.Builder"
-	]
-});
-dojo.provide("dojo.string.*");
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/string/common.js b/continuum-webapp/src/main/webapp/struts/dojo/string/common.js
deleted file mode 100644
index 363028a..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/string/common.js
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
-	Copyright (c) 2004-2006, The Dojo Foundation
-	All Rights Reserved.
-
-	Licensed under the Academic Free License version 2.1 or above OR the
-	modified BSD license. For more information on Dojo licensing, see:
-
-		http://dojotoolkit.org/community/licensing.shtml
-*/
-
-dojo.provide("dojo.string.common");
-
-dojo.string.trim = function(/* string */str, /* integer? */wh){
-	//	summary
-	//	Trim whitespace from str.  If wh > 0, trim from start, if wh < 0, trim from end, else both
-	if(!str.replace){ return str; }
-	if(!str.length){ return str; }
-	var re = (wh > 0) ? (/^\s+/) : (wh < 0) ? (/\s+$/) : (/^\s+|\s+$/g);
-	return str.replace(re, "");	//	string
-}
-
-dojo.string.trimStart = function(/* string */str) {
-	//	summary
-	//	Trim whitespace at the beginning of 'str'
-	return dojo.string.trim(str, 1);	//	string
-}
-
-dojo.string.trimEnd = function(/* string */str) {
-	//	summary
-	//	Trim whitespace at the end of 'str'
-	return dojo.string.trim(str, -1);
-}
-
-dojo.string.repeat = function(/* string */str, /* integer */count, /* string? */separator) {
-	//	summary
-	//	Return 'str' repeated 'count' times, optionally placing 'separator' between each rep
-	var out = "";
-	for(var i = 0; i < count; i++) {
-		out += str;
-		if(separator && i < count - 1) {
-			out += separator;
-		}
-	}
-	return out;	//	string
-}
-
-dojo.string.pad = function(/* string */str, /* integer */len/*=2*/, /* string */ c/*='0'*/, /* integer */dir/*=1*/) {
-	//	summary
-	//	Pad 'str' to guarantee that it is at least 'len' length with the character 'c' at either the 
-	//	start (dir=1) or end (dir=-1) of the string
-	var out = String(str);
-	if(!c) {
-		c = '0';
-	}
-	if(!dir) {
-		dir = 1;
-	}
-	while(out.length < len) {
-		if(dir > 0) {
-			out = c + out;
-		} else {
-			out += c;
-		}
-	}
-	return out;	//	string
-}
-
-dojo.string.padLeft = function(/* string */str, /* integer */len, /* string */c) {
-	//	summary
-	//	same as dojo.string.pad(str, len, c, 1)
-	return dojo.string.pad(str, len, c, 1);	//	string
-}
-
-dojo.string.padRight = function(/* string */str, /* integer */len, /* string */c) {
-	//	summary
-	//	same as dojo.string.pad(str, len, c, -1)
-	return dojo.string.pad(str, len, c, -1);	//	string
-}
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/string/extras.js b/continuum-webapp/src/main/webapp/struts/dojo/string/extras.js
deleted file mode 100644
index 9ccec43..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/string/extras.js
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
-	Copyright (c) 2004-2006, The Dojo Foundation
-	All Rights Reserved.
-
-	Licensed under the Academic Free License version 2.1 or above OR the
-	modified BSD license. For more information on Dojo licensing, see:
-
-		http://dojotoolkit.org/community/licensing.shtml
-*/
-
-dojo.provide("dojo.string.extras");
-
-dojo.require("dojo.string.common");
-dojo.require("dojo.lang.common");
-dojo.require("dojo.lang.array");
-
-//TODO: should we use ${} substitution syntax instead, like widgets do?
-dojo.string.substituteParams = function(/*string*/template, /* object - optional or ... */hash){
-// summary:
-//	Performs parameterized substitutions on a string. Throws an exception if any parameter is unmatched.
-//
-// description:
-//	For example,
-//		dojo.string.substituteParams("File '%{0}' is not found in directory '%{1}'.","foo.html","/temp");
-//	returns
-//		"File 'foo.html' is not found in directory '/temp'."
-//
-// template: the original string template with %{values} to be replaced
-// hash: name/value pairs (type object) to provide substitutions.  Alternatively, substitutions may be
-//	included as arguments 1..n to this function, corresponding to template parameters 0..n-1
-
-	var map = (typeof hash == 'object') ? hash : dojo.lang.toArray(arguments, 1);
-
-	return template.replace(/\%\{(\w+)\}/g, function(match, key){
-		if(typeof(map[key]) != "undefined" && map[key] != null){
-			return map[key];
-		}
-		dojo.raise("Substitution not found: " + key);
-	}); // string
-};
-
-dojo.string.capitalize = function(/*string*/str){
-// summary:
-//	Uppercases the first letter of each word
-
-	if(!dojo.lang.isString(str)){ return ""; }
-	if(arguments.length == 0){ str = this; }
-
-	var words = str.split(' ');
-	for(var i=0; i<words.length; i++){
-		words[i] = words[i].charAt(0).toUpperCase() + words[i].substring(1);
-	}
-	return words.join(" "); // string
-}
-
-dojo.string.isBlank = function(/*string*/str){
-// summary:
-//	Return true if the entire string is whitespace characters
-
-	if(!dojo.lang.isString(str)){ return true; }
-	return (dojo.string.trim(str).length == 0); // boolean
-}
-
-//FIXME: not sure exactly what encodeAscii is trying to do, or if it's working right
-dojo.string.encodeAscii = function(/*string*/str){
-	if(!dojo.lang.isString(str)){ return str; } // unknown
-	var ret = "";
-	var value = escape(str);
-	var match, re = /%u([0-9A-F]{4})/i;
-	while((match = value.match(re))){
-		var num = Number("0x"+match[1]);
-		var newVal = escape("&#" + num + ";");
-		ret += value.substring(0, match.index) + newVal;
-		value = value.substring(match.index+match[0].length);
-	}
-	ret += value.replace(/\+/g, "%2B");
-	return ret; // string
-}
-
-dojo.string.escape = function(/*string*/type, /*string*/str){
-// summary:
-//	Adds escape sequences for special characters according to the convention of 'type'
-//
-// type: one of xml|html|xhtml|sql|regexp|regex|javascript|jscript|js|ascii
-// str: the string to be escaped
-
-	var args = dojo.lang.toArray(arguments, 1);
-	switch(type.toLowerCase()){
-		case "xml":
-		case "html":
-		case "xhtml":
-			return dojo.string.escapeXml.apply(this, args); // string
-		case "sql":
-			return dojo.string.escapeSql.apply(this, args); // string
-		case "regexp":
-		case "regex":
-			return dojo.string.escapeRegExp.apply(this, args); // string
-		case "javascript":
-		case "jscript":
-		case "js":
-			return dojo.string.escapeJavaScript.apply(this, args); // string
-		case "ascii":
-			// so it's encode, but it seems useful
-			return dojo.string.encodeAscii.apply(this, args); // string
-		default:
-			return str; // string
-	}
-}
-
-dojo.string.escapeXml = function(/*string*/str, /*boolean*/noSingleQuotes){
-//summary:
-//	Adds escape sequences for special characters in XML: &<>"'
-//  Optionally skips escapes for single quotes
-
-	str = str.replace(/&/gm, "&amp;").replace(/</gm, "&lt;")
-		.replace(/>/gm, "&gt;").replace(/"/gm, "&quot;");
-	if(!noSingleQuotes){ str = str.replace(/'/gm, "&#39;"); }
-	return str; // string
-}
-
-dojo.string.escapeSql = function(/*string*/str){
-//summary:
-//	Adds escape sequences for single quotes in SQL expressions
-
-	return str.replace(/'/gm, "''"); //string
-}
-
-dojo.string.escapeRegExp = function(/*string*/str){
-//summary:
-//	Adds escape sequences for special characters in regular expressions
-
-	return str.replace(/\\/gm, "\\\\").replace(/([\f\b\n\t\r[\^$|?*+(){}])/gm, "\\$1"); // string
-}
-
-//FIXME: should this one also escape backslash?
-dojo.string.escapeJavaScript = function(/*string*/str){
-//summary:
-//	Adds escape sequences for single and double quotes as well
-//	as non-visible characters in JavaScript string literal expressions
-
-	return str.replace(/(["'\f\b\n\t\r])/gm, "\\$1"); // string
-}
-
-//FIXME: looks a lot like escapeJavaScript, just adds quotes? deprecate one?
-dojo.string.escapeString = function(/*string*/str){
-//summary:
-//	Adds escape sequences for non-visual characters, double quote and backslash
-//	and surrounds with double quotes to form a valid string literal.
-	return ('"' + str.replace(/(["\\])/g, '\\$1') + '"'
-		).replace(/[\f]/g, "\\f"
-		).replace(/[\b]/g, "\\b"
-		).replace(/[\n]/g, "\\n"
-		).replace(/[\t]/g, "\\t"
-		).replace(/[\r]/g, "\\r"); // string
-}
-
-// TODO: make an HTML version
-dojo.string.summary = function(/*string*/str, /*number*/len){
-// summary:
-//	Truncates 'str' after 'len' characters and appends periods as necessary so that it ends with "..."
-
-	if(!len || str.length <= len){
-		return str; // string
-	}
-
-	return str.substring(0, len).replace(/\.+$/, "") + "..."; // string
-}
-
-dojo.string.endsWith = function(/*string*/str, /*string*/end, /*boolean*/ignoreCase){
-// summary:
-//	Returns true if 'str' ends with 'end'
-
-	if(ignoreCase){
-		str = str.toLowerCase();
-		end = end.toLowerCase();
-	}
-	if((str.length - end.length) < 0){
-		return false; // boolean
-	}
-	return str.lastIndexOf(end) == str.length - end.length; // boolean
-}
-
-dojo.string.endsWithAny = function(/*string*/str /* , ... */){
-// summary:
-//	Returns true if 'str' ends with any of the arguments[2 -> n]
-
-	for(var i = 1; i < arguments.length; i++) {
-		if(dojo.string.endsWith(str, arguments[i])) {
-			return true; // boolean
-		}
-	}
-	return false; // boolean
-}
-
-dojo.string.startsWith = function(/*string*/str, /*string*/start, /*boolean*/ignoreCase){
-// summary:
-//	Returns true if 'str' starts with 'start'
-
-	if(ignoreCase) {
-		str = str.toLowerCase();
-		start = start.toLowerCase();
-	}
-	return str.indexOf(start) == 0; // boolean
-}
-
-dojo.string.startsWithAny = function(/*string*/str /* , ... */){
-// summary:
-//	Returns true if 'str' starts with any of the arguments[2 -> n]
-
-	for(var i = 1; i < arguments.length; i++) {
-		if(dojo.string.startsWith(str, arguments[i])) {
-			return true; // boolean
-		}
-	}
-	return false; // boolean
-}
-
-dojo.string.has = function(/*string*/str /* , ... */) {
-// summary:
-//	Returns true if 'str' contains any of the arguments 2 -> n
-
-	for(var i = 1; i < arguments.length; i++) {
-		if(str.indexOf(arguments[i]) > -1){
-			return true; // boolean
-		}
-	}
-	return false; // boolean
-}
-
-dojo.string.normalizeNewlines = function(/*string*/text, /*string? (\n or \r)*/newlineChar){
-// summary:
-//	Changes occurences of CR and LF in text to CRLF, or if newlineChar is provided as '\n' or '\r',
-//	substitutes newlineChar for occurrences of CR/LF and CRLF
-
-	if (newlineChar == "\n"){
-		text = text.replace(/\r\n/g, "\n");
-		text = text.replace(/\r/g, "\n");
-	} else if (newlineChar == "\r"){
-		text = text.replace(/\r\n/g, "\r");
-		text = text.replace(/\n/g, "\r");
-	}else{
-		text = text.replace(/([^\r])\n/g, "$1\r\n").replace(/\r([^\n])/g, "\r\n$1");
-	}
-	return text; // string
-}
-
-dojo.string.splitEscaped = function(/*string*/str, /*string of length=1*/charac){
-// summary:
-//	Splits 'str' into an array separated by 'charac', but skips characters escaped with a backslash
-
-	var components = [];
-	for (var i = 0, prevcomma = 0; i < str.length; i++){
-		if (str.charAt(i) == '\\'){ i++; continue; }
-		if (str.charAt(i) == charac){
-			components.push(str.substring(prevcomma, i));
-			prevcomma = i + 1;
-		}
-	}
-	components.push(str.substr(prevcomma));
-	return components; // array
-}
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/text/__package__.js b/continuum-webapp/src/main/webapp/struts/dojo/text/__package__.js
deleted file mode 100644
index 35a57d6..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/text/__package__.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
-	Copyright (c) 2004-2006, The Dojo Foundation
-	All Rights Reserved.
-
-	Licensed under the Academic Free License version 2.1 or above OR the
-	modified BSD license. For more information on Dojo licensing, see:
-
-		http://dojotoolkit.org/community/licensing.shtml
-*/
-
-dojo.kwCompoundRequire({
-	common: [
-		"dojo.text.String",
-		"dojo.text.Builder"
-	]
-});
-
-dojo.deprecated("dojo.text", "textDirectory moved to cal, text.String and text.Builder havne't been here for awhile", "0.5");
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/text/textDirectory.js b/continuum-webapp/src/main/webapp/struts/dojo/text/textDirectory.js
deleted file mode 100644
index 1576f86..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/text/textDirectory.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
-	Copyright (c) 2004-2006, The Dojo Foundation
-	All Rights Reserved.
-
-	Licensed under the Academic Free License version 2.1 or above OR the
-	modified BSD license. For more information on Dojo licensing, see:
-
-		http://dojotoolkit.org/community/licensing.shtml
-*/
-
-dojo.require("dojo.cal.textDirectory");
-dojo.deprecate("dojo.text.textDirectory", "use dojo.cal.textDirectory", "0.5");
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/validate.js b/continuum-webapp/src/main/webapp/struts/dojo/validate.js
deleted file mode 100644
index e176479..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/validate.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
-	Copyright (c) 2004-2006, The Dojo Foundation
-	All Rights Reserved.
-
-	Licensed under the Academic Free License version 2.1 or above OR the
-	modified BSD license. For more information on Dojo licensing, see:
-
-		http://dojotoolkit.org/community/licensing.shtml
-*/
-
-dojo.provide("dojo.validate");
-dojo.require("dojo.validate.common");
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/validate/__package__.js b/continuum-webapp/src/main/webapp/struts/dojo/validate/__package__.js
deleted file mode 100644
index 6feb1d9..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/validate/__package__.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
-	Copyright (c) 2004-2006, The Dojo Foundation
-	All Rights Reserved.
-
-	Licensed under the Academic Free License version 2.1 or above OR the
-	modified BSD license. For more information on Dojo licensing, see:
-
-		http://dojotoolkit.org/community/licensing.shtml
-*/
-
-dojo.require("dojo.validate");
-dojo.kwCompoundRequire({
-	common:		["dojo.validate.check", 
-						"dojo.validate.datetime", 
-						"dojo.validate.de", 
-						"dojo.validate.jp", 
-						"dojo.validate.us", 
-						"dojo.validate.web" 
-	]
-});
-dojo.provide("dojo.validate.*");
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/validate/check.js b/continuum-webapp/src/main/webapp/struts/dojo/validate/check.js
deleted file mode 100644
index 908d47c..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/validate/check.js
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
-	Copyright (c) 2004-2006, The Dojo Foundation
-	All Rights Reserved.
-
-	Licensed under the Academic Free License version 2.1 or above OR the
-	modified BSD license. For more information on Dojo licensing, see:
-
-		http://dojotoolkit.org/community/licensing.shtml
-*/
-
-dojo.provide("dojo.validate.check");
-dojo.require("dojo.validate.common");
-dojo.require("dojo.lang.common");
-
-dojo.validate.check = function(/*HTMLFormElement*/form, /*Object*/profile){
-	// summary: validates user input of an HTML form based on input profile
-	//
-	// description:
-	//	returns an object that contains several methods summarizing the results of the validation
-	//
-	// form: form to be validated
-	// profile: specifies how the form fields are to be validated
-	// {trim:Array, uppercase:Array, lowercase:Array, ucfirst:Array, digit:Array,
-	//	required:Array, dependencies:Object, constraints:Object, confirm:Object}
-
-	// Essentially private properties of results object
-	var missing = [];
-	var invalid = [];
-
-	// results object summarizes the validation
-	var results = {
-		isSuccessful: function() {return ( !this.hasInvalid() && !this.hasMissing() );},
-		hasMissing: function() {return ( missing.length > 0 );},
-		getMissing: function() {return missing;},
-		isMissing: function(elemname) {
-			for(var i = 0; i < missing.length; i++){
-				if(elemname == missing[i]){ return true; }
-			}
-			return false;
-		},
-		hasInvalid: function() {return ( invalid.length > 0 );},
-		getInvalid: function() {return invalid;},
-		isInvalid: function(elemname){
-			for(var i = 0; i < invalid.length; i++){
-				if(elemname == invalid[i]){ return true; }
-			}
-			return false;
-		}
-	};
-
-	// Filters are applied before fields are validated.
-	// Trim removes white space at the front and end of the fields.
-	if(profile.trim instanceof Array){
-		for(var i = 0; i < profile.trim.length; i++){
-			var elem = form[profile.trim[i]];
-			if(elem.type != "text" && elem.type != "textarea" && elem.type != "password"){ continue; }
-			elem.value = elem.value.replace(/(^\s*|\s*$)/g, "");
-		}
-	}
-	// Convert to uppercase
-	if(profile.uppercase instanceof Array){
-		for(var i = 0; i < profile.uppercase.length; i++){
-			var elem = form[profile.uppercase[i]];
-			if(elem.type != "text" && elem.type != "textarea" && elem.type != "password"){ continue; }
-			elem.value = elem.value.toUpperCase();
-		}
-	}
-	// Convert to lowercase
-	if(profile.lowercase instanceof Array){
-		for (var i = 0; i < profile.lowercase.length; i++){
-			var elem = form[profile.lowercase[i]];
-			if(elem.type != "text" && elem.type != "textarea" && elem.type != "password"){ continue; }
-			elem.value = elem.value.toLowerCase();
-		}
-	}
-	// Uppercase first letter
-	if(profile.ucfirst instanceof Array){
-		for(var i = 0; i < profile.ucfirst.length; i++){
-			var elem = form[profile.ucfirst[i]];
-			if(elem.type != "text" && elem.type != "textarea" && elem.type != "password"){ continue; }
-			elem.value = elem.value.replace(/\b\w+\b/g, function(word) { return word.substring(0,1).toUpperCase() + word.substring(1).toLowerCase(); });
-		}
-	}
-	// Remove non digits characters from the input.
-	if(profile.digit instanceof Array){
-		for(var i = 0; i < profile.digit.length; i++){
-			var elem = form[profile.digit[i]];
-			if(elem.type != "text" && elem.type != "textarea" && elem.type != "password"){ continue; }
-			elem.value = elem.value.replace(/\D/g, "");
-		}
-	}
-
-	// See if required input fields have values missing.
-	if(profile.required instanceof Array){
-		for(var i = 0; i < profile.required.length; i++){ 
-			if(!dojo.lang.isString(profile.required[i])){ continue; }
-			var elem = form[profile.required[i]];
-			// Are textbox, textarea, or password fields blank.
-			if((elem.type == "text" || elem.type == "textarea" || elem.type == "password") && /^\s*$/.test(elem.value)){	
-				missing[missing.length] = elem.name;
-			}
-			// Does drop-down box have option selected.
-			else if((elem.type == "select-one" || elem.type == "select-multiple") 
-						&& (elem.selectedIndex == -1 
-						|| /^\s*$/.test(elem.options[elem.selectedIndex].value))){
-				missing[missing.length] = elem.name;
-			}
-			// Does radio button group (or check box group) have option checked.
-			else if(elem instanceof Array){
-				var checked = false;
-				for(var j = 0; j < elem.length; j++){
-					if (elem[j].checked) { checked = true; }
-				}
-				if(!checked){	
-					missing[missing.length] = elem[0].name;
-				}
-			}
-		}
-	}
-
-	// See if checkbox groups and select boxes have x number of required values.
-	if(profile.required instanceof Array){
-		for (var i = 0; i < profile.required.length; i++){ 
-			if(!dojo.lang.isObject(profile.required[i])){ continue; }
-			var elem, numRequired;
-			for(var name in profile.required[i]){ 
-				elem = form[name]; 
-				numRequired = profile.required[i][name];
-			}
-			// case 1: elem is a check box group
-			if(elem instanceof Array){
-				var checked = 0;
-				for(var j = 0; j < elem.length; j++){
-					if(elem[j].checked){ checked++; }
-				}
-				if(checked < numRequired){	
-					missing[missing.length] = elem[0].name;
-				}
-			}
-			// case 2: elem is a select box
-			else if(elem.type == "select-multiple" ){
-				var selected = 0;
-				for(var j = 0; j < elem.options.length; j++){
-					if (elem.options[j].selected && !/^\s*$/.test(elem.options[j].value)) { selected++; }
-				}
-				if(selected < numRequired){	
-					missing[missing.length] = elem.name;
-				}
-			}
-		}
-	}
-
-	// Dependent fields are required when the target field is present (not blank).
-	// Todo: Support dependent and target fields that are radio button groups, or select drop-down lists.
-	// Todo: Make the dependency based on a specific value of the target field.
-	// Todo: allow dependent fields to have several required values, like {checkboxgroup: 3}.
-	if(dojo.lang.isObject(profile.dependencies) || dojo.lang.isObject(profile.dependancies)){
-		if(profile["dependancies"]){
-			dojo.deprecated("dojo.validate.check", "profile 'dependancies' is deprecated, please use "
-							+ "'dependencies'", "0.5");
-			profile.dependencies=profile.dependancies;
-		}
-		// properties of dependencies object are the names of dependent fields to be checked
-		for(name in profile.dependencies){
-			var elem = form[name];	// the dependent element
-			if(elem.type != "text" && elem.type != "textarea" && elem.type != "password"){ continue; } // limited support
-			if(/\S+/.test(elem.value)){ continue; }	// has a value already
-			if(results.isMissing(elem.name)){ continue; }	// already listed as missing
-			var target = form[profile.dependencies[name]];
-			if(target.type != "text" && target.type != "textarea" && target.type != "password"){ continue; }	// limited support
-			if(/^\s*$/.test(target.value)){ continue; }	// skip if blank
-			missing[missing.length] = elem.name;	// ok the dependent field is missing
-		}
-	}
-
-	// Find invalid input fields.
-	if(dojo.lang.isObject(profile.constraints)){
-		// constraint properties are the names of fields to bevalidated
-		for(name in profile.constraints){
-			var elem = form[name];
-			if(	(elem.type != "text")&&
-				(elem.type != "textarea")&&
-				(elem.type != "password")){
-				continue;
-			}
-			// skip if blank - its optional unless required, in which case it
-			// is already listed as missing.
-			if(/^\s*$/.test(elem.value)){ continue; }
-
-			var isValid = true;
-			// case 1: constraint value is validation function
-			if(dojo.lang.isFunction(profile.constraints[name])){
-				isValid = profile.constraints[name](elem.value);
-			}else if(dojo.lang.isArray(profile.constraints[name])){
-				// handle nested arrays for multiple constraints
-				if(dojo.lang.isArray(profile.constraints[name][0])){
-					for (var i=0; i<profile.constraints[name].length; i++){
-						isValid = dojo.validate.evaluateConstraint(profile, profile.constraints[name][i], name, elem);
-						if(!isValid){ break; }
-					}
-				}else{
-					// case 2: constraint value is array, first elem is function,
-					// tail is parameters
-					isValid = dojo.validate.evaluateConstraint(profile, profile.constraints[name], name, elem);
-				}
-			}
-
-			if(!isValid){	
-				invalid[invalid.length] = elem.name;
-			}
-		}
-	}
-
-	// Find unequal confirm fields and report them as Invalid.
-	if(dojo.lang.isObject(profile.confirm)){
-		for(name in profile.confirm){
-			var elem = form[name];	// the confirm element
-			var target = form[profile.confirm[name]];
-			if ( (elem.type != "text" && elem.type != "textarea" && elem.type != "password") 
-				||(target.type != elem.type)
-				||(target.value == elem.value)	// it's valid
-				||(results.isInvalid(elem.name))// already listed as invalid
-				||(/^\s*$/.test(target.value)))	// skip if blank - only confirm if target has a value
-			{
-				continue; 
-			}	
-			invalid[invalid.length] = elem.name;
-		}
-	}
-
-	return results; // Object
-}
-
-//TODO: evaluateConstraint doesn't use profile or fieldName args?
-dojo.validate.evaluateConstraint=function(profile, /*Array*/constraint, fieldName, elem){
-	// summary:
-	//	Evaluates dojo.validate.check() constraints that are specified as array
-	//	arguments
-	//
-	// description: The arrays are expected to be in the format of:
-	//      constraints:{
-	//              fieldName: [functionToCall, param1, param2, etc.],
-	//              fieldName: [[functionToCallFirst, param1],[functionToCallSecond,param2]]
-	//      }
-	// 
-	//  This function evaluates a single array function in the format of:
-	//      [functionName, argument1, argument2, etc]
-	// 
-	//  The function will be parsed out and evaluated against the incoming parameters.
-	//
-	// profile: The dojo.validate.check() profile that this evaluation is against.
-	// constraint: The single [] array of function and arguments for the function.
-	// fieldName: The form dom name of the field being validated.
-	// elem: The form element field.
-
- 	var isValidSomething = constraint[0];
-	var params = constraint.slice(1);
-	params.unshift(elem.value);
-	if(typeof isValidSomething != "undefined"){
-		return isValidSomething.apply(null, params);
-	}
-	return false; // Boolean
-}
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/validate/common.js b/continuum-webapp/src/main/webapp/struts/dojo/validate/common.js
deleted file mode 100644
index df7471e..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/validate/common.js
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
-	Copyright (c) 2004-2006, The Dojo Foundation
-	All Rights Reserved.
-
-	Licensed under the Academic Free License version 2.1 or above OR the
-	modified BSD license. For more information on Dojo licensing, see:
-
-		http://dojotoolkit.org/community/licensing.shtml
-*/
-
-dojo.provide("dojo.validate.common");
-
-dojo.require("dojo.regexp");
-
-
-dojo.validate.isText = function(/*String*/value, /*Object?*/flags){
-// summary:
-//	Checks if a string has non whitespace characters. 
-//	Parameters allow you to constrain the length.
-//
-// value: A string
-// flags: {length: Number, minlength: Number, maxlength: Number}
-//    flags.length  If set, checks if there are exactly flags.length number of characters.
-//    flags.minlength  If set, checks if there are at least flags.minlength number of characters.
-//    flags.maxlength  If set, checks if there are at most flags.maxlength number of characters.
-
-	flags = (typeof flags == "object") ? flags : {};
-
-	// test for text
-	if(/^\s*$/.test(value)){ return false; } // Boolean
-
-	// length tests
-	if(typeof flags.length == "number" && flags.length != value.length){ return false; } // Boolean
-	if(typeof flags.minlength == "number" && flags.minlength > value.length){ return false; } // Boolean
-	if(typeof flags.maxlength == "number" && flags.maxlength < value.length){ return false; } // Boolean
-
-	return true; // Boolean
-}
-
-dojo.validate.isInteger = function(/*String*/value, /*Object?*/flags){
-// summary:
-//	Validates whether a string is in an integer format
-//
-// value  A string
-// flags  {signed: Boolean|[true,false], separator: String}
-//    flags.signed  The leading plus-or-minus sign.  Can be true, false, or [true, false].
-//      Default is [true, false], (i.e. sign is optional).
-//    flags.separator  The character used as the thousands separator.  Default is no separator.
-//      For more than one symbol use an array, e.g. [",", ""], makes ',' optional.
-
-	var re = new RegExp("^" + dojo.regexp.integer(flags) + "$");
-	return re.test(value); // Boolean
-}
-
-dojo.validate.isRealNumber = function(/*String*/value, /*Object?*/flags){
-// summary:
-//	Validates whether a string is a real valued number. 
-//	Format is the usual exponential notation.
-//
-// value: A string
-// flags: {places: Number, decimal: String, exponent: Boolean|[true,false], eSigned: Boolean|[true,false], ...}
-//    flags.places  The integer number of decimal places.
-//      If not given, the decimal part is optional and the number of places is unlimited.
-//    flags.decimal  The character used for the decimal point.  Default is ".".
-//    flags.exponent  Express in exponential notation.  Can be true, false, or [true, false].
-//      Default is [true, false], (i.e. the exponential part is optional).
-//    flags.eSigned  The leading plus-or-minus sign on the exponent.  Can be true, false, 
-//      or [true, false].  Default is [true, false], (i.e. sign is optional).
-//    flags in regexp.integer can be applied.
-
-	var re = new RegExp("^" + dojo.regexp.realNumber(flags) + "$");
-	return re.test(value); // Boolean
-}
-
-dojo.validate.isCurrency = function(/*String*/value, /*Object?*/flags){
-// summary:
-//	Validates whether a string denotes a monetary value. 
-// value: A string
-// flags: {signed:Boolean|[true,false], symbol:String, placement:String, separator:String,
-//	fractional:Boolean|[true,false], decimal:String}
-//    flags.signed  The leading plus-or-minus sign.  Can be true, false, or [true, false].
-//      Default is [true, false], (i.e. sign is optional).
-//    flags.symbol  A currency symbol such as Yen "�", Pound "�", or the Euro sign "�".  
-//      Default is "$".  For more than one symbol use an array, e.g. ["$", ""], makes $ optional.
-//    flags.placement  The symbol can come "before" the number or "after".  Default is "before".
-//    flags.separator  The character used as the thousands separator. The default is ",".
-//    flags.fractional  The appropriate number of decimal places for fractional currency (e.g. cents)
-//      Can be true, false, or [true, false].  Default is [true, false], (i.e. cents are optional).
-//    flags.decimal  The character used for the decimal point.  Default is ".".
-
-	var re = new RegExp("^" + dojo.regexp.currency(flags) + "$");
-	return re.test(value); // Boolean
-}
-
-dojo.validate.isInRange = function(/*String*/value, /*Object?*/flags){
-//summary:
-//	Validates whether a string denoting an integer, 
-//	real number, or monetary value is between a max and min. 
-//
-// value: A string
-// flags: {max:Number, min:Number, decimal:String}
-//    flags.max  A number, which the value must be less than or equal to for the validation to be true.
-//    flags.min  A number, which the value must be greater than or equal to for the validation to be true.
-//    flags.decimal  The character used for the decimal point.  Default is ".".
-
-	//stripping the seperator allows NaN to perform as expected, if no separator, we assume ','
-	//once i18n support is ready for this, instead of assuming, we default to i18n's recommended value
-	value = value.replace((dojo.lang.has(flags,'separator'))?flags.separator:',','');
-	if(isNaN(value)){
-		return false; // Boolean
-	}
-	// assign default values to missing paramters
-	flags = (typeof flags == "object") ? flags : {};
-	var max = (typeof flags.max == "number") ? flags.max : Infinity;
-	var min = (typeof flags.min == "number") ? flags.min : -Infinity;
-	var dec = (typeof flags.decimal == "string") ? flags.decimal : ".";
-	
-	// splice out anything not part of a number
-	var pattern = "[^" + dec + "\\deE+-]";
-	value = value.replace(RegExp(pattern, "g"), "");
-
-	// trim ends of things like e, E, or the decimal character
-	value = value.replace(/^([+-]?)(\D*)/, "$1");
-	value = value.replace(/(\D*)$/, "");
-
-	// replace decimal with ".". The minus sign '-' could be the decimal!
-	pattern = "(\\d)[" + dec + "](\\d)";
-	value = value.replace(RegExp(pattern, "g"), "$1.$2");
-
-	value = Number(value);
-	if ( value < min || value > max ) { return false; } // Boolean
-
-	return true; // Boolean
-}
-
-dojo.validate.isNumberFormat = function(/*String*/value, /*Object?*/flags){
-// summary:
-//	Validates any sort of number based format
-//
-// description:
-//	Use it for phone numbers, social security numbers, zip-codes, etc.
-//	The value can be validated against one format or one of multiple formats.
-//
-//  Format
-//    #        Stands for a digit, 0-9.
-//    ?        Stands for an optional digit, 0-9 or nothing.
-//    All other characters must appear literally in the expression.
-//
-//  Example   
-//    "(###) ###-####"       ->   (510) 542-9742
-//    "(###) ###-#### x#???" ->   (510) 542-9742 x153
-//    "###-##-####"          ->   506-82-1089       i.e. social security number
-//    "#####-####"           ->   98225-1649        i.e. zip code
-//
-// value: A string
-// flags: {format:String}
-//    flags.format  A string or an Array of strings for multiple formats.
-
-	var re = new RegExp("^" + dojo.regexp.numberFormat(flags) + "$", "i");
-	return re.test(value); // Boolean
-}
-
-dojo.validate.isValidLuhn = function(/*String*/value){
-//summary: Compares value against the Luhn algorithm to verify its integrity
-	var sum, parity, curDigit;
-	if(typeof value!='string'){
-		value = String(value);
-	}
-	value = value.replace(/[- ]/g,''); //ignore dashes and whitespaces
-	parity = value.length%2;
-	sum=0;
-	for(var i=0;i<value.length;i++){
-		curDigit = parseInt(value.charAt(i));
-		if(i%2==parity){
-			curDigit*=2;
-		}
-		if(curDigit>9){
-			curDigit-=9;
-		}
-		sum+=curDigit;
-	}
-	return !(sum%10);
-}
-
-/**
-	Procedural API Description
-
-		The main aim is to make input validation expressible in a simple format.
-		You define profiles which declare the required and optional fields and any constraints they might have.
-		The results are provided as an object that makes it easy to handle missing and invalid input.
-
-	Usage
-
-		var results = dojo.validate.check(form, profile);
-
-	Profile Object
-
-		var profile = {
-			// filters change the field value and are applied before validation.
-			trim: ["tx1", "tx2"],
-			uppercase: ["tx9"],
-			lowercase: ["tx5", "tx6", "tx7"],
-			ucfirst: ["tx10"],
-			digit: ["tx11"],
-
-			// required input fields that are blank will be reported missing.
-			// required radio button groups and drop-down lists with no selection will be reported missing.
-			// checkbox groups and selectboxes can be required to have more than one value selected.
-			// List required fields by name and use this notation to require more than one value: {checkboxgroup: 2}, {selectboxname: 3}.
-			required: ["tx7", "tx8", "pw1", "ta1", "rb1", "rb2", "cb3", "s1", {"doubledip":2}, {"tripledip":3}],
-
-			// dependant/conditional fields are required if the target field is present and not blank.
-			// At present only textbox, password, and textarea fields are supported.
-			dependencies:	{
-				cc_exp: "cc_no",	
-				cc_type: "cc_no",	
-			},
-
-			// Fields can be validated using any boolean valued function.  
-			// Use arrays to specify parameters in addition to the field value.
-			constraints: {
-				field_name1: myValidationFunction,
-				field_name2: dojo.validate.isInteger,
-				field_name3: [myValidationFunction, additional parameters],
-				field_name4: [dojo.validate.isValidDate, "YYYY.MM.DD"],
-				field_name5: [dojo.validate.isEmailAddress, false, true],
-			},
-
-			// Confirm is a sort of conditional validation.
-			// It associates each field in its property list with another field whose value should be equal.
-			// If the values are not equal, the field in the property list is reported as Invalid. Unless the target field is blank.
-			confirm: {
-				email_confirm: "email",	
-				pw2: "pw1",	
-			}
-		};
-
-	Results Object
-
-		isSuccessful(): Returns true if there were no invalid or missing fields, else it returns false.
-		hasMissing():  Returns true if the results contain any missing fields.
-		getMissing():  Returns a list of required fields that have values missing.
-		isMissing(field):  Returns true if the field is required and the value is missing.
-		hasInvalid():  Returns true if the results contain fields with invalid data.
-		getInvalid():  Returns a list of fields that have invalid values.
-		isInvalid(field):  Returns true if the field has an invalid value.
-
-*/
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/validate/creditCard.js b/continuum-webapp/src/main/webapp/struts/dojo/validate/creditCard.js
deleted file mode 100644
index 671a069..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/validate/creditCard.js
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
-	Copyright (c) 2004-2006, The Dojo Foundation
-	All Rights Reserved.
-
-	Licensed under the Academic Free License version 2.1 or above OR the
-	modified BSD license. For more information on Dojo licensing, see:
-
-		http://dojotoolkit.org/community/licensing.shtml
-*/
-
-dojo.provide('dojo.validate.creditCard');
-
-dojo.require("dojo.lang.common");
-dojo.require("dojo.validate.common");
-
-/*
-	Validates Credit Cards using account number rules in conjunction with the Luhn algorightm
-	
- */
-
-dojo.validate.isValidCreditCard = function(value,ccType){
-	//checks if type matches the # scheme, and if Luhn checksum is accurate (unless its an Enroute card, the checkSum is skipped)
-	if(value&&ccType&&((ccType.toLowerCase()=='er'||dojo.validate.isValidLuhn(value))&&(dojo.validate.isValidCreditCardNumber(value,ccType.toLowerCase())))){
-			return true;
-	}
-	return false;
-}
-dojo.validate.isValidCreditCardNumber = function(value,ccType) {
-	//only checks if the # matches the pattern for that card or any card types if none is specified
-	//value == CC #, white spaces and dashes are ignored
-	//ccType is of the values in cardinfo -- if Omitted it it returns a | delimited string of matching card types, or false if no matches found
-	if(typeof value!='string'){
-		value = String(value);
-	}
-	value = value.replace(/[- ]/g,''); //ignore dashes and whitespaces
-	/* 	FIXME: not sure on all the abbreviations for credit cards,below is what each stands for atleast to my knowledge
-		mc: Mastercard
-		ec: Eurocard
-		vi: Visa
-		ax: American Express
-		dc: Diners Club
-		bl: Carte Blanch
-		di: Discover
-		jcb: JCB
-		er: Enroute
-	 */
-	var results=[];
-	var cardinfo = {
-		'mc':'5[1-5][0-9]{14}','ec':'5[1-5][0-9]{14}','vi':'4([0-9]{12}|[0-9]{15})',
-		'ax':'3[47][0-9]{13}', 'dc':'3(0[0-5][0-9]{11}|[68][0-9]{12})',
-		'bl':'3(0[0-5][0-9]{11}|[68][0-9]{12})','di':'6011[0-9]{12}',
-		'jcb':'(3[0-9]{15}|(2131|1800)[0-9]{11})','er':'2(014|149)[0-9]{11}'
-	};
-	if(ccType&&dojo.lang.has(cardinfo,ccType.toLowerCase())){
-		return Boolean(value.match(cardinfo[ccType.toLowerCase()])); // boolean
-	}else{
-		for(var p in cardinfo){
-			if(value.match('^'+cardinfo[p]+'$')!=null){
-				results.push(p);
-			}
-		}
-		return (results.length)?results.join('|'):false; // string | boolean
-	}	
-}
-
-dojo.validate.isValidCvv = function(value, ccType) {
-	if(typeof value!='string'){
-		value=String(value);
-	}
-	var format;
-	switch (ccType.toLowerCase()){
-		case 'mc':
-		case 'ec':
-		case 'vi':
-		case 'di':
-			format = '###';
-			break;
-		case 'ax':
-			format = '####';
-			break;
-		default:
-			return false;
-	}
-	var flags = {format:format};
-	//FIXME? Why does isNumberFormat take an object for flags when its only parameter is either a string or an array inside the object?
-	if ((value.length == format.length)&&(dojo.validate.isNumberFormat(value, flags))){
-		return true;
-	}
-	return false;
-}
\ No newline at end of file
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/validate/datetime.js b/continuum-webapp/src/main/webapp/struts/dojo/validate/datetime.js
deleted file mode 100644
index 1ae9494..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/validate/datetime.js
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
-	Copyright (c) 2004-2006, The Dojo Foundation
-	All Rights Reserved.
-
-	Licensed under the Academic Free License version 2.1 or above OR the
-	modified BSD license. For more information on Dojo licensing, see:
-
-		http://dojotoolkit.org/community/licensing.shtml
-*/
-
-dojo.provide("dojo.validate.datetime");
-dojo.require("dojo.validate.common");
-
-/**
-  Validates a time value in any International format.
-  The value can be validated against one format or one of multiple formats.
-
-  Format
-  h        12 hour, no zero padding.
-  hh       12 hour, has leading zero.
-  H        24 hour, no zero padding.
-  HH       24 hour, has leading zero.
-  m        minutes, no zero padding.
-  mm       minutes, has leading zero.
-  s        seconds, no zero padding.
-  ss       seconds, has leading zero.
-  All other characters must appear literally in the expression.
-
-  Example
-    "h:m:s t"  ->   2:5:33 PM
-    "HH:mm:ss" ->  14:05:33
-
-  @param value  A string.
-  @param flags  An object.
-    flags.format  A string or an array of strings.  Default is "h:mm:ss t".
-    flags.amSymbol  The symbol used for AM.  Default is "AM".
-    flags.pmSymbol  The symbol used for PM.  Default is "PM".
-  @return  true or false
-*/
-dojo.validate.isValidTime = function(value, flags) {
-	dojo.deprecated("dojo.validate.datetime", "use dojo.date.parse instead", "0.5");
-	var re = new RegExp("^" + dojo.regexp.time(flags) + "$", "i");
-	return re.test(value);
-}
-
-/**
-  Validates 12-hour time format.
-  Zero-padding is not allowed for hours, required for minutes and seconds.
-  Seconds are optional.
-
-  @param value  A string.
-  @return  true or false
-*/
-dojo.validate.is12HourTime = function(value) {
-	dojo.deprecated("dojo.validate.datetime", "use dojo.date.parse instead", "0.5");
-	return dojo.validate.isValidTime(value, {format: ["h:mm:ss t", "h:mm t"]});
-}
-
-/**
-  Validates 24-hour military time format.
-  Zero-padding is required for hours, minutes, and seconds.
-  Seconds are optional.
-
-  @param value  A string.
-  @return  true or false
-*/
-dojo.validate.is24HourTime = function(value) {
-	dojo.deprecated("dojo.validate.datetime", "use dojo.date.parse instead", "0.5");
-	return dojo.validate.isValidTime(value, {format: ["HH:mm:ss", "HH:mm"]} );
-}
-
-/**
-  Returns true if the date conforms to the format given and is a valid date. Otherwise returns false.
-
-  @param dateValue  A string for the date.
-  @param format  A string, default is  "MM/DD/YYYY".
-  @return  true or false
-
-  Accepts any type of format, including ISO8601.
-  All characters in the format string are treated literally except the following tokens:
-
-  YYYY - matches a 4 digit year
-  M - matches a non zero-padded month
-  MM - matches a zero-padded month
-  D -  matches a non zero-padded date
-  DD -  matches a zero-padded date
-  DDD -  matches an ordinal date, 001-365, and 366 on leapyear
-  ww - matches week of year, 01-53
-  d - matches day of week, 1-7
-
-  Examples: These are all today's date.
-
-  Date          Format
-  2005-W42-3    YYYY-Www-d
-  2005-292      YYYY-DDD
-  20051019      YYYYMMDD
-  10/19/2005    M/D/YYYY
-  19.10.2005    D.M.YYYY
-*/
-dojo.validate.isValidDate = function(dateValue, format) {
-	dojo.deprecated("dojo.validate.datetime", "use dojo.date.parse instead", "0.5");
-	// Default is the American format
-	if (typeof format == "object" && typeof format.format == "string"){ format = format.format; }
-	if (typeof format != "string") { format = "MM/DD/YYYY"; }
-
-	// Create a literal regular expression based on format
-	var reLiteral = format.replace(/([$^.*+?=!:|\/\\\(\)\[\]\{\}])/g, "\\$1");
-
-	// Convert all the tokens to RE elements
-	reLiteral = reLiteral.replace( "YYYY", "([0-9]{4})" );
-	reLiteral = reLiteral.replace( "MM", "(0[1-9]|10|11|12)" );
-	reLiteral = reLiteral.replace( "M", "([1-9]|10|11|12)" );
-	reLiteral = reLiteral.replace( "DDD", "(00[1-9]|0[1-9][0-9]|[12][0-9][0-9]|3[0-5][0-9]|36[0-6])" );
-	reLiteral = reLiteral.replace( "DD", "(0[1-9]|[12][0-9]|30|31)" );
-	reLiteral = reLiteral.replace( "D", "([1-9]|[12][0-9]|30|31)" );
-	reLiteral = reLiteral.replace( "ww", "(0[1-9]|[1-4][0-9]|5[0-3])" );
-	reLiteral = reLiteral.replace( "d", "([1-7])" );
-
-	// Anchor pattern to begining and end of string
-	reLiteral = "^" + reLiteral + "$";
-
-	// Dynamic RE that parses the original format given
-	var re = new RegExp(reLiteral);
-	
-	// Test if date is in a valid format
-	if (!re.test(dateValue))  return false;
-
-	// Parse date to get elements and check if date is valid
-	// Assume valid values for date elements not given.
-	var year = 0, month = 1, date = 1, dayofyear = 1, week = 1, day = 1;
-
-	// Capture tokens
-	var tokens = format.match( /(YYYY|MM|M|DDD|DD|D|ww|d)/g );
-
-	// Capture date values
-	var values = re.exec(dateValue);
-
-	// Match up tokens with date values
-	for (var i = 0; i < tokens.length; i++) {
-		switch (tokens[i]) {
-		case "YYYY":
-			year = Number(values[i+1]); break;
-		case "M":
-		case "MM":
-			month = Number(values[i+1]); break;
-		case "D":
-		case "DD":
-			date = Number(values[i+1]); break;
-		case "DDD":
-			dayofyear = Number(values[i+1]); break;
-		case "ww":
-			week = Number(values[i+1]); break;
-		case "d":
-			day = Number(values[i+1]); break;
-		}
-	}
-
-	// Leap years are divisible by 4, but not by 100, unless by 400
-	var leapyear = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
-
-	// 31st of a month with 30 days
-	if (date == 31 && (month == 4 || month == 6 || month == 9 || month == 11)) return false; 
-
-	// February 30th or 31st
-	if (date >= 30 && month == 2) return false; 
-
-	// February 29th outside a leap year
-	if (date == 29 && month == 2 && !leapyear) return false; 
-	if (dayofyear == 366 && !leapyear)  return false;
-
-	return true;
-}
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/validate/de.js b/continuum-webapp/src/main/webapp/struts/dojo/validate/de.js
deleted file mode 100644
index 43be273..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/validate/de.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
-	Copyright (c) 2004-2006, The Dojo Foundation
-	All Rights Reserved.
-
-	Licensed under the Academic Free License version 2.1 or above OR the
-	modified BSD license. For more information on Dojo licensing, see:
-
-		http://dojotoolkit.org/community/licensing.shtml
-*/
-
-dojo.provide("dojo.validate.de");
-dojo.require("dojo.validate.common");
-
-dojo.validate.isGermanCurrency = function(/*String*/value) {
-	//summary: checks to see if 'value' is a valid representation of German currency (Euros)
-	var flags = {
-		symbol: "\u20AC",
-		placement: "after",
-		signPlacement: "begin", //TODO: this is really locale-dependent.  Will get fixed in v0.5 currency rewrite. 
-		decimal: ",",
-		separator: "."
-	};
-	return dojo.validate.isCurrency(value, flags); // Boolean
-}
-
-
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/validate/jp.js b/continuum-webapp/src/main/webapp/struts/dojo/validate/jp.js
deleted file mode 100644
index a46fc45..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/validate/jp.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
-	Copyright (c) 2004-2006, The Dojo Foundation
-	All Rights Reserved.
-
-	Licensed under the Academic Free License version 2.1 or above OR the
-	modified BSD license. For more information on Dojo licensing, see:
-
-		http://dojotoolkit.org/community/licensing.shtml
-*/
-
-dojo.provide("dojo.validate.jp");
-dojo.require("dojo.validate.common");
-
-dojo.validate.isJapaneseCurrency = function(/*String*/value) {
-	//summary: checks to see if 'value' is a valid representation of Japanese currency
-	var flags = {
-		symbol: "\u00a5",
-		fractional: false
-	};
-	return dojo.validate.isCurrency(value, flags); // Boolean
-}
-
-
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/validate/us.js b/continuum-webapp/src/main/webapp/struts/dojo/validate/us.js
deleted file mode 100644
index 09f5b3c..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/validate/us.js
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
-	Copyright (c) 2004-2006, The Dojo Foundation
-	All Rights Reserved.
-
-	Licensed under the Academic Free License version 2.1 or above OR the
-	modified BSD license. For more information on Dojo licensing, see:
-
-		http://dojotoolkit.org/community/licensing.shtml
-*/
-
-dojo.provide("dojo.validate.us");
-dojo.require("dojo.validate.common");
-
-dojo.validate.us.isCurrency = function(/*String*/value, /*Object?*/flags){
-	// summary: Validates U.S. currency
-	// value: the representation to check
-	// flags: flags in validate.isCurrency can be applied.
-	return dojo.validate.isCurrency(value, flags); // Boolean
-}
-
-
-dojo.validate.us.isState = function(/*String*/value, /*Object?*/flags){
-	// summary: Validates US state and territory abbreviations.
-	//
-	// value: A two character string
-	// flags: An object
-	//    flags.allowTerritories  Allow Guam, Puerto Rico, etc.  Default is true.
-	//    flags.allowMilitary  Allow military 'states', e.g. Armed Forces Europe (AE).  Default is true.
-
-	var re = new RegExp("^" + dojo.regexp.us.state(flags) + "$", "i");
-	return re.test(value); // Boolean
-}
-
-dojo.validate.us.isPhoneNumber = function(/*String*/value){
-	// summary: Validates 10 US digit phone number for several common formats
-	// value: The telephone number string
-
-	var flags = {
-		format: [
-			"###-###-####",
-			"(###) ###-####",
-			"(###) ### ####",
-			"###.###.####",
-			"###/###-####",
-			"### ### ####",
-			"###-###-#### x#???",
-			"(###) ###-#### x#???",
-			"(###) ### #### x#???",
-			"###.###.#### x#???",
-			"###/###-#### x#???",
-			"### ### #### x#???",
-			"##########"
-		]
-	};
-
-	return dojo.validate.isNumberFormat(value, flags); // Boolean
-}
-
-dojo.validate.us.isSocialSecurityNumber = function(/*String*/value){
-// summary: Validates social security number
-	var flags = {
-		format: [
-			"###-##-####",
-			"### ## ####",
-			"#########"
-		]
-	};
-
-	return dojo.validate.isNumberFormat(value, flags); // Boolean
-}
-
-dojo.validate.us.isZipCode = function(/*String*/value){
-// summary: Validates U.S. zip-code
-	var flags = {
-		format: [
-			"#####-####",
-			"##### ####",
-			"#########",
-			"#####"
-		]
-	};
-
-	return dojo.validate.isNumberFormat(value, flags); // Boolean
-}
diff --git a/continuum-webapp/src/main/webapp/struts/dojo/validate/web.js b/continuum-webapp/src/main/webapp/struts/dojo/validate/web.js
deleted file mode 100644
index f6f2a9c..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojo/validate/web.js
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
-	Copyright (c) 2004-2006, The Dojo Foundation
-	All Rights Reserved.
-
-	Licensed under the Academic Free License version 2.1 or above OR the
-	modified BSD license. For more information on Dojo licensing, see:
-
-		http://dojotoolkit.org/community/licensing.shtml
-*/
-
-dojo.provide("dojo.validate.web");
-dojo.require("dojo.validate.common");
-
-dojo.validate.isIpAddress = function(/*String*/value, /*Object?*/flags) {
-	// summary: Validates an IP address
-	//
-	// description:
-	//  Supports 5 formats for IPv4: dotted decimal, dotted hex, dotted octal, decimal and hexadecimal.
-	//  Supports 2 formats for Ipv6.
-	//
-	// value  A string.
-	// flags  An object.  All flags are boolean with default = true.
-	//    flags.allowDottedDecimal  Example, 207.142.131.235.  No zero padding.
-	//    flags.allowDottedHex  Example, 0x18.0x11.0x9b.0x28.  Case insensitive.  Zero padding allowed.
-	//    flags.allowDottedOctal  Example, 0030.0021.0233.0050.  Zero padding allowed.
-	//    flags.allowDecimal  Example, 3482223595.  A decimal number between 0-4294967295.
-	//    flags.allowHex  Example, 0xCF8E83EB.  Hexadecimal number between 0x0-0xFFFFFFFF.
-	//      Case insensitive.  Zero padding allowed.
-	//    flags.allowIPv6   IPv6 address written as eight groups of four hexadecimal digits.
-	//    flags.allowHybrid   IPv6 address written as six groups of four hexadecimal digits
-	//      followed by the usual 4 dotted decimal digit notation of IPv4. x:x:x:x:x:x:d.d.d.d
-
-	var re = new RegExp("^" + dojo.regexp.ipAddress(flags) + "$", "i");
-	return re.test(value); // Boolean
-}
-
-
-dojo.validate.isUrl = function(/*String*/value, /*Object?*/flags) {
-	// summary: Checks if a string could be a valid URL
-	// value: A string
-	// flags: An object
-	//    flags.scheme  Can be true, false, or [true, false]. 
-	//      This means: required, not allowed, or either.
-	//    flags in regexp.host can be applied.
-	//    flags in regexp.ipAddress can be applied.
-	//    flags in regexp.tld can be applied.
-
-	var re = new RegExp("^" + dojo.regexp.url(flags) + "$", "i");
-	return re.test(value); // Boolean
-}
-
-dojo.validate.isEmailAddress = function(/*String*/value, /*Object?*/flags) {
-	// summary: Checks if a string could be a valid email address
-	//
-	// value: A string
-	// flags: An object
-	//    flags.allowCruft  Allow address like <mailto:foo@yahoo.com>.  Default is false.
-	//    flags in regexp.host can be applied.
-	//    flags in regexp.ipAddress can be applied.
-	//    flags in regexp.tld can be applied.
-
-	var re = new RegExp("^" + dojo.regexp.emailAddress(flags) + "$", "i");
-	return re.test(value); // Boolean
-}
-
-dojo.validate.isEmailAddressList = function(/*String*/value, /*Object?*/flags) {
-	// summary: Checks if a string could be a valid email address list.
-	//
-	// value  A string.
-	// flags  An object.
-	//    flags.listSeparator  The character used to separate email addresses.  Default is ";", ",", "\n" or " ".
-	//    flags in regexp.emailAddress can be applied.
-	//    flags in regexp.host can be applied.
-	//    flags in regexp.ipAddress can be applied.
-	//    flags in regexp.tld can be applied.
-
-	var re = new RegExp("^" + dojo.regexp.emailAddressList(flags) + "$", "i");
-	return re.test(value); // Boolean
-}
-
-dojo.validate.getEmailAddressList = function(/*String*/value, /*Object?*/flags) {
-	// summary: Check if value is an email address list. If an empty list
-	//  is returned, the value didn't pass the test or it was empty.
-	//
-	// value: A string
-	// flags: An object (same as dojo.validate.isEmailAddressList)
-
-	if(!flags) { flags = {}; }
-	if(!flags.listSeparator) { flags.listSeparator = "\\s;,"; }
-
-	if ( dojo.validate.isEmailAddressList(value, flags) ) {
-		return value.split(new RegExp("\\s*[" + flags.listSeparator + "]\\s*")); // Array
-	}
-	return []; // Array
-}
diff --git a/continuum-webapp/src/main/webapp/struts/dojoRequire.js b/continuum-webapp/src/main/webapp/struts/dojoRequire.js
deleted file mode 100644
index 9eadb36..0000000
--- a/continuum-webapp/src/main/webapp/struts/dojoRequire.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- *
- * 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.
- */
-
-dojo.hostenv.writeIncludes(); // not needed, but allows the Venkman debugger to work with the includes
\ No newline at end of file
diff --git a/continuum-webapp/src/main/webapp/struts/optiontransferselect.js b/continuum-webapp/src/main/webapp/struts/optiontransferselect.js
deleted file mode 100644
index ac7d3c6..0000000
--- a/continuum-webapp/src/main/webapp/struts/optiontransferselect.js
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- *
- * 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.
- */
-
-function moveSelectedOptions(objSourceElement, objTargetElement, toSort, notMove1, notMove2) {
-    var test1 = compile(notMove1);
-    var test2 = compile(notMove2);
-    moveOptions(objSourceElement, objTargetElement, toSort, 
-        function(opt) {
-            return (opt.selected && !test1(opt.value) && !test2(opt.value));
-        }
-    );
-}
-
-function moveAllOptions(objSourceElement, objTargetElement, toSort, notMove1, notMove2) {
-    var test1 = compile(notMove1);
-    var test2 = compile(notMove2);
-    moveOptions(objSourceElement, objTargetElement, toSort, 
-        function(opt) {
-            return (!test1(opt.value) && !test2(opt.value));
-        }
-    );
-}
-
-function compile(ptn) {
-    if (ptn != undefined) {
-    	if (ptn == '' || !window.RegExp) {
-            return function(val) { return val == ptn; }
-        } else {
-            var reg = new RegExp(ptn);
-            return function (val) { 
-                if (val == '') { // ignore empty option added by template 
-                	return true;
-                }
-            	return reg.test(val); }
-        }
-    }
-    return function(val) { return false; }
-}    
-
-function moveOptions(objSourceElement, objTargetElement, toSort, chooseFunc) {
-    var aryTempSourceOptions = new Array();
-    var aryTempTargetOptions = new Array();
-    var x = 0;
-
-    //looping through source element to find selected options
-    for (var i = 0; i < objSourceElement.length; i++) {
-        if (chooseFunc(objSourceElement.options[i])) {
-            //need to move this option to target element
-            var intTargetLen = objTargetElement.length++;
-            objTargetElement.options[intTargetLen].text =   objSourceElement.options[i].text;
-            objTargetElement.options[intTargetLen].value =  objSourceElement.options[i].value;
-        }
-        else {
-            //storing options that stay to recreate select element
-            var objTempValues = new Object();
-            objTempValues.text = objSourceElement.options[i].text;
-            objTempValues.value = objSourceElement.options[i].value;
-            aryTempSourceOptions[x] = objTempValues;
-            x++;
-        }
-    }
-
-    //sorting and refilling target list
-    for (var i = 0; i < objTargetElement.length; i++) {
-        var objTempValues = new Object();
-        objTempValues.text = objTargetElement.options[i].text;
-        objTempValues.value = objTargetElement.options[i].value;
-        aryTempTargetOptions[i] = objTempValues;
-    }
-    
-    if (toSort) {
-        aryTempTargetOptions.sort(sortByText);
-    }    
-    
-    for (var i = 0; i < objTargetElement.length; i++) {
-        objTargetElement.options[i].text = aryTempTargetOptions[i].text;
-        objTargetElement.options[i].value = aryTempTargetOptions[i].value;
-        objTargetElement.options[i].selected = false;
-    }   
-    
-    //resetting length of source
-    objSourceElement.length = aryTempSourceOptions.length;
-    //looping through temp array to recreate source select element
-    for (var i = 0; i < aryTempSourceOptions.length; i++) {
-        objSourceElement.options[i].text = aryTempSourceOptions[i].text;
-        objSourceElement.options[i].value = aryTempSourceOptions[i].value;
-        objSourceElement.options[i].selected = false;
-    }
-}
-
-function sortByText(a, b) {
-    if (a.text < b.text) {return -1}
-    if (a.text > b.text) {return 1}
-    return 0;
-}
-
-function selectAllOptionsExceptSome(objTargetElement, type, ptn) {
-    var test = compile(ptn);
-    for (var i = 0; i < objTargetElement.length; i++) {
-        var opt = objTargetElement.options[i];
-        if ((type == 'key' && !test(opt.value)) ||
-              (type == 'text' && !test(opt.text))) {
-            opt.selected = true;
-        } else {
-            opt.selected = false;
-        }    
-    }
-    return false;
-}
-
-function selectAllOptions(objTargetElement) {
-    for (var i = 0; i < objTargetElement.length; i++) {
-        if (objTargetElement.options[i].value != '') {
-            objTargetElement.options[i].selected = true;    
-        }    
-    }
-    return false;
-}
-
-function moveOptionUp(objTargetElement, type, ptn) {
-	var test = compile(ptn);
-	for (i=0; i<objTargetElement.length; i++) {
-		if (objTargetElement[i].selected) {
-			var v;
-			if (i != 0 && !objTargetElement[i-1].selected) {
-		    	if (type == 'key') {
-		    		v = objTargetElement[i-1].value
-		    	}
-		    	else {
-		    		v = objTargetElement[i-1].text;
-		    	}
-				if (!test(v)) {
-					swapOptions(objTargetElement,i,i-1);
-				}
-		    }
-		}
-	}
-}
-
-function moveOptionDown(objTargetElement, type, ptn) {
-	var test = compile(ptn);
-	for (i=(objTargetElement.length-1); i>= 0; i--) {
-		if (objTargetElement[i].selected) {
-			var v;
-			if ((i != (objTargetElement.length-1)) && !objTargetElement[i+1].selected) {
-		    	if (type == 'key') {
-		    		v = objTargetElement[i].value
-		    	}
-		    	else {
-		    		v = objTargetElement[i].text;
-		    	}
-				if (!test(v)) {
-					swapOptions(objTargetElement,i,i+1);
-				}
-		    }
-		}
-	}
-}
-
-function swapOptions(objTargetElement, first, second) {
-	var opt = objTargetElement.options;
-	var temp = new Option(opt[first].text, opt[first].value, opt[first].defaultSelected, opt[first].selected);
-	var temp2= new Option(opt[second].text, opt[second].value, opt[second].defaultSelected, opt[second].selected);
-	opt[first] = temp2;
-	opt[second] = temp;
-}
diff --git a/continuum-webapp/src/main/webapp/struts/validation.js b/continuum-webapp/src/main/webapp/struts/validation.js
deleted file mode 100644
index cd66b25..0000000
--- a/continuum-webapp/src/main/webapp/struts/validation.js
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- *
- * 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.
- */
-
-function clearErrorMessages(form) {
-    clearErrorMessagesXHTML(form);
-}
-
-function clearErrorMessagesXHTML(form) {
-
-    // get field table
-    var table;
-    for (var i = 0; i < form.childNodes.length; i++) {
-        if (form.childNodes[i].tagName != null && form.childNodes[i].tagName.toLowerCase() == 'table') {
-            table = form.childNodes[i];
-            break;
-        }
-    }
-
-    if (table == null) {
-        return;
-    }
-
-    // clear out any rows with an "errorFor" attribute
-    var rows = table.rows;
-    if (rows == null){
-        return;
-    }
-
-    var rowsToDelete = new Array();
-    for(var i = 0; i < rows.length; i++) {
-        var r = rows[i];
-        // allow blank errorFor values on dojo markup
-        if (r.getAttribute("errorFor") != null) {
-            rowsToDelete.push(r);
-        }
-    }
-
-    // now delete the rows
-    for (var i = 0; i < rowsToDelete.length; i++) {
-        var r = rowsToDelete[i];
-        table.deleteRow(r.rowIndex);
-        //table.removeChild(rowsToDelete[i]); 
-    }
-}
-
-function clearErrorLabels(form) {
-    clearErrorLabelsXHTML(form);
-}
-
-function clearErrorLabelsXHTML(form) {
-    // set all labels back to the normal class
-    var elements = form.elements;
-    for (var i = 0; i < elements.length; i++) {
-
-        var parentEl = elements[i];
-        // search for the parent table row, abort if the form is reached
-        // the form may contain "non-wrapped" inputs inserted by Dojo
-        while (parentEl.nodeName.toUpperCase() != "TR" && parentEl.nodeName.toUpperCase() != "FORM") {
-            parentEl = parentEl.parentNode;
-        }
-        if (parentEl.nodeName.toUpperCase() == "FORM") {
-            parentEl = null;
-        }
-
-         //if labelposition is 'top' the label is on the row above
-        if(parentEl && parentEl.cells) {
-          var labelRow = parentEl.cells.length > 1 ? parentEl : StrutsUtils.previousElement(parentEl, "tr");
-          if (labelRow) {
-              var cells = labelRow.cells;
-              if (cells && cells.length >= 1) {
-                  var label = cells[0].getElementsByTagName("label")[0];
-                  if (label) {
-                      label.setAttribute("class", "label");
-                      label.setAttribute("className", "label"); //ie hack cause ie does not support setAttribute
-                  }
-              }
-          }
-        }
-    }
-
-}
-
-function addError(e, errorText) {
-    addErrorXHTML(e, errorText);
-}
-
-function addErrorXHTML(e, errorText) {
-    try {
-        var row = (e.type ? e : e[0]);
-        while(row.nodeName.toUpperCase() != "TR") {
-            row = row.parentNode;
-        }
-        var table = row.parentNode;
-        var error = document.createTextNode(errorText);
-        var tr = document.createElement("tr");
-        var td = document.createElement("td");
-        var span = document.createElement("span");
-        td.align = "center";
-        td.valign = "top";
-        td.colSpan = 2;
-        span.setAttribute("class", "errorMessage");
-        span.setAttribute("className", "errorMessage"); //ie hack cause ie does not support setAttribute
-        span.appendChild(error);
-        td.appendChild(span);
-        tr.appendChild(td);
-        tr.setAttribute("errorFor", e.id);
-        table.insertBefore(tr, row);
-
-        // update the label too
-        //if labelposition is 'top' the label is on the row above
-        var labelRow = row.cells.length > 1 ? row : StrutsUtils.previousElement(tr, "tr");
-        var label = labelRow.cells[0].getElementsByTagName("label")[0];
-        label.setAttribute("class", "errorLabel");
-        label.setAttribute("className", "errorLabel"); //ie hack cause ie does not support setAttribute
-    } catch (e) {
-        alert(e);
-    }
-}
diff --git a/continuum-webapp/src/test/java/org/apache/continuum/web/action/AbstractActionTest.java b/continuum-webapp/src/test/java/org/apache/continuum/web/action/AbstractActionTest.java
new file mode 100644
index 0000000..9bccb54
--- /dev/null
+++ b/continuum-webapp/src/test/java/org/apache/continuum/web/action/AbstractActionTest.java
@@ -0,0 +1,52 @@
+package org.apache.continuum.web.action;
+
+/*
+ * 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 com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.config.ConfigurationManager;
+import com.opensymphony.xwork2.config.providers.XWorkConfigurationProvider;
+import com.opensymphony.xwork2.inject.Container;
+import com.opensymphony.xwork2.util.ValueStack;
+import com.opensymphony.xwork2.util.ValueStackFactory;
+import org.jmock.MockObjectTestCase;
+
+public abstract class AbstractActionTest
+    extends MockObjectTestCase
+{
+    protected void setUp()
+        throws Exception
+    {
+        if ( ActionContext.getContext() == null )
+        {
+            // This fix allow initialization of ActionContext.getContext() to avoid NPE
+
+            ConfigurationManager configurationManager = new ConfigurationManager();
+            configurationManager.addContainerProvider( new XWorkConfigurationProvider() );
+            com.opensymphony.xwork2.config.Configuration config = configurationManager.getConfiguration();
+            Container container = config.getContainer();
+
+            ValueStack stack = container.getInstance( ValueStackFactory.class ).createValueStack();
+            stack.getContext().put( ActionContext.CONTAINER, container );
+            ActionContext.setContext( new ActionContext( stack.getContext() ) );
+
+            assertNotNull( ActionContext.getContext() );
+        }
+    }
+}
diff --git a/continuum-webapp/src/test/java/org/apache/continuum/web/action/AbstractReleaseActionTest.java b/continuum-webapp/src/test/java/org/apache/continuum/web/action/AbstractReleaseActionTest.java
new file mode 100644
index 0000000..4b69379
--- /dev/null
+++ b/continuum-webapp/src/test/java/org/apache/continuum/web/action/AbstractReleaseActionTest.java
@@ -0,0 +1,157 @@
+package org.apache.continuum.web.action;
+
+/*
+ * 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 org.apache.continuum.configuration.BuildAgentConfiguration;
+import org.apache.continuum.configuration.BuildAgentGroupConfiguration;
+import org.apache.continuum.release.distributed.DistributedReleaseUtil;
+import org.apache.continuum.web.action.stub.ReleaseActionStub;
+import org.apache.maven.continuum.Continuum;
+import org.apache.maven.continuum.configuration.ConfigurationService;
+import org.apache.maven.continuum.model.system.Profile;
+import org.jmock.Mock;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class AbstractReleaseActionTest
+    extends AbstractActionTest
+{
+    private ReleaseActionStub action;
+
+    private Mock continuumMock;
+
+    private Mock configurationServiceMock;
+
+    private String defaultBuildagentUrl = "http://localhost:8181/continuum-buildagent/xmlrpc";
+
+    protected void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        continuumMock = mock( Continuum.class );
+        configurationServiceMock = mock( ConfigurationService.class );
+
+        Profile profile = new Profile();
+        profile.setBuildAgentGroup( "BUILDAGENT_GROUP" );
+
+        action = new ReleaseActionStub();
+        action.setProfile( profile );
+        action.setDefaultBuildagent( defaultBuildagentUrl );
+        action.setContinuum( (Continuum) continuumMock.proxy() );
+    }
+
+    public void testGetEnvironmentsDefaultAgentInGroup()
+        throws Exception
+    {
+        BuildAgentGroupConfiguration buildAgentGroup = createBuildAgentGroupConfiguration( true );
+        buildAgentGroup.addBuildAgent( new BuildAgentConfiguration( defaultBuildagentUrl, "Default Build Agent",
+                                                                    true ) );
+
+        continuumMock.expects( atLeastOnce() ).method( "getConfiguration" ).will( returnValue(
+            configurationServiceMock.proxy() ) );
+        configurationServiceMock.expects( atLeastOnce() ).method( "getBuildAgentGroup" ).will( returnValue(
+            buildAgentGroup ) );
+
+        action.getEnvironments();
+        Map<String, String> envVars = action.getEnvironmentVariables();
+        String buildagent = envVars.get( DistributedReleaseUtil.KEY_BUILD_AGENT_URL );
+
+        assertNotNull( envVars );
+        assertTrue( "Default build agent is expected to be used.", defaultBuildagentUrl.equals( buildagent ) );
+    }
+
+    public void testGetEnvironmentsDefaultAgentNotInGroup()
+        throws Exception
+    {
+        BuildAgentGroupConfiguration buildAgentGroup = createBuildAgentGroupConfiguration( true );
+
+        continuumMock.expects( atLeastOnce() ).method( "getConfiguration" ).will( returnValue(
+            configurationServiceMock.proxy() ) );
+        configurationServiceMock.expects( atLeastOnce() ).method( "getBuildAgentGroup" ).will( returnValue(
+            buildAgentGroup ) );
+
+        action.getEnvironments();
+        Map<String, String> envVars = action.getEnvironmentVariables();
+        String buildagent = envVars.get( DistributedReleaseUtil.KEY_BUILD_AGENT_URL );
+
+        assertNotNull( envVars );
+        assertFalse( "Default build agent is not expected to be used.", defaultBuildagentUrl.equals( buildagent ) );
+    }
+
+    public void testGetEnvironmentsNoEnabledAgentInGroup()
+        throws Exception
+    {
+        BuildAgentGroupConfiguration buildAgentGroup = createBuildAgentGroupConfiguration( false );
+        buildAgentGroup.addBuildAgent( new BuildAgentConfiguration( defaultBuildagentUrl, "Default Build Agent",
+                                                                    false ) );
+
+        continuumMock.expects( atLeastOnce() ).method( "getConfiguration" ).will( returnValue(
+            configurationServiceMock.proxy() ) );
+        configurationServiceMock.expects( atLeastOnce() ).method( "getBuildAgentGroup" ).will( returnValue(
+            buildAgentGroup ) );
+
+        action.getEnvironments();
+        Map<String, String> envVars = action.getEnvironmentVariables();
+        String buildagent = envVars.get( DistributedReleaseUtil.KEY_BUILD_AGENT_URL );
+
+        assertNotNull( envVars );
+        assertFalse( "Default build agent is not expected to be used.", defaultBuildagentUrl.equals( buildagent ) );
+        assertNull( "Build agent should be empty.", buildagent );
+    }
+
+    public void testGetEnvironmentsNoAgentInGroup()
+        throws Exception
+    {
+        BuildAgentGroupConfiguration buildAgentGroup = new BuildAgentGroupConfiguration();
+
+        continuumMock.expects( atLeastOnce() ).method( "getConfiguration" ).will( returnValue(
+            configurationServiceMock.proxy() ) );
+        configurationServiceMock.expects( atLeastOnce() ).method( "getBuildAgentGroup" ).will( returnValue(
+            buildAgentGroup ) );
+
+        action.getEnvironments();
+        Map<String, String> envVars = action.getEnvironmentVariables();
+        String buildagent = envVars.get( DistributedReleaseUtil.KEY_BUILD_AGENT_URL );
+
+        assertNotNull( envVars );
+        assertFalse( "Default build agent is not expected to be used.", defaultBuildagentUrl.equals( buildagent ) );
+        assertNull( "Build agent should be empty.", buildagent );
+    }
+
+    private BuildAgentGroupConfiguration createBuildAgentGroupConfiguration( boolean isAgentEnabled )
+    {
+        BuildAgentConfiguration buildagent1 = new BuildAgentConfiguration(
+            "http://localhost:9191/continuum-buildagent/xmlrpc", "Other Build Agent", isAgentEnabled );
+        BuildAgentConfiguration buildagent2 = new BuildAgentConfiguration(
+            "http://localhost:9292/continuum-buildagent/xmlrpc", "Other Build Agent", isAgentEnabled );
+
+        List<BuildAgentConfiguration> buildAgents = new ArrayList<BuildAgentConfiguration>();
+        buildAgents.add( buildagent1 );
+        buildAgents.add( buildagent2 );
+
+        BuildAgentGroupConfiguration buildAgentGroup = new BuildAgentGroupConfiguration( "BUILDAGENT_GROUP",
+                                                                                         buildAgents );
+
+        return buildAgentGroup;
+    }
+}
diff --git a/continuum-webapp/src/test/java/org/apache/continuum/web/action/ViewBuildsReportActionTest.java b/continuum-webapp/src/test/java/org/apache/continuum/web/action/ViewBuildsReportActionTest.java
new file mode 100644
index 0000000..b2100bb
--- /dev/null
+++ b/continuum-webapp/src/test/java/org/apache/continuum/web/action/ViewBuildsReportActionTest.java
@@ -0,0 +1,181 @@
+package org.apache.continuum.web.action;
+
+/*
+ * 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 com.opensymphony.xwork2.Action;
+import org.apache.commons.io.IOUtils;
+import org.apache.continuum.web.action.stub.ViewBuildsReportActionStub;
+import org.apache.maven.continuum.Continuum;
+import org.apache.maven.continuum.model.project.BuildResult;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.project.ProjectGroup;
+import org.jmock.Mock;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+
+public class ViewBuildsReportActionTest
+    extends AbstractActionTest
+{
+    private ViewBuildsReportActionStub action;
+
+    private Mock continuum;
+
+    private List<BuildResult> buildResults = new ArrayList<BuildResult>();
+
+    @Override
+    protected void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        action = new ViewBuildsReportActionStub();
+        continuum = mock( Continuum.class );
+        action.setContinuum( (Continuum) continuum.proxy() );
+    }
+
+    public void testInvalidRowCount()
+    {
+        action.setRowCount( -1 );
+        String result = action.execute();
+
+        assertEquals( Action.INPUT, result );
+        assertTrue( action.hasFieldErrors() );
+        assertFalse( action.hasActionErrors() );
+        continuum.verify();
+    }
+
+    public void testEndDateBeforeStartDate()
+    {
+        action.setStartDate( "04/25/2010" );
+        action.setEndDate( "04/24/2010" );
+        String result = action.execute();
+
+        assertEquals( Action.INPUT, result );
+        assertTrue( action.hasFieldErrors() );
+        assertFalse( action.hasActionErrors() );
+        continuum.verify();
+    }
+
+    public void testMalformedStartDate()
+    {
+        action.setStartDate( "not a date" );
+        String result = action.execute();
+
+        assertEquals( Action.ERROR, result );
+        assertTrue( action.hasActionErrors() );
+        assertFalse( action.hasFieldErrors() );
+        continuum.verify();
+    }
+
+    public void testMalformedEndDate()
+    {
+        action.setEndDate( "not a date" );
+        String result = action.execute();
+
+        assertEquals( Action.ERROR, result );
+        assertTrue( action.hasActionErrors() );
+        assertFalse( action.hasFieldErrors() );
+        continuum.verify();
+    }
+
+    public void testStartDateSameWithEndDate()
+    {
+        continuum.expects( once() ).method( "getBuildResultsInRange" ).will( returnValue( buildResults ) );
+
+        action.setStartDate( "04/25/2010" );
+        action.setEndDate( "04/25/2010" );
+        String result = action.execute();
+
+        assertSuccessResult( result );
+        continuum.verify();
+    }
+
+    public void testEndDateWithNoStartDate()
+    {
+        continuum.expects( once() ).method( "getBuildResultsInRange" ).will( returnValue( buildResults ) );
+        action.setEndDate( "04/25/2010" );
+        String result = action.execute();
+
+        assertSuccessResult( result );
+        continuum.verify();
+    }
+
+    public void testExportToCsv()
+        throws Exception
+    {
+        Calendar cal = Calendar.getInstance();
+        cal.set( 2010, 1, 1, 1, 1, 1 );
+
+        List<BuildResult> results = createBuildResult( cal.getTimeInMillis() );
+
+        continuum.expects( once() ).method( "getBuildResultsInRange" ).will( returnValue( results ) );
+        action.setProjectGroupId( 0 );
+        action.setBuildStatus( 0 );
+        action.setStartDate( "" );
+        action.setEndDate( "" );
+        action.setTriggeredBy( "" );
+
+        String result = action.downloadBuildsReport();
+
+        assertEquals( "send-file", result );
+        assertFileContentsEqual( IOUtils.toString( action.getInputStream() ), cal.getTime().toString() );
+        continuum.verify();
+    }
+
+    private void assertSuccessResult( String result )
+    {
+        assertEquals( Action.SUCCESS, result );
+        assertFalse( action.hasFieldErrors() );
+        assertFalse( action.hasActionErrors() );
+    }
+
+    private List<BuildResult> createBuildResult( long timeInMillis )
+    {
+        List<BuildResult> results = new ArrayList<BuildResult>();
+
+        BuildResult result = new BuildResult();
+
+        ProjectGroup group = new ProjectGroup();
+        group.setName( "Test Group" );
+
+        Project project = new Project();
+        project.setName( "Test Project" );
+        project.setProjectGroup( group );
+
+        result.setProject( project );
+        result.setState( 2 );
+        result.setStartTime( timeInMillis );
+        result.setUsername( "test-admin" );
+
+        results.add( result );
+
+        return results;
+    }
+
+    private void assertFileContentsEqual( String report, String buildDate )
+    {
+        String result = "Project Group,Project Name,Build Date,Triggered By,Build Status\n" +
+            "Test Group,Test Project," + buildDate + ",test-admin,Ok\n";
+
+        assertEquals( report, result );
+    }
+}
diff --git a/continuum-webapp/src/test/java/org/apache/continuum/web/action/stub/ReleaseActionStub.java b/continuum-webapp/src/test/java/org/apache/continuum/web/action/stub/ReleaseActionStub.java
new file mode 100644
index 0000000..8dbafb1
--- /dev/null
+++ b/continuum-webapp/src/test/java/org/apache/continuum/web/action/stub/ReleaseActionStub.java
@@ -0,0 +1,61 @@
+package org.apache.continuum.web.action.stub;
+
+/*
+ * 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 org.apache.continuum.web.action.AbstractReleaseAction;
+import org.apache.maven.continuum.model.system.Profile;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class ReleaseActionStub
+    extends AbstractReleaseAction
+{
+    private Map<String, String> environmentVariables;
+
+    private Profile profile;
+
+    private String defaultBuildagent;
+
+    public ReleaseActionStub()
+    {
+        this.environmentVariables = new HashMap<String, String>();
+    }
+
+    public void getEnvironments()
+    {
+        this.environmentVariables = getEnvironments( profile, defaultBuildagent );
+    }
+
+    public Map<String, String> getEnvironmentVariables()
+    {
+        return this.environmentVariables;
+    }
+
+    public void setProfile( Profile profile )
+    {
+        this.profile = profile;
+    }
+
+    public void setDefaultBuildagent( String defaultBuildagent )
+    {
+        this.defaultBuildagent = defaultBuildagent;
+    }
+}
diff --git a/continuum-webapp/src/test/java/org/apache/continuum/web/action/stub/ViewBuildsReportActionStub.java b/continuum-webapp/src/test/java/org/apache/continuum/web/action/stub/ViewBuildsReportActionStub.java
new file mode 100644
index 0000000..97137e3
--- /dev/null
+++ b/continuum-webapp/src/test/java/org/apache/continuum/web/action/stub/ViewBuildsReportActionStub.java
@@ -0,0 +1,36 @@
+package org.apache.continuum.web.action.stub;
+
+/*
+ * 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 org.apache.continuum.web.action.ViewBuildsReportAction;
+
+public class ViewBuildsReportActionStub
+    extends ViewBuildsReportAction
+{
+    protected void checkViewProjectGroupAuthorization( String resource )
+    {
+        // skip authorization check
+    }
+
+    protected void checkViewReportsAuthorization()
+    {
+        // skip authorization check
+    }
+}
diff --git a/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/AddMavenProjectActionTest.java b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/AddMavenProjectActionTest.java
new file mode 100644
index 0000000..dcda61c
--- /dev/null
+++ b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/AddMavenProjectActionTest.java
@@ -0,0 +1,92 @@
+package org.apache.maven.continuum.web.action;
+
+/*
+ * 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 com.opensymphony.xwork2.Action;
+import org.apache.continuum.web.action.AbstractActionTest;
+import org.apache.maven.continuum.ContinuumException;
+import org.apache.maven.continuum.builddefinition.BuildDefinitionServiceException;
+import org.apache.maven.continuum.web.action.stub.AddMavenProjectStub;
+import org.jmock.Mock;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLEncoder;
+
+/**
+ * Verifies {@link org.apache.maven.continuum.web.action.AddMavenProjectAction}.
+ */
+public class AddMavenProjectActionTest
+    extends AbstractActionTest
+{
+    private AddMavenProjectStub action;
+
+    private Mock requestMock;
+
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        action = new AddMavenProjectStub();
+
+        // TODO: upgrade to generics-based mocking
+        requestMock = new Mock( HttpServletRequest.class );
+        action.setServletRequest( (HttpServletRequest) requestMock.proxy() );
+
+    }
+
+    public void testHttpUrlConstructionWithCreds()
+        throws BuildDefinitionServiceException, ContinuumException, MalformedURLException, UnsupportedEncodingException
+    {
+        String scheme = "http";
+        String host = "www.example.com";
+        String port = "8080";
+        String path = "/project/path/perhaps";
+        String query = "fileName=pom.xml&project=Project%20Name";
+        String username = "batkinson@apache.org";
+        String password = "p&s/W:rd";
+        String encoding = "UTF-8";
+        String urlToFetch = String.format( "%s://%s:%s%s?%s", scheme, host, port, path, query );
+
+        action.setPomUrl( urlToFetch );
+        action.setScmUsername( username );
+        action.setScmPassword( password );
+        requestMock.expects( once() ).method( "getCharacterEncoding" ).will( returnValue( encoding ) );
+
+        String result = action.execute();
+
+        requestMock.verify();
+        assertEquals( "action should have succeeded", Action.SUCCESS, result );
+
+        URL builtUrl = new URL( action.getPom() );
+        String expectedUserInfo =
+            String.format( "%s:%s", URLEncoder.encode( username, encoding ), URLEncoder.encode( password, encoding ) );
+
+        assertEquals( "url should include encoded user information", expectedUserInfo, builtUrl.getUserInfo() );
+        assertEquals( "url should include original protocol scheme", scheme, builtUrl.getProtocol() );
+        assertEquals( "url should include original host", host, builtUrl.getHost() );
+        assertEquals( "url should include original port", port, Integer.toString( builtUrl.getPort() ) );
+        assertEquals( "url should include original path ", path, builtUrl.getPath() );
+        assertEquals( "url should include original query params", query, builtUrl.getQuery() );
+    }
+}
diff --git a/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/AddProjectActionTest.java b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/AddProjectActionTest.java
new file mode 100644
index 0000000..29845b7
--- /dev/null
+++ b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/AddProjectActionTest.java
@@ -0,0 +1,217 @@
+package org.apache.maven.continuum.web.action;
+
+/*
+ * 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 org.apache.continuum.web.action.AbstractActionTest;
+import org.apache.maven.continuum.Continuum;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.project.ProjectGroup;
+import org.apache.maven.continuum.web.action.stub.AddProjectActionStub;
+import org.jmock.Mock;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Test for {@link AddProjectAction}
+ *
+ * @author <a href="mailto:jzurbano@apache.org">jzurbano</a>
+ */
+public class AddProjectActionTest
+    extends AbstractActionTest
+{
+    private AddProjectActionStub action;
+
+    private Mock continuumMock;
+
+    private static final String VALID_NAME_CHARACTER = "abcABC123whitespaces_.:-";
+
+    private static final String VALID_VERSION_CHARACTER = "abcABC123.-";
+
+    private static final String VALID_SCM_URL_CHARACTER = "abcABC123_.:-#~=@\\/|[]";
+
+    private static final String VALID_SCM_TAG_CHARACTER = "abcABC123_.:-#~=@\\/|[]";
+
+    private static final String VALID_DESCRIPTION_CHARACTER = "abcABC123whitespaces_.-";
+
+    protected void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        action = new AddProjectActionStub();
+        continuumMock = new Mock( Continuum.class );
+        action.setContinuum( (Continuum) continuumMock.proxy() );
+
+        Collection<ProjectGroup> projectGroups = new ArrayList<ProjectGroup>();
+        ProjectGroup projectGroup = new ProjectGroup();
+        projectGroups.add( projectGroup );
+
+        action.setProjectGroups( projectGroups );
+    }
+
+    public void testAddProjectNullValues()
+        throws Exception
+    {
+        action.setProjectName( null );
+        action.setProjectVersion( null );
+        action.setProjectScmUrl( null );
+
+        action.validate();
+    }
+
+    /**
+     * Test add of Ant project
+     *
+     * @throws Exception
+     */
+    public void testAddAntProject()
+        throws Exception
+    {
+        String scmUrl = "scm:svn:http://project/scm/url/test/build.xml";
+
+        List<Project> projects = createProjectList();
+        continuumMock.expects( once() ).method( "getProjects" ).will( returnValue( projects ) );
+        continuumMock.expects( once() ).method( "addProject" ).will( returnValue( 3 ) );
+
+        action.setProjectName( "Ant Test Project" );
+        action.setProjectVersion( "1.0-SNAPSHOT" );
+        action.setProjectScmUrl( scmUrl );
+        action.setProjectType( "ant" );
+        action.setSelectedProjectGroup( 1 );
+        action.setBuildDefintionTemplateId( 1 );
+
+        action.validate();
+        action.add();
+        continuumMock.verify();
+
+    }
+
+    public void testAddAntProjectWithValidValues()
+        throws Exception
+    {
+        List<Project> projects = createProjectList();
+        continuumMock.expects( once() ).method( "getProjects" ).will( returnValue( projects ) );
+        continuumMock.expects( once() ).method( "addProject" ).will( returnValue( 3 ) );
+
+        action.setProjectName( VALID_NAME_CHARACTER );
+        action.setProjectDescription( VALID_DESCRIPTION_CHARACTER );
+        action.setProjectVersion( VALID_VERSION_CHARACTER );
+        action.setProjectScmUrl( VALID_SCM_URL_CHARACTER );
+        action.setProjectScmTag( VALID_SCM_TAG_CHARACTER );
+        action.setProjectType( "ant" );
+        action.setSelectedProjectGroup( 1 );
+        action.setBuildDefintionTemplateId( 1 );
+
+        // validate
+        action.validate();
+
+        // verify
+        assertFalse( action.hasActionErrors() );
+        assertEquals( 0, action.getActionErrors().size() );
+
+        // add
+        action.add();
+
+        continuumMock.verify();
+    }
+
+    /**
+     * Test add of Shell project
+     *
+     * @throws Exception
+     */
+    public void testAddShellProject()
+        throws Exception
+    {
+        String scmUrl = "scm:svn:http://project/scm/url/test/run.sh";
+
+        List<Project> projects = createProjectList();
+        continuumMock.expects( once() ).method( "getProjects" ).will( returnValue( projects ) );
+        continuumMock.expects( once() ).method( "addProject" ).will( returnValue( 3 ) );
+
+        action.setProjectName( "Shell Test Project" );
+        action.setProjectVersion( "1.0-SNAPSHOT" );
+        action.setProjectScmUrl( scmUrl );
+        action.setProjectType( "shell" );
+        action.setSelectedProjectGroup( 1 );
+        action.setBuildDefintionTemplateId( 1 );
+
+        action.validate();
+        action.add();
+        continuumMock.verify();
+    }
+
+    public void testAddShellProjectWithValidValues()
+        throws Exception
+    {
+        List<Project> projects = createProjectList();
+        continuumMock.expects( once() ).method( "getProjects" ).will( returnValue( projects ) );
+        continuumMock.expects( once() ).method( "addProject" ).will( returnValue( 3 ) );
+
+        action.setProjectName( VALID_NAME_CHARACTER );
+        action.setProjectDescription( VALID_DESCRIPTION_CHARACTER );
+        action.setProjectVersion( VALID_VERSION_CHARACTER );
+        action.setProjectScmUrl( VALID_SCM_URL_CHARACTER );
+        action.setProjectScmTag( VALID_SCM_TAG_CHARACTER );
+        action.setProjectType( "shell" );
+        action.setSelectedProjectGroup( 1 );
+        action.setBuildDefintionTemplateId( 1 );
+
+        // validate
+        action.validate();
+
+        // verify
+        assertFalse( action.hasActionErrors() );
+        assertEquals( 0, action.getActionErrors().size() );
+
+        // add
+        action.add();
+
+        continuumMock.verify();
+    }
+
+    private List<Project> createProjectList()
+    {
+        List<Project> projects = new ArrayList<Project>();
+
+        Project project1 = createProject( "scm:svn:http://project/scm/url/test-1/run.sh", "Shell Test Project 1",
+                                          "1.0-SNAPSHOT", 1 );
+        Project project2 = createProject( "scm:svn:http://project/scm/url/test-2/build.xml", "Ant Test Project 1",
+                                          "1.0-SNAPSHOT", 2 );
+
+        projects.add( project1 );
+        projects.add( project2 );
+
+        return projects;
+    }
+
+    private Project createProject( String scmUrl, String name, String version, int id )
+    {
+        Project project = new Project();
+        project.setId( id );
+        project.setName( name );
+        project.setVersion( version );
+        project.setScmUrl( scmUrl );
+
+        return project;
+    }
+}
diff --git a/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/BuildAgentActionTest.java b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/BuildAgentActionTest.java
new file mode 100644
index 0000000..220cf2e
--- /dev/null
+++ b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/BuildAgentActionTest.java
@@ -0,0 +1,107 @@
+package org.apache.maven.continuum.web.action;
+
+/*
+ * 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 org.apache.continuum.builder.distributed.manager.DistributedBuildManager;
+import org.apache.continuum.configuration.BuildAgentConfiguration;
+import org.apache.continuum.configuration.BuildAgentGroupConfiguration;
+import org.apache.continuum.web.action.AbstractActionTest;
+import org.apache.continuum.web.action.admin.BuildAgentAction;
+import org.apache.maven.continuum.Continuum;
+import org.apache.maven.continuum.configuration.ConfigurationService;
+import org.jmock.Mock;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class BuildAgentActionTest
+    extends AbstractActionTest
+{
+    private BuildAgentAction action;
+
+    private Mock continuumMock;
+
+    private Mock configurationServiceMock;
+
+    private Mock distributedBuildManagerMock;
+
+    private List<BuildAgentConfiguration> buildAgents;
+
+    protected void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        action = new BuildAgentAction();
+        continuumMock = mock( Continuum.class );
+        configurationServiceMock = mock( ConfigurationService.class );
+        distributedBuildManagerMock = mock( DistributedBuildManager.class );
+
+        action.setContinuum( (Continuum) continuumMock.proxy() );
+
+        buildAgents = new ArrayList<BuildAgentConfiguration>();
+    }
+
+    public void testAddBuildAgent()
+        throws Exception
+    {
+        continuumMock.expects( once() ).method( "getConfiguration" ).will( returnValue(
+            configurationServiceMock.proxy() ) );
+        configurationServiceMock.expects( atLeastOnce() ).method( "getBuildAgents" ).will( returnValue( buildAgents ) );
+        configurationServiceMock.expects( once() ).method( "addBuildAgent" ).isVoid();
+        configurationServiceMock.expects( once() ).method( "store" ).isVoid();
+        continuumMock.expects( once() ).method( "getDistributedBuildManager" ).will( returnValue(
+            distributedBuildManagerMock.proxy() ) );
+        distributedBuildManagerMock.expects( once() ).method( "update" ).isVoid();
+
+        BuildAgentConfiguration buildAgent = new BuildAgentConfiguration();
+        buildAgent.setUrl( "http://sample/agent" );
+
+        action.setBuildAgent( buildAgent );
+        action.save();
+    }
+
+    public void testDeleteBuildAgent()
+        throws Exception
+    {
+        List<BuildAgentGroupConfiguration> buildAgentGroups = new ArrayList<BuildAgentGroupConfiguration>();
+
+        continuumMock.expects( atLeastOnce() ).method( "getDistributedBuildManager" ).will( returnValue(
+            distributedBuildManagerMock.proxy() ) );
+        distributedBuildManagerMock.expects( once() ).method( "isBuildAgentBusy" ).will( returnValue( false ) );
+        continuumMock.expects( once() ).method( "getConfiguration" ).will( returnValue(
+            configurationServiceMock.proxy() ) );
+        configurationServiceMock.expects( atLeastOnce() ).method( "getBuildAgentGroups" ).will( returnValue(
+            buildAgentGroups ) );
+        configurationServiceMock.expects( atLeastOnce() ).method( "getBuildAgents" ).will( returnValue( buildAgents ) );
+
+        distributedBuildManagerMock.expects( never() ).method( "removeDistributedBuildQueueOfAgent" ).isVoid();
+        distributedBuildManagerMock.expects( never() ).method( "reload" ).isVoid();
+        configurationServiceMock.expects( never() ).method( "removeBuildAgent" ).isVoid();
+        configurationServiceMock.expects( never() ).method( "store" ).isVoid();
+
+        BuildAgentConfiguration buildAgent = new BuildAgentConfiguration();
+        buildAgent.setUrl( "http://sample/agent" );
+
+        action.setConfirmed( true );
+        action.setBuildAgent( buildAgent );
+        action.delete();
+    }
+}
diff --git a/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/BuildResultActionTest.java b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/BuildResultActionTest.java
new file mode 100644
index 0000000..6a372e1
--- /dev/null
+++ b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/BuildResultActionTest.java
@@ -0,0 +1,125 @@
+package org.apache.maven.continuum.web.action;
+
+/*
+ * 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 org.apache.continuum.builder.distributed.manager.DistributedBuildManager;
+import org.apache.continuum.buildmanager.BuildsManager;
+import org.apache.continuum.taskqueue.BuildProjectTask;
+import org.apache.continuum.web.action.AbstractActionTest;
+import org.apache.maven.continuum.Continuum;
+import org.apache.maven.continuum.configuration.ConfigurationService;
+import org.apache.maven.continuum.model.project.BuildResult;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.web.action.stub.BuildResultActionStub;
+import org.apache.maven.continuum.xmlrpc.project.ContinuumProjectState;
+import org.jmock.Mock;
+
+import java.io.File;
+import java.util.HashMap;
+
+public class BuildResultActionTest
+    extends AbstractActionTest
+{
+    private BuildResultActionStub action;
+
+    private Mock continuum;
+
+    private Mock configurationService;
+
+    private Mock distributedBuildManager;
+
+    private Mock buildsManager;
+
+    protected void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        action = new BuildResultActionStub();
+        continuum = mock( Continuum.class );
+        configurationService = mock( ConfigurationService.class );
+        distributedBuildManager = mock( DistributedBuildManager.class );
+        buildsManager = mock( BuildsManager.class );
+
+        action.setContinuum( (Continuum) continuum.proxy() );
+        action.setDistributedBuildManager( (DistributedBuildManager) distributedBuildManager.proxy() );
+    }
+
+    public void testViewPreviousBuild()
+        throws Exception
+    {
+        Project project = createProject( "stub-project" );
+        BuildResult buildResult = createBuildResult( project );
+
+        continuum.expects( once() ).method( "getProject" ).will( returnValue( project ) );
+        continuum.expects( once() ).method( "getBuildResult" ).will( returnValue( buildResult ) );
+        continuum.expects( atLeastOnce() ).method( "getConfiguration" ).will( returnValue(
+            (ConfigurationService) configurationService.proxy() ) );
+        configurationService.expects( once() ).method( "isDistributedBuildEnabled" ).will( returnValue( false ) );
+        configurationService.expects( once() ).method( "getTestReportsDirectory" ).will( returnValue( new File(
+            "testReportsDir" ) ) );
+        continuum.expects( once() ).method( "getChangesSinceLastSuccess" ).will( returnValue( null ) );
+        configurationService.expects( once() ).method( "getBuildOutputFile" ).will( returnValue( new File(
+            "buildOutputFile" ) ) );
+        continuum.expects( once() ).method( "getBuildsManager" ).will( returnValue( buildsManager.proxy() ) );
+        buildsManager.expects( once() ).method( "getCurrentBuilds" ).will( returnValue(
+            new HashMap<String, BuildProjectTask>() ) );
+
+        action.execute();
+        continuum.verify();
+    }
+
+    public void testViewCurrentBuildInDistributedBuildAgent()
+        throws Exception
+    {
+        Project project = createProject( "stub-project" );
+
+        continuum.expects( once() ).method( "getProject" ).will( returnValue( project ) );
+        continuum.expects( once() ).method( "getConfiguration" ).will( returnValue(
+            (ConfigurationService) configurationService.proxy() ) );
+        configurationService.expects( once() ).method( "isDistributedBuildEnabled" ).will( returnValue( true ) );
+        distributedBuildManager.expects( once() ).method( "getBuildResult" ).will( returnValue(
+            new HashMap<String, Object>() ) );
+
+        action.execute();
+        continuum.verify();
+    }
+
+    private Project createProject( String name )
+    {
+        Project project = new Project();
+        project.setId( 1 );
+        project.setName( name );
+        project.setArtifactId( "foo:bar" );
+        project.setVersion( "1.0" );
+        project.setState( ContinuumProjectState.BUILDING );
+
+        return project;
+    }
+
+    private BuildResult createBuildResult( Project project )
+    {
+        BuildResult buildResult = new BuildResult();
+        buildResult.setId( 1 );
+        buildResult.setProject( project );
+
+        return buildResult;
+    }
+}
diff --git a/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/ContinuumActionLoggingTest.java b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/ContinuumActionLoggingTest.java
index fc54ffb..16280fc 100644
--- a/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/ContinuumActionLoggingTest.java
+++ b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/ContinuumActionLoggingTest.java
@@ -19,6 +19,8 @@
  * under the License.
  */
 
+import org.codehaus.plexus.spring.PlexusInSpringTestCase;
+
 import java.io.BufferedOutputStream;
 import java.io.FileOutputStream;
 import java.io.FilterOutputStream;
@@ -26,8 +28,6 @@
 import java.io.OutputStream;
 import java.io.PrintStream;
 
-import org.codehaus.plexus.spring.PlexusInSpringTestCase;
-
 /**
  * TestContinuumActionLogging:
  *
@@ -53,8 +53,8 @@
 
     public void tearDown()
     {
-        System.setOut( new PrintStream(
-            new BufferedOutputStream( new FileOutputStream( java.io.FileDescriptor.out ), 128 ), true ) );
+        System.setOut( new PrintStream( new BufferedOutputStream( new FileOutputStream( java.io.FileDescriptor.out ),
+                                                                  128 ), true ) );
     }
 
 
diff --git a/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/ProjectGroupActionTest.java b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/ProjectGroupActionTest.java
new file mode 100644
index 0000000..d986db9
--- /dev/null
+++ b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/ProjectGroupActionTest.java
@@ -0,0 +1,159 @@
+package org.apache.maven.continuum.web.action;
+
+/*
+ * 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 org.apache.continuum.web.action.AbstractActionTest;
+import org.apache.maven.continuum.Continuum;
+import org.apache.maven.continuum.model.project.ProjectGroup;
+import org.apache.maven.continuum.web.action.stub.ProjectGroupActionStub;
+import org.apache.maven.continuum.web.bean.ProjectGroupUserBean;
+import org.codehaus.plexus.redback.rbac.RBACManager;
+import org.codehaus.plexus.redback.rbac.Role;
+import org.codehaus.plexus.redback.rbac.UserAssignment;
+import org.codehaus.plexus.redback.rbac.jdo.JdoRole;
+import org.codehaus.plexus.redback.rbac.jdo.JdoUserAssignment;
+import org.jmock.Mock;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ProjectGroupActionTest
+    extends AbstractActionTest
+{
+    private ProjectGroupActionStub action;
+
+    private Mock continuum;
+
+    private Mock rbac;
+
+    protected void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        action = new ProjectGroupActionStub();
+        continuum = mock( Continuum.class );
+        rbac = mock( RBACManager.class );
+
+        action.setContinuum( (Continuum) continuum.proxy() );
+        action.setRbacManager( (RBACManager) rbac.proxy() );
+    }
+
+    public void testViewMembersWithProjectAdminRole()
+        throws Exception
+    {
+        ProjectGroup group = new ProjectGroup();
+        group.setName( "Project A" );
+
+        List<Role> roles = new ArrayList<Role>();
+        Role role1 = new JdoRole();
+        role1.setName( "Project User - Project A" );
+        roles.add( role1 );
+
+        Role role2 = new JdoRole();
+        role2.setName( "Continuum Manage Scheduling" );
+        roles.add( role2 );
+
+        Role role3 = new JdoRole();
+        role3.setName( "Project Developer - Project A" );
+        roles.add( role3 );
+
+        Role role4 = new JdoRole();
+        role4.setName( "Project Administrator - Project A" );
+        roles.add( role4 );
+
+        List<UserAssignment> userAssignments = new ArrayList<UserAssignment>();
+        UserAssignment ua1 = new JdoUserAssignment();
+        ua1.setPrincipal( "user1" );
+        userAssignments.add( ua1 );
+
+        List<Role> eRoles = roles;
+
+        continuum.expects( once() ).method( "getProjectGroupWithProjects" ).will( returnValue( group ) );
+        rbac.expects( once() ).method( "getAllRoles" ).will( returnValue( roles ) );
+        rbac.expects( once() ).method( "getUserAssignmentsForRoles" ).will( returnValue( userAssignments ) );
+        rbac.expects( once() ).method( "getEffectivelyAssignedRoles" ).will( returnValue( eRoles ) );
+
+        action.members();
+
+        continuum.verify();
+        rbac.verify();
+
+        List<ProjectGroupUserBean> users = action.getProjectGroupUsers();
+        assertEquals( 1, users.size() );
+        assertTrue( users.get( 0 ).isAdministrator() );
+        assertTrue( users.get( 0 ).isDeveloper() );
+        assertTrue( users.get( 0 ).isUser() );
+    }
+
+    public void testViewMembersWithProjectUserRole()
+        throws Exception
+    {
+        ProjectGroup group = new ProjectGroup();
+        group.setName( "Project A" );
+
+        List<Role> roles = new ArrayList<Role>();
+        Role role1 = new JdoRole();
+        role1.setName( "Project User - Project A" );
+        roles.add( role1 );
+
+        Role role2 = new JdoRole();
+        role2.setName( "Continuum Manage Scheduling" );
+        roles.add( role2 );
+
+        Role role3 = new JdoRole();
+        role3.setName( "Project Developer - test-group" );
+        roles.add( role3 );
+
+        Role role4 = new JdoRole();
+        role4.setName( "Project Administrator - test-group" );
+        roles.add( role4 );
+
+        Role role5 = new JdoRole();
+        role5.setName( "Project Administrator - Project C" );
+        roles.add( role5 );
+
+        List<UserAssignment> userAssignments = new ArrayList<UserAssignment>();
+        UserAssignment ua1 = new JdoUserAssignment();
+        ua1.setPrincipal( "user1" );
+        userAssignments.add( ua1 );
+
+        List<Role> eRoles = new ArrayList<Role>();
+        eRoles.add( role1 );
+        eRoles.add( role2 );
+        eRoles.add( role5 );
+
+        continuum.expects( once() ).method( "getProjectGroupWithProjects" ).will( returnValue( group ) );
+        rbac.expects( once() ).method( "getAllRoles" ).will( returnValue( roles ) );
+        rbac.expects( once() ).method( "getUserAssignmentsForRoles" ).will( returnValue( userAssignments ) );
+        rbac.expects( once() ).method( "getEffectivelyAssignedRoles" ).will( returnValue( eRoles ) );
+
+        action.members();
+
+        continuum.verify();
+        rbac.verify();
+
+        List<ProjectGroupUserBean> users = action.getProjectGroupUsers();
+        assertEquals( 1, users.size() );
+        assertFalse( users.get( 0 ).isAdministrator() );
+        assertFalse( users.get( 0 ).isDeveloper() );
+        assertTrue( users.get( 0 ).isUser() );
+    }
+}
diff --git a/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/ReleasePrepareActionTest.java b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/ReleasePrepareActionTest.java
index 06fb67a..13a13b1 100644
--- a/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/ReleasePrepareActionTest.java
+++ b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/ReleasePrepareActionTest.java
@@ -19,10 +19,10 @@
  * under the License.
  */
 
+import org.apache.continuum.web.action.AbstractActionTest;
 import org.apache.maven.continuum.Continuum;
 import org.apache.maven.continuum.model.project.Project;
 import org.jmock.Mock;
-import org.jmock.MockObjectTestCase;
 
 /**
  * Test for {@link ReleasePrepareAction}
@@ -31,19 +31,17 @@
  * @version $Id$
  */
 public class ReleasePrepareActionTest
-    extends MockObjectTestCase
+    extends AbstractActionTest
 {
-
     private ReleasePrepareAction action;
 
     private Mock continuumMock;
 
-    private Mock securitySessionMock;
-
-    private Mock actionContextMock;
-
-    public ReleasePrepareActionTest()
+    protected void setUp()
+        throws Exception
     {
+        super.setUp();
+
         action = new ReleasePrepareAction();
         continuumMock = new Mock( Continuum.class );
         //securitySessionMock = new Mock( SecuritySession.class );
diff --git a/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/SummaryActionTest.java b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/SummaryActionTest.java
new file mode 100644
index 0000000..b82abeb
--- /dev/null
+++ b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/SummaryActionTest.java
@@ -0,0 +1,197 @@
+package org.apache.maven.continuum.web.action;
+
+/*
+ * 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 org.apache.continuum.buildmanager.BuildsManager;
+import org.apache.continuum.web.action.AbstractActionTest;
+import org.apache.maven.continuum.Continuum;
+import org.apache.maven.continuum.configuration.ConfigurationService;
+import org.apache.maven.continuum.model.project.BuildResult;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.project.ProjectGroup;
+import org.apache.maven.continuum.web.action.stub.SummaryActionStub;
+import org.apache.maven.continuum.web.model.ProjectSummary;
+import org.apache.maven.continuum.xmlrpc.project.ContinuumProjectState;
+import org.jmock.Mock;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class SummaryActionTest
+    extends AbstractActionTest
+{
+    private SummaryActionStub action;
+
+    private Mock continuum;
+
+    private Mock configurationService;
+
+    private Mock buildsManager;
+
+    protected void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        action = new SummaryActionStub();
+
+        continuum = mock( Continuum.class );
+
+        configurationService = mock( ConfigurationService.class );
+
+        buildsManager = mock( BuildsManager.class );
+
+        action.setContinuum( (Continuum) continuum.proxy() );
+        action.setParallelBuildsManager( (BuildsManager) buildsManager.proxy() );
+    }
+
+    public void testLatestBuildIdWhenCurrentlyBuildingInDistributedBuild()
+        throws Exception
+    {
+        Collection<Project> projectsInGroup = createProjectsInGroup( 1, ContinuumProjectState.BUILDING );
+        Map<Integer, BuildResult> buildResults = createBuildResults( 0, ContinuumProjectState.OK );
+        Map<Integer, BuildResult> buildResultsInSuccess = new HashMap<Integer, BuildResult>();
+
+        continuum.expects( once() ).method( "getProjectsInGroup" ).will( returnValue( projectsInGroup ) );
+        continuum.expects( once() ).method( "getLatestBuildResults" ).will( returnValue( buildResults ) );
+        continuum.expects( once() ).method( "getBuildResultsInSuccess" ).will( returnValue( buildResultsInSuccess ) );
+
+        buildsManager.expects( once() ).method( "isInAnyBuildQueue" ).will( returnValue( false ) );
+        buildsManager.expects( once() ).method( "isInPrepareBuildQueue" ).will( returnValue( false ) );
+        buildsManager.expects( once() ).method( "isInAnyCheckoutQueue" ).will( returnValue( false ) );
+
+        continuum.expects( once() ).method( "getConfiguration" ).will( returnValue(
+            (ConfigurationService) configurationService.proxy() ) );
+        configurationService.expects( once() ).method( "isDistributedBuildEnabled" ).will( returnValue( true ) );
+
+        action.execute();
+        continuum.verify();
+
+        List<ProjectSummary> projects = action.getProjects();
+
+        assertNotNull( projects );
+        assertEquals( 1, projects.size() );
+
+        ProjectSummary summary = projects.get( 0 );
+        assertEquals( 0, summary.getLatestBuildId() );
+    }
+
+    public void testLatestBuildIdInDistributedBuild()
+        throws Exception
+    {
+        Collection<Project> projectsInGroup = createProjectsInGroup( 1, ContinuumProjectState.OK );
+        Map<Integer, BuildResult> buildResults = createBuildResults( 1, ContinuumProjectState.OK );
+        Map<Integer, BuildResult> buildResultsInSuccess = new HashMap<Integer, BuildResult>();
+
+        continuum.expects( once() ).method( "getProjectsInGroup" ).will( returnValue( projectsInGroup ) );
+        continuum.expects( once() ).method( "getLatestBuildResults" ).will( returnValue( buildResults ) );
+        continuum.expects( once() ).method( "getBuildResultsInSuccess" ).will( returnValue( buildResultsInSuccess ) );
+
+        buildsManager.expects( once() ).method( "isInAnyBuildQueue" ).will( returnValue( false ) );
+        buildsManager.expects( once() ).method( "isInPrepareBuildQueue" ).will( returnValue( false ) );
+        buildsManager.expects( once() ).method( "isInAnyCheckoutQueue" ).will( returnValue( false ) );
+
+        continuum.expects( once() ).method( "getConfiguration" ).will( returnValue(
+            (ConfigurationService) configurationService.proxy() ) );
+        configurationService.expects( once() ).method( "isDistributedBuildEnabled" ).will( returnValue( true ) );
+
+        action.execute();
+        continuum.verify();
+
+        List<ProjectSummary> projects = action.getProjects();
+
+        assertNotNull( projects );
+        assertEquals( 1, projects.size() );
+
+        ProjectSummary summary = projects.get( 0 );
+        assertEquals( 1, summary.getLatestBuildId() );
+    }
+
+    public void testLatestBuildIdWhenCurrentlyBuilding()
+        throws Exception
+    {
+        Collection<Project> projectsInGroup = createProjectsInGroup( 1, ContinuumProjectState.BUILDING );
+        Map<Integer, BuildResult> buildResults = createBuildResults( 1, ContinuumProjectState.BUILDING );
+        Map<Integer, BuildResult> buildResultsInSuccess = new HashMap<Integer, BuildResult>();
+
+        continuum.expects( once() ).method( "getProjectsInGroup" ).will( returnValue( projectsInGroup ) );
+        continuum.expects( once() ).method( "getLatestBuildResults" ).will( returnValue( buildResults ) );
+        continuum.expects( once() ).method( "getBuildResultsInSuccess" ).will( returnValue( buildResultsInSuccess ) );
+
+        buildsManager.expects( once() ).method( "isInAnyBuildQueue" ).will( returnValue( false ) );
+        buildsManager.expects( once() ).method( "isInPrepareBuildQueue" ).will( returnValue( false ) );
+        buildsManager.expects( once() ).method( "isInAnyCheckoutQueue" ).will( returnValue( false ) );
+
+        continuum.expects( once() ).method( "getConfiguration" ).will( returnValue(
+            (ConfigurationService) configurationService.proxy() ) );
+        configurationService.expects( once() ).method( "isDistributedBuildEnabled" ).will( returnValue( false ) );
+
+        action.execute();
+        continuum.verify();
+
+        List<ProjectSummary> projects = action.getProjects();
+
+        assertNotNull( projects );
+        assertEquals( 1, projects.size() );
+
+        ProjectSummary summary = projects.get( 0 );
+        assertEquals( 1, summary.getLatestBuildId() );
+    }
+
+    private Collection<Project> createProjectsInGroup( int projectId, int state )
+    {
+        Collection<Project> projectsInGroup = new ArrayList<Project>();
+
+        ProjectGroup group = new ProjectGroup();
+        group.setId( 1 );
+        group.setName( "test-group" );
+
+        Project project = new Project();
+        project.setId( projectId );
+        project.setName( "test-project" );
+        project.setVersion( "1.0" );
+        project.setBuildNumber( 1 );
+        project.setState( state );
+        project.setExecutorId( "maven2" );
+        project.setProjectGroup( group );
+
+        projectsInGroup.add( project );
+
+        return projectsInGroup;
+    }
+
+    private Map<Integer, BuildResult> createBuildResults( int projectId, int state )
+    {
+        Map<Integer, BuildResult> buildResults = new HashMap<Integer, BuildResult>();
+
+        BuildResult br = new BuildResult();
+        br.setId( 1 );
+        br.setStartTime( System.currentTimeMillis() );
+        br.setEndTime( System.currentTimeMillis() );
+        br.setState( state );
+
+        buildResults.put( projectId, br );
+
+        return buildResults;
+    }
+}
diff --git a/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/TestAction.java b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/TestAction.java
index a9a5a01..e105cb7 100644
--- a/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/TestAction.java
+++ b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/TestAction.java
@@ -1,5 +1,8 @@
 package org.apache.maven.continuum.web.action;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -28,12 +31,14 @@
 public class TestAction
     extends PlexusActionSupport
 {
+    private static final Logger logger = LoggerFactory.getLogger( TestAction.class );
+
     private String testString;
 
     public String execute()
         throws Exception
     {
-        getLogger().info( testString );
+        logger.info( testString );
 
         return INPUT;
     }
diff --git a/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/stub/AddMavenProjectStub.java b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/stub/AddMavenProjectStub.java
new file mode 100644
index 0000000..cf2d747
--- /dev/null
+++ b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/stub/AddMavenProjectStub.java
@@ -0,0 +1,48 @@
+package org.apache.maven.continuum.web.action.stub;
+
+/*
+ * 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 org.apache.maven.continuum.ContinuumException;
+import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
+import org.apache.maven.continuum.web.action.AddMavenProjectAction;
+import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
+
+/**
+ * A stubbed implementation of {@link org.apache.maven.continuum.web.action.AddMavenProjectAction} useful for testing
+ * the abstract class's functionality.
+ */
+public class AddMavenProjectStub
+    extends AddMavenProjectAction
+{
+    @Override
+    protected void checkAddProjectGroupAuthorization()
+        throws AuthorizationRequiredException
+    {
+        // skip authorization check
+    }
+
+    @Override
+    protected ContinuumProjectBuildingResult doExecute( String pomUrl, int selectedProjectGroup, boolean checkProtocol,
+                                                        boolean scmUseCache )
+        throws ContinuumException
+    {
+        return new ContinuumProjectBuildingResult();
+    }
+}
diff --git a/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/stub/AddProjectActionStub.java b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/stub/AddProjectActionStub.java
new file mode 100644
index 0000000..ceeba86
--- /dev/null
+++ b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/stub/AddProjectActionStub.java
@@ -0,0 +1,57 @@
+package org.apache.maven.continuum.web.action.stub;
+
+/*
+ * 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 org.apache.maven.continuum.web.action.AddProjectAction;
+
+/**
+ * Stub for {@link AddProjectAction}
+ *
+ * @author <a href="mailto:jzurbano@apache.org">jzurbano</a>
+ */
+public class AddProjectActionStub
+    extends AddProjectAction
+{
+    public String input()
+    {
+        return INPUT;
+    }
+
+    private void initializeProjectGroupName()
+    {
+        setProjectGroupName( "Test Project Group" );
+    }
+
+    private boolean isAuthorizedToAddProjectToGroup( String projectGroupName )
+    {
+        return true;
+    }
+
+    protected void checkAddProjectGroupAuthorization()
+    {
+        // skip authorization check
+    }
+
+    protected void checkAddProjectToGroupAuthorization( String projectGroupName )
+    {
+        // skip authorization check
+    }
+}
+
diff --git a/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/stub/BuildResultActionStub.java b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/stub/BuildResultActionStub.java
new file mode 100644
index 0000000..8593a5f
--- /dev/null
+++ b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/stub/BuildResultActionStub.java
@@ -0,0 +1,36 @@
+package org.apache.maven.continuum.web.action.stub;
+
+/*
+ * 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 org.apache.maven.continuum.web.action.BuildResultAction;
+
+public class BuildResultActionStub
+    extends BuildResultAction
+{
+    public String getProjectGroupName()
+    {
+        return "test-group";
+    }
+
+    protected void checkViewProjectGroupAuthorization( String resource )
+    {
+        // skip authorization check
+    }
+}
diff --git a/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/stub/ProjectGroupActionStub.java b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/stub/ProjectGroupActionStub.java
new file mode 100644
index 0000000..2db7c10
--- /dev/null
+++ b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/stub/ProjectGroupActionStub.java
@@ -0,0 +1,48 @@
+package org.apache.maven.continuum.web.action.stub;
+
+/*
+ * 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 org.apache.maven.continuum.web.action.ProjectGroupAction;
+import org.codehaus.plexus.redback.users.User;
+import org.codehaus.plexus.redback.users.UserNotFoundException;
+import org.codehaus.plexus.redback.users.jdo.JdoUser;
+
+public class ProjectGroupActionStub
+    extends ProjectGroupAction
+{
+    public String getProjectGroupName()
+    {
+        return "test-group";
+    }
+
+    protected void checkViewProjectGroupAuthorization( String resource )
+    {
+        // skip authorization check
+    }
+
+    protected User getUser( String principal )
+        throws UserNotFoundException
+    {
+        User user = new JdoUser();
+        user.setUsername( principal );
+
+        return user;
+    }
+}
diff --git a/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/stub/SummaryActionStub.java b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/stub/SummaryActionStub.java
new file mode 100644
index 0000000..3843ec3
--- /dev/null
+++ b/continuum-webapp/src/test/java/org/apache/maven/continuum/web/action/stub/SummaryActionStub.java
@@ -0,0 +1,36 @@
+package org.apache.maven.continuum.web.action.stub;
+
+/*
+ * 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 org.apache.maven.continuum.web.action.SummaryAction;
+
+public class SummaryActionStub
+    extends SummaryAction
+{
+    public String getProjectGroupName()
+    {
+        return "test-group";
+    }
+
+    protected void checkViewProjectGroupAuthorization( String resource )
+    {
+        // skip authorization check
+    }
+}
diff --git a/continuum-webapp/src/test/resources/log4j.xml b/continuum-webapp/src/test/resources/log4j.xml
deleted file mode 100644
index f07072a..0000000
--- a/continuum-webapp/src/test/resources/log4j.xml
+++ /dev/null
@@ -1,112 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
-
-<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
-
-  <appender name="console" class="org.apache.log4j.ConsoleAppender">
-    <layout class="org.apache.log4j.PatternLayout">
-      <param name="Target" value="System.out"/>
-      <param name="ConversionPattern" value="%d [%t] %-5p %c %x - %m%n"/>
-    </layout>
-  </appender>
-
-  <!-- Help identify bugs during testing -->
-  <logger name="org.apache.maven">
-    <level value="info"/>
-  </logger>
-
-  <logger name="org.apache.maven.continuum">
-    <level value="info" />
-  </logger>
-
-  <logger name="org.apache.maven.scm">
-    <level value="debug" />
-  </logger>
-  
-  <logger name="org.apache.continuum.scm.manager.Slf4jScmLogger">
-    <level value="debug" />
-  </logger>  
-
-  <logger name="org.codehaus.plexus.redback">
-    <level value="info"/>
-  </logger>
-
-  <!-- squelch noisy objects (for now) -->
-  <logger name="org.apache.commons">
-    <level value="warn"/>
-  </logger>
-
-  <logger name="net.sf.ehcache">
-    <level value="warn"/>
-  </logger>
-
-  <logger name="org.codehaus.plexus.mailsender.MailSender">
-    <level value="info"/>
-  </logger>
-
-  <logger name="org.codehaus.plexus.velocity">
-    <level value="error"/>
-  </logger>
-
-  <logger name="org.quartz">
-    <level value="info"/>
-  </logger>
-
-  <logger name="org.apache.jasper">
-    <level value="info"/>
-  </logger>
-
-  <logger name="com.opensymphony.xwork2">
-    <level value="info"/>
-  </logger>
-	
-  <logger name="org.apache.struts2">
-    <level value="info"/>
-  </logger>
-
-  <!-- CONTINUUM-1228 -->
-  <logger name="com.opensymphony.xwork2.util.OgnlUtil">
-    <level value="error"/>
-  </logger>
-
-  <logger name="org.codehaus.plexus.PlexusContainer">
-    <level value="info"/>
-  </logger>
-
-  <logger name="JPOX">
-    <level value="warn"/>
-  </logger>
-
-  <logger name="JPOX.MetaData">
-    <level value="error"/>
-  </logger>
-
-  <logger name="JPOX.RDBMS.SQL">
-    <level value="error"/>
-  </logger>
-
-  <logger name="SQL">
-    <level value="error"/>
-  </logger>
-
-  <logger name="freemarker">
-    <level value="warn"/>
-  </logger>
-
-  <logger name="org.codehaus.plexus.component.manager.ClassicSingletonComponentManager">
-    <level value="error"/>
-  </logger>
-  
-  <logger name="org.springframework.beans.factory.xml.XmlBeanDefinitionReader">
-    <level value="error"/>
-  </logger>
-  <logger name="org.springframework.beans.factory.support.DefaultListableBeanFactory">
-    <level value="error"/>
-  </logger>
-
-  <root>
-    <priority value="info" />
-    <appender-ref ref="console" />
-  </root>
-
-</log4j:configuration>
diff --git a/continuum-webapp/src/test/tomcat/tomcat-context-continuum.xml b/continuum-webapp/src/test/tomcat/tomcat-context-continuum.xml
new file mode 100644
index 0000000..25d73e9
--- /dev/null
+++ b/continuum-webapp/src/test/tomcat/tomcat-context-continuum.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ 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.
+  -->
+
+<Context path="/continuum">
+  <Resource name="jdbc/users" auth="Container" type="javax.sql.DataSource"
+            username="sa"
+            password=""
+            driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
+            url="jdbc:derby:${catalina.base}/target/database/users;create=true"
+      />
+  <Resource name="jdbc/continuum" auth="Container" type="javax.sql.DataSource"
+            username="sa"
+            password=""
+            driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
+            url="jdbc:derby:${catalina.base}/target/database/continuum;create=true"
+      />
+  <Resource name="mail/Session" auth="Container"
+            type="javax.mail.Session"
+            mail.smtp.host="localhost"/>
+
+</Context>
diff --git a/continuum-xmlrpc/continuum-xmlrpc-api/pom.xml b/continuum-xmlrpc/continuum-xmlrpc-api/pom.xml
index 44c0273..3289c42 100644
--- a/continuum-xmlrpc/continuum-xmlrpc-api/pom.xml
+++ b/continuum-xmlrpc/continuum-xmlrpc-api/pom.xml
@@ -1,40 +1,33 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
+  ~ 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.
+  -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <groupId>org.apache.continuum</groupId>
     <artifactId>continuum-xmlrpc</artifactId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>continuum-xmlrpc-api</artifactId>
   <name>Continuum :: XMLRPC :: API</name>
 
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.xmlrpc</groupId>
-      <artifactId>xmlrpc-common</artifactId>
-      <version>3.1</version>
-    </dependency>
-  </dependencies>
-
   <build>
     <plugins>
       <plugin>
@@ -47,15 +40,38 @@
               <goal>java</goal>
             </goals>
             <configuration>
-              <model>src/main/mdo/continuum-service.xml</model>
+              <models>
+                <model>src/main/mdo/continuum-service.xml</model>
+              </models>
             </configuration>
           </execution>
         </executions>
         <configuration>
-          <version>1.1.1</version>
+          <version>1.4.1</version>
           <packageWithVersion>false</packageWithVersion>
+          <useJava5>true</useJava5>
         </configuration>
       </plugin>
+      <plugin>
+        <groupId>com.google.code.maven-replacer-plugin</groupId>
+        <artifactId>replacer</artifactId>
+        <executions>
+          <execution>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>replace</goal>
+            </goals>
+            <configuration>
+              <basedir>${basedir}</basedir>
+              <includes>
+                <include>target/generated-sources/**</include>
+              </includes>
+              <token>Generated by Modello.*</token>
+              <value>Generated by Modello</value>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
     </plugins>
   </build>
 </project>
diff --git a/continuum-xmlrpc/continuum-xmlrpc-api/src/main/java/org/apache/maven/continuum/xmlrpc/ContinuumService.java b/continuum-xmlrpc/continuum-xmlrpc-api/src/main/java/org/apache/maven/continuum/xmlrpc/ContinuumService.java
index e417086..f0ee6b8 100644
--- a/continuum-xmlrpc/continuum-xmlrpc-api/src/main/java/org/apache/maven/continuum/xmlrpc/ContinuumService.java
+++ b/continuum-xmlrpc/continuum-xmlrpc-api/src/main/java/org/apache/maven/continuum/xmlrpc/ContinuumService.java
@@ -19,14 +19,14 @@
  * under the License.
  */
 
-import java.util.List;
-import java.util.Map;
-
+import org.apache.continuum.xmlrpc.release.ContinuumReleaseResult;
 import org.apache.continuum.xmlrpc.repository.DirectoryPurgeConfiguration;
 import org.apache.continuum.xmlrpc.repository.LocalRepository;
 import org.apache.continuum.xmlrpc.repository.RepositoryPurgeConfiguration;
-import org.apache.continuum.xmlrpc.release.ContinuumReleaseResult;
+import org.apache.continuum.xmlrpc.utils.BuildTrigger;
 import org.apache.maven.continuum.xmlrpc.project.AddingResult;
+import org.apache.maven.continuum.xmlrpc.project.BuildAgentConfiguration;
+import org.apache.maven.continuum.xmlrpc.project.BuildAgentGroupConfiguration;
 import org.apache.maven.continuum.xmlrpc.project.BuildDefinition;
 import org.apache.maven.continuum.xmlrpc.project.BuildDefinitionTemplate;
 import org.apache.maven.continuum.xmlrpc.project.BuildProjectTask;
@@ -36,12 +36,17 @@
 import org.apache.maven.continuum.xmlrpc.project.ProjectGroup;
 import org.apache.maven.continuum.xmlrpc.project.ProjectGroupSummary;
 import org.apache.maven.continuum.xmlrpc.project.ProjectNotifier;
+import org.apache.maven.continuum.xmlrpc.project.ProjectScmRoot;
 import org.apache.maven.continuum.xmlrpc.project.ProjectSummary;
+import org.apache.maven.continuum.xmlrpc.project.ReleaseListenerSummary;
 import org.apache.maven.continuum.xmlrpc.project.Schedule;
 import org.apache.maven.continuum.xmlrpc.system.Installation;
 import org.apache.maven.continuum.xmlrpc.system.Profile;
 import org.apache.maven.continuum.xmlrpc.system.SystemConfiguration;
-import org.apache.xmlrpc.XmlRpcException;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
@@ -59,22 +64,20 @@
      * @param projectGroupId The project group Id
      * @return List of {@link ProjectSummary}
      * @throws Exception
-     * @throws XmlRpcException
      */
     List<ProjectSummary> getProjects( int projectGroupId )
         throws Exception;
 
-    
-   /**
-    * Same method but compatible with standard XMLRPC
-    * 
-    * @param projectGroupId The project group Id
-    * @return List of {@link ProjectSummary} as RPC value
-    * @throws Exception
-    */
-   List<Object> getProjectsRPC(int projectGroupId)throws Exception;   
-    
-    
+    /**
+     * Same method but compatible with standard XMLRPC
+     *
+     * @param projectGroupId The project group Id
+     * @return List of {@link ProjectSummary} as RPC value
+     * @throws Exception
+     */
+    List<Object> getProjectsRPC( int projectGroupId )
+        throws Exception;
+
     /**
      * Get a project.
      *
@@ -87,13 +90,14 @@
 
     /**
      * Same method but compatible with standard XMLRPC
-     * 
+     *
      * @param projectId the project id
      * @return The project summary as RPC value
      * @throws Exception
      */
-    Map<String,Object> getProjectSummaryRPC(int projectId)throws Exception;   
-    
+    Map<String, Object> getProjectSummaryRPC( int projectId )
+        throws Exception;
+
     /**
      * Get a project with all details.
      *
@@ -106,13 +110,14 @@
 
     /**
      * Same method but compatible with standard XMLRPC
-     * 
+     *
      * @param projectId the project id
      * @return The project as RPC value
      * @throws Exception
      */
-    Map<String,Object> getProjectWithAllDetailsRPC(int projectId)throws Exception;   
-    
+    Map<String, Object> getProjectWithAllDetailsRPC( int projectId )
+        throws Exception;
+
     /**
      * Remove a project.
      *
@@ -133,34 +138,38 @@
 
     /**
      * Same method but compatible with standard XMLRPC
-     * 
+     *
      * @param project The project to update
      * @return The project as RPC value
      * @throws Exception
      */
-    Map<String,Object> updateProjectRPC(Map<String,Object> project)throws Exception;
+    Map<String, Object> updateProjectRPC( Map<String, Object> project )
+        throws Exception;
+
     // ----------------------------------------------------------------------
     // Projects Groups
     // ----------------------------------------------------------------------
 
     /**
      * Get a project groups.
-     * 
+     *
      * @param projectGroupId the id
      * @return project group
      * @throws Exception
      */
-    ProjectGroup getProjectGroup(int projectGroupId) throws Exception;
-    
+    ProjectGroup getProjectGroup( int projectGroupId )
+        throws Exception;
+
     /**
      * Same method but compatible with standard XMLRPC
-     * 
+     *
      * @param projectGroupId the id
      * @return project group as RPC value
      * @throws Exception
      */
-    Map<String, Object> getProjectGroupRPC(int projectGroupId) throws Exception;
-    
+    Map<String, Object> getProjectGroupRPC( int projectGroupId )
+        throws Exception;
+
     /**
      * Get all project groups.
      *
@@ -172,12 +181,13 @@
 
     /**
      * Same method but compatible with standard XMLRPC
-     * 
+     *
      * @return List of {@link ProjectGroupSummary} as RPC value
      * @throws Exception
      */
-    List<Object> getAllProjectGroupsRPC()throws Exception;   
-    
+    List<Object> getAllProjectGroupsRPC()
+        throws Exception;
+
     /**
      * Get all project groups with all details (project summaries, notifiers, build definitions).
      *
@@ -189,12 +199,13 @@
 
     /**
      * Same method but compatible with standard XMLRPC
-     * 
+     *
      * @return List of {@link ProjectGroup} as RPC value
      * @throws Exception
      */
-    List<Object> getAllProjectGroupsWithAllDetailsRPC()throws Exception;   
-    
+    List<Object> getAllProjectGroupsWithAllDetailsRPC()
+        throws Exception;
+
     /**
      * Get all project groups with all details.
      *
@@ -217,13 +228,14 @@
 
     /**
      * Same method but compatible with standard XMLRPC
-     * 
+     *
      * @param projectGroupId The project group id
      * @return The project group summary as RPC value
      * @throws Exception
      */
-    Map<String,Object> getProjectGroupSummaryRPC(int projectGroupId)throws Exception;   
-    
+    Map<String, Object> getProjectGroupSummaryRPC( int projectGroupId )
+        throws Exception;
+
     /**
      * Get a project group with all details.
      *
@@ -236,13 +248,14 @@
 
     /**
      * Same method but compatible with standard XMLRPC
-     * 
+     *
      * @param projectGroupId The project group id
      * @return The project group as RPC value
      * @throws Exception
      */
-    Map<String,Object> getProjectGroupWithProjectsRPC(int projectGroupId)throws Exception;   
-    
+    Map<String, Object> getProjectGroupWithProjectsRPC( int projectGroupId )
+        throws Exception;
+
     /**
      * Remove a project group.
      *
@@ -263,13 +276,14 @@
 
     /**
      * Same method but compatible with standard XMLRPC
-     * 
+     *
      * @param projectGroup The project group to update
      * @return The project group as RPC value
      * @throws Exception
      */
-    Map<String,Object> updateProjectGroupRPC(Map<String,Object> projectGroup)throws Exception;   
-    
+    Map<String, Object> updateProjectGroupRPC( Map<String, Object> projectGroup )
+        throws Exception;
+
     /**
      * Add a project Group.
      *
@@ -281,8 +295,10 @@
      */
     ProjectGroupSummary addProjectGroup( String groupName, String groupId, String description )
         throws Exception;
-    
-    int removeBuildDefinitionFromProjectGroup(int projectGroupId, int buildDefinitionId) throws Exception;
+
+    int removeBuildDefinitionFromProjectGroup( int projectGroupId, int buildDefinitionId )
+        throws Exception;
+
     /**
      * Same method but compatible with standard XMLRPC
      *
@@ -292,37 +308,51 @@
      * @return the project group summary of the created project group as RPC value
      * @throws Exception
      */
-    Map<String,Object> addProjectGroupRPC( String groupName, String groupId, String description )
+    Map<String, Object> addProjectGroupRPC( String groupName, String groupId, String description )
         throws Exception;
-    
-    ProjectNotifier getNotifier(int projectid, int notifierId) throws Exception;
-  
-    Map<String, Object> getNotifierRPC(int projectid, int notifierId) throws Exception;
-    
-    ProjectNotifier getGroupNotifier(int projectgroupid, int notifierId) throws Exception;
-    
-    Map<String, Object> getGroupNotifierRPC(int projectgroupid, int notifierId) throws Exception;
-    
-    ProjectNotifier updateGroupNotifier(int projectgroupid, ProjectNotifier newNotifier) throws Exception;
-    
-    Map<String, Object> updateGroupNotifierRPC(int projectgroupid, Map<String, Object> newNotifier) throws Exception;
-    
-    ProjectNotifier updateNotifier(int projectid, ProjectNotifier newNotifier) throws Exception;
-    
-    Map<String, Object> updateNotifierRPC(int projectid, Map<String, Object> newNotifier) throws Exception;
-    
-    int removeGroupNotifier(int projectgroupid, int notifierId) throws Exception;
-    
-    int removeNotifier(int projectid, int notifierId) throws Exception;
-    
-    ProjectNotifier addNotifier(int projectid, ProjectNotifier newNotifier) throws Exception;
-    
-    ProjectNotifier addGroupNotifier(int projectgroupid, ProjectNotifier newNotifier) throws Exception;
-    
-    Map<String, Object> addNotifierRPC(int projectid, Map<String, Object> newNotifier) throws Exception;
-    
-    Map<String, Object> addGroupNotifierRPC(int projectgroupid, Map<String, Object> newNotifier) throws Exception;
-    
+
+    ProjectNotifier getNotifier( int projectid, int notifierId )
+        throws Exception;
+
+    Map<String, Object> getNotifierRPC( int projectid, int notifierId )
+        throws Exception;
+
+    ProjectNotifier getGroupNotifier( int projectgroupid, int notifierId )
+        throws Exception;
+
+    Map<String, Object> getGroupNotifierRPC( int projectgroupid, int notifierId )
+        throws Exception;
+
+    ProjectNotifier updateGroupNotifier( int projectgroupid, ProjectNotifier newNotifier )
+        throws Exception;
+
+    Map<String, Object> updateGroupNotifierRPC( int projectgroupid, Map<String, Object> newNotifier )
+        throws Exception;
+
+    ProjectNotifier updateNotifier( int projectid, ProjectNotifier newNotifier )
+        throws Exception;
+
+    Map<String, Object> updateNotifierRPC( int projectid, Map<String, Object> newNotifier )
+        throws Exception;
+
+    int removeGroupNotifier( int projectgroupid, int notifierId )
+        throws Exception;
+
+    int removeNotifier( int projectid, int notifierId )
+        throws Exception;
+
+    ProjectNotifier addNotifier( int projectid, ProjectNotifier newNotifier )
+        throws Exception;
+
+    ProjectNotifier addGroupNotifier( int projectgroupid, ProjectNotifier newNotifier )
+        throws Exception;
+
+    Map<String, Object> addNotifierRPC( int projectid, Map<String, Object> newNotifier )
+        throws Exception;
+
+    Map<String, Object> addGroupNotifierRPC( int projectgroupid, Map<String, Object> newNotifier )
+        throws Exception;
+
     // ----------------------------------------------------------------------
     // Build Definitions
     // ----------------------------------------------------------------------
@@ -346,7 +376,7 @@
      */
     List<Object> getBuildDefinitionsForProjectRPC( int projectId )
         throws Exception;
-    
+
     /**
      * Get the build definitions list of the project group.
      *
@@ -366,12 +396,32 @@
      */
     List<Object> getBuildDefinitionsForProjectGroupRPC( int projectGroupId )
         throws Exception;
-    
+
+    /**
+     * Get the build definition
+     *
+     * @param buildDefinitionId The build definition id
+     * @return The build definition
+     * @throws Exception
+     */
+    BuildDefinition getBuildDefinition( int buildDefinitionId )
+        throws Exception;
+
+    /**
+     * Same method but compatible with standard XMLRPC
+     *
+     * @param buildDefinitionId The build definition id
+     * @return The build definition as RPC value
+     * @throws Exception
+     */
+    Map<String, Object> getBuildDefinitionRPC( int buildDefinitionId )
+        throws Exception;
+
     /**
      * Update a project build definition.
      *
      * @param projectId The project id
-     * @param buildDef  The build defintion to update
+     * @param buildDef  The build definition to update
      * @return the updated build definition
      * @throws Exception
      */
@@ -382,18 +432,18 @@
      * Same method but compatible with standard XMLRPC
      *
      * @param projectId The project id
-     * @param buildDef  The build defintion to update
+     * @param buildDef  The build definition to update
      * @return the updated build definition as RPC value
      * @throws Exception
      */
-    Map<String,Object> updateBuildDefinitionForProjectRPC( int projectId, Map<String,Object> buildDef )
+    Map<String, Object> updateBuildDefinitionForProjectRPC( int projectId, Map<String, Object> buildDef )
         throws Exception;
 
     /**
      * Update a project group build definition.
      *
      * @param projectGroupId The project group id
-     * @param buildDef       The build defintion to update
+     * @param buildDef       The build definition to update
      * @return the updated build definition
      * @throws Exception
      */
@@ -404,18 +454,18 @@
      * Same method but compatible with standard XMLRPC
      *
      * @param projectGroupId The project group id
-     * @param buildDef  The build defintion to update
+     * @param buildDef       The build definition to update
      * @return the updated build definition as RPC value
      * @throws Exception
      */
-    Map<String,Object> updateBuildDefinitionForProjectGroupRPC( int projectGroupId, Map<String,Object> buildDef )
+    Map<String, Object> updateBuildDefinitionForProjectGroupRPC( int projectGroupId, Map<String, Object> buildDef )
         throws Exception;
-    
+
     /**
      * Add a project build definition.
      *
      * @param projectId The project id
-     * @param buildDef  The build defintion to update
+     * @param buildDef  The build definition to update
      * @return the added build definition
      * @throws Exception
      */
@@ -426,18 +476,18 @@
      * Same method but compatible with standard XMLRPC
      *
      * @param projectId The project id
-     * @param buildDef  The build defintion to update
+     * @param buildDef  The build definition to update
      * @return the added build definition as RPC value
      * @throws Exception
      */
-    Map<String,Object> addBuildDefinitionToProjectRPC( int projectId, Map<String,Object> buildDef )
+    Map<String, Object> addBuildDefinitionToProjectRPC( int projectId, Map<String, Object> buildDef )
         throws Exception;
-    
+
     /**
      * Add a project group buildDefinition.
      *
      * @param projectGroupId The project group id
-     * @param buildDef       The build defintion to update
+     * @param buildDef       The build definition to update
      * @return the build definition added
      * @throws Exception
      */
@@ -448,13 +498,13 @@
      * Same method but compatible with standard XMLRPC
      *
      * @param projectGroupId The project group id
-     * @param buildDef  The build defintion to update
+     * @param buildDef       The build definition to update
      * @return the added build definition as RPC value
      * @throws Exception
      */
-    Map<String,Object> addBuildDefinitionToProjectGroupRPC( int projectGroupId, Map<String,Object> buildDef )
+    Map<String, Object> addBuildDefinitionToProjectGroupRPC( int projectGroupId, Map<String, Object> buildDef )
         throws Exception;
-    
+
     /**
      * Get the build definition templates list.
      *
@@ -472,6 +522,7 @@
      */
     List<Object> getBuildDefinitionTemplatesRPC()
         throws Exception;
+
     // ----------------------------------------------------------------------
     // Building
     // ----------------------------------------------------------------------
@@ -515,6 +566,29 @@
         throws Exception;
 
     /**
+     * Forced build the project
+     *
+     * @param projectId    The project id
+     * @param buildTrigger The build trigger
+     * @return
+     * @throws Exception
+     */
+    int buildProject( int projectId, BuildTrigger buildTrigger )
+        throws Exception;
+
+    /**
+     * Forced build the project
+     *
+     * @param projectId         The project id
+     * @param buildDefinitionId The build definition id
+     * @param buildTrigger      The build trigger
+     * @return
+     * @throws Exception
+     */
+    int buildProject( int projectId, int buildDefinitionId, BuildTrigger buildTrigger )
+        throws Exception;
+
+    /**
      * Build the project group with the default build definition.
      *
      * @param projectGroupId The project group id
@@ -534,6 +608,30 @@
         throws Exception;
 
     // ----------------------------------------------------------------------
+    // SCM roots
+    // ----------------------------------------------------------------------
+
+    /**
+     * Get the SCM roots for all projects in a project group
+     *
+     * @param projectGroupId the project group id
+     * @return
+     * @throws Exception
+     */
+    List<ProjectScmRoot> getProjectScmRootByProjectGroup( int projectGroupId )
+        throws Exception;
+
+    /**
+     * Get the SCM root for a specific project
+     *
+     * @param projectId the project id
+     * @return
+     * @throws Exception
+     */
+    ProjectScmRoot getProjectScmRootByProject( int projectId )
+        throws Exception;
+
+    // ----------------------------------------------------------------------
     // Build Results
     // ----------------------------------------------------------------------
 
@@ -554,9 +652,9 @@
      * @return The build result as RPC value
      * @throws Exception
      */
-    Map<String,Object> getLatestBuildResultRPC( int projectId )
+    Map<String, Object> getLatestBuildResultRPC( int projectId )
         throws Exception;
-    
+
     /**
      * Returns the build result.
      *
@@ -576,9 +674,9 @@
      * @return The build result as RPC value
      * @throws Exception
      */
-    Map<String,Object> getBuildResultRPC( int projectId, int buildId )
+    Map<String, Object> getBuildResultRPC( int projectId, int buildId )
         throws Exception;
-    
+
     /**
      * Returns the project build result summary list.
      *
@@ -598,7 +696,7 @@
      */
     List<Object> getBuildResultsForProjectRPC( int projectId )
         throws Exception;
-    
+
     /**
      * Remove the project build result.
      *
@@ -616,9 +714,9 @@
      * @return 0
      * @throws Exception
      */
-    int removeBuildResultRPC( Map<String,Object> br )
+    int removeBuildResultRPC( Map<String, Object> br )
         throws Exception;
-    
+
     /**
      * Returns the build output.
      *
@@ -651,9 +749,9 @@
      * @return The result of the action with the list of projects created as RPC value
      * @throws Exception
      */
-    Map<String,Object>  addMavenTwoProjectRPC( String url )
+    Map<String, Object> addMavenTwoProjectRPC( String url )
         throws Exception;
-        
+
     /**
      * Add a maven 2.x project from an url.
      *
@@ -668,38 +766,100 @@
     /**
      * Same method but compatible with standard XMLRPC
      *
-     * @param url The POM url
+     * @param url            The POM url
      * @param projectGroupId The id of the group where projects will be stored
      * @return The result of the action with the list of projects created as RPC value
      * @throws Exception
      */
-    Map<String,Object>  addMavenTwoProjectRPC( String url, int projectGroupId )
+    Map<String, Object> addMavenTwoProjectRPC( String url, int projectGroupId )
         throws Exception;
 
-    // ----------------------------------------------------------------------
-    // Maven 1.x projects
-    // ----------------------------------------------------------------------
-
     /**
-     * Add a maven 1.x project from an url.
+     * Add a maven 2.x project from an url.
      *
-     * @param url The POM url
+     * @param url            The POM url
+     * @param projectGroupId The id of the group where projects will be stored
      * @return The result of the action with the list of projects created
      * @throws Exception
+     * @Param checkoutInSingleDirectory Determines whether the project will be stored on a single directory
      */
-    AddingResult addMavenOneProject( String url )
+    AddingResult addMavenTwoProject( String url, int projectGroupId, boolean checkoutInSingleDirectory )
         throws Exception;
 
     /**
      * Same method but compatible with standard XMLRPC
      *
-     * @param url The POM url
+     * @param url            The POM url
+     * @param projectGroupId The id of the group where projects will be stored
+     * @return The result of the action with the list of projects created as RPC value
+     * @throws Exception
+     * @Param checkoutInSingleDirectory Determines whether the project will be stored on a single directory
+     */
+    Map<String, Object> addMavenTwoProjectRPC( String url, int projectGroupId, boolean checkoutInSingleDirectory )
+        throws Exception;
+
+    /**
+     * Add a maven 2.x multi-module project from a url and add it to Continuum as a single project instead of as
+     * multiple projects (one project per module). To add a multi-module project with its modules as separate Continuum
+     * projects, use ContinuumService#addMavenTwoProject( String url, int projectGroupId, boolean
+     * checkoutInSingleDirectory) instead.
+     *
+     * @param url
+     * @param projectGroupId
+     * @return
+     * @throws Exception
+     */
+    AddingResult addMavenTwoProjectAsSingleProject( String url, int projectGroupId )
+        throws Exception;
+
+    /**
+     * Same method but compatible with standard XMLRPC
+     *
+     * @param url
+     * @param projectGroupId
+     * @return
+     * @throws Exception
+     */
+    Map<String, Object> addMavenTwoProjectAsSingleProjectRPC( String url, int projectGroupId )
+        throws Exception;
+
+    /**
+     * Add a maven 2.x multi-module project from a url
+     *
+     * @param url                       The POM url
+     * @param projectGroupId            The id of the group where projects will be stored
+     * @param checkProtocol             Determines whether the protocol will be checked
+     * @param useCredentialsCache       Determines whether user credentials will be cached
+     * @param recursiveProjects         Determines whether to load recursive projects
+     * @param checkoutInSingleDirectory Determines whether the project will be stored on a single directory
+     * @return The result of the action with the list of projects created
+     * @throws Exception
+     */
+    AddingResult addMavenTwoProject( String url, int projectGroupId, boolean checkProtocol, boolean useCredentialsCache,
+                                     boolean recursiveProjects, boolean checkoutInSingleDirectory )
+        throws Exception;
+
+    /**
+     * Same method but compatible with standard XMLRPC
+     *
+     * @param url                       The POM url
+     * @param projectGroupId            The id of the group where projects will be stored
+     * @param checkProtocol             Determines whether the protocol will be checked
+     * @param useCredentialsCache       Determines whether user credentials will be cached
+     * @param recursiveProjects         Determines whether to load recursive projects
+     * @param checkoutInSingleDirectory Determines whether the project will be stored on a single directory
      * @return The result of the action with the list of projects created as RPC value
      * @throws Exception
      */
-    Map<String,Object>  addMavenOneProjectRPC( String url )
+    Map<String, Object> addMavenTwoProjectRPC( String url, int projectGroupId, boolean checkProtocol,
+                                               boolean useCredentialsCache, boolean recursiveProjects,
+                                               boolean checkoutInSingleDirectory )
         throws Exception;
 
+    // ----------------------------------------------------------------------
+    // Maven 1.x projects
+    // ----------------------------------------------------------------------
+
     /**
      * Add a maven 1.x project from an url.
      *
@@ -714,39 +874,19 @@
     /**
      * Same method but compatible with standard XMLRPC
      *
-     * @param url The POM url
+     * @param url            The POM url
      * @param projectGroupId The id of the group where projects will be stored
      * @return The result of the action with the list of projects created as RPC value
      * @throws Exception
      */
-    Map<String,Object>  addMavenOneProjectRPC( String url, int projectGroupId )
+    Map<String, Object> addMavenOneProjectRPC( String url, int projectGroupId )
         throws Exception;
-    
+
     // ----------------------------------------------------------------------
     // Maven ANT projects
     // ----------------------------------------------------------------------
 
     /**
-     * Add an ANT project.
-     *
-     * @param project The project to add. name, version and scm informations are required
-     * @return The project populated with the id.
-     * @throws Exception
-     */
-    ProjectSummary addAntProject( ProjectSummary project )
-        throws Exception;
-
-    /**
-     * Same method but compatible with standard XMLRPC
-     *
-     * @param project The project to add. name, version and scm informations are required
-     * @return The project populated with the id as RPC value
-     * @throws Exception
-     */
-    Map<String,Object>  addAntProjectRPC( Map<String,Object> project)
-        throws Exception;
-    
-    /**
      * Add an ANT project in the specified group.
      *
      * @param project        The project to add. name, version and scm informations are required
@@ -765,34 +905,14 @@
      * @return The project populated with the id as RPC value
      * @throws Exception
      */
-    Map<String,Object>  addAntProjectRPC( Map<String,Object> project, int projectGroupId )
+    Map<String, Object> addAntProjectRPC( Map<String, Object> project, int projectGroupId )
         throws Exception;
-    
+
     // ----------------------------------------------------------------------
     // Maven Shell projects
     // ----------------------------------------------------------------------
 
     /**
-     * Add an shell project.
-     *
-     * @param project The project to add. name, version and scm informations are required
-     * @return The project populated with the id.
-     * @throws Exception
-     */
-    ProjectSummary addShellProject( ProjectSummary project )
-        throws Exception;
-
-    /**
-     * Same method but compatible with standard XMLRPC
-     *
-     * @param project The project to add. name, version and scm informations are required
-     * @return The project populated with the id as RPC value
-     * @throws Exception
-     */
-    Map<String,Object>  addShellProjectRPC( Map<String,Object> project )
-        throws Exception;
-    
-    /**
      * Add an shell project in the specified group.
      *
      * @param project        The project to add. name, version and scm informations are required
@@ -806,14 +926,14 @@
     /**
      * Same method but compatible with standard XMLRPC
      *
-     * @param project The project to add. name, version and scm informations are required
+     * @param project        The project to add. name, version and scm informations are required
      * @param projectGroupId The id of the group where projects will be stored
      * @return The project populated with the id as RPC value
      * @throws Exception
      */
-    Map<String,Object>  addShellProjectRPC( Map<String,Object> project, int projectGroupId )
+    Map<String, Object> addShellProjectRPC( Map<String, Object> project, int projectGroupId )
         throws Exception;
-    
+
     // ----------------------------------------------------------------------
     // ADMIN TASKS
     // ----------------------------------------------------------------------
@@ -839,7 +959,7 @@
      */
     List<Object> getSchedulesRPC()
         throws Exception;
-    
+
     /**
      * Return the schedule defined by this id.
      *
@@ -857,9 +977,9 @@
      * @return The schedule as RPC value.
      * @throws Exception
      */
-    Map<String,Object> getScheduleRPC(int scheduleId)
+    Map<String, Object> getScheduleRPC( int scheduleId )
         throws Exception;
-    
+
     /**
      * Add the schedule.
      *
@@ -877,7 +997,7 @@
      * @return The schedule as RPC value.
      * @throws Exception
      */
-    Map<String,Object> addScheduleRPC( Map<String,Object> schedule )
+    Map<String, Object> addScheduleRPC( Map<String, Object> schedule )
         throws Exception;
 
     /**
@@ -897,9 +1017,9 @@
      * @return The schedule as RPC value.
      * @throws Exception
      */
-    Map<String,Object> updateScheduleRPC( Map<String,Object> schedule )
+    Map<String, Object> updateScheduleRPC( Map<String, Object> schedule )
         throws Exception;
-    
+
     // ----------------------------------------------------------------------
     // Profiles
     // ----------------------------------------------------------------------
@@ -921,7 +1041,7 @@
      */
     List<Object> getProfilesRPC()
         throws Exception;
-    
+
     /**
      * Return the profile defined by this id.
      *
@@ -939,24 +1059,30 @@
      * @return The profile.
      * @throws Exception
      */
-    Map<String,Object> getProfileRPC( int profileId )
+    Map<String, Object> getProfileRPC( int profileId )
         throws Exception;
-    
-    Profile addProfile(Profile profile)
+
+    Profile getProfileWithName( String profileName )
         throws Exception;
-    
-    int updateProfile(Profile profile)
+
+    Map<String, Object> getProfileWithNameRPC( String profileName )
         throws Exception;
-    
-    int deleteProfile(int profileId)
+
+    Profile addProfile( Profile profile )
         throws Exception;
-    
-    Map<String,Object> addProfileRPC(Map<String,Object> profile)
+
+    int updateProfile( Profile profile )
         throws Exception;
-   
-    int updateProfileRPC(Map<String,Object> profile)
+
+    int deleteProfile( int profileId )
         throws Exception;
-   
+
+    Map<String, Object> addProfileRPC( Map<String, Object> profile )
+        throws Exception;
+
+    int updateProfileRPC( Map<String, Object> profile )
+        throws Exception;
+
     // ----------------------------------------------------------------------
     // Installations
     // ----------------------------------------------------------------------
@@ -978,7 +1104,7 @@
      */
     List<Object> getInstallationsRPC()
         throws Exception;
-    
+
     /**
      * Return the installation defined by this id.
      *
@@ -996,24 +1122,64 @@
      * @return The installation.
      * @throws Exception
      */
-    Map<String,Object> getInstallationRPC( int installationId )
-        throws Exception;
-    
-    Installation addInstallation(Installation installation)
-        throws Exception;
-    
-    int updateInstallation(Installation installation)
-        throws Exception;
-    
-    int deleteInstallation(int installationId)
+    Map<String, Object> getInstallationRPC( int installationId )
         throws Exception;
 
-    Map<String,Object> addInstallationRPC(Map<String,Object> installation)
+    /**
+     * Return the installation defined by this name
+     *
+     * @param installationName The installation name
+     * @return The installation
+     * @throws Exception
+     */
+    Installation getInstallation( String installationName )
         throws Exception;
-    
-    int updateInstallationRPC(Map<String,Object> installation)
+
+    /**
+     * Same method but compatible with standard XMLRPC
+     *
+     * @param installationName The installation name
+     * @return The installation
+     * @throws Exception
+     */
+    Map<String, Object> getInstallationRPC( String installationName )
         throws Exception;
-    
+
+    /**
+     * Return the installations list defined by this URL.
+     *
+     * @param url The build agent URL
+     * @return The installations list.
+     * @throws Exception
+     */
+    List<Installation> getBuildAgentInstallations( String url )
+        throws Exception;
+
+    /**
+     * Same method but compatible with standard XMLRPC
+     *
+     * @param url The build agent URL
+     * @return The installations list.
+     * @throws Exception
+     */
+    List<Object> getBuildAgentInstallationsRPC( String url )
+        throws Exception;
+
+    Installation addInstallation( Installation installation )
+        throws Exception;
+
+    int updateInstallation( Installation installation )
+        throws Exception;
+
+    int deleteInstallation( int installationId )
+        throws Exception;
+
+    Map<String, Object> addInstallationRPC( Map<String, Object> installation )
+        throws Exception;
+
+    int updateInstallationRPC( Map<String, Object> installation )
+        throws Exception;
+
     // ----------------------------------------------------------------------
     // SystemConfiguration
     // ----------------------------------------------------------------------
@@ -1021,34 +1187,104 @@
     SystemConfiguration getSystemConfiguration()
         throws Exception;
 
-    Map<String,Object> getSystemConfigurationRPC()
-       throws Exception;
-    
+    Map<String, Object> getSystemConfigurationRPC()
+        throws Exception;
+
     // ----------------------------------------------------------------------
     // Queue
     // ----------------------------------------------------------------------
-    
-        
-        /**
-     * Return true is the project is in building queue.
+
+    /**
+     * Return true if the project is in prepare build queue
      *
-     * @param projectGroupId    The project group id
+     * @param projectId The project id
+     * @throws ContinuumException
+     */
+    boolean isProjectInPrepareBuildQueue( int projectId )
+        throws Exception;
+
+    /**
+     * Return true if the project is in prepare build queue
+     *
+     * @param projectId         The project id
+     * @param buildDefinitionId The build definition id
+     * @throws ContinuumException
+     */
+    boolean isProjectInPrepareBuildQueue( int projectId, int buildDefinitionId )
+        throws Exception;
+
+    /**
+     * Return true if the project is in building queue.
+     *
+     * @param projectId The project id
      * @throws ContinuumException
      */
     boolean isProjectInBuildingQueue( int projectId )
         throws Exception;
 
     /**
+     * Return true if the project is in building queue.
+     *
+     * @param projectId         The project id
+     * @param buildDefinitionId The build definition id
+     * @throws ContinuumException
+     */
+    boolean isProjectInBuildingQueue( int projectId, int buildDefinitionId )
+        throws Exception;
+
+    /**
+     * Return true if the project is currently preparing build
+     *
+     * @param projectId The project id
+     * @return
+     * @throws Exception
+     */
+    boolean isProjectCurrentlyPreparingBuild( int projectId )
+        throws Exception;
+
+    /**
+     * Return true if the project is currently preparing build
+     *
+     * @param projectId         The project id
+     * @param buildDefinitionId The build definition id
+     * @return
+     * @throws Exception
+     */
+    boolean isProjectCurrentlyPreparingBuild( int projectId, int buildDefinitionId )
+        throws Exception;
+
+    /**
+     * Return true if the project is currently building
+     *
+     * @param projectId The project id
+     * @return
+     * @throws Exception
+     */
+    boolean isProjectCurrentlyBuilding( int projectId )
+        throws Exception;
+
+    /**
+     * Return true if the project is currently building
+     *
+     * @param projectId         The project id
+     * @param buildDefinitionId The build definition id
+     * @return
+     * @throws Exception
+     */
+    boolean isProjectCurrentlyBuilding( int projectId, int buildDefinitionId )
+        throws Exception;
+
+    /**
      * Return projects building queue.
      *
      * @throws ContinuumException
      */
     public List<BuildProjectTask> getProjectsInBuildQueue()
-        throws Exception;    
+        throws Exception;
 
     /**
      * Remove projects from build queue
-     * 
+     *
      * @param projectsId project id to be removed from the building queue
      * @return
      * @throws Exception
@@ -1058,13 +1294,24 @@
 
     /**
      * Cancel the current project build
-     * 
+     *
      * @return
      * @throws Exception
      */
     boolean cancelCurrentBuild()
         throws Exception;
 
+    /**
+     * Cancel a project build
+     *
+     * @param projectId         the project id
+     * @param buildDefinitionId the build definition id
+     * @return
+     * @throws Exception
+     */
+    boolean cancelBuild( int projectId, int buildDefinitionId )
+        throws Exception;
+
     // ----------------------------------------------------------------------
     // TODO:Users
     // ----------------------------------------------------------------------
@@ -1082,7 +1329,7 @@
 
     /**
      * Add a local repository
-     * 
+     *
      * @param repository the local repository to add
      * @return
      * @throws Exception
@@ -1092,7 +1339,7 @@
 
     /**
      * Same method but compatible with the standard XMLRPC
-     * 
+     *
      * @param repository the local repository to add
      * @return
      * @throws Exception
@@ -1102,7 +1349,7 @@
 
     /**
      * Update the local repository
-     * 
+     *
      * @param repository the local repository to update
      * @return
      * @throws Exception
@@ -1112,7 +1359,7 @@
 
     /**
      * Same method but compatible with the standard XMLRPC
-     * 
+     *
      * @param repository the local repository to update
      * @return
      * @throws Exception
@@ -1122,7 +1369,7 @@
 
     /**
      * Remove the local repository
-     * 
+     *
      * @param repositoryId
      * @return
      * @throws Exception
@@ -1132,7 +1379,7 @@
 
     /**
      * Returns the local repository
-     * 
+     *
      * @param repositoryId the local repository id
      * @return
      * @throws Exception
@@ -1142,7 +1389,7 @@
 
     /**
      * Same method but compatible with the standard XMLRPC
-     * 
+     *
      * @param repositoryId
      * @return
      * @throws Exception
@@ -1152,7 +1399,7 @@
 
     /**
      * Returns all local repositories
-     * 
+     *
      * @return
      * @throws Exception
      */
@@ -1161,7 +1408,7 @@
 
     /**
      * Same method but compatible with the standard XMLRPC
-     * 
+     *
      * @return
      * @throws Exception
      */
@@ -1174,7 +1421,7 @@
 
     /**
      * Add a repository purge configuration
-     * 
+     *
      * @param repoPurge the repository purge configuration
      * @return
      * @throws Exception
@@ -1184,7 +1431,7 @@
 
     /**
      * Same method but compatible with the standard XMLRPC
-     * 
+     *
      * @param repoPurge the repository purge configuration
      * @return
      * @throws Exception
@@ -1194,7 +1441,7 @@
 
     /**
      * Update the repository purge configuration
-     * 
+     *
      * @param repoPurge the repository purge configuration
      * @return
      * @throws Exception
@@ -1204,7 +1451,7 @@
 
     /**
      * Same method but compatible with the standard XMLRPC
-     * 
+     *
      * @param repoPurge the repository purge configuration
      * @return
      * @throws Exception
@@ -1214,7 +1461,7 @@
 
     /**
      * Remove repository purge configuration
-     * 
+     *
      * @param repoPurgeId the repository purge configuration id
      * @return
      * @throws Exception
@@ -1224,7 +1471,7 @@
 
     /**
      * Returns the repository purge configuration
-     * 
+     *
      * @param purgeConfigId the repository purge configuration id
      * @return the repository purge configuration
      * @throws Exception
@@ -1234,7 +1481,7 @@
 
     /**
      * Same method but compatible with standard XMLRPC
-     * 
+     *
      * @param purgeConfigId the repository purge configuration id
      * @return the repository purge configuration
      * @throws Exception
@@ -1244,7 +1491,7 @@
 
     /**
      * Returns repository purge configurations list
-     * 
+     *
      * @return list of repository purge configurations
      * @throws Exception
      */
@@ -1253,7 +1500,7 @@
 
     /**
      * Same method but compatible with standard XMLRPC
-     * 
+     *
      * @return list of repository purge configurations
      * @throws Exception
      */
@@ -1262,7 +1509,7 @@
 
     /**
      * Add a directory purge configuration
-     * 
+     *
      * @param dirPurge the directory purge configuration
      * @return
      * @throws Exception
@@ -1272,7 +1519,7 @@
 
     /**
      * Same method but compatible with the standard XMLRPC
-     * 
+     *
      * @param dirPurge the directory purge configuration
      * @return
      * @throws Exception
@@ -1282,7 +1529,7 @@
 
     /**
      * Update the directory purge configuration
-     * 
+     *
      * @param dirPurge the directory purge configuration
      * @return
      * @throws Exception
@@ -1292,7 +1539,7 @@
 
     /**
      * Same method but compatible with the standard XMLRPC
-     * 
+     *
      * @param dirPurge the directory purge configuration
      * @return
      * @throws Exception
@@ -1302,7 +1549,7 @@
 
     /**
      * Removes the directory purge configuration
-     * 
+     *
      * @param dirPurgeId the directory purge configuration id
      * @return
      * @throws Exception
@@ -1312,7 +1559,7 @@
 
     /**
      * Returns the directory purge configuration
-     * 
+     *
      * @param purgeConfigId the directory purge configuration id
      * @return the directory purge configuration
      * @throws Exception
@@ -1322,7 +1569,7 @@
 
     /**
      * Same method but compatible with standard XMLRPC
-     * 
+     *
      * @param purgeConfigId the directory purge configuration id
      * @return the directory purge configuration
      * @throws Exception
@@ -1332,7 +1579,7 @@
 
     /**
      * Returns directory purge configurations list
-     * 
+     *
      * @return list of directory purge configurations
      * @throws Exception
      */
@@ -1341,17 +1588,17 @@
 
     /**
      * Same method but compatible with standard XMLRPC
-     * 
+     *
      * @return list of directory purge configurations
      * @throws Exception
      */
     List<Object> getAllDirectoryPurgeConfigurationsRPC()
         throws Exception;
 
-    void purgeLocalRepository( int repoPurgeId )
+    int purgeLocalRepository( int repoPurgeId )
         throws Exception;
 
-    void purgeDirectory( int dirPurgeId )
+    int purgeDirectory( int dirPurgeId )
         throws Exception;
 
     // ----------------------------------------------------------------------
@@ -1371,13 +1618,13 @@
     /**
      * Same method but compatible with standard XMLRPC
      *
-     * @param releaseId   The release id
+     * @param releaseId The release id
      * @return The release result as RPC value
      * @throws Exception
      */
-    Map<String,Object> getReleaseResultRPC( int releaseId )
+    Map<String, Object> getReleaseResultRPC( int releaseId )
         throws Exception;
-    
+
     /**
      * Returns the project group release result list.
      *
@@ -1415,9 +1662,9 @@
      * @return 0
      * @throws Exception
      */
-    int removeReleaseResultRPC( Map<String,Object> rr )
+    int removeReleaseResultRPC( Map<String, Object> rr )
         throws Exception;
-    
+
     /**
      * Returns the release output.
      *
@@ -1427,4 +1674,220 @@
      */
     String getReleaseOutput( int releaseId )
         throws Exception;
+
+    /**
+     * Release prepare a project
+     *
+     * @param projectId
+     * @param releaseProperties
+     * @param releaseVersions
+     * @param developmentVersions
+     * @param environments
+     * @param username
+     * @return The release id
+     * @throws Exception
+     */
+    String releasePrepare( int projectId, Properties releaseProperties, Map<String, String> releaseVersions,
+                           Map<String, String> developmentVersions, Map<String, String> environments, String username )
+        throws Exception;
+
+    /**
+     * Release perform a project
+     *
+     * @param projectId
+     * @param releaseId
+     * @param goals
+     * @param arguments
+     * @param useReleaseProfile
+     * @param repositoryName
+     * @param username
+     * @return
+     * @throws Exception
+     */
+    int releasePerform( int projectId, String releaseId, String goals, String arguments, boolean useReleaseProfile,
+                        String repositoryName, String username )
+        throws Exception;
+
+    /**
+     * Get release listener
+     *
+     * @param projectId
+     * @param releaseId
+     * @return
+     * @throws Exception
+     */
+    ReleaseListenerSummary getListener( int projectId, String releaseId )
+        throws Exception;
+
+    /**
+     * Cleanup the release
+     *
+     * @param projectId
+     * @param releaseId
+     * @return
+     * @throws Exception
+     */
+    int releaseCleanup( int projectId, String releaseId )
+        throws Exception;
+
+    /**
+     * Cleanup the release
+     *
+     * @param projectId
+     * @param releaseId
+     * @param releaseType
+     * @return
+     * @throws Exception
+     */
+    int releaseCleanup( int projectId, String releaseId, String releaseType )
+        throws Exception;
+
+    /**
+     * Rollback a release
+     *
+     * @param projectId
+     * @param releaseId
+     * @return
+     * @throws Exception
+     */
+    int releaseRollback( int projectId, String releaseId )
+        throws Exception;
+
+    /**
+     * Get release plugin parameters
+     *
+     * @param projectId
+     * @return
+     */
+    Map<String, Object> getReleasePluginParameters( int projectId )
+        throws Exception;
+
+    List<Map<String, String>> getProjectReleaseAndDevelopmentVersions( int projectId, String pomFilename,
+                                                                       boolean autoVersionSubmodules )
+        throws Exception;
+
+    /**
+     * Add/Register build agent to Continuum Master
+     *
+     * @return
+     * @throws Exception
+     */
+    BuildAgentConfiguration addBuildAgent( BuildAgentConfiguration buildAgentConfiguration )
+        throws Exception;
+
+    /**
+     * Same method but compatible with standard XMLRPC
+     *
+     * @return
+     * @throws Exception
+     */
+    Map<String, Object> addBuildAgentRPC( Map<String, Object> buildAgentConfiguration )
+        throws Exception;
+
+    /**
+     * Get build agent in Continuum Master
+     *
+     * @param url - build agent URL
+     * @return
+     */
+    BuildAgentConfiguration getBuildAgent( String url );
+
+    /**
+     * Get the url of the build agent that is processing the project
+     *
+     * @param projectId         project Id
+     * @param buildDefinitionId build definition Id
+     * @return build agent url
+     */
+    String getBuildAgentUrl( int projectId, int buildDefinition )
+        throws Exception;
+
+    /**
+     * Same method but compatible with standard XMLRPC
+     *
+     * @param url - build agent URL
+     * @return
+     */
+    Map<String, Object> getBuildAgentRPC( String url );
+
+    /**
+     * Update build agent in Continuum Master
+     *
+     * @return
+     * @throws Exception
+     */
+    BuildAgentConfiguration updateBuildAgent( BuildAgentConfiguration buildAgentConfiguration )
+        throws Exception;
+
+    /**
+     * Same method but compatible with standard XMLRPC
+     *
+     * @return
+     * @throws Exception
+     */
+    Map<String, Object> updateBuildAgentRPC( Map<String, Object> buildAgentConfiguration )
+        throws Exception;
+
+    /**
+     * remove build agent in Continuum Master
+     *
+     * @param url - build agent URL
+     * @return Exception
+     */
+    boolean removeBuildAgent( String url )
+        throws Exception;
+
+    /**
+     * List all build agent in Continuum Master
+     *
+     * @return
+     */
+    List<BuildAgentConfiguration> getAllBuildAgents();
+
+    /**
+     * Same method but compatible with standard XMLRPC
+     *
+     * @return
+     */
+    List<Object> getAllBuildAgentsRPC();
+
+    /**
+     * Retrieve all enabled build agents with their available installations
+     *
+     * @return
+     * @throws Exception
+     */
+    List<BuildAgentConfiguration> getBuildAgentsWithInstallations()
+        throws Exception;
+
+    /**
+     * Same method but compatible with standard XMLRPC
+     *
+     * @return
+     * @throws Exception
+     */
+    List<Object> getBuildAgentsWithInstallationsRPC()
+        throws Exception;
+
+    boolean pingBuildAgent( String buildAgentUrl )
+        throws Exception;
+
+    BuildAgentGroupConfiguration addBuildAgentGroup( BuildAgentGroupConfiguration buildAgentGroup )
+        throws Exception;
+
+    Map<String, Object> addBuildAgentGroupRPC( Map<String, Object> buildAgentGroup )
+        throws Exception;
+
+    BuildAgentGroupConfiguration getBuildAgentGroup( String name );
+
+    Map<String, Object> getBuildAgentGroupRPC( String name );
+
+    BuildAgentGroupConfiguration updateBuildAgentGroup( BuildAgentGroupConfiguration buildAgentGroup )
+        throws Exception;
+
+    Map<String, Object> updateBuildAgentGroupRPC( Map<String, Object> buildAgentGroup )
+        throws Exception;
+
+    int removeBuildAgentGroup( String name )
+        throws Exception;
 }
diff --git a/continuum-xmlrpc/continuum-xmlrpc-api/src/main/mdo/continuum-service.xml b/continuum-xmlrpc/continuum-xmlrpc-api/src/main/mdo/continuum-service.xml
index 3401482..5560889 100644
--- a/continuum-xmlrpc/continuum-xmlrpc-api/src/main/mdo/continuum-service.xml
+++ b/continuum-xmlrpc/continuum-xmlrpc-api/src/main/mdo/continuum-service.xml
@@ -472,6 +472,12 @@
             <type>BuildDefinition</type>
           </association>
         </field>
+        <field jpox.null-value="default">
+          <name>buildUrl</name>
+          <version>1.4.1+</version>
+          <type>String</type>
+          <defaultValue></defaultValue>
+        </field>
       </fields>
     </class>
 
@@ -527,8 +533,8 @@
       </fields>
       <codeSegments>
         <codeSegment>
-           <version>1.1.0+</version>
-           <code><![CDATA[
+          <version>1.1.0+</version>
+          <code><![CDATA[
             private java.util.List errors = new java.util.ArrayList();
 
             /**
@@ -820,8 +826,8 @@
           <name>type</name>
           <version>1.1.0+</version>
           <type>String</type>
-          <description>type of the buid defintion</description>          
-        </field>                
+          <description>type of the buid defintion</description>
+        </field>
         <field>
           <name>schedule</name>
           <version>1.1.0+</version>
@@ -853,7 +859,7 @@
           <description>
             true if this buildDefinition is a template
           </description>
-        </field>         
+        </field>
       </fields>
     </class>
     <class>
@@ -886,8 +892,8 @@
           <name>type</name>
           <version>1.1.0+</version>
           <type>String</type>
-          <description>type of the buid BuildDefinitionTemplate use for default</description>          
-        </field>                                
+          <description>type of the buid BuildDefinitionTemplate use for default</description>
+        </field>
         <field xml.reference="true" stash.part="true">
           <name>buildDefinitions</name>
           <version>1.1.0+</version>
@@ -1010,7 +1016,12 @@
             <type>Installation</type>
             <multiplicity>*</multiplicity>
           </association>
-        </field>          
+        </field>
+        <field>
+          <name>buildAgentGroup</name>
+          <version>1.4.1+</version>
+          <type>String</type>
+        </field>
       </fields>
     </class>
 
@@ -1033,7 +1044,7 @@
           <name>varName</name>
           <version>1.1.0+</version>
           <type>String</type>
-        </field>          
+        </field>
         <field>
           <name>name</name>
           <version>1.1.0+</version>
@@ -1115,8 +1126,8 @@
       </fields>
       <codeSegments>
         <codeSegment>
-           <version>1.1.0+</version>
-           <code><![CDATA[
+          <version>1.1.0+</version>
+          <code><![CDATA[
     public final static int NEW = 1;
     public final static int OK = 2;
     public final static int FAILED = 3;
@@ -1207,7 +1218,7 @@
           <type>String</type>
         </field>
       </fields>
-    </class>    
+    </class>
 
     <class>
       <name>LocalRepository</name>
@@ -1232,7 +1243,7 @@
           <type>String</type>
           <required>true</required>
           <description>
-          The file system location for this repository
+            The file system location for this repository
           </description>
         </field>
         <field>
@@ -1241,12 +1252,12 @@
           <type>String</type>
           <defaultValue>default</defaultValue>
           <description>
-          The layout of the repository. Valid values are "default" and "legacy"
+            The layout of the repository. Valid values are "default" and "legacy"
           </description>
         </field>
       </fields>
     </class>
-    
+
     <class>
       <name>AbstractPurgeConfiguration</name>
       <version>1.1.1+</version>
@@ -1276,7 +1287,7 @@
           <type>int</type>
           <defaultValue>2</defaultValue>
           <description>
-          The total count of the artifact for each snapshot or the release/build output folder to be retained.
+            The total count of the artifact for each snapshot or the release/build output folder to be retained.
           </description>
         </field>
         <field>
@@ -1285,7 +1296,7 @@
           <type>int</type>
           <defaultValue>100</defaultValue>
           <description>
-          The number of days old which will be the basis for removing a snapshot or a folder.
+            The number of days old which will be the basis for removing a snapshot or a folder.
           </description>
         </field>
         <field>
@@ -1359,7 +1370,7 @@
         </field>
       </fields>
     </class>
-       
+
     <class>
       <name>ContinuumReleaseResult</name>
       <version>1.1.1+</version>
@@ -1388,16 +1399,16 @@
         </field>
         <field>
           <name>projectGroup</name>
-          <version>1.1.1+</version>
-          <association xml.reference="true" stash.part="true" jpox.dependent="false">
-            <type>ProjectGroup</type>
+          <version>1.4.1+</version>
+          <association xml.reference="true">
+            <type>ProjectGroupSummary</type>
           </association>
         </field>
         <field>
           <name>project</name>
-          <version>1.1.1+</version>
-          <association xml.reference="true" stash.part="true" jpox.dependent="false">
-            <type>Project</type>
+          <version>1.4.1+</version>
+          <association xml.reference="true">
+            <type>ProjectSummary</type>
           </association>
         </field>
         <field>
@@ -1405,7 +1416,160 @@
           <version>1.1.1+</version>
           <type>String</type>
         </field>
+        <field>
+          <name>username</name>
+          <version>1.4.1+</version>
+          <type>String</type>
+        </field>
       </fields>
-    </class> 
+    </class>
+    <class>
+      <name>BuildTrigger</name>
+      <version>1.4.1+</version>
+      <packageName>org.apache.continuum.xmlrpc.utils</packageName>
+      <fields>
+        <field>
+          <name>trigger</name>
+          <version>1.4.1+</version>
+          <type>int</type>
+        </field>
+        <field>
+          <name>triggeredBy</name>
+          <version>1.4.1+</version>
+          <type>String</type>
+        </field>
+      </fields>
+    </class>
+    <class>
+      <name>ReleaseListenerSummary</name>
+      <version>1.4.1+</version>
+      <fields>
+        <field>
+          <name>phases</name>
+          <version>1.4.1+</version>
+          <association>
+            <type>String</type>
+            <multiplicity>*</multiplicity>
+          </association>
+        </field>
+        <field>
+          <name>completedPhases</name>
+          <version>1.4.1+</version>
+          <association>
+            <type>String</type>
+            <multiplicity>*</multiplicity>
+          </association>
+        </field>
+        <field>
+          <name>inProgress</name>
+          <version>1.4.1+</version>
+          <type>String</type>
+        </field>
+        <field>
+          <name>state</name>
+          <version>1.4.1+</version>
+          <type>int</type>
+        </field>
+        <field>
+          <name>error</name>
+          <version>1.4.1+</version>
+          <type>String</type>
+        </field>
+        <field>
+          <name>username</name>
+          <version>1.4.1+</version>
+          <type>String</type>
+        </field>
+      </fields>
+    </class>
+    <class>
+      <name>BuildAgentConfiguration</name>
+      <version>1.4.1+</version>
+      <packageName>org.apache.maven.continuum.xmlrpc.project</packageName>
+      <fields>
+        <field>
+          <name>url</name>
+          <version>1.4.1+</version>
+          <type>String</type>
+        </field>
+        <field>
+          <name>description</name>
+          <version>1.4.1+</version>
+          <type>String</type>
+        </field>
+        <field>
+          <name>enabled</name>
+          <version>1.4.1+</version>
+          <type>boolean</type>
+        </field>
+        <field>
+          <name>platform</name>
+          <version>1.4.1+</version>
+          <type>String</type>
+        </field>
+        <field>
+          <name>installations</name>
+          <version>1.4.1+</version>
+          <association>
+            <type>Installation</type>
+            <multiplicity>*</multiplicity>
+          </association>
+        </field>
+      </fields>
+    </class>
+    <class>
+      <name>BuildAgentGroupConfiguration</name>
+      <version>1.4.1+</version>
+      <packageName>org.apache.maven.continuum.xmlrpc.project</packageName>
+      <fields>
+        <field>
+          <name>name</name>
+          <version>1.4.1+</version>
+          <type>String</type>
+        </field>
+        <field>
+          <name>buildAgents</name>
+          <version>1.4.1+</version>
+          <association>
+            <type>BuildAgentConfiguration</type>
+            <multiplicity>*</multiplicity>
+          </association>
+        </field>
+      </fields>
+    </class>
+    <class>
+      <name>ProjectScmRoot</name>
+      <version>1.4.1+</version>
+      <packageName>org.apache.maven.continuum.xmlrpc.project</packageName>
+      <fields>
+        <field>
+          <name>id</name>
+          <version>1.4.1+</version>
+          <identifier>true</identifier>
+          <type>int</type>
+        </field>
+        <field>
+          <name>scmRootAddress</name>
+          <version>1.4.1+</version>
+          <type>String</type>
+          <required>true</required>
+        </field>
+        <field>
+          <name>oldState</name>
+          <version>1.4.1+</version>
+          <type>int</type>
+        </field>
+        <field jpox.column="scmRootState">
+          <name>state</name>
+          <version>1.4.1+</version>
+          <type>int</type>
+        </field>
+        <field stash.maxSize="8192">
+          <name>error</name>
+          <version>1.4.1+</version>
+          <type>String</type>
+        </field>
+      </fields>
+    </class>
   </classes>
 </model>
diff --git a/continuum-xmlrpc/continuum-xmlrpc-backup/pom.xml b/continuum-xmlrpc/continuum-xmlrpc-backup/pom.xml
index dec6252..07414ca 100644
--- a/continuum-xmlrpc/continuum-xmlrpc-backup/pom.xml
+++ b/continuum-xmlrpc/continuum-xmlrpc-backup/pom.xml
@@ -1,27 +1,28 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
+  ~ 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.
+  -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <groupId>org.apache.continuum</groupId>
     <artifactId>continuum-xmlrpc</artifactId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>continuum-xmlrpc-backup</artifactId>
@@ -31,17 +32,14 @@
     <dependency>
       <groupId>org.apache.continuum</groupId>
       <artifactId>continuum-xmlrpc-api</artifactId>
-      <version>${project.version}</version>
     </dependency>
     <dependency>
       <groupId>org.apache.continuum</groupId>
       <artifactId>continuum-xmlrpc-client</artifactId>
-      <version>${project.version}</version>
     </dependency>
     <dependency>
       <groupId>com.google.code.cli-parser</groupId>
       <artifactId>cli</artifactId>
-      <version>7</version>
     </dependency>
     <dependency>
       <groupId>log4j</groupId>
@@ -73,7 +71,6 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-assembly-plugin</artifactId>
-        <version>2.1</version>
         <configuration>
           <descriptor>src/assembly/app.xml</descriptor>
           <archive>
diff --git a/continuum-xmlrpc/continuum-xmlrpc-backup/src/main/java/org/apache/maven/continuum/xmlrpc/backup/Backup.java b/continuum-xmlrpc/continuum-xmlrpc-backup/src/main/java/org/apache/maven/continuum/xmlrpc/backup/Backup.java
index 04d29c2..64a2a62 100644
--- a/continuum-xmlrpc/continuum-xmlrpc-backup/src/main/java/org/apache/maven/continuum/xmlrpc/backup/Backup.java
+++ b/continuum-xmlrpc/continuum-xmlrpc-backup/src/main/java/org/apache/maven/continuum/xmlrpc/backup/Backup.java
@@ -21,13 +21,13 @@
 
 import com.sampullara.cli.Args;
 import com.sampullara.cli.Argument;
-import org.apache.log4j.BasicConfigurator;
-import org.apache.log4j.Level;
-import org.apache.log4j.Logger;
 import org.apache.continuum.xmlrpc.release.ContinuumReleaseResult;
 import org.apache.continuum.xmlrpc.repository.DirectoryPurgeConfiguration;
 import org.apache.continuum.xmlrpc.repository.LocalRepository;
 import org.apache.continuum.xmlrpc.repository.RepositoryPurgeConfiguration;
+import org.apache.log4j.BasicConfigurator;
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
 import org.apache.maven.continuum.xmlrpc.client.ContinuumXmlRpcClient;
 import org.apache.maven.continuum.xmlrpc.project.BuildDefinition;
 import org.apache.maven.continuum.xmlrpc.project.BuildDefinitionTemplate;
@@ -138,7 +138,7 @@
         if ( !command.overwrite && out.exists() )
         {
             System.err.println( out.getAbsolutePath() +
-                " already exists and will not be overwritten unless the -overwrite flag is used." );
+                                    " already exists and will not be overwritten unless the -overwrite flag is used." );
             Args.usage( command );
             return;
         }
@@ -173,32 +173,32 @@
     private static class Commands
     {
 
-        @Argument(description = "Display help information", value = "help", alias = "h")
+        @Argument( description = "Display help information", value = "help", alias = "h" )
         private boolean help;
 
-        @Argument(description = "Display version information", value = "version", alias = "v")
+        @Argument( description = "Display version information", value = "version", alias = "v" )
         private boolean version;
 
-        @Argument(description = "Continuum XMLRPC URL", value = "url")
+        @Argument( description = "Continuum XMLRPC URL", value = "url" )
         private URL url;
 
-        @Argument(description = "Username", value = "username", alias = "u")
+        @Argument( description = "Username", value = "username", alias = "u" )
         private String username;
 
-        @Argument(description = "Password", value = "password", alias = "p")
+        @Argument( description = "Password", value = "password", alias = "p" )
         private String password;
 
-        @Argument(description = "Backup file", value = "outputFile", alias = "o")
+        @Argument( description = "Backup file", value = "outputFile", alias = "o" )
         private File outputFile;
 
         @Argument(
             description = "Whether to overwrite the designated backup file if it already exists in export mode. Default is false.",
-            value = "overwrite")
+            value = "overwrite" )
         private boolean overwrite;
 
         @Argument(
             description = "Turn on debugging information. Default is off.",
-            value = "debug")
+            value = "debug" )
         private boolean debug;
     }
 
@@ -260,10 +260,16 @@
                 List<BuildDefinition> bds = bdt.getBuildDefinitions();
                 if ( bds != null && !bds.isEmpty() )
                 {
+
+                    startTag( "buildDefinitions", true );
+
                     for ( BuildDefinition bd : bds )
                     {
                         backupBuildDefinition( bd );
                     }
+
+                    endTag( "buildDefinitions", true );
+
                 }
                 endTag( "buildDefinitionTemplate", true );
             }
@@ -570,8 +576,8 @@
             startTag( "environmentVariables", true );
             for ( Installation env : (List<Installation>) profile.getEnvironmentVariables() )
             {
-                writeTagWithParameter( "environmentVariable", "installationId",
-                                       String.valueOf( env.getInstallationId() ) );
+                writeTagWithParameter( "environmentVariable", "installationId", String.valueOf(
+                    env.getInstallationId() ) );
             }
             endTag( "environmentVariables", true );
         }
@@ -583,8 +589,8 @@
 
         if ( profile.getBuilder() != null )
         {
-            writeTagWithParameter( "builder", "installationId",
-                                   String.valueOf( profile.getBuilder().getInstallationId() ) );
+            writeTagWithParameter( "builder", "installationId", String.valueOf(
+                profile.getBuilder().getInstallationId() ) );
         }
 
         endTag( "profile", true );
@@ -719,7 +725,7 @@
         }
         startTag( "repositoryPurgeConfiguration", true );
         writeSimpleFields( repoPurge );
-        
+
         if ( repoPurge.getRepository() != null )
         {
             writeTagWithParameter( "repository", "id", String.valueOf( repoPurge.getRepository().getId() ) );
@@ -756,7 +762,7 @@
         {
             return;
         }
-        startTag( "directoryPurgeConfiguration", true);
+        startTag( "directoryPurgeConfiguration", true );
         writeSimpleFields( dirPurge );
 
         if ( dirPurge.getSchedule() != null )
diff --git a/continuum-xmlrpc/continuum-xmlrpc-client/README.txt b/continuum-xmlrpc/continuum-xmlrpc-client/README.txt
new file mode 100644
index 0000000..85c66d8
--- /dev/null
+++ b/continuum-xmlrpc/continuum-xmlrpc-client/README.txt
@@ -0,0 +1,13 @@
+Apache Continuum XML-RPC Client
+
+To run the sample client code:
+
+mvn exec:exec
+
+This assumes Continuum is running on port 8080.  If not, you will need to edit
+the url in the exec plugin's configuration.
+
+-----------------
+
+To purge old build results, change the exec plugin configuration to run BuildResultsPurge instead of SampleClient
+and run 'mvn exec:exec'.
\ No newline at end of file
diff --git a/continuum-xmlrpc/continuum-xmlrpc-client/pom.xml b/continuum-xmlrpc/continuum-xmlrpc-client/pom.xml
index 1b09e7a..e5b69cd 100644
--- a/continuum-xmlrpc/continuum-xmlrpc-client/pom.xml
+++ b/continuum-xmlrpc/continuum-xmlrpc-client/pom.xml
@@ -1,27 +1,28 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
+  ~ 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.
+  -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <groupId>org.apache.continuum</groupId>
     <artifactId>continuum-xmlrpc</artifactId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>continuum-xmlrpc-client</artifactId>
@@ -31,12 +32,36 @@
     <dependency>
       <groupId>org.apache.continuum</groupId>
       <artifactId>continuum-xmlrpc-api</artifactId>
-      <version>${project.version}</version>
     </dependency>
     <dependency>
       <groupId>org.apache.xmlrpc</groupId>
       <artifactId>xmlrpc-client</artifactId>
-      <version>3.1</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-httpclient</groupId>
+      <artifactId>commons-httpclient</artifactId>
+      <scope>runtime</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>commons-logging</groupId>
+          <artifactId>commons-logging</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>jcl-over-slf4j</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+      <scope>runtime</scope>
     </dependency>
   </dependencies>
   <build>
@@ -46,16 +71,25 @@
         <artifactId>exec-maven-plugin</artifactId>
         <configuration>
           <executable>java</executable>
+          <mainClass>org.apache.maven.continuum.xmlrpc.client.SampleClient</mainClass>
           <arguments>
-            <argument>-Dmyproperty=myvalue</argument>
-            <argument>-classpath</argument>
+            <!--argument>-Dmyproperty=myvalue</argument>
+            <argument>-classpath</argument-->
             <!-- automatically creates the classpath using all project dependencies, 
                  also adding the project build directory -->
-            <classpath />
-            <argument>org.apache.maven.continuum.xmlrpc.client.SampleClient</argument>
+            <!--classpath /-->
+            <argument>${url}/xmlrpc</argument>
+            <argument>${username}</argument>
+            <argument>${password}</argument>
           </arguments>
         </configuration>
       </plugin>
     </plugins>
   </build>
+  <properties>
+    <url>http://localhost:${port}/continuum</url>
+    <port>8080</port>
+    <username>admin</username>
+    <password>admin123</password>
+  </properties>
 </project>
diff --git a/continuum-xmlrpc/continuum-xmlrpc-client/src/main/java/org/apache/maven/continuum/xmlrpc/client/BuildResultsPurge.java b/continuum-xmlrpc/continuum-xmlrpc-client/src/main/java/org/apache/maven/continuum/xmlrpc/client/BuildResultsPurge.java
new file mode 100644
index 0000000..edbb889
--- /dev/null
+++ b/continuum-xmlrpc/continuum-xmlrpc-client/src/main/java/org/apache/maven/continuum/xmlrpc/client/BuildResultsPurge.java
@@ -0,0 +1,99 @@
+package org.apache.maven.continuum.xmlrpc.client;
+
+/*
+ * 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 org.apache.maven.continuum.xmlrpc.project.BuildResult;
+import org.apache.maven.continuum.xmlrpc.project.BuildResultSummary;
+import org.apache.maven.continuum.xmlrpc.project.ProjectGroupSummary;
+import org.apache.maven.continuum.xmlrpc.project.ProjectSummary;
+
+import java.net.URL;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Utility class to purge old build results.
+ * <p/>
+ * The easiest way to use it is to change the exec plugin config in the pom to execute this class instead of
+ * SampleClient, change RETENTION_DAYS if desired, and type 'mvn clean install exec:exec'
+ */
+public class BuildResultsPurge
+{
+
+    private static ContinuumXmlRpcClient client;
+
+    private static long RETENTION_DAYS = 60;
+
+    private static long DAY_IN_MILLISECONDS = 24 * 60 * 60 * 1000;
+
+    public static void main( String[] args )
+        throws Exception
+    {
+
+        client = new ContinuumXmlRpcClient( new URL( args[0] ), args[1], args[2] );
+
+        long today = new Date().getTime();
+
+        System.out.println( "Today is " + new Date( today ) );
+
+        long purgeDate = today - ( RETENTION_DAYS * DAY_IN_MILLISECONDS );
+        //long purgeDate = today - 1000;  // 1 second ago (for testing)
+
+        System.out.println( "Purging build results older than " + new Date( purgeDate ) );
+
+        List<ProjectGroupSummary> groups = client.getAllProjectGroups();
+
+        for ( ProjectGroupSummary group : groups )
+        {
+
+            System.out.println( "Project Group [" + group.getId() + "] " + group.getName() );
+
+            List<ProjectSummary> projects = client.getProjects( group.getId() );
+
+            for ( ProjectSummary project : projects )
+            {
+
+                System.out.println( " Project [" + project.getId() + "] " + project.getName() );
+
+                List<BuildResultSummary> results = client.getBuildResultsForProject( project.getId() );
+
+                for ( BuildResultSummary brs : results )
+                {
+
+                    BuildResult br = client.getBuildResult( project.getId(), brs.getId() );
+
+                    System.out.print( "  Build Result [" + br.getId() + "] ended " + new Date( br.getEndTime() ) );
+
+                    if ( br.getEndTime() > 0 && br.getEndTime() < purgeDate )
+                    {
+
+                        client.removeBuildResult( br );
+                        System.out.println( " ...removed." );
+                    }
+                    else
+                    {
+                        System.out.println( " ...retained." );
+                    }
+                }
+            }
+
+        }
+    }
+}
diff --git a/continuum-xmlrpc/continuum-xmlrpc-client/src/main/java/org/apache/maven/continuum/xmlrpc/client/ContinuumXmlRpcClient.java b/continuum-xmlrpc/continuum-xmlrpc-client/src/main/java/org/apache/maven/continuum/xmlrpc/client/ContinuumXmlRpcClient.java
index a0750c0..b6941cf 100644
--- a/continuum-xmlrpc/continuum-xmlrpc-client/src/main/java/org/apache/maven/continuum/xmlrpc/client/ContinuumXmlRpcClient.java
+++ b/continuum-xmlrpc/continuum-xmlrpc-client/src/main/java/org/apache/maven/continuum/xmlrpc/client/ContinuumXmlRpcClient.java
@@ -23,8 +23,11 @@
 import org.apache.continuum.xmlrpc.repository.DirectoryPurgeConfiguration;
 import org.apache.continuum.xmlrpc.repository.LocalRepository;
 import org.apache.continuum.xmlrpc.repository.RepositoryPurgeConfiguration;
+import org.apache.continuum.xmlrpc.utils.BuildTrigger;
 import org.apache.maven.continuum.xmlrpc.ContinuumService;
 import org.apache.maven.continuum.xmlrpc.project.AddingResult;
+import org.apache.maven.continuum.xmlrpc.project.BuildAgentConfiguration;
+import org.apache.maven.continuum.xmlrpc.project.BuildAgentGroupConfiguration;
 import org.apache.maven.continuum.xmlrpc.project.BuildDefinition;
 import org.apache.maven.continuum.xmlrpc.project.BuildDefinitionTemplate;
 import org.apache.maven.continuum.xmlrpc.project.BuildProjectTask;
@@ -35,20 +38,23 @@
 import org.apache.maven.continuum.xmlrpc.project.ProjectGroup;
 import org.apache.maven.continuum.xmlrpc.project.ProjectGroupSummary;
 import org.apache.maven.continuum.xmlrpc.project.ProjectNotifier;
+import org.apache.maven.continuum.xmlrpc.project.ProjectScmRoot;
 import org.apache.maven.continuum.xmlrpc.project.ProjectSummary;
+import org.apache.maven.continuum.xmlrpc.project.ReleaseListenerSummary;
 import org.apache.maven.continuum.xmlrpc.project.Schedule;
 import org.apache.maven.continuum.xmlrpc.system.Installation;
 import org.apache.maven.continuum.xmlrpc.system.Profile;
 import org.apache.maven.continuum.xmlrpc.system.SystemConfiguration;
-import org.apache.xmlrpc.XmlRpcException;
 import org.apache.xmlrpc.client.XmlRpcClient;
 import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
+import org.apache.xmlrpc.client.XmlRpcCommonsTransportFactory;
 import org.apache.xmlrpc.client.util.ClientFactory;
 
 import java.net.URL;
 import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
+import java.util.Properties;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
@@ -57,22 +63,22 @@
 public class ContinuumXmlRpcClient
     implements ContinuumService
 {
-    private ContinuumService continuum;
+    private final ContinuumService continuum;
 
-    private static Hashtable statusMap;
+    private static Hashtable<Integer, String> statusMap;
 
     static
     {
-        statusMap = new Hashtable();
-        statusMap.put( new Integer( ContinuumProjectState.NEW ), "New" );
-        statusMap.put( new Integer( ContinuumProjectState.CHECKEDOUT ), "New" );
-        statusMap.put( new Integer( ContinuumProjectState.OK ), "OK" );
-        statusMap.put( new Integer( ContinuumProjectState.FAILED ), "Failed" );
-        statusMap.put( new Integer( ContinuumProjectState.ERROR ), "Error" );
-        statusMap.put( new Integer( ContinuumProjectState.BUILDING ), "Building" );
-        statusMap.put( new Integer( ContinuumProjectState.CHECKING_OUT ), "Checking out" );
-        statusMap.put( new Integer( ContinuumProjectState.UPDATING ), "Updating" );
-        statusMap.put( new Integer( ContinuumProjectState.WARNING ), "Warning" );
+        statusMap = new Hashtable<Integer, String>();
+        statusMap.put( ContinuumProjectState.NEW, "New" );
+        statusMap.put( ContinuumProjectState.CHECKEDOUT, "New" );
+        statusMap.put( ContinuumProjectState.OK, "OK" );
+        statusMap.put( ContinuumProjectState.FAILED, "Failed" );
+        statusMap.put( ContinuumProjectState.ERROR, "Error" );
+        statusMap.put( ContinuumProjectState.BUILDING, "Building" );
+        statusMap.put( ContinuumProjectState.CHECKING_OUT, "Checking out" );
+        statusMap.put( ContinuumProjectState.UPDATING, "Updating" );
+        statusMap.put( ContinuumProjectState.WARNING, "Warning" );
     }
 
     public ContinuumXmlRpcClient( URL serviceUrl )
@@ -98,6 +104,7 @@
         config.setServerURL( serviceUrl );
 
         XmlRpcClient client = new XmlRpcClient();
+        client.setTransportFactory( new XmlRpcCommonsTransportFactory( client ) );
         client.setConfig( config );
         ClientFactory factory = new ClientFactory( client );
         continuum = (ContinuumService) factory.newInstance( ContinuumService.class );
@@ -324,19 +331,47 @@
         return continuum.buildProject( projectId, buildDefinitionId );
     }
 
+    public int buildProject( int projectId, BuildTrigger buildTrigger )
+        throws Exception
+    {
+        return continuum.buildProject( projectId, buildTrigger );
+    }
+
+    public int buildProject( int projectId, int buildDefinitionId, BuildTrigger buildTrigger )
+        throws Exception
+    {
+        return continuum.buildProject( projectId, buildDefinitionId, buildTrigger );
+    }
+
     public int buildGroup( int projectGroupId )
-        throws Exception, XmlRpcException
+        throws Exception
     {
         return continuum.buildGroup( projectGroupId );
     }
 
     public int buildGroup( int projectGroupId, int buildDefinitionId )
-        throws Exception, XmlRpcException
+        throws Exception
     {
         return continuum.buildGroup( projectGroupId, buildDefinitionId );
     }
 
     // ----------------------------------------------------------------------
+    // SCM roots
+    // ----------------------------------------------------------------------
+
+    public List<ProjectScmRoot> getProjectScmRootByProjectGroup( int projectGroupId )
+        throws Exception
+    {
+        return continuum.getProjectScmRootByProjectGroup( projectGroupId );
+    }
+
+    public ProjectScmRoot getProjectScmRootByProject( int projectId )
+        throws Exception
+    {
+        return continuum.getProjectScmRootByProject( projectId );
+    }
+
+    // ----------------------------------------------------------------------
     // Build Results
     // ----------------------------------------------------------------------
 
@@ -359,7 +394,7 @@
     }
 
     public int removeBuildResult( BuildResult br )
-        throws Exception, XmlRpcException
+        throws Exception
     {
         return continuum.removeBuildResult( br );
     }
@@ -386,16 +421,31 @@
         return continuum.addMavenTwoProject( url, projectGroupId );
     }
 
+    public AddingResult addMavenTwoProject( String url, int projectGroupId, boolean checkoutInSingleDirectory )
+        throws Exception
+    {
+        return continuum.addMavenTwoProject( url, projectGroupId, checkoutInSingleDirectory );
+    }
+
+    public AddingResult addMavenTwoProjectAsSingleProject( String url, int projectGroupId )
+        throws Exception
+    {
+        return continuum.addMavenTwoProjectAsSingleProject( url, projectGroupId );
+    }
+
+    public AddingResult addMavenTwoProject( String url, int projectGroupId, boolean checkProtocol,
+                                            boolean useCredentialsCache, boolean recursiveProjects,
+                                            boolean checkoutInSingleDirectory )
+        throws Exception
+    {
+        return continuum.addMavenTwoProject( url, projectGroupId, checkProtocol, useCredentialsCache, recursiveProjects,
+                                             checkoutInSingleDirectory );
+    }
+
     // ----------------------------------------------------------------------
     // Maven 1.x projects
     // ----------------------------------------------------------------------
 
-    public AddingResult addMavenOneProject( String url )
-        throws Exception
-    {
-        return continuum.addMavenOneProject( url );
-    }
-
     public AddingResult addMavenOneProject( String url, int projectGroupId )
         throws Exception
     {
@@ -406,12 +456,6 @@
     // Maven ANT projects
     // ----------------------------------------------------------------------
 
-    public ProjectSummary addAntProject( ProjectSummary project )
-        throws Exception
-    {
-        return continuum.addAntProject( project );
-    }
-
     public ProjectSummary addAntProject( ProjectSummary project, int projectGroupId )
         throws Exception
     {
@@ -422,12 +466,6 @@
     // Maven Shell projects
     // ----------------------------------------------------------------------
 
-    public ProjectSummary addShellProject( ProjectSummary project )
-        throws Exception
-    {
-        return continuum.addShellProject( project );
-    }
-
     public ProjectSummary addShellProject( ProjectSummary project, int projectGroupId )
         throws Exception
     {
@@ -478,6 +516,12 @@
         return continuum.getProfile( profileId );
     }
 
+    public Profile getProfileWithName( String profileName )
+        throws Exception
+    {
+        return continuum.getProfileWithName( profileName );
+    }
+
     // ----------------------------------------------------------------------
     // Installations
     // ----------------------------------------------------------------------
@@ -494,6 +538,18 @@
         return continuum.getInstallation( installationId );
     }
 
+    public Installation getInstallation( String installationName )
+        throws Exception
+    {
+        return continuum.getInstallation( installationName );
+    }
+
+    public List<Installation> getBuildAgentInstallations( String url )
+        throws Exception
+    {
+        return continuum.getBuildAgentInstallations( url );
+    }
+
     // ----------------------------------------------------------------------
     // SystemConfiguration
     // ----------------------------------------------------------------------
@@ -510,12 +566,23 @@
 
     public String getProjectStatusAsString( int status )
     {
-        return (String) statusMap.get( new Integer( status ) );
+        return statusMap.get( new Integer( status ) );
     }
 
     // ----------------------------------------------------------------------
     // Queue
     // ----------------------------------------------------------------------
+    public boolean isProjectInPrepareBuildQueue( int projectId )
+        throws Exception
+    {
+        return continuum.isProjectInPrepareBuildQueue( projectId );
+    }
+
+    public boolean isProjectInPrepareBuildQueue( int projectId, int buildDefinitionId )
+        throws Exception
+    {
+        return continuum.isProjectInPrepareBuildQueue( projectId, buildDefinitionId );
+    }
 
     public List<BuildProjectTask> getProjectsInBuildQueue()
         throws Exception
@@ -529,6 +596,36 @@
         return continuum.isProjectInBuildingQueue( projectId );
     }
 
+    public boolean isProjectInBuildingQueue( int projectId, int buildDefinitionId )
+        throws Exception
+    {
+        return continuum.isProjectInBuildingQueue( projectId, buildDefinitionId );
+    }
+
+    public boolean isProjectCurrentlyPreparingBuild( int projectId )
+        throws Exception
+    {
+        return continuum.isProjectCurrentlyPreparingBuild( projectId );
+    }
+
+    public boolean isProjectCurrentlyPreparingBuild( int projectId, int buildDefinitionId )
+        throws Exception
+    {
+        return continuum.isProjectCurrentlyPreparingBuild( projectId, buildDefinitionId );
+    }
+
+    public boolean isProjectCurrentlyBuilding( int projectId )
+        throws Exception
+    {
+        return continuum.isProjectCurrentlyBuilding( projectId );
+    }
+
+    public boolean isProjectCurrentlyBuilding( int projectId, int buildDefinitionId )
+        throws Exception
+    {
+        return continuum.isProjectCurrentlyBuilding( projectId, buildDefinitionId );
+    }
+
     public int removeProjectsFromBuildingQueue( int[] projectsId )
         throws Exception
     {
@@ -541,6 +638,12 @@
         return continuum.cancelCurrentBuild();
     }
 
+    public boolean cancelBuild( int projectId, int buildDefinitionId )
+        throws Exception
+    {
+        return continuum.cancelBuild( projectId, buildDefinitionId );
+    }
+
     // ----------------------------------------------------------------------
     // Release Result
     // ----------------------------------------------------------------------
@@ -633,16 +736,16 @@
         return continuum.getAllDirectoryPurgeConfigurations();
     }
 
-    public void purgeLocalRepository( int repoPurgeId )
+    public int purgeLocalRepository( int repoPurgeId )
         throws Exception
     {
-        continuum.purgeLocalRepository( repoPurgeId );
+        return continuum.purgeLocalRepository( repoPurgeId );
     }
 
-    public void purgeDirectory( int dirPurgeId )
+    public int purgeDirectory( int dirPurgeId )
         throws Exception
     {
-        continuum.purgeDirectory( dirPurgeId );
+        return continuum.purgeDirectory( dirPurgeId );
     }
 
     // ----------------------------------------------------------------------
@@ -679,10 +782,39 @@
         return continuum.getAllLocalRepositories();
     }
 
-    public Map<String, Object> addAntProjectRPC( Map<String, Object> project )
+    // ----------------------------------------------------------------------
+    // ConfigurationService
+    // ----------------------------------------------------------------------
+
+    public BuildAgentConfiguration addBuildAgent( BuildAgentConfiguration buildAgentConfiguration )
         throws Exception
     {
-        return continuum.addAntProjectRPC( project );
+        return continuum.addBuildAgent( buildAgentConfiguration );
+    }
+
+    public BuildAgentConfiguration getBuildAgent( String url )
+
+    {
+        return continuum.getBuildAgent( url );
+    }
+
+    public BuildAgentConfiguration updateBuildAgent( BuildAgentConfiguration buildAgentConfiguration )
+        throws Exception
+
+    {
+        return continuum.updateBuildAgent( buildAgentConfiguration );
+    }
+
+    public boolean removeBuildAgent( String url )
+        throws Exception
+
+    {
+        return continuum.removeBuildAgent( url );
+    }
+
+    public List<BuildAgentConfiguration> getAllBuildAgents()
+    {
+        return continuum.getAllBuildAgents();
     }
 
     public Map<String, Object> addAntProjectRPC( Map<String, Object> project, int projectGroupId )
@@ -691,26 +823,18 @@
         return continuum.addAntProjectRPC( project, projectGroupId );
     }
 
-    public Map<String, Object> addBuildDefinitionToProjectGroupRPC( int projectGroupId,
-                                                                    Map<String, Object> buildDef )
+    public Map<String, Object> addBuildDefinitionToProjectGroupRPC( int projectGroupId, Map<String, Object> buildDef )
         throws Exception
     {
         return continuum.addBuildDefinitionToProjectGroupRPC( projectGroupId, buildDef );
     }
 
-    public Map<String, Object> addBuildDefinitionToProjectRPC( int projectId,
-                                                               Map<String, Object> buildDef )
+    public Map<String, Object> addBuildDefinitionToProjectRPC( int projectId, Map<String, Object> buildDef )
         throws Exception
     {
         return continuum.addBuildDefinitionToProjectRPC( projectId, buildDef );
     }
 
-    public Map<String, Object> addMavenOneProjectRPC( String url )
-        throws Exception
-    {
-        return continuum.addMavenOneProjectRPC( url );
-    }
-
     public Map<String, Object> addMavenOneProjectRPC( String url, int projectGroupId )
         throws Exception
     {
@@ -729,9 +853,29 @@
         return continuum.addMavenTwoProjectRPC( url, projectGroupId );
     }
 
-    public Map<String, Object> addProjectGroupRPC( String groupName,
-                                                   String groupId,
-                                                   String description )
+    public Map<String, Object> addMavenTwoProjectRPC( String url, int projectGroupId,
+                                                      boolean checkoutInSingleDirectory )
+        throws Exception
+    {
+        return continuum.addMavenTwoProjectRPC( url, projectGroupId, checkoutInSingleDirectory );
+    }
+
+    public Map<String, Object> addMavenTwoProjectAsSingleProjectRPC( String url, int projectGroupId )
+        throws Exception
+    {
+        return continuum.addMavenTwoProjectAsSingleProjectRPC( url, projectGroupId );
+    }
+
+    public Map<String, Object> addMavenTwoProjectRPC( String url, int projectGroupId, boolean checkProtocol,
+                                                      boolean useCredentialsCache, boolean recursiveProjects,
+                                                      boolean checkoutInSingleDirectory )
+        throws Exception
+    {
+        return continuum.addMavenTwoProjectRPC( url, projectGroupId, checkProtocol, useCredentialsCache,
+                                                recursiveProjects, checkoutInSingleDirectory );
+    }
+
+    public Map<String, Object> addProjectGroupRPC( String groupName, String groupId, String description )
         throws Exception
     {
         return continuum.addProjectGroupRPC( groupName, groupId, description );
@@ -749,12 +893,6 @@
         return continuum.addShellProjectRPC( project, projectGroupId );
     }
 
-    public Map<String, Object> addShellProjectRPC( Map<String, Object> project )
-        throws Exception
-    {
-        return continuum.addShellProjectRPC( project );
-    }
-
     public List<Object> getAllProjectGroupsRPC()
         throws Exception
     {
@@ -803,12 +941,24 @@
         return continuum.getInstallationRPC( installationId );
     }
 
+    public Map<String, Object> getInstallationRPC( String installationName )
+        throws Exception
+    {
+        return continuum.getInstallationRPC( installationName );
+    }
+
     public List<Object> getInstallationsRPC()
         throws Exception
     {
         return continuum.getInstallationsRPC();
     }
 
+    public List<Object> getBuildAgentInstallationsRPC( String url )
+        throws Exception
+    {
+        return continuum.getBuildAgentInstallationsRPC( url );
+    }
+
     public Map<String, Object> getLatestBuildResultRPC( int projectId )
         throws Exception
     {
@@ -821,6 +971,12 @@
         return continuum.getProfileRPC( profileId );
     }
 
+    public Map<String, Object> getProfileWithNameRPC( String profileName )
+        throws Exception
+    {
+        return continuum.getProfileWithNameRPC( profileName );
+    }
+
     public List<Object> getProfilesRPC()
         throws Exception
     {
@@ -894,8 +1050,7 @@
         return continuum.updateBuildDefinitionForProjectGroupRPC( projectGroupId, buildDef );
     }
 
-    public Map<String, Object> updateBuildDefinitionForProjectRPC( int projectId,
-                                                                   Map<String, Object> buildDef )
+    public Map<String, Object> updateBuildDefinitionForProjectRPC( int projectId, Map<String, Object> buildDef )
         throws Exception
     {
         return continuum.updateBuildDefinitionForProjectRPC( projectId, buildDef );
@@ -955,8 +1110,7 @@
         return continuum.updateGroupNotifier( projectgroupid, newNotifier );
     }
 
-    public Map<String, Object> updateGroupNotifierRPC( int projectgroupid,
-                                                       Map<String, Object> newNotifier )
+    public Map<String, Object> updateGroupNotifierRPC( int projectgroupid, Map<String, Object> newNotifier )
         throws Exception
     {
         return continuum.updateGroupNotifierRPC( projectgroupid, newNotifier );
@@ -992,8 +1146,7 @@
         return continuum.addGroupNotifier( projectgroupid, newNotifier );
     }
 
-    public Map<String, Object> addGroupNotifierRPC( int projectgroupid,
-                                                    Map<String, Object> newNotifier )
+    public Map<String, Object> addGroupNotifierRPC( int projectgroupid, Map<String, Object> newNotifier )
         throws Exception
     {
         return continuum.addGroupNotifierRPC( projectgroupid, newNotifier );
@@ -1160,4 +1313,158 @@
     {
         return continuum.getAllLocalRepositoriesRPC();
     }
+
+    public Map<String, Object> addBuildAgentRPC( Map<String, Object> buildAgentConfiguration )
+        throws Exception
+    {
+        return continuum.addBuildAgentRPC( buildAgentConfiguration );
+    }
+
+    public Map<String, Object> getBuildAgentRPC( String url )
+
+    {
+        return continuum.getBuildAgentRPC( url );
+    }
+
+    public Map<String, Object> updateBuildAgentRPC( Map<String, Object> buildAgentConfiguration )
+        throws Exception
+
+    {
+        return continuum.updateBuildAgentRPC( buildAgentConfiguration );
+    }
+
+    public List<Object> getAllBuildAgentsRPC()
+    {
+        return continuum.getAllBuildAgentsRPC();
+    }
+
+    public int releasePerform( int projectId, String releaseId, String goals, String arguments,
+                               boolean useReleaseProfile, String repositoryName, String username )
+        throws Exception
+    {
+        return continuum.releasePerform( projectId, releaseId, goals, arguments, useReleaseProfile, repositoryName,
+                                         username );
+    }
+
+    public String releasePrepare( int projectId, Properties releaseProperties, Map<String, String> releaseVersions,
+                                  Map<String, String> developmentVersions, Map<String, String> environments,
+                                  String username )
+        throws Exception
+    {
+        return continuum.releasePrepare( projectId, releaseProperties, releaseVersions, developmentVersions,
+                                         environments, username );
+    }
+
+    public ReleaseListenerSummary getListener( int projectId, String releaseId )
+        throws Exception
+    {
+        return continuum.getListener( projectId, releaseId );
+    }
+
+    public int releaseCleanup( int projectId, String releaseId )
+        throws Exception
+    {
+        return continuum.releaseCleanup( projectId, releaseId );
+    }
+
+    public int releaseCleanup( int projectId, String releaseId, String releaseType )
+        throws Exception
+    {
+        return continuum.releaseCleanup( projectId, releaseId, releaseType );
+    }
+
+    public int releaseRollback( int projectId, String releaseId )
+        throws Exception
+    {
+        return continuum.releaseRollback( projectId, releaseId );
+    }
+
+    public Map<String, Object> getReleasePluginParameters( int projectId )
+        throws Exception
+    {
+        return continuum.getReleasePluginParameters( projectId );
+    }
+
+    public List<Map<String, String>> getProjectReleaseAndDevelopmentVersions( int projectId, String pomFilename,
+                                                                              boolean autoVersionSubmodules )
+        throws Exception
+    {
+        return continuum.getProjectReleaseAndDevelopmentVersions( projectId, pomFilename, autoVersionSubmodules );
+    }
+
+    public boolean pingBuildAgent( String buildAgentUrl )
+        throws Exception
+    {
+        return continuum.pingBuildAgent( buildAgentUrl );
+    }
+
+    public String getBuildAgentUrl( int projectId, int buildDefinitionId )
+        throws Exception
+    {
+        return continuum.getBuildAgentUrl( projectId, buildDefinitionId );
+    }
+
+    public BuildDefinition getBuildDefinition( int buildDefinitionId )
+        throws Exception
+    {
+        return continuum.getBuildDefinition( buildDefinitionId );
+    }
+
+    public Map<String, Object> getBuildDefinitionRPC( int buildDefinitionId )
+        throws Exception
+    {
+        return continuum.getBuildDefinitionRPC( buildDefinitionId );
+    }
+
+    public BuildAgentGroupConfiguration addBuildAgentGroup( BuildAgentGroupConfiguration buildAgentGroup )
+        throws Exception
+    {
+        return continuum.addBuildAgentGroup( buildAgentGroup );
+    }
+
+    public Map<String, Object> addBuildAgentGroupRPC( Map<String, Object> buildAgentGroup )
+        throws Exception
+    {
+        return continuum.addBuildAgentGroupRPC( buildAgentGroup );
+    }
+
+    public BuildAgentGroupConfiguration getBuildAgentGroup( String name )
+    {
+        return continuum.getBuildAgentGroup( name );
+    }
+
+    public Map<String, Object> getBuildAgentGroupRPC( String name )
+    {
+        return continuum.getBuildAgentGroupRPC( name );
+    }
+
+    public BuildAgentGroupConfiguration updateBuildAgentGroup( BuildAgentGroupConfiguration buildAgentGroup )
+        throws Exception
+    {
+        return continuum.updateBuildAgentGroup( buildAgentGroup );
+    }
+
+    public Map<String, Object> updateBuildAgentGroupRPC( Map<String, Object> buildAgentGroup )
+        throws Exception
+    {
+        return continuum.updateBuildAgentGroupRPC( buildAgentGroup );
+    }
+
+    public int removeBuildAgentGroup( String name )
+        throws Exception
+    {
+        return continuum.removeBuildAgentGroup( name );
+    }
+
+    public List<BuildAgentConfiguration> getBuildAgentsWithInstallations()
+        throws Exception
+    {
+        return continuum.getBuildAgentsWithInstallations();
+    }
+
+    public List<Object> getBuildAgentsWithInstallationsRPC()
+        throws Exception
+    {
+        return continuum.getBuildAgentsWithInstallationsRPC();
+    }
 }
diff --git a/continuum-xmlrpc/continuum-xmlrpc-client/src/main/java/org/apache/maven/continuum/xmlrpc/client/SampleClient.java b/continuum-xmlrpc/continuum-xmlrpc-client/src/main/java/org/apache/maven/continuum/xmlrpc/client/SampleClient.java
index 367fb97..57c5d70 100644
--- a/continuum-xmlrpc/continuum-xmlrpc-client/src/main/java/org/apache/maven/continuum/xmlrpc/client/SampleClient.java
+++ b/continuum-xmlrpc/continuum-xmlrpc-client/src/main/java/org/apache/maven/continuum/xmlrpc/client/SampleClient.java
@@ -22,10 +22,12 @@
 import org.apache.continuum.xmlrpc.repository.DirectoryPurgeConfiguration;
 import org.apache.continuum.xmlrpc.repository.LocalRepository;
 import org.apache.continuum.xmlrpc.repository.RepositoryPurgeConfiguration;
+import org.apache.continuum.xmlrpc.utils.BuildTrigger;
 import org.apache.maven.continuum.xmlrpc.project.AddingResult;
 import org.apache.maven.continuum.xmlrpc.project.BuildDefinition;
 import org.apache.maven.continuum.xmlrpc.project.BuildResult;
 import org.apache.maven.continuum.xmlrpc.project.BuildResultSummary;
+import org.apache.maven.continuum.xmlrpc.project.ContinuumProjectState;
 import org.apache.maven.continuum.xmlrpc.project.ProjectDependency;
 import org.apache.maven.continuum.xmlrpc.project.ProjectGroupSummary;
 import org.apache.maven.continuum.xmlrpc.project.ProjectSummary;
@@ -33,6 +35,7 @@
 import org.apache.maven.continuum.xmlrpc.scm.ScmResult;
 
 import java.net.URL;
+import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 
@@ -49,8 +52,45 @@
     {
         client = new ContinuumXmlRpcClient( new URL( args[0] ), args[1], args[2] );
 
+        // Test for [CONTINUUM-2641]: (test with distributed builds with multiple build agents or parallel builds with > 1 build queue)
+        // make sure to set the projectIds to the actual projectIds of your projects added in Continuum
+        int projectIds[] = new int[]{2, 3, 4, 5, 6};
+
+        List<Thread> threads = new ArrayList<Thread>();
+
+        for ( int i = 0; i < projectIds.length; i++ )
+        {
+            final int order = i;
+            final int projectId = projectIds[i];
+            Runnable task = new Runnable()
+            {
+                public void run()
+                {
+                    BuildTrigger buildTrigger = new BuildTrigger();
+                    buildTrigger.setTrigger( ContinuumProjectState.TRIGGER_FORCED );
+                    buildTrigger.setTriggeredBy( "admin" );
+                    System.out.println( "Building project #" + order + " '" + projectId + "'.." );
+                    try
+                    {
+                        client.buildProject( projectId, buildTrigger );
+                    }
+                    catch ( Exception e )
+                    {
+                        throw new RuntimeException( e );
+                    }
+                }
+            };
+            threads.add( new Thread( task ) );
+        }
+
+        for ( Thread thread : threads )
+        {
+            thread.start();
+        }
+
         System.out.println( "Adding project..." );
-        AddingResult result = client.addMavenTwoProject( "http://svn.apache.org/repos/asf/continuum/sandbox/simple-example/pom.xml" );
+        AddingResult result = client.addMavenTwoProject(
+            "http://svn.apache.org/repos/asf/continuum/sandbox/simple-example/pom.xml" );
         if ( result.hasErrors() )
         {
             System.out.println( result.getErrorsAsString() );
@@ -86,14 +126,23 @@
         {
             ps = client.refreshProjectSummary( ps );
             System.out.println( "State of " + ps.getName() + "(" + ps.getId() + "): " +
-                client.getProjectStatusAsString( ps.getState() ) );
+                                    client.getProjectStatusAsString( ps.getState() ) );
             Thread.sleep( 1000 );
         }
 
         System.out.println();
 
+        BuildDefinition buildDef = new BuildDefinition();
+        buildDef.setArguments( "A-Za-z0-9_./=,\": \\-" );
+        buildDef.setSchedule( client.getSchedule( 1 ) );
+        client.addBuildDefinitionToProjectGroup( 1, buildDef );
+
+        ps = client.getProjectSummary( 1 );
         System.out.println( "Add the project to the build queue." );
-        client.buildProject( ps.getId() );
+        BuildTrigger trigger = new BuildTrigger();
+        trigger.setTrigger( 1 );
+        trigger.setTriggeredBy( "<script>alert('hahaha' )</script>" );
+        client.buildProject( ps.getId(), trigger );
         while ( !"Building".equals( client.getProjectStatusAsString( ps.getState() ) ) )
         {
             ps = client.refreshProjectSummary( ps );
@@ -102,8 +151,8 @@
 
         System.out.println( "Building..." );
         String state = "unknown";
-        while ( "Updating".equals( client.getProjectStatusAsString( ps.getState() ) ) ||
-                "Building".equals( client.getProjectStatusAsString( ps.getState() ) ) )
+        while ( "Updating".equals( client.getProjectStatusAsString( ps.getState() ) ) || "Building".equals(
+            client.getProjectStatusAsString( ps.getState() ) ) )
         {
             ps = client.refreshProjectSummary( ps );
             state = client.getProjectStatusAsString( ps.getState() );
@@ -133,9 +182,9 @@
             brs = (BuildResultSummary) i.next();
             System.out.print( "Removing build result (" + brs.getId() + ") - " );
             BuildResult br = client.getBuildResult( ps.getId(), brs.getId() );
-            System.out.println( (client.removeBuildResult( br ) == 0 ? "OK" : "Error" ) );
+            System.out.println( ( client.removeBuildResult( br ) == 0 ? "OK" : "Error" ) );
         }
-        System.out.println( "Done.");
+        System.out.println( "Done." );
 
         System.out.println();
 
@@ -194,7 +243,7 @@
         System.out.println( "Adding Directory Purge Configuration..." );
         dirPurgeConfig = client.addDirectoryPurgeConfiguration( dirPurgeConfig );
         System.out.println();
-        
+
         RepositoryPurgeConfiguration purgeConfig = new RepositoryPurgeConfiguration();
         purgeConfig.setDeleteAll( true );
         purgeConfig.setRepository( repository );
@@ -214,8 +263,8 @@
 
         System.out.println( "Remove local repository" );
         System.out.println( "=====================" );
-        System.out.println( "Removing Local Repository '" + repository.getName() + "' (" + 
-                            repository.getId() + ")..." );
+        System.out.println( "Removing Local Repository '" + repository.getName() + "' (" +
+                                repository.getId() + ")..." );
         client.removeLocalRepository( repository.getId() );
         System.out.println( "Done." );
     }
@@ -328,7 +377,7 @@
 
     public static void printLocalRepository( LocalRepository repo )
     {
-        System.out.println( "Id: " +repo.getId() );
+        System.out.println( "Id: " + repo.getId() );
         System.out.println( "Layout: " + repo.getLayout() );
         System.out.println( "Location: " + repo.getLocation() );
         System.out.println( "Name: " + repo.getName() );
diff --git a/continuum-xmlrpc/continuum-xmlrpc-server/pom.xml b/continuum-xmlrpc/continuum-xmlrpc-server/pom.xml
index 4e0bd9f..973be36 100644
--- a/continuum-xmlrpc/continuum-xmlrpc-server/pom.xml
+++ b/continuum-xmlrpc/continuum-xmlrpc-server/pom.xml
@@ -1,27 +1,28 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
+  ~ 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.
+  -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <groupId>org.apache.continuum</groupId>
     <artifactId>continuum-xmlrpc</artifactId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>continuum-xmlrpc-server</artifactId>
@@ -29,16 +30,32 @@
 
   <dependencies>
     <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
       <groupId>org.apache.continuum</groupId>
       <artifactId>continuum-xmlrpc-api</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-security</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
       <artifactId>continuum-api</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-security</artifactId>
+      <artifactId>continuum-model</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-buildagent-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.continuum</groupId>
+      <artifactId>continuum-release</artifactId>
     </dependency>
     <dependency>
       <groupId>org.codehaus.redback</groupId>
@@ -46,22 +63,59 @@
     </dependency>
     <dependency>
       <groupId>org.codehaus.redback</groupId>
+      <artifactId>redback-users-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>redback-authorization-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>redback-authentication-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>redback-policy</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.redback</groupId>
       <artifactId>redback-system</artifactId>
     </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-utils</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-classworlds</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-component-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-container-default</artifactId>
       <version>1.0-alpha-20</version>
     </dependency>
     <dependency>
       <groupId>org.apache.xmlrpc</groupId>
+      <artifactId>xmlrpc-common</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.xmlrpc</groupId>
       <artifactId>xmlrpc-server</artifactId>
-      <version>3.1</version>
     </dependency>
     <dependency>
       <groupId>net.sf.dozer</groupId>
       <artifactId>dozer</artifactId>
       <version>4.0</version>
+      <exclusions>
+        <exclusion>
+          <groupId>commons-logging</groupId>
+          <artifactId>commons-logging</artifactId>
+        </exclusion>
+      </exclusions>
     </dependency>
     <dependency>
       <groupId>javax.servlet</groupId>
@@ -69,6 +123,31 @@
       <version>2.4</version>
       <scope>provided</scope>
     </dependency>
+    <dependency>
+      <groupId>org.jmock</groupId>
+      <artifactId>jmock</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jmock</groupId>
+      <artifactId>jmock-junit3</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>cglib</groupId>
+      <artifactId>cglib-nodep</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.objenesis</groupId>
+      <artifactId>objenesis</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-simple</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>
diff --git a/continuum-xmlrpc/continuum-xmlrpc-server/src/main/java/org/apache/maven/continuum/xmlrpc/server/AbstractContinuumSecureService.java b/continuum-xmlrpc/continuum-xmlrpc-server/src/main/java/org/apache/maven/continuum/xmlrpc/server/AbstractContinuumSecureService.java
index 03b5c62..5426fc8 100644
--- a/continuum-xmlrpc/continuum-xmlrpc-server/src/main/java/org/apache/maven/continuum/xmlrpc/server/AbstractContinuumSecureService.java
+++ b/continuum-xmlrpc/continuum-xmlrpc-server/src/main/java/org/apache/maven/continuum/xmlrpc/server/AbstractContinuumSecureService.java
@@ -63,12 +63,8 @@
      */
     public boolean isAuthenticated()
     {
-        if ( getSecuritySession() == null || !getSecuritySession().isAuthenticated() )
-        {
-            return false;
-        }
+        return !( getSecuritySession() == null || !getSecuritySession().isAuthenticated() );
 
-        return true;
     }
 
     /**
@@ -538,7 +534,7 @@
         {
             throw new ContinuumException( "Authentication required." );
         }
-    
+
         try
         {
             checkAuthorization( ContinuumRoleConstants.SYSTEM_ADMINISTRATOR_ROLE );
diff --git a/continuum-xmlrpc/continuum-xmlrpc-server/src/main/java/org/apache/maven/continuum/xmlrpc/server/AddingResultUtil.java b/continuum-xmlrpc/continuum-xmlrpc-server/src/main/java/org/apache/maven/continuum/xmlrpc/server/AddingResultUtil.java
new file mode 100644
index 0000000..4bfcf2d
--- /dev/null
+++ b/continuum-xmlrpc/continuum-xmlrpc-server/src/main/java/org/apache/maven/continuum/xmlrpc/server/AddingResultUtil.java
@@ -0,0 +1,72 @@
+package org.apache.maven.continuum.xmlrpc.server;
+
+/*
+ * 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.HashMap;
+import java.util.Map;
+
+public class AddingResultUtil
+{
+    private static final Map<String, String> errorMap;
+
+    static
+    {
+        errorMap = new HashMap<String, String>();
+        errorMap.put( "add.project.unknown.host.error", "The specified host is either unknown or inaccessible." );
+        errorMap.put( "add.project.connect.error", "Unable to connect to remote server." );
+        errorMap.put( "add.project.malformed.url.error", "The URL provided is malformed." );
+        errorMap.put( "add.project.field.required.error", "Either POM URL or Upload POM is required." );
+        errorMap.put( "add.project.xml.parse.error", "The XML content of the POM can not be parsed." );
+        errorMap.put( "add.project.extend.error", "Cannot use a POM with an ''extend'' element." );
+        errorMap.put( "add.project.missing.pom.error",
+                      "POM file does not exist. Either the POM you specified or one of its modules does not exist." );
+        errorMap.put( "add.project.missing.groupid.error", "Missing 'groupId' element in the POM." );
+        errorMap.put( "add.project.missing.artifactid.error", "Missing 'artifactId' element in the POM." );
+        errorMap.put( "add.project.missing.version.error", "Missing 'version' element in the POM." );
+        errorMap.put( "add.project.missing.name.error", "Missing 'name' element in the POM." );
+        errorMap.put( "add.project.missing.repository.error", "Missing 'repository' element in the POM." );
+        errorMap.put( "add.project.missing.scm.error", "Missing 'scm' element in the POM project." );
+        errorMap.put( "add.project.missing.scm.connection.error",
+                      "Missing 'connection' sub-element in the 'scm' element in the POM." );
+        errorMap.put( "add.project.missing.notifier.type.error",
+                      "Missing 'type' sub-element in the 'notifier' element in the POM." );
+        errorMap.put( "add.project.missing.notifier.configuration.error",
+                      "Missing 'configuration' sub-element in the 'notifier' element in the POM." );
+        errorMap.put( "add.project.metadata.transfer.error", "Transfer of Metadata has failed." );
+        errorMap.put( "add.project.validation.protocol.not_allowed",
+                      "The specified resource isn't a file or the protocol used isn't allowed." );
+        errorMap.put( "add.project.unauthorized.error",
+                      "You are not authorized to access the requested URL. Please verify that the correct username and password are provided." );
+        errorMap.put( "add.project.artifact.not.found.error",
+                      "Missing artifact trying to build the POM. Check that its parent POM is available or add it first in Continuum." );
+        errorMap.put( "add.project.project.building.error", "Unknown error trying to build POM." );
+        errorMap.put( "add.project.unknown.error",
+                      "The specified resource cannot be accessed. Please try again later or contact your administrator." );
+        errorMap.put( "add.project.nogroup.error", "No project group specified." );
+        errorMap.put( "add.project.duplicate.error", "Trying to add duplicate projects in the same project group." );
+    }
+
+    public static String getErrorMessage( String error )
+    {
+        String message = errorMap.get( error );
+
+        return message == null ? error : message;
+    }
+}
diff --git a/continuum-xmlrpc/continuum-xmlrpc-server/src/main/java/org/apache/maven/continuum/xmlrpc/server/ConfiguredBeanProcessorFactory.java b/continuum-xmlrpc/continuum-xmlrpc-server/src/main/java/org/apache/maven/continuum/xmlrpc/server/ConfiguredBeanProcessorFactory.java
index f935faf..6de733a 100644
--- a/continuum-xmlrpc/continuum-xmlrpc-server/src/main/java/org/apache/maven/continuum/xmlrpc/server/ConfiguredBeanProcessorFactory.java
+++ b/continuum-xmlrpc/continuum-xmlrpc-server/src/main/java/org/apache/maven/continuum/xmlrpc/server/ConfiguredBeanProcessorFactory.java
@@ -34,7 +34,6 @@
 import org.slf4j.LoggerFactory;
 
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.Map;
 
 /**
@@ -45,23 +44,22 @@
 public class ConfiguredBeanProcessorFactory
     implements RequestProcessorFactoryFactory, Initializable, Contextualizable
 {
-    private Logger log = LoggerFactory.getLogger( ConfiguredBeanProcessorFactory.class );
+    private static final Logger log = LoggerFactory.getLogger( ConfiguredBeanProcessorFactory.class );
 
     /**
      * @plexus.requirement role="org.apache.maven.continuum.xmlrpc.server.ContinuumXmlRpcComponent"
      */
-    private Map xmlrpcComponents;
+    private Map<String, Object> xmlrpcComponents;
 
-    private Map componentsMapping = new HashMap();
+    private Map<String, String> componentsMapping = new HashMap<String, String>();
 
     PlexusContainer container;
 
     public void initialize()
         throws InitializationException
     {
-        for ( Iterator i = xmlrpcComponents.keySet().iterator(); i.hasNext(); )
+        for ( String key : xmlrpcComponents.keySet() )
         {
-            String key = (String) i.next();
             String className = xmlrpcComponents.get( key ).getClass().getName();
             componentsMapping.put( className, key );
         }
@@ -112,7 +110,7 @@
 
     private String getComponentKey( Class cls )
     {
-        return (String) componentsMapping.get( cls.getName() );
+        return componentsMapping.get( cls.getName() );
     }
 
     private Object getComponent( Class cls )
diff --git a/continuum-xmlrpc/continuum-xmlrpc-server/src/main/java/org/apache/maven/continuum/xmlrpc/server/ContinuumServiceImpl.java b/continuum-xmlrpc/continuum-xmlrpc-server/src/main/java/org/apache/maven/continuum/xmlrpc/server/ContinuumServiceImpl.java
index 97c2411..23f18c7 100644
--- a/continuum-xmlrpc/continuum-xmlrpc-server/src/main/java/org/apache/maven/continuum/xmlrpc/server/ContinuumServiceImpl.java
+++ b/continuum-xmlrpc/continuum-xmlrpc-server/src/main/java/org/apache/maven/continuum/xmlrpc/server/ContinuumServiceImpl.java
@@ -21,26 +21,41 @@
 
 import net.sf.dozer.util.mapping.DozerBeanMapperSingletonWrapper;
 import net.sf.dozer.util.mapping.MapperIF;
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.continuum.buildagent.NoBuildAgentException;
+import org.apache.continuum.buildagent.NoBuildAgentInGroupException;
+import org.apache.continuum.builder.distributed.manager.DistributedBuildManager;
+import org.apache.continuum.buildmanager.BuildManagerException;
+import org.apache.continuum.buildmanager.BuildsManager;
+import org.apache.continuum.configuration.BuildAgentConfigurationException;
+import org.apache.continuum.configuration.ContinuumConfigurationException;
 import org.apache.continuum.dao.SystemConfigurationDao;
 import org.apache.continuum.purge.ContinuumPurgeManagerException;
 import org.apache.continuum.purge.PurgeConfigurationServiceException;
 import org.apache.continuum.repository.RepositoryServiceException;
-import org.apache.continuum.taskqueue.manager.TaskQueueManager;
-import org.apache.continuum.taskqueue.manager.TaskQueueManagerException;
+import org.apache.continuum.utils.release.ReleaseUtil;
 import org.apache.continuum.xmlrpc.release.ContinuumReleaseResult;
 import org.apache.continuum.xmlrpc.repository.DirectoryPurgeConfiguration;
 import org.apache.continuum.xmlrpc.repository.LocalRepository;
 import org.apache.continuum.xmlrpc.repository.RepositoryPurgeConfiguration;
+import org.apache.continuum.xmlrpc.utils.BuildTrigger;
 import org.apache.maven.continuum.Continuum;
 import org.apache.maven.continuum.ContinuumException;
+import org.apache.maven.continuum.builddefinition.BuildDefinitionServiceException;
+import org.apache.maven.continuum.configuration.ConfigurationException;
+import org.apache.maven.continuum.configuration.ConfigurationService;
+import org.apache.maven.continuum.configuration.ConfigurationStoringException;
 import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
 import org.apache.maven.continuum.installation.InstallationException;
-import org.apache.maven.continuum.profile.ProfileException;
+import org.apache.maven.continuum.installation.InstallationService;
 import org.apache.maven.continuum.project.ContinuumProjectState;
 import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
 import org.apache.maven.continuum.security.ContinuumRoleConstants;
 import org.apache.maven.continuum.store.ContinuumStoreException;
 import org.apache.maven.continuum.xmlrpc.project.AddingResult;
+import org.apache.maven.continuum.xmlrpc.project.BuildAgentConfiguration;
+import org.apache.maven.continuum.xmlrpc.project.BuildAgentGroupConfiguration;
 import org.apache.maven.continuum.xmlrpc.project.BuildDefinition;
 import org.apache.maven.continuum.xmlrpc.project.BuildDefinitionTemplate;
 import org.apache.maven.continuum.xmlrpc.project.BuildProjectTask;
@@ -50,24 +65,30 @@
 import org.apache.maven.continuum.xmlrpc.project.ProjectGroup;
 import org.apache.maven.continuum.xmlrpc.project.ProjectGroupSummary;
 import org.apache.maven.continuum.xmlrpc.project.ProjectNotifier;
+import org.apache.maven.continuum.xmlrpc.project.ProjectScmRoot;
 import org.apache.maven.continuum.xmlrpc.project.ProjectSummary;
+import org.apache.maven.continuum.xmlrpc.project.ReleaseListenerSummary;
 import org.apache.maven.continuum.xmlrpc.project.Schedule;
 import org.apache.maven.continuum.xmlrpc.system.Installation;
 import org.apache.maven.continuum.xmlrpc.system.Profile;
 import org.apache.maven.continuum.xmlrpc.system.SystemConfiguration;
+import org.apache.maven.scm.provider.svn.repository.SvnScmProviderRepository;
 import org.codehaus.plexus.redback.authorization.AuthorizationException;
 import org.codehaus.plexus.redback.role.RoleManager;
 import org.codehaus.plexus.redback.role.RoleManagerException;
-import org.codehaus.plexus.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+import java.io.File;
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
@@ -77,7 +98,49 @@
 public class ContinuumServiceImpl
     extends AbstractContinuumSecureService
 {
-    private static MapperIF mapper = DozerBeanMapperSingletonWrapper.getInstance();
+    private static final String NAME_VALID_EXPRESSION = "[A-Za-z0-9_.\\s\\-():\\/,]*";
+
+    private static final String DIRECTORY_VALID_EXPRESSION = "[A-Za-z0-9_/\\s:.\\\\-]*";
+
+    private static final String URL_VALID_EXPRESSION = "[A-Za-z0-9_.@:/-]*";
+
+    private static final String PROJECT_VERSION_VALID_EXPRESSION = "[a-zA-Z0-9.-]*";
+
+    private static final String PROJECT_SCM_URL_VALID_EXPRESSION = "[a-zA-Z0-9_.:${}#~=@\\/|\\[\\]-]*";
+
+    private static final String PROJECT_SCM_TAG_VALID_EXPRESSION = "[a-zA-Z0-9_.:@\\/|#~=\\[\\]-]*";
+
+    private static final String PROJECT_ARTIFACT_ID_VALID_EXPRESSION = "[A-Za-z0-9\\-]*";
+
+    private static final String PROJECT_EXECUTOR_OR_BUILDDEF_TYPE_VALID_EXPRESSION = "maven2|maven-1|ant|shell";
+
+    private static final String SCHEDULE_CRON_VALID_EXPRESSION = "[A-Z0-9\\s*/,-?#]*";
+
+    private static final String PROJECTGROUP_ID_VALID_EXPRESSION = "[a-zA-Z0-9_.\\s\\-]*";
+
+    private static final String REPOSITORY_LAYOUT_VALID_EXPRESSION = "default|legacy";
+
+    private static final String BUILD_DEFINITION_ARGUMENTS_VALID_EXPRESSION = "[!A-Za-z0-9_./=,${}\":\\s\\\\-]*";
+
+    private static final String BUILD_DEFINITION_GOALS_VALID_EXPRESSION = "[A-Za-z0-9_:\\s\\-]*";
+
+    private static final String BUILD_DEFINITION_BUILD_FILE_VALID_EXPRESSION = "[A-Za-z0-9_.\\-/\\\\]*";
+
+    private static final String INSTALLATION_VARNAME_VALID_EXPRESSION = "[A-Za-z][A-Za-z0-9_]*";
+
+    private static final String INSTALLATION_VARVALUE_VALID_EXPRESSION = "(?:[~A-Za-z0-9_.:=${}\\\\/\\-+]|\\s|[()])*";
+
+    private static final String INSTALLATION_TYPE_VALID_EXPRESSION = "jdk|maven2|maven1|ant|envvar";
+
+    private static final String DIRECTORY_TYPE_VALID_EXPRESSION = "releases|buildOutput";
+
+    private static final String NOTIFIER_TYPE_VALID_EXPRESSION = "irc|jabber|msn|mail|wagon";
+
+    private static final String USERNAME_VALID_EXPRESSION = "[a-zA-Z_0-9\\-.@]*";
+
+    private static final MapperIF mapper = DozerBeanMapperSingletonWrapper.getInstance();
+
+    private final Logger logger = LoggerFactory.getLogger( ContinuumServiceImpl.class );
 
     /**
      * @plexus.requirement
@@ -95,9 +158,14 @@
     private RoleManager roleManager;
 
     /**
+     * @plexus.requirement role-hint="parallel"
+     */
+    private BuildsManager parallelBuildsManager;
+
+    /**
      * @plexus.requirement
      */
-    private TaskQueueManager taskQueueManager;
+    private DistributedBuildManager distributedBuildManager;
 
     public boolean ping()
         throws ContinuumException
@@ -116,8 +184,8 @@
 
         List<ProjectSummary> projectsList = new ArrayList<ProjectSummary>();
 
-        Collection<org.apache.maven.continuum.model.project.Project> projects =
-            continuum.getProjectsInGroup( projectGroupId );
+        Collection<org.apache.maven.continuum.model.project.Project> projects = continuum.getProjectsInGroup(
+            projectGroupId );
         if ( projects != null )
         {
             for ( org.apache.maven.continuum.model.project.Project project : projects )
@@ -149,7 +217,6 @@
         return populateProject( project );
     }
 
-
     public int removeProject( int projectId )
         throws ContinuumException
     {
@@ -165,6 +232,30 @@
     public ProjectSummary updateProject( ProjectSummary project )
         throws ContinuumException
     {
+        if ( StringUtils.isNotBlank( project.getName() ) && !project.getName().matches( NAME_VALID_EXPRESSION ) )
+        //!GenericValidator.matchRegexp( project.getName(), NAME_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Project Name contains invalid characters" );
+        }
+
+        if ( StringUtils.isNotBlank( project.getScmTag() ) && !project.getScmTag().matches(
+            PROJECT_SCM_TAG_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Project Scm Tag contains invalid characters" );
+        }
+
+        if ( StringUtils.isNotBlank( project.getScmUrl() ) && !project.getScmUrl().matches(
+            PROJECT_SCM_URL_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Project Scm Url contains invalid characters" );
+        }
+
+        if ( StringUtils.isNotBlank( project.getVersion() ) && !project.getVersion().matches(
+            PROJECT_VERSION_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Project Version contains invalid characters" );
+        }
+
         ProjectSummary ps = getProjectSummary( project.getId() );
 
         checkRemoveProjectFromGroupAuthorization( ps.getProjectGroup().getName() );
@@ -214,7 +305,8 @@
         throws ContinuumException
     {
         ProjectGroup result = null;
-        org.apache.maven.continuum.model.project.ProjectGroup projectGroup = continuum.getProjectGroup( projectGroupId );
+        org.apache.maven.continuum.model.project.ProjectGroup projectGroup = continuum.getProjectGroup(
+            projectGroupId );
         try
         {
             if ( isAuthorized( ContinuumRoleConstants.CONTINUUM_VIEW_GROUP_OPERATION, projectGroup.getName() ) )
@@ -268,7 +360,8 @@
     private ProjectGroupSummary getPGSummary( int projectGroupId )
         throws ContinuumException
     {
-        org.apache.maven.continuum.model.project.ProjectGroup projectGroup = continuum.getProjectGroup( projectGroupId );
+        org.apache.maven.continuum.model.project.ProjectGroup projectGroup = continuum.getProjectGroup(
+            projectGroupId );
 
         checkViewProjectGroupAuthorization( projectGroup.getName() );
         return populateProjectGroupSummary( projectGroup );
@@ -279,8 +372,8 @@
     {
         checkViewProjectGroupAuthorization( getProjectGroupName( projectGroupId ) );
 
-        org.apache.maven.continuum.model.project.ProjectGroup projectGroup =
-            continuum.getProjectGroup( projectGroupId );
+        org.apache.maven.continuum.model.project.ProjectGroup projectGroup = continuum.getProjectGroup(
+            projectGroupId );
         return populateProjectGroupSummary( projectGroup );
     }
 
@@ -289,8 +382,8 @@
     {
         checkViewProjectGroupAuthorization( getProjectGroupName( projectGroupId ) );
 
-        org.apache.maven.continuum.model.project.ProjectGroup projectGroup =
-            continuum.getProjectGroupWithProjects( projectGroupId );
+        org.apache.maven.continuum.model.project.ProjectGroup projectGroup = continuum.getProjectGroupWithProjects(
+            projectGroupId );
         return populateProjectGroupWithAllDetails( projectGroup );
     }
 
@@ -322,8 +415,13 @@
             throw new ContinuumException( "project group name can't be spaces" );
         }
 
-        org.apache.maven.continuum.model.project.ProjectGroup pg =
-            continuum.getProjectGroupWithProjects( projectGroup.getId() );
+        if ( !projectGroup.getName().matches( NAME_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "ProjectGroup Name contains invalid characters" );
+        }
+
+        org.apache.maven.continuum.model.project.ProjectGroup pg = continuum.getProjectGroupWithProjects(
+            projectGroup.getId() );
 
         // need to administer roles since they are based off of this
         // todo convert everything like to work off of string keys
@@ -343,12 +441,12 @@
             }
         }
 
-        pg.setDescription( projectGroup.getDescription() );
+        pg.setDescription( StringEscapeUtils.escapeXml( projectGroup.getDescription() ) );
 
-        org.apache.continuum.model.repository.LocalRepository repo = 
+        org.apache.continuum.model.repository.LocalRepository repo =
             new org.apache.continuum.model.repository.LocalRepository();
         pg.setLocalRepository( populateLocalRepository( projectGroup.getLocalRepository(), repo ) );
-        
+
         continuum.updateProjectGroup( pg );
         return getProjectGroupSummary( projectGroup.getId() );
     }
@@ -356,11 +454,21 @@
     public ProjectGroupSummary addProjectGroup( String groupName, String groupId, String description )
         throws Exception
     {
+        if ( StringUtils.isNotBlank( groupId ) && !groupId.matches( PROJECTGROUP_ID_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "ProjectGroup Id contains invalid characters" );
+        }
+
+        if ( StringUtils.isNotBlank( groupName ) && !groupName.matches( NAME_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "ProjectGroup Name contains invalid characters" );
+        }
+
         org.apache.maven.continuum.model.project.ProjectGroup pg =
             new org.apache.maven.continuum.model.project.ProjectGroup();
         pg.setName( groupName );
         pg.setGroupId( groupId );
-        pg.setDescription( description );
+        pg.setDescription( StringEscapeUtils.escapeXml( description ) );
         continuum.addProjectGroup( pg );
         return populateProjectGroupSummary( continuum.getProjectGroupByGroupId( groupId ) );
     }
@@ -374,9 +482,14 @@
     public ProjectNotifier updateNotifier( int projectid, ProjectNotifier newNotifier )
         throws ContinuumException
     {
+        if ( StringUtils.isNotBlank( newNotifier.getType() ) && !newNotifier.getType().matches(
+            NOTIFIER_TYPE_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Notifier Type can only be 'irc, jabber, msn, mail or wagon" );
+        }
 
-        org.apache.maven.continuum.model.project.ProjectNotifier notifier =
-                        continuum.getNotifier( projectid, newNotifier.getId() );
+        org.apache.maven.continuum.model.project.ProjectNotifier notifier = continuum.getNotifier( projectid,
+                                                                                                   newNotifier.getId() );
         notifier.setConfiguration( newNotifier.getConfiguration() );
         notifier.setFrom( newNotifier.getFrom() );
         notifier.setRecipientType( newNotifier.getRecipientType() );
@@ -392,9 +505,14 @@
     public ProjectNotifier addNotifier( int projectid, ProjectNotifier newNotifier )
         throws ContinuumException
     {
+        if ( StringUtils.isNotBlank( newNotifier.getType() ) && !newNotifier.getType().matches(
+            NOTIFIER_TYPE_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Notifier Type can only be 'irc, jabber, msn, mail or wagon'" );
+        }
 
         org.apache.maven.continuum.model.project.ProjectNotifier notifier =
-                        new org.apache.maven.continuum.model.project.ProjectNotifier();
+            new org.apache.maven.continuum.model.project.ProjectNotifier();
         notifier.setConfiguration( newNotifier.getConfiguration() );
         notifier.setFrom( newNotifier.getFrom() );
         notifier.setRecipientType( newNotifier.getRecipientType() );
@@ -423,9 +541,14 @@
     public ProjectNotifier updateGroupNotifier( int projectgroupid, ProjectNotifier newNotifier )
         throws ContinuumException
     {
+        if ( StringUtils.isNotBlank( newNotifier.getType() ) && !newNotifier.getType().matches(
+            NOTIFIER_TYPE_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Notifier Type can only be 'irc, jabber, msn, mail, or wagon" );
+        }
 
-        org.apache.maven.continuum.model.project.ProjectNotifier notifier =
-                        continuum.getGroupNotifier( projectgroupid, newNotifier.getId() );
+        org.apache.maven.continuum.model.project.ProjectNotifier notifier = continuum.getGroupNotifier( projectgroupid,
+                                                                                                        newNotifier.getId() );
         notifier.setConfiguration( newNotifier.getConfiguration() );
         notifier.setFrom( newNotifier.getFrom() );
         notifier.setRecipientType( newNotifier.getRecipientType() );
@@ -442,7 +565,14 @@
         throws ContinuumException
     {
         org.apache.maven.continuum.model.project.ProjectNotifier notifier =
-                        new org.apache.maven.continuum.model.project.ProjectNotifier();
+            new org.apache.maven.continuum.model.project.ProjectNotifier();
+
+        if ( StringUtils.isNotBlank( newNotifier.getType() ) && !newNotifier.getType().matches(
+            NOTIFIER_TYPE_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Notifier Type can only be 'irc, jabber, msn, mail or wagon" );
+        }
+
         notifier.setConfiguration( newNotifier.getConfiguration() );
         notifier.setFrom( newNotifier.getFrom() );
         notifier.setRecipientType( newNotifier.getRecipientType() );
@@ -473,8 +603,8 @@
 
         checkViewProjectGroupAuthorization( ps.getProjectGroup().getName() );
 
-        List<org.apache.maven.continuum.model.project.BuildDefinition> bds =
-            continuum.getBuildDefinitionsForProject( projectId );
+        List<org.apache.maven.continuum.model.project.BuildDefinition> bds = continuum.getBuildDefinitionsForProject(
+            projectId );
 
         List<BuildDefinition> result = new ArrayList<BuildDefinition>();
         for ( org.apache.maven.continuum.model.project.BuildDefinition bd : bds )
@@ -500,6 +630,14 @@
         return result;
     }
 
+    public BuildDefinition getBuildDefinition( int buildDefinitionId )
+        throws Exception
+    {
+        org.apache.maven.continuum.model.project.BuildDefinition bd = continuum.getBuildDefinition( buildDefinitionId );
+
+        return populateBuildDefinition( bd );
+    }
+
     public int removeBuildDefinitionFromProjectGroup( int projectGroupId, int buildDefinitionId )
         throws ContinuumException
     {
@@ -515,8 +653,8 @@
         ProjectSummary ps = getProjectSummary( projectId );
 
         checkModifyProjectBuildDefinitionAuthorization( ps.getProjectGroup().getName() );
-        org.apache.maven.continuum.model.project.BuildDefinition newbd =
-            continuum.getBuildDefinition( buildDef.getId() );
+        org.apache.maven.continuum.model.project.BuildDefinition newbd = continuum.getBuildDefinition(
+            buildDef.getId() );
         org.apache.maven.continuum.model.project.BuildDefinition bd = populateBuildDefinition( buildDef, newbd );
         bd = continuum.updateBuildDefinitionForProject( projectId, bd );
         return populateBuildDefinition( bd );
@@ -526,8 +664,8 @@
         throws ContinuumException
     {
         checkModifyGroupBuildDefinitionAuthorization( getProjectGroupName( projectGroupId ) );
-        org.apache.maven.continuum.model.project.BuildDefinition newbd =
-            continuum.getBuildDefinition( buildDef.getId() );
+        org.apache.maven.continuum.model.project.BuildDefinition newbd = continuum.getBuildDefinition(
+            buildDef.getId() );
         org.apache.maven.continuum.model.project.BuildDefinition bd = populateBuildDefinition( buildDef, newbd );
         bd = continuum.updateBuildDefinitionForProjectGroup( projectGroupId, bd );
         return populateBuildDefinition( bd );
@@ -584,69 +722,137 @@
     // Building
     // ----------------------------------------------------------------------
 
+    // TODO: delete this since it does exactly the same as buildProject( int projectId )
     public int addProjectToBuildQueue( int projectId )
-        throws ContinuumException
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException
     {
         ProjectSummary ps = getProjectSummary( projectId );
         checkBuildProjectInGroupAuthorization( ps.getProjectGroup().getName() );
 
-        continuum.buildProject( projectId, ContinuumProjectState.TRIGGER_SCHEDULED );
+        continuum.buildProject( projectId, new org.apache.continuum.utils.build.BuildTrigger(
+            ContinuumProjectState.TRIGGER_SCHEDULED, "" ) );
         return 0;
     }
 
+    // Alternative to buildProject since that forces TRIGGER_FORCED
     public int addProjectToBuildQueue( int projectId, int buildDefinitionId )
-        throws ContinuumException
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException
     {
         ProjectSummary ps = getProjectSummary( projectId );
         checkBuildProjectInGroupAuthorization( ps.getProjectGroup().getName() );
 
-        continuum.buildProject( projectId, buildDefinitionId, ContinuumProjectState.TRIGGER_SCHEDULED );
+        continuum.buildProject( projectId, buildDefinitionId, new org.apache.continuum.utils.build.BuildTrigger(
+            ContinuumProjectState.TRIGGER_SCHEDULED, "" ) );
         return 0;
     }
 
     public int buildProject( int projectId )
-        throws ContinuumException
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException
     {
         ProjectSummary ps = getProjectSummary( projectId );
         checkBuildProjectInGroupAuthorization( ps.getProjectGroup().getName() );
 
-        continuum.buildProject( projectId );
+        continuum.buildProject( projectId, new org.apache.continuum.utils.build.BuildTrigger(
+            ContinuumProjectState.TRIGGER_SCHEDULED, "" ) );
         return 0;
     }
 
-    public int buildProject( int projectId, int buildDefintionId )
-        throws ContinuumException
+    public int buildProject( int projectId, int buildDefinitionId )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException
     {
         ProjectSummary ps = getProjectSummary( projectId );
         checkBuildProjectInGroupAuthorization( ps.getProjectGroup().getName() );
 
-        continuum.buildProjectWithBuildDefinition( projectId, buildDefintionId );
+        buildProjectWithBuildDefinition( projectId, buildDefinitionId,
+                                         new org.apache.continuum.utils.build.BuildTrigger(
+                                             ContinuumProjectState.TRIGGER_SCHEDULED, "" )
+        );
+        return 0;
+    }
+
+    public int buildProject( int projectId, BuildTrigger xmlrpcBuildTrigger )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException
+    {
+        ProjectSummary ps = getProjectSummary( projectId );
+        checkBuildProjectInGroupAuthorization( ps.getProjectGroup().getName() );
+
+        org.apache.continuum.utils.build.BuildTrigger buildTrigger = populateBuildTrigger( xmlrpcBuildTrigger );
+
+        continuum.buildProject( projectId, buildTrigger );
+        return 0;
+    }
+
+    public int buildProject( int projectId, int buildDefinitionId, BuildTrigger xmlrpcBuildTrigger )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException
+    {
+        ProjectSummary projectSummary = getProjectSummary( projectId );
+        checkBuildProjectInGroupAuthorization( projectSummary.getProjectGroup().getName() );
+
+        org.apache.continuum.utils.build.BuildTrigger buildTrigger = populateBuildTrigger( xmlrpcBuildTrigger );
+        buildProjectWithBuildDefinition( projectId, buildDefinitionId, buildTrigger );
+
         return 0;
     }
 
     public int buildGroup( int projectGroupId )
-        throws ContinuumException
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException
     {
         ProjectGroupSummary pg = getProjectGroupSummary( projectGroupId );
         checkBuildProjectInGroupAuthorization( pg.getName() );
 
-        continuum.buildProjectGroup( projectGroupId );
+        continuum.buildProjectGroup( projectGroupId, new org.apache.continuum.utils.build.BuildTrigger(
+            ContinuumProjectState.TRIGGER_SCHEDULED, "" ) );
 
         return 0;
     }
 
-    public int buildGroup( int projectGroupId, int buildDefintionId )
-        throws ContinuumException
+    public int buildGroup( int projectGroupId, int buildDefinitionId )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException
     {
         ProjectGroupSummary pg = getProjectGroupSummary( projectGroupId );
         checkBuildProjectInGroupAuthorization( pg.getName() );
 
-        continuum.buildProjectGroupWithBuildDefinition( projectGroupId, buildDefintionId );
+        continuum.buildProjectGroupWithBuildDefinition( projectGroupId, buildDefinitionId,
+                                                        new org.apache.continuum.utils.build.BuildTrigger(
+                                                            ContinuumProjectState.TRIGGER_SCHEDULED, "" )
+        );
 
         return 0;
     }
 
     // ----------------------------------------------------------------------
+    // SCM roots
+    // ----------------------------------------------------------------------
+
+    public List<ProjectScmRoot> getProjectScmRootByProjectGroup( int projectGroupId )
+        throws ContinuumException
+    {
+        checkViewProjectGroupAuthorization( getProjectGroupName( projectGroupId ) );
+
+        List<org.apache.continuum.model.project.ProjectScmRoot> projectScmRoots =
+            continuum.getProjectScmRootByProjectGroup( projectGroupId );
+
+        List<ProjectScmRoot> result = new ArrayList<ProjectScmRoot>( projectScmRoots.size() );
+        for ( org.apache.continuum.model.project.ProjectScmRoot projectScmRoot : projectScmRoots )
+        {
+            result.add( populateProjectScmRoot( projectScmRoot ) );
+        }
+
+        return result;
+    }
+
+    public ProjectScmRoot getProjectScmRootByProject( int projectId )
+        throws ContinuumException
+    {
+        org.apache.continuum.model.project.ProjectScmRoot projectScmRoot = continuum.getProjectScmRootByProject(
+            projectId );
+
+        checkViewProjectGroupAuthorization( projectScmRoot.getProjectGroup().getName() );
+
+        return populateProjectScmRoot( projectScmRoot );
+    }
+
+    // ----------------------------------------------------------------------
     // Build Results
     // ----------------------------------------------------------------------
 
@@ -656,10 +862,15 @@
         ProjectSummary ps = getProjectSummary( projectId );
         checkViewProjectGroupAuthorization( ps.getProjectGroup().getName() );
 
-        org.apache.maven.continuum.model.project.BuildResult buildResult =
-            continuum.getLatestBuildResultForProject( projectId );
+        org.apache.maven.continuum.model.project.BuildResult buildResult = continuum.getLatestBuildResultForProject(
+            projectId );
 
-        return getBuildResult( projectId, buildResult.getId() );
+        if ( buildResult != null )
+        {
+            return getBuildResult( projectId, buildResult.getId() );
+        }
+
+        return null;
     }
 
     public BuildResult getBuildResult( int projectId, int buildId )
@@ -678,10 +889,11 @@
         checkViewProjectGroupAuthorization( ps.getProjectGroup().getName() );
 
         List<BuildResultSummary> result = new ArrayList<BuildResultSummary>();
-        Collection buildResults = continuum.getBuildResultsForProject( projectId );
+        Collection<org.apache.maven.continuum.model.project.BuildResult> buildResults =
+            continuum.getBuildResultsForProject( projectId );
         if ( buildResults != null )
         {
-            for ( org.apache.maven.continuum.model.project.BuildResult buildResult : (List<org.apache.maven.continuum.model.project.BuildResult>) buildResults )
+            for ( org.apache.maven.continuum.model.project.BuildResult buildResult : buildResults )
             {
                 BuildResultSummary br = populateBuildResultSummary( buildResult );
                 result.add( br );
@@ -694,8 +906,8 @@
     public int removeBuildResult( BuildResult br )
         throws ContinuumException
     {
-        checkModifyProjectGroupAuthorization(
-            getProjectSummary( br.getProject().getId() ).getProjectGroup().getName() );
+        checkModifyProjectGroupAuthorization( getProjectSummary(
+            br.getProject().getId() ).getProjectGroup().getName() );
         continuum.removeBuildResult( br.getId() );
         return 0;
     }
@@ -725,29 +937,105 @@
     public AddingResult addMavenTwoProject( String url, int projectGroupId )
         throws ContinuumException
     {
-        checkAddProjectToGroupAuthorization( getProjectGroupName( projectGroupId ) );
+        checkAddProjectAuthorization( projectGroupId );
 
         ContinuumProjectBuildingResult result = continuum.addMavenTwoProject( url, projectGroupId );
         return populateAddingResult( result );
     }
 
+    public AddingResult addMavenTwoProject( String url, int projectGroupId, boolean checkoutInSingleDirectory )
+        throws ContinuumException
+    {
+        checkAddProjectAuthorization( projectGroupId );
+
+        ContinuumProjectBuildingResult result;
+        try
+        {
+            result = continuum.addMavenTwoProject( url, projectGroupId, true, // checkProtocol
+                                                   false, // useCredentialsCache
+                                                   true, // recursiveProjects
+                                                   continuum.getBuildDefinitionService().getDefaultMavenTwoBuildDefinitionTemplate().getId(),
+                                                   checkoutInSingleDirectory );
+        }
+        catch ( BuildDefinitionServiceException e )
+        {
+            throw new ContinuumException( e.getMessage(), e );
+        }
+
+        return populateAddingResult( result );
+    }
+
+    public AddingResult addMavenTwoProjectAsSingleProject( String url, int projectGroupId )
+        throws Exception
+    {
+        checkAddProjectAuthorization( projectGroupId );
+
+        ContinuumProjectBuildingResult result;
+        try
+        {
+            result = continuum.addMavenTwoProject( url, projectGroupId, true, // checkProtocol
+                                                   false, // useCredentialsCache
+                                                   false, // recursiveProjects
+                                                   continuum.getBuildDefinitionService().getDefaultMavenTwoBuildDefinitionTemplate().getId(),
+                                                   true ); // a multi-module project added as a single project is always
+            // checked out
+            // in a single directory, regardless the value set for
+            // checkoutInSingleDirectory
+            // variable
+        }
+        catch ( BuildDefinitionServiceException e )
+        {
+            throw new ContinuumException( e.getMessage(), e );
+        }
+
+        return populateAddingResult( result );
+    }
+
+    private void checkAddProjectAuthorization( int projectGroupId )
+        throws ContinuumException
+    {
+        if ( projectGroupId == -1 )
+        {
+            checkAuthorization( ContinuumRoleConstants.CONTINUUM_ADD_GROUP_OPERATION );
+        }
+        else
+        {
+            checkAuthorization( ContinuumRoleConstants.CONTINUUM_ADD_PROJECT_TO_GROUP_OPERATION, getProjectGroupName(
+                projectGroupId ) );
+        }
+    }
+
+    public AddingResult addMavenTwoProject( String url, int projectGroupId, boolean checkProtocol,
+                                            boolean useCredentialsCache, boolean recursiveProjects,
+                                            boolean checkoutInSingleDirectory )
+        throws Exception
+    {
+        checkAddProjectAuthorization( projectGroupId );
+
+        ContinuumProjectBuildingResult result;
+        try
+        {
+            result = continuum.addMavenTwoProject( url, projectGroupId, checkProtocol, useCredentialsCache,
+                                                   recursiveProjects,
+                                                   continuum.getBuildDefinitionService().getDefaultMavenTwoBuildDefinitionTemplate().getId(),
+                                                   checkoutInSingleDirectory );
+        }
+        catch ( BuildDefinitionServiceException e )
+        {
+            throw new ContinuumException( e.getMessage(), e );
+        }
+
+        return populateAddingResult( result );
+    }
+
     // ----------------------------------------------------------------------
     // Maven 1.x projects
     // ----------------------------------------------------------------------
 
-    public AddingResult addMavenOneProject( String url )
-        throws ContinuumException
-    {
-        checkAddProjectGroupAuthorization();
-
-        ContinuumProjectBuildingResult result = continuum.addMavenOneProject( url );
-        return populateAddingResult( result );
-    }
-
     public AddingResult addMavenOneProject( String url, int projectGroupId )
         throws ContinuumException
     {
-        checkAddProjectToGroupAuthorization( getProjectGroupName( projectGroupId ) );
+        checkAddProjectAuthorization( projectGroupId );
 
         ContinuumProjectBuildingResult result = continuum.addMavenOneProject( url, projectGroupId );
         return populateAddingResult( result );
@@ -757,26 +1045,14 @@
     // Maven ANT projects
     // ----------------------------------------------------------------------
 
-    public ProjectSummary addAntProject( ProjectSummary project )
-        throws ContinuumException
-    {
-        checkAddProjectGroupAuthorization();
-        org.apache.maven.continuum.model.project.Project newProject =
-                        new org.apache.maven.continuum.model.project.Project();
-        int projectId =
-            continuum.addProject( populateProject( project, newProject ), ContinuumBuildExecutorConstants.ANT_BUILD_EXECUTOR );
-        return getProjectSummary( projectId );
-    }
-
     public ProjectSummary addAntProject( ProjectSummary project, int projectGroupId )
         throws ContinuumException
     {
         checkAddProjectGroupAuthorization();
         org.apache.maven.continuum.model.project.Project newProject =
-                        new org.apache.maven.continuum.model.project.Project();
-        int projectId =
-                        continuum.addProject( populateProject( project, newProject ),
-                            ContinuumBuildExecutorConstants.ANT_BUILD_EXECUTOR, projectGroupId );
+            new org.apache.maven.continuum.model.project.Project();
+        int projectId = continuum.addProject( populateProject( project, newProject ),
+                                              ContinuumBuildExecutorConstants.ANT_BUILD_EXECUTOR, projectGroupId );
         return getProjectSummary( projectId );
     }
 
@@ -784,27 +1060,14 @@
     // Maven Shell projects
     // ----------------------------------------------------------------------
 
-    public ProjectSummary addShellProject( ProjectSummary project )
-        throws ContinuumException
-    {
-        checkAddProjectGroupAuthorization();
-        org.apache.maven.continuum.model.project.Project newProject =
-                        new org.apache.maven.continuum.model.project.Project();
-        int projectId =
-                        continuum.addProject( populateProject( project, newProject ),
-                            ContinuumBuildExecutorConstants.SHELL_BUILD_EXECUTOR );
-        return getProjectSummary( projectId );
-    }
-
     public ProjectSummary addShellProject( ProjectSummary project, int projectGroupId )
         throws ContinuumException
     {
         checkAddProjectGroupAuthorization();
         org.apache.maven.continuum.model.project.Project newProject =
-                        new org.apache.maven.continuum.model.project.Project();
-        int projectId =
-                        continuum.addProject( populateProject( project, newProject ),
-                            ContinuumBuildExecutorConstants.SHELL_BUILD_EXECUTOR, projectGroupId );
+            new org.apache.maven.continuum.model.project.Project();
+        int projectId = continuum.addProject( populateProject( project, newProject ),
+                                              ContinuumBuildExecutorConstants.SHELL_BUILD_EXECUTOR, projectGroupId );
         return getProjectSummary( projectId );
     }
 
@@ -843,7 +1106,7 @@
         org.apache.maven.continuum.model.project.Schedule storedSchedule = continuum.getSchedule( schedule.getId() );
         storedSchedule.setActive( newSchedule.isActive() );
         storedSchedule.setName( newSchedule.getName() );
-        storedSchedule.setDescription( newSchedule.getDescription() );
+        storedSchedule.setDescription( StringEscapeUtils.escapeXml( newSchedule.getDescription() ) );
         storedSchedule.setDelay( newSchedule.getDelay() );
         storedSchedule.setCronExpression( newSchedule.getCronExpression() );
         storedSchedule.setMaxJobExecutionTime( newSchedule.getMaxJobExecutionTime() );
@@ -862,16 +1125,6 @@
         return populateSchedule( continuum.getScheduleByName( schedule.getName() ) );
     }
 
-    public int removeSchedule( int scheduleId )
-        throws ContinuumException
-    {
-        checkManageSchedulesAuthorization();
-
-        continuum.removeSchedule( scheduleId );
-
-        return 0;
-    }
-
     // ----------------------------------------------------------------------
     // Profiles
     // ----------------------------------------------------------------------
@@ -898,11 +1151,20 @@
         return populateProfile( continuum.getProfileService().getProfile( profileId ) );
     }
 
+    public Profile getProfileWithName( String profileName )
+        throws ContinuumException
+    {
+        checkManageProfilesAuthorization();
+        org.apache.maven.continuum.model.system.Profile profile = continuum.getProfileService().getProfileWithName(
+            profileName );
+        return profile != null ? populateProfile( profile ) : null;
+    }
+
     public Profile addProfile( Profile profile )
         throws ContinuumException
     {
         org.apache.maven.continuum.model.system.Profile newProfile =
-                        new org.apache.maven.continuum.model.system.Profile();
+            new org.apache.maven.continuum.model.system.Profile();
 
         return populateProfile( continuum.getProfileService().addProfile( populateProfile( profile, newProfile ) ) );
     }
@@ -910,8 +1172,8 @@
     public int updateProfile( Profile profile )
         throws ContinuumException
     {
-        org.apache.maven.continuum.model.system.Profile newProfile =
-                        continuum.getProfileService().getProfile( profile.getId() );
+        org.apache.maven.continuum.model.system.Profile newProfile = continuum.getProfileService().getProfile(
+            profile.getId() );
 
         continuum.getProfileService().updateProfile( populateProfile( profile, newProfile ) );
         return 0;
@@ -951,6 +1213,28 @@
         }
     }
 
+    public List<Installation> getBuildAgentInstallations( String url )
+        throws ContinuumException
+    {
+        try
+        {
+            List<org.apache.maven.continuum.model.system.Installation> buildAgentInstallations =
+                distributedBuildManager.getAvailableInstallations( url );
+
+            List<Installation> convertedBuildAgentInstallations = new ArrayList<Installation>();
+            for ( Object buildAgentInstallation : buildAgentInstallations )
+            {
+                convertedBuildAgentInstallations.add( populateInstallation(
+                    (org.apache.maven.continuum.model.system.Installation) buildAgentInstallation ) );
+            }
+            return convertedBuildAgentInstallations;
+        }
+        catch ( Exception e )
+        {
+            throw new ContinuumException( "Can't load installations", e );
+        }
+    }
+
     public Installation getInstallation( int installationId )
         throws ContinuumException
     {
@@ -967,15 +1251,31 @@
         }
     }
 
+    public Installation getInstallation( String installationName )
+        throws ContinuumException
+    {
+        checkManageInstallationsAuthorization();
+        try
+        {
+            org.apache.maven.continuum.model.system.Installation install =
+                continuum.getInstallationService().getInstallation( installationName );
+            return install != null ? populateInstallation( install ) : null;
+        }
+        catch ( InstallationException e )
+        {
+            throw new ContinuumException( "Can't load installations", e );
+        }
+    }
+
     public Installation addInstallation( Installation installation )
         throws ContinuumException
     {
         try
         {
             org.apache.maven.continuum.model.system.Installation newInstallation =
-                            new org.apache.maven.continuum.model.system.Installation();
-            return populateInstallation( continuum.getInstallationService().add(
-                populateInstallation( installation, newInstallation ) ) );
+                new org.apache.maven.continuum.model.system.Installation();
+            return populateInstallation( continuum.getInstallationService().add( populateInstallation( installation,
+                                                                                                       newInstallation ) ) );
         }
         catch ( InstallationException e )
         {
@@ -989,7 +1289,7 @@
         try
         {
             final org.apache.maven.continuum.model.system.Installation newInst =
-                            continuum.getInstallationService().getInstallation( installation.getInstallationId() );
+                continuum.getInstallationService().getInstallation( installation.getInstallationId() );
             continuum.getInstallationService().update( populateInstallation( installation, newInst ) );
             return 0;
         }
@@ -1005,7 +1305,7 @@
         try
         {
             org.apache.maven.continuum.model.system.Installation installationTODelete =
-                            continuum.getInstallationService().getInstallation( installationId );
+                continuum.getInstallationService().getInstallation( installationId );
             continuum.getInstallationService().delete( installationTODelete );
             return 0;
         }
@@ -1038,16 +1338,105 @@
     // ----------------------------------------------------------------------
     // Queue
     // ----------------------------------------------------------------------
+    public boolean isProjectInPrepareBuildQueue( int projectId )
+        throws ContinuumException
+    {
+        return isProjectInPrepareBuildQueue( projectId, -1 );
+    }
 
-
-    public boolean isProjectInBuildingQueue( int projectId )
+    public boolean isProjectInPrepareBuildQueue( int projectId, int buildDefinitionId )
         throws ContinuumException
     {
         try
         {
-            return taskQueueManager.isInBuildingQueue( projectId );
+            if ( continuum.getConfiguration().isDistributedBuildEnabled() )
+            {
+                return distributedBuildManager.isProjectInAnyPrepareBuildQueue( projectId, buildDefinitionId );
+            }
+            else
+            {
+                return parallelBuildsManager.isInPrepareBuildQueue( projectId );
+            }
         }
-        catch ( TaskQueueManagerException e )
+        catch ( BuildManagerException e )
+        {
+            throw new ContinuumException( e.getMessage(), e );
+        }
+    }
+
+    public boolean isProjectInBuildingQueue( int projectId )
+        throws ContinuumException
+    {
+        return isProjectInBuildingQueue( projectId, -1 );
+    }
+
+    public boolean isProjectInBuildingQueue( int projectId, int buildDefinitionId )
+        throws ContinuumException
+    {
+        try
+        {
+            if ( continuum.getConfiguration().isDistributedBuildEnabled() )
+            {
+                return distributedBuildManager.isProjectInAnyBuildQueue( projectId, buildDefinitionId );
+            }
+            else
+            {
+                return parallelBuildsManager.isInAnyBuildQueue( projectId );
+            }
+        }
+        catch ( BuildManagerException e )
+        {
+            throw new ContinuumException( e.getMessage(), e );
+        }
+    }
+
+    public boolean isProjectCurrentlyPreparingBuild( int projectId )
+        throws ContinuumException
+    {
+        return isProjectCurrentlyPreparingBuild( projectId, -1 );
+    }
+
+    public boolean isProjectCurrentlyPreparingBuild( int projectId, int buildDefinitionId )
+        throws ContinuumException
+    {
+        try
+        {
+            if ( continuum.getConfiguration().isDistributedBuildEnabled() )
+            {
+                return distributedBuildManager.isProjectCurrentlyPreparingBuild( projectId, buildDefinitionId );
+            }
+            else
+            {
+                return parallelBuildsManager.isProjectCurrentlyPreparingBuild( projectId );
+            }
+        }
+        catch ( BuildManagerException e )
+        {
+            throw new ContinuumException( e.getMessage(), e );
+        }
+    }
+
+    public boolean isProjectCurrentlyBuilding( int projectId )
+        throws ContinuumException
+    {
+        return isProjectCurrentlyBuilding( projectId, -1 );
+    }
+
+    public boolean isProjectCurrentlyBuilding( int projectId, int buildDefinitionId )
+        throws ContinuumException
+    {
+        try
+        {
+            if ( continuum.getConfiguration().isDistributedBuildEnabled() )
+            {
+                return distributedBuildManager.isProjectCurrentlyBuilding( projectId, buildDefinitionId );
+            }
+            else
+            {
+                return parallelBuildsManager.isProjectInAnyCurrentBuild( projectId );
+            }
+        }
+        catch ( BuildManagerException e )
         {
             throw new ContinuumException( e.getMessage(), e );
         }
@@ -1058,9 +1447,33 @@
     {
         try
         {
-            return populateBuildProjectTaskList( taskQueueManager.getProjectsInBuildQueue() );
+            Map<String, List<org.apache.continuum.taskqueue.BuildProjectTask>> buildTasks;
+
+            if ( continuum.getConfiguration().isDistributedBuildEnabled() )
+            {
+                buildTasks = distributedBuildManager.getProjectsInBuildQueue();
+            }
+            else
+            {
+                buildTasks = parallelBuildsManager.getProjectsInBuildQueues();
+            }
+
+            Set<String> keys = buildTasks.keySet();
+            List<org.apache.continuum.taskqueue.BuildProjectTask> convertedTasks =
+                new ArrayList<org.apache.continuum.taskqueue.BuildProjectTask>();
+
+            for ( String key : keys )
+            {
+                List<org.apache.continuum.taskqueue.BuildProjectTask> tasks = buildTasks.get( key );
+                for ( org.apache.continuum.taskqueue.BuildProjectTask task : tasks )
+                {
+                    convertedTasks.add( task );
+                }
+            }
+
+            return populateBuildProjectTaskList( convertedTasks );
         }
-        catch ( TaskQueueManagerException e )
+        catch ( BuildManagerException e )
         {
             throw new ContinuumException( e.getMessage(), e );
         }
@@ -1070,14 +1483,9 @@
         throws ContinuumException
     {
         checkManageQueuesAuthorization();
-        try
-        {
-            taskQueueManager.removeProjectsFromBuildingQueue( projectsId );
-        }
-        catch ( TaskQueueManagerException e )
-        {
-            throw new ContinuumException( e.getMessage(), e );
-        }
+
+        parallelBuildsManager.removeProjectsFromBuildQueue( projectsId );
+
         return 0;
     }
 
@@ -1087,9 +1495,110 @@
         checkManageQueuesAuthorization();
         try
         {
-            return taskQueueManager.cancelCurrentBuild();
+            return parallelBuildsManager.cancelAllBuilds();
         }
-        catch ( TaskQueueManagerException e )
+        catch ( BuildManagerException e )
+        {
+            throw new ContinuumException( e.getMessage(), e );
+        }
+    }
+
+    public boolean cancelBuild( int projectId, int buildDefinitionId )
+        throws ContinuumException
+    {
+        checkManageQueuesAuthorization();
+        try
+        {
+            if ( continuum.getConfiguration().isDistributedBuildEnabled() )
+            {
+                DistributedBuildManager dbm = continuum.getDistributedBuildManager();
+
+                String buildAgentUrl = dbm.getBuildAgentUrl( projectId, buildDefinitionId );
+
+                if ( dbm.isProjectInAnyPrepareBuildQueue( projectId, buildDefinitionId ) )
+                {
+                    if ( buildAgentUrl != null )
+                    {
+                        org.apache.continuum.model.project.ProjectScmRoot scmRoot =
+                            continuum.getProjectScmRootByProject( projectId );
+                        dbm.removeFromPrepareBuildQueue( buildAgentUrl, scmRoot.getProjectGroup().getId(),
+                                                         scmRoot.getId() );
+                    }
+                }
+                // wait if already preparing
+                else if ( dbm.isProjectCurrentlyPreparingBuild( projectId, buildDefinitionId ) )
+                {
+                    while ( dbm.isProjectCurrentlyPreparingBuild( projectId, buildDefinitionId ) )
+                    {
+                        try
+                        {
+                            Thread.sleep( 1000 );
+                        }
+                        catch ( InterruptedException e )
+                        {
+                            // do nothing
+                        }
+                    }
+                }
+
+                if ( dbm.isProjectInAnyBuildQueue( projectId, buildDefinitionId ) )
+                {
+                    dbm.removeFromBuildQueue( buildAgentUrl, projectId, buildDefinitionId );
+                }
+                else if ( dbm.isProjectCurrentlyBuilding( projectId, buildDefinitionId ) )
+                {
+                    if ( buildAgentUrl != null )
+                    {
+                        dbm.cancelDistributedBuild( buildAgentUrl );
+                    }
+                }
+
+                return true;
+            }
+            else
+            {
+                // if currently preparing build or being checked out, wait until done
+                if ( parallelBuildsManager.isProjectCurrentlyPreparingBuild( projectId ) ||
+                    parallelBuildsManager.isProjectCurrentlyBeingCheckedOut( projectId ) )
+                {
+                    while ( parallelBuildsManager.isProjectCurrentlyPreparingBuild( projectId ) ||
+                        parallelBuildsManager.isProjectCurrentlyBeingCheckedOut( projectId ) )
+                    {
+                        try
+                        {
+                            Thread.sleep( 1000 );
+                        }
+                        catch ( InterruptedException e )
+                        {
+                            // do nothing
+                        }
+                    }
+                }
+
+                if ( parallelBuildsManager.isInPrepareBuildQueue( projectId ) )
+                {
+                    org.apache.continuum.model.project.ProjectScmRoot scmRoot = continuum.getProjectScmRootByProject(
+                        projectId );
+                    parallelBuildsManager.removeProjectFromPrepareBuildQueue( scmRoot.getProjectGroup().getId(),
+                                                                              scmRoot.getId() );
+                }
+                else if ( parallelBuildsManager.isInAnyCheckoutQueue( projectId ) )
+                {
+                    parallelBuildsManager.removeProjectFromCheckoutQueue( projectId );
+                }
+                else if ( parallelBuildsManager.isInAnyBuildQueue( projectId ) )
+                {
+                    parallelBuildsManager.removeProjectFromBuildQueue( projectId );
+                }
+                else if ( parallelBuildsManager.isProjectInAnyCurrentBuild( projectId ) )
+                {
+                    return parallelBuildsManager.cancelBuild( projectId );
+                }
+
+                return true;
+            }
+        }
+        catch ( BuildManagerException e )
         {
             throw new ContinuumException( e.getMessage(), e );
         }
@@ -1102,7 +1611,8 @@
     public ContinuumReleaseResult getReleaseResult( int releaseId )
         throws ContinuumException
     {
-        org.apache.continuum.model.release.ContinuumReleaseResult releaseResult = continuum.getContinuumReleaseResult( releaseId );
+        org.apache.continuum.model.release.ContinuumReleaseResult releaseResult = continuum.getContinuumReleaseResult(
+            releaseId );
         checkViewProjectGroupAuthorization( getProjectGroupName( releaseResult.getProjectGroup().getId() ) );
         return populateReleaseResult( releaseResult );
     }
@@ -1112,7 +1622,7 @@
     {
         checkViewProjectGroupAuthorization( getProjectGroupName( projectGroupId ) );
         Collection releaseResults = continuum.getContinuumReleaseResultsByProjectGroup( projectGroupId );
-        
+
         List<ContinuumReleaseResult> r = new ArrayList<ContinuumReleaseResult>();
         for ( Object releaseResult : releaseResults )
         {
@@ -1132,7 +1642,8 @@
     public String getReleaseOutput( int releaseId )
         throws ContinuumException
     {
-        org.apache.continuum.model.release.ContinuumReleaseResult releaseResult = continuum.getContinuumReleaseResult( releaseId );
+        org.apache.continuum.model.release.ContinuumReleaseResult releaseResult = continuum.getContinuumReleaseResult(
+            releaseId );
         checkViewProjectGroupAuthorization( getProjectGroupName( releaseResult.getProjectGroup().getId() ) );
 
         return continuum.getReleaseOutput( releaseId );
@@ -1146,13 +1657,15 @@
         throws ContinuumException
     {
         checkManagePurgingAuthorization();
-        
+
         try
         {
-            org.apache.continuum.model.repository.RepositoryPurgeConfiguration newPurge = 
+            org.apache.continuum.model.repository.RepositoryPurgeConfiguration newPurge =
                 new org.apache.continuum.model.repository.RepositoryPurgeConfiguration();
-            return populateRepositoryPurgeConfiguration( continuum.getPurgeConfigurationService().
-                                                         addRepositoryPurgeConfiguration( populateRepositoryPurgeConfiguration( repoPurge, newPurge ) ) );
+            return populateRepositoryPurgeConfiguration(
+                continuum.getPurgeConfigurationService().addRepositoryPurgeConfiguration(
+                    populateRepositoryPurgeConfiguration( repoPurge, newPurge ) )
+            );
         }
         catch ( RepositoryServiceException e )
         {
@@ -1168,12 +1681,13 @@
         throws ContinuumException
     {
         checkManagePurgingAuthorization();
-        
+
         try
         {
-            org.apache.continuum.model.repository.RepositoryPurgeConfiguration purge = 
+            org.apache.continuum.model.repository.RepositoryPurgeConfiguration purge =
                 new org.apache.continuum.model.repository.RepositoryPurgeConfiguration();
-            continuum.getPurgeConfigurationService().updateRepositoryPurgeConfiguration( populateRepositoryPurgeConfiguration( repoPurge, purge ) );
+            continuum.getPurgeConfigurationService().updateRepositoryPurgeConfiguration(
+                populateRepositoryPurgeConfiguration( repoPurge, purge ) );
             return 0;
         }
         catch ( RepositoryServiceException e )
@@ -1193,7 +1707,7 @@
 
         try
         {
-            org.apache.continuum.model.repository.RepositoryPurgeConfiguration repoPurge = 
+            org.apache.continuum.model.repository.RepositoryPurgeConfiguration repoPurge =
                 continuum.getPurgeConfigurationService().getRepositoryPurgeConfiguration( repoPurgeId );
             continuum.getPurgeConfigurationService().removeRepositoryPurgeConfiguration( repoPurge );
             return 0;
@@ -1211,7 +1725,7 @@
 
         try
         {
-            org.apache.continuum.model.repository.RepositoryPurgeConfiguration repoPurgeConfig = 
+            org.apache.continuum.model.repository.RepositoryPurgeConfiguration repoPurgeConfig =
                 continuum.getPurgeConfigurationService().getRepositoryPurgeConfiguration( repoPurgeId );
             return populateRepositoryPurgeConfiguration( repoPurgeConfig );
         }
@@ -1226,11 +1740,12 @@
     {
         checkManagePurgingAuthorization();
         Collection repoPurgeConfigs = continuum.getPurgeConfigurationService().getAllRepositoryPurgeConfigurations();
-        
+
         List<RepositoryPurgeConfiguration> r = new ArrayList<RepositoryPurgeConfiguration>();
         for ( Object repoPurgeConfig : repoPurgeConfigs )
         {
-            r.add( populateRepositoryPurgeConfiguration( ( org.apache.continuum.model.repository.RepositoryPurgeConfiguration ) repoPurgeConfig ) );
+            r.add( populateRepositoryPurgeConfiguration(
+                (org.apache.continuum.model.repository.RepositoryPurgeConfiguration) repoPurgeConfig ) );
         }
         return r;
     }
@@ -1244,8 +1759,10 @@
         {
             org.apache.continuum.model.repository.DirectoryPurgeConfiguration newPurge =
                 new org.apache.continuum.model.repository.DirectoryPurgeConfiguration();
-            return populateDirectoryPurgeConfiguration( continuum.getPurgeConfigurationService().
-                                                        addDirectoryPurgeConfiguration( populateDirectoryPurgeConfiguration( dirPurge, newPurge ) ) );
+            return populateDirectoryPurgeConfiguration(
+                continuum.getPurgeConfigurationService().addDirectoryPurgeConfiguration(
+                    populateDirectoryPurgeConfiguration( dirPurge, newPurge ) )
+            );
         }
         catch ( RepositoryServiceException e )
         {
@@ -1266,7 +1783,8 @@
         {
             org.apache.continuum.model.repository.DirectoryPurgeConfiguration purge =
                 new org.apache.continuum.model.repository.DirectoryPurgeConfiguration();
-            continuum.getPurgeConfigurationService().updateDirectoryPurgeConfiguration( populateDirectoryPurgeConfiguration( dirPurge, purge ) );
+            continuum.getPurgeConfigurationService().updateDirectoryPurgeConfiguration(
+                populateDirectoryPurgeConfiguration( dirPurge, purge ) );
             return 0;
         }
         catch ( RepositoryServiceException e )
@@ -1283,7 +1801,7 @@
         throws ContinuumException
     {
         checkManagePurgingAuthorization();
-        
+
         try
         {
             org.apache.continuum.model.repository.DirectoryPurgeConfiguration dirPurge =
@@ -1304,7 +1822,8 @@
 
         try
         {
-            org.apache.continuum.model.repository.DirectoryPurgeConfiguration dirPurgeConfig = continuum.getPurgeConfigurationService().getDirectoryPurgeConfiguration( dirPurgeId );
+            org.apache.continuum.model.repository.DirectoryPurgeConfiguration dirPurgeConfig =
+                continuum.getPurgeConfigurationService().getDirectoryPurgeConfiguration( dirPurgeId );
             return populateDirectoryPurgeConfiguration( dirPurgeConfig );
         }
         catch ( PurgeConfigurationServiceException e )
@@ -1322,20 +1841,24 @@
         List<DirectoryPurgeConfiguration> d = new ArrayList<DirectoryPurgeConfiguration>();
         for ( Object dirPurgeConfig : dirPurgeConfigs )
         {
-            d.add( populateDirectoryPurgeConfiguration( ( org.apache.continuum.model.repository.DirectoryPurgeConfiguration ) dirPurgeConfig ) );
+            d.add( populateDirectoryPurgeConfiguration(
+                (org.apache.continuum.model.repository.DirectoryPurgeConfiguration) dirPurgeConfig ) );
         }
         return d;
     }
-    
-    public void purgeLocalRepository( int repoPurgeId )
+
+    public int purgeLocalRepository( int repoPurgeId )
         throws ContinuumException
     {
         checkManagePurgingAuthorization();
 
         try
         {
-            org.apache.continuum.model.repository.RepositoryPurgeConfiguration repoPurgeConfig = continuum.getPurgeConfigurationService().getRepositoryPurgeConfiguration( repoPurgeId );
+            org.apache.continuum.model.repository.RepositoryPurgeConfiguration repoPurgeConfig =
+                continuum.getPurgeConfigurationService().getRepositoryPurgeConfiguration( repoPurgeId );
             continuum.getPurgeManager().purgeRepository( repoPurgeConfig );
+
+            return 0;
         }
         catch ( PurgeConfigurationServiceException e )
         {
@@ -1347,15 +1870,18 @@
         }
     }
 
-    public void purgeDirectory( int dirPurgeId )
+    public int purgeDirectory( int dirPurgeId )
         throws ContinuumException
     {
         checkManagePurgingAuthorization();
 
         try
         {
-            org.apache.continuum.model.repository.DirectoryPurgeConfiguration dirPurgeConfig = continuum.getPurgeConfigurationService().getDirectoryPurgeConfiguration( dirPurgeId );
+            org.apache.continuum.model.repository.DirectoryPurgeConfiguration dirPurgeConfig =
+                continuum.getPurgeConfigurationService().getDirectoryPurgeConfiguration( dirPurgeId );
             continuum.getPurgeManager().purgeDirectory( dirPurgeConfig );
+
+            return 0;
         }
         catch ( PurgeConfigurationServiceException e )
         {
@@ -1379,9 +1905,9 @@
         try
         {
             org.apache.continuum.model.repository.LocalRepository newRepository =
-                        new org.apache.continuum.model.repository.LocalRepository();
+                new org.apache.continuum.model.repository.LocalRepository();
             return populateLocalRepository( continuum.getRepositoryService().addLocalRepository(
-                                           populateLocalRepository( repository, newRepository ) ) );
+                populateLocalRepository( repository, newRepository ) ) );
         }
         catch ( RepositoryServiceException e )
         {
@@ -1397,7 +1923,7 @@
         try
         {
             final org.apache.continuum.model.repository.LocalRepository newRepo =
-                            continuum.getRepositoryService().getLocalRepository( repository.getId() );
+                continuum.getRepositoryService().getLocalRepository( repository.getId() );
             continuum.getRepositoryService().updateLocalRepository( populateLocalRepository( repository, newRepo ) );
             return 0;
         }
@@ -1417,7 +1943,7 @@
             continuum.getRepositoryService().removeLocalRepository( repositoryId );
             return 0;
         }
-        catch ( RepositoryServiceException e)
+        catch ( RepositoryServiceException e )
         {
             throw new ContinuumException( "Can't delete repository", e );
         }
@@ -1427,14 +1953,14 @@
         throws ContinuumException
     {
         checkManageRepositoriesAuthorization();
-        
+
         try
         {
             return populateLocalRepository( continuum.getRepositoryService().getLocalRepository( repositoryId ) );
         }
         catch ( RepositoryServiceException e )
         {
-            throw new ContinuumException( "Error while retrieving repository.", e);
+            throw new ContinuumException( "Error while retrieving repository.", e );
         }
     }
 
@@ -1453,6 +1979,269 @@
     }
 
     // ----------------------------------------------------------------------
+    // Build agent
+    // ----------------------------------------------------------------------
+
+    public BuildAgentConfiguration addBuildAgent( BuildAgentConfiguration buildAgentConfiguration )
+        throws ConfigurationException, ConfigurationStoringException, ContinuumConfigurationException
+    {
+        ConfigurationService configurationService = continuum.getConfiguration();
+
+        if ( buildAgentConfiguration == null )
+        {
+            return null;
+        }
+        try
+        {
+            configurationService.addBuildAgent( populateBuildAgent( buildAgentConfiguration ) );
+            configurationService.store();
+            return populateBuildAgent( configurationService.getBuildAgent( buildAgentConfiguration.getUrl() ) );
+        }
+        catch ( ContinuumException e )
+        {
+            throw new ConfigurationException( "Error in adding buildAgent", e );
+        }
+    }
+
+    public BuildAgentConfiguration getBuildAgent( String url )
+    {
+        ConfigurationService configurationService = continuum.getConfiguration();
+        org.apache.continuum.configuration.BuildAgentConfiguration buildAgent = configurationService.getBuildAgent(
+            url );
+        return buildAgent != null ? populateBuildAgent( buildAgent ) : null;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @throws ContinuumException distributed build is not enabled or error during retrieval of build agent url
+     * @see DistributedBuildManager#getBuildAgentUrl(int, int)
+     */
+    public String getBuildAgentUrl( int projectId, int buildDefinitionId )
+        throws ContinuumException
+    {
+        if ( !continuum.getConfiguration().isDistributedBuildEnabled() )
+        {
+            throw new ContinuumException( "Method available only in distributed build mode." );
+        }
+
+        return distributedBuildManager.getBuildAgentUrl( projectId, buildDefinitionId );
+    }
+
+    public BuildAgentConfiguration updateBuildAgent( BuildAgentConfiguration buildAgentConfiguration )
+        throws ConfigurationStoringException, ContinuumConfigurationException
+    {
+        try
+        {
+            ConfigurationService configurationService = continuum.getConfiguration();
+            org.apache.continuum.configuration.BuildAgentConfiguration buildAgent = configurationService.getBuildAgent(
+                buildAgentConfiguration.getUrl() );
+            BuildAgentConfiguration buildAgentConfigurationToUpdate = buildAgent != null ? populateBuildAgent(
+                buildAgent ) : null;
+
+            if ( buildAgentConfigurationToUpdate != null )
+            {
+                buildAgentConfigurationToUpdate.setDescription( StringEscapeUtils.escapeXml(
+                    buildAgentConfiguration.getDescription() ) );
+                buildAgentConfigurationToUpdate.setEnabled( buildAgentConfiguration.isEnabled() );
+                configurationService.updateBuildAgent( populateBuildAgent( buildAgentConfigurationToUpdate ) );
+                configurationService.store();
+                return populateBuildAgent( configurationService.getBuildAgent( buildAgentConfiguration.getUrl() ) );
+            }
+            else
+            {
+                return null;
+            }
+        }
+        catch ( ContinuumException e )
+        {
+            throw new ContinuumConfigurationException( "Error in adding buildAgent", e );
+        }
+    }
+
+    public boolean removeBuildAgent( String url )
+        throws BuildAgentConfigurationException, ConfigurationStoringException, ContinuumConfigurationException,
+        ContinuumException
+    {
+        ConfigurationService configurationService = continuum.getConfiguration();
+
+        boolean SUCCESS;
+        org.apache.continuum.configuration.BuildAgentConfiguration buildAgent = configurationService.getBuildAgent(
+            url );
+        BuildAgentConfiguration buildAgentConfiguration = buildAgent != null ? populateBuildAgent( buildAgent ) : null;
+        if ( buildAgentConfiguration != null )
+        {
+            if ( continuum.getDistributedBuildManager().isBuildAgentBusy( buildAgentConfiguration.getUrl() ) )
+            {
+                throw new BuildAgentConfigurationException(
+                    "Cannot delete build agent because it's busy at the moment" );
+            }
+
+            if ( configurationService.getBuildAgentGroups() != null )
+            {
+                for ( org.apache.continuum.configuration.BuildAgentGroupConfiguration buildAgentGroup : configurationService.getBuildAgentGroups() )
+                {
+                    if ( configurationService.containsBuildAgentUrl( buildAgentConfiguration.getUrl(),
+                                                                     buildAgentGroup ) )
+                    {
+                        throw new BuildAgentConfigurationException(
+                            "Cannot delete build agent because it's in use at the moment" );
+                    }
+                }
+            }
+
+            try
+            {
+                continuum.getDistributedBuildManager().removeDistributedBuildQueueOfAgent(
+                    buildAgentConfiguration.getUrl() );
+                configurationService.removeBuildAgent( populateBuildAgent( buildAgentConfiguration ) );
+                configurationService.store();
+                SUCCESS = true;
+            }
+            catch ( ContinuumException e )
+            {
+                throw new ContinuumException( "Error when removing build agent in build queue", e );
+            }
+
+        }
+        else
+        {
+            throw new BuildAgentConfigurationException( "Build agent does not exist." );
+        }
+
+        return SUCCESS;
+    }
+
+    public List<BuildAgentConfiguration> getAllBuildAgents()
+    {
+        ConfigurationService configurationService = continuum.getConfiguration();
+
+        List<org.apache.continuum.configuration.BuildAgentConfiguration> buildAgents =
+            configurationService.getBuildAgents();
+        List<BuildAgentConfiguration> buildAgentConfigurations = new ArrayList<BuildAgentConfiguration>();
+
+        if ( buildAgents != null )
+        {
+            for ( org.apache.continuum.configuration.BuildAgentConfiguration buildAgent : buildAgents )
+            {
+                buildAgentConfigurations.add( populateBuildAgent( buildAgent ) );
+            }
+        }
+        return buildAgentConfigurations;
+    }
+
+    public List<BuildAgentConfiguration> getBuildAgentsWithInstallations()
+        throws Exception
+    {
+        ConfigurationService configurationService = continuum.getConfiguration();
+
+        List<org.apache.continuum.configuration.BuildAgentConfiguration> buildAgents =
+            configurationService.getBuildAgents();
+        List<BuildAgentConfiguration> buildAgentConfigurations = new ArrayList<BuildAgentConfiguration>();
+
+        if ( buildAgents != null )
+        {
+            for ( org.apache.continuum.configuration.BuildAgentConfiguration buildAgent : buildAgents )
+            {
+                if ( buildAgent.isEnabled() )
+                {
+                    BuildAgentConfiguration agent = populateBuildAgent( buildAgent );
+                    agent.setInstallations( getBuildAgentInstallations( buildAgent.getUrl() ) );
+                    buildAgentConfigurations.add( agent );
+                }
+            }
+        }
+        return buildAgentConfigurations;
+    }
+
+    // ----------------------------------------------------------------------
+    // Build agent group
+    // ----------------------------------------------------------------------
+
+    public BuildAgentGroupConfiguration addBuildAgentGroup( BuildAgentGroupConfiguration buildAgentGroup )
+        throws ConfigurationException, ConfigurationStoringException, ContinuumConfigurationException
+    {
+        ConfigurationService configurationService = continuum.getConfiguration();
+
+        if ( buildAgentGroup == null )
+        {
+            return null;
+        }
+        try
+        {
+            configurationService.addBuildAgentGroup( populateBuildAgentGroup( buildAgentGroup ) );
+            configurationService.store();
+            return populateBuildAgentGroup( configurationService.getBuildAgentGroup( buildAgentGroup.getName() ) );
+        }
+        catch ( ContinuumException e )
+        {
+            throw new ConfigurationException( "Error in adding buildAgentGroup", e );
+        }
+    }
+
+    public BuildAgentGroupConfiguration getBuildAgentGroup( String name )
+    {
+        ConfigurationService configurationService = continuum.getConfiguration();
+        org.apache.continuum.configuration.BuildAgentGroupConfiguration buildAgentGroup =
+            configurationService.getBuildAgentGroup( name );
+        return buildAgentGroup != null ? populateBuildAgentGroup( buildAgentGroup ) : null;
+    }
+
+    public BuildAgentGroupConfiguration updateBuildAgentGroup( BuildAgentGroupConfiguration buildAgentGroup )
+        throws ConfigurationException, ConfigurationStoringException, ContinuumConfigurationException
+    {
+        try
+        {
+            ConfigurationService configurationService = continuum.getConfiguration();
+            org.apache.continuum.configuration.BuildAgentGroupConfiguration buildAgentGroupConfiguration =
+                configurationService.getBuildAgentGroup( buildAgentGroup.getName() );
+
+            if ( buildAgentGroupConfiguration != null )
+            {
+                buildAgentGroupConfiguration.setName( StringEscapeUtils.escapeXml( buildAgentGroup.getName() ) );
+                if ( buildAgentGroup.getBuildAgents() != null )
+                {
+                    buildAgentGroupConfiguration.getBuildAgents().clear();
+                    for ( BuildAgentConfiguration buildAgent : buildAgentGroup.getBuildAgents() )
+                    {
+                        buildAgentGroupConfiguration.getBuildAgents().add( populateBuildAgent( buildAgent ) );
+                    }
+                }
+                else
+                {
+                    buildAgentGroupConfiguration.setBuildAgents( null );
+                }
+                configurationService.updateBuildAgentGroup( buildAgentGroupConfiguration );
+                configurationService.store();
+                return populateBuildAgentGroup( configurationService.getBuildAgentGroup( buildAgentGroup.getName() ) );
+            }
+            else
+            {
+                return null;
+            }
+        }
+        catch ( ContinuumException e )
+        {
+            throw new ContinuumConfigurationException(
+                "Error in updating build agent group " + buildAgentGroup.getName(), e );
+        }
+    }
+
+    public int removeBuildAgentGroup( String name )
+        throws ConfigurationException
+    {
+        ConfigurationService configurationService = continuum.getConfiguration();
+        org.apache.continuum.configuration.BuildAgentGroupConfiguration buildAgentGroupConfiguration =
+            configurationService.getBuildAgentGroup( name );
+        if ( buildAgentGroupConfiguration != null )
+        {
+            configurationService.removeBuildAgentGroup( buildAgentGroupConfiguration );
+        }
+
+        return 0;
+    }
+
+    // ----------------------------------------------------------------------
     // Converters
     // ----------------------------------------------------------------------
 
@@ -1478,6 +2267,11 @@
         return (Project) mapper.map( project, Project.class );
     }
 
+    private ProjectScmRoot populateProjectScmRoot( org.apache.continuum.model.project.ProjectScmRoot projectScmRoot )
+    {
+        return (ProjectScmRoot) mapper.map( projectScmRoot, ProjectScmRoot.class );
+    }
+
     private org.apache.maven.continuum.model.project.Project populateProject( ProjectSummary projectSummary,
                                                                               org.apache.maven.continuum.model.project.Project project )
         throws ContinuumException
@@ -1486,9 +2280,65 @@
         {
             return null;
         }
+
+        // validate
+        if ( StringUtils.isNotBlank( projectSummary.getArtifactId() ) && !projectSummary.getArtifactId().matches(
+            PROJECT_ARTIFACT_ID_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Project Artifact Id contains invalid characters" );
+        }
+
+        if ( StringUtils.isNotBlank( projectSummary.getExecutorId() ) && !projectSummary.getExecutorId().matches(
+            PROJECT_EXECUTOR_OR_BUILDDEF_TYPE_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Project Executor Id can only be 'maven2, maven-1, ant or shell'" );
+        }
+
+        if ( StringUtils.isNotBlank( projectSummary.getGroupId() ) && !projectSummary.getGroupId().matches(
+            PROJECTGROUP_ID_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Project Group Id contains invalid characters" );
+        }
+
+        if ( StringUtils.isNotBlank( projectSummary.getName() ) && !projectSummary.getName().matches(
+            NAME_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Project Name contains invalid characters" );
+        }
+
+        if ( StringUtils.isNotBlank( projectSummary.getScmTag() ) && !projectSummary.getScmTag().matches(
+            PROJECT_SCM_TAG_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Project Scm Tag contains invalid characters" );
+        }
+
+        if ( StringUtils.isNotBlank( projectSummary.getScmUrl() ) && !projectSummary.getScmUrl().matches(
+            PROJECT_SCM_URL_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Project Scm Url contains invalid characters" );
+        }
+
+        if ( StringUtils.isNotBlank( projectSummary.getUrl() ) && !projectSummary.getUrl().matches(
+            URL_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Project Url contains invalid characters" );
+        }
+
+        if ( StringUtils.isNotBlank( projectSummary.getVersion() ) && !projectSummary.getVersion().matches(
+            PROJECT_VERSION_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Project Version contains invalid characters" );
+        }
+
+        if ( StringUtils.isNotBlank( projectSummary.getWorkingDirectory() ) &&
+            !projectSummary.getWorkingDirectory().matches( DIRECTORY_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Project Working Directory contains invalid characters" );
+        }
+
         project.setArtifactId( projectSummary.getArtifactId() );
         project.setBuildNumber( projectSummary.getBuildNumber() );
-        project.setDescription( projectSummary.getDescription() );
+        project.setDescription( StringEscapeUtils.escapeXml( projectSummary.getDescription() ) );
         project.setExecutorId( projectSummary.getExecutorId() );
         project.setGroupId( projectSummary.getGroupId() );
         project.setId( projectSummary.getId() );
@@ -1496,8 +2346,8 @@
         project.setName( projectSummary.getName() );
         if ( projectSummary.getProjectGroup() != null )
         {
-            org.apache.maven.continuum.model.project.ProjectGroup g =
-                            continuum.getProjectGroup( projectSummary.getProjectGroup().getId() );
+            org.apache.maven.continuum.model.project.ProjectGroup g = continuum.getProjectGroup(
+                projectSummary.getProjectGroup().getId() );
             project.setProjectGroup( populateProjectGroupSummary( projectSummary.getProjectGroup(), g ) );
         }
         else
@@ -1520,20 +2370,33 @@
         return (ProjectNotifier) mapper.map( notifier, ProjectNotifier.class );
     }
 
-    private ProjectGroupSummary populateProjectGroupSummary( org.apache.maven.continuum.model.project.ProjectGroup group )
+    private ProjectGroupSummary populateProjectGroupSummary(
+        org.apache.maven.continuum.model.project.ProjectGroup group )
     {
         return (ProjectGroupSummary) mapper.map( group, ProjectGroupSummary.class );
     }
 
-    private org.apache.maven.continuum.model.project.ProjectGroup populateProjectGroupSummary( ProjectGroupSummary group,
-                                                                                               org.apache.maven.continuum.model.project.ProjectGroup g )
+    private org.apache.maven.continuum.model.project.ProjectGroup populateProjectGroupSummary(
+        ProjectGroupSummary group, org.apache.maven.continuum.model.project.ProjectGroup g )
+        throws ContinuumException
     {
         if ( group == null )
         {
             return null;
         }
 
-        g.setDescription( group.getDescription() );
+        if ( StringUtils.isNotBlank( group.getGroupId() ) && !group.getGroupId().matches(
+            PROJECTGROUP_ID_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "ProjectGroup Id contains invalid characters" );
+        }
+
+        if ( StringUtils.isNotBlank( group.getName() ) && !group.getName().matches( NAME_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "ProjectGroup Name contains invalid characters" );
+        }
+
+        g.setDescription( StringEscapeUtils.escapeXml( group.getDescription() ) );
         g.setGroupId( group.getGroupId() );
         g.setId( group.getId() );
         g.setName( group.getName() );
@@ -1543,12 +2406,14 @@
         return g;
     }
 
-    private ProjectGroup populateProjectGroupWithAllDetails( org.apache.maven.continuum.model.project.ProjectGroup group )
+    private ProjectGroup populateProjectGroupWithAllDetails(
+        org.apache.maven.continuum.model.project.ProjectGroup group )
     {
         return (ProjectGroup) mapper.map( group, ProjectGroup.class );
     }
 
-    private BuildResultSummary populateBuildResultSummary( org.apache.maven.continuum.model.project.BuildResult buildResult )
+    private BuildResultSummary populateBuildResultSummary(
+        org.apache.maven.continuum.model.project.BuildResult buildResult )
     {
         return (BuildResultSummary) mapper.map( buildResult, BuildResultSummary.class );
     }
@@ -1569,29 +2434,31 @@
 
         if ( result.hasErrors() )
         {
-            for ( Iterator i = result.getErrors().iterator(); i.hasNext(); )
+            if ( StringUtils.isNotBlank( result.getErrorsAsString() ) )
             {
-                String error = (String) i.next();
-                res.addError( error );
+                res.addError( result.getErrorsAsString() );
+            }
+            else
+            {
+                for ( String error : result.getErrors() )
+                {
+                    res.addError( AddingResultUtil.getErrorMessage( error ) );
+                }
             }
         }
 
         if ( result.getProjects() != null )
         {
-            for ( Iterator i = result.getProjects().iterator(); i.hasNext(); )
+            for ( org.apache.maven.continuum.model.project.Project project : result.getProjects() )
             {
-                org.apache.maven.continuum.model.project.Project project =
-                    (org.apache.maven.continuum.model.project.Project) i.next();
                 res.addProject( populateProjectSummary( project ) );
             }
         }
 
         if ( result.getProjectGroups() != null )
         {
-            for ( Iterator i = result.getProjectGroups().iterator(); i.hasNext(); )
+            for ( org.apache.maven.continuum.model.project.ProjectGroup projectGroup : result.getProjectGroups() )
             {
-                org.apache.maven.continuum.model.project.ProjectGroup projectGroup =
-                    (org.apache.maven.continuum.model.project.ProjectGroup) i.next();
                 res.addProjectGroup( populateProjectGroupSummary( projectGroup ) );
             }
         }
@@ -1604,15 +2471,39 @@
         return (BuildDefinition) mapper.map( buildDef, BuildDefinition.class );
     }
 
-    private org.apache.maven.continuum.model.project.BuildDefinition populateBuildDefinition( BuildDefinition buildDef,
-                                                                                              org.apache.maven.continuum.model.project.BuildDefinition bd )
-        throws ProfileException, ContinuumException
+    protected org.apache.maven.continuum.model.project.BuildDefinition populateBuildDefinition(
+        BuildDefinition buildDef, org.apache.maven.continuum.model.project.BuildDefinition bd )
+        throws ContinuumException
     {
         if ( buildDef == null )
         {
             return null;
         }
 
+        if ( StringUtils.isNotBlank( buildDef.getArguments() ) && !buildDef.getArguments().matches(
+            BUILD_DEFINITION_ARGUMENTS_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Build Definition Arguments contain invalid characters" );
+        }
+
+        if ( StringUtils.isNotBlank( buildDef.getBuildFile() ) && !buildDef.getBuildFile().matches(
+            BUILD_DEFINITION_BUILD_FILE_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Build Definition Build File contains invalid characters" );
+        }
+
+        if ( StringUtils.isNotBlank( buildDef.getGoals() ) && !buildDef.getGoals().matches(
+            BUILD_DEFINITION_GOALS_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Build Definition Goals contain invalid characters" );
+        }
+
+        if ( StringUtils.isNotBlank( buildDef.getType() ) && !buildDef.getType().matches(
+            PROJECT_EXECUTOR_OR_BUILDDEF_TYPE_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Build Definition Type can only be 'maven2, maven-1, ant, or shell'" );
+        }
+
         bd.setArguments( buildDef.getArguments() );
         bd.setBuildFile( buildDef.getBuildFile() );
         bd.setType( buildDef.getType() );
@@ -1632,34 +2523,59 @@
         }
         if ( buildDef.getSchedule() != null )
         {
-            bd.setSchedule( populateSchedule( buildDef.getSchedule(), continuum.getSchedule( buildDef.getSchedule()
-                            .getId() ) ) );
+            bd.setSchedule( populateSchedule( buildDef.getSchedule(), continuum.getSchedule(
+                buildDef.getSchedule().getId() ) ) );
         }
         else
         {
             bd.setSchedule( null );
         }
 
+        if ( StringUtils.isNotEmpty( buildDef.getDescription() ) )
+        {
+            bd.setDescription( StringEscapeUtils.escapeXml( buildDef.getDescription() ) );
+        }
+
         return bd;
     }
 
-    private BuildDefinitionTemplate populateBuildDefinitionTemplate( org.apache.maven.continuum.model.project.BuildDefinitionTemplate bdt )
+    protected void buildProjectWithBuildDefinition( int projectId, int buildDefinitionId,
+                                                    org.apache.continuum.utils.build.BuildTrigger buildTrigger )
+        throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException
+    {
+        continuum.buildProjectWithBuildDefinition( projectId, buildDefinitionId, buildTrigger );
+    }
+
+    private BuildDefinitionTemplate populateBuildDefinitionTemplate(
+        org.apache.maven.continuum.model.project.BuildDefinitionTemplate bdt )
     {
         return (BuildDefinitionTemplate) mapper.map( bdt, BuildDefinitionTemplate.class );
     }
 
     private org.apache.maven.continuum.model.project.Schedule populateSchedule( Schedule schedule,
                                                                                 org.apache.maven.continuum.model.project.Schedule s )
+        throws ContinuumException
     {
         if ( schedule == null )
         {
             return null;
         }
 
+        if ( StringUtils.isNotBlank( schedule.getCronExpression() ) && !schedule.getCronExpression().matches(
+            SCHEDULE_CRON_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Schedule Cron Expression contains invalid characters" );
+        }
+
+        if ( StringUtils.isNotBlank( schedule.getName() ) && !schedule.getName().matches( NAME_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Schedule Name contains invalid characters" );
+        }
+
         s.setActive( schedule.isActive() );
         s.setCronExpression( schedule.getCronExpression() );
         s.setDelay( schedule.getDelay() );
-        s.setDescription( schedule.getDescription() );
+        s.setDescription( StringEscapeUtils.escapeXml( schedule.getDescription() ) );
         s.setId( schedule.getId() );
         s.setMaxJobExecutionTime( schedule.getMaxJobExecutionTime() );
         s.setName( schedule.getName() );
@@ -1680,18 +2596,23 @@
             return null;
         }
 
+        if ( StringUtils.isNotBlank( profile.getName() ) && !profile.getName().matches( NAME_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Build Environment Name contains invalid characters" );
+        }
+
         try
         {
             newProfile.setActive( profile.isActive() );
             newProfile.setBuildWithoutChanges( profile.isBuildWithoutChanges() );
-            newProfile.setDescription( profile.getDescription() );
+            newProfile.setDescription( StringEscapeUtils.escapeXml( profile.getDescription() ) );
             newProfile.setName( profile.getName() );
             newProfile.setScmMode( profile.getScmMode() );
+            newProfile.setBuildAgentGroup( profile.getBuildAgentGroup() );
             if ( profile.getBuilder() != null )
             {
                 final org.apache.maven.continuum.model.system.Installation newBuilder =
-                                continuum.getInstallationService().getInstallation(
-                                    profile.getBuilder().getInstallationId() );
+                    continuum.getInstallationService().getInstallation( profile.getBuilder().getInstallationId() );
                 newProfile.setBuilder( populateInstallation( profile.getBuilder(), newBuilder ) );
 
             }
@@ -1702,8 +2623,7 @@
             if ( profile.getJdk() != null )
             {
                 final org.apache.maven.continuum.model.system.Installation newJdk =
-                                continuum.getInstallationService().getInstallation(
-                                    profile.getJdk().getInstallationId() );
+                    continuum.getInstallationService().getInstallation( profile.getJdk().getInstallationId() );
                 newProfile.setJdk( populateInstallation( profile.getJdk(), newJdk ) );
 
             }
@@ -1714,12 +2634,10 @@
             newProfile.getEnvironmentVariables().clear();
             if ( profile.getEnvironmentVariables() != null )
             {
-                for ( Iterator it = profile.getEnvironmentVariables().iterator(); it.hasNext(); )
+                for ( final Installation varEnv : profile.getEnvironmentVariables() )
                 {
-                    final Installation varEnv = (Installation) it.next();
-
                     final org.apache.maven.continuum.model.system.Installation newInst =
-                                    continuum.getInstallationService().getInstallation( varEnv.getInstallationId() );
+                        continuum.getInstallationService().getInstallation( varEnv.getInstallationId() );
                     newProfile.getEnvironmentVariables().add( populateInstallation( varEnv, newInst ) );
 
                 }
@@ -1739,12 +2657,36 @@
 
     private org.apache.maven.continuum.model.system.Installation populateInstallation( Installation install,
                                                                                        org.apache.maven.continuum.model.system.Installation inst )
+        throws ContinuumException
     {
         if ( install == null )
         {
             return null;
         }
 
+        if ( StringUtils.isNotBlank( install.getName() ) && !install.getName().matches( NAME_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Installation Name contains invalid characters" );
+        }
+
+        if ( StringUtils.isNotBlank( install.getType() ) && !install.getType().matches(
+            INSTALLATION_TYPE_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Installation Type contains invalid characters" );
+        }
+
+        if ( StringUtils.isNotBlank( install.getVarName() ) && !install.getVarName().matches(
+            INSTALLATION_VARNAME_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Installation VarName contains invalid characters" );
+        }
+
+        if ( StringUtils.isNotBlank( install.getVarValue() ) && !install.getVarValue().matches(
+            INSTALLATION_VARVALUE_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Installation VarValue contains invalid characters" );
+        }
+
         inst.setName( install.getName() );
         inst.setType( install.getType() );
         inst.setVarName( install.getVarName() );
@@ -1757,23 +2699,27 @@
         return (Installation) mapper.map( install, Installation.class );
     }
 
-    private SystemConfiguration populateSystemConfiguration( org.apache.maven.continuum.model.system.SystemConfiguration sysConf )
+    private SystemConfiguration populateSystemConfiguration(
+        org.apache.maven.continuum.model.system.SystemConfiguration sysConf )
     {
         return (SystemConfiguration) mapper.map( sysConf, SystemConfiguration.class );
     }
 
-    private ContinuumReleaseResult populateReleaseResult( org.apache.continuum.model.release.ContinuumReleaseResult releaseResult )
+    private ContinuumReleaseResult populateReleaseResult(
+        org.apache.continuum.model.release.ContinuumReleaseResult releaseResult )
     {
         return (ContinuumReleaseResult) mapper.map( releaseResult, ContinuumReleaseResult.class );
     }
 
-    private RepositoryPurgeConfiguration populateRepositoryPurgeConfiguration( org.apache.continuum.model.repository.RepositoryPurgeConfiguration repoPurgeConfig )
+    private RepositoryPurgeConfiguration populateRepositoryPurgeConfiguration(
+        org.apache.continuum.model.repository.RepositoryPurgeConfiguration repoPurgeConfig )
     {
         return (RepositoryPurgeConfiguration) mapper.map( repoPurgeConfig, RepositoryPurgeConfiguration.class );
     }
 
-    private org.apache.continuum.model.repository.RepositoryPurgeConfiguration populateRepositoryPurgeConfiguration( RepositoryPurgeConfiguration repoPurgeConfig,
-                                                                                                                     org.apache.continuum.model.repository.RepositoryPurgeConfiguration repoPurge )
+    private org.apache.continuum.model.repository.RepositoryPurgeConfiguration populateRepositoryPurgeConfiguration(
+        RepositoryPurgeConfiguration repoPurgeConfig,
+        org.apache.continuum.model.repository.RepositoryPurgeConfiguration repoPurge )
         throws RepositoryServiceException, ContinuumException
     {
         if ( repoPurgeConfig == null )
@@ -1785,13 +2731,15 @@
         repoPurge.setDefaultPurge( repoPurgeConfig.isDefaultPurge() );
         repoPurge.setDeleteAll( repoPurgeConfig.isDeleteAll() );
         repoPurge.setDeleteReleasedSnapshots( repoPurgeConfig.isDeleteReleasedSnapshots() );
-        repoPurge.setDescription( repoPurgeConfig.getDescription() );
+        repoPurge.setDescription( StringEscapeUtils.escapeXml( repoPurgeConfig.getDescription() ) );
         repoPurge.setEnabled( repoPurgeConfig.isEnabled() );
         repoPurge.setRetentionCount( repoPurgeConfig.getRetentionCount() );
         if ( repoPurgeConfig.getRepository() != null )
         {
-            repoPurge.setRepository( populateLocalRepository( repoPurgeConfig.getRepository(), continuum.getRepositoryService().
-                                                              getLocalRepository( repoPurgeConfig.getRepository().getId() ) ) );
+            repoPurge.setRepository( populateLocalRepository( repoPurgeConfig.getRepository(),
+                                                              continuum.getRepositoryService().getLocalRepository(
+                                                                  repoPurgeConfig.getRepository().getId() )
+            ) );
         }
         else
         {
@@ -1799,8 +2747,8 @@
         }
         if ( repoPurgeConfig.getSchedule() != null )
         {
-            repoPurge.setSchedule( populateSchedule( repoPurgeConfig.getSchedule(), continuum.getSchedule( repoPurgeConfig.getSchedule()
-                            .getId() ) ) );
+            repoPurge.setSchedule( populateSchedule( repoPurgeConfig.getSchedule(), continuum.getSchedule(
+                repoPurgeConfig.getSchedule().getId() ) ) );
         }
         else
         {
@@ -1810,13 +2758,15 @@
         return repoPurge;
     }
 
-    private DirectoryPurgeConfiguration populateDirectoryPurgeConfiguration( org.apache.continuum.model.repository.DirectoryPurgeConfiguration dirPurgeConfig )
+    private DirectoryPurgeConfiguration populateDirectoryPurgeConfiguration(
+        org.apache.continuum.model.repository.DirectoryPurgeConfiguration dirPurgeConfig )
     {
         return (DirectoryPurgeConfiguration) mapper.map( dirPurgeConfig, DirectoryPurgeConfiguration.class );
     }
 
-    private org.apache.continuum.model.repository.DirectoryPurgeConfiguration populateDirectoryPurgeConfiguration( DirectoryPurgeConfiguration dirPurgeConfig, 
-                                                                                                                   org.apache.continuum.model.repository.DirectoryPurgeConfiguration dirPurge )
+    private org.apache.continuum.model.repository.DirectoryPurgeConfiguration populateDirectoryPurgeConfiguration(
+        DirectoryPurgeConfiguration dirPurgeConfig,
+        org.apache.continuum.model.repository.DirectoryPurgeConfiguration dirPurge )
         throws RepositoryServiceException, ContinuumException
     {
         if ( dirPurgeConfig == null )
@@ -1824,10 +2774,22 @@
             return null;
         }
 
+        if ( StringUtils.isNotBlank( dirPurgeConfig.getDirectoryType() ) && !dirPurgeConfig.getDirectoryType().matches(
+            DIRECTORY_TYPE_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Directory Purge Configuration Type can only be 'releases or buildOutput'" );
+        }
+
+        if ( StringUtils.isNotBlank( dirPurgeConfig.getLocation() ) && !dirPurgeConfig.getLocation().matches(
+            DIRECTORY_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Directory Purge Configuration Location contains invalid characters" );
+        }
+
         dirPurge.setDaysOlder( dirPurgeConfig.getDaysOlder() );
         dirPurge.setDefaultPurge( dirPurgeConfig.isDefaultPurge() );
         dirPurge.setDeleteAll( dirPurgeConfig.isDeleteAll() );
-        dirPurge.setDescription( dirPurgeConfig.getDescription() );
+        dirPurge.setDescription( StringEscapeUtils.escapeXml( dirPurgeConfig.getDescription() ) );
         dirPurge.setDirectoryType( dirPurgeConfig.getDirectoryType() );
         dirPurge.setEnabled( dirPurgeConfig.isEnabled() );
 
@@ -1841,13 +2803,13 @@
         {
             path = continuum.getConfiguration().getBuildOutputDirectory().getAbsolutePath();
         }
-        
+
         dirPurge.setLocation( path );
         dirPurge.setRetentionCount( dirPurgeConfig.getRetentionCount() );
         if ( dirPurgeConfig.getSchedule() != null )
         {
-            dirPurge.setSchedule( populateSchedule( dirPurgeConfig.getSchedule(), continuum.getSchedule( dirPurgeConfig.getSchedule()
-                            .getId() ) ) );
+            dirPurge.setSchedule( populateSchedule( dirPurgeConfig.getSchedule(), continuum.getSchedule(
+                dirPurgeConfig.getSchedule().getId() ) ) );
         }
         else
         {
@@ -1857,26 +2819,140 @@
         return dirPurge;
     }
 
-    private LocalRepository populateLocalRepository( org.apache.continuum.model.repository.LocalRepository localRepository )
+    private LocalRepository populateLocalRepository(
+        org.apache.continuum.model.repository.LocalRepository localRepository )
     {
         return (LocalRepository) mapper.map( localRepository, LocalRepository.class );
     }
 
     private org.apache.continuum.model.repository.LocalRepository populateLocalRepository( LocalRepository repository,
                                                                                            org.apache.continuum.model.repository.LocalRepository repo )
+        throws ContinuumException
     {
         if ( repository == null )
         {
             return null;
         }
 
+        if ( StringUtils.isNotBlank( repository.getLayout() ) && !repository.getLayout().matches(
+            REPOSITORY_LAYOUT_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Repository Layout can only be 'default or legacy'" );
+        }
+
+        if ( StringUtils.isNotBlank( repository.getLocation() ) && !repository.getLocation().matches(
+            DIRECTORY_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Repository Location contains invalid characters" );
+        }
+
+        if ( StringUtils.isNotBlank( repository.getName() ) && !repository.getName().matches( NAME_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Repository Name contains invalid characters" );
+        }
+
         repo.setLayout( repository.getLayout() );
         repo.setLocation( repository.getLocation() );
         repo.setName( repository.getName() );
         return repo;
     }
 
-    private Map<String, Object> serializeObject( Object o, final String ... ignore )
+    private org.apache.continuum.utils.build.BuildTrigger populateBuildTrigger( BuildTrigger buildTrigger )
+        throws ContinuumException
+    {
+        if ( buildTrigger == null )
+        {
+            return null;
+        }
+
+        if ( StringUtils.isNotBlank( buildTrigger.getTriggeredBy() ) && !buildTrigger.getTriggeredBy().matches(
+            USERNAME_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "BuildTrigger Triggered By contains invalid characters" );
+        }
+
+        return new org.apache.continuum.utils.build.BuildTrigger( buildTrigger.getTrigger(),
+                                                                  buildTrigger.getTriggeredBy() );
+    }
+
+    private org.apache.continuum.configuration.BuildAgentConfiguration populateBuildAgent(
+        BuildAgentConfiguration buildAgent )
+        throws ContinuumException
+    {
+        if ( buildAgent == null )
+        {
+            return null;
+        }
+
+        if ( StringUtils.isNotBlank( buildAgent.getUrl() ) && !buildAgent.getUrl().matches( URL_VALID_EXPRESSION ) )
+        {
+            throw new ContinuumException( "Build Agent URL contains invalid characters" );
+        }
+
+        org.apache.continuum.configuration.BuildAgentConfiguration buildAgentConfiguration =
+            new org.apache.continuum.configuration.BuildAgentConfiguration();
+        buildAgentConfiguration.setUrl( buildAgent.getUrl() );
+        buildAgentConfiguration.setDescription( StringEscapeUtils.escapeXml( buildAgent.getDescription() ) );
+        buildAgentConfiguration.setEnabled( buildAgent.isEnabled() );
+        return buildAgentConfiguration;
+    }
+
+    private BuildAgentConfiguration populateBuildAgent(
+        org.apache.continuum.configuration.BuildAgentConfiguration buildAgent )
+    {
+        BuildAgentConfiguration buildAgentConfiguration = (BuildAgentConfiguration) mapper.map( buildAgent,
+                                                                                                BuildAgentConfiguration.class );
+        try
+        {
+            buildAgentConfiguration.setPlatform( distributedBuildManager.getBuildAgentPlatform(
+                buildAgentConfiguration.getUrl() ) );
+            return buildAgentConfiguration;
+        }
+        catch ( ContinuumException e )
+        {
+            logger.warn( "Unable to connect to build agent " + buildAgentConfiguration.getUrl() + ".", e );
+            buildAgentConfiguration.setPlatform( "" );
+            return buildAgentConfiguration;
+        }
+    }
+
+    private org.apache.continuum.configuration.BuildAgentGroupConfiguration populateBuildAgentGroup(
+        BuildAgentGroupConfiguration buildAgentGroup )
+        throws ContinuumException
+    {
+        if ( buildAgentGroup == null )
+        {
+            return null;
+        }
+
+        org.apache.continuum.configuration.BuildAgentGroupConfiguration buildAgentGroupConfiguration =
+            new org.apache.continuum.configuration.BuildAgentGroupConfiguration();
+
+        if ( StringUtils.isBlank( buildAgentGroup.getName() ) )
+        {
+            throw new ContinuumException( "Build agent group name is required" );
+        }
+
+        buildAgentGroupConfiguration.setName( StringEscapeUtils.escapeXml( buildAgentGroup.getName() ) );
+
+        buildAgentGroupConfiguration.getBuildAgents().clear();
+        if ( buildAgentGroup.getBuildAgents() != null )
+        {
+            for ( BuildAgentConfiguration buildAgent : buildAgentGroup.getBuildAgents() )
+            {
+                buildAgentGroupConfiguration.getBuildAgents().add( populateBuildAgent( buildAgent ) );
+            }
+        }
+        return buildAgentGroupConfiguration;
+    }
+
+    private BuildAgentGroupConfiguration populateBuildAgentGroup(
+        org.apache.continuum.configuration.BuildAgentGroupConfiguration buildAgentGroup )
+    {
+        return (BuildAgentGroupConfiguration) mapper.map( buildAgentGroup, BuildAgentGroupConfiguration.class );
+    }
+
+    private Map<String, Object> serializeObject( Object o, final String... ignore )
     {
         if ( o != null )
         {
@@ -1888,7 +2964,7 @@
         }
     }
 
-    private Map<String, Object> serializeObject( Object o, Class clasz, final String ... ignore )
+    private Map<String, Object> serializeObject( Object o, Class clasz, final String... ignore )
     {
 
         final List<String> ignoreList = ignore == null ? new ArrayList<String>() : Arrays.asList( ignore );
@@ -2077,22 +3153,22 @@
 
     private String serializeObject( Byte o )
     {
-        return (o == null ? null : o.toString());
+        return ( o == null ? null : o.toString() );
     }
 
     private String serializeObject( Character o )
     {
-        return (o == null ? null : o.toString());
+        return ( o == null ? null : o.toString() );
     }
 
     private Double serializeObject( Long o )
     {
-        return (o == null ? null : o.doubleValue());
+        return ( o == null ? null : o.doubleValue() );
     }
 
     private Double serializeObject( Float o )
     {
-        return (o == null ? null : o.doubleValue());
+        return ( o == null ? null : o.doubleValue() );
     }
 
     private Double serializeObject( Double o )
@@ -2275,12 +3351,6 @@
         return o;
     }
 
-    public Map<String, Object> addAntProjectRPC( Map<String, Object> project )
-        throws Exception
-    {
-        return serializeObject( this.addAntProject( (ProjectSummary) unserializeObject( project ) ) );
-    }
-
     public Map<String, Object> addAntProjectRPC( Map<String, Object> project, int projectGroupId )
         throws Exception
     {
@@ -2291,20 +3361,15 @@
         throws Exception
     {
         return serializeObject( this.addBuildDefinitionToProjectGroup( projectGroupId,
-            (BuildDefinition) unserializeObject( buildDef ) ) );
+                                                                       (BuildDefinition) unserializeObject(
+                                                                           buildDef ) ) );
     }
 
     public Map<String, Object> addBuildDefinitionToProjectRPC( int projectId, Map<String, Object> buildDef )
         throws Exception
     {
-        return serializeObject( this.addBuildDefinitionToProject( projectId,
-            (BuildDefinition) unserializeObject( buildDef ) ) );
-    }
-
-    public Map<String, Object> addMavenOneProjectRPC( String url )
-        throws Exception
-    {
-        return serializeObject( this.addMavenOneProject( url ) );
+        return serializeObject( this.addBuildDefinitionToProject( projectId, (BuildDefinition) unserializeObject(
+            buildDef ) ) );
     }
 
     public Map<String, Object> addMavenOneProjectRPC( String url, int projectGroupId )
@@ -2325,6 +3390,28 @@
         return serializeObject( this.addMavenTwoProject( url, projectGroupId ) );
     }
 
+    public Map<String, Object> addMavenTwoProjectRPC( String url, int projectGroupId,
+                                                      boolean checkoutInSingleDirectory )
+        throws Exception
+    {
+        return serializeObject( this.addMavenTwoProject( url, projectGroupId, checkoutInSingleDirectory ) );
+    }
+
+    public Map<String, Object> addMavenTwoProjectAsSingleProjectRPC( String url, int projectGroupId )
+        throws Exception
+    {
+        return serializeObject( this.addMavenTwoProjectAsSingleProject( url, projectGroupId ) );
+    }
+
+    public Map<String, Object> addMavenTwoProjectRPC( String url, int projectGroupId, boolean checkProtocol,
+                                                      boolean useCredentialsCache, boolean recursiveProjects,
+                                                      boolean checkoutInSingleDirectory )
+        throws Exception
+    {
+        return serializeObject( this.addMavenTwoProject( url, projectGroupId, checkProtocol, useCredentialsCache,
+                                                         recursiveProjects, checkoutInSingleDirectory ) );
+    }
+
     public Map<String, Object> addProjectGroupRPC( String groupName, String groupId, String description )
         throws Exception
     {
@@ -2343,12 +3430,6 @@
         return serializeObject( this.addShellProject( (ProjectSummary) unserializeObject( project ), projectGroupId ) );
     }
 
-    public Map<String, Object> addShellProjectRPC( Map<String, Object> project )
-        throws Exception
-    {
-        return serializeObject( this.addShellProject( (ProjectSummary) unserializeObject( project ) ) );
-    }
-
     public List<Object> getAllProjectGroupsRPC()
         throws Exception
     {
@@ -2379,6 +3460,12 @@
         return serializeObject( this.getBuildDefinitionsForProject( projectId ) );
     }
 
+    public Map<String, Object> getBuildDefinitionRPC( int buildDefinitionId )
+        throws Exception
+    {
+        return serializeObject( this.getBuildDefinition( buildDefinitionId ) );
+    }
+
     public Map<String, Object> getBuildResultRPC( int projectId, int buildId )
         throws Exception
     {
@@ -2397,12 +3484,24 @@
         return serializeObject( this.getInstallation( installationId ) );
     }
 
+    public Map<String, Object> getInstallationRPC( String installationName )
+        throws Exception
+    {
+        return serializeObject( this.getInstallation( installationName ) );
+    }
+
     public List<Object> getInstallationsRPC()
         throws Exception
     {
         return serializeObject( this.getInstallations() );
     }
 
+    public List<Object> getBuildAgentInstallationsRPC( String url )
+        throws Exception
+    {
+        return serializeObject( this.getBuildAgentInstallations( url ) );
+    }
+
     public Map<String, Object> getLatestBuildResultRPC( int projectId )
         throws Exception
     {
@@ -2415,6 +3514,12 @@
         return serializeObject( this.getProfile( profileId ) );
     }
 
+    public Map<String, Object> getProfileWithNameRPC( String profileName )
+        throws Exception
+    {
+        return serializeObject( this.getProfileWithName( profileName ) );
+    }
+
     public List<Object> getProfilesRPC()
         throws Exception
     {
@@ -2481,18 +3586,21 @@
         return serializeObject( this.removeBuildResult( (BuildResult) unserializeObject( br ) ) );
     }
 
-    public Map<String, Object> updateBuildDefinitionForProjectGroupRPC( int projectGroupId, Map<String, Object> buildDef )
+    public Map<String, Object> updateBuildDefinitionForProjectGroupRPC( int projectGroupId,
+                                                                        Map<String, Object> buildDef )
         throws Exception
     {
         return serializeObject( this.updateBuildDefinitionForProjectGroup( projectGroupId,
-            (BuildDefinition) unserializeObject( buildDef ) ) );
+                                                                           (BuildDefinition) unserializeObject(
+                                                                               buildDef )
+        ) );
     }
 
     public Map<String, Object> updateBuildDefinitionForProjectRPC( int projectId, Map<String, Object> buildDef )
         throws Exception
     {
-        return serializeObject( this.updateBuildDefinitionForProject( projectId,
-            (BuildDefinition) unserializeObject( buildDef ) ) );
+        return serializeObject( this.updateBuildDefinitionForProject( projectId, (BuildDefinition) unserializeObject(
+            buildDef ) ) );
     }
 
     public Map<String, Object> updateProjectRPC( Map<String, Object> project )
@@ -2528,8 +3636,8 @@
     public Map<String, Object> updateGroupNotifierRPC( int projectgroupid, Map<String, Object> newNotifier )
         throws Exception
     {
-        return serializeObject( this.updateGroupNotifier( projectgroupid,
-            (ProjectNotifier) unserializeObject( newNotifier ) ) );
+        return serializeObject( this.updateGroupNotifier( projectgroupid, (ProjectNotifier) unserializeObject(
+            newNotifier ) ) );
     }
 
     public Map<String, Object> updateNotifierRPC( int projectid, Map<String, Object> newNotifier )
@@ -2541,8 +3649,8 @@
     public Map<String, Object> addGroupNotifierRPC( int projectgroupid, Map<String, Object> newNotifier )
         throws Exception
     {
-        return serializeObject( this.addGroupNotifier( projectgroupid,
-            (ProjectNotifier) unserializeObject( newNotifier ) ) );
+        return serializeObject( this.addGroupNotifier( projectgroupid, (ProjectNotifier) unserializeObject(
+            newNotifier ) ) );
     }
 
     public Map<String, Object> addNotifierRPC( int projectid, Map<String, Object> newNotifier )
@@ -2575,7 +3683,7 @@
         return this.updateProfile( (Profile) unserializeObject( profile ) );
     }
 
-    public Map<String,Object> getReleaseResultRPC( int releaseId )
+    public Map<String, Object> getReleaseResultRPC( int releaseId )
         throws Exception
     {
         return serializeObject( this.getReleaseResult( releaseId ) );
@@ -2596,13 +3704,15 @@
     public Map<String, Object> addRepositoryPurgeConfigurationRPC( Map<String, Object> repoPurge )
         throws Exception
     {
-        return serializeObject( this.addRepositoryPurgeConfiguration( (RepositoryPurgeConfiguration) unserializeObject( repoPurge ) ) );
+        return serializeObject( this.addRepositoryPurgeConfiguration( (RepositoryPurgeConfiguration) unserializeObject(
+            repoPurge ) ) );
     }
 
     public int updateRepositoryPurgeConfigurationRPC( Map<String, Object> repoPurge )
         throws Exception
     {
-        return serializeObject( this.updateRepositoryPurgeConfiguration( (RepositoryPurgeConfiguration) unserializeObject( repoPurge ) ) );
+        return serializeObject( this.updateRepositoryPurgeConfiguration(
+            (RepositoryPurgeConfiguration) unserializeObject( repoPurge ) ) );
     }
 
     public Map<String, Object> getRepositoryPurgeConfigurationRPC( int repoPurgeId )
@@ -2620,13 +3730,15 @@
     public Map<String, Object> addDirectoryPurgeConfigurationRPC( Map<String, Object> dirPurge )
         throws Exception
     {
-        return serializeObject( this.addDirectoryPurgeConfiguration( (DirectoryPurgeConfiguration) unserializeObject( dirPurge ) ) );
+        return serializeObject( this.addDirectoryPurgeConfiguration( (DirectoryPurgeConfiguration) unserializeObject(
+            dirPurge ) ) );
     }
 
     public int updateDirectoryPurgeConfigurationRPC( Map<String, Object> dirPurge )
         throws Exception
     {
-        return serializeObject( this.updateDirectoryPurgeConfiguration( (DirectoryPurgeConfiguration) unserializeObject( dirPurge ) ) );
+        return serializeObject( this.updateDirectoryPurgeConfiguration( (DirectoryPurgeConfiguration) unserializeObject(
+            dirPurge ) ) );
     }
 
     public Map<String, Object> getDirectoryPurgeConfigurationRPC( int dirPurgeId )
@@ -2664,4 +3776,418 @@
     {
         return serializeObject( this.getAllLocalRepositories() );
     }
+
+    public Map<String, Object> addBuildAgentRPC( Map<String, Object> buildAgentConfiguration )
+        throws Exception
+    {
+        return serializeObject( this.addBuildAgent( (BuildAgentConfiguration) unserializeObject(
+            buildAgentConfiguration ) ) );
+    }
+
+    public Map<String, Object> getBuildAgentRPC( String url )
+    {
+        return serializeObject( this.getBuildAgent( url ) );
+    }
+
+    public Map<String, Object> updateBuildAgentRPC( Map<String, Object> buildAgentConfiguration )
+        throws ConfigurationStoringException, ContinuumConfigurationException
+    {
+        return serializeObject( this.updateBuildAgent( (BuildAgentConfiguration) unserializeObject(
+            buildAgentConfiguration ) ) );
+    }
+
+    public List<Object> getAllBuildAgentsRPC()
+    {
+        return serializeObject( this.getAllBuildAgents() );
+    }
+
+    public List<Object> getBuildAgentsWithInstallationsRPC()
+        throws Exception
+    {
+        return serializeObject( this.getBuildAgentsWithInstallations() );
+    }
+
+    public Map<String, Object> addBuildAgentGroupRPC( Map<String, Object> buildAgentGroup )
+        throws ConfigurationException, ConfigurationStoringException, ContinuumConfigurationException
+    {
+        return serializeObject( this.addBuildAgentGroup( (BuildAgentGroupConfiguration) unserializeObject(
+            buildAgentGroup ) ) );
+    }
+
+    public Map<String, Object> getBuildAgentGroupRPC( String name )
+    {
+        return serializeObject( this.getBuildAgentGroup( name ) );
+    }
+
+    public Map<String, Object> updateBuildAgentGroupRPC( Map<String, Object> buildAgentGroup )
+        throws ConfigurationException, ConfigurationStoringException, ContinuumConfigurationException
+    {
+        return serializeObject( this.updateBuildAgentGroup( (BuildAgentGroupConfiguration) unserializeObject(
+            buildAgentGroup ) ) );
+    }
+
+    public String releasePrepare( int projectId, Properties releaseProperties, Map<String, String> releaseVersions,
+                                  Map<String, String> developmentVersions, Map<String, String> environments,
+                                  String username )
+        throws Exception
+    {
+        org.apache.maven.continuum.model.project.Project project = continuum.getProject( projectId );
+
+        if ( project != null )
+        {
+            checkBuildProjectInGroupAuthorization( project.getProjectGroup().getName() );
+
+            if ( continuum.getConfiguration().isDistributedBuildEnabled() )
+            {
+                return continuum.getDistributedReleaseManager().releasePrepare( project, releaseProperties,
+                                                                                releaseVersions, developmentVersions,
+                                                                                environments, username );
+            }
+            else
+            {
+                String executable = null;
+
+                if ( environments != null )
+                {
+                    String m2Home = environments.get( continuum.getInstallationService().getEnvVar(
+                        InstallationService.MAVEN2_TYPE ) );
+                    if ( StringUtils.isNotEmpty( m2Home ) )
+                    {
+                        executable = m2Home + File.separator + "bin" + File.separator + executable;
+                    }
+                }
+
+                releaseProperties.setProperty( "release-by", username );
+                return continuum.getReleaseManager().prepare( project, releaseProperties, releaseVersions,
+                                                              developmentVersions, null, continuum.getWorkingDirectory(
+                        projectId ).getPath(), environments, executable
+                );
+            }
+        }
+        else
+        {
+            throw new Exception(
+                "Unable to prepare release project with id : " + projectId + " because it doesn't exist" );
+        }
+    }
+
+    public int releasePerform( int projectId, String releaseId, String goals, String arguments,
+                               boolean useReleaseProfile, String repositoryName, String username )
+        throws Exception
+    {
+        org.apache.maven.continuum.model.project.Project project = continuum.getProject( projectId );
+
+        if ( project != null )
+        {
+            checkBuildProjectInGroupAuthorization( project.getProjectGroup().getName() );
+
+            org.apache.continuum.model.repository.LocalRepository repository =
+                continuum.getRepositoryService().getLocalRepositoryByName( repositoryName );
+
+            if ( continuum.getConfiguration().isDistributedBuildEnabled() )
+            {
+                continuum.getDistributedReleaseManager().releasePerform( projectId, releaseId, goals, arguments,
+                                                                         useReleaseProfile, repository, username );
+            }
+            else
+            {
+                File performDirectory = new File( continuum.getConfiguration().getWorkingDirectory(),
+                                                  "releases-" + System.currentTimeMillis() );
+                performDirectory.mkdirs();
+
+                continuum.getReleaseManager().perform( releaseId, performDirectory, goals, arguments, useReleaseProfile,
+                                                       null, repository );
+            }
+
+            return 0;
+        }
+        else
+        {
+            throw new Exception(
+                "Unable to perform release project with id : " + projectId + " because it doesn't exist" );
+        }
+    }
+
+    public ReleaseListenerSummary getListener( int projectId, String releaseId )
+        throws Exception
+    {
+        org.apache.maven.continuum.model.project.Project project = continuum.getProject( projectId );
+
+        if ( project != null )
+        {
+            checkBuildProjectInGroupAuthorization( project.getProjectGroup().getName() );
+
+            if ( continuum.getConfiguration().isDistributedBuildEnabled() )
+            {
+                Map<String, Object> map = continuum.getDistributedReleaseManager().getListener( releaseId );
+                return processListenerMap( map );
+            }
+            else
+            {
+                return populateReleaseListenerSummary( continuum.getReleaseManager().getListener( releaseId ) );
+            }
+        }
+        else
+        {
+            throw new Exception( "Unable to get release listener for '" + releaseId + "'" );
+        }
+    }
+
+    public int releaseCleanup( int projectId, String releaseId )
+        throws Exception
+    {
+        return releaseCleanup( projectId, releaseId, null );
+    }
+
+    public int releaseCleanup( int projectId, String releaseId, String releaseType )
+        throws Exception
+    {
+        org.apache.maven.continuum.model.project.Project project = continuum.getProject( projectId );
+
+        if ( project != null )
+        {
+            checkBuildProjectInGroupAuthorization( project.getProjectGroup().getName() );
+            org.apache.continuum.model.release.ContinuumReleaseResult result = continuum.addContinuumReleaseResult(
+                projectId, releaseId, releaseType );
+
+            if ( continuum.getConfiguration().isDistributedBuildEnabled() )
+            {
+                continuum.getDistributedReleaseManager().releaseCleanup( releaseId );
+            }
+            else
+            {
+                continuum.getReleaseManager().getReleaseResults().remove( releaseId );
+                continuum.getReleaseManager().getListeners().remove( releaseId );
+            }
+
+            return result != null ? result.getId() : 0;
+        }
+        else
+        {
+            throw new Exception( "Unable to do release cleanup for release '" + releaseId + "'" );
+        }
+    }
+
+    public int releaseRollback( int projectId, String releaseId )
+        throws Exception
+    {
+        org.apache.maven.continuum.model.project.Project project = continuum.getProject( projectId );
+
+        if ( project != null )
+        {
+            checkBuildProjectInGroupAuthorization( project.getProjectGroup().getName() );
+            if ( continuum.getConfiguration().isDistributedBuildEnabled() )
+            {
+                continuum.getDistributedReleaseManager().releaseRollback( releaseId, projectId );
+            }
+            else
+            {
+                continuum.getReleaseManager().rollback( releaseId, continuum.getWorkingDirectory( projectId ).getPath(),
+                                                        null );
+                continuum.getReleaseManager().getPreparedReleases().remove( releaseId );
+            }
+            return 0;
+        }
+        else
+        {
+            throw new Exception( "Unable to rollback the release for '" + releaseId + "'" );
+        }
+    }
+
+    public Map<String, Object> getReleasePluginParameters( int projectId )
+        throws Exception
+    {
+        org.apache.maven.continuum.model.project.Project project = continuum.getProject( projectId );
+
+        if ( project != null )
+        {
+            checkBuildProjectInGroupAuthorization( project.getProjectGroup().getName() );
+            Map<String, Object> params;
+
+            if ( continuum.getConfiguration().isDistributedBuildEnabled() )
+            {
+                params = continuum.getDistributedReleaseManager().getReleasePluginParameters( projectId, "pom.xml" );
+            }
+            else
+            {
+                params = ReleaseUtil.getReleasePluginParameters( continuum.getWorkingDirectory( projectId ).getPath(),
+                                                                 "pom.xml" );
+            }
+
+            // set scm tag and scm tag base if no values yet
+            // scm tag
+            if ( StringUtils.isBlank( (String) params.get( "scm-tag" ) ) )
+            {
+                String scmTag;
+                if ( project.getScmTag() != null )
+                {
+                    scmTag = project.getScmTag();
+                }
+                else
+                {
+                    String version = project.getVersion();
+                    int idx = version.indexOf( "-SNAPSHOT" );
+
+                    if ( idx >= 0 )
+                    {
+                        // strip the snapshot version suffix
+                        scmTag = project.getArtifactId() + "-" + version.substring( 0, idx );
+                    }
+                    else
+                    {
+                        scmTag = project.getArtifactId() + "-" + version;
+                    }
+                }
+
+                continuum.getReleaseManager().sanitizeTagName( project.getScmUrl(), scmTag );
+                params.put( "scm-tag", scmTag );
+            }
+
+            // scm tagbase
+            if ( StringUtils.isBlank( (String) params.get( "scm-tagbase" ) ) )
+            {
+                if ( project.getScmUrl().startsWith( "scm:svn" ) )
+                {
+                    String scmTagBase = new SvnScmProviderRepository( project.getScmUrl(), project.getScmUsername(),
+                                                                      project.getScmPassword() ).getTagBase();
+                    // strip the Maven scm protocol prefix
+                    params.put( "scm-tagbase", scmTagBase.substring( "scm:svn".length() + 1 ) );
+                }
+                else
+                {
+                    params.put( "scm-tagbase", "" );
+                }
+            }
+
+            return params;
+        }
+        else
+        {
+            throw new Exception( "Unable to get release plugin parameters for project with id " + projectId );
+        }
+    }
+
+    public List<Map<String, String>> getProjectReleaseAndDevelopmentVersions( int projectId, String pomFilename,
+                                                                              boolean autoVersionSubmodules )
+        throws Exception
+    {
+        org.apache.maven.continuum.model.project.Project project = continuum.getProject( projectId );
+
+        if ( project != null )
+        {
+            checkBuildProjectInGroupAuthorization( project.getProjectGroup().getName() );
+            List<Map<String, String>> projects = new ArrayList<Map<String, String>>();
+
+            if ( continuum.getConfiguration().isDistributedBuildEnabled() )
+            {
+                projects = continuum.getDistributedReleaseManager().processProject( projectId, pomFilename,
+                                                                                    autoVersionSubmodules );
+            }
+            else
+            {
+                ReleaseUtil.processProject( continuum.getWorkingDirectory( projectId ).getPath(), pomFilename,
+                                            autoVersionSubmodules, projects );
+            }
+
+            return projects;
+        }
+        else
+        {
+            throw new Exception( "Unable to get release plugin parameters for project with id " + projectId );
+        }
+    }
+
+    private ReleaseListenerSummary processListenerMap( Map<String, Object> context )
+    {
+        ReleaseListenerSummary listenerSummary = new ReleaseListenerSummary();
+        Object value = context.get( "release-in-progress" );
+        if ( value != null )
+        {
+            listenerSummary.setInProgress( (String) value );
+        }
+
+        value = context.get( "release-error" );
+        if ( value != null )
+        {
+            listenerSummary.setError( (String) value );
+        }
+
+        value = context.get( "username" );
+        if ( value != null )
+        {
+            listenerSummary.setUsername( (String) value );
+        }
+
+        value = context.get( "state" );
+        if ( value != null )
+        {
+            listenerSummary.setState( (Integer) value );
+        }
+
+        value = context.get( "release-phases" );
+        if ( value != null )
+        {
+            listenerSummary.setPhases( getList( value ) );
+        }
+
+        value = context.get( "completed-release-phases" );
+        if ( value != null )
+        {
+            listenerSummary.setCompletedPhases( getList( value ) );
+        }
+
+        return listenerSummary;
+    }
+
+    private ReleaseListenerSummary populateReleaseListenerSummary(
+        org.apache.continuum.model.release.ReleaseListenerSummary listener )
+    {
+        return (ReleaseListenerSummary) mapper.map( listener, ReleaseListenerSummary.class );
+    }
+
+    public boolean pingBuildAgent( String buildAgentUrl )
+        throws Exception
+    {
+        return distributedBuildManager.pingBuildAgent( buildAgentUrl );
+    }
+
+    private List<String> getList( Object obj )
+    {
+        List<String> list = new ArrayList<String>();
+
+        if ( obj instanceof String[] )
+        {
+            list.addAll( Arrays.asList( (String[]) obj ) );
+        }
+        else if ( obj instanceof Object[] )
+        {
+            // fallback needed since XMLRPC to the build agent will return a List<String> as Object[]
+            for ( Object o : (Object[]) obj )
+            {
+                list.add( (String) o );
+            }
+        }
+        else
+        {
+            list = (List<String>) obj;
+        }
+
+        return list;
+    }
+
+    // testing
+    public void setContinuum( Continuum continuum )
+    {
+        this.continuum = continuum;
+    }
+
+    public void setDistributedBuildManager( DistributedBuildManager distributedBuildManager )
+    {
+        this.distributedBuildManager = distributedBuildManager;
+    }
+
+    public void setRoleManager( RoleManager roleManager )
+    {
+        this.roleManager = roleManager;
+    }
 }
diff --git a/continuum-xmlrpc/continuum-xmlrpc-server/src/main/java/org/apache/maven/continuum/xmlrpc/server/ContinuumXmlRpcMetaDataHandler.java b/continuum-xmlrpc/continuum-xmlrpc-server/src/main/java/org/apache/maven/continuum/xmlrpc/server/ContinuumXmlRpcMetaDataHandler.java
index 1acc0e8..75331f0 100644
--- a/continuum-xmlrpc/continuum-xmlrpc-server/src/main/java/org/apache/maven/continuum/xmlrpc/server/ContinuumXmlRpcMetaDataHandler.java
+++ b/continuum-xmlrpc/continuum-xmlrpc-server/src/main/java/org/apache/maven/continuum/xmlrpc/server/ContinuumXmlRpcMetaDataHandler.java
@@ -1,5 +1,24 @@
 package org.apache.maven.continuum.xmlrpc.server;
 
+/*
+ * 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 org.apache.xmlrpc.XmlRpcException;
 import org.apache.xmlrpc.XmlRpcHandler;
 import org.apache.xmlrpc.XmlRpcRequest;
@@ -52,7 +71,7 @@
 
     private final String methodHelp;
 
-    private PlexusContainer container;
+    private final PlexusContainer container;
 
     /**
      * Creates a new instance.
@@ -109,9 +128,8 @@
             args[j] = pRequest.getParameter( j );
         }
         Object instance = getInstance( pRequest );
-        for ( int i = 0; i < methods.length; i++ )
+        for ( MethodData methodData : methods )
         {
-            MethodData methodData = methods[i];
             TypeConverter[] converters = methodData.typeConverters;
             if ( args.length == converters.length )
             {
diff --git a/continuum-xmlrpc/continuum-xmlrpc-server/src/main/java/org/apache/maven/continuum/xmlrpc/server/ContinuumXmlRpcServlet.java b/continuum-xmlrpc/continuum-xmlrpc-server/src/main/java/org/apache/maven/continuum/xmlrpc/server/ContinuumXmlRpcServlet.java
index daf39e9..9974ef2 100644
--- a/continuum-xmlrpc/continuum-xmlrpc-server/src/main/java/org/apache/maven/continuum/xmlrpc/server/ContinuumXmlRpcServlet.java
+++ b/continuum-xmlrpc/continuum-xmlrpc-server/src/main/java/org/apache/maven/continuum/xmlrpc/server/ContinuumXmlRpcServlet.java
@@ -34,20 +34,20 @@
 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
 import org.codehaus.plexus.redback.authentication.AuthenticationException;
 import org.codehaus.plexus.redback.authentication.PasswordBasedAuthenticationDataSource;
-import org.codehaus.plexus.redback.policy.AccountLockedException;
+import org.codehaus.plexus.redback.policy.PolicyViolationException;
 import org.codehaus.plexus.redback.system.DefaultSecuritySession;
 import org.codehaus.plexus.redback.system.SecuritySystem;
 import org.codehaus.plexus.redback.users.UserNotFoundException;
 
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
 import javax.servlet.ServletConfig;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
 
 /**
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
@@ -112,10 +112,10 @@
         {
             XmlRpcServerConfigImpl cfg = (XmlRpcServerConfigImpl) server.getConfig();
             cfg.setEnabledForExtensions( true );
-            PropertiesHandlerMapping mapping =
-                (PropertiesHandlerMapping) lookup( PropertyHandlerMapping.class.getName() );
-            mapping.setRequestProcessorFactoryFactory(
-                (RequestProcessorFactoryFactory) lookup( RequestProcessorFactoryFactory.class.getName() ) );
+            PropertiesHandlerMapping mapping = (PropertiesHandlerMapping) lookup(
+                PropertyHandlerMapping.class.getName() );
+            mapping.setRequestProcessorFactoryFactory( (RequestProcessorFactoryFactory) lookup(
+                RequestProcessorFactoryFactory.class.getName() ) );
             mapping.load();
             mapping.setAuthenticationHandler( getAuthenticationHandler() );
             server.setHandlerMapping( mapping );
@@ -128,62 +128,60 @@
 
     private AbstractReflectiveHandlerMapping.AuthenticationHandler getAuthenticationHandler()
     {
-        AbstractReflectiveHandlerMapping.AuthenticationHandler handler =
-            new AbstractReflectiveHandlerMapping.AuthenticationHandler()
+        return new AbstractReflectiveHandlerMapping.AuthenticationHandler()
+        {
+            public boolean isAuthorized( XmlRpcRequest pRequest )
             {
-                public boolean isAuthorized( XmlRpcRequest pRequest )
+                if ( pRequest.getConfig() instanceof ContinuumXmlRpcConfig )
                 {
-                    if ( pRequest.getConfig() instanceof ContinuumXmlRpcConfig )
+                    ContinuumXmlRpcConfig config = (ContinuumXmlRpcConfig) pRequest.getConfig();
+
+                    try
                     {
-                        ContinuumXmlRpcConfig config = (ContinuumXmlRpcConfig) pRequest.getConfig();
-
-                        try
+                        // if username is null, then treat this as a guest user with an empty security session
+                        if ( config.getBasicUserName() == null )
                         {
-                            // if username is null, then treat this as a guest user with an empty security session
-                            if ( config.getBasicUserName() == null )
-                            {
-                                config.setSecuritySession( new DefaultSecuritySession() );
+                            config.setSecuritySession( new DefaultSecuritySession() );
 
-                                return true;
-                            }
-                            else
-                            {
-                                // otherwise treat this as an authn required session, and if the credentials are invalid
-                                // do not default to guest privileges 
-                                PasswordBasedAuthenticationDataSource authdatasource =
-                                    new PasswordBasedAuthenticationDataSource();
-                                authdatasource.setPrincipal( config.getBasicUserName() );
-                                authdatasource.setPassword( config.getBasicPassword() );
-
-                                config.setSecuritySession( securitySystem.authenticate( authdatasource ) );
-
-                                return config.getSecuritySession().isAuthenticated();
-                            }
+                            return true;
                         }
-                        catch ( AuthenticationException e )
+                        else
                         {
-                            e.printStackTrace();
-                            return false;
-                        }
-                        catch ( AccountLockedException e )
-                        {
-                            e.printStackTrace();
-                            return false;
-                        }
-                        catch ( UserNotFoundException e )
-                        {
-                            e.printStackTrace();
-                            return false;
+                            // otherwise treat this as an authn required session, and if the credentials are invalid
+                            // do not default to guest privileges
+                            PasswordBasedAuthenticationDataSource authdatasource =
+                                new PasswordBasedAuthenticationDataSource();
+                            authdatasource.setPrincipal( config.getBasicUserName() );
+                            authdatasource.setPassword( config.getBasicPassword() );
+
+                            config.setSecuritySession( securitySystem.authenticate( authdatasource ) );
+
+                            return config.getSecuritySession().isAuthenticated();
                         }
                     }
-                    else
+                    catch ( AuthenticationException e )
                     {
-                        System.out.println( "unknown xml rpc configiration object found..." );
+                        e.printStackTrace();
+                        return false;
+                    }
+                    catch ( PolicyViolationException e )
+                    {
+                        e.printStackTrace();
+                        return false;
+                    }
+                    catch ( UserNotFoundException e )
+                    {
+                        e.printStackTrace();
                         return false;
                     }
                 }
-            };
-        return handler;
+                else
+                {
+                    System.out.println( "unknown xml rpc configiration object found..." );
+                    return false;
+                }
+            }
+        };
     }
 
     public void doPost( HttpServletRequest pRequest, HttpServletResponse pResponse )
@@ -215,8 +213,8 @@
         PlexusContainer pc;
         try
         {
-            pc = new DefaultPlexusContainer( "default", keys, "META-INF/plexus/application.xml",
-                                             new ClassWorld( "plexus.core", getClass().getClassLoader() ) );
+            pc = new DefaultPlexusContainer( "default", keys, "META-INF/plexus/application.xml", new ClassWorld(
+                "plexus.core", getClass().getClassLoader() ) );
 
             context.setAttribute( PlexusConstants.PLEXUS_KEY, pc );
         }
diff --git a/continuum-xmlrpc/continuum-xmlrpc-server/src/main/java/org/apache/maven/continuum/xmlrpc/server/PropertiesHandlerMapping.java b/continuum-xmlrpc/continuum-xmlrpc-server/src/main/java/org/apache/maven/continuum/xmlrpc/server/PropertiesHandlerMapping.java
index fb3ff3b..5cb25bf 100644
--- a/continuum-xmlrpc/continuum-xmlrpc-server/src/main/java/org/apache/maven/continuum/xmlrpc/server/PropertiesHandlerMapping.java
+++ b/continuum-xmlrpc/continuum-xmlrpc-server/src/main/java/org/apache/maven/continuum/xmlrpc/server/PropertiesHandlerMapping.java
@@ -32,7 +32,6 @@
 import org.slf4j.LoggerFactory;
 
 import java.lang.reflect.Method;
-import java.util.Iterator;
 import java.util.Map;
 
 /**
@@ -44,21 +43,20 @@
     extends PropertyHandlerMapping
     implements Contextualizable
 {
-    private Logger log = LoggerFactory.getLogger( PropertiesHandlerMapping.class );
+    private static final Logger log = LoggerFactory.getLogger( PropertiesHandlerMapping.class );
 
     /**
      * @plexus.requirement role="org.apache.maven.continuum.xmlrpc.server.ContinuumXmlRpcComponent"
      */
-    private Map xmlrpcComponents;
+    private Map<String, Object> xmlrpcComponents;
 
     private PlexusContainer container;
 
     public void load()
         throws XmlRpcException
     {
-        for ( Iterator i = xmlrpcComponents.keySet().iterator(); i.hasNext(); )
+        for ( String key : xmlrpcComponents.keySet() )
         {
-            String key = (String) i.next();
             Class cl = xmlrpcComponents.get( key ).getClass();
             if ( log.isDebugEnabled() )
             {
@@ -71,9 +69,9 @@
         if ( log.isDebugEnabled() )
         {
             String[] methods = getListMethods();
-            for ( int i = 0; i < methods.length; i++ )
+            for ( String method : methods )
             {
-                log.debug( methods[i] );
+                log.debug( method );
             }
         }
     }
diff --git a/continuum-xmlrpc/continuum-xmlrpc-server/src/main/resources/dozerBeanMapping.xml b/continuum-xmlrpc/continuum-xmlrpc-server/src/main/resources/dozerBeanMapping.xml
index bf3c610..6d3309e 100644
--- a/continuum-xmlrpc/continuum-xmlrpc-server/src/main/resources/dozerBeanMapping.xml
+++ b/continuum-xmlrpc/continuum-xmlrpc-server/src/main/resources/dozerBeanMapping.xml
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ 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.
+  -->
+
 <!DOCTYPE mappings PUBLIC "-//DOZER//DTD MAPPINGS//EN"
    "http://dozer.sourceforge.net/dtd/dozerbeanmapping.dtd">
 <mappings>
@@ -203,7 +223,7 @@
   </mapping>
   
   <mapping>
-    <class-a>org.apache.maven.continuum.buildqueue.BuildProjectTask</class-a>
+    <class-a>org.apache.continuum.taskqueue.BuildProjectTask</class-a>
     <class-b>org.apache.maven.continuum.xmlrpc.project.BuildProjectTask</class-b>
   </mapping>
 
@@ -246,14 +266,40 @@
     <field>
       <a>projectGroup</a>
       <b>projectGroup</b>
-      <a-hint>org.apache.maven.continuum.xmlrpc.project.ProjectGroup</a-hint>
+      <a-hint>org.apache.maven.continuum.xmlrpc.project.ProjectGroupSummary</a-hint>
       <b-hint>org.apache.maven.continuum.model.project.ProjectGroup</b-hint>
     </field>
     <field>
       <a>project</a>
       <b>project</b>
-      <a-hint>org.apache.maven.continuum.xmlrpc.project.Project</a-hint>
+      <a-hint>org.apache.maven.continuum.xmlrpc.project.ProjectSummary</a-hint>
       <b-hint>org.apache.maven.continuum.model.project.Project</b-hint>
     </field>
   </mapping>
+
+  <mapping>
+    <class-a>org.apache.continuum.xmlrpc.utils.BuildTrigger</class-a>
+    <class-b>org.apache.continuum.utils.build.BuildTrigger</class-b>
+  </mapping>
+
+  <mapping>
+    <class-a>org.apache.maven.continuum.xmlrpc.project.ReleaseListenerSummary</class-a>
+    <class-b>org.apache.continuum.model.release.ReleaseListenerSummary</class-b>
+  </mapping>
+  
+  <mapping>
+    <class-a>org.apache.maven.continuum.xmlrpc.project.BuildAgentConfiguration</class-a>
+    <class-b>org.apache.continuum.configuration.BuildAgentConfiguration</class-b>
+  </mapping>
+
+  <mapping>
+    <class-a>org.apache.maven.continuum.xmlrpc.project.BuildAgentGroupConfiguration</class-a>
+    <class-b>org.apache.continuum.configuration.BuildAgentGroupConfiguration</class-b>
+    <field>
+      <a>buildAgents</a>
+      <b>buildAgents</b>
+      <a-hint>org.apache.maven.continuum.xmlrpc.project.BuildAgentConfiguration</a-hint>
+      <b-hint>org.apache.continuum.configuration.BuildAgentConfiguration</b-hint>
+    </field>
+  </mapping>
 </mappings>
diff --git a/continuum-xmlrpc/continuum-xmlrpc-server/src/test/java/org/apache/continuum/xmlrpc/server/ContinuumServiceImplStub.java b/continuum-xmlrpc/continuum-xmlrpc-server/src/test/java/org/apache/continuum/xmlrpc/server/ContinuumServiceImplStub.java
new file mode 100644
index 0000000..ac90b02
--- /dev/null
+++ b/continuum-xmlrpc/continuum-xmlrpc-server/src/test/java/org/apache/continuum/xmlrpc/server/ContinuumServiceImplStub.java
@@ -0,0 +1,50 @@
+package org.apache.continuum.xmlrpc.server;
+
+/*
+ * 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 org.apache.continuum.utils.build.BuildTrigger;
+import org.apache.maven.continuum.ContinuumException;
+import org.apache.maven.continuum.profile.ProfileException;
+import org.apache.maven.continuum.xmlrpc.project.BuildDefinition;
+import org.apache.maven.continuum.xmlrpc.server.ContinuumServiceImpl;
+import org.codehaus.plexus.redback.authorization.AuthorizationException;
+
+public class ContinuumServiceImplStub
+    extends ContinuumServiceImpl
+{
+    @Override
+    protected boolean isAuthorized( String role, String resource, boolean requiredResource )
+        throws AuthorizationException
+    {
+        return true;
+    }
+
+    protected void buildProjectWithBuildDefinition( int projectId, int buildDefinitionId, BuildTrigger buildTrigger )
+    {
+        // do nothing
+    }
+
+    public org.apache.maven.continuum.model.project.BuildDefinition getBuildDefinition( BuildDefinition buildDef,
+                                                                                        org.apache.maven.continuum.model.project.BuildDefinition buildDefinition )
+        throws ContinuumException
+    {
+        return populateBuildDefinition( buildDef, buildDefinition );
+    }
+}
diff --git a/continuum-xmlrpc/continuum-xmlrpc-server/src/test/java/org/apache/continuum/xmlrpc/server/ContinuumServiceImplTest.java b/continuum-xmlrpc/continuum-xmlrpc-server/src/test/java/org/apache/continuum/xmlrpc/server/ContinuumServiceImplTest.java
new file mode 100644
index 0000000..0e5aadd
--- /dev/null
+++ b/continuum-xmlrpc/continuum-xmlrpc-server/src/test/java/org/apache/continuum/xmlrpc/server/ContinuumServiceImplTest.java
@@ -0,0 +1,594 @@
+package org.apache.continuum.xmlrpc.server;
+
+/*
+ * 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 org.apache.continuum.builder.distributed.manager.DistributedBuildManager;
+import org.apache.continuum.configuration.BuildAgentGroupConfiguration;
+import org.apache.continuum.model.project.ProjectScmRoot;
+import org.apache.continuum.release.distributed.manager.DistributedReleaseManager;
+import org.apache.continuum.xmlrpc.utils.BuildTrigger;
+import org.apache.maven.continuum.Continuum;
+import org.apache.maven.continuum.ContinuumException;
+import org.apache.maven.continuum.configuration.ConfigurationService;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.project.ProjectGroup;
+import org.apache.maven.continuum.release.ContinuumReleaseManager;
+import org.apache.maven.continuum.xmlrpc.project.BuildAgentConfiguration;
+import org.apache.maven.continuum.xmlrpc.project.BuildDefinition;
+import org.apache.maven.continuum.xmlrpc.project.ContinuumProjectState;
+import org.apache.maven.continuum.xmlrpc.project.ProjectGroupSummary;
+import org.apache.maven.continuum.xmlrpc.project.ReleaseListenerSummary;
+import org.apache.maven.continuum.xmlrpc.server.ContinuumServiceImpl;
+import org.apache.maven.continuum.xmlrpc.system.Installation;
+import org.codehaus.plexus.redback.role.RoleManager;
+import org.codehaus.plexus.spring.PlexusInSpringTestCase;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.integration.junit3.JUnit3Mockery;
+import org.jmock.lib.legacy.ClassImposteriser;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ContinuumServiceImplTest
+    extends PlexusInSpringTestCase
+{
+    private ContinuumServiceImpl continuumService;
+
+    private Mockery context;
+
+    private Continuum continuum;
+
+    private DistributedReleaseManager distributedReleaseManager;
+
+    private ContinuumReleaseManager releaseManager;
+
+    private DistributedBuildManager distributedBuildManager;
+
+    private ConfigurationService configurationService;
+
+    private Project project;
+
+    private Map<String, Object> params;
+
+    private RoleManager roleManager;
+
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        context = new JUnit3Mockery();
+        context.setImposteriser( ClassImposteriser.INSTANCE );
+
+        distributedReleaseManager = context.mock( DistributedReleaseManager.class );
+        releaseManager = context.mock( ContinuumReleaseManager.class );
+        configurationService = context.mock( ConfigurationService.class );
+        distributedBuildManager = context.mock( DistributedBuildManager.class );
+        roleManager = context.mock( RoleManager.class );
+
+        continuumService = new ContinuumServiceImplStub();
+        continuum = context.mock( Continuum.class );
+        continuumService.setContinuum( continuum );
+        continuumService.setDistributedBuildManager( distributedBuildManager );
+        continuumService.setRoleManager( roleManager );
+
+        ProjectGroup projectGroup = new ProjectGroup();
+        projectGroup.setName( "test-group" );
+
+        project = new Project();
+        project.setId( 1 );
+        project.setProjectGroup( projectGroup );
+        project.setVersion( "1.0-SNAPSHOT" );
+        project.setArtifactId( "continuum-test" );
+        project.setScmUrl( "scm:svn:http://svn.test.org/repository/project" );
+    }
+
+    public void testGetReleasePluginParameters()
+        throws Exception
+    {
+        params = new HashMap<String, Object>();
+        params.put( "scm-tag", "" );
+        params.put( "scm-tagbase", "" );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( continuum ).getProject( 1 );
+                will( returnValue( project ) );
+
+                one( continuum ).getConfiguration();
+                will( returnValue( configurationService ) );
+
+                one( configurationService ).isDistributedBuildEnabled();
+                will( returnValue( true ) );
+
+                one( continuum ).getDistributedReleaseManager();
+                will( returnValue( distributedReleaseManager ) );
+
+                one( distributedReleaseManager ).getReleasePluginParameters( 1, "pom.xml" );
+                will( returnValue( params ) );
+
+                one( continuum ).getReleaseManager();
+                will( returnValue( releaseManager ) );
+
+                one( releaseManager ).sanitizeTagName( "scm:svn:http://svn.test.org/repository/project",
+                                                       "continuum-test-1.0" );
+            }
+        } );
+
+        Map<String, Object> releaseParams = continuumService.getReleasePluginParameters( 1 );
+        assertEquals( "continuum-test-1.0", releaseParams.get( "scm-tag" ) );
+        assertEquals( "http://svn.test.org/repository/project/tags", releaseParams.get( "scm-tagbase" ) );
+
+        context.assertIsSatisfied();
+    }
+
+    public void testGetListenerWithDistributedBuilds()
+        throws Exception
+    {
+        final Map map = getListenerMap();
+
+        context.checking( new Expectations()
+        {
+            {
+                one( continuum ).getProject( 1 );
+                will( returnValue( project ) );
+
+                one( continuum ).getConfiguration();
+                will( returnValue( configurationService ) );
+
+                one( configurationService ).isDistributedBuildEnabled();
+                will( returnValue( true ) );
+
+                one( continuum ).getDistributedReleaseManager();
+                will( returnValue( distributedReleaseManager ) );
+
+                one( distributedReleaseManager ).getListener( "releaseId-1" );
+                will( returnValue( map ) );
+            }
+        } );
+
+        ReleaseListenerSummary summary = continuumService.getListener( 1, "releaseId-1" );
+        assertNotNull( summary );
+        assertEquals( "incomplete-phase", summary.getPhases().get( 0 ) );
+        assertEquals( "completed-phase", summary.getCompletedPhases().get( 0 ) );
+    }
+
+    public void testPopulateBuildDefinition()
+        throws Exception
+    {
+        ContinuumServiceImplStub continuumServiceStub = new ContinuumServiceImplStub();
+
+        BuildDefinition buildDef = createBuildDefinition();
+        org.apache.maven.continuum.model.project.BuildDefinition buildDefinition =
+            new org.apache.maven.continuum.model.project.BuildDefinition();
+
+        buildDefinition = continuumServiceStub.getBuildDefinition( buildDef, buildDefinition );
+
+        assertEquals( buildDef.getArguments(), buildDefinition.getArguments() );
+        assertEquals( buildDef.getBuildFile(), buildDefinition.getBuildFile() );
+        assertEquals( buildDef.getDescription(), buildDefinition.getDescription() );
+        assertEquals( buildDef.getGoals(), buildDefinition.getGoals() );
+        assertEquals( buildDef.getType(), buildDefinition.getType() );
+        assertEquals( buildDef.isAlwaysBuild(), buildDefinition.isAlwaysBuild() );
+        assertEquals( buildDef.isBuildFresh(), buildDefinition.isBuildFresh() );
+        assertEquals( buildDef.isDefaultForProject(), buildDefinition.isDefaultForProject() );
+    }
+
+    public void testBuildProjectWithBuildTrigger()
+        throws Exception
+    {
+        final ProjectGroup projectGroup = new ProjectGroup();
+        projectGroup.setName( "test-group" );
+
+        BuildTrigger buildTrigger = new BuildTrigger();
+        buildTrigger.setTrigger( ContinuumProjectState.TRIGGER_FORCED );
+        buildTrigger.setTriggeredBy( "username" );
+
+        BuildDefinition buildDef = createBuildDefinition();
+        buildDef.setId( 1 );
+
+        context.checking( new Expectations()
+        {
+            {
+                atLeast( 1 ).of( continuum ).getProject( project.getId() );
+                will( returnValue( project ) );
+
+                atLeast( 1 ).of( continuum ).getProjectGroupByProjectId( project.getId() );
+                will( returnValue( projectGroup ) );
+            }
+        } );
+
+        int result = continuumService.buildProject( project.getId(), buildDef.getId(), buildTrigger );
+        assertEquals( 0, result );
+
+    }
+
+    public void testGetProjectScmRootByProjectGroup()
+        throws Exception
+    {
+        final ProjectGroup projectGroup = new ProjectGroup();
+        projectGroup.setName( "test-group" );
+        projectGroup.setId( 1 );
+
+        final List<ProjectScmRoot> scmRoots = new ArrayList<ProjectScmRoot>();
+
+        ProjectScmRoot scmRoot = new ProjectScmRoot();
+        scmRoot.setState( 1 );
+        scmRoot.setOldState( 3 );
+        scmRoot.setScmRootAddress( "address1" );
+        scmRoot.setProjectGroup( projectGroup );
+        scmRoots.add( scmRoot );
+
+        scmRoot = new ProjectScmRoot();
+        scmRoot.setState( 2 );
+        scmRoot.setOldState( 4 );
+        scmRoot.setScmRootAddress( "address2" );
+        scmRoot.setProjectGroup( projectGroup );
+        scmRoots.add( scmRoot );
+
+        context.checking( new Expectations()
+        {
+            {
+                atLeast( 1 ).of( continuum ).getProjectScmRootByProjectGroup( projectGroup.getId() );
+                will( returnValue( scmRoots ) );
+
+                atLeast( 1 ).of( continuum ).getProjectGroup( projectGroup.getId() );
+                will( returnValue( projectGroup ) );
+            }
+        } );
+
+        List<org.apache.maven.continuum.xmlrpc.project.ProjectScmRoot> projectScmRoots =
+            continuumService.getProjectScmRootByProjectGroup( projectGroup.getId() );
+        assertEquals( 2, projectScmRoots.size() );
+        assertEquals( 1, projectScmRoots.get( 0 ).getState() );
+        assertEquals( 2, projectScmRoots.get( 1 ).getState() );
+    }
+
+    public void testGetProjectScmRootByProject()
+        throws Exception
+    {
+        final ProjectGroup projectGroup = new ProjectGroupStub();
+        projectGroup.setName( "test-group" );
+        projectGroup.setId( 1 );
+
+        final int projectId = 1;
+
+        final ProjectScmRoot scmRoot = new ProjectScmRoot();
+        scmRoot.setState( 1 );
+        scmRoot.setOldState( 3 );
+        scmRoot.setScmRootAddress( "address1" );
+        scmRoot.setProjectGroup( projectGroup );
+
+        context.checking( new Expectations()
+        {
+            {
+                atLeast( 1 ).of( continuum ).getProjectScmRootByProject( projectId );
+                will( returnValue( scmRoot ) );
+            }
+        } );
+
+        org.apache.maven.continuum.xmlrpc.project.ProjectScmRoot projectScmRoot =
+            continuumService.getProjectScmRootByProject( projectId );
+        assertNotNull( projectScmRoot );
+        assertEquals( 1, projectScmRoot.getState() );
+        assertEquals( 3, projectScmRoot.getOldState() );
+        assertEquals( "address1", projectScmRoot.getScmRootAddress() );
+    }
+
+    public void testGetBuildAgentUrl()
+        throws Exception
+    {
+        context.checking( new Expectations()
+        {
+            {
+                one( continuum ).getConfiguration();
+                will( returnValue( configurationService ) );
+
+                one( configurationService ).isDistributedBuildEnabled();
+                will( returnValue( true ) );
+
+                one( distributedBuildManager ).getBuildAgentUrl( 1, 1 );
+                will( returnValue( "http://localhost:8181/continuum-buildagent/xmlrpc" ) );
+            }
+        } );
+        String buildAgentUrl = continuumService.getBuildAgentUrl( 1, 1 );
+        assertEquals( "http://localhost:8181/continuum-buildagent/xmlrpc", buildAgentUrl );
+
+        context.assertIsSatisfied();
+    }
+
+    public void testGetBuildAgentUrlNotSupported()
+        throws Exception
+    {
+        context.checking( new Expectations()
+        {
+            {
+                one( continuum ).getConfiguration();
+                will( returnValue( configurationService ) );
+
+                one( configurationService ).isDistributedBuildEnabled();
+                will( returnValue( false ) );
+            }
+        } );
+
+        try
+        {
+            continuumService.getBuildAgentUrl( 1, 1 );
+            fail( "ContinuumException is expected to occur here." );
+        }
+        catch ( ContinuumException e )
+        {
+            //pass
+        }
+        context.assertIsSatisfied();
+    }
+
+    public void testGetNonExistingBuildAgentGroup()
+        throws Exception
+    {
+        context.checking( new Expectations()
+        {
+            {
+                one( continuum ).getConfiguration();
+                will( returnValue( configurationService ) );
+
+                one( configurationService ).getBuildAgentGroup( "Agent Group Name" );
+                will( returnValue( null ) );
+            }
+        } );
+        int result = continuumService.removeBuildAgentGroup( "Agent Group Name" );
+        assertEquals( 0, result );
+
+        context.assertIsSatisfied();
+    }
+
+    public void testRemoveNonExistingBuildAgentGroup()
+        throws Exception
+    {
+        context.checking( new Expectations()
+        {
+            {
+                one( continuum ).getConfiguration();
+                will( returnValue( configurationService ) );
+
+                one( configurationService ).getBuildAgentGroup( "Agent Group Name" );
+                will( returnValue( null ) );
+
+                never( configurationService ).removeBuildAgentGroup( with( any(
+                    BuildAgentGroupConfiguration.class ) ) );
+            }
+        } );
+
+        continuumService.removeBuildAgentGroup( "Agent Group Name" );
+        context.assertIsSatisfied();
+    }
+
+    public void testGetBuildAgentsWithInstallations()
+        throws Exception
+    {
+        final List<org.apache.continuum.configuration.BuildAgentConfiguration> buildAgents =
+            new ArrayList<org.apache.continuum.configuration.BuildAgentConfiguration>();
+
+        org.apache.continuum.configuration.BuildAgentConfiguration buildAgent =
+            new org.apache.continuum.configuration.BuildAgentConfiguration();
+        buildAgent.setUrl( "http://localhost:8080/xmlrpc" );
+        buildAgent.setEnabled( true );
+        buildAgents.add( buildAgent );
+
+        org.apache.continuum.configuration.BuildAgentConfiguration buildAgent2 =
+            new org.apache.continuum.configuration.BuildAgentConfiguration();
+        buildAgent2.setUrl( "http://localhost:8181/xmlrpc" );
+        buildAgent2.setEnabled( false );
+        buildAgents.add( buildAgent2 );
+
+        final List<org.apache.maven.continuum.model.system.Installation> buildAgentInstallations =
+            new ArrayList<org.apache.maven.continuum.model.system.Installation>();
+
+        org.apache.maven.continuum.model.system.Installation buildAgentInstallation =
+            new org.apache.maven.continuum.model.system.Installation();
+        buildAgentInstallation.setInstallationId( 1 );
+        buildAgentInstallation.setName( "JDK 6" );
+        buildAgentInstallation.setType( "jdk" );
+        buildAgentInstallation.setVarName( "JAVA_HOME" );
+        buildAgentInstallation.setVarValue( "/opt/java" );
+        buildAgentInstallations.add( buildAgentInstallation );
+
+        context.checking( new Expectations()
+        {
+            {
+                one( continuum ).getConfiguration();
+                will( returnValue( configurationService ) );
+
+                one( configurationService ).getBuildAgents();
+                will( returnValue( buildAgents ) );
+
+                one( distributedBuildManager ).getBuildAgentPlatform( "http://localhost:8080/xmlrpc" );
+                will( returnValue( "Linux" ) );
+
+                one( distributedBuildManager ).getAvailableInstallations( "http://localhost:8080/xmlrpc" );
+                will( returnValue( buildAgentInstallations ) );
+            }
+        } );
+        List<BuildAgentConfiguration> agents = continuumService.getBuildAgentsWithInstallations();
+        assertEquals( 1, agents.size() );
+        BuildAgentConfiguration agent = agents.get( 0 );
+        assertEquals( "http://localhost:8080/xmlrpc", agent.getUrl() );
+        assertEquals( "Linux", agent.getPlatform() );
+        assertEquals( 1, agent.getInstallations().size() );
+
+        context.assertIsSatisfied();
+    }
+
+    public void testAddProjectGroupWithPunctuation()
+        throws Exception
+    {
+        final String name = "Test :: Group Name (with punctuation)";
+        final String groupId = "com.example.long-group-id";
+        final String description = "Description";
+
+        context.checking( new Expectations()
+        {
+            {
+                ProjectGroup group = createProjectGroup( name, groupId, description );
+                one( continuum ).addProjectGroup( group );
+
+                group = createProjectGroup( name, groupId, description );
+                one( continuum ).getProjectGroupByGroupId( groupId );
+                will( returnValue( group ) );
+            }
+        } );
+
+        ProjectGroupSummary group = continuumService.addProjectGroup( name, groupId, description );
+        assertEquals( name, group.getName() );
+        assertEquals( groupId, group.getGroupId() );
+        assertEquals( description, group.getDescription() );
+
+        context.assertIsSatisfied();
+    }
+
+    public void testEditProjectGroupWithPunctuation()
+        throws Exception
+    {
+        final String newName = "Test :: Group Name (with punctuation)";
+        final String newGroupId = "com.example.long-group-id";
+        final String newDescription = "Description";
+        final int projectGroupId = 1;
+
+        context.checking( new Expectations()
+        {
+            {
+                ProjectGroup group = createProjectGroup( "name", "groupId", "description" );
+
+                one( continuum ).addProjectGroup( group );
+
+                group = createProjectGroup( projectGroupId );
+                one( continuum ).getProjectGroupByGroupId( "groupId" );
+                will( returnValue( group ) );
+
+                one( continuum ).getProjectGroupWithProjects( projectGroupId );
+                will( returnValue( group ) );
+
+                for ( String role : Arrays.asList( "project-administrator", "project-developer", "project-user" ) )
+                {
+                    one( roleManager ).updateRole( role, "name", newName );
+                }
+
+                ProjectGroup newProjectGroup = createProjectGroup( projectGroupId, newName, newGroupId,
+                                                                   newDescription );
+                one( continuum ).updateProjectGroup( newProjectGroup );
+
+                exactly( 3 ).of( continuum ).getProjectGroup( projectGroupId );
+                onConsecutiveCalls( returnValue( group ), returnValue( group ), returnValue( newProjectGroup ) );
+            }
+        } );
+
+        ProjectGroupSummary group = continuumService.addProjectGroup( "name", "groupId", "description" );
+        group.setName( newName );
+        group.setGroupId( newGroupId );
+        group.setDescription( newDescription );
+
+        continuumService.updateProjectGroup( group );
+
+        context.assertIsSatisfied();
+    }
+
+    public void testInstallationEnvironmentVariableWithOtherOptions()
+        throws ContinuumException
+    {
+        context.checking( new Expectations()
+        {
+            {
+                one( continuum ).getInstallationService();
+            }
+        } );
+
+        Installation installation = new Installation();
+        installation.setName( "name" );
+        installation.setType( "envvar" );
+        installation.setVarName( "JAVA_OPTS" );
+        installation.setVarValue( "-XX:+CompressedOops" );
+
+        continuumService.addInstallation( installation );
+
+        context.assertIsSatisfied();
+    }
+
+    private static ProjectGroup createProjectGroup( String name, String groupId, String description )
+    {
+        ProjectGroup group = new ProjectGroup();
+        group.setName( name );
+        group.setGroupId( groupId );
+        group.setDescription( description );
+        return group;
+    }
+
+    private static ProjectGroup createProjectGroup( int projectGroupId, String name, String groupId,
+                                                    String description )
+    {
+        ProjectGroup group = createProjectGroup( name, groupId, description );
+        group.setId( projectGroupId );
+        return group;
+    }
+
+    private static ProjectGroup createProjectGroup( int projectGroupId )
+    {
+        return createProjectGroup( projectGroupId, "name", "groupId", "description" );
+    }
+
+    private BuildDefinition createBuildDefinition()
+    {
+        BuildDefinition buildDef = new BuildDefinition();
+        buildDef.setArguments( "--batch-mode -P!dev" );
+        buildDef.setBuildFile( "pom.xml" );
+        buildDef.setType( "maven2" );
+        buildDef.setBuildFresh( false );
+        buildDef.setAlwaysBuild( true );
+        buildDef.setDefaultForProject( true );
+        buildDef.setGoals( "clean install" );
+        buildDef.setDescription( "Test Build Definition" );
+
+        return buildDef;
+    }
+
+    private Map<String, Object> getListenerMap()
+    {
+        Map<String, Object> map = new HashMap<String, Object>();
+
+        map.put( "release-phases", Arrays.asList( "incomplete-phase" ) );
+        map.put( "completed-release-phases", Arrays.asList( "completed-phase" ) );
+        return map;
+    }
+
+    public class ProjectGroupStub
+        extends ProjectGroup
+    {
+        @Override
+        public List<Project> getProjects()
+        {
+            throw new RuntimeException( "Can't call getProjects as it will throw JDODetachedFieldAccessException" );
+        }
+    }
+}
diff --git a/continuum-xmlrpc/pom.xml b/continuum-xmlrpc/pom.xml
index 067969a..ada922d 100644
--- a/continuum-xmlrpc/pom.xml
+++ b/continuum-xmlrpc/pom.xml
@@ -1,27 +1,28 @@
 <?xml version='1.0' encoding='UTF-8'?>
+
 <!--
-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.
--->
+  ~ 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.
+  -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <artifactId>continuum</artifactId>
     <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
+    <version>1.4.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>continuum-xmlrpc</artifactId>
@@ -29,8 +30,8 @@
   <packaging>pom</packaging>
   <modules>
     <module>continuum-xmlrpc-api</module>
-    <module>continuum-xmlrpc-backup</module>
     <module>continuum-xmlrpc-client</module>
+    <module>continuum-xmlrpc-backup</module>
     <module>continuum-xmlrpc-server</module>
   </modules>
 </project>
diff --git a/design/checking-out-process.dia b/design/checking-out-process.dia
deleted file mode 100644
index 2ca03b7..0000000
--- a/design/checking-out-process.dia
+++ /dev/null
Binary files differ
diff --git a/design/continuum.zuml b/design/continuum.zuml
deleted file mode 100644
index b124c4e..0000000
--- a/design/continuum.zuml
+++ /dev/null
Binary files differ
diff --git a/design/notes.txt b/design/notes.txt
deleted file mode 100644
index ce4e221..0000000
--- a/design/notes.txt
+++ /dev/null
@@ -1,104 +0,0 @@
-m2:
-http://svn.apache.org/viewcvs.cgi/*checkout*/maven/wagon/trunk/wagon-provider-api/pom.xml?rev=169925&content-type=text%2Fplain
-
-Get these into JIRA
-
-o need to check if a project already exists
-
-o check out the release documentation, it would be good to tell users what
-  they need to be installed in order to use the various builders
-
-x deploy/release all components i've modified
-  - plexus-i18n
-  - plexus-action
-  - plexus-formica
-  - plexus-formica-web
-  - plexus-summit  
-
-x hookup scm validator
-x trigger the build from the summary
-x i18n the delete message
-x test update
-x need the content generator to be used in the view
-x separate add form for m1/m2 from the display and update
-  the add form should have the POM and goals/phase
-x formica needs to be able to call methods with parameters instead of using
-  a target object
-
-      add  / update / view / delete
------------------------------------
-m1    ok     ok       ok     ok
------------------------------------
-m2    ok     ok       ok     ok
------------------------------------
-ant   ok     ok       ok     ok
------------------------------------
-shell ok     ok       ok     ok
------------------------------------
-
-NOTE: delete only works when projects are added via the
-web interface. projects added to the continuum via xmlrpc
-can't be deleted.
-
----
-
-alpha-2
-
-o fix the layout selection so that the menu doesn't show up in the login
-
-o need a way in summit to map an url to a page + any parameters required:
-  i want to set the default page to continuumProject.form?mode=summary, but
-  you can't set a target with parameters.
-
-o properties files for localization are horrible in order to easily
-  make language packs we need a tool to help show the keys for the target
-  language that need values.
-
-o move the configuration of summit into the webapp components.xml so that I 
-  can control the default view and error page better
-  
-o stackable validators
-
-o for complex validations like the scm validator we may want a better error
-  out put mechanism. or at least make the error output configurable because
-  lots of things could be wrong. need to return a i18n key for the given 
-  error message. this is the only way that you can get a meaningful message
-  back from validation. One per validator doesn't cut it.
-
-o need to make a paging mechanism, things like the number of builds adds
-  up pretty quickly.
-
-o start/stop scripts and supervise integration. it has to be easy
-  for users to start and stop
-
-o debug mode that spits out sample urls to use for testing
-
-o whip up some quick tests using maxq
-
-o when the build fails completely the errors are not captured in the
-  standard output
-
-o when the addition of project fails by passing in a POM the user must
-  be given details of the error so that they can fix the POM.
-
-o need to account for the difference between required, and validation
-  though with stackable validators that should be possible.
-
-o take a top-level POM (m1/m2) and pull in the whole group of projects
-  and then walk over the checked out directory and collect all the POMs.
-  In m2 this is easy because we can look at modules, but in m1 we need
-  to be aware of test POMs. This would be extremely convenient.
-
-o need to be able to configure notifications
-
-o add developer list to the continuum project so that the developer
-  who broke the build can be notified and tracked
-
-o i would like to be able to develop components and have the application
-  pick them up from their target directory. so artifact enable the app server
-  and teach it about the unified source directory.
-  
-  right now i have a little script that creates the necessary symlinks to the
-  appropriate directories but it would be nice to have something a little more
-  elegant then that. couple that with some dynamic JAR reloading and that
-  would make development much quicker.
diff --git a/design/old-white-site/addAntProject.html b/design/old-white-site/addAntProject.html
deleted file mode 100644
index 8c2d4c5..0000000
--- a/design/old-white-site/addAntProject.html
+++ /dev/null
@@ -1,181 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-  </div>
-</td>
-<td>
-  <div id="bodycol">
-    <div class="app">
-      <div id="axial" class="h3">
-        <h3>Add Ant Project</h3>
-
-        <form method="post" action="viewProject.html">
-          <input type="hidden" name="fid" value="antProject"/>
-
-          <input type="hidden" name="action" value="addEntity"/>
-          <input type="hidden" name="view" value="Summary.vm"/>
-          <input type="hidden" name="id" value="$id"/>
-
-          <div class="axial">
-            <table border="1" cellspacing="2" cellpadding="3" width="100%">
-              <tr>
-
-                <th>Project Name</th>
-
-
-                <td>
-                  <input type="text" name="project.name" value="" size="40"/>
-
-                  <p>
-                    Enter the project name <font color="red"><b></b></font>
-                  </p>
-                </td>
-              </tr>
-              <tr>
-                <th>Version</th>
-
-
-                <td>
-                  <input type="text" name="project.version" value="" size="40"/>
-
-                  <p>
-
-                    Enter the version of the project <font color="red"><b></b></font>
-                  </p>
-                </td>
-              </tr>
-
-              <tr>
-                <th>Scm Url</th>
-
-
-                <td>
-                  <input type="text" name="projectScmUrl" value="" size="40"/>
-
-                  <p>
-                    Enter the <a href="http://maven.apache.org/reference/plugins/scm/scmurl.html">Maven SCM URL</a>
-                    <font color="red">
-                      <b></b></font>
-
-                  </p>
-                </td>
-              </tr>
-            </table>
-            <div class="functnbar3">
-              <input type="submit" value="Submit"/>
-            </div>
-          </div>
-        </form>
-
-      </div>
-    </div>
-
-  </div></td>
-</tr>
-</tbody>
-</table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/addBuildDef.html b/design/old-white-site/addBuildDef.html
deleted file mode 100644
index d4f72fb..0000000
--- a/design/old-white-site/addBuildDef.html
+++ /dev/null
@@ -1,206 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-    <div style="margin-top: 5em; color: #555; border: 1px dashed black; padding: 1em;">
-      <p>Notes:</p>
-      <ul>
-        <li>POM filename is replaced by build filename for Ant, script name for shell</li>
-        <li>Goals replaced by targets for Ant, ommitted for shell</li>
-      </ul>
-    </div>
-  </div>
-</td>
-<td>
-  <div id="bodycol">
-    <div class="app">
-      <div id="axial" class="h3">
-        <h3>Add Build Definition</h3>
-
-        <form method="post" action="viewProject.html">
-          <input type="hidden" name="fid" value="antProject"/>
-
-          <input type="hidden" name="action" value="addEntity"/>
-          <input type="hidden" name="view" value="Summary.vm"/>
-          <input type="hidden" name="id" value="$id"/>
-
-          <div class="axial">
-            <table border="1" cellspacing="2" cellpadding="3" width="100%">
-              <tr>
-                <th>POM filename</th>
-
-
-                <td>
-                  <input type="text" name="project.executable" value="build.xml" size="40"/>
-
-                  <p>
-                    Relative path of the POM file <font color="red"><b></b></font>
-                  </p>
-                </td>
-              </tr>
-              <tr>
-                <th>Goals</th>
-
-
-                <td>
-                  <input type="text" name="project.targets" value="clean:clean install" size="40"/>
-
-                  <p>
-                    Enter one or more goals - leave empty to use the default <font color="red">
-                    <b></b></font>
-                  </p>
-                </td>
-              </tr>
-              <tr>
-                <th>Arguments</th>
-
-
-                <td>
-                  <input type="text" name="project.targets" value="" size="40"/>
-
-                  <p>
-                    Enter one or more command line arguments <font color="red"><b></b></font>
-                  </p>
-                </td>
-              </tr>
-              <tr>
-                <th>Profile</th>
-
-
-                <td>
-                  <select>
-                    <option selected="selected">Maven 2.0 Default</option>
-                    <option>JDK 1.3, Clean checkout</option>
-                  </select>
-                </td>
-              </tr>
-              <tr>
-                <th>Schedule</th>
-
-
-                <td>
-                  <select>
-                    <option selected="selected">Weekly</option>
-                    <option>Hourly</option>
-                    <option>Blue moon</option>
-                  </select>
-                </td>
-              </tr>
-            </table>
-            <div class="functnbar3">
-              <input type="submit" value="Submit"/>
-            </div>
-          </div>
-        </form>
-
-      </div>
-    </div>
-
-  </div></td>
-</tr>
-</tbody>
-</table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/addCruiseControlProject.html b/design/old-white-site/addCruiseControlProject.html
deleted file mode 100644
index 401d1a7..0000000
--- a/design/old-white-site/addCruiseControlProject.html
+++ /dev/null
@@ -1,176 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-  </div>
-</td>
-<td>
-  <div id="bodycol">
-    <div class="app">
-      <div id="axial" class="h3">
-        <h3>Import Cruise Control Project</h3>
-
-        <form method="post" action="viewGroup.html">
-          <input type="hidden" name="fid" value="addMavenTwoProject"/>
-
-          <input type="hidden" name="action" value="addMavenTwoProject"/>
-          <input type="hidden" name="view" value="Summary.vm"/>
-          <input type="hidden" name="id" value="$id"/>
-
-          <div class="axial">
-            <table border="1" cellspacing="2" cellpadding="3" width="100%">
-              <tr>
-                <th>
-                  <input type="radio" checked="checked"/>
-                  URL
-                </th>
-
-
-                <td>
-                  <input type="text" name="m2PomUrl" value="" size="40"/>
-
-                  <p>
-                    Enter the URL of a Cruise Control configuration file <font color="red"><b></b></font>
-                  </p>
-                </td>
-              </tr>
-              <tr>
-                <td>&nbsp;</td>
-                <td>
-                  <strong>OR</strong>
-                </td>
-              </tr>
-              <tr>
-                <th>
-                  <input type="radio"/>
-                  Upload
-                </th>
-
-
-                <td>
-                  <input type="file" name="m2PomUrl" value="" size="40"/>
-
-                  <p>
-                    Enter the local filename of the Cruise Control configuration to upload <font color="red"><b></b>
-                  </font>
-                  </p>
-                </td>
-              </tr>
-            </table>
-            <div class="functnbar3">
-
-              <input type="submit" value="Submit"/>
-            </div>
-          </div>
-        </form>
-      </div>
-    </div>
-  </div>
-</td>
-</tr>
-</tbody>
-</table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/addDeveloper.html b/design/old-white-site/addDeveloper.html
deleted file mode 100644
index 74b33a1..0000000
--- a/design/old-white-site/addDeveloper.html
+++ /dev/null
@@ -1,177 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-  <td id="leftcol" width="30%">
-    <div id="navcolum">
-      <div id="projectmenu" class="toolgroup">
-        <div class="label">Continuum</div>
-
-        <div class="body">
-          <div><a href="index.html">Show Projects</a></div>
-
-          <div><a href="schedule.html">View Build Schedule</a></div>
-        </div>
-      </div>
-
-      <div id="projecttools" class="toolgroup">
-        <div class="label">Add Project</div>
-
-        <div class="body">
-          <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-          <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-          <div><a href="addAntProject.html">Ant Project</a></div>
-
-          <div><a href="addShellProject.html">Shell Project</a></div>
-        </div>
-      </div>
-
-      <div id="projectimport" class="toolgroup">
-        <div class="label">Import Project</div>
-
-        <div class="body">
-          <div>
-            <a href="addCruiseControlProject.html">CruiseControl</a>
-          </div>
-        </div>
-      </div>
-
-      <div style="margin-top: 5em; color: #555; border: 1px dashed black; padding: 1em;">
-        <p>Notes:</p>
-        <ul>
-          <li>This is just the developers relationship to the project</li>
-          <li>Name and email are edited in the user's profile</li>
-          <li>Continuum ID can be put into the POM using a property, but defaults to their SCM ID</li>
-          <li>Roles are also administered through the user profile</li>
-          <li>(evenisse) Can we have a upload field for upload a list of user instead of add them one by one? (brett)
-            Bulk upload is usually from a POM, what other sources are you suggesting that also provide their SCM and
-            Continuum ID? (evenisse) I thought that it will be useful for an adminitrator to upload some file like
-            users list (with/without all user infos), group list, mapping between users and groups. With this,
-            administrator will can setup continuum more quickly.</li>
-        </ul>
-      </div>
-
-    </div>
-  </td>
-  <td>
-    <div id="bodycol">
-      <div class="app">
-        <div id="axial" class="h3">
-          <h3>Add (Edit) Developer</h3>
-
-          <form method="post" action="viewProject.html">
-            <input type="hidden" name="fid" value="antProject"/>
-
-            <input type="hidden" name="action" value="addEntity"/>
-            <input type="hidden" name="view" value="Summary.vm"/>
-            <input type="hidden" name="id" value="$id"/>
-
-            <div class="axial">
-              <table border="1" cellspacing="2" cellpadding="3" width="100%">
-                <tr>
-
-                  <th>Username</th>
-
-
-                  <td>
-                    <input type="text" name="project.name" value="" size="40"/>
-
-                    <p>
-                      Enter the Continuum username
-                    </p>
-                  </td>
-                </tr>
-                <tr>
-                  <th>SCM ID</th>
-                  <td>
-                    <input type="text" name="project.version" value="" size="40"/>
-
-                    <p>
-                      Enter the user's ID in the SCM
-                    </p>
-                  </td>
-                </tr>
-              </table>
-              <div class="functnbar3">
-                <input type="submit" value="Submit"/>
-              </div>
-            </div>
-          </form>
-
-        </div>
-      </div>
-
-    </div></td>
-</tr>
-</tbody>
-</table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/addMaven1Project.html b/design/old-white-site/addMaven1Project.html
deleted file mode 100644
index b4e73d2..0000000
--- a/design/old-white-site/addMaven1Project.html
+++ /dev/null
@@ -1,175 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-  </div>
-</td>
-<td>
-  <div id="bodycol">
-    <div class="app">
-      <div id="axial" class="h3">
-        <h3>Add Maven 1.x Project</h3>
-
-        <form method="post" action="viewProject.html">
-          <input type="hidden" name="fid" value="addMavenTwoProject"/>
-
-          <input type="hidden" name="action" value="addMavenTwoProject"/>
-          <input type="hidden" name="view" value="Summary.vm"/>
-          <input type="hidden" name="id" value="$id"/>
-
-          <div class="axial">
-            <table border="1" cellspacing="2" cellpadding="3" width="100%">
-              <tr>
-                <th>
-                  <input type="radio" checked="checked"/>
-                  POM Url
-                </th>
-
-
-                <td>
-                  <input type="text" name="m1PomUrl" value="" size="40"/>
-
-                  <p>
-                    Enter the URL to the Maven 1 POM <font color="red"><b></b></font>
-                  </p>
-                </td>
-              </tr>
-              <tr>
-                <td>&nbsp;</td>
-                <td>
-                  <strong>OR</strong>
-                </td>
-              </tr>
-              <tr>
-                <th>
-                  <input type="radio"/>
-                  Upload POM
-                </th>
-
-
-                <td>
-                  <input type="file" name="m1PomUrl" value="" size="40"/>
-
-                  <p>
-                    Enter the local filename of the Maven 1 POM to upload <font color="red"><b></b></font>
-                  </p>
-                </td>
-              </tr>
-            </table>
-            <div class="functnbar3">
-
-              <input type="submit" value="Submit"/>
-            </div>
-          </div>
-        </form>
-      </div>
-    </div>
-  </div>
-</td>
-</tr>
-</tbody>
-</table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/addMaven2Project.html b/design/old-white-site/addMaven2Project.html
deleted file mode 100644
index 99f4d93..0000000
--- a/design/old-white-site/addMaven2Project.html
+++ /dev/null
@@ -1,175 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-  </div>
-</td>
-<td>
-  <div id="bodycol">
-    <div class="app">
-      <div id="axial" class="h3">
-        <h3>Add Maven 2.0+ Project</h3>
-
-        <form method="post" action="viewProject.html">
-          <input type="hidden" name="fid" value="addMavenTwoProject"/>
-
-          <input type="hidden" name="action" value="addMavenTwoProject"/>
-          <input type="hidden" name="view" value="Summary.vm"/>
-          <input type="hidden" name="id" value="$id"/>
-
-          <div class="axial">
-            <table border="1" cellspacing="2" cellpadding="3" width="100%">
-              <tr>
-                <th>
-                  <input type="radio" checked="checked"/>
-                  POM Url
-                </th>
-
-
-                <td>
-                  <input type="text" name="m2PomUrl" value="" size="40"/>
-
-                  <p>
-                    Enter the URL to the Maven 2 POM <font color="red"><b></b></font>
-                  </p>
-                </td>
-              </tr>
-              <tr>
-                <td>&nbsp;</td>
-                <td>
-                  <strong>OR</strong>
-                </td>
-              </tr>
-              <tr>
-                <th>
-                  <input type="radio"/>
-                  Upload POM
-                </th>
-
-
-                <td>
-                  <input type="file" name="m2PomUrl" value="" size="40"/>
-
-                  <p>
-                    Enter the local filename of the Maven 2 POM to upload <font color="red"><b></b></font>
-                  </p>
-                </td>
-              </tr>
-            </table>
-            <div class="functnbar3">
-
-              <input type="submit" value="Submit"/>
-            </div>
-          </div>
-        </form>
-      </div>
-    </div>
-  </div>
-</td>
-</tr>
-</tbody>
-</table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/addNotifier.html b/design/old-white-site/addNotifier.html
deleted file mode 100644
index 4ff3438..0000000
--- a/design/old-white-site/addNotifier.html
+++ /dev/null
@@ -1,254 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-    <div style="margin-top: 5em; color: #555; border: 1px dashed black; padding: 1em;">
-      <p>Notes:</p>
-      <ul>
-        <li>Should the IRC host be a dropdown, only configured from the admin interface? How does this correlate with
-          POMs?</li>
-        <li><!-- TODO:--> I would like to split this page into one edit per notifier type, and then put the type as a
-          drop down on the page where add is</li>
-      </ul>
-    </div>
-  </div>
-</td>
-<td>
-<div id="bodycol">
-<div class="app">
-<div id="axial" class="h3">
-<h3>Add (Edit) Notifier</h3>
-
-<form method="post" action="viewProject.html">
-<input type="hidden" name="fid" value="antProject"/>
-
-<input type="hidden" name="action" value="addEntity"/>
-<input type="hidden" name="view" value="Summary.vm"/>
-<input type="hidden" name="id" value="$id"/>
-
-<div class="axial">
-<table border="1" cellspacing="2" cellpadding="3" width="100%">
-<tr>
-
-  <th>Type</th>
-
-
-  <td>
-    <table>
-      <tr>
-        <td>
-          <input value="mail" name="type" type="radio" checked="checked"/>&nbsp;Mail
-        </td>
-        <td colspan="2">&nbsp;</td>
-      </tr>
-      <tr>
-        <td>
-          <input value="irc" name="type" type="radio"/>&nbsp;IRC
-        </td>
-        <td>
-          Host:
-          <input type="text" name="config" value="" size="40"/>
-        </td>
-        <td>
-          Port:
-          <input type="text" name="config" value="" size="5"/>
-        </td>
-      </tr>
-      <tr>
-        <td>
-          <input value="msn" name="type" type="radio"/>&nbsp;MSN
-        </td>
-        <td colspan="2">&nbsp;</td>
-      </tr>
-      <tr>
-        <td>
-          <input value="yahoo" name="type" type="radio"/>&nbsp;Yahoo
-        </td>
-        <td colspan="2">&nbsp;</td>
-      </tr>
-      <tr>
-        <td>
-          <input value="jabber" name="type" type="radio"/>&nbsp;Jabber
-        </td>
-        <td>
-          Host:
-          <input type="text" name="config" value="" size="40"/>
-        </td>
-        <td>
-          Port:
-          <input type="text" name="config" value="" size="5"/>
-        </td>
-      </tr>
-    </table>
-  </td>
-</tr>
-<tr>
-  <th>Recipients</th>
-  <td>
-    <table>
-      <tr>
-        <td><input value="all" name="recipient" type="radio" checked="checked"/>&nbsp;All Developers</td>
-        <td>&nbsp;</td>
-      </tr>
-      <tr>
-        <td>
-          <input value="developer" name="recipient" type="radio"/>&nbsp;Single Developer
-        </td>
-        <td>
-          <input type="text" name="config" value="" size="40"/>
-          <small>(Enter the developer's Continuum ID)</small>
-        </td>
-      </tr>
-      <tr>
-        <td>
-          <input value="role" name="recipient" type="radio"/>&nbsp;Developers with Role
-        </td>
-        <td>
-          <select>
-            <option selected="selected">Build Manager</option>
-            <option>Hippie</option>
-            <option>Cowboy</option>
-          </select>
-        </td>
-      </tr>
-      <tr>
-        <td>
-          <input value="single" name="recipient" type="radio"/>&nbsp;Single recipient
-        </td>
-        <td>
-          <input type="text" name="config" value="" size="40"/>
-          <small>(Enter the e-mail address, Jabber ID, etc. of the recipient)</small>
-        </td>
-      </tr>
-    </table>
-  </td>
-</tr>
-<tr>
-
-  <th>Events</th>
-
-
-  <td>
-    <input value="success" name="event" type="checkbox" checked="checked"/>&nbsp;Build Success
-    <input value="failure" name="event" type="checkbox" checked="checked"/>&nbsp;Build Failure
-    <input value="failure" name="event" type="checkbox" checked="checked"/>&nbsp;Build Error
-  </td>
-</tr>
-</table>
-<div class="functnbar3">
-  <input type="submit" value="Submit"/>
-</div>
-</div>
-</form>
-
-</div>
-</div>
-
-</div></td>
-</tr>
-</tbody>
-</table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/addShellProject.html b/design/old-white-site/addShellProject.html
deleted file mode 100644
index 8258cf3..0000000
--- a/design/old-white-site/addShellProject.html
+++ /dev/null
@@ -1,181 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-  </div>
-</td>
-<td>
-  <div id="bodycol">
-    <div class="app">
-      <div id="axial" class="h3">
-        <h3>Add Shell Project</h3>
-
-        <form method="post" action="viewProject.html">
-          <input type="hidden" name="fid" value="antProject"/>
-
-          <input type="hidden" name="action" value="addEntity"/>
-          <input type="hidden" name="view" value="Summary.vm"/>
-          <input type="hidden" name="id" value="$id"/>
-
-          <div class="axial">
-            <table border="1" cellspacing="2" cellpadding="3" width="100%">
-              <tr>
-
-                <th>Project Name</th>
-
-
-                <td>
-                  <input type="text" name="project.name" value="" size="40"/>
-
-                  <p>
-                    Enter the project name <font color="red"><b></b></font>
-                  </p>
-                </td>
-              </tr>
-              <tr>
-                <th>Version</th>
-
-
-                <td>
-                  <input type="text" name="project.version" value="" size="40"/>
-
-                  <p>
-
-                    Enter the version of the project <font color="red"><b></b></font>
-                  </p>
-                </td>
-              </tr>
-
-              <tr>
-                <th>Scm Url</th>
-
-
-                <td>
-                  <input type="text" name="projectScmUrl" value="" size="40"/>
-
-                  <p>
-                    Enter the <a href="http://maven.apache.org/reference/plugins/scm/scmurl.html">Maven SCM URL</a>
-                    <font color="red">
-                      <b></b></font>
-
-                  </p>
-                </td>
-              </tr>
-            </table>
-            <div class="functnbar3">
-              <input type="submit" value="Submit"/>
-            </div>
-          </div>
-        </form>
-
-      </div>
-    </div>
-
-  </div></td>
-</tr>
-</tbody>
-</table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/addUserNotifier.html b/design/old-white-site/addUserNotifier.html
deleted file mode 100644
index c1f8c0a..0000000
--- a/design/old-white-site/addUserNotifier.html
+++ /dev/null
@@ -1,211 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Logged in as: <b>Brett Porter</b> | <a href="userProfile.html">Profile</a> | <a href="login.html">Log out</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-    <div style="margin-top: 5em; color: #555; border: 1px dashed black; padding: 1em;">
-      <p>Notes:</p>
-      <ul>
-        <li>Should the IRC host be a dropdown, only configured from the admin interface? How does this correlate with
-          POMs?
-        </li>
-        <li><!-- TODO:--> I would like to split this page into one edit per notifier type, and then put the type as a
-          drop down on the page where add is - this would allow explicit setting of irc host/port/channel which is
-          clearer</li>
-      </ul>
-    </div>
-  </div>
-</td>
-<td>
-  <div id="bodycol">
-    <div class="app">
-      <div id="axial" class="h3">
-        <h3>Add (Edit) Notifier</h3>
-
-        <form method="post" action="viewProject.html">
-          <input type="hidden" name="fid" value="antProject"/>
-
-          <input type="hidden" name="action" value="addEntity"/>
-          <input type="hidden" name="view" value="Summary.vm"/>
-          <input type="hidden" name="id" value="$id"/>
-
-          <div class="axial">
-            <table border="1" cellspacing="2" cellpadding="3" width="100%">
-              <tr>
-
-                <th>Type</th>
-
-
-                <td>
-                  <table>
-                    <tr>
-                      <td>
-                        <input value="mail" name="type" type="radio" checked="checked"/>&nbsp;Mail
-                      </td>
-                      <td colspan="2">&nbsp;</td>
-                    </tr>
-                    <tr>
-                      <td>
-                        <input value="irc" name="type" type="radio"/>&nbsp;IRC
-                      </td>
-                      <td>
-                        Host:
-                        <input type="text" name="config" value="" size="40"/>
-                      </td>
-                      <td>
-                        Port:
-                        <input type="text" name="config" value="" size="5"/>
-                      </td>
-                    </tr>
-                    <tr>
-                      <td>
-                        <input value="msn" name="type" type="radio"/>&nbsp;MSN
-                      </td>
-                      <td colspan="2">&nbsp;</td>
-                    </tr>
-                    <tr>
-                      <td>
-                        <input value="yahoo" name="type" type="radio"/>&nbsp;Yahoo
-                      </td>
-                      <td colspan="2">&nbsp;</td>
-                    </tr>
-                    <tr>
-                      <td>
-                        <input value="jabber" name="type" type="radio"/>&nbsp;Jabber
-                      </td>
-                      <td>
-                        Host:
-                        <input type="text" name="config" value="" size="40"/>
-                      </td>
-                      <td>
-                        Port:
-                        <input type="text" name="config" value="" size="5"/>
-                      </td>
-                    </tr>
-                  </table>
-                </td>
-              </tr>
-              <tr>
-                <th>Address</th>
-                <td>
-                  <input type="text" name="config" value="" size="40"/>
-                  <small>(Enter the e-mail address, Jabber ID, IRC channel, etc. of the recipient)</small>
-                </td>
-              </tr>
-            </table>
-            <div class="functnbar3">
-              <input type="submit" value="Submit"/>
-            </div>
-          </div>
-        </form>
-
-      </div>
-    </div>
-
-  </div></td>
-</tr>
-</tbody>
-</table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/builds.html b/design/old-white-site/builds.html
deleted file mode 100644
index 650d26c..0000000
--- a/design/old-white-site/builds.html
+++ /dev/null
@@ -1,192 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-  </div>
-</td>
-<td>
-  <div id="bodycol">
-    <div class="app">
-
-      <div>
-        <p style="border-top: 1px solid transparent; border-bottom: 1px solid black;">
-          <a style="border: 1px solid black; padding-left: 1em; padding-right: 1em; text-decoration:none;"
-             href="viewProject.html">Info</a>
-          <b style="border: 1px solid black; padding-left: 1em; padding-right: 1em;">Builds</b>
-          <a style="border: 1px solid black; padding-left: 1em; padding-right: 1em; text-decoration:none;"
-             href="workingCopy.html">Working&nbsp;Copy</a>
-        </p>
-      </div>
-
-      <div id="axial" class="h3">
-        <h3>Build results for Default Plexus Container</h3>
-        <table border="1" cellspacing="2" cellpadding="3" width="100%">
-          <tr>
-            <th>Build #</th>
-            <th>End Time</th>
-            <th>State</th>
-            <th>&nbsp;</th>
-          </tr>
-          <tr class="b">
-            <td>&nbsp;</td>
-            <td>In progress</td>
-            <td>&nbsp;</td>
-            <td>
-              <a href="#">Cancel</a>
-            </td>
-          </tr>
-          <tr class="b">
-            <td>&nbsp;</td>
-            <td>Jul 28, 2005 3:40:40 PM</td>
-            <td><img src="continuum_files/icon_warning_sml.gif" alt="Error"/></td>
-            <td>
-              <a href="viewBuild.html">Details</a> | <a href="#">Delete</a>
-            </td>
-          </tr>
-          <tr class="a">
-            <td>2</td>
-            <td>Jul 23, 2005 3:55:56 PM</td>
-
-            <td><img src="continuum_files/icon_success_sml.gif" alt="Success"/></td>
-            <td>
-              <a href="viewBuild.html">Details</a> | <a href="#">Delete</a>
-            </td>
-          </tr>
-          <tr class="b">
-            <td>&nbsp;</td>
-            <td>Jul 21, 2005 3:51:23 PM</td>
-            <td><img src="continuum_files/icon_error_sml.gif" alt="Failed"/></td>
-
-            <td>
-              <a href="viewBuild.html">Details</a> | <a href="#">Delete</a>
-            </td>
-          </tr>
-          <tr class="a">
-            <td>&nbsp;</td>
-            <td>Jul 17, 2005 6:45:11 PM</td>
-            <td><img src="continuum_files/icon_warning_sml.gif" alt="Error"/></td>
-            <td>
-              <a href="viewBuild.html">Details</a> | <a href="#">Delete</a>
-            </td>
-
-          </tr>
-          <tr class="b">
-            <td>1</td>
-            <td>Jul 12, 2005 9:02:42 AM</td>
-            <td><img src="continuum_files/icon_success_sml.gif" alt="Success"/></td>
-            <td>
-              <a href="viewBuild.html">Details</a> | <a href="#">Delete</a>
-            </td>
-          </tr>
-
-        </table>
-
-      </div>
-    </div>
-  </div>
-</td>
-</tr>
-</tbody></table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/configuration.html b/design/old-white-site/configuration.html
deleted file mode 100644
index 86c8909..0000000
--- a/design/old-white-site/configuration.html
+++ /dev/null
@@ -1,147 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Logged in as: <b>Brett Porter</b> | <a href="userProfile.html">Profile</a> | <a href="login.html">Log out</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-  <tbody><tr valign="top">
-    <td id="leftcol" width="30%">
-      <div id="navcolum">
-        <div id="projectmenu" class="toolgroup">
-          <div class="label">Continuum</div>
-
-          <div class="body">
-            <div><a href="index.html">Show Projects</a></div>
-
-            <div><a href="schedule.html">View Build Schedule</a></div>
-          </div>
-        </div>
-
-        <div id="projecttools" class="toolgroup">
-          <div class="label">Add Project</div>
-
-          <div class="body">
-            <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-            <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-            <div><a href="addAntProject.html">Ant Project</a></div>
-
-            <div><a href="addShellProject.html">Shell Project</a></div>
-          </div>
-        </div>
-
-        <div id="projectimport" class="toolgroup">
-          <div class="label">Import Project</div>
-
-          <div class="body">
-            <div>
-              <a href="addCruiseControlProject.html">CruiseControl</a>
-            </div>
-          </div>
-        </div>
-      </div>
-    </td>
-    <td>
-      <div id="bodycol">
-        <div class="app">
-
-          <div id="axial" class="h3">
-            <h3>General Configuration</h3>
-
-            <div class="axial">
-              <table border="1" cellspacing="2" cellpadding="3" width="100%">
-
-                <tr class="b">
-                  <th>Guests</th>
-                  <td>Guest user is <strong style="color: green;">enabled</strong></td>
-                </tr>
-              </table>
-              <div class="functnbar3">
-                <table>
-                  <tr>
-                    <td>
-                      <form method="post" action="editConfiguration.html">
-
-                        <input type="hidden" name="action" value="cam"/>
-                        <input type="hidden" name="cid" value="checkoutProject"/>
-                        <input type="hidden" name="id" value="43"/>
-                        <input type="submit" name="edit-project" value="Edit"/>
-                      </form>
-                    </td>
-                  </tr>
-                </table>
-              </div>
-            </div>
-
-          </div>
-        </div>
-      </div>
-    </td>
-  </tr>
-  </tbody></table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/continuum_files/continuum_logo.png b/design/old-white-site/continuum_files/continuum_logo.png
deleted file mode 100644
index 0559f41..0000000
--- a/design/old-white-site/continuum_files/continuum_logo.png
+++ /dev/null
Binary files differ
diff --git a/design/old-white-site/continuum_files/continuum_logo_75.gif b/design/old-white-site/continuum_files/continuum_logo_75.gif
deleted file mode 100644
index 7875d40..0000000
--- a/design/old-white-site/continuum_files/continuum_logo_75.gif
+++ /dev/null
Binary files differ
diff --git a/design/old-white-site/continuum_files/icon_error_sml.gif b/design/old-white-site/continuum_files/icon_error_sml.gif
deleted file mode 100644
index 61132ef..0000000
--- a/design/old-white-site/continuum_files/icon_error_sml.gif
+++ /dev/null
Binary files differ
diff --git a/design/old-white-site/continuum_files/icon_in_progress_sml.gif b/design/old-white-site/continuum_files/icon_in_progress_sml.gif
deleted file mode 100644
index 8c6362e..0000000
--- a/design/old-white-site/continuum_files/icon_in_progress_sml.gif
+++ /dev/null
Binary files differ
diff --git a/design/old-white-site/continuum_files/icon_success_sml.gif b/design/old-white-site/continuum_files/icon_success_sml.gif
deleted file mode 100644
index 52e85a4..0000000
--- a/design/old-white-site/continuum_files/icon_success_sml.gif
+++ /dev/null
Binary files differ
diff --git a/design/old-white-site/continuum_files/icon_warning_sml.gif b/design/old-white-site/continuum_files/icon_warning_sml.gif
deleted file mode 100644
index 873bbb5..0000000
--- a/design/old-white-site/continuum_files/icon_warning_sml.gif
+++ /dev/null
Binary files differ
diff --git a/design/old-white-site/continuum_files/print.css b/design/old-white-site/continuum_files/print.css
deleted file mode 100644
index c7bcdc1..0000000
--- a/design/old-white-site/continuum_files/print.css
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-/* $Id$ */
-
-#banner, #footer, #leftcol, #breadcrumbs, .docs #toc, .docs .courtesylinks	{
-	display: none;
-	}
-body.docs div.docs	{
-	margin: 0 !important;
-	border: none !important
-	}
diff --git a/design/old-white-site/continuum_files/tigris.css b/design/old-white-site/continuum_files/tigris.css
deleted file mode 100644
index ab18ac4..0000000
--- a/design/old-white-site/continuum_files/tigris.css
+++ /dev/null
@@ -1,820 +0,0 @@
-/*
- * 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.
- */
-
-/* $Id$
-	
-	This file defines basic default formatting for HTML conforming to Tigris application style. To extend or override these rules for your instance, edit inst.css instead of this file. */
-
-/* colors, backgrounds, borders, link indication */
-body {
-	background: #fff;
-	color: #000;
-}
-
-.app h3, .app h4, .tabs td, .tabs th, .functnbar {
-	background-image: url(../images/nw_maj_rond.gif);
-	background-repeat: no-repeat;
-}
-
-.functnbar, .functnbar2 {
-	background-color: #aaa;
-}
-
-.functnbar2, .functnbar3 {
-	background-color: #aaa;
-	background-image: url(../images/sw_maj_rond.gif);
-	background-repeat: no-repeat;
-	background-position: bottom left;
-}
-
-.functnbar3 {
-	background-color: #ddd;
-	background-image: url(../images/sw_med_rond.gif);
-}
-
-.functnbar, .functnbar2, .functnbar3 {
-	color: #000;
-}
-
-.functnbar a, .functnbar2 a, .functnbar3 a {
-	color: #000;
-	text-decoration: underline;
-}
-
-#navcolumn .body div, body.docs #toc li li {
-	background-image: url(../images/strich.gif);
-	background-repeat: no-repeat;
-	background-position: .5em .5em;
-}
-
-#searchbox .body div, #navcolumn .body .heading {
-	background-image: none;
-}
-
-a:link, #navcolumn a:visited, .app a:visited, .tasknav a:visited {
-	color: blue;
-}
-
-a:link.selfref, a:visited.selfref {
-	color: #555 !important;
-	text-decoration: none;
-}
-
-a:active, a:hover, #leftcol a:active, #leftcol a:hover {
-	color: #f30 !important;
-}
-
-#leftcol a, #breadcrumbs a {
-	text-decoration: none;
-}
-
-.app h3, .app h4 {
-	color: #fff;
-}
-
-.app h3 {
-	background-color: #333;
-}
-
-.app h3 a:link, .app h3 a:visited, .app h4 a:link, .app h4 a:visited {
-	color: #fff !important;
-	text-decoration: underline;
-}
-
-.app h4 {
-	background-color: #888;
-}
-
-.a td {
-	background: #ddd;
-}
-
-.b td {
-	background: #efefef;
-}
-
-.warning td {
-	background: #cc0000;
-}	
-
-.inputerror {
-  background: #ffffcc;
-}
-
-table, th, td {
-	border: none;
-}
-
-div.colbar {
-	background: #eee;
-	border-color: #999 #EEE #EEE #999;
-	border-width: 1px;
-	border-style: solid;
-}
-
-.toolgroup {
-	background: #efefef;
-}
-
-.toolgroup .label {
-	border-bottom: 1px solid #666;
-	border-right: 1px solid #666;
-	background: #ddd;
-	color: #555;
-}
-
-.toolgroup .body {
-	border-right: 1px solid #aaa;
-	border-bottom: 1px solid #aaa;
-}
-
-#breadcrumbs {
-	border-top: 1px solid #fff;
-	background-color: #ccc;
-}
-
-#main {
-	border-top: 1px solid #999;
-}
-
-#rightcol div.www, #rightcol div.help {
-	border: 1px solid #ddd;
-}
-
-body.docs div.docs {
-	background-color: #fff;
-	border-left: 1px solid #ddd;
-	border-top: 1px solid #ddd;
-}
-
-#helptext .label {
-	background-image: url(../images/icon_help_sml.gif);
-	background-repeat: no-repeat;
-	background-position: 97%;
-}
-
-body.docs {
-	background: #eee url(../images/help_logo.gif) top right no-repeat !important;
-}
-
-.docs h3, .docs h4 {
-	border-top: solid 1px #000;
-}
-
-#apphead h2 em {
-	color: #777;
-}
-
-.app th {
-	background-color: #bbb;
-}
-
-.tabs th {
-	border-right: 1px solid #333;
-	background-color: #ddd;
-	color: #fff;
-	border-left: 1px solid #fff;
-}
-
-.tabs td {
-	background-color: #999;
-	border-bottom: 1px solid #fff;
-	border-right: 1px solid #fff;
-	border-left: 1px solid #fff;
-}
-
-.tabs {
-	border-bottom: 6px #ddd solid;
-}
-
-.tabs th, .tabs th a:link, .tabs th a:visited {
-	color: #555;
-}
-
-.tabs td, .tabs td a:link, .tabs td a:visited {
-	color: #fff;
-}
-
-.tabs a {
-	text-decoration: none;
-}
-
-.axial th {
-	background-color: #ddd;
-	color: black;
-}
-
-.alert {
-	background-color: #ff9;
-}
-
-.expandedwaste {
-	background: url(../images/icon_arrowwaste2_sml.gif) no-repeat;
-}
-
-.collapsedwaste {
-	background: url(../images/icon_arrowwaste1_sml.gif) no-repeat;
-}
-
-.filebrowse .expanded, .filebrowse-alt .expanded {
-	background-image: url(../images/icon_arrowfolderopen2_sml.gif);
-	background-repeat: no-repeat;
-}
-
-.filebrowse .collapsed, .filebrowse-alt .collapsed {
-	background-image: url(../images/icon_arrowfolderclosed1_sml.gif);
-	background-repeat: no-repeat;
-}
-
-.filebrowse .leafnode, .filebrowse-alt .leafnode {
-	background-image: url(../images/icon_folder_sml.gif);
-	background-repeat: no-repeat;
-}
-
-.filebrowse .leaf, .filebrowse-alt .leaf {
-	background-image: url(../images/icon_doc_sml.gif);
-	background-repeat: no-repeat;
-}
-
-.sortup {
-	background: url(../images/icon_sortup.gif) no-repeat;
-}
-
-.sortdown {
-	background: url(../images/icon_sortdown.gif) no-repeat;
-}
-
-.collapsedwaste {
-	background: url(../images/icon_arrowwaste1_sml.gif) no-repeat;
-}
-
-body .grid td {
-	border-top: 1px solid #ccc;
-	border-left: 1px solid #ccc;
-	background-color: transparent;
-}
-
-.confirm {
-	color: #090;
-}
-
-.info {
-	color: #069;
-}
-
-.errormessage, .warningmessage, .donemessage, .infomessage {
-	border-top: 5px solid #900;
-	border-left: 1px solid #900;
-	background-image: url(../images/icon_error_lrg.gif);
-	background-repeat: no-repeat;
-	background-position: 5px 1.33em;
-}
-
-.warningmessage {
-	background-image: url(../images/icon_warning_lrg.gif);
-	border-color: #c60;
-}
-
-.donemessage {
-	background-image: url(../images/icon_success_lrg.gif);
-	border-color: #090;
-}
-
-.infomessage {
-	background-image: url(../images/icon_info_lrg.gif);
-	border-color: #069;
-}
-
-.docinfo {
-	background: url(../images/icon_doc_lrg.gif) no-repeat;
-}
-
-.dirinfo {
-	background: url(../images/icon_folder_lrg.gif) no-repeat;
-}
-
-.memberinfo {
-	background: url(../images/icon_members_lrg.gif) no-repeat;
-}
-
-.usergroupinfo {
-	background: url(../images/icon_usergroups_lrg.gif) no-repeat;
-}
-
-.errormark, .warningmark, .donemark, .infomark {
-	background: url(../images/icon_error_sml.gif) no-repeat;
-}
-
-.warningmark {
-	background-image: url(../images/icon_warning_sml.gif);
-}
-
-.donemark {
-	background-image: url(../images/icon_success_sml.gif);
-}
-
-.infomark {
-	background-image: url(../images/icon_info_sml.gif);
-}
-
-.cvsdiff, .cvsblame {
-	background-color: #ccc;
-}
-
-.cvsdiffadd {
-	background-color: #afa;
-}
-
-.cvsdiffremove {
-	background-color: #faa;
-}
-
-.cvsdiffchanges1 {
-	background-color: #ff7;
-}
-
-.cvsdiffchanges2 {
-	background-color: #ff7;
-}
-
-li.selection ul a {
-	background: #fff;
-}
-
-.band1 {
-	color: #fff;
-	background-color: #663;
-}
-
-.band2 {
-	color: #fff;
-	background-color: #66C;
-}
-
-.band3 {
-	background-color: #C99;
-}
-
-.band4 {
-	background-color: #CFF;
-}
-
-.band5 {
-	color: #fff;
-	background-color: #336;
-}
-
-.band6 {
-	color: #fff;
-	background-color: #966;
-}
-
-.band7 {
-	background-color: #9CC;
-}
-
-.band8 {
-	background-color: #FFC;
-}
-
-.band9 {
-	color: #fff;
-	background-color: #633;
-}
-
-.band10 {
-	color: #fff;
-	background-color: #699;
-}
-
-.band11 {
-	background-color: #CC9;
-}
-
-.band12 {
-	background-color: #CCF;
-}
-
-.band13 {
-	color: #fff;
-	background-color: #366;
-}
-
-.band14 {
-	color: #fff;
-	background-color: #996;
-}
-
-.band15 {
-	background-color: #99C;
-}
-
-.band16 {
-	background-color: #FCC;
-}
-
-.app .helplink, #helptext .helplink {
-	cursor: help;
-}
-
-.legend th, .bars th {
-	background-color: #fff;
-}
-
-/* font and text properties, exclusive of link indication, alignment, text-indent */
-body, th, td, input, select {
-	font-family: Verdana, Helvetica, Arial, sans-serif;
-}
-
-code, pre {
-	font-family: 'Andale Mono', Courier, monospace;
-}
-
-body, .app h3, .app h4, #rightcol h3, pre, code, #apphead h2 small {
-	font-size: x-small;
-	voice-family: "\"}\"";
-	voice-family: inherit;
-	font-size: small;
-}
-
-small, div#footer, div#login, div.tabs th, div.tabs td, input, select, .paginate, .functnbar, .functnbar2, .functnbar3, #breadcrumbs, .courtesylinks, #rightcol div.help, .colbar, .tasknav, body.docs div#toc, #leftcol, .legend, .bars {
-	font-size: xx-small;
-	voice-family: "\"}\"";
-	voice-family: inherit;
-	font-size: x-small;
-}
-
-.tabs td, .tabs th, dt, .tasknav .selfref, #login .username, .selection {
-	font-weight: bold;
-}
-
-li.selection ul {
-	font-weight: normal;
-}
-
-h4, table {
-	font-size: 1em;
-}
-
-#apphead h2 em {
-	font-style: normal;
-}
-
-#banner h1 {
-	font-size: 1.25em;
-}
-
-/* box properties (exclusive of borders), positioning, alignments, list types, text-indent */
-#bodycol h2 {
-	margin-top: .3em;
-	margin-bottom: .5em;
-}
-
-p, ul, ol, dl, .bars table {
-	margin-top: .67em;
-	margin-bottom: .67em;
-}
-
-h3, h4 {
-	margin-bottom: 0;
-}
-
-form {
-	margin: 0;
-}
-
-#bodycol {
-	padding-left: 12px;
-	padding-right: 12px;
-	width: 100%;
-	voice-family: "\"}\"";
-	voice-family: inherit;
-	width: auto;
-}
-
-html>body #bodycol {
-	width: auto;
-}
-
-.docs {
-	line-height: 1.4;
-}
-
-ol ol {
-	list-style-type: lower-alpha;
-}
-
-ol ol ol {
-	list-style-type: lower-roman;
-}
-
-.app h3, .app h4 {
-	padding: 5px;
-	margin-right: 2px;
-	margin-left: 2px;
-}
-
-.app td, .app th {
-	padding: 2px 3px;
-}
-
-.h3 p, .h4 p, .h3 dt, .h4 dt {
-	margin-right: 7px;
-	margin-left: 7px;
-}
-
-.tasknav {
-	margin-bottom: 1.33em;
-}
-
-div.colbar {
-	padding: 3px;
-	margin: 2px 2px 0;
-}
-
-.tabs {
-	margin-top: .67em;
-	margin-right: 2px;
-	margin-left: 2px;
-	padding-left: 8px;
-}
-
-.tabs td, .tabs th {
-	padding: 3px 9px;
-}
-
-#rightcol div.www, #rightcol div.help {
-	padding: 0 .5em;
-}
-
-body.docs #toc {
-	position: absolute;
-	top: 15px;
-	left: 0px;
-	width: 120px;
-	padding: 0 20px 0 0;
-}
-
-body.docs #toc ul, #toc ol {
-	margin-left: 0;
-	padding-left: 0;
-}
-
-body.docs #toc li {
-	margin-top: 7px;
-	padding-left: 10px;
-	list-style-type: none;
-}
-
-body.docs div.docs {
-	margin: 61px 0 0 150px;
-	padding: 1em 2em 1em 1em !important;
-}
-
-.docs p+p {
-	text-indent: 5%;
-	margin-top: -.67em;
-}
-
-.docs h3, .docs h4 {
-	margin-bottom: .1em;
-	padding-top: .3em;
-}
-
-.functnbar, .functnbar2, .functnbar3 {
-	padding: 5px;
-	margin: .67em 2px;
-}
-
-.functnbar3 {
-	margin-top: 0;
-}
-
-body {
-	padding: 1em;
-}
-
-body.composite, body.docs {
-	margin: 0;
-	padding: 0;
-}
-
-th, td {
-	text-align: left;
-	vertical-align: top;
-}
-
-.right {
-	text-align: right !important;
-}
-
-.center {
-	text-align: center !important;
-}
-
-.axial th, .axial th .strut {
-	text-align: right;
-}
-
-.app .axial td th {
-	text-align: left;
-}
-
-body .stb {
-	margin-top: 1em;
-	text-indent: 0;
-}
-
-body .mtb {
-	margin-top: 2em;
-	text-indent: 0;
-}
-
-.courtesylinks {
-	margin-top: 1em;
-	padding-top: 1em;
-}
-
-dd {
-	margin-bottom: .67em;
-}
-
-.toolgroup {
-	margin-bottom: 6px;
-}
-
-.toolgroup .body {
-	padding: 4px 4px 4px 0;
-}
-
-.toolgroup .label {
-	padding: 4px;
-}
-
-.toolgroup .body div {
-	padding-bottom: .3em;
-	padding-left: 1em;
-}
-
-.toolgroup .body div div {
-	margin-top: .3em;
-	padding-bottom: 0;
-}
-
-.tier1 {
-	margin-left: 0;
-}
-
-.tier2 {
-	margin-left: 1.5em;
-}
-
-.tier3 {
-	margin-left: 3em;
-}
-
-.tier4 {
-	margin-left: 4.5em;
-}
-
-.tier5 {
-	margin-left: 6em;
-}
-
-.tier6 {
-	margin-left: 7.5em;
-}
-
-.tier7 {
-	margin-left: 9em;
-}
-
-.tier8 {
-	margin-left: 10.5em;
-}
-
-.tier9 {
-	margin-left: 12em;
-}
-
-.tier10 {
-	margin-left: 13.5em;
-}
-
-.filebrowse .expanded, .filebrowse .collapsed {
-	padding-left: 34px;
-}
-
-.filebrowse .leafnode, .filebrowse .leaf {
-	padding-left: 20px;
-}
-
-.messagechild {
-	padding-left: 34px;
-}
-
-.filebrowse-alt .expanded, .filebrowse-alt .collapsed, .filebrowse-alt .leaf, .filebrowse-alt .leafnode, .expandedwaste, .collapsedwaste, .sortup, .sortdown {
-	/* hide from macie5\*/
-	float: left;
-	/* resume */
-	display: inline-block;
-	height: 15px;
-	width: 34px;
-	padding-left: 0 !important;
-}
-
-.filebrowse-alt .leaf, .filebrowse-alt .leafnode, .sortup, .sortdown {
-	width: 20px;
-}
-
-.filebrowse ul, .filebrowse-alt ul {
-	list-style-type: none;
-	padding-left: 0;
-	margin-left: 0;
-}
-
-.filebrowse ul ul, .filebrowse-alt ul ul {
-	margin-left: 1.5em;
-	margin-top: 0;
-	padding-top: .67em;
-}
-
-.filebrowse li, .filebrowse-alt li {
-	margin-bottom: .67em;
-}
-
-td.filebrowse h3 {
-	margin-top: 0;
-}
-
-.errormessage, .warningmessage, .donemessage, .infomessage, .docinfo, .dirinfo, .memberinfo, .usergroupinfo {
-	margin: .67em 0;
-	padding: .33em 0 .67em 42px;
-	min-height: 32px;
-}
-
-.errormark, .warningmark, .donemark, .infomark {
-	padding-left: 20px;
-	min-height: 15px;
-}
-
-.alt {
-	display: none;
-}
-
-#banner h1 {
-	margin: 0;
-}
-
-#leftcol {
-	width: 14em;
-}
-
-.axial th, .axial th .strut, #leftcol .strut {
-	width: 12em;
-}
-
-#breadcrumbs {
-	padding: 2px 8px;
-}
-
-.app h3, .app h4, .bars {
-	clear: both;
-}
-
-.legend {
-	float: right;
-}
-
-.legend th, .bars th {
-	text-align: right;
-	padding-left: 1em;
-}
-
-.bars table {
-	table-layout: fixed;
-}
-
-.bars th {
-	width: 12em;
-}
-
-#projectdocumentlist td.filebrowse-alt {
-	padding-right: .75em;
-}
diff --git a/design/old-white-site/continuum_files/tigris.js b/design/old-white-site/continuum_files/tigris.js
deleted file mode 100644
index 9030d47..0000000
--- a/design/old-white-site/continuum_files/tigris.js
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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.
- */
-
-// Write the Netscape 4-specific stylesheet.
-if (document.layers) {
-  document.writeln('<link rel="stylesheet" type="text/css" href="http://style.tigris.org/nonav/css/ns4_only.css" media="screen" />')
-}
-
-
-// Focus on user name input (the "loginform.loginID" field).
-function focus() {
-  if (document.loginform) {
-    document.loginform.loginID.focus();
-  }
-}
-
-/* Open popup widows of (mostly) predetermined types.
-
-   windowURL -- The URL to load in the new browser window.
-   type -- The (predetermined) type of window to launch.
-           acceptable values for type:
-           1: a help window
-           2: a 400x400 window
-           3: Issuezilla assignable users popup window
-           ... and you can hard code others yourself inside the function.
-   atts -- (optional) If the window you wish to create is unique and you do
-           not want to set up a "type" for it, or if you want to pass
-           additional attributes for a certain "type", you can pass its
-           attributes directly to the function via this parameter.
-*/
-
-var tigrisPopupCounter = 0;
-
-function launch(windowURL, type, atts) {
-  tigrisPopupCounter += 1;
-
-  var windowName = 'SourceCast' + type;
-  if (atts) {
-    windowName += tigrisPopupCounter;
-  }
-
-  var windowAttributes;
-  if (type == 1) {
-    windowAttributes = 'resizable=yes,left=10,top=10,screenX=12,screenY=12,height=485,width=724,status=yes,scrollbars=yes,toolbar=yes,menubar=yes,location=yes'
-  }
-  else if (type == 2) {
-    windowAttributes = 'resizable=yes,left=10,top=10,screenX=12,screenY=12,height=400,width=400';
-  }
-  else if (type == 3) {
-   windowAttributes = 'resizable=yes,left=10,top=10,screenX=12,screenY=12,height=440,width=600,scrollbars=yes'; 
-  }
-  if (atts) {
-    windowAttributes += ',' + atts;
-  }
-
-  var windowObj = window.open(windowURL, windowName, windowAttributes);
-
-  if (windowObj) {
-    return false;
-  }
-  else {
-    return true;
-  }
-}
diff --git a/design/old-white-site/createUser.html b/design/old-white-site/createUser.html
deleted file mode 100644
index 3d82322..0000000
--- a/design/old-white-site/createUser.html
+++ /dev/null
@@ -1,181 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-  </div>
-</td>
-<td>
-  <div id="bodycol">
-    <div class="app">
-      <div id="axial" class="h3">
-        <h3>Create New Account</h3>
-
-        <form method="post" action="userProfile.html">
-          <input type="hidden" name="fid" value="antProject"/>
-
-          <input type="hidden" name="action" value="addEntity"/>
-          <input type="hidden" name="view" value="Summary.vm"/>
-          <input type="hidden" name="id" value="$id"/>
-
-          <div class="axial">
-            <table border="1" cellspacing="2" cellpadding="3" width="100%">
-              <tr>
-
-                <th>Username</th>
-
-
-                <td>
-                  <input type="text" name="username" value="" size="40"/>
-                </td>
-              </tr>
-              <tr>
-                <th>Password</th>
-
-
-                <td>
-                  <input type="password" value="" size="40"/>
-                </td>
-              </tr>
-              <tr>
-                <th>Confirm Password</th>
-
-
-                <td>
-                  <input type="password" value="" size="40"/>
-                </td>
-              </tr>
-              <tr>
-
-                <th>Full Name</th>
-
-
-                <td>
-                  <input type="text" name="username" value="" size="40"/>
-                </td>
-              </tr>
-              <tr>
-
-                <th>Email</th>
-
-
-                <td>
-                  <input type="text" name="username" value="" size="40"/>
-                </td>
-              </tr>
-            </table>
-            <div class="functnbar3">
-              <input type="submit" value="Submit"/>
-            </div>
-          </div>
-        </form>
-
-      </div>
-    </div>
-
-  </div></td>
-</tr>
-</tbody>
-</table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/deleteProject.html b/design/old-white-site/deleteProject.html
deleted file mode 100644
index 708a5e1..0000000
--- a/design/old-white-site/deleteProject.html
+++ /dev/null
@@ -1,142 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-  <tbody><tr valign="top">
-    <td id="leftcol" width="30%">
-      <div id="navcolum">
-        <div id="projectmenu" class="toolgroup">
-          <div class="label">Continuum</div>
-
-          <div class="body">
-            <div><a href="index.html">Show Projects</a></div>
-
-            <div><a href="schedule.html">View Build Schedule</a></div>
-          </div>
-        </div>
-
-        <div id="projecttools" class="toolgroup">
-          <div class="label">Add Project</div>
-
-          <div class="body">
-            <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-            <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-            <div><a href="addAntProject.html">Ant Project</a></div>
-
-            <div><a href="addShellProject.html">Shell Project</a></div>
-          </div>
-        </div>
-
-        <div id="projectimport" class="toolgroup">
-          <div class="label">Import Project</div>
-
-          <div class="body">
-            <div>
-              <a href="addCruiseControlProject.html">CruiseControl</a>
-            </div>
-          </div>
-        </div>
-
-      </div>
-    </td>
-    <td>
-      <div id="bodycol">
-
-
-        <div class="app">
-          <div id="axial" class="h3">
-            <h3>Delete Continuum Project</h3>
-
-            <div class="warningmessage">
-              <p>
-
-                <strong>Are you sure you want to delete this project?</strong>
-              </p>
-            </div>
-
-            <form method="post" action="index.html">
-              <input type="hidden" name="fid" value="maven2Project"/>
-              <input type="hidden" name="action" value="deleteEntity"/>
-              <input type="hidden" name="view" value="Summary.vm"/>
-              <input type="hidden" name="id" value="43"/>
-
-              <div class="functnbar3">
-                <input type="submit" name="deleteEntry" value="Delete"/>
-                <input type="submit" name="cancel" value="Cancel"/>
-              </div>
-            </form>
-          </div>
-        </div>
-      </div>
-    </td>
-  </tr>
-  </tbody></table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/editConfiguration.html b/design/old-white-site/editConfiguration.html
deleted file mode 100644
index a90c440..0000000
--- a/design/old-white-site/editConfiguration.html
+++ /dev/null
@@ -1,149 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Logged in as: <b>Brett Porter</b> | <a href="userProfile.html">Profile</a> | <a href="login.html">Log out</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-  <tbody><tr valign="top">
-    <td id="leftcol" width="30%">
-      <div id="navcolum">
-        <div id="projectmenu" class="toolgroup">
-          <div class="label">Continuum</div>
-
-          <div class="body">
-            <div><a href="index.html">Show Projects</a></div>
-
-            <div><a href="schedule.html">View Build Schedule</a></div>
-          </div>
-        </div>
-
-        <div id="projecttools" class="toolgroup">
-          <div class="label">Add Project</div>
-
-          <div class="body">
-            <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-            <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-            <div><a href="addAntProject.html">Ant Project</a></div>
-
-            <div><a href="addShellProject.html">Shell Project</a></div>
-          </div>
-        </div>
-
-        <div id="projectimport" class="toolgroup">
-          <div class="label">Import Project</div>
-
-          <div class="body">
-            <div>
-              <a href="addCruiseControlProject.html">CruiseControl</a>
-            </div>
-          </div>
-        </div>
-      </div>
-    </td>
-    <td>
-      <div id="bodycol">
-        <div class="app">
-
-          <div id="axial" class="h3">
-            <h3>General Configuration</h3>
-
-            <div class="axial">
-              <table border="1" cellspacing="2" cellpadding="3" width="100%">
-
-                <tr class="b">
-                  <th>Guests</th>
-                  <td>
-                    <input type="checkbox" checked="checked"/> Enable guest user
-                  </td>
-                </tr>
-              </table>
-              <div class="functnbar3">
-                <table>
-                  <tr>
-                    <td>
-                      <form method="post" action="configuration.html">
-
-                        <input type="hidden" name="action" value="cam"/>
-                        <input type="hidden" name="cid" value="checkoutProject"/>
-                        <input type="hidden" name="id" value="43"/>
-                        <input type="submit" name="edit-project" value="Submit"/>
-                      </form>
-                    </td>
-                  </tr>
-                </table>
-              </div>
-            </div>
-
-          </div>
-        </div>
-      </div>
-    </td>
-  </tr>
-  </tbody></table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/editGroup.html b/design/old-white-site/editGroup.html
deleted file mode 100644
index a9d8c14..0000000
--- a/design/old-white-site/editGroup.html
+++ /dev/null
@@ -1,170 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-  <tbody><tr valign="top">
-    <td id="leftcol" width="30%">
-      <div id="navcolum">
-        <div id="projectmenu" class="toolgroup">
-          <div class="label">Continuum</div>
-
-          <div class="body">
-            <div><a href="index.html">Show Projects</a></div>
-
-            <div><a href="schedule.html">View Build Schedule</a></div>
-          </div>
-        </div>
-
-        <div id="projecttools" class="toolgroup">
-          <div class="label">Add Project</div>
-
-          <div class="body">
-            <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-            <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-            <div><a href="addAntProject.html">Ant Project</a></div>
-
-            <div><a href="addShellProject.html">Shell Project</a></div>
-          </div>
-        </div>
-
-        <div id="projectimport" class="toolgroup">
-          <div class="label">Import Project</div>
-
-          <div class="body">
-            <div>
-              <a href="addCruiseControlProject.html">CruiseControl</a>
-            </div>
-          </div>
-        </div>
-
-        <div style="margin-top: 5em; color: #555; border: 1px dashed black; padding: 1em;">
-          <p>Notes:</p>
-          <ul>
-            <li>No Maven Group ID on non-Maven projects</li>
-          </ul>
-        </div>
-      </div>
-    </td>
-    <td>
-      <div id="bodycol">
-        <div class="app">
-          <div id="axial" class="h3">
-            <h3>Edit Project Group</h3>
-
-            <form method="post" action="viewGroup.html">
-              <input type="hidden" name="fid" value="antProject"/>
-
-              <input type="hidden" name="action" value="addEntity"/>
-              <input type="hidden" name="view" value="Summary.vm"/>
-              <input type="hidden" name="id" value="$id"/>
-
-              <div class="axial">
-                <table border="1" cellspacing="2" cellpadding="3" width="100%">
-                  <tr>
-
-                    <th>Project Group Name</th>
-
-
-                    <td>
-                      <input type="text" name="project.name" value="" size="40"/>
-                    </td>
-                  </tr>
-                  <tr>
-                    <th>Maven Group ID</th>
-
-
-                    <td>
-                      <input type="text" name="project.version" value="" size="40"/>
-                    </td>
-                  </tr>
-                  <tr>
-                    <th>Description</th>
-
-
-                    <td>
-                      <input type="text" name="project.version" value="" size="40"/>
-                    </td>
-                  </tr>
-                </table>
-                <div class="functnbar3">
-                  <input type="submit" value="Submit"/>
-                </div>
-              </div>
-            </form>
-
-          </div>
-        </div>
-
-      </div></td>
-  </tr>
-  </tbody>
-</table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/editProfile.html b/design/old-white-site/editProfile.html
deleted file mode 100644
index 7c00d05..0000000
--- a/design/old-white-site/editProfile.html
+++ /dev/null
@@ -1,207 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-    <div style="margin-top: 5em; color: #555; border: 1px dashed black; padding: 1em;">
-      <p>Notes:</p>
-      <ul>
-        <li>different sections for different project types (Maven1 home, Ant home, no Java home for shell projects,
-          etc)</li>
-      </ul>
-    </div>
-  </div>
-</td>
-<td>
-  <div id="bodycol">
-    <div class="app">
-      <div id="axial" class="h3">
-        <h3>Add (Edit) Profile</h3>
-
-        <form method="post" action="profiles.html">
-          <input type="hidden" name="fid" value="antProject"/>
-
-          <input type="hidden" name="action" value="addEntity"/>
-          <input type="hidden" name="view" value="Summary.vm"/>
-          <input type="hidden" name="id" value="$id"/>
-
-          <div class="axial">
-            <table border="1" cellspacing="2" cellpadding="3" width="100%">
-              <tr>
-
-                <th>Profile Name</th>
-
-
-                <td>
-                  <input type="text" name="project.name" value="" size="40"/>
-                </td>
-              </tr>
-              <tr>
-                <th>Description</th>
-
-
-                <td>
-                  <input type="text" name="project.version" value="" size="40"/>
-                </td>
-              </tr>
-
-              <tr>
-                <th>JDK</th>
-                <td>
-                  <select>
-                    <option selected="selected">Default JDK 1.4 (/usr/local/java)</option>
-                    <option>JDK 1.3 (/usr/local/java-1.3)</option>
-                  </select>
-                </td>
-              </tr>
-              <tr>
-                <th>Maven 2.0 Installation</th>
-                <td>
-                  <select>
-                    <option selected="selected">Default Maven 2.0 (/usr/local/maven2)</option>
-                    <option>Maven 2.0 alpha 3 (/usr/local/maven-2.0-alpha-3)</option>
-                  </select>
-                </td>
-              </tr>
-              <tr>
-                <th>SCM</th>
-
-
-                <td>
-                  <input type="radio" name="scm" checked="checked"/>&nbsp;Update
-                  <input type="radio" name="scm"/>&nbsp;Checkout
-                </td>
-              </tr>
-              <tr>
-                <th>&nbsp;</th>
-
-
-                <td>
-                  <input type="checkbox" name="project.version"/>&nbsp;Build without Changes
-                </td>
-              </tr>
-              <tr>
-                <th>&nbsp;</th>
-
-
-                <td>
-                  <input type="checkbox" name="project.version" checked="checked"/>&nbsp;Enabled
-                </td>
-              </tr>
-            </table>
-            <div class="functnbar3">
-              <input type="submit" value="Submit"/>
-            </div>
-          </div>
-        </form>
-
-      </div>
-    </div>
-
-  </div></td>
-</tr>
-</tbody>
-</table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/editProject.html b/design/old-white-site/editProject.html
deleted file mode 100644
index 8d8195c..0000000
--- a/design/old-white-site/editProject.html
+++ /dev/null
@@ -1,181 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-  </div>
-</td>
-<td>
-  <div id="bodycol">
-    <div class="app">
-      <div id="axial" class="h3">
-        <h3>Edit Project - NAME_HERE</h3>
-
-        <form method="post" action="viewProject.html">
-          <input type="hidden" name="fid" value="antProject"/>
-
-          <input type="hidden" name="action" value="addEntity"/>
-          <input type="hidden" name="view" value="Summary.vm"/>
-          <input type="hidden" name="id" value="$id"/>
-
-          <div class="axial">
-            <table border="1" cellspacing="2" cellpadding="3" width="100%">
-              <tr>
-
-                <th>Project Name</th>
-
-
-                <td>
-                  <input type="text" name="project.name" value="" size="40"/>
-
-                  <p>
-                    Enter the project name <font color="red"><b></b></font>
-                  </p>
-                </td>
-              </tr>
-              <tr>
-                <th>Version</th>
-
-
-                <td>
-                  <input type="text" name="project.version" value="" size="40"/>
-
-                  <p>
-
-                    Enter the version of the project <font color="red"><b></b></font>
-                  </p>
-                </td>
-              </tr>
-
-              <tr>
-                <th>Scm Url</th>
-
-
-                <td>
-                  <input type="text" name="projectScmUrl" value="" size="40"/>
-
-                  <p>
-                    Enter the <a href="http://maven.apache.org/reference/plugins/scm/scmurl.html">Maven SCM URL</a>
-                    <font color="red">
-                      <b></b></font>
-
-                  </p>
-                </td>
-              </tr>
-            </table>
-            <div class="functnbar3">
-              <input type="submit" value="Submit"/>
-            </div>
-          </div>
-        </form>
-
-      </div>
-    </div>
-
-  </div></td>
-</tr>
-</tbody>
-</table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/editRoles.html b/design/old-white-site/editRoles.html
deleted file mode 100644
index b071883..0000000
--- a/design/old-white-site/editRoles.html
+++ /dev/null
@@ -1,313 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-    <div style="margin-top: 5em; color: #555; border: 1px dashed black; padding: 1em;">
-      <p>Notes:</p>
-      <ul>
-        <li>link back to project management page these roles correspond to in heading</li>
-        <li>can add new role with bottom link</li>
-        <li>back and forth elements might need a different ui widget</li>
-      </ul>
-    </div>
-  </div>
-</td>
-<td>
-<div id="bodycol">
-<div class="app">
-
-<div id="axial" class="h3">
-<h3>Manage Roles for - <a href="manageGroup.html">Plexus</a></h3>
-
-<h4>Role - admin</h4>
-<table border="1" cellspacing="2" cellpadding="3" width="100%">
-  <tr>
-
-    <th>Granted Permissions</th>
-    <th>Action</th>
-    <th>Available Permissions</td>
-  </tr>
-  <tr class="b">
-    <td>
-      <center>
-      <select multiple="true">
-        <option>view project</option>
-        <option>add projects</option>
-        <option>trigger builds<option>
-        <option>manage users</option>  
-      </select>
-      </center>
-    </td>
-    <td>
-      <center>
-        <form method="post" action="editRole.html">
-          <input type="hidden" name="action" value="cam"/>
-          <input type="submit" name="add-role-def" value="->"/>
-        </form>
-        <form method="post" action="editRole.html">
-          <input type="hidden" name="action" value="cam"/>
-          <input type="submit" name="add-role-def" value="<-"/>
-        </form>
-      </center>
-    </td>
-    <td>
-    <center>
-    <select multiple="true">      
-      <option>future I<option>
-      <option>future II</option>
-    </select>
-    </center>
-    </td>
-  </tr>
-
-</table>
-
-<table border="1" cellspacing="2" cellpadding="3" width="100%">
-  <tr>
-
-    <th>Assigned Users</th>
-    <th>Action</th>
-    <th>Available Users</td>
-  </tr>
-  <tr class="b">
-    <td>
-      <center>
-      <select multiple="true">
-        <option>Jason Van Zyl</option>
-        <option>Brett Porter</option>        
-      </select>
-      </center>
-    </td>
-    <td>
-      <center>
-        <form method="post" action="editRole.html">
-          <input type="hidden" name="action" value="cam"/>
-          <input type="submit" name="add-role-def" value="->"/>
-        </form>
-        <form method="post" action="editRole.html">
-          <input type="hidden" name="action" value="cam"/>
-          <input type="submit" name="add-role-def" value="<-"/>
-        </form>
-      </center>
-    </td>
-    <td>
-    <center>
-    <select multiple="true">      
-      <option>Carlos Sanchez<option>
-      <option>Emmanuel Venisse</option>
-    </select>
-    </center>
-    </td>
-  </tr>
-
-</table>
-
-<h4>Role - user</h4>
-<table border="1" cellspacing="2" cellpadding="3" width="100%">
-  <tr>
-
-    <th>Granted Permissions</th>
-    <th>Action</th>
-    <th>Available Permissions</td>
-  </tr>
-  <tr class="b">
-    <td>
-      <center>
-      <select multiple="true">
-        <option>view project</option>
-        <option>trigger builds</option>
-      </select>
-      </center>
-    </td>
-    <td>
-      <center>
-        <form method="post" action="editRole.html">
-          <input type="hidden" name="action" value="cam"/>
-          <input type="submit" name="add-role-def" value="->"/>
-        </form>
-        <form method="post" action="editRole.html">
-          <input type="hidden" name="action" value="cam"/>
-          <input type="submit" name="add-role-def" value="<-"/>
-        </form>
-      </center>
-    </td>
-    <td>
-    <center>
-    <select multiple="true">      
-      <option>add projects<option>
-      <option>manage users</option>
-      <option>future I</option>
-      <option>future II</option>
-    </select>
-    </center>
-    </td>
-  </tr>
-
-</table>
-
-<table border="1" cellspacing="2" cellpadding="3" width="100%">
-  <tr>
-
-    <th>Assigned Users</th>
-    <th>Action</th>
-    <th>Available Users</td>
-  </tr>
-  <tr class="b">
-    <td>
-      <center>
-      <select multiple="true">
-        <option>Jason Van Zyl</option>
-        <option>Brett Porter</option>
-        <option>Carlos Sanchez</option>
-      </select>
-      </center>
-    </td>
-    <td>
-      <center>
-        <form method="post" action="editRole.html">
-          <input type="hidden" name="action" value="cam"/>
-          <input type="submit" name="add-role-def" value="->"/>
-        </form>
-        <form method="post" action="editRole.html">
-          <input type="hidden" name="action" value="cam"/>
-          <input type="submit" name="add-role-def" value="<-"/>
-        </form>
-      </center>
-    </td>
-    <td>
-    <center>
-    <select multiple="true">      
-      <option>Emmanuel Venisse</option>
-    </select>
-    </center>
-    </td>
-  </tr>
-
-</table>
-
-<div class="functnbar3">
-  <table>
-    <tr>
-      <td>
-        <form method="post" action="addRole.html">
-
-          <input type="hidden" name="action" value="cam"/>
-          <input type="submit" name="add-role-def" value="Add Role"/>
-        </form>
-      </td>
-    </tr>
-  </table>
-</div>
-
-</div>
-
-</div>
-</div>
-</div>
-</td>
-</tr>
-</tbody></table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/editSchedule.html b/design/old-white-site/editSchedule.html
deleted file mode 100644
index fbc9604..0000000
--- a/design/old-white-site/editSchedule.html
+++ /dev/null
@@ -1,180 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-  </div>
-</td>
-<td>
-  <div id="bodycol">
-    <div class="app">
-      <div id="axial" class="h3">
-        <h3>Add (Edit) Schedule</h3>
-
-        <form method="post" action="schedules.html">
-          <input type="hidden" name="fid" value="antProject"/>
-
-          <input type="hidden" name="action" value="addEntity"/>
-          <input type="hidden" name="view" value="Summary.vm"/>
-          <input type="hidden" name="id" value="$id"/>
-
-          <div class="axial">
-            <table border="1" cellspacing="2" cellpadding="3" width="100%">
-              <tr>
-
-                <th>Schedule Name</th>
-
-
-                <td>
-                  <input type="text" name="project.name" value="" size="40"/>
-                </td>
-              </tr>
-              <tr>
-                <th>Description</th>
-
-
-                <td>
-                  <input type="text" name="project.version" value="" size="40"/>
-                </td>
-              </tr>
-
-              <tr>
-                <th>Cron</th>
-
-
-                <td>
-                  <input type="text" name="project.version" value="" size="40"/>
-                </td>
-              </tr>
-              <tr>
-                <th>Quiet Period (seconds)</th>
-
-
-                <td>
-                  <input type="text" name="project.version" value="" size="40"/>
-                </td>
-              </tr>
-              <tr>
-                <th>&nbsp;</th>
-
-
-                <td>
-                  <input type="checkbox" name="project.version" checked="checked"/>&nbsp;Enabled
-                </td>
-              </tr>
-            </table>
-            <div class="functnbar3">
-              <input type="submit" value="Submit"/>
-            </div>
-          </div>
-        </form>
-
-      </div>
-    </div>
-
-  </div></td>
-</tr>
-</tbody>
-</table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/editUser.html b/design/old-white-site/editUser.html
deleted file mode 100644
index 15f1c7a..0000000
--- a/design/old-white-site/editUser.html
+++ /dev/null
@@ -1,197 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Logged in as: <b>Brett Porter</b> | <a href="userProfile.html">Profile</a> | <a href="login.html">Log out</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-    <div style="margin-top: 5em; color: #555; border: 1px dashed black; padding: 1em;">
-      <p>Notes:</p>
-      <ul>
-        <li>when this is the edit user page, there is an additional "old password" field, and the username is not
-          editable</li>
-      </ul>
-    </div>
-  </div>
-</td>
-<td>
-  <div id="bodycol">
-    <div class="app">
-      <div id="axial" class="h3">
-        <h3>Create New Account</h3>
-
-        <form method="post" action="userProfile.html">
-          <input type="hidden" name="fid" value="antProject"/>
-
-          <input type="hidden" name="action" value="addEntity"/>
-          <input type="hidden" name="view" value="Summary.vm"/>
-          <input type="hidden" name="id" value="$id"/>
-
-          <div class="axial">
-            <table border="1" cellspacing="2" cellpadding="3" width="100%">
-              <tr>
-
-                <th>Username</th>
-
-
-                <td>
-                  <input type="text" disabled="disabled" name="username" value="brettporter" size="40"/>
-                </td>
-              </tr>
-              <tr>
-                <th>Current Password</th>
-
-
-                <td>
-                  <input type="password" value="" size="40"/>
-                </td>
-              </tr>
-              <tr>
-                <th>Password</th>
-
-
-                <td>
-                  <input type="password" value="" size="40"/>
-                </td>
-              </tr>
-              <tr>
-                <th>Confirm Password</th>
-
-
-                <td>
-                  <input type="password" value="" size="40"/>
-                </td>
-              </tr>
-              <tr>
-
-                <th>Full Name</th>
-
-
-                <td>
-                  <input type="text" name="username" value="" size="40"/>
-                </td>
-              </tr>
-              <tr>
-
-                <th>Email</th>
-
-
-                <td>
-                  <input type="text" name="username" value="" size="40"/>
-                </td>
-              </tr>
-            </table>
-            <div class="functnbar3">
-              <input type="submit" value="Submit"/>
-            </div>
-          </div>
-        </form>
-
-      </div>
-    </div>
-
-  </div></td>
-</tr>
-</tbody>
-</table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/forgotPassword.html b/design/old-white-site/forgotPassword.html
deleted file mode 100644
index 88c7d11..0000000
--- a/design/old-white-site/forgotPassword.html
+++ /dev/null
@@ -1,148 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-  <tbody><tr valign="top">
-    <td id="leftcol" width="30%">
-      <div id="navcolum">
-        <div id="projectmenu" class="toolgroup">
-          <div class="label">Continuum</div>
-
-          <div class="body">
-            <div><a href="index.html">Show Projects</a></div>
-
-            <div><a href="schedule.html">View Build Schedule</a></div>
-          </div>
-        </div>
-
-        <div id="projecttools" class="toolgroup">
-          <div class="label">Add Project</div>
-
-          <div class="body">
-            <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-            <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-            <div><a href="addAntProject.html">Ant Project</a></div>
-
-            <div><a href="addShellProject.html">Shell Project</a></div>
-          </div>
-        </div>
-
-        <div id="projectimport" class="toolgroup">
-          <div class="label">Import Project</div>
-
-          <div class="body">
-            <div>
-              <a href="addCruiseControlProject.html">CruiseControl</a>
-            </div>
-          </div>
-        </div>
-
-      </div>
-    </td>
-    <td>
-      <div id="bodycol">
-        <div class="app">
-          <div id="axial" class="h3">
-            <h3>Forgot password</h3>
-
-            <form method="post" action="login.html">
-              <input type="hidden" name="fid" value="antProject"/>
-
-              <input type="hidden" name="action" value="addEntity"/>
-              <input type="hidden" name="view" value="Summary.vm"/>
-              <input type="hidden" name="id" value="$id"/>
-
-              <div class="axial">
-                <table border="1" cellspacing="2" cellpadding="3" width="100%">
-                  <tr>
-
-                    <th>Email address</th>
-
-
-                    <td>
-                      <input type="text" name="username" value="" size="40"/>
-                    </td>
-                  </tr>
-                </table>
-                <div class="functnbar3">
-                  <input type="submit" value="Submit"/>
-                </div>
-              </div>
-            </form>
-
-          </div>
-        </div>
-
-      </div></td>
-  </tr>
-  </tbody>
-</table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/groupStatus.html b/design/old-white-site/groupStatus.html
deleted file mode 100644
index d5d0870..0000000
--- a/design/old-white-site/groupStatus.html
+++ /dev/null
@@ -1,202 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-    <div style="margin-top: 5em; color: #555; border: 1px dashed black; padding: 1em;">
-      <p>Notes:</p>
-      <ul>
-        <li></li>
-      </ul>
-    </div>
-  </div>
-</td>
-<td>
-<div id="bodycol">
-<div class="app">
-
-<div>
-  <p style="border-top: 1px solid transparent; border-bottom: 1px solid black;">
-    <b style="border: 1px solid black; padding-left: 1em; padding-right: 1em;"><a href="groupStatus.html">Status</a></b>
-    <b style="border: 1px solid black; padding-left: 1em; padding-right: 1em;"><a href="manageGroup.html">Manage</a></b>
-  </p>
-</div>
-
-<div id="axial" class="h3">
-<h3>Continuum Project Group</h3>
-
-    <h4><a href="viewGroup.html">Plexus</a></h4>
-    <table id="projectSummaryTable" border="1" cellpadding="3" cellspacing="2" width="100%">
-
-      <!-- i18n -->
-      <tbody><tr>
-        <th>&nbsp;</th>
-        <th width="100%">Name</th>
-        <th>Version</th>
-        <th>Build</th>
-        <th colspan="5"></th>
-      </tr>
-
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_warning_sml.gif" alt="Error"></td>
-          <td><a href="viewProject.html">Default Plexus Container</a></td>
-          <td>1.0-alpha-6-SNAPSHOT</td>
-          <td><a href="viewBuild.html">5</a></td>
-
-          <td><a href="#">Build&nbsp;Now</a></td>
-          <td><a href="builds.html">Build&nbsp;History</a></td>
-          <td><a href="workingCopy.html">Working&nbsp;Copy</a></td>
-          <td>Release</td>
-          <td><a href="deleteProject.html">Delete</a></td>
-        </tr>
-
-        <tr class="b">
-          <td>&nbsp;</td>
-          <td><a href="viewProject.html">Plexus Utils</a></td>
-          <td>1.0.2-SNAPSHOT</td>
-          <td><strong>In&nbsp;progress</strong></td>
-          
-          <td><a href="#">Cancel&nbsp;Build</a></td>
-          <td><a href="builds.html">Build&nbsp;History</a></td>
-          <td><a href="workingCopy.html">Working&nbsp;Copy</a></td>
-          <td>Release</td>
-          <td><a href="deleteProject.html">Delete</a></td>
-        </tr>
-
-        <tr class="a">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td><a href="viewProject.html">Plexus Action</a></td>
-          <td>1.0-alpha-6-SNAPSHOT</td>
-          <td><a href="viewBuild.html">2</a></td>
-          
-          <td><a href="#">Build&nbsp;Now</a></td>
-          <td><a href="builds.html">Build&nbsp;History</a></td>
-          <td><a href="workingCopy.html">Working&nbsp;Copy</a></td>
-          <td><a href="releaseProject.html">Release</a></td>
-          <td><a href="deleteProject.html">Delete</a></td>
-        </tr>
-
-      </tbody></table>
-
-    <div class="functnbar3">
-      <form method="post" action="#">
-        <img src="continuum_files/icon_success_sml.gif" alt="Success"> 0
-        <img src="continuum_files/icon_error_sml.gif" alt="Failed"> 0
-        <img src="continuum_files/icon_warning_sml.gif" alt="Error"> 2
-        <input name="action" value="cam" type="hidden">
-        <input name="cid" value="buildAllProjects" type="hidden">
-        <input name="build-broken" value="Build All In Error" type="submit">
-        <input name="build-all" value="Build All" type="submit">
-      </form>
-    </div>
-
-
-</div>
-</div>
-</td>
-</tr>
-</tbody></table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
diff --git a/design/old-white-site/index.html b/design/old-white-site/index.html
deleted file mode 100644
index 662ce14..0000000
--- a/design/old-white-site/index.html
+++ /dev/null
@@ -1,372 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Logged in as: <b>Brett Porter</b> | <a href="userProfile.html">Profile</a> | <a href="login.html">Log out</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-    <div id="admin" class="toolgroup">
-      <div class="label">Administration</div>
-
-      <div class="body">
-        <div>
-          <a href="profiles.html">Profiles</a>
-        </div>
-
-        <div>
-          <a href="schedules.html">Schedules</a>
-        </div>
-
-        <div>
-          <a href="configuration.html">Configuration</a>
-        </div>
-
-        <div>
-          <a href="users.html">Users</a>
-        </div>
-      </div>
-    </div>
-
-  </div>
-</td>
-<td>
-<div id="bodycol">
-
-
-<div class="app">
-  <div id="h3">
-    <center><h3>Continuum Projects</h3></center>
-    
-    <h4><a href="groupStatus.html">Plexus</a></h4>
-    <table id="projectSummaryTable" border="1" cellpadding="3" cellspacing="2" width="100%">
-
-      <!-- i18n -->
-      <tbody><tr>
-        <th>&nbsp;</th>
-        <th width="100%">Name</th>
-        <th>Version</th>
-        <th>Build</th>
-        <th colspan="4"></th>
-      </tr>
-
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_warning_sml.gif" alt="Error"></td>
-          <td><a href="viewProject.html">Default Plexus Container</a></td>
-          <td>1.0-alpha-6-SNAPSHOT</td>
-          <td><a href="viewBuild.html">5</a></td>
-
-          <td><a href="#">Build&nbsp;Now</a></td>
-          <td><a href="builds.html">Build&nbsp;History</a></td>
-          <td><a href="workingCopy.html">Working&nbsp;Copy</a></td>
-          <td><a href="deleteProject.html">Delete</a></td>
-        </tr>
-
-        <tr class="b">
-          <td>&nbsp;</td>
-          <td><a href="viewProject.html">Plexus Utils</a></td>
-          <td>1.0.2-SNAPSHOT</td>
-          <td><strong>In&nbsp;progress</strong></td>
-          
-          <td><a href="#">Cancel&nbsp;Build</a></td>
-          <td><a href="builds.html">Build&nbsp;History</a></td>
-          <td><a href="workingCopy.html">Working&nbsp;Copy</a></td>
-          <td><a href="deleteProject.html">Delete</a></td>
-        </tr>
-
-        <tr class="a">
-          <td><img src="continuum_files/icon_warning_sml.gif" alt="Error"></td>
-          <td><a href="viewProject.html">Plexus Action</a></td>
-          <td>1.0-alpha-6-SNAPSHOT</td>
-          <td><a href="viewBuild.html">2</a></td>
-          
-          <td><a href="#">Build&nbsp;Now</a></td>
-          <td><a href="builds.html">Build&nbsp;History</a></td>
-          <td><a href="workingCopy.html">Working&nbsp;Copy</a></td>
-          <td><a href="deleteProject.html">Delete</a></td>
-        </tr>
-
-      </tbody></table>
-
-    <div class="functnbar3">
-      <form method="post" action="#">
-        <img src="continuum_files/icon_success_sml.gif" alt="Success"> 0
-        <img src="continuum_files/icon_error_sml.gif" alt="Failed"> 0
-        <img src="continuum_files/icon_warning_sml.gif" alt="Error"> 2
-        <input name="action" value="cam" type="hidden">
-        <input name="cid" value="buildAllProjects" type="hidden">
-        <input name="build-broken" value="Build All In Error" type="submit">
-        <input name="build-all" value="Build All" type="submit">
-      </form>
-    </div>
-    
-    
-    <h4><a href="groupStatus.html">Maven</a></h4>
-    <table id="projectSummaryTable" border="1" cellpadding="3" cellspacing="2" width="100%">
-
-      <!-- i18n -->
-      <tbody><tr>
-        <th>&nbsp;</th>
-        <th width="100%">Name</th>
-        <th>Version</th>
-        <th>Build</th>
-        <th colspan="4"></th>
-      </tr>
-
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_warning_sml.gif" alt="Error"></td>
-          <td><a href="viewProject.html">Maven Model</a></td>
-          <td>2.1-SNAPSHOT</td>
-          <td><a href="viewBuild.html">5</a></td>
-          <td><a href="#">Build&nbsp;Now</a></td>
-          <td><a href="builds.html">Build&nbsp;History</a></td>
-          <td><a href="workingCopy.html">Working&nbsp;Copy</a></td>
-          <td><a href="deleteProject.html">Delete</a></td>
-        </tr>
-
-        <tr class="b">
-          <td>&nbsp;</td>
-          <td><a href="viewProject.html">Maven Project</a></td>
-          <td>2.1-SNAPSHOT</td>
-          <td><strong>In&nbsp;progress</strong></td>
-          
-          <td><a href="#">Cancel&nbsp;Build</a></td>
-          <td><a href="builds.html">Build&nbsp;History</a></td>
-          <td><a href="workingCopy.html">Working&nbsp;Copy</a></td>
-          <td><a href="deleteProject.html">Delete</a></td>
-        </tr>
-
-        <tr class="a">
-          <td><img src="continuum_files/icon_warning_sml.gif" alt="Error"></td>
-          <td><a href="viewProject.html">Maven Plugin API</a></td>
-          <td>2.1-SNAPSHOT</td>
-          <td><a href="viewBuild.html">2</a></td>
-         
-          <td><a href="#">Build&nbsp;Now</a></td>
-          <td><a href="builds.html">Build&nbsp;History</a></td>
-          <td><a href="workingCopy.html">Working&nbsp;Copy</a></td>
-          <td><a href="deleteProject.html">Delete</a></td>
-        </tr>
-
-      </tbody></table>
-      
-      <div class="functnbar3">
-      <form method="post" action="#">
-        <img src="continuum_files/icon_success_sml.gif" alt="Success"> 0
-        <img src="continuum_files/icon_error_sml.gif" alt="Failed"> 0
-        <img src="continuum_files/icon_warning_sml.gif" alt="Error"> 2
-        <input name="action" value="cam" type="hidden">
-        <input name="cid" value="buildAllProjects" type="hidden">
-        <input name="build-broken" value="Build All In Error" type="submit">
-        <input name="build-all" value="Build All" type="submit">
-      </form>
-    </div>
-      
-      <h4><a href="groupStatus.html">Maven Plugins<a/></h4>
-    <table id="projectSummaryTable" border="1" cellpadding="3" cellspacing="2" width="100%">
-
-      <!-- i18n -->
-      <tbody><tr>
-        <th>&nbsp;</th>
-        <th width="100%">Name</th>
-        <th>Version</th>
-        <th>Build</th>
-        
-        <th colspan="4"></th>
-      </tr>
-
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_warning_sml.gif" alt="Error"></td>
-          <td><a href="viewProject.html">Maven Clean Plugin</a></td>
-          <td>2.1-SNAPSHOT</td>
-          <td><a href="viewBuild.html">5</a></td>
-         
-          <td><a href="#">Build&nbsp;Now</a></td>
-          <td><a href="builds.html">Build&nbsp;History</a></td>
-          <td><a href="workingCopy.html">Working&nbsp;Copy</a></td>
-          <td><a href="deleteProject.html">Delete</a></td>
-        </tr>
-
-        <tr class="b">
-          <td>&nbsp;</td>
-          <td><a href="viewProject.html">Maven War Plugin</a></td>
-          <td>2.1-SNAPSHOT</td>
-          <td><strong>In&nbsp;progress</strong></td>
-          
-          <td><a href="#">Cancel&nbsp;Build</a></td>
-          <td><a href="builds.html">Build&nbsp;History</a></td>
-          <td><a href="workingCopy.html">Working&nbsp;Copy</a></td>
-          <td><a href="deleteProject.html">Delete</a></td>
-        </tr>
-
-        <tr class="a">
-          <td><img src="continuum_files/icon_warning_sml.gif" alt="Error"></td>
-          <td><a href="viewProject.html">Maven Assembly Plugin</a></td>
-          <td>2.1-SNAPSHOT</td>
-          <td><a href="viewBuild.html">2</a></td>
-         
-          <td><a href="#">Build&nbsp;Now</a></td>
-          <td><a href="builds.html">Build&nbsp;History</a></td>
-          <td><a href="workingCopy.html">Working&nbsp;Copy</a></td>
-          <td><a href="deleteProject.html">Delete</a></td>
-        </tr>
-
-      </tbody></table>
-      
-      <div class="functnbar3">
-      <form method="post" action="#">
-        <img src="continuum_files/icon_success_sml.gif" alt="Success"> 0
-        <img src="continuum_files/icon_error_sml.gif" alt="Failed"> 0
-        <img src="continuum_files/icon_warning_sml.gif" alt="Error"> 2
-        <input name="action" value="cam" type="hidden">
-        <input name="cid" value="buildAllProjects" type="hidden">
-        <input name="build-broken" value="Build All In Error" type="submit">
-        <input name="build-all" value="Build All" type="submit">
-      </form>
-    </div>
-  </div>
-</div>
-
-<div style="margin-top: 5em; color: #555; border: 1px dashed black; padding: 1em; width: 75%; margin-left: auto; margin-right: auto;">
-  <p>Other thoughts:</p>
-  <ul>
-    <li>
-      What should "Build Now" do if there is more than one build definition? Ignoring the difference in schedules, there
-      may be different profiles - should we have a default that is used, use the next one coming, or go to a selection page?
-    </li>
-    <li>
-      Not sure I like the links on the name and build#, but the number of links on the right was making it hard to
-      view in a smaller resolution.
-      Maybe we can work on replacing them by icons.
-    </li>
-    <li>
-      (evenisse) we can use checkbox for choose projects and use some buttons that run an action on all checked
-      projects (build now, cancel build, delete). Icons will be better than links.
-    </li>
-    <li>
-      I think edit can stand to be on the view page (gotten to by the link on the project here)
-    </li>
-    <li>
-      Project group could be represented by a banner over the set of projects it represents instead of a column,
-      perhaps with a show/hide button to fold it
-      up and down, and a view/edit button.
-    </li>
-    <li>
-      I'm not sure a front page with just groups and then drilling down is useful, hence the fold up,down idea. What
-      might be good when we
-      have user accounts is to have a dashboard and to make certain project groups portlets that can go on a
-      dashboard. Later.
-    </li>
-    <li>
-      Build summary could be inside each group as well as at the bottom for all. Any folded groups could just have
-      the summary.
-    </li>
-  </ul></div>
-
-</div>
-</td>
-</tr>
-</tbody></table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/login.html b/design/old-white-site/login.html
deleted file mode 100644
index 804d0dc..0000000
--- a/design/old-white-site/login.html
+++ /dev/null
@@ -1,174 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-  <td id="leftcol" width="30%">
-    <div id="navcolum">
-      <div id="projectmenu" class="toolgroup">
-        <div class="label">Continuum</div>
-
-        <div class="body">
-          <div><a href="index.html">Show Projects</a></div>
-
-          <div><a href="schedule.html">View Build Schedule</a></div>
-        </div>
-      </div>
-
-      <div id="projecttools" class="toolgroup">
-        <div class="label">Add Project</div>
-
-        <div class="body">
-          <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-          <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-          <div><a href="addAntProject.html">Ant Project</a></div>
-
-          <div><a href="addShellProject.html">Shell Project</a></div>
-        </div>
-      </div>
-
-      <div id="projectimport" class="toolgroup">
-        <div class="label">Import Project</div>
-
-        <div class="body">
-          <div>
-            <a href="addCruiseControlProject.html">CruiseControl</a>
-          </div>
-        </div>
-      </div>
-
-      <div style="margin-top: 5em; color: #555; border: 1px dashed black; padding: 1em;">
-        <p>Notes:</p>
-        <ul>
-          <li>Log out only drops you here if Guest does not have priviledges to view access and pages, otherwise logout
-            drops you to the index page</li>
-          <li>Create user link is only present if the system allows anonymous account creation</li>
-        </ul>
-      </div>
-    </div>
-  </td>
-  <td>
-    <div id="bodycol">
-      <div class="app">
-        <div id="axial" class="h3">
-          <h3>Login</h3>
-
-          <form method="post" action="viewProject.html">
-            <input type="hidden" name="fid" value="antProject"/>
-
-            <input type="hidden" name="action" value="addEntity"/>
-            <input type="hidden" name="view" value="Summary.vm"/>
-            <input type="hidden" name="id" value="$id"/>
-
-            <div class="axial">
-              <table border="1" cellspacing="2" cellpadding="3" width="100%">
-                <tr>
-
-                  <th>Username</th>
-
-
-                  <td>
-                    <input type="text" name="username" value="" size="40"/>
-                    <small><a href="createUser.html">Create A New Account</a></small>
-                  </td>
-                </tr>
-                <tr>
-                  <th>Password</th>
-
-
-                  <td>
-                    <input type="password" value="" size="40"/>
-                    <small><a href="forgotPassword.html">Forgotten password?</a></small>
-                  </td>
-                </tr>
-                <tr>
-                  <th>&nbsp;</th>
-
-
-                  <td>
-                    <input type="checkbox" checked="checked"/>&nbsp;Remember me
-                  </td>
-                </tr>
-              </table>
-              <div class="functnbar3">
-                <input type="submit" value="Submit"/>
-              </div>
-            </div>
-          </form>
-
-        </div>
-      </div>
-
-    </div></td>
-</tr>
-</tbody>
-</table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/manageGroup.html b/design/old-white-site/manageGroup.html
deleted file mode 100644
index 64b97f7..0000000
--- a/design/old-white-site/manageGroup.html
+++ /dev/null
@@ -1,295 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-    <div style="margin-top: 5em; color: #555; border: 1px dashed black; padding: 1em;">
-      <p>Notes:</p>
-      <ul>
-       <li></li>
-      </ul>
-    </div>
-  </div>
-</td>
-<td>
-<div id="bodycol">
-<div class="app">
-
-<div>
-  <p style="border-top: 1px solid transparent; border-bottom: 1px solid black;">
-    <b style="border: 1px solid black; padding-left: 1em; padding-right: 1em;"><a href="groupStatus.html">Status</a></b>
-    <b style="border: 1px solid black; padding-left: 1em; padding-right: 1em;"><a href="manageGroup.html">Manage</a></b>
-  </p>
-</div>
-
-<div id="axial" class="h3">
-<h3>Continuum Project Group</h3>
-
-<div class="axial">
-  <table border="1" cellspacing="2" cellpadding="3" width="100%">
-
-    <tr class="b">
-      <th>Project Group Name</th>
-      <td>Plexus</td>
-    </tr>
-    <tr class="b">
-      <th>Maven Group ID</th>
-      <td>org.codehaus.plexus</td>
-    </tr>
-    <tr class="b">
-      <th>Description</th>
-      <td>&nbsp;</td>
-    </tr>
-  </table>
-  <div class="functnbar3">
-    <table>
-      <tr>
-        <td>
-          <form method="post" action="editGroup.html">
-
-            <input type="hidden" name="action" value="cam"/>
-            <input type="hidden" name="cid" value="checkoutProject"/>
-            <input type="hidden" name="id" value="43"/>
-            <input type="submit" name="edit-project" value="Edit"/>
-          </form>
-        </td>
-      </tr>
-    </table>
-  </div>
-</div>
-
-<h3>Projects</h3>
-<table border="1" cellspacing="2" cellpadding="3" width="100%">
-  <tr>
-
-    <th>Name</th>
-  </tr>
-  <tr class="b">
-    <td><a href="viewProject.html">Plexus Utils</a></td>
-  </tr>
-  <tr class="b">
-    <td><a href="viewProject.html">Default Plexus Container</a></td>
-  </tr>
-
-</table>
-
-<h3>Shared Notifiers</h3>
-<table border="1" cellspacing="2" cellpadding="3" width="100%">
-  <tr>
-
-    <th>Type</th>
-    <th>Recipient</th>
-    <th>Events</th>
-    <th width="10%">&nbsp;</th>
-  </tr>
-  <tr class="b">
-    <td>Mail</td>
-    <td>dev@plexus.codehaus.org</td>
-    <td>Failures</td>
-    <td><a href="addNotifier.html">Edit</a> | <a href="#">Delete</a></td>
-  </tr>
-  <tr class="b">
-    <td>Mail</td>
-    <td><i>All Project Developers</i></td>
-    <td>Failures</td>
-    <td><a href="addNotifier.html">Edit</a> | <a href="#">Delete</a></td>
-  </tr>
-
-</table>
-<div class="functnbar3">
-  <table>
-    <tr>
-      <td>
-        <form method="post" action="addNotifier.html">
-
-          <input type="hidden" name="action" value="cam"/>
-          <input type="hidden" name="cid" value="checkoutProject"/>
-          <input type="hidden" name="id" value="43"/>
-          <input type="submit" name="add-notifier" value="Add"/>
-        </form>
-      </td>
-    </tr>
-  </table>
-</div>
-
-<h3>Shared Build Definitions</h3>
-<table border="1" cellspacing="2" cellpadding="3" width="100%">
-  <tr>
-
-    <th>Goals</th>
-    <th>Arguments</th>
-    <th>POM File</th>
-    <th>Profile</th>
-    <th>Schedule</th>
-    <th width="10%">&nbsp;</th>
-  </tr>
-  <tr class="b">
-    <td>clean:clean install</td>
-    <td>--batch-mode</td>
-    <td>pom.xml</td>
-    <td><a href="viewProfile.html">Maven 2.0 Default</a></td>
-    <td><a href="viewSchedule.html">Hourly</a></td>
-    <td><a href="addBuildDef.html">Edit</a> | <a href="#">Delete</a></td>
-  </tr>
-
-</table>
-<div class="functnbar3">
-  <table>
-    <tr>
-      <td>
-        <form method="post" action="addBuildDef.html">
-
-          <input type="hidden" name="action" value="cam"/>
-          <input type="hidden" name="cid" value="checkoutProject"/>
-          <input type="hidden" name="id" value="43"/>
-          <input type="submit" name="add-build-def" value="Add"/>
-        </form>
-      </td>
-    </tr>
-  </table>
-</div>
-
-<h3>Role Definitions</h3>
-<table border="1" cellspacing="2" cellpadding="3" width="100%">
-  <tr>
-
-    <th>Role</th>
-    <th>Permissions</th>
-    <th>Members</td>
-    
-  </tr>
-  <tr class="b">
-    <td>admin</td>
-    <td>view project<br/>add projects<br/>trigger builds<br/>manage users</td>
-    <td>jason<br/>brett</td>
-  </tr>
-    <tr class="b">
-    <td>user</td>
-    <td>view project<br/>trigger builds</td>
-    <td>trygvis</td>
-  </tr>
-
-</table>
-<div class="functnbar3">
-  <table>
-    <tr>
-      <td>
-        <form method="post" action="editRoles.html">
-
-          <input type="hidden" name="action" value="cam"/>
-          <input type="submit" name="add-build-def" value="Edit Roles"/>
-        </form>
-      </td>
-    </tr>
-  </table>
-</div>
-
-</div>
-</div>
-</div>
-</td>
-</tr>
-</tbody></table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/performRelease.html b/design/old-white-site/performRelease.html
deleted file mode 100644
index 8c772ab..0000000
--- a/design/old-white-site/performRelease.html
+++ /dev/null
@@ -1,188 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-    <div style="margin-top: 5em; color: #555; border: 1px dashed black; padding: 1em;">
-      <p>Notes:</p>
-      <ul>
-        <li>different sections for different project types (Maven1 home, Ant home, no Java home for shell projects,
-          etc)</li>
-      </ul>
-    </div>
-  </div>
-</td>
-<td>
-  <div id="bodycol">
-    <div class="app">
-      <div id="axial" class="h3">
-        <h3>Perform Project Release - <a href="viewGroup.html">Plexus</a></h3>
-
-        <form method="post" action="performReleaseProgress.html">
-
-          <div class="axial">
-            <h4>Release Parameters</h4>
-            <table border="1" cellspacing="2" cellpadding="3" width="100%">
-              <tr>
-                <th><font color="red">*</font>Connection URL</th>
-                <td>
-                  <input type="text" name="release.releaseVersion" value="default is a known preparedRelease SCM connection" size="40"/>
-                </td>
-              </tr>
-              <tr>
-                <th>SCM Username</th>
-                <td>
-                  <input type="text" name="release.scmUsername" value="" size="40"/>
-                </td>
-              </tr>
-              <tr>
-                <th>SCM Password</th>
-                <td>
-                  <input type="text" name="release.scmPassword" value="" size="40"/>
-                </td>
-              </tr>
-              <tr>
-                <th>SCM Tag</th>
-                <td>
-                  <input type="text" name="release.scmTag" value="" size="40"/>
-                </td>
-              </tr>
-              <tr>
-                <th>SCM Tagbase</th>
-                <td>
-                  <input type="text" name="release.scmTagbase" value="" size="40"/>
-                </td>
-              </tr>
-              <tr>
-                <th>Maven Arguments</th>
-                <td>
-                  <input type="text" name="release.arguments" value="" size="40"/>
-                </td>
-              </tr>
-              <tr>
-                <th>Use Release Profile</th>
-                <td>
-                  <select name="release.useProfile">
-                    <option value="false">False</option>
-                    <option value="true">True</option>
-                  </select>
-                </td>
-              </tr>
-            </table>
-
-            <div class="functnbar3">
-              <input type="submit" value="Submit"/>
-            </div>
-          </div>
-        </form>
-
-      </div>
-    </div>
-
-  </div></td>
-</tr>
-</tbody>
-</table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
diff --git a/design/old-white-site/performReleaseFinish.html b/design/old-white-site/performReleaseFinish.html
deleted file mode 100644
index 8da60e9..0000000
--- a/design/old-white-site/performReleaseFinish.html
+++ /dev/null
@@ -1,176 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-    <div style="margin-top: 5em; color: #555; border: 1px dashed black; padding: 1em;">
-      <p>Notes:</p>
-      <ul>
-        <li></li>
-      </ul>
-    </div>
-  </div>
-</td>
-<td>
-<div id="bodycol">
-<div class="app">
-
-<div id="axial" class="h3">
-<h3>Continuum Release</h3>
-
-    <h4><a href="viewGroup.html">Plexus</a></h4>
-    <table id="projectSummaryTable" border="1" cellpadding="3" cellspacing="2" width="100%">
-
-      <!-- i18n -->
-      <tbody><tr>
-        <th>&nbsp;</th>
-        <th>Phase</th>
-      </tr>
-
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Verify release configuration</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Verify completed release:prepare phases</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Configure repositories</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Checkout project from SCM</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Build project</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>End Release</td>
-        </tr>
-
-      </tbody></table>
-
-      <div class="functnbar3">
-        <form action="groupStatus.html">
-          <input type="submit" value="Done"/>&nbsp;&nbsp;<a href="viewBuild.html">View Build Output</a>
-        </form>
-      </div>
-
-</div>
-</div>
-</td>
-</tr>
-</tbody></table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
diff --git a/design/old-white-site/performReleaseProgress.html b/design/old-white-site/performReleaseProgress.html
deleted file mode 100644
index 86ba51d..0000000
--- a/design/old-white-site/performReleaseProgress.html
+++ /dev/null
@@ -1,176 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-    <div style="margin-top: 5em; color: #555; border: 1px dashed black; padding: 1em;">
-      <p>Notes:</p>
-      <ul>
-        <li></li>
-      </ul>
-    </div>
-  </div>
-</td>
-<td>
-<div id="bodycol">
-<div class="app">
-
-<div id="axial" class="h3">
-<h3>Continuum Release</h3>
-
-    <h4><a href="viewGroup.html">Plexus</a></h4>
-    <table id="projectSummaryTable" border="1" cellpadding="3" cellspacing="2" width="100%">
-
-      <!-- i18n -->
-      <tbody><tr>
-        <th>&nbsp;</th>
-        <th>Phase</th>
-      </tr>
-
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Verify release configuration</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Verify completed release:prepare phases</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Configure repositories</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_in_progress_sml.gif" alt="In Progress"></td>
-          <td>Checkout project from SCM</td>
-        </tr>
-
-        <tr class="b">
-          <td>&nbsp;</td>
-          <td>Build project</td>
-        </tr>
-
-        <tr class="b">
-          <td>&nbsp;</td>
-          <td>End Release</td>
-        </tr>
-
-      </tbody></table>
-
-      <div class="functnbar3">
-        <form action="performReleaseFinish.html">
-          <input type="submit" value="Refresh"/>
-        </form>
-      </div>
-
-</div>
-</div>
-</td>
-</tr>
-</tbody></table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
diff --git a/design/old-white-site/prepareRelease.html b/design/old-white-site/prepareRelease.html
deleted file mode 100644
index 8e24bea..0000000
--- a/design/old-white-site/prepareRelease.html
+++ /dev/null
@@ -1,237 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-    <div style="margin-top: 5em; color: #555; border: 1px dashed black; padding: 1em;">
-      <p>Notes:</p>
-      <ul>
-        <li>different sections for different project types (Maven1 home, Ant home, no Java home for shell projects,
-          etc)</li>
-      </ul>
-    </div>
-  </div>
-</td>
-<td>
-  <div id="bodycol">
-    <div class="app">
-      <div id="axial" class="h3">
-
-        <h3>Prepare Project Release - <a href="viewGroup.html">Plexus</a></h3>
-          <form method="post" action="prepareReleaseProgress.html">
-
-          <div class="axial">
-            <h4>Common Release Parameters</h3>
-            <table border="1" cellspacing="2" cellpadding="3" width="100%">
-              <tr>
-                <th>SCM Username</th>
-                <td>
-                  <input type="text" name="release.scmUsername" value="" size="40"/>
-                </td>
-              </tr>
-              <tr>
-                <th>SCM Password</th>
-                <td>
-                  <input type="text" name="release.scmPassword" value="" size="40"/>
-                </td>
-              </tr>
-              <tr>
-                <th>SCM Tag</th>
-                <td>
-                  <input type="text" name="release.scmTag" value="" size="40"/>
-                </td>
-              </tr>
-              <tr>
-                <th>SCM Tagbase</th>
-                <td>
-                  <input type="text" name="release.scmTagbase" value="" size="40"/>
-                </td>
-              </tr>
-              <tr>
-                <th>Maven Arguments</th>
-                <td>
-                  <input type="text" name="release.arguments" value="" size="40"/>
-                </td>
-              </tr>
-            </table>
-
-            <h4><a href="viewProject.html">Plexus</a> (parent)</h4>
-            <table border="1" cellspacing="2" cellpadding="3" width="100%">
-              <tr>
-                <th><font color="red">*</font>Release Version</th>
-                <td>
-                  <input type="text" name="release.releaseVersion" value="1.0.6" size="40"/>
-                </td>
-              </tr>
-              <tr>
-                <th><font color="red">*</font>New Development Version</th>
-                <td>
-                  <input type="text" name="release.nextVersion" value="1.0.7-SNAPSHOT" size="40"/>
-                </td>
-              </tr>
-            </table>
-
-            <h4><a href="viewProject.html">Plexus Default Container</a></h4>
-            <table border="1" cellspacing="2" cellpadding="3" width="100%">
-              <tr>
-                <th><font color="red">*</font>Release Version</th>
-                <td>
-                  <input type="text" name="release.releaseVersion" value="1.0.6" size="40"/>
-                </td>
-              </tr>
-              <tr>
-                <th><font color="red">*</font>New Development Version</th>
-                <td>
-                  <input type="text" name="release.nextVersion" value="1.0.7-SNAPSHOT" size="40"/>
-                </td>
-              </tr>
-            </table>
-
-            <h4><a href="viewProject.html">Plexus Utils</a></h4>
-            <table border="1" cellspacing="2" cellpadding="3" width="100%">
-              <tr>
-                <th><font color="red">*</font>Release Version</th>
-                <td>
-                  <input type="text" name="release.releaseVersion" value="1.0.2" size="40"/>
-                </td>
-              </tr>
-              <tr>
-                <th><font color="red">*</font>New Development Version</th>
-                <td>
-                  <input type="text" name="release.nextVersion" value="1.0.3-SNAPSHOT" size="40"/>
-                </td>
-              </tr>
-            </table>
-
-            <h4><a href="viewProject.html">Plexus Action</a></h4>
-            <table border="1" cellspacing="2" cellpadding="3" width="100%">
-              <tr>
-                <th><font color="red">*</font>Release Version</th>
-                <td>
-                  <input type="text" name="release.releaseVersion" value="1.0.6" size="40"/>
-                </td>
-              </tr>
-              <tr>
-                <th><font color="red">*</font>New Development Version</th>
-                <td>
-                  <input type="text" name="release.nextVersion" value="1.0.7-SNAPSHOT" size="40"/>
-                </td>
-              </tr>
-            </table>
-
-            <div class="functnbar3">
-              <input type="submit" value="Submit"/>
-            </div>
-          </div>
-        </form>
-
-      </div>
-    </div>
-
-  </div></td>
-</tr>
-</tbody>
-</table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
diff --git a/design/old-white-site/prepareReleaseFinish.html b/design/old-white-site/prepareReleaseFinish.html
deleted file mode 100644
index d801013..0000000
--- a/design/old-white-site/prepareReleaseFinish.html
+++ /dev/null
@@ -1,221 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-    <div style="margin-top: 5em; color: #555; border: 1px dashed black; padding: 1em;">
-      <p>Notes:</p>
-      <ul>
-        <li></li>
-      </ul>
-    </div>
-  </div>
-</td>
-<td>
-<div id="bodycol">
-<div class="app">
-
-<div id="axial" class="h3">
-<h3>Continuum Release</h3>
-
-    <h4><a href="viewGroup.html">Plexus</a></h4>
-    <table id="projectSummaryTable" border="1" cellpadding="3" cellspacing="2" width="100%">
-
-      <!-- i18n -->
-      <tbody><tr>
-        <th>&nbsp;</th>
-        <th>Phase</th>
-      </tr>
-
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Check Pom</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Check for SCM modifications</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Check for snapshot dependencies</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Map release versions</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Apply defaults to missing optional parameters</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Map development versions</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Rewrite poms for release</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Generate release poms</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Run preparation goals</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>SCM commit release</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>SCM tag</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Rewrite poms for development</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Remove release poms</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>SCM commit development poms</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>End release</td>
-        </tr>
-
-      </tbody></table>
-
-      <div class="functnbar3">
-        <form action="groupStatus.html">
-          <input type="submit" value="Done"/>&nbsp;&nbsp;<a href="viewBuild.html">View Build Output</a>
-        </form>
-      </div>
-
-</div>
-</div>
-</td>
-</tr>
-</tbody></table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
diff --git a/design/old-white-site/prepareReleaseProgress.html b/design/old-white-site/prepareReleaseProgress.html
deleted file mode 100644
index dbcb6f8..0000000
--- a/design/old-white-site/prepareReleaseProgress.html
+++ /dev/null
@@ -1,221 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-    <div style="margin-top: 5em; color: #555; border: 1px dashed black; padding: 1em;">
-      <p>Notes:</p>
-      <ul>
-        <li></li>
-      </ul>
-    </div>
-  </div>
-</td>
-<td>
-<div id="bodycol">
-<div class="app">
-
-<div id="axial" class="h3">
-<h3>Continuum Release</h3>
-
-    <h4><a href="viewGroup.html">Plexus</a></h4>
-    <table id="projectSummaryTable" border="1" cellpadding="3" cellspacing="2" width="100%">
-
-      <!-- i18n -->
-      <tbody><tr>
-        <th>&nbsp;</th>
-        <th>Phase</th>
-      </tr>
-
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Check Pom</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Check for SCM modifications</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Check for snapshot dependencies</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Map release versions</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Apply defaults to missing optional parameters</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Map development versions</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Rewrite poms for release</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Generate release poms</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_success_sml.gif" alt="Success"></td>
-          <td>Run preparation goals</td>
-        </tr>
-
-        <tr class="b">
-          <td><img src="continuum_files/icon_in_progress_sml.gif" alt="In Progress"></td>
-          <td>SCM commit release</td>
-        </tr>
-
-        <tr class="b">
-          <td>&nbsp;</td>
-          <td>SCM tag</td>
-        </tr>
-
-        <tr class="b">
-          <td>&nbsp;</td>
-          <td>Rewrite poms for development</td>
-        </tr>
-
-        <tr class="b">
-          <td>&nbsp;</td>
-          <td>Remove release poms</td>
-        </tr>
-
-        <tr class="b">
-          <td>&nbsp;</td>
-          <td>SCM commit development poms</td>
-        </tr>
-
-        <tr class="b">
-          <td>&nbsp;</td>
-          <td>End release</td>
-        </tr>
-
-      </tbody></table>
-
-      <div class="functnbar3">
-        <form action="prepareReleaseFinish.html">
-          <input type="submit" value="Refresh"/>
-        </form>
-      </div>
-
-</div>
-</div>
-</td>
-</tr>
-</tbody></table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
diff --git a/design/old-white-site/profiles.html b/design/old-white-site/profiles.html
deleted file mode 100644
index 0781f4e..0000000
--- a/design/old-white-site/profiles.html
+++ /dev/null
@@ -1,185 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Logged in as: <b>Brett Porter</b> | <a href="userProfile.html">Profile</a> | <a href="login.html">Log out</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-    <div id="admin" class="toolgroup">
-      <div class="label">Administration</div>
-
-      <div class="body">
-        <div>
-          <a href="profiles.html">Profiles</a>
-        </div>
-
-        <div>
-          <a href="schedules.html">Schedules</a>
-        </div>
-
-        <div>
-          <a href="configuration.html">Configuration</a>
-        </div>
-
-        <div>
-          <a href="users.html">Users</a>
-        </div>
-      </div>
-    </div>
-  </div>
-</td>
-<td>
-  <div id="bodycol">
-
-
-    <div class="app">
-      <div id="h3">
-        <h3>Profiles</h3>
-        <table border="1" cellspacing="2" cellpadding="3" width="100%">
-          <tr>
-            <th>Name</th>
-            <th>Type</th>
-            <th>Description</th>
-            <th width="10%">&nbsp;</th>
-          </tr>
-          <tr class="b">
-            <td><a href="viewProfile.html">Maven 2.0 Default</a></td>
-            <td>Maven 2.0</td>
-            <td>Default profile for Maven 2.0 projects that uses the M2_HOME and JAVA_HOME environment variables</td>
-            <td><a href="editProfile.html">Edit</a> | <a href="#">Delete</a></td>
-          </tr>
-          <tr class="b" style="color: silver;">
-            <td><a href="viewProfile.html">JDK 1.3, Clean checkout</a> <strong>(disabled)</strong></td>
-            <td>Maven 2.0</td>
-            <td>JDK 1.3</td>
-            <td><a href="editProfile.html">Edit</a> | <a href="#">Delete</a></td>
-          </tr>
-        </table>
-        <div class="functnbar3">
-          <table>
-            <tr>
-              <td>
-                <form method="post" action="editProfile.html">
-                  <select>
-                    <option selected="selected">Maven 2.0</option>
-                    <option>Maven 1.x</option>
-                    <option>Ant</option>
-                    <option>Generic</option>
-                  </select>
-                  <input type="hidden" name="action" value="cam"/>
-                  <input type="hidden" name="cid" value="checkoutProject"/>
-                  <input type="hidden" name="id" value="43"/>
-                  <input type="submit" name="add-build-def" value="Add"/>
-                </form>
-              </td>
-            </tr>
-          </table>
-        </div>
-      </div>
-    </div>
-
-  </div>
-</td>
-</tr>
-</tbody></table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/releaseProject.html b/design/old-white-site/releaseProject.html
deleted file mode 100644
index f31cb9e..0000000
--- a/design/old-white-site/releaseProject.html
+++ /dev/null
@@ -1,159 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script language="javascript">
-    function submitAction()
-    {
-      if ( document.actionForm.action[0].checked == true )
-      {
-        window.location.href = "prepareRelease.html";
-      }
-      else
-      {
-        window.location.href = "performRelease.html";
-      }
-    }
-  </script>
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-  </div>
-</td>
-<td>
-  <div id="bodycol">
-    <div class="app">
-      <div id="axial" class="h3">
-        <h3>Continuum Release - Plexus</h3>
-
-        <form name="actionForm" method="post">
-          <div class="axial">
-            <p>
-              <input type="radio" name="action" value="prepare" checked />Prepare project for release
-            </p>
-
-            <p>
-              <input type="radio" name="action" value="perfrom"/>Perform project release<br/>
-              <select name="releaseId">
-                <option value="0">provide arbitrary scm tag</option>
-                <option value="1">prev prepared release #1</option>
-                <option value="2">prev prepared release #2</option>
-                <option value="3">prev prepared release #3</option>
-              </select>
-            </p>
-
-            <div class="functnbar3">
-              <input type="button" value="Submit" onClick="submitAction();"/>
-            </div>
-          </div>
-        </form>
-
-      </div>
-    </div>
-  </div>
-</td>
-</tr>
-</tbody>
-</table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
diff --git a/design/old-white-site/schedule.html b/design/old-white-site/schedule.html
deleted file mode 100644
index 45e5ac8..0000000
--- a/design/old-white-site/schedule.html
+++ /dev/null
@@ -1,171 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-  <tbody><tr valign="top">
-    <td id="leftcol" width="30%">
-      <div id="navcolum">
-        <div id="projectmenu" class="toolgroup">
-          <div class="label">Continuum</div>
-
-          <div class="body">
-            <div><a href="index.html">Show Projects</a></div>
-
-            <div><a href="schedule.html">View Build Schedule</a></div>
-          </div>
-        </div>
-
-        <div id="projecttools" class="toolgroup">
-          <div class="label">Add Project</div>
-
-          <div class="body">
-            <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-            <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-            <div><a href="addAntProject.html">Ant Project</a></div>
-
-            <div><a href="addShellProject.html">Shell Project</a></div>
-          </div>
-        </div>
-
-        <div id="projectimport" class="toolgroup">
-          <div class="label">Import Project</div>
-
-          <div class="body">
-            <div>
-              <a href="addCruiseControlProject.html">CruiseControl</a>
-            </div>
-          </div>
-        </div>
-
-      </div>
-    </td>
-    <td>
-      <div id="bodycol">
-        <div class="app">
-          <div id="h3">
-            <h3>Build Schedule</h3>
-
-            <table width="100%">
-              <tr>
-                <th colspan="4">Recently Completed (last hour)</th>
-              </tr>
-              <tr>
-                <th width="10%">Time</th><th>Build</th><th width="20%">Profile</th><th width="10%">&nbsp;</th>
-              </tr>
-              <tr>
-                <td>1/5/04 10:00am</td><td><a href="viewGroup.html">Plexus (Group)</a></td><td><a
-                      href="viewProfile.html">Maven 2.0 Default</a></td><td><a href="viewBuild.html">Details</a></td>
-              </tr>
-            </table>
-            <br/>
-            <table width="100%">
-              <tr>
-                <th colspan="4">In Progress</th>
-              </tr>
-              <tr>
-                <th width="10%">&nbsp;</th><th>Build</th><th width="20%">Profile</th><th width="10%">&nbsp;</th>
-              </tr>
-              <tr>
-                <td>In progress</td><td><a href="viewProject.html">plexus-utils</a></td><td><a
-                      href="viewProfile.html">Maven 2.0 Default</a></td><td><a href="#">Cancel</a></td>
-              </tr>
-            </table>
-            <br/>
-            <table width="100%">
-              <tr>
-                <th colspan="4">Coming Up (next 2 hours)</th>
-              </tr>
-              <tr>
-                <th width="10%">Time</th><th>Build</th><th width="20%">Profile</th><th width="10%">&nbsp;</th>
-              </tr>
-              <tr>
-                <td>1/5/04 11:00am</td><td><a href="viewProject.html">plexus-utils</a></td><td><a
-                      href="viewProfile.html">JDK 1.3, Clean checkout</a></td><td><a href="schedule.html">Build
-                Now</a> | <a href="schedule.html">Skip</a></td>
-              </tr>
-              <tr>
-                <td>1/5/04 12:00pm</td><td><a href="viewGroup.html">Plexus (Group)</a></td><td><a
-                      href="viewProfile.html">Maven 2.0 Default</a></td><td><a href="schedule.html">Build Now</a>
-                | <a href="schedule.html">Skip</a></td>
-              </tr>
-              <tr>
-                <td>&nbsp;</td><td><a href="viewProject.html">plexus-utils</a></td><td><a href="viewProfile.html">JDK
-                1.3, Clean checkout</a></td><td><a href="schedule.html">Build
-                Now</a> | <a href="schedule.html">Skip</a></td>
-              </tr>
-            </table>
-          </div>
-        </div>
-      </div>
-    </td>
-  </tr>
-  </tbody></table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/schedules.html b/design/old-white-site/schedules.html
deleted file mode 100644
index 849fe87..0000000
--- a/design/old-white-site/schedules.html
+++ /dev/null
@@ -1,183 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Logged in as: <b>Brett Porter</b> | <a href="userProfile.html">Profile</a> | <a href="login.html">Log out</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-    <div id="admin" class="toolgroup">
-      <div class="label">Administration</div>
-
-      <div class="body">
-        <div>
-          <a href="profiles.html">Profiles</a>
-        </div>
-
-        <div>
-          <a href="schedules.html">Schedules</a>
-        </div>
-
-        <div>
-          <a href="configuration.html">Configuration</a>
-        </div>
-
-        <div>
-          <a href="users.html">Users</a>
-        </div>
-      </div>
-    </div>
-  </div>
-</td>
-<td>
-  <div id="bodycol">
-
-
-    <div class="app">
-      <div id="h3">
-        <h3>Schedules</h3>
-        <table border="1" cellspacing="2" cellpadding="3" width="100%">
-          <tr>
-            <th>Name</th>
-            <th>Description</th>
-            <th>Cron</th>
-            <th>Quiet Period (seconds)</th>
-            <th width="10%">&nbsp;</th>
-          </tr>
-          <tr class="b">
-            <td><a href="viewSchedule.html">Weekly</a></td>
-            <td>Run weekly</td>
-            <td>0 0 0 * *</td>
-            <td>0</td>
-            <td><a href="editSchedule.html">Edit</a> | <a href="#">Delete</a></td>
-          </tr>
-          <tr class="b" style="color: silver;">
-            <td><a href="viewSchedule.html">Hourly</a> <strong>(disabled)</strong></td>
-            <td>Run hourly</td>
-            <td>0 * * * *</td>
-            <td>15</td>
-            <td><a href="editSchedule.html">Edit</a> | <a href="#">Delete</a></td>
-          </tr>
-        </table>
-        <div class="functnbar3">
-          <table>
-            <tr>
-              <td>
-                <form method="post" action="editSchedule.html">
-
-                  <input type="hidden" name="action" value="cam"/>
-                  <input type="hidden" name="cid" value="checkoutProject"/>
-                  <input type="hidden" name="id" value="43"/>
-                  <input type="submit" name="add-build-def" value="Add"/>
-                </form>
-              </td>
-            </tr>
-          </table>
-        </div>
-      </div>
-    </div>
-
-  </div>
-</td>
-</tr>
-</tbody></table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/userProfile.html b/design/old-white-site/userProfile.html
deleted file mode 100644
index 68ed59f..0000000
--- a/design/old-white-site/userProfile.html
+++ /dev/null
@@ -1,274 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Logged in as: <b>Brett Porter</b> | <a href="userProfile.html">Profile</a> | <a href="login.html">Log out</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-    <div style="margin-top: 5em; color: #555; border: 1px dashed black; padding: 1em;">
-      <p>Notes:</p>
-      <ul>
-        <li>Note that only the administrator and user should be able to access this page</li>
-        <li>Only the administrator should be able to edit the permissions</li>
-        <li>Should permissions relate to POM roles? How can we really do that securely?</li>
-        <li>Under roles, if user has rights to edit the role, then the edit list renders</li>
-      </ul>
-    </div>
-  </div>
-</td>
-<td>
-<div id="bodycol">
-<div class="app">
-
-<div id="axial" class="h3">
-<h3>User Profile</h3>
-
-<div class="axial">
-  <table border="1" cellspacing="2" cellpadding="3" width="100%">
-
-    <tr class="b">
-      <th>Full Name</th>
-      <td>Brett Porter</td>
-    </tr>
-    <tr class="b">
-      <th>Email</th>
-      <td>brett@apache.org</td>
-    </tr>
-  </table>
-  <div class="functnbar3">
-    <table>
-      <tr>
-        <td>
-          <form method="post" action="editUser.html">
-
-            <input type="hidden" name="action" value="cam"/>
-            <input type="hidden" name="cid" value="checkoutProject"/>
-            <input type="hidden" name="id" value="43"/>
-            <input type="submit" name="edit-project" value="Edit"/>
-          </form>
-        </td>
-      </tr>
-    </table>
-  </div>
-</div>
-
-
-<h3>Permissions</h3>
-<table border="1" cellspacing="2" cellpadding="3" width="100%">
-  <tr>
-
-    <th>Permission</th>
-    <th width="10%">&nbsp;</th>
-  </tr>
-  <tr class="b">
-    <td>Administrator</td>
-    <td><a href="#">Delete</a></td>
-  </tr>
-  <tr class="b">
-    <td>Build Monkey</td>
-    <td><a href="#">Delete</a></td>
-  </tr>
-</table>
-<div class="functnbar3">
-  <table>
-    <tr>
-      <td>
-        <form method="post" action="#">
-
-          <input type="hidden" name="action" value="cam"/>
-          <input type="hidden" name="cid" value="checkoutProject"/>
-          <input type="hidden" name="id" value="43"/>
-          <select>
-            <option>Administrator</option>
-            <option>Build Monkey</option>
-          </select>
-          <input type="submit" name="add-developer" value="Add"/>
-        </form>
-      </td>
-    </tr>
-  </table>
-</div>
-
-<h3>Notification Addresses</h3>
-<table border="1" cellspacing="2" cellpadding="3" width="100%">
-  <tr>
-
-    <th>Type</th>
-    <th>Address</th>
-    <th width="10%">&nbsp;</th>
-  </tr>
-  <tr class="b">
-    <td>Mail</td>
-    <td>brett@apache.org</td>
-    <td>&nbsp;</td>
-  </tr>
-  <tr class="b">
-    <td>Yahoo</td>
-    <td>brettporter</td>
-    <td><a href="addUserNotifier.html">Edit</a> | <a href="#">Delete</a></td>
-  </tr>
-  <tr class="b">
-    <td>IRC</td>
-    <td>irc.codehaus.org brett</td>
-    <td><a href="addUserNotifier.html">Edit</a> | <a href="#">Delete</a></td>
-  </tr>
-
-</table>
-<div class="functnbar3">
-  <table>
-    <tr>
-      <td>
-        <form method="post" action="addUserNotifier.html">
-
-          <input type="hidden" name="action" value="cam"/>
-          <input type="hidden" name="cid" value="checkoutProject"/>
-          <input type="hidden" name="id" value="43"/>
-          <input type="submit" name="add-notifier" value="Add"/>
-        </form>
-      </td>
-    </tr>
-  </table>
-</div>
-
-<h3>Assigned Roles</h3>
-<table border="1" cellspacing="2" cellpadding="3" width="100%">
-  <tr>
-
-    <th>Project</th>
-    <th>Role</th>
-    <th>&nbsp;</td>
-  </tr>
-  <tr class="b">
-    <td>Plexus</td>
-    <td>admin<br/>user</td>
-    <td><a href="editRoles.html">Edit</a></td>
-  </tr>
-  <tr class="b">
-    <td>Maven</td>
-    <td>admin<br/>user</td>   
-    <td><a href="editRoles.html">Edit</a></td>
-  </tr>
-  <tr class="b">
-    <td>Maven Plugins</td>
-    <td>user</td>
-    <td>&nbsp;</td>
-  </tr>
-
-</table>
-<div class="functnbar3">
-  <table>
-    <tr>
-      <td>
-       
-      </td>
-    </tr>
-  </table>
-</div>
-
-</div>
-</div>
-</div>
-</td>
-</tr>
-</tbody></table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/users.html b/design/old-white-site/users.html
deleted file mode 100644
index 6aee634..0000000
--- a/design/old-white-site/users.html
+++ /dev/null
@@ -1,187 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Logged in as: <b>Brett Porter</b> | <a href="userProfile.html">Profile</a> | <a href="login.html">Log out</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-    <div id="admin" class="toolgroup">
-      <div class="label">Administration</div>
-
-      <div class="body">
-        <div>
-          <a href="profiles.html">Profiles</a>
-        </div>
-
-        <div>
-          <a href="schedules.html">Schedules</a>
-        </div>
-
-        <div>
-          <a href="configuration.html">Configuration</a>
-        </div>
-
-        <div>
-          <a href="users.html">Users</a>
-        </div>
-      </div>
-    </div>
-
-    <div style="margin-top: 5em; color: #555; border: 1px dashed black; padding: 1em;">
-      <p>Notes:</p>
-      <ul>
-        <li>we'll want some paging/search on this too at some point</li>
-      </ul>
-    </div>
-
-  </div>
-</td>
-<td>
-  <div id="bodycol">
-
-
-    <div class="app">
-      <div id="h3">
-        <h3>Continuum Users</h3>
-        <table border="1" cellspacing="2" cellpadding="3" width="100%">
-          <tr>
-            <th>Username</th>
-            <th>Name</th>
-            <th>Email</th>
-            <th width="10%">&nbsp;</th>
-          </tr>
-          <tr class="b">
-            <td>jvanzyl</td>
-            <td><a href="userProfile.html">Jason van Zyl</a></td>
-            <td><a href="mailto:jason@zenplex.com">jason@zenplex.com</a></td>
-            <td><a href="#">Delete</a></td>
-          </tr>
-
-          <tr class="b">
-            <td>brett</td>
-            <td><a href="userProfile.html">Brett Porter</a></td>
-            <td><a href="mailto:brett@apache.org">brett@apache.org</a></td>
-            <td><a href="#">Delete</a></td>
-          </tr>
-          <tr class="a">
-            <td>trygvis</td>
-            <td><a href="userProfile.html">Trygve Laugstøl</a></td>
-            <td><a href="mailto:trygvis@codehaus.org">trygvis@codehaus.org</a></td>
-            <td><a href="#">Delete</a></td>
-
-          </tr>
-          <tr class="b">
-            <td>forge</td>
-            <td><a href="userProfile.html">Kenney Westerhof</a></td>
-            <td><a href="mailto:kenney@codehaus.org">kenney@codehaus.org</a></td>
-            <td><a href="#">Delete</a></td>
-          </tr>
-        </table>
-      </div>
-    </div>
-
-  </div>
-</td>
-</tr>
-</tbody></table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/viewBuild.html b/design/old-white-site/viewBuild.html
deleted file mode 100644
index c6b04d4..0000000
--- a/design/old-white-site/viewBuild.html
+++ /dev/null
@@ -1,270 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-    <div style="margin-top: 5em; color: #555; border: 1px dashed black; padding: 1em;">
-      <p>Notes:</p>
-      <ul>
-        <li>Artifacts are omitted if the build was not successful</li>
-        <li>Changes since success do not duplicate those since last build</li>
-        <li>The error on this page obviously doesn't match the result</li>
-        <li>Deleting a build should prompt to delete the artifacts too</li>
-        <li>Build trigger is one of scheduled, remote (perhaps with reason - eg SCM), forced</li>
-      </ul>
-    </div>
-
-  </div>
-</td>
-<td>
-<div id="bodycol">
-<div class="app">
-
-<div>
-  <p style="border-top: 1px solid transparent; border-bottom: 1px solid black;">
-    <a style="border: 1px solid black; padding-left: 1em; padding-right: 1em; text-decoration:none;"
-       href="viewProject.html">Info</a>
-    <a style="border: 1px solid black; padding-left: 1em; padding-right: 1em; font-weight: bold; text-decoration:none;"
-       href="builds.html">Builds</a>
-    <a style="border: 1px solid black; padding-left: 1em; padding-right: 1em; text-decoration:none;"
-       href="workingCopy.html">Working&nbsp;Copy</a>
-  </p>
-</div>
-
-<div id="axial" class="h3">
-<h3>Build result for Default Plexus Container</h3>
-<table border="1" cellspacing="2" cellpadding="3" width="100%">
-  <tr class="a">
-
-    <th>Start Time</th>
-    <td>Jul 28, 2005 3:40:20 PM</td>
-  </tr>
-  <tr class="a">
-    <th>End Time</th>
-    <td>Jul 28, 2005 3:40:40 PM</td>
-  </tr>
-
-  <tr class="a">
-    <th>Build trigger</th>
-    <td>Scheduled</td>
-  </tr>
-  <tr class="a">
-    <th>State</th>
-    <td><img src="continuum_files/icon_error_sml.gif" alt="Failed"/></td>
-  </tr>
-  <tr class="a">
-    <th>Build #</th>
-    <td>N/A</td>
-  </tr>
-</table>
-
-<p><a href="#">Delete Build</a></p>
-
-<h4>Changes Since Last Build</h4>
-
-<p>
-  <b>No files changed</b>
-</p>
-
-<h4>Other Changes Since Last Success</h4>
-
-<table border="1" cellspacing="2" cellpadding="3" width="100%">
-  <tr class="a">
-    <th>Revision</th>
-    <th>Files</th>
-    <th>Developer</th>
-    <th>Comment</th>
-  </tr>
-  <tr class="a">
-    <td>240356</td>
-    <td>
-      pom.xml<br/>
-      src/main/java/org/codehaus/plexus/DefaultPlexusContainer.java
-    </td>
-    <td>Brett Porter</td>
-    <td>
-      Configure the container from a URL
-    </td>
-  </tr>
-</table>
-
-<h4>Generated Artifacts</h4>
-
-<table border="1" cellspacing="2" cellpadding="3" width="100%">
-  <tr class="a">
-    <td><a href="#">/plexus/plexus-container-default/1.0-alpha-6-SNAPSHOT/plexus-container-default-1.0-alpha-6-20050801.143055-2.jar</a>
-    </td>
-  </tr>
-  <tr class="a">
-    <td><a href="#">/plexus/plexus-container-default/1.0-alpha-6-SNAPSHOT/plexus-container-default-1.0-alpha-6-20050801.143055-2-bin.tar.gz</a>
-    </td>
-  </tr>
-</table>
-
-<h4>Generated Reports</h4>
-
-<table border="1" cellspacing="2" cellpadding="3" width="100%">
-  <tr class="a">
-    <td><a href="#">JUnit Report</a></td>
-    <td><b style="color: green;">Success</b>: 10; <b style="color: red;">Failed</b>: 1; <b
-            style="color: red;">Error</b>: 3</td>
-  </tr>
-</table>
-
-<h4>Build Error</h4>
-
-<p>
-  <b>Reason: </b> Tests failed.
-
-<div style="width:100%; height:500px; overflow:auto; border-style: solid; border-width: 1px; white-space: pre; font-family:monospace;">
-  org.apache.maven.continuum.execution.ContinuumBuildExecutorException: Error while mapping metadata.
-  at
-  org.apache.maven.continuum.execution.maven.m2.MavenTwoBuildExecutor.updateProjectFromCheckOut(MavenTwoBuildExecutor.java:92)
-  at
-  org.apache.maven.continuum.core.action.UpdateProjectFromWorkingDirectoryContinuumAction.execute(UpdateProjectFromWorkingDirectoryContinuumAction.java:45)
-  at org.apache.maven.continuum.buildcontroller.DefaultBuildController.build(DefaultBuildController.java:183)
-  at org.apache.maven.continuum.buildcontroller.BuildProjectTaskExecutor.executeTask(BuildProjectTaskExecutor.java:50)
-  at
-  org.codehaus.plexus.taskqueue.execution.ThreadedTaskQueueExecutor$ExecutorRunnable.run(ThreadedTaskQueueExecutor.java:103)
-  at java.lang.Thread.run(Thread.java:595)
-  Caused by: org.apache.maven.continuum.execution.maven.m2.MavenBuilderHelperException: Cannot build maven project
-  from /export/home/continuum/continuum-1.0-alpha-3/apps/continuum/temp/43/pom.xml.
-  at
-  org.apache.maven.continuum.execution.maven.m2.DefaultMavenBuilderHelper.getMavenProject(DefaultMavenBuilderHelper.java:178)
-  at
-  org.apache.maven.continuum.execution.maven.m2.DefaultMavenBuilderHelper.mapMetadataToProject(DefaultMavenBuilderHelper.java:77)
-  at
-  org.apache.maven.continuum.execution.maven.m2.MavenTwoBuildExecutor.updateProjectFromCheckOut(MavenTwoBuildExecutor.java:88)
-  ... 5 more
-  Caused by: org.apache.maven.project.ProjectBuildingException: Failed to parse model from file
-  '/export/home/continuum/.m2/repository/plexus/plexus-root/1.0/plexus-root-1.0.pom'.
-  Error: 'TEXT must be immediately followed by END_TAG and not START_TAG (position: START_TAG seen ...&lt;snapshotRepository&gt;\r\n
-  &lt;id&gt;... @43:11) '
-  at org.apache.maven.project.DefaultMavenProjectBuilder.readModel(DefaultMavenProjectBuilder.java:525)
-  at org.apache.maven.project.DefaultMavenProjectBuilder.findModelFromRepository(DefaultMavenProjectBuilder.java:244)
-  at org.apache.maven.project.DefaultMavenProjectBuilder.assembleLineage(DefaultMavenProjectBuilder.java:491)
-  at org.apache.maven.project.DefaultMavenProjectBuilder.assembleLineage(DefaultMavenProjectBuilder.java:493)
-  at org.apache.maven.project.DefaultMavenProjectBuilder.build(DefaultMavenProjectBuilder.java:297)
-  at org.apache.maven.project.DefaultMavenProjectBuilder.buildFromSourceFile(DefaultMavenProjectBuilder.java:198)
-  at org.apache.maven.project.DefaultMavenProjectBuilder.build(DefaultMavenProjectBuilder.java:186)
-  at
-  org.apache.maven.continuum.execution.maven.m2.DefaultMavenBuilderHelper.getMavenProject(DefaultMavenBuilderHelper.java:170)
-  ... 7 more
-  Caused by: org.codehaus.plexus.util.xml.pull.XmlPullParserException: TEXT must be immediately followed by END_TAG
-  and not START_TAG (position: START_TAG seen ...&lt;snapshotRepository&gt;\r\n      &lgt;id&gt;... @43:11)
-  at org.codehaus.plexus.util.xml.pull.MXParser.nextText(MXParser.java:1060)
-  at org.apache.maven.model.io.xpp3.MavenXpp3Reader.parseDistributionManagement(MavenXpp3Reader.java:847)
-  at org.apache.maven.model.io.xpp3.MavenXpp3Reader.parseModel(MavenXpp3Reader.java:1339)
-  at org.apache.maven.model.io.xpp3.MavenXpp3Reader.read(MavenXpp3Reader.java:2604)
-  at org.apache.maven.project.DefaultMavenProjectBuilder.readModel(DefaultMavenProjectBuilder.java:510)
-  ... 14 more
-</div>
-</div>
-</div>
-</div>
-</td>
-</tr>
-</tbody></table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/viewGroup.html b/design/old-white-site/viewGroup.html
deleted file mode 100644
index 5fc0ebd..0000000
--- a/design/old-white-site/viewGroup.html
+++ /dev/null
@@ -1,267 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-    <div style="margin-top: 5em; color: #555; border: 1px dashed black; padding: 1em;">
-      <p>Notes:</p>
-      <ul>
-        <li>add/edit links here go to the standard page, which returns to the project, not the group</li>
-        <li>in build definitions, targets replace goals for Ant, and it is omitted for shell</li>
-        <li>in build definitions, build.xml replace pom file for Ant</li>
-        <li>in build definitions, Executable replace pom file for Shell, and it is before the arguments</li>
-        <li>later we might allow arbitrary groups, but for now they aren't editable</li>
-        <li>pom.xml is relative to the project basedirs, not the group</li>
-        <li>Do we want an aggregated group mode, where the build is only run on a reactor represented by the group?</li>
-        <li>No Maven Group ID on non-Maven projects</li>
-      </ul>
-    </div>
-  </div>
-</td>
-<td>
-<div id="bodycol">
-<div class="app">
-
-<div>
-  <p style="border-top: 1px solid transparent; border-bottom: 1px solid black;">
-    <b style="border: 1px solid black; padding-left: 1em; padding-right: 1em;"><a href="groupStatus.html">Status</a></b>
-    <b style="border: 1px solid black; padding-left: 1em; padding-right: 1em;"><a href="manageGroup.html">Manage</a></b>
-  </p>
-</div>
-
-<div id="axial" class="h3">
-<h3>Continuum Project Group</h3>
-
-<div class="axial">
-  <table border="1" cellspacing="2" cellpadding="3" width="100%">
-
-    <tr class="b">
-      <th>Project Group Name</th>
-      <td>Plexus</td>
-    </tr>
-    <tr class="b">
-      <th>Maven Group ID</th>
-      <td>org.codehaus.plexus</td>
-    </tr>
-    <tr class="b">
-      <th>Description</th>
-      <td>&nbsp;</td>
-    </tr>
-  </table>
-  <div class="functnbar3">
-    <table>
-      <tr>
-        <td>
-          <form method="post" action="editGroup.html">
-
-            <input type="hidden" name="action" value="cam"/>
-            <input type="hidden" name="cid" value="checkoutProject"/>
-            <input type="hidden" name="id" value="43"/>
-            <input type="submit" name="edit-project" value="Edit"/>
-          </form>
-        </td>
-      </tr>
-    </table>
-  </div>
-</div>
-
-<h3>Projects</h3>
-<table border="1" cellspacing="2" cellpadding="3" width="100%">
-  <tr>
-
-    <th>Name</th>
-  </tr>
-  <tr class="b">
-    <td><a href="viewProject.html">Plexus Utils</a></td>
-  </tr>
-  <tr class="b">
-    <td><a href="viewProject.html">Default Plexus Container</a></td>
-  </tr>
-
-</table>
-
-<h3>Shared Notifiers</h3>
-<table border="1" cellspacing="2" cellpadding="3" width="100%">
-  <tr>
-
-    <th>Type</th>
-    <th>Recipient</th>
-    <th>Events</th>
-    <th width="10%">&nbsp;</th>
-  </tr>
-  <tr class="b">
-    <td>Mail</td>
-    <td>dev@plexus.codehaus.org</td>
-    <td>Failures</td>
-    <td><a href="addNotifier.html">Edit</a> | <a href="#">Delete</a></td>
-  </tr>
-  <tr class="b">
-    <td>Mail</td>
-    <td><i>All Project Developers</i></td>
-    <td>Failures</td>
-    <td><a href="addNotifier.html">Edit</a> | <a href="#">Delete</a></td>
-  </tr>
-
-</table>
-<div class="functnbar3">
-  <table>
-    <tr>
-      <td>
-        <form method="post" action="addNotifier.html">
-
-          <input type="hidden" name="action" value="cam"/>
-          <input type="hidden" name="cid" value="checkoutProject"/>
-          <input type="hidden" name="id" value="43"/>
-          <input type="submit" name="add-notifier" value="Add"/>
-        </form>
-      </td>
-    </tr>
-  </table>
-</div>
-
-<h3>Shared Build Definitions</h3>
-<table border="1" cellspacing="2" cellpadding="3" width="100%">
-  <tr>
-
-    <th>Goals</th>
-    <th>Arguments</th>
-    <th>POM File</th>
-    <th>Profile</th>
-    <th>Schedule</th>
-    <th width="10%">&nbsp;</th>
-  </tr>
-  <tr class="b">
-    <td>clean:clean install</td>
-    <td>--batch-mode</td>
-    <td>pom.xml</td>
-    <td><a href="viewProfile.html">Maven 2.0 Default</a></td>
-    <td><a href="viewSchedule.html">Hourly</a></td>
-    <td><a href="addBuildDef.html">Edit</a> | <a href="#">Delete</a></td>
-  </tr>
-
-</table>
-<div class="functnbar3">
-  <table>
-    <tr>
-      <td>
-        <form method="post" action="addBuildDef.html">
-
-          <input type="hidden" name="action" value="cam"/>
-          <input type="hidden" name="cid" value="checkoutProject"/>
-          <input type="hidden" name="id" value="43"/>
-          <input type="submit" name="add-build-def" value="Add"/>
-        </form>
-      </td>
-    </tr>
-  </table>
-</div>
-
-</div>
-</div>
-</div>
-</td>
-</tr>
-</tbody></table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/viewProfile.html b/design/old-white-site/viewProfile.html
deleted file mode 100644
index a79c07b..0000000
--- a/design/old-white-site/viewProfile.html
+++ /dev/null
@@ -1,187 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-
-    </div>
-
-    <div style="margin-top: 5em; color: #555; border: 1px dashed black; padding: 1em;">
-      <p>Notes:</p>
-      <ul>
-        <li>different sections for different project types (Maven1 home, Ant home, no Java home for shell projects,
-          etc)</li>
-      </ul>
-    </div>
-  </div>
-</td>
-<td>
-  <div id="bodycol">
-    <div class="app">
-      <div id="axial" class="h3">
-        <h3>Profile</h3>
-
-        <div class="axial">
-          <table border="1" cellspacing="2" cellpadding="3" width="100%">
-
-            <tr class="b">
-              <th>Profile Name</th>
-              <td>Maven 2.0 Default</td>
-            </tr>
-            <tr class="b">
-              <th>Description</th>
-              <td>Default profile for Maven 2.0 projects that uses the M2_HOME and JAVA_HOME environment variables</td>
-            </tr>
-            <tr class="b">
-              <th>JDK</th>
-              <td>Default JDK 1.4 (/usr/local/java)</td>
-            </tr>
-            <tr class="b">
-              <th>Maven 2.0 Installation</th>
-              <td>Default Maven 2.0 (/usr/local/maven2)</td>
-            </tr>
-            <tr class="b">
-              <th>SCM</th>
-              <td>
-                <ul>
-                  <li>
-                    <strong>Update</strong> from SCM on build
-                  </li>
-                  <li>
-                    Only build if there are changes.
-                  </li>
-                </ul>
-              </td>
-            </tr>
-            <tr class="b">
-              <th>Enabled</th>
-              <td>
-                <strong style="color: red;">No</strong>
-              </td>
-            </tr>
-          </table>
-          <div class="functnbar3">
-            <table>
-              <tr>
-                <td>
-                  <form method="post" action="editProfile.html">
-
-                    <input type="hidden" name="action" value="cam"/>
-                    <input type="hidden" name="cid" value="checkoutProject"/>
-                    <input type="hidden" name="id" value="43"/>
-                    <input type="submit" name="edit-project" value="Edit"/>
-                  </form>
-                </td>
-              </tr>
-            </table>
-          </div>
-        </div>
-
-      </div>
-    </div>
-
-  </div></td>
-</tr>
-</tbody>
-</table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/viewProject.html b/design/old-white-site/viewProject.html
deleted file mode 100644
index 97883b3..0000000
--- a/design/old-white-site/viewProject.html
+++ /dev/null
@@ -1,357 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-<tbody><tr valign="top">
-<td id="leftcol" width="30%">
-  <div id="navcolum">
-    <div id="projectmenu" class="toolgroup">
-      <div class="label">Continuum</div>
-
-      <div class="body">
-        <div><a href="index.html">Show Projects</a></div>
-
-        <div><a href="schedule.html">View Build Schedule</a></div>
-      </div>
-    </div>
-
-    <div id="projecttools" class="toolgroup">
-      <div class="label">Add Project</div>
-
-      <div class="body">
-        <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-        <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-        <div><a href="addAntProject.html">Ant Project</a></div>
-
-        <div><a href="addShellProject.html">Shell Project</a></div>
-      </div>
-    </div>
-
-    <div id="projectimport" class="toolgroup">
-      <div class="label">Import Project</div>
-
-      <div class="body">
-        <div>
-          <a href="addCruiseControlProject.html">CruiseControl</a>
-        </div>
-      </div>
-    </div>
-
-    <div style="margin-top: 5em; color: #555; border: 1px dashed black; padding: 1em;">
-      <p>Notes:</p>
-      <ul>
-        <li>edit links here go to the add page, which are identical except for being prefilled</li>
-        <li>in build definitions, targets replace goals for Ant, and it is omitted for shell</li>
-        <li>in build definitions, build.xml replace pom file for Ant</li>
-        <li>in build definitions, Executable replace pom file for Shell, and it is before the arguments</li>
-        <li>Users with a <b>(?)</b> are those not found in the continuum system</li>
-      </ul>
-    </div>
-  </div>
-</td>
-<td>
-<div id="bodycol">
-<div class="app">
-
-<div>
-  <p style="border-top: 1px solid transparent; border-bottom: 1px solid black;">
-    <b style="border: 1px solid black; padding-left: 1em; padding-right: 1em;">Info</b>
-    <a style="border: 1px solid black; padding-left: 1em; padding-right: 1em; text-decoration:none;" href="builds.html">Builds</a>
-    <a style="border: 1px solid black; padding-left: 1em; padding-right: 1em; text-decoration:none;"
-       href="workingCopy.html">Working&nbsp;Copy</a>
-  </p>
-</div>
-
-<div id="axial" class="h3">
-<h3>Continuum Project</h3>
-
-<div class="axial">
-  <table border="1" cellspacing="2" cellpadding="3" width="100%">
-
-    <tr class="b">
-      <th>Project Name</th>
-      <td>Default Plexus Container</td>
-    </tr>
-    <tr class="b">
-      <th>Scm Url</th>
-      <td>scm:svn:svn://svn.codehaus.org/plexus/scm/trunk/plexus-containers/plexus-container-default</td>
-    </tr>
-    <tr class="b">
-      <th>Version</th>
-
-      <td>1.0-alpha-6-SNAPSHOT</td>
-    </tr>
-    <tr class="b">
-      <th>Group</th>
-      <td><a href="viewGroup.html">Plexus</a></td>
-    </tr>
-  </table>
-  <div class="functnbar3">
-    <table>
-      <tr>
-        <td>
-          <form method="post" action="editProject.html">
-
-            <input type="hidden" name="action" value="cam"/>
-            <input type="hidden" name="cid" value="checkoutProject"/>
-            <input type="hidden" name="id" value="43"/>
-            <input type="submit" name="edit-project" value="Edit"/>
-            <b style="color: red;">Note: </b> Project details are out of sync with Maven POM
-          </form>
-        </td>
-      </tr>
-    </table>
-  </div>
-</div>
-
-
-<h3>Build Definitions</h3>
-<table border="1" cellspacing="2" cellpadding="3" width="100%">
-  <tr>
-
-    <th>Goals</th>
-    <th>Arguments</th>
-    <th>POM File</th>
-    <th>Profile</th>
-    <th>Schedule</th>
-    <th>From</th>
-    <th width="10%">&nbsp;</th>
-  </tr>
-  <tr class="b">
-    <td>clean:clean install</td>
-    <td>--batch-mode</td>
-    <td>pom.xml</td>
-    <td><a href="viewProfile.html">Maven 2.0 Default</a></td>
-    <td><a href="viewSchedule.html">Hourly</a></td>
-    <td><a href="viewGroup.html">Group</a></td>
-    <td><a href="addBuildDef.html">Edit</a> | <a href="#">Delete</a></td>
-  </tr>
-  <tr class="b">
-    <td>clean:clean install</td>
-    <td>--batch-mode</td>
-    <td>pom.xml</td>
-    <td><a href="viewProfile.html">JDK 1.3, clean checkout</a></td>
-    <td><a href="viewSchedule.html">Weekly</a></td>
-    <td>Project</td>
-    <td><a href="addBuildDef.html">Edit</a> | <a href="#">Delete</a></td>
-  </tr>
-
-</table>
-<div class="functnbar3">
-  <table>
-    <tr>
-      <td>
-        <form method="post" action="addBuildDef.html">
-
-          <input type="hidden" name="action" value="cam"/>
-          <input type="hidden" name="cid" value="checkoutProject"/>
-          <input type="hidden" name="id" value="43"/>
-          <input type="submit" name="add-build-def" value="Add"/>
-        </form>
-      </td>
-    </tr>
-  </table>
-</div>
-
-<h3>Notifiers</h3>
-<table border="1" cellspacing="2" cellpadding="3" width="100%">
-  <tr>
-
-    <th>Type</th>
-    <th>Recipient</th>
-    <th>Events</th>
-    <th>From</th>
-    <th width="10%">&nbsp;</th>
-  </tr>
-  <tr class="b">
-    <td>Mail</td>
-    <td>dev@plexus.codehaus.org</td>
-    <td>Failures</td>
-    <td><a href="viewGroup.html">Group</a></td>
-    <td><a href="addNotifier.html">Edit</a> | <a href="#">Delete</a></td>
-  </tr>
-  <tr class="b">
-    <td>Mail</td>
-    <td><i>All Project Developers</i></td>
-    <td>Failures</td>
-    <td><a href="viewGroup.html">Group</a></td>
-    <td><a href="addNotifier.html">Edit</a> | <a href="#">Delete</a></td>
-  </tr>
-  <tr class="b">
-    <td>Mail</td>
-    <td><i>Project Developers with Role "Build Manager"</i></td>
-    <td>Success, Failures</td>
-    <td>Project</td>
-    <td><a href="addNotifier.html">Edit</a> | <a href="#">Delete</a></td>
-  </tr>
-  <tr class="b">
-    <td>IRC</td>
-    <td>irc.codehaus.org #plexus</td>
-    <td>Success, Failures</td>
-    <td>Project</td>
-    <td><a href="addNotifier.html">Edit</a> | <a href="#">Delete</a></td>
-  </tr>
-
-</table>
-<div class="functnbar3">
-  <table>
-    <tr>
-      <td>
-        <form method="post" action="addNotifier.html">
-
-          <input type="hidden" name="action" value="cam"/>
-          <input type="hidden" name="cid" value="checkoutProject"/>
-          <input type="hidden" name="id" value="43"/>
-          <input type="submit" name="add-notifier" value="Add"/>
-          <b style="color: red;">Note: </b> Notifiers are out of sync with Maven POM
-        </form>
-      </td>
-    </tr>
-  </table>
-</div>
-
-<h3>Dependencies</h3>
-<table border="1" cellspacing="2" cellpadding="3" width="100%">
-  <tr>
-
-    <th>Name</th>
-  </tr>
-  <tr class="b">
-    <td><a href="viewProject.html">Plexus Utils</a></td>
-  </tr>
-</table>
-
-<h3>Used By</h3>
-<table border="1" cellspacing="2" cellpadding="3" width="100%">
-  <tr>
-
-    <th>Name</th>
-  </tr>
-  <tr class="b">
-    <td><a href="viewProject.html">Plexus Artifact Container</a></td>
-  </tr>
-</table>
-
-<h3>Developers</h3>
-<table border="1" cellspacing="2" cellpadding="3" width="100%">
-  <tr>
-
-    <th>Name</th>
-    <th>Email</th>
-    <th width="10%">&nbsp;</th>
-  </tr>
-  <tr class="b">
-    <td><a href="userProfile.html">Jason van Zyl</a></td>
-    <td><a href="mailto:jason@zenplex.com">jason@zenplex.com</a></td>
-    <td><a href="addDeveloper.html">Edit</a> | <a href="#">Delete</a></td>
-  </tr>
-
-  <tr class="b">
-    <td>Emmanuel Venisse <b>(?)</b></td>
-    <td><a href="mailto:evenisse@codehaus.org">evenisse@codehaus.org</a></td>
-    <td><a href="addDeveloper.html">Edit</a> | <a href="#">Delete</a></td>
-  </tr>
-  <tr class="a">
-    <td><a href="userProfile.html">Trygve Laugstøl</a></td>
-    <td><a href="mailto:trygvis@codehaus.org">trygvis@codehaus.org</a></td>
-    <td><a href="addDeveloper.html">Edit</a> | <a href="#">Delete</a></td>
-
-  </tr>
-  <tr class="b">
-    <td><a href="userProfile.html">Kenney Westerhof</a></td>
-    <td><a href="mailto:kenney@codehaus.org">kenney@codehaus.org</a></td>
-    <td><a href="addDeveloper.html">Edit</a> | <a href="#">Delete</a></td>
-  </tr>
-</table>
-<div class="functnbar3">
-  <table>
-    <tr>
-      <td>
-        <form method="post" action="addDeveloper.html">
-
-          <input type="hidden" name="action" value="cam"/>
-          <input type="hidden" name="cid" value="checkoutProject"/>
-          <input type="hidden" name="id" value="43"/>
-          <input type="submit" name="add-developer" value="Add"/>
-          <b style="color: red;">Note: </b> Developers are out of sync with Maven POM
-        </form>
-      </td>
-    </tr>
-  </table>
-</div>
-
-</div>
-</div>
-</div>
-</td>
-</tr>
-</tbody></table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/viewSchedule.html b/design/old-white-site/viewSchedule.html
deleted file mode 100644
index 5fa8bcb..0000000
--- a/design/old-white-site/viewSchedule.html
+++ /dev/null
@@ -1,166 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-  <tbody><tr valign="top">
-    <td id="leftcol" width="30%">
-      <div id="navcolum">
-        <div id="projectmenu" class="toolgroup">
-          <div class="label">Continuum</div>
-
-          <div class="body">
-            <div><a href="index.html">Show Projects</a></div>
-
-            <div><a href="schedule.html">View Build Schedule</a></div>
-          </div>
-        </div>
-
-        <div id="projecttools" class="toolgroup">
-          <div class="label">Add Project</div>
-
-          <div class="body">
-            <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-            <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-            <div><a href="addAntProject.html">Ant Project</a></div>
-
-            <div><a href="addShellProject.html">Shell Project</a></div>
-          </div>
-        </div>
-
-        <div id="projectimport" class="toolgroup">
-          <div class="label">Import Project</div>
-
-          <div class="body">
-            <div>
-              <a href="addCruiseControlProject.html">CruiseControl</a>
-            </div>
-          </div>
-
-        </div>
-      </div>
-    </td>
-    <td>
-      <div id="bodycol">
-        <div class="app">
-          <div id="axial" class="h3">
-            <h3>Schedule</h3>
-
-            <div class="axial">
-              <table border="1" cellspacing="2" cellpadding="3" width="100%">
-
-                <tr class="b">
-                  <th>Schedule Name</th>
-                  <td>Weekly</td>
-                </tr>
-                <tr class="b">
-                  <th>Description</th>
-                  <td>Run weekly</td>
-                </tr>
-                <tr class="b">
-                  <th>Cron</th>
-                  <td>0 0 0 * *</td>
-                </tr>
-                <tr class="b">
-                  <th>Quiet Period</th>
-                  <td>0</td>
-                </tr>
-                <tr class="b">
-                  <th>Enabled</th>
-                  <td>
-                    <strong style="color: green;">Yes</strong>
-                  </td>
-                </tr>
-              </table>
-              <div class="functnbar3">
-                <table>
-                  <tr>
-                    <td>
-                      <form method="post" action="editSchedule.html">
-
-                        <input type="hidden" name="action" value="cam"/>
-                        <input type="hidden" name="cid" value="checkoutProject"/>
-                        <input type="hidden" name="id" value="43"/>
-                        <input type="submit" name="edit-project" value="Edit"/>
-                      </form>
-                    </td>
-                  </tr>
-                </table>
-              </div>
-            </div>
-
-          </div>
-        </div>
-
-      </div></td>
-  </tr>
-  </tbody>
-</table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/old-white-site/workingCopy.html b/design/old-white-site/workingCopy.html
deleted file mode 100644
index e27a65e..0000000
--- a/design/old-white-site/workingCopy.html
+++ /dev/null
@@ -1,155 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><title>Continuum</title>
-
-  <link rel="stylesheet" type="text/css" href="continuum_files/tigris.css" media="screen">
-  <link rel="stylesheet" type="text/css" href="continuum_files/print.css" media="print">
-
-  <script src="continuum_files/tigris.js" type="text/javascript"></script></head>
-
-<body onload="focus()" class="composite">
-
-<div id="banner">
-  <table border="1" cellpadding="8" cellspacing="0" width="100%">
-    <tbody><tr>
-      <td>
-        <a href="http://www.apache.org/">
-          Your company logo here
-        </a>
-      </td>
-      <td>
-        <a href="http://maven.apache.org/continuum">
-          <img src="continuum_files/continuum_logo_75.gif" alt="Continuum" align="right" border="0">
-        </a>
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-<div id="breadcrumbs">
-  <div style="float: right">
-    <a href="http://maven.apache.org/continuum">Continuum</a> |
-    <a href="http://maven.apache.org/">Maven</a> |
-    <a href="http://www.apache.org/">Apache</a>
-  </div>
-
-  <div>
-    Welcome, <b>Guest</b> | <a href="login.html">Login</a>
-  </div>
-</div>
-
-<table id="main" border="0" cellpadding="4" cellspacing="0" width="100%">
-  <tbody><tr valign="top">
-    <td id="leftcol" width="30%">
-      <div id="navcolum">
-        <div id="projectmenu" class="toolgroup">
-          <div class="label">Continuum</div>
-
-          <div class="body">
-            <div><a href="index.html">Show Projects</a></div>
-
-            <div><a href="schedule.html">View Build Schedule</a></div>
-          </div>
-        </div>
-
-        <div id="projecttools" class="toolgroup">
-          <div class="label">Add Project</div>
-
-          <div class="body">
-            <div><a href="addMaven2Project.html">Maven 2.0+ Project</a></div>
-
-            <div><a href="addMaven1Project.html">Maven 1.x Project</a></div>
-
-            <div><a href="addAntProject.html">Ant Project</a></div>
-
-            <div><a href="addShellProject.html">Shell Project</a></div>
-          </div>
-        </div>
-
-        <div id="projectimport" class="toolgroup">
-          <div class="label">Import Project</div>
-
-          <div class="body">
-            <div>
-              <a href="addCruiseControlProject.html">CruiseControl</a>
-            </div>
-          </div>
-        </div>
-
-        <div style="margin-top: 5em; color: #555; border: 1px dashed black; padding: 1em;">
-          <p>Notes:</p>
-          <ul>
-            <li>Navigate to directories to descend</li>
-            <li>A full tree control might be good here, but may make the HTML too large</li>
-            <li>Cannot delete if a build is in progress</li>
-            <li>Navigate to a file to view it</li>
-          </ul>
-        </div>
-      </div>
-    </td>
-    <td>
-      <div id="bodycol">
-        <div class="app">
-
-          <div>
-            <p style="border-top: 1px solid transparent; border-bottom: 1px solid black;">
-              <a style="border: 1px solid black; padding-left: 1em; padding-right: 1em; text-decoration:none;"
-                 href="viewProject.html">Info</a>
-              <a style="border: 1px solid black; padding-left: 1em; padding-right: 1em; text-decoration:none;"
-                 href="builds.html">Builds</a>
-              <b style="border: 1px solid black; padding-left: 1em; padding-right: 1em;">Working&nbsp;Copy</b>
-            </p>
-          </div>
-
-          <div id="axial" class="h3">
-            <h3>Working Copy of Default Plexus Container</h3>
-
-            <p><a href="#">Delete Working Copy</a></p>
-
-            <ul>
-              <li>/</li>
-              <li style="list-style:none;">
-                <ul>
-                  <li><a href="#">pom.xml</a></li>
-                  <li><a href="#">src</a></li>
-                  <li><a href="#">target</a></li>
-                </ul>
-              </li>
-            </ul>
-
-          </div>
-        </div>
-      </div>
-    </td>
-  </tr>
-  </tbody></table>
-
-<div id="footer">
-  <table border="0" cellpadding="4" cellspacing="0">
-    <tbody><tr>
-      <td>
-        Continuum &#169; 2005 Apache Software Foundation
-      </td>
-    </tr>
-    </tbody></table>
-</div>
-
-</body></html>
\ No newline at end of file
diff --git a/design/white-site/pom.xml b/design/white-site/pom.xml
deleted file mode 100644
index 7ae4fdb..0000000
--- a/design/white-site/pom.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<!--
-  ~ 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.
-  -->
-
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <groupId>org.apache.maven.continuum</groupId>
-  <artifactId>white-site</artifactId>
-  <version>1.0-SNAPSHOT</version>
-  <packaging>pom</packaging>
-  <distributionManagement>
-    <site>
-      <id>apache.website</id>
-      <url>scp://people.apache.org/home/brett/public_html/continuum-white-site</url>
-    </site>
-  </distributionManagement>
-</project>
diff --git a/design/white-site/src/site/resources/images/continuum_logo_75.gif b/design/white-site/src/site/resources/images/continuum_logo_75.gif
deleted file mode 100644
index b5e99a2..0000000
--- a/design/white-site/src/site/resources/images/continuum_logo_75.gif
+++ /dev/null
Binary files differ
diff --git a/design/white-site/src/site/site.xml b/design/white-site/src/site/site.xml
deleted file mode 100644
index a7f19fe..0000000
--- a/design/white-site/src/site/site.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!--
-  ~ 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.
-  -->
-<project name="Continuum">
-  <bannerLeft>
-    <src>images/continuum_logo_75.gif</src>
-  </bannerLeft>
-  <bannerRight>
-    <src>http://www.apache.org/images/asf_logo_wide.gif</src>
-  </bannerRight>
-  <skin>
-    <groupId>org.apache.maven.skins</groupId>
-    <artifactId>maven-application-skin</artifactId>
-  </skin>
-  <publishDate position="none"/>
-  <body>
-    <breadcrumbs>
-      <item name="Login/Register" href="/admin/login.html"/>
-    </breadcrumbs>
-    <links>
-      <item name="Continuum" href="http://maven.apache.org/continuum/"/>
-      <item name="Maven" href="http://maven.apache.org/"/>
-      <item name="Apache" href="http://www.apache.org/"/>
-    </links>
-    <menu name="Projects">
-      <item name="Project Group Summary" href="/index.html"/>
-      <!-- TODO: this should just be 'add project', and have a simple first page that can figure out what to do -->
-      <item name="Add Maven 2.x Project" href="/add-maven-2.html" />
-      <item name="Add Maven 1.x Project" href="/add-maven-1.html" />
-      <item name="Add Ant Project" href="/add-ant.html" />
-      <item name="Add Other Project" href="/add-other.html" />
-    </menu>
-    <menu name="Administration">
-      <item name="Settings" href="/admin/settings.html" />
-      <item name="Appearance" href="/admin/appearance.html" />
-      <item name="Schedules" href="/admin/schedules.html"/>
-      <item name="Users" href="" /> <!-- TODO: link in to p-sec white site -->
-    </menu>
-    <menu name="Legend">
-      <!-- Legend goes here -->
-    </menu>
-  </body>
-</project>
diff --git a/design/white-site/src/site/xdoc/admin/appearance.xml b/design/white-site/src/site/xdoc/admin/appearance.xml
deleted file mode 100644
index c6dc886..0000000
--- a/design/white-site/src/site/xdoc/admin/appearance.xml
+++ /dev/null
@@ -1,95 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!--
-  ~ 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.
-  -->
-
-<!--
-  ~ 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.
-  -->
-
-<document>
-  <properties>
-    <title>Continuum</title>
-  </properties>
-  <body>
-    <h1>Appearance</h1>
-
-    <div>
-      <div style="float: right">
-        <a href="edit-appearance.html">Edit</a>
-      </div>
-      <h2>Company Details</h2>
-    </div>
-
-    <form action="../index.html">
-      <table>
-        <tr>
-          <th>Group ID</th>
-          <td>org.apache</td>
-        </tr>
-        <tr>
-          <th>Artifact ID</th>
-          <td>apache</td>
-        </tr>
-      </table>
-      <div style="float: right">
-        <p>
-          <a href="edit-company-pom.html">Edit Company POM</a>
-        </p>
-      </div>
-      <h3>POM Information</h3>
-      <table>
-        <tr>
-          <th>Name</th>
-          <td>Apache Software Foundation</td>
-        </tr>
-        <tr>
-          <th>URL</th>
-          <td>
-            <a href="http://www.apache.org">
-              <code>http://www.apache.org</code>
-            </a>
-          </td>
-        </tr>
-        <tr>
-          <th>Logo URL</th>
-          <td>
-            <code>http://www.apache.org/images/asf_logo_wide.gif</code>
-          </td>
-        </tr>
-      </table>
-    </form>
-
-  </body>
-</document>
-
diff --git a/design/white-site/src/site/xdoc/admin/edit-appearance.xml b/design/white-site/src/site/xdoc/admin/edit-appearance.xml
deleted file mode 100644
index 313e66f..0000000
--- a/design/white-site/src/site/xdoc/admin/edit-appearance.xml
+++ /dev/null
@@ -1,72 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!--
-  ~ 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.
-  -->
-
-<!--
-  ~ 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.
-  -->
-
-<document>
-  <properties>
-    <title>Continuum</title>
-  </properties>
-  <body>
-    <h1>Edit Appearance</h1>
-
-    <h2>Company Details</h2>
-
-    <p>
-      Enter the details of the company super POM below. If it exists, the organization name, URL and logo will be read
-      from it.
-    </p>
-    <form action="appearance.html">
-    <table>
-      <tr>
-        <th>Group ID</th>
-        <td><input type="text" /></td>
-      </tr>
-      <tr>
-        <th>Artifact ID</th>
-        <td><input type="text" /></td>
-      </tr>
-      <tr>
-        <td></td>
-        <td><input type="submit" value="Save" /></td>
-      </tr>
-    </table>
-    </form>
-
-  </body>
-</document>
-
diff --git a/design/white-site/src/site/xdoc/admin/edit-company-pom.xml b/design/white-site/src/site/xdoc/admin/edit-company-pom.xml
deleted file mode 100644
index 661cf37..0000000
--- a/design/white-site/src/site/xdoc/admin/edit-company-pom.xml
+++ /dev/null
@@ -1,65 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!--
-  ~ 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.
-  -->
-
-<document>
-  <properties>
-    <title>Continuum</title>
-  </properties>
-  <body>
-    <h1>Edit Company POM</h1>
-    <form action="appearance.html">
-    <table>
-      <tr>
-        <th>Group ID</th>
-        <td><input type="text" /></td>
-      </tr>
-      <tr>
-        <th>Artifact ID</th>
-        <td><input type="text" /></td>
-      </tr>
-      <tr>
-        <th>Version</th>
-        <td>2 <i>(The version will automatically be incremented when you save this form)</i></td>
-      </tr>
-      <tr>
-        <td></td>
-        <td><h2>Organization</h2></td>
-      </tr>
-      <tr>
-        <th>Name</th>
-        <td><input type="text" size="40" /></td>
-      </tr>
-      <tr>
-        <th>URL</th>
-        <td><input type="text" size="70" /></td>
-      </tr>
-      <tr>
-        <th>Logo URL</th>
-        <td><input type="text" size="70"/></td>
-      </tr>
-      <tr>
-        <td></td>
-        <td><input type="submit" value="Save" /></td>
-      </tr>
-    </table>
-    </form>
-  </body>
-</document>
-
diff --git a/design/white-site/src/site/xdoc/admin/settings.xml b/design/white-site/src/site/xdoc/admin/settings.xml
deleted file mode 100644
index 5b9c8d3..0000000
--- a/design/white-site/src/site/xdoc/admin/settings.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!--
-  ~ 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.
-  -->
-
-<document>
-  <properties>
-    <title>Continuum</title>
-  </properties>
-  <body>
-    <h1>Settings</h1>
-
-    <form action="../index.html">
-    <table>
-      <tr>
-        <th>Working Directory</th>
-        <td><input type="text" size="100" /><br/>
-          Enter the working directory of the Continuum web application
-        </td>
-      </tr>
-      <tr>
-        <th>Build Output Directory</th>
-        <td><input type="text" size="100" /><br/>
-          Enter the build output directory of the Continuum web application
-        </td>
-      </tr>
-      <tr>
-        <th>Deployment Repository Directory</th>
-        <td><input type="text" size="100" /><br/>
-          Enter the deployment repository directory of the Continuum web application
-        </td>
-      </tr>
-      <tr>
-        <th>Base URL</th>
-        <td><input type="text" size="100" /><br/>
-          Enter the base URL for the Continuum web application
-        </td>
-      </tr>
-      <tr>
-        <td></td>
-        <td><input type="submit" value="Save" /></td>
-      </tr>
-    </table>
-    </form>
-  </body>
-</document>
-
diff --git a/design/white-site/src/site/xdoc/index.xml b/design/white-site/src/site/xdoc/index.xml
deleted file mode 100644
index 53b74b2..0000000
--- a/design/white-site/src/site/xdoc/index.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!--
-  ~ 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.
-  -->
-
-<document>
-  <properties>
-    <title>Continuum</title>
-  </properties>
-  <body>
-    <h1>TODO...</h1>
-
-  </body>
-</document>
-
diff --git a/doap_Continuum.rdf b/doap_Continuum.rdf
new file mode 100644
index 0000000..00f3b1c
--- /dev/null
+++ b/doap_Continuum.rdf
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl"?>
+<rdf:RDF xml:lang="en"
+         xmlns="http://usefulinc.com/ns/doap#" 
+         xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
+         xmlns:asfext="http://projects.apache.org/ns/asfext#"
+         xmlns:foaf="http://xmlns.com/foaf/0.1/">
+<!--
+    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.
+-->
+  <Project rdf:about="http://continuum.apache.org">
+    <created>2012-04-14</created>
+    <license rdf:resource="http://usefulinc.com/doap/licenses/asl20" />
+    <name>Apache Continuum</name>
+    <homepage rdf:resource="http://continuum.apache.org" />
+    <asfext:pmc rdf:resource="http://continuum.apache.org" />
+    <shortdesc>Apache Continuum software is an enterprise-ready continuous integration server with features such as automated builds, release management, role-based security, and integration with popular build tools and source control management systems.</shortdesc>
+    <description>Whether you have a centralized build team or want to put control of releases in the hands of developers, Apache Continuum can help you improve quality and maintain a consistent build environment. Follow us on Twitter @apachecontinuum to get the latest news and updates!</description>
+    <bug-database rdf:resource="http://jira.codehaus.org/browse/CONTINUUM" />
+    <mailing-list rdf:resource="http://continuum.apache.org/mail-lists.html" />
+    <download-page rdf:resource="http://continuum.apache.org/download.html" />
+    <programming-language>Java</programming-language>
+    <category rdf:resource="http://projects.apache.org/category/build-management" />
+    <release>
+      <Version>
+        <name>Apache Continuum 1.4.2</name>
+        <created>2014-06-13</created>
+        <revision>1.4.2</revision>
+      </Version>
+      <Version>
+        <name>Apache Continuum 1.4.1</name>
+        <created>2013-01-07</created>
+        <revision>1.4.1</revision>
+      </Version>
+      <Version>
+        <name>Apache Continuum 1.3.8</name>
+        <created>2011-09-18</created>
+        <revision>1.3.8</revision>
+      </Version>
+    </release>
+    <repository>
+      <SVNRepository>
+        <location rdf:resource="http://svn.apache.org/repos/asf/continuum"/>
+        <browse rdf:resource="http://svn.apache.org/viewvc/continuum"/>
+      </SVNRepository>
+    </repository>
+    <maintainer>
+      <foaf:Person>
+        <foaf:name>Apache Continuum PMC</foaf:name>
+          <foaf:mbox rdf:resource="mailto:dev@continuum.apache.org"/>
+      </foaf:Person>
+    </maintainer>
+  </Project>
+</rdf:RDF>
diff --git a/init-git-svn.sh b/init-git-svn.sh
new file mode 100755
index 0000000..2a3f19a
--- /dev/null
+++ b/init-git-svn.sh
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+(
+  cd .git
+  wget -O authors.txt http://git.apache.org/authors.txt
+)
+git config svn.authorsfile ".git/authors.txt"
+git svn init --prefix=origin/ --tags=tags --trunk=trunk --branches=branches https://svn.apache.org/repos/asf/continuum
+git svn rebase
diff --git a/maven-continuum-plugin/pom.xml b/maven-continuum-plugin/pom.xml
deleted file mode 100644
index 9ba8a2c..0000000
--- a/maven-continuum-plugin/pom.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<!--
-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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <parent>
-    <artifactId>continuum</artifactId>
-    <groupId>org.apache.continuum</groupId>
-    <version>1.3.1-SNAPSHOT</version>
-  </parent>
-  <modelVersion>4.0.0</modelVersion>
-  <artifactId>continuum-maven-plugin</artifactId>
-  <packaging>maven-plugin</packaging>
-  <name>Continuum :: Maven Plugin</name>
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-api</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-xmlrpc-api</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.continuum</groupId>
-      <artifactId>continuum-xmlrpc-client</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven</groupId>
-      <artifactId>maven-plugin-api</artifactId>
-      <version>2.0</version>
-    </dependency>
-  </dependencies>
-</project>
diff --git a/maven-continuum-plugin/src/main/java/org/apache/maven/continuum/plugin/AbstractAddProject.java b/maven-continuum-plugin/src/main/java/org/apache/maven/continuum/plugin/AbstractAddProject.java
deleted file mode 100644
index 10a67f3..0000000
--- a/maven-continuum-plugin/src/main/java/org/apache/maven/continuum/plugin/AbstractAddProject.java
+++ /dev/null
@@ -1,139 +0,0 @@
-package org.apache.maven.continuum.plugin;
-
-/*
- * 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 org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
-import org.apache.maven.continuum.xmlrpc.project.ProjectSummary;
-import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugin.MojoFailureException;
-
-/**
- * Base class to add ANT/Shell projects.
- *
- * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
- * @version $Id$
- */
-public abstract class AbstractAddProject
-    extends AbstractContinuumMojo
-{
-    /**
-     * The project name.
-     *
-     * @parameter expression="${projectName}"
-     * @required
-     */
-    private String projectName;
-
-    /**
-     * The project verion.
-     *
-     * @parameter expression="${projectVersion}"
-     * @required
-     */
-    private String projectVersion;
-
-    /**
-     * The SCM Url. Must be a Maven-SCM url.
-     *
-     * @parameter expression="${scmUrl}"
-     * @required
-     */
-    private String scmUrl;
-
-    /**
-     * The SCM username.
-     *
-     * @parameter expression="${scm.username}"
-     */
-    private String scmUsernme;
-
-    /**
-     * The SCM password.
-     *
-     * @parameter expression="${scm.password}"
-     */
-    private String scmPassword;
-
-    /**
-     * The SCM branch/tag name.
-     *
-     * @parameter expression="${scm.tag}"
-     */
-    private String scmTag;
-
-    /**
-     * Use SCM credentials Cache, if available.
-     *
-     * @parameter expression="${scm.useCredentialsCache}" default-value="false"
-     */
-    private boolean scmUseCredentialsCache;
-
-    /**
-     * The project Group Id.
-     *
-     * @parameter expression="${projectGroupId}"
-     */
-    private String projectGroupId;
-
-    public void execute()
-        throws MojoExecutionException, MojoFailureException
-    {
-        ProjectSummary project = new ProjectSummary();
-        project.setName( projectName );
-        project.setVersion( projectVersion );
-        project.setScmUrl( scmUrl );
-        project.setScmUsername( scmUsernme );
-        project.setScmPassword( scmPassword );
-        project.setScmTag( scmTag );
-        project.setScmUseCache( scmUseCredentialsCache );
-
-        try
-        {
-            if ( projectGroupId != null && projectGroupId.length() > 0 )
-            {
-                if ( ContinuumBuildExecutorConstants.ANT_BUILD_EXECUTOR.equals( getProjectType() ) )
-                {
-                    getClient().addAntProject( project, Integer.parseInt( projectGroupId ) );
-                }
-                else
-                {
-                    getClient().addShellProject( project, Integer.parseInt( projectGroupId ) );
-                }
-            }
-            else
-            {
-                if ( ContinuumBuildExecutorConstants.ANT_BUILD_EXECUTOR.equals( getProjectType() ) )
-                {
-                    getClient().addAntProject( project );
-                }
-                else
-                {
-                    getClient().addShellProject( project );
-                }
-            }
-        }
-        catch ( Exception e )
-        {
-            throw new MojoExecutionException( "Can't add the " + getProjectType() + " project.", e );
-        }
-    }
-
-    protected abstract String getProjectType();
-}
diff --git a/maven-continuum-plugin/src/main/java/org/apache/maven/continuum/plugin/AbstractContinuumMojo.java b/maven-continuum-plugin/src/main/java/org/apache/maven/continuum/plugin/AbstractContinuumMojo.java
deleted file mode 100644
index 7a1a3f0..0000000
--- a/maven-continuum-plugin/src/main/java/org/apache/maven/continuum/plugin/AbstractContinuumMojo.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.apache.maven.continuum.plugin;
-
-/*
- * 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 org.apache.maven.continuum.xmlrpc.client.ContinuumXmlRpcClient;
-import org.apache.maven.plugin.AbstractMojo;
-import org.apache.maven.plugin.MojoExecutionException;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-
-/**
- * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
- * @version $Id$
- */
-public abstract class AbstractContinuumMojo
-    extends AbstractMojo
-{
-    /**
-     * The Continuum XML-RPC server URL.
-     *
-     * @parameter expression="${url}"
-     * @required
-     */
-    private String url;
-
-    /**
-     * The Continuum username.
-     *
-     * @parameter expression="${username}"
-     */
-    private String username;
-
-    /**
-     * The Continuum password.
-     *
-     * @parameter expression="${password}"
-     */
-    private String password;
-
-    private ContinuumXmlRpcClient client;
-
-    protected void createClient()
-        throws MojoExecutionException
-    {
-        URL continuumUrl;
-
-        try
-        {
-            continuumUrl = new URL( url );
-        }
-        catch ( MalformedURLException e )
-        {
-            throw new MojoExecutionException( "The URL '" + url + "' isn't valid." );
-        }
-
-        client = new ContinuumXmlRpcClient( continuumUrl, username, password );
-    }
-
-    protected ContinuumXmlRpcClient getClient()
-        throws MojoExecutionException
-    {
-        if ( client == null )
-        {
-            createClient();
-        }
-        return client;
-    }
-}
diff --git a/maven-continuum-plugin/src/main/java/org/apache/maven/continuum/plugin/AddAntProject.java b/maven-continuum-plugin/src/main/java/org/apache/maven/continuum/plugin/AddAntProject.java
deleted file mode 100644
index 6d9f5ee..0000000
--- a/maven-continuum-plugin/src/main/java/org/apache/maven/continuum/plugin/AddAntProject.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.apache.maven.continuum.plugin;
-
-/*
- * 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 org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
-
-/**
- * Goal which add an ANT project.
- *
- * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
- * @version $Id$
- * @goal add-ant-project
- */
-public class AddAntProject
-    extends AbstractAddProject
-{
-    protected String getProjectType()
-    {
-        return ContinuumBuildExecutorConstants.ANT_BUILD_EXECUTOR;
-    }
-}
diff --git a/maven-continuum-plugin/src/main/java/org/apache/maven/continuum/plugin/AddMavenOneProject.java b/maven-continuum-plugin/src/main/java/org/apache/maven/continuum/plugin/AddMavenOneProject.java
deleted file mode 100644
index d6f5384..0000000
--- a/maven-continuum-plugin/src/main/java/org/apache/maven/continuum/plugin/AddMavenOneProject.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package org.apache.maven.continuum.plugin;
-
-/*
- * 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 org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugin.MojoFailureException;
-
-/**
- * Goal which add a Maven1 project.
- *
- * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
- * @version $Id$
- * @goal add-maven-one-project
- */
-public class AddMavenOneProject
-    extends AbstractContinuumMojo
-{
-    /**
-     * POM Url.
-     *
-     * @parameter expression="${projectUrl}" default-value="${project.scm.url}"
-     * @required
-     */
-    private String projectUrl;
-
-    /**
-     * Project Group Id.
-     *
-     * @parameter expression="${projectGroupId}"
-     */
-    private String projectGroupId;
-
-    public void execute()
-        throws MojoExecutionException, MojoFailureException
-    {
-        try
-        {
-            if ( projectGroupId != null && projectGroupId.length() > 0 )
-            {
-                getClient().addMavenOneProject( projectUrl, Integer.parseInt( projectGroupId ) );
-            }
-            else
-            {
-                getClient().addMavenOneProject( projectUrl );
-            }
-        }
-        catch ( Exception e )
-        {
-            throw new MojoExecutionException( "Can't add the Maven1 project from '" + projectUrl + "'.", e );
-        }
-    }
-}
diff --git a/maven-continuum-plugin/src/main/java/org/apache/maven/continuum/plugin/AddMavenTwoProject.java b/maven-continuum-plugin/src/main/java/org/apache/maven/continuum/plugin/AddMavenTwoProject.java
deleted file mode 100644
index de556f4..0000000
--- a/maven-continuum-plugin/src/main/java/org/apache/maven/continuum/plugin/AddMavenTwoProject.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package org.apache.maven.continuum.plugin;
-
-/*
- * 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 org.apache.maven.continuum.xmlrpc.project.AddingResult;
-import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugin.MojoFailureException;
-
-/**
- * Goal which add a Maven2 project.
- *
- * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
- * @version $Id$
- * @goal add-maven-two-project
- */
-public class AddMavenTwoProject
-    extends AbstractContinuumMojo
-{
-    /**
-     * POM file name.
-     *
-     * @parameter expression="${pomFilename}" default-value="pom.xml"
-     * @required
-     */
-    private String pomFilename;
-
-    /**
-     * POM Url.
-     *
-     * @parameter expression="${projectUrl}" default-value="${project.scm.url}"
-     * @required
-     */
-    private String projectUrl;
-
-    /**
-     * Project Group Id.
-     *
-     * @parameter expression="${projectGroupId}"
-     */
-    private String projectGroupId;
-
-    public void execute()
-        throws MojoExecutionException, MojoFailureException
-    {
-        AddingResult addingResult = null;
-        try
-        {
-            if ( !projectUrl.endsWith( pomFilename ) )
-            {
-                if ( !projectUrl.endsWith( "/" ) )
-                {
-                    projectUrl += "/";
-                }
-                projectUrl += pomFilename;
-            }
-
-            getLog().info( "Adding M2 project from " + projectUrl );
-            if ( projectGroupId != null && projectGroupId.length() > 0 )
-            {
-                addingResult = getClient().addMavenTwoProject( projectUrl, Integer.parseInt( projectGroupId ) );
-            }
-            else
-            {
-                addingResult = getClient().addMavenTwoProject( projectUrl );
-            }
-            if ( addingResult.getErrorsAsString() != null )
-            {
-                getLog().error( "fail to add mavenTwo project " + addingResult.getErrorsAsString() );
-                throw new MojoExecutionException( "fail to add mavenTwo project " + addingResult.getErrorsAsString() );
-            }
-            //TODO: print projects/project groups added
-            //addingResult.getProjects();
-        }
-        catch ( MojoExecutionException e )
-        {
-            throw e;
-        }
-        catch ( Exception e )
-        {
-            throw new MojoExecutionException( "Can't add the Maven2 project from '" + projectUrl + "'.", e );
-        }
-    }
-}
diff --git a/maven-continuum-plugin/src/main/java/org/apache/maven/continuum/plugin/AddShellProject.java b/maven-continuum-plugin/src/main/java/org/apache/maven/continuum/plugin/AddShellProject.java
deleted file mode 100644
index c829c6d..0000000
--- a/maven-continuum-plugin/src/main/java/org/apache/maven/continuum/plugin/AddShellProject.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.apache.maven.continuum.plugin;
-
-/*
- * 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 org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
-
-/**
- * Goal which add a Shell Project.
- *
- * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
- * @version $Id$
- * @goal add-shell-project
- */
-public class AddShellProject
-    extends AbstractAddProject
-{
-    protected String getProjectType()
-    {
-        return ContinuumBuildExecutorConstants.SHELL_BUILD_EXECUTOR;
-    }
-}
diff --git a/maven-continuum-plugin/src/main/java/org/apache/maven/continuum/plugin/PingMojo.java b/maven-continuum-plugin/src/main/java/org/apache/maven/continuum/plugin/PingMojo.java
deleted file mode 100644
index a0569c5..0000000
--- a/maven-continuum-plugin/src/main/java/org/apache/maven/continuum/plugin/PingMojo.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.apache.maven.continuum.plugin;
-
-/*
- * 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 org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugin.MojoFailureException;
-
-/**
- * Goal which ping the Continuum server.
- *
- * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
- * @version $Id$
- * @goal ping
- */
-public class PingMojo
-    extends AbstractContinuumMojo
-{
-    public void execute()
-        throws MojoExecutionException, MojoFailureException
-    {
-        try
-        {
-            getClient().ping();
-        }
-        catch ( Exception e )
-        {
-            throw new MojoExecutionException( "Can't run the continuum command.", e );
-        }
-    }
-}
diff --git a/pom.xml b/pom.xml
index 079dce3..6e5ccf3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,27 +1,29 @@
 <?xml version="1.0" encoding="UTF-8"?>
+
 <!--
-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.
---><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
     <groupId>org.apache.continuum</groupId>
     <artifactId>continuum-parent</artifactId>
-    <version>2</version>
+    <version>5</version>
     <relativePath>../parent/pom.xml</relativePath>
   </parent>
 
@@ -29,50 +31,84 @@
   <artifactId>continuum</artifactId>
   <packaging>pom</packaging>
   <name>Continuum :: Project</name>
-  <url>http://continuum.apache.org</url>
-  <version>1.3.1-SNAPSHOT</version>
+  <url>http://continuum.apache.org/ref/latest</url>
+  <version>1.4.3</version>
 
   <prerequisites>
-    <maven>2.0.7</maven>
+    <maven>2.0.9</maven>
   </prerequisites>
 
+  <properties>
+    <jetty.version>8.1.7.v20120910</jetty.version>
+    <continuumWebappVersion>${project.version}</continuumWebappVersion>
+    <!-- Note, when later moving beyond 2.2.1, the continuum-artifact-manager module should be removed -->
+    <maven.version>2.2.1</maven.version>
+    <spring.version>2.5.6</spring.version>
+    <struts.version>2.3.20</struts.version>
+    <wagon.version>1.0-beta-6</wagon.version>
+    <maven-scm.version>1.4</maven-scm.version>
+    <redback.version>1.3-M3</redback.version>
+    <archiva.version>1.2.1</archiva.version>
+    <slf4jVersion>1.5.8</slf4jVersion>
+    <xmlrpc.version>3.1.2</xmlrpc.version>
+    <atlassian.xmlrpc.binder.version>0.11</atlassian.xmlrpc.binder.version>
+    <surefire.version>2.12</surefire.version>
+    <svnUrl>https://svn.apache.org/repos/asf/continuum/site-publish/ref/latest</svnUrl>
+    <checkoutDirectory>site-publish</checkoutDirectory>
+  </properties>
+
   <scm>
-    <connection>scm:svn:http://svn.apache.org/repos/asf/continuum/trunk/</connection>
-    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/continuum/trunk/</developerConnection>
-    <url>http://svn.apache.org/viewcvs.cgi/continuum/trunk/</url>
+    <connection>scm:svn:http://svn.apache.org/repos/asf/continuum/tags/continuum-1.4.3</connection>
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/continuum/tags/continuum-1.4.3</developerConnection>
+    <url>http://svn.apache.org/viewvc/continuum/tags/continuum-1.4.3</url>
   </scm>
-  <distributionManagement>
-    <site>
-      <id>apache.website</id>
-      <url>scp://people.apache.org/www/continuum.apache.org/ref/${project.version}</url>
-    </site>
-  </distributionManagement>
   <reporting>
+    <excludeDefaults>true</excludeDefaults>
     <plugins>
       <plugin>
-        <groupId>org.codehaus.mojo</groupId>
-        <artifactId>findbugs-maven-plugin</artifactId>
-        <version>1.1.1</version>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-project-info-reports-plugin</artifactId>
+        <version>2.7</version>
+        <reportSets>
+          <reportSet>
+            <reports>
+              <report>index</report>
+              <report>summary</report>
+              <report>license</report>
+              <report>dependencies</report>
+              <report>dependency-management</report>
+              <report>plugins</report>
+              <report>plugin-management</report>
+              <report>modules</report>
+              <report>dependency-convergence</report>
+            </reports>
+          </reportSet>
+        </reportSets>
       </plugin>
       <plugin>
-        <groupId>org.codehaus.mojo</groupId>
-        <artifactId>changelog-maven-plugin</artifactId>
-      </plugin>
-      <plugin>
-        <groupId>org.codehaus.mojo</groupId>
-        <artifactId>taglist-maven-plugin</artifactId>
-      </plugin>
-      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-jxr-plugin</artifactId>
-        <configuration>
-          <aggregate>true</aggregate>
-        </configuration>
+        <version>2.3</version>
+        <inherited>false</inherited>
+        <reportSets>
+          <reportSet>
+            <id>aggregate</id>
+            <reports>
+              <report>aggregate</report>
+              <report>test-aggregate</report>
+            </reports>
+          </reportSet>
+        </reportSets>
       </plugin>
       <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-javadoc-plugin</artifactId>
+        <version>2.9</version>
+        <inherited>false</inherited>
         <configuration>
           <source>1.5</source>
-          <aggregate>true</aggregate>
+          <notimestamp>true</notimestamp>
+<!-- Disabled - currently generating empty PDFs in my environment (brett, 2013-01-02)
           <doclet>gr.spinellis.umlgraph.doclet.UmlGraphDoc</doclet>
           <docletArtifact>
             <groupId>gr.spinellis</groupId>
@@ -85,36 +121,135 @@
             -postfixpackage -nodefontsize 9
             -nodefontpackagesize 7
           </additionalparam>
+-->
         </configuration>
-      </plugin>
-      <plugin>
-        <artifactId>maven-pmd-plugin</artifactId>
-        <!-- TODO: choose appropriate rulesets -->
-        <configuration>
-          <targetJdk>1.5</targetJdk>
-        </configuration>
+        <reportSets>
+          <reportSet>
+            <id>aggregate</id>
+            <reports>
+              <report>aggregate</report>
+            </reports>
+          </reportSet>
+        </reportSets>
       </plugin>
     </plugins>
   </reporting>
   <build>
+    <finalName>apache-continuum-${project.version}</finalName>
     <pluginManagement>
       <plugins>
         <plugin>
+          <groupId>org.apache.rat</groupId>
+          <artifactId>apache-rat-plugin</artifactId>
+          <version>0.10</version>
+          <configuration>
+            <excludes>
+              <exclude>continuum-webapp-test/src/test/example-projects/**</exclude>
+              <exclude>continuum-webapp-test/src/test/example-svn/**</exclude>
+              <exclude>continuum-webapp-test/src/test/selenium-ide/**</exclude>
+              <exclude>**/*.iml</exclude>
+              <exclude>**/*.fbp</exclude>
+              <exclude>Continuum.sonarj</exclude>
+              <!-- modules that are not in the default build, need to be checked manually -->
+              <exclude>continuum-webapp-test/target/**</exclude>
+              <exclude>continuum-docs/target/**</exclude>
+            </excludes>
+          </configuration>
+        </plugin>
+        <plugin>
           <artifactId>maven-release-plugin</artifactId>
           <configuration>
             <tagBase>https://svn.apache.org/repos/asf/continuum/tags</tagBase>
             <preparationGoals>clean install</preparationGoals>
+            <autoVersionSubmodules>true</autoVersionSubmodules>
           </configuration>
         </plugin>
         <plugin>
           <groupId>org.codehaus.plexus</groupId>
           <artifactId>plexus-maven-plugin</artifactId>
-          <version>1.3.4</version>
+          <version>1.3.8</version>
         </plugin>
         <plugin>
           <groupId>org.codehaus.modello</groupId>
           <artifactId>modello-maven-plugin</artifactId>
-          <version>1.0-alpha-18</version>
+          <version>1.1</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-gpg-plugin</artifactId>
+          <version>1.1</version>
+          <configuration>
+            <useAgent>true</useAgent>
+          </configuration>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-antrun-plugin</artifactId>
+          <version>1.1</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-war-plugin</artifactId>
+          <version>2.0.2</version>
+        </plugin>
+        <plugin>
+          <groupId>org.codehaus.mojo</groupId>
+          <artifactId>appassembler-maven-plugin</artifactId>
+          <version>1.2</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-shade-plugin</artifactId>
+          <version>2.3</version>
+        </plugin>
+        <plugin>
+          <groupId>org.codehaus.mojo</groupId>
+          <artifactId>tomcat-maven-plugin</artifactId>
+          <version>1.0-beta-1</version>
+        </plugin>
+        <plugin>
+          <groupId>org.codehaus.mojo</groupId>
+          <artifactId>jpox-maven-plugin</artifactId>
+          <version>1.1.7</version>
+        </plugin>
+        <plugin>
+          <groupId>org.codehaus.mojo</groupId>
+          <artifactId>jspc-maven-plugin</artifactId>
+          <version>1.4.6</version>
+        </plugin>
+        <plugin>
+          <groupId>org.mortbay.jetty</groupId>
+          <artifactId>jetty-maven-plugin</artifactId>
+          <version>${jetty.version}</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-failsafe-plugin</artifactId>
+          <version>${surefire.version}</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-surefire-plugin</artifactId>
+          <version>${surefire.version}</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-scm-publish-plugin</artifactId>
+          <configuration>
+            <!-- Note: we use this instead of distributionManagement as that currently impacts the URLs that are
+                 inherited in continuum-docs -->
+            <pubScmUrl>scm:svn:${svnUrl}</pubScmUrl>
+          </configuration>
+        </plugin>
+        <plugin>
+          <groupId>com.google.code.maven-replacer-plugin</groupId>
+          <artifactId>replacer</artifactId>
+          <version>1.5.2</version>
+        </plugin>
+        <plugin>
+          <groupId>org.codehaus.mojo</groupId>
+          <artifactId>exec-maven-plugin</artifactId>
+          <version>1.2.1</version>
         </plugin>
       </plugins>
     </pluginManagement>
@@ -122,7 +257,7 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-enforcer-plugin</artifactId>
-        <version>1.0-alpha-3</version>
+        <version>1.3.1</version>
         <executions>
           <execution>
             <goals>
@@ -130,18 +265,30 @@
             </goals>
             <configuration>
               <rules>
+                <requireMavenVersion>
+                  <version>2.0.9</version>
+                </requireMavenVersion>
                 <bannedDependencies>
                   <excludes>
-<!--
-                    <exclude>org.codehaus.plexus:plexus-container-default</exclude>
--->
                     <exclude>velocity:velocity-dep</exclude>
                     <exclude>classworlds:classworlds</exclude>
                     <exclude>javax.transaction:jta</exclude>
                     <exclude>javax.sql:jdbc-stdext</exclude>
                     <exclude>ant:ant-optional</exclude>
                     <exclude>xom:xom</exclude>
+                    <exclude>org.codehaus.plexus:plexus-log4j-logging</exclude>
+                    <exclude>commons-logging:commons-logging</exclude>
+                    <exclude>org.slf4j:jcl104-over-slf4j</exclude>
+                    <exclude>org.slf4j:slf4j-nop</exclude>
+                    <exclude>org.codehaus.plexus:plexus-spring</exclude>
+                    <exclude>xml-apis:xml-apis</exclude>
+                    <exclude>jtidy:jtidy</exclude>
+                    <exclude>jdom:jdom</exclude>
+                    <exclude>org.apache.maven:maven-artifact-manager</exclude>
                   </excludes>
+                  <includes>
+                    <include>org.apache.maven:maven-artifact-manager:*:jar:provided</include>
+                  </includes>
                 </bannedDependencies>
               </rules>
             </configuration>
@@ -164,23 +311,29 @@
       </plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-failsafe-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
+          <redirectTestOutputToFile>true</redirectTestOutputToFile>
+          <argLine>-Xmx512m</argLine>
           <systemProperties>
             <property>
               <name>JAVA_HOME</name>
-              <value>${java.home}</value>    
-            </property>     
+              <value>${java.home}</value>
+            </property>
             <property>
               <name>M2_HOME</name>
-              <value>${maven.home}</value>    
-            </property>    
+              <value>${maven.home}</value>
+            </property>
             <property>
               <name>plexus.home</name>
               <!-- ${project.build.directory} is not evaluated see surefire documentation -->
               <!--value>${project.build.directory}</value-->
               <value>./target</value>
-            </property>                           
+            </property>
             <property>
               <name>appserver.base</name>
               <value>${basedir}/target/test-classes/</value>
@@ -192,7 +345,7 @@
             <property>
               <!-- java.io.tmpdir is a shared directory on solaris and cause permission issues -->
               <name>java.io.tmpdir</name>
-              <value>./target</value>
+              <value>${project.build.directory}</value>
             </property>
           </systemProperties>
         </configuration>
@@ -201,11 +354,11 @@
   </build>
   <modules>
     <module>continuum-api</module>
-    <module>continuum-base</module>    
+    <module>continuum-base</module>
     <module>continuum-commons</module>
     <module>continuum-security</module>
-    <module>continuum-store</module>    
-    <module>continuum-reports</module>    
+    <module>continuum-store</module>
+    <module>continuum-reports</module>
     <module>continuum-core</module>
     <module>continuum-model</module>
     <module>continuum-notifiers</module>
@@ -214,90 +367,80 @@
     <module>continuum-xmlrpc</module>
     <module>continuum-release</module>
     <module>continuum-data-management</module>
-    <module>maven-continuum-plugin</module>
-    <module>continuum-docs</module>
     <module>continuum-jetty</module>
     <module>continuum-purge</module>
-    <module>continuum-distributed-build</module>
+    <module>continuum-buildagent</module>
+    <module>continuum-distributed</module>
     <module>continuum-builder</module>
+    <module>continuum-artifact-manager</module>
   </modules>
-  <!-- TODO: confirm whether these are needed -->
   <repositories>
+    <!-- atlassian xmlrpc 0.11 -->
     <repository>
-      <id>maven2-repository.dev.java.net</id>
-      <name>Java.net Repository for Maven</name>
-      <url>http://download.java.net/maven/2/</url>
+      <id>atlassian.releases</id>
+      <url>https://maven.atlassian.com/content/groups/public</url>
       <releases>
         <enabled>true</enabled>
       </releases>
       <snapshots>
         <enabled>false</enabled>
-      </snapshots>      
+      </snapshots>
     </repository>
-    <repository>
-      <id>maven1-repository.dev.java.net</id>
-      <name>Java.net Repository for Maven 1</name>
-      <url>http://download.java.net/maven/1/</url>
-      <layout>legacy</layout>
-      <releases>
-        <enabled>true</enabled>
-      </releases>
-      <snapshots>
-        <enabled>false</enabled>
-      </snapshots>      
-    </repository>    
-    <!-- remove when parent is released -->
-    <repository>
-      <id>apache.snapshots</id>
-      <name>Apache Snapshot Repository</name>
-      <url>http://people.apache.org/repo/m2-snapshot-repository</url>
-      <releases>
-        <enabled>false</enabled>
-      </releases>
-      <snapshots>
-        <enabled>true</enabled>
-      </snapshots>
-    </repository>    
-    <repository>
-      <id>codehaus.snapshots</id>
-      <name>Codehaus Snapshot Repository</name>
-      <url>http://snapshots.repository.codehaus.org</url>
-      <releases>
-        <enabled>false</enabled>
-      </releases>
-      <snapshots>
-        <enabled>true</enabled>
-      </snapshots>
-    </repository>    
   </repositories>
   <dependencies>
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
-      <version>3.8.1</version>
       <scope>test</scope>
     </dependency>
   </dependencies>
   <dependencyManagement>
     <dependencies>
       <dependency>
+        <groupId>junit</groupId>
+        <artifactId>junit</artifactId>
+        <version>3.8.1</version>
+      </dependency>
+      <dependency>
         <groupId>org.jmock</groupId>
         <artifactId>jmock-junit3</artifactId>
         <version>2.4.0</version>
         <scope>test</scope>
       </dependency>
       <dependency>
+        <groupId>org.jmock</groupId>
+        <artifactId>jmock-legacy</artifactId>
+        <version>2.4.0</version>
+        <scope>test</scope>
+      </dependency>
+      <dependency>
         <groupId>jmock</groupId>
         <artifactId>jmock</artifactId>
         <version>1.0.1</version>
         <scope>test</scope>
       </dependency>
       <dependency>
+        <groupId>cglib</groupId>
+        <artifactId>cglib-nodep</artifactId>
+        <version>2.1_3</version>
+        <scope>test</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.objenesis</groupId>
+        <artifactId>objenesis</artifactId>
+        <version>1.0</version>
+        <scope>test</scope>
+      </dependency>
+      <dependency>
         <groupId>org.apache.maven</groupId>
         <artifactId>maven-core</artifactId>
         <version>${maven.version}</version>
         <exclusions>
           <exclusion>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+          </exclusion>
+          <exclusion>
             <groupId>classworlds</groupId>
             <artifactId>classworlds</artifactId>
           </exclusion>
@@ -333,6 +476,7 @@
         <groupId>org.apache.maven</groupId>
         <artifactId>maven-artifact-manager</artifactId>
         <version>${maven.version}</version>
+        <scope>provided</scope>
         <exclusions>
           <exclusion>
             <groupId>org.codehaus.plexus</groupId>
@@ -342,6 +486,22 @@
       </dependency>
       <dependency>
         <groupId>org.apache.maven</groupId>
+        <artifactId>maven-repository-metadata</artifactId>
+        <version>${maven.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.continuum</groupId>
+        <artifactId>continuum-artifact-manager</artifactId>
+        <version>${project.version}</version>
+        <exclusions>
+          <exclusion>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-artifact-manager</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.maven</groupId>
         <artifactId>maven-project</artifactId>
         <version>${maven.version}</version>
         <exclusions>
@@ -349,6 +509,10 @@
             <groupId>org.codehaus.plexus</groupId>
             <artifactId>plexus-container-default</artifactId>
           </exclusion>
+          <exclusion>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-artifact-manager</artifactId>
+          </exclusion>
         </exclusions>
       </dependency>
       <dependency>
@@ -369,6 +533,21 @@
       </dependency>
       <dependency>
         <groupId>org.apache.maven.scm</groupId>
+        <artifactId>maven-scm-provider-svnexe</artifactId>
+        <version>${maven-scm.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.maven.scm</groupId>
+        <artifactId>maven-scm-provider-cvsjava</artifactId>
+        <version>${maven-scm.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.maven.scm</groupId>
+        <artifactId>maven-scm-provider-cvsexe</artifactId>
+        <version>${maven-scm.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.maven.scm</groupId>
         <artifactId>maven-scm-manager-plexus</artifactId>
         <version>${maven-scm.version}</version>
       </dependency>
@@ -377,7 +556,7 @@
         <artifactId>maven-scm-providers-standard</artifactId>
         <version>${maven-scm.version}</version>
         <type>pom</type>
-      </dependency>      
+      </dependency>
       <dependency>
         <groupId>org.apache.maven.scm</groupId>
         <artifactId>maven-scm-provider-local</artifactId>
@@ -387,12 +566,70 @@
         <groupId>org.apache.maven.scm</groupId>
         <artifactId>maven-scm-provider-cvs-commons</artifactId>
         <version>${maven-scm.version}</version>
-      </dependency>    
+      </dependency>
       <dependency>
         <groupId>org.apache.maven.scm</groupId>
         <artifactId>maven-scm-provider-svn-commons</artifactId>
         <version>${maven-scm.version}</version>
-      </dependency>         
+      </dependency>
+      <dependency>
+        <groupId>org.apache.maven.scm</groupId>
+        <artifactId>maven-scm-provider-bazaar</artifactId>
+        <version>${maven-scm.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.maven.scm</groupId>
+        <artifactId>maven-scm-provider-clearcase</artifactId>
+        <version>${maven-scm.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.maven.scm</groupId>
+        <artifactId>maven-scm-provider-hg</artifactId>
+        <version>${maven-scm.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.maven.scm</groupId>
+        <artifactId>maven-scm-provider-perforce</artifactId>
+        <version>${maven-scm.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.maven.scm</groupId>
+        <artifactId>maven-scm-provider-starteam</artifactId>
+        <version>${maven-scm.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.maven.scm</groupId>
+        <artifactId>maven-scm-provider-synergy</artifactId>
+        <version>${maven-scm.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.maven.scm</groupId>
+        <artifactId>maven-scm-provider-git-commons</artifactId>
+        <version>${maven-scm.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.maven.release</groupId>
+        <artifactId>maven-release-manager</artifactId>
+        <version>2.1</version>
+        <exclusions>
+          <exclusion>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>org.codehaus.plexus</groupId>
+            <artifactId>plexus-container-default</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>jdom</groupId>
+            <artifactId>jdom</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-artifact-manager</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
       <dependency>
         <groupId>org.apache.maven.wagon</groupId>
         <artifactId>wagon-provider-api</artifactId>
@@ -407,6 +644,16 @@
         <groupId>org.apache.maven.wagon</groupId>
         <artifactId>wagon-http-lightweight</artifactId>
         <version>${wagon.version}</version>
+        <exclusions>
+          <exclusion>
+            <groupId>xml-apis</groupId>
+            <artifactId>xml-apis</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>jtidy</groupId>
+            <artifactId>jtidy</artifactId>
+          </exclusion>
+        </exclusions>
       </dependency>
       <dependency>
         <groupId>org.apache.maven.wagon</groupId>
@@ -420,59 +667,73 @@
       </dependency>
       <dependency>
         <groupId>org.apache.maven.wagon</groupId>
-        <artifactId>wagon-webdav</artifactId>
+        <artifactId>wagon-webdav-jackrabbit</artifactId>
         <version>${wagon.version}</version>
+        <exclusions>
+          <exclusion>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>jdom</groupId>
+            <artifactId>jdom</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-nop</artifactId>
+          </exclusion>
+        </exclusions>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>continuum-model</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>continuum-api</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>continuum-commons</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>continuum-configuration</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>continuum-scm</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>continuum-store</artifactId>
         <classifier>tests</classifier>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>continuum-store</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>continuum-reports</artifactId>
-        <version>${pom.version}</version>
-      </dependency>      
+        <version>${project.version}</version>
+      </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>continuum-core</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>continuum-test</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
@@ -487,134 +748,208 @@
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>continuum-xmlrpc-server</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
-        <artifactId>continuum-plexus-application</artifactId>
-        <version>${pom.version}</version>
+        <artifactId>continuum-buildagent-webdav</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.xmlrpc</groupId>
+        <artifactId>xmlrpc-client</artifactId>
+        <version>${xmlrpc.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.xmlrpc</groupId>
+        <artifactId>xmlrpc-server</artifactId>
+        <version>${xmlrpc.version}</version>
+        <exclusions>
+          <exclusion>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.xmlrpc</groupId>
+        <artifactId>xmlrpc-common</artifactId>
+        <version>${xmlrpc.version}</version>
+        <exclusions>
+          <exclusion>
+            <groupId>xml-apis</groupId>
+            <artifactId>xml-apis</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
+      <dependency>
+        <groupId>com.atlassian.xmlrpc</groupId>
+        <artifactId>atlassian-xmlrpc-binder-annotations</artifactId>
+        <version>${atlassian.xmlrpc.binder.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>com.atlassian.xmlrpc</groupId>
+        <artifactId>atlassian-xmlrpc-binder-support</artifactId>
+        <version>${atlassian.xmlrpc.binder.version}</version>
+        <exclusions>
+          <exclusion>
+            <groupId>xml-apis</groupId>
+            <artifactId>xml-apis</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
+      <dependency>
+        <groupId>com.atlassian.xmlrpc</groupId>
+        <artifactId>atlassian-xmlrpc-binder</artifactId>
+        <version>${atlassian.xmlrpc.binder.version}</version>
+        <exclusions>
+          <exclusion>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
+      <dependency>
+        <groupId>com.atlassian.xmlrpc</groupId>
+        <artifactId>atlassian-xmlrpc-binder-server-spring</artifactId>
+        <version>${atlassian.xmlrpc.binder.version}</version>
+        <exclusions>
+          <exclusion>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>xml-apis</groupId>
+            <artifactId>xml-apis</artifactId>
+          </exclusion>
+        </exclusions>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>continuum-notifier-api</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>continuum-notifier-irc</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>continuum-notifier-jabber</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>continuum-notifier-msn</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>continuum-notifier-wagon</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>continuum-release</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>continuum-security</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>continuum-webapp</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
         <type>war</type>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>continuum-legacy</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>data-management-api</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>data-management-cli</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>data-management-jdo</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>data-management-redback-jdo</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>redback-legacy</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>continuum-builder</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>continuum-buildagent-api</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>continuum-buildagent-core</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>continuum-buildagent-webapp</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
         <type>war</type>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
-        <artifactId>continuum-distributed-build-transport-slave-api</artifactId>
-        <version>${pom.version}</version>
+        <artifactId>continuum-distributed-commons</artifactId>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
-        <artifactId>continuum-distributed-build-transport-slave-server</artifactId>
-        <version>${pom.version}</version>
+        <artifactId>continuum-distributed-slave-api</artifactId>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
-        <artifactId>continuum-distributed-build-transport-slave-client</artifactId>
-        <version>${pom.version}</version>
+        <artifactId>continuum-distributed-slave-server</artifactId>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
-        <artifactId>continuum-distributed-build-transport-master-api</artifactId>
-        <version>${pom.version}</version>
+        <artifactId>continuum-distributed-slave-client</artifactId>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
-        <artifactId>continuum-distributed-build-transport-master-server</artifactId>
-        <version>${pom.version}</version>
+        <artifactId>continuum-distributed-master-api</artifactId>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.continuum</groupId>
-        <artifactId>continuum-distributed-build-transport-master-client</artifactId>
-        <version>${pom.version}</version>
+        <artifactId>continuum-distributed-master-server</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.continuum</groupId>
+        <artifactId>continuum-distributed-master-client</artifactId>
+        <version>${project.version}</version>
       </dependency>
       <dependency>
         <groupId>net.sf.ehcache</groupId>
@@ -640,6 +975,10 @@
             <groupId>org.codehaus.plexus</groupId>
             <artifactId>plexus-container-default</artifactId>
           </exclusion>
+          <exclusion>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-artifact-manager</artifactId>
+          </exclusion>
         </exclusions>
       </dependency>
       <dependency>
@@ -674,9 +1013,24 @@
             <groupId>commons-logging</groupId>
             <artifactId>commons-logging-api</artifactId>
           </exclusion>
+          <exclusion>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+          </exclusion>
         </exclusions>
       </dependency>
       <dependency>
+        <groupId>xmlunit</groupId>
+        <artifactId>xmlunit</artifactId>
+        <version>1.0</version>
+        <scope>test</scope>
+      </dependency>
+      <dependency>
+        <groupId>jdom</groupId>
+        <artifactId>jdom</artifactId>
+        <version>1.0</version>
+      </dependency>
+      <dependency>
         <groupId>jpox</groupId>
         <artifactId>jpox</artifactId>
         <version>1.1.9-1</version>
@@ -689,6 +1043,11 @@
             <groupId>javax.resource</groupId>
             <artifactId>connector-api</artifactId>
           </exclusion>
+          <!-- targeting JDK 1.4 we don't need this -->
+          <exclusion>
+            <groupId>javax.sql</groupId>
+            <artifactId>jdbc-stdext</artifactId>
+          </exclusion>
         </exclusions>
       </dependency>
       <dependency>
@@ -717,14 +1076,9 @@
         <version>5.2</version>
       </dependency>
       <dependency>
-        <groupId>log4j</groupId>
-        <artifactId>log4j</artifactId>
-        <version>1.2.12</version>
-      </dependency>
-      <dependency>
         <groupId>org.codehaus.plexus</groupId>
         <artifactId>plexus-utils</artifactId>
-        <version>1.5.4</version>
+        <version>3.0.15</version>
       </dependency>
       <dependency>
         <groupId>org.codehaus.plexus</groupId>
@@ -739,13 +1093,24 @@
       </dependency>
       <dependency>
         <groupId>org.apache.httpcomponents</groupId>
+        <artifactId>httpcore</artifactId>
+        <version>4.1.1</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.httpcomponents</groupId>
         <artifactId>httpclient</artifactId>
-        <version>4.0-beta2</version>
+        <version>4.1.1</version>
+        <exclusions>
+          <exclusion>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+          </exclusion>
+        </exclusions>
       </dependency>
       <dependency>
         <groupId>org.codehaus.plexus</groupId>
         <artifactId>plexus-velocity</artifactId>
-        <version>1.1.4</version>
+        <version>1.1.7</version>
         <exclusions>
           <exclusion>
             <groupId>velocity</groupId>
@@ -772,13 +1137,29 @@
         <groupId>org.slf4j</groupId>
         <artifactId>slf4j-api</artifactId>
         <version>${slf4jVersion}</version>
-      </dependency>      
+      </dependency>
+      <dependency>
+        <groupId>org.slf4j</groupId>
+        <artifactId>slf4j-simple</artifactId>
+        <version>${slf4jVersion}</version>
+        <scope>test</scope>
+      </dependency>
       <dependency>
         <groupId>org.slf4j</groupId>
         <artifactId>slf4j-log4j12</artifactId>
         <version>${slf4jVersion}</version>
       </dependency>
-      
+      <dependency>
+        <groupId>org.slf4j</groupId>
+        <artifactId>jcl-over-slf4j</artifactId>
+        <version>${slf4jVersion}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.slf4j</groupId>
+        <artifactId>slf4j-jdk14</artifactId>
+        <version>${slf4jVersion}</version>
+      </dependency>
+
       <dependency>
         <groupId>org.codehaus.plexus</groupId>
         <artifactId>plexus-taskqueue</artifactId>
@@ -790,6 +1171,16 @@
         <version>10.1.3.1</version>
       </dependency>
       <dependency>
+        <groupId>javax.mail</groupId>
+        <artifactId>mail</artifactId>
+        <version>1.4</version>
+      </dependency>
+      <dependency>
+        <groupId>javax.activation</groupId>
+        <artifactId>activation</artifactId>
+        <version>1.1</version>
+      </dependency>
+      <dependency>
         <groupId>hsqldb</groupId>
         <artifactId>hsqldb</artifactId>
         <version>1.8.0.7</version>
@@ -798,31 +1189,43 @@
         <groupId>org.codehaus.plexus</groupId>
         <artifactId>plexus-quartz</artifactId>
         <version>1.0-alpha-4</version>
+        <exclusions>
+          <exclusion>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+          </exclusion>
+        </exclusions>
       </dependency>
       <dependency>
         <groupId>commons-configuration</groupId>
         <artifactId>commons-configuration</artifactId>
         <version>1.5</version>
+        <exclusions>
+          <exclusion>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+          </exclusion>
+        </exclusions>
       </dependency>
       <dependency>
         <groupId>commons-lang</groupId>
         <artifactId>commons-lang</artifactId>
         <version>2.4</version>
-      </dependency>      
+      </dependency>
       <dependency>
         <groupId>commons-collections</groupId>
         <artifactId>commons-collections</artifactId>
         <version>3.2.1</version>
-      </dependency>      
+      </dependency>
       <dependency>
         <groupId>commons-io</groupId>
         <artifactId>commons-io</artifactId>
         <version>1.4</version>
-      </dependency>      
+      </dependency>
       <dependency>
         <groupId>org.apache.struts</groupId>
         <artifactId>struts2-core</artifactId>
-        <version>2.0.14</version>
+        <version>${struts.version}</version>
         <exclusions>
           <exclusion>
             <groupId>commons-logging</groupId>
@@ -833,7 +1236,7 @@
       <dependency>
         <groupId>org.apache.struts</groupId>
         <artifactId>struts2-spring-plugin</artifactId>
-        <version>2.0.14</version>
+        <version>${struts.version}</version>
         <exclusions>
           <exclusion>
             <groupId>commons-logging</groupId>
@@ -841,11 +1244,6 @@
           </exclusion>
         </exclusions>
       </dependency>
-      <dependency>
-        <groupId>com.opensymphony</groupId>
-        <artifactId>xwork</artifactId>
-        <version>2.0.7</version>
-      </dependency>
       <!--
         Plexus Redback Dependencies
         -->
@@ -863,6 +1261,31 @@
       </dependency>
       <dependency>
         <groupId>org.codehaus.redback</groupId>
+        <artifactId>redback-authentication-api</artifactId>
+        <version>${redback.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.codehaus.redback</groupId>
+        <artifactId>redback-policy</artifactId>
+        <version>${redback.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.codehaus.redback</groupId>
+        <artifactId>redback-authorization-api</artifactId>
+        <version>${redback.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.codehaus.redback</groupId>
+        <artifactId>redback-users-api</artifactId>
+        <version>${redback.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.codehaus.redback</groupId>
+        <artifactId>redback-keys-api</artifactId>
+        <version>${redback.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.codehaus.redback</groupId>
         <artifactId>redback-users-memory</artifactId>
         <version>${redback.version}</version>
         <scope>test</scope>
@@ -908,6 +1331,10 @@
             <groupId>org.codehaus.plexus</groupId>
             <artifactId>plexus-container-default</artifactId>
           </exclusion>
+          <exclusion>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+          </exclusion>
         </exclusions>
       </dependency>
       <dependency>
@@ -953,7 +1380,7 @@
           <exclusion>
             <groupId>commons-logging</groupId>
             <artifactId>commons-logging</artifactId>
-          </exclusion> 
+          </exclusion>
         </exclusions>
       </dependency>
       <dependency>
@@ -965,44 +1392,116 @@
         <groupId>commons-httpclient</groupId>
         <artifactId>commons-httpclient</artifactId>
         <version>3.1</version>
+        <exclusions>
+          <exclusion>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+          </exclusion>
+        </exclusions>
       </dependency>
       <dependency>
-        <groupId>org.codehaus.plexus</groupId>
+        <groupId>org.codehaus.redback</groupId>
         <artifactId>plexus-spring</artifactId>
-        <version>1.2</version>
+        <version>${redback.version}</version>
+        <exclusions>
+          <exclusion>
+            <groupId>xml-apis</groupId>
+            <artifactId>xml-apis</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+          </exclusion>
+        </exclusions>
       </dependency>
-      
+      <dependency>
+        <groupId>org.codehaus.redback</groupId>
+        <artifactId>redback-xmlrpc-services</artifactId>
+        <version>${redback.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.codehaus.redback</groupId>
+        <artifactId>redback-xmlrpc-security</artifactId>
+        <version>${redback.version}</version>
+      </dependency>
+
       <!-- due to http://jira.codehaus.org/browse/MECLIPSE-472 -->
       <dependency>
         <groupId>org.codehaus.plexus</groupId>
         <artifactId>plexus-component-api</artifactId>
-        <version>1.0-alpha-20</version>
-      </dependency>      
+        <version>1.0-alpha-22</version>
+      </dependency>
+      <dependency>
+        <groupId>org.codehaus.plexus</groupId>
+        <artifactId>plexus-container-default</artifactId>
+        <version>1.0-alpha-22</version>
+      </dependency>
 
       <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-beans</artifactId>
         <version>${spring.version}</version>
+        <exclusions>
+          <exclusion>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+          </exclusion>
+        </exclusions>
       </dependency>
       <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-context</artifactId>
         <version>${spring.version}</version>
+        <exclusions>
+          <exclusion>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+          </exclusion>
+        </exclusions>
       </dependency>
       <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-context-support</artifactId>
         <version>${spring.version}</version>
-      </dependency>      
+        <exclusions>
+          <exclusion>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
       <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-core</artifactId>
         <version>${spring.version}</version>
+        <exclusions>
+          <exclusion>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+          </exclusion>
+        </exclusions>
       </dependency>
       <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-web</artifactId>
         <version>${spring.version}</version>
+        <exclusions>
+          <exclusion>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
+      <dependency>
+        <groupId>org.springframework</groupId>
+        <artifactId>spring-tx</artifactId>
+        <version>${spring.version}</version>
+        <exclusions>
+          <exclusion>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+          </exclusion>
+        </exclusions>
       </dependency>
       <dependency>
         <groupId>javax.annotation</groupId>
@@ -1012,44 +1511,333 @@
       <dependency>
         <groupId>org.apache.continuum</groupId>
         <artifactId>continuum-purge</artifactId>
-        <version>${pom.version}</version>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.archiva</groupId>
+        <artifactId>archiva-model</artifactId>
+        <version>${archiva.version}</version>
+        <exclusions>
+          <exclusion>
+            <groupId>org.slf4j</groupId>
+            <artifactId>jcl104-over-slf4j</artifactId>
+          </exclusion>
+        </exclusions>
       </dependency>
       <dependency>
         <groupId>org.apache.archiva</groupId>
         <artifactId>archiva-common</artifactId>
         <version>${archiva.version}</version>
+        <exclusions>
+          <exclusion>
+            <groupId>xalan</groupId>
+            <artifactId>xalan</artifactId>
+          </exclusion>
+        </exclusions>
       </dependency>
       <dependency>
-        <groupId>org.apache.maven.archiva</groupId>
+        <groupId>org.apache.archiva</groupId>
         <artifactId>archiva-repository-layer</artifactId>
         <version>${archiva.version}</version>
+        <exclusions>
+          <exclusion>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>org.slf4j</groupId>
+            <artifactId>jcl104-over-slf4j</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>xml-apis</groupId>
+            <artifactId>xml-apis</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>jdom</groupId>
+            <artifactId>jdom</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.archiva</groupId>
+        <artifactId>archiva-core-consumers</artifactId>
+        <version>${archiva.version}</version>
+        <exclusions>
+          <exclusion>
+            <groupId>org.apache.archiva</groupId>
+            <artifactId>archiva-database</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>org.apache.archiva</groupId>
+            <artifactId>archiva-configuration</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>org.apache.archiva</groupId>
+            <artifactId>archiva-indexer</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>org.apache.archiva</groupId>
+            <artifactId>archiva-consumer-api</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>org.apache.archiva</groupId>
+            <artifactId>archiva-repository-layer</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
+      <dependency>
+        <groupId>org.codehaus.plexus</groupId>
+        <artifactId>plexus-command-line</artifactId>
+        <version>1.0-alpha-2</version>
+        <exclusions>
+          <exclusion>
+            <groupId>org.codehaus.plexus</groupId>
+            <artifactId>plexus-container-default</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
+      <dependency>
+        <groupId>easymock</groupId>
+        <artifactId>easymock</artifactId>
+        <version>1.2_Java1.3</version>
+        <scope>test</scope>
+      </dependency>
+      <dependency>
+        <groupId>easymock</groupId>
+        <artifactId>easymockclassextension</artifactId>
+        <version>1.2</version>
+        <scope>test</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.codehaus.plexus</groupId>
+        <artifactId>plexus-action</artifactId>
+        <version>1.0-alpha-6</version>
+        <exclusions>
+          <exclusion>
+            <groupId>org.codehaus.plexus</groupId>
+            <artifactId>plexus-container-default</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
+      <dependency>
+        <groupId>stax</groupId>
+        <artifactId>stax</artifactId>
+        <version>1.1.1-dev</version>
+        <scope>runtime</scope>
+        <exclusions>
+          <exclusion>
+            <groupId>xmlbeans</groupId>
+            <artifactId>xmlbeans-jsr173-api</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
+      <dependency>
+        <groupId>net.java.dev.stax-utils</groupId>
+        <artifactId>stax-utils</artifactId>
+        <version>20060502</version>
+        <exclusions>
+          <exclusion>
+            <groupId>com.bea.xml</groupId>
+            <artifactId>jsr173-ri</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
+      <dependency>
+        <groupId>stax</groupId>
+        <artifactId>stax-api</artifactId>
+        <version>1.0.1</version>
+      </dependency>
+      <dependency>
+        <groupId>org.eclipse.jetty</groupId>
+        <artifactId>jetty-server</artifactId>
+        <version>${jetty.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.eclipse.jetty</groupId>
+        <artifactId>jetty-deploy</artifactId>
+        <version>${jetty.version}</version>
+        <scope>runtime</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.eclipse.jetty</groupId>
+        <artifactId>jetty-start</artifactId>
+        <version>${jetty.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.eclipse.jetty</groupId>
+        <artifactId>jetty-jndi</artifactId>
+        <version>${jetty.version}</version>
+        <scope>runtime</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.eclipse.jetty</groupId>
+        <artifactId>jetty-jsp</artifactId>
+        <version>${jetty.version}</version>
+        <scope>runtime</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.eclipse.jetty</groupId>
+        <artifactId>jetty-plus</artifactId>
+        <version>${jetty.version}</version>
+        <scope>runtime</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.eclipse.jetty</groupId>
+        <artifactId>jetty-annotations</artifactId>
+        <version>${jetty.version}</version>
+        <scope>runtime</scope>
+      </dependency>
+      <dependency>
+        <groupId>commons-dbcp</groupId>
+        <artifactId>commons-dbcp</artifactId>
+        <version>1.4</version>
+        <scope>runtime</scope>
+      </dependency>
+      <dependency>
+        <groupId>com.google.code.cli-parser</groupId>
+        <artifactId>cli</artifactId>
+        <version>7</version>
+      </dependency>
+      <dependency>
+        <groupId>log4j</groupId>
+        <artifactId>log4j</artifactId>
+        <version>1.2.14</version>
+      </dependency>
+      <dependency>
+        <groupId>backport-util-concurrent</groupId>
+        <artifactId>backport-util-concurrent</artifactId>
+        <version>3.0</version>
+      </dependency>
+      <dependency>
+        <groupId>quartz</groupId>
+        <artifactId>quartz</artifactId>
+        <version>1.5.2</version>
+        <exclusions>
+          <exclusion>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
+      <dependency>
+        <groupId>org.jmock</groupId>
+        <artifactId>jmock</artifactId>
+        <version>2.4.0</version>
+        <scope>test</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.hamcrest</groupId>
+        <artifactId>hamcrest-core</artifactId>
+        <version>1.1</version>
+        <scope>test</scope>
+      </dependency>
+      <dependency>
+        <groupId>velocity</groupId>
+        <artifactId>velocity</artifactId>
+        <version>1.4</version>
+        <exclusions>
+          <exclusion>
+            <groupId>velocity</groupId>
+            <artifactId>velocity-dep</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
+      <dependency>
+        <groupId>org.codehaus.plexus</groupId>
+        <artifactId>plexus-classworlds</artifactId>
+        <version>1.2-alpha-7</version>
+      </dependency>
+      <dependency>
+        <groupId>javax.jdo</groupId>
+        <artifactId>jdo2-api</artifactId>
+        <version>2.0</version>
+      </dependency>
+      <dependency>
+        <groupId>xml-apis</groupId>
+        <artifactId>xml-apis</artifactId>
+        <version>1.0.b2</version>
+      </dependency>
+      <dependency>
+        <groupId>commons-logging</groupId>
+        <artifactId>commons-logging-api</artifactId>
+        <version>1.1</version>
+      </dependency>
+      <dependency>
+        <groupId>javax.servlet</groupId>
+        <artifactId>servlet-api</artifactId>
+        <version>2.4</version>
+        <scope>provided</scope>
+      </dependency>
+      <dependency>
+        <groupId>joda-time</groupId>
+        <artifactId>joda-time</artifactId>
+        <version>1.5.2</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.jackrabbit</groupId>
+        <artifactId>jackrabbit-webdav</artifactId>
+        <version>1.5.0</version>
+        <exclusions>
+          <exclusion>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
+      <dependency>
+        <groupId>httpunit</groupId>
+        <artifactId>httpunit</artifactId>
+        <version>1.6.2</version>
+        <scope>test</scope>
+        <exclusions>
+          <exclusion>
+            <groupId>jtidy</groupId>
+            <artifactId>jtidy</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
+      <dependency>
+        <groupId>org.jsoup</groupId>
+        <artifactId>jsoup</artifactId>
+        <version>1.5.2</version>
+      </dependency>
+      <dependency>
+        <groupId>jpox</groupId>
+        <artifactId>jpox-ehcache</artifactId>
+        <version>1.1.9</version>
+      </dependency>
+      <dependency>
+        <groupId>org.jdom</groupId>
+        <artifactId>jdom</artifactId>
+        <version>1.1</version>
+      </dependency>
+      <dependency>
+        <groupId>nekohtml</groupId>
+        <artifactId>nekohtml</artifactId>
+        <version>1.9.6.2</version>
+        <exclusions>
+          <exclusion>
+            <groupId>xml-apis</groupId>
+            <artifactId>xml-apis</artifactId>
+          </exclusion>
+        </exclusions>
       </dependency>
     </dependencies>
   </dependencyManagement>
 
   <profiles>
     <profile>
-      <id>release</id>
+      <id>apache-release</id>
       <build>
         <plugins>
           <plugin>
-            <artifactId>maven-assembly-plugin</artifactId>
-            <version>2.1</version>
-            <inherited>false</inherited>
-            <configuration>
-              <descriptors>
-                <descriptor>src/main/assembly/src.xml</descriptor>
-              </descriptors>
-              <tarLongFileMode>gnu</tarLongFileMode>
-              <appendAssemblyId>false</appendAssemblyId>
-              <finalName>apache-continuum-${version}-src</finalName>
-            </configuration>
+            <groupId>org.apache.rat</groupId>
+            <artifactId>apache-rat-plugin</artifactId>
             <executions>
               <execution>
-                <id>make-assembly</id>
-                <phase>package</phase>
+                <phase>verify</phase>
                 <goals>
-                  <goal>single</goal>
+                  <goal>check</goal>
                 </goals>
               </execution>
             </executions>
@@ -1088,20 +1876,16 @@
               <doCheck>false</doCheck>
               <doUpdate>false</doUpdate>
             </configuration>
-          </plugin>        
+          </plugin>
         </plugins>
       </build>
     </profile>
   </profiles>
-
-  <properties>
-    <continuumWebappVersion>${pom.version}</continuumWebappVersion>
-    <maven.version>2.0.9</maven.version>
-    <spring.version>2.5.6</spring.version>
-    <wagon.version>1.0-beta-2</wagon.version>
-    <maven-scm.version>1.1</maven-scm.version>
-    <redback.version>1.2-SNAPSHOT</redback.version>
-    <archiva.version>1.1</archiva.version>
-    <slf4jVersion>1.5.6</slf4jVersion>
-  </properties>
+  <distributionManagement>
+    <!-- Site base required here for site:stage to calculate correct URLs -->
+    <site>
+      <id>apache</id>
+      <url>scm:svn:${rootSitePublishUrl}</url>
+    </site>
+  </distributionManagement>
 </project>
diff --git a/release-script.sh b/release-script.sh
deleted file mode 100755
index a038010..0000000
--- a/release-script.sh
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/local/bin/bash
-## $Id$ ##
-#$1 version
-#$2 staging repo path on p.a.o
-
-set -x
-if test $# -ne 2 
-then
-  echo 'usage release-script.sh version stagingRepoPath on p.a.o'
-  exit
-fi
-export VER=$1
-export STAGE_REPO=$2
-
-cd /www/people.apache.org/builds/continuum/$1
-
-find $STAGE_REPO -name "*.zip*"    -exec cp {} . \;
-find $STAGE_REPO -name "*.tar.gz*" -exec cp {} . \;
-find $STAGE_REPO -name "*.war*"    -exec cp {} . \;
-find . -name "*.asc.*" -exec rm {} \;
-
-mv continuum-$VER.zip apache-continuum-$VER-src.zip
-mv continuum-$VER.zip.md5 apache-continuum-$VER-src.zip.md5
-mv continuum-$VER.zip.sha1 apache-continuum-$VER-src.zip.sha1
-mv continuum-$VER.zip.asc apache-continuum-$VER-src.zip.asc
-
-mv continuum-jetty-$VER-bin.tar.gz apache-continuum-$VER-bin.tar.gz
-mv continuum-jetty-$VER-bin.tar.gz.md5 apache-continuum-$VER-bin.tar.gz.md5
-mv continuum-jetty-$VER-bin.tar.gz.sha1 apache-continuum-$VER-bin.tar.gz.sha1
-mv continuum-jetty-$VER-bin.tar.gz.asc apache-continuum-$VER-bin.tar.gz.asc
-
-mv continuum-jetty-$VER-bin.zip apache-continuum-$VER-bin.zip
-mv continuum-jetty-$VER-bin.zip.md5 apache-continuum-$VER-bin.zip.md5
-mv continuum-jetty-$VER-bin.zip.sha1 apache-continuum-$VER-bin.zip.sha1
-mv continuum-jetty-$VER-bin.zip.asc apache-continuum-$VER-bin.zip.asc
-
-mv continuum-webapp-$VER.war apache-continuum-$VER.war
-mv continuum-webapp-$VER.war.asc apache-continuum-$VER.war.asc
-mv continuum-webapp-$VER.war.md5 apache-continuum-$VER.war.md5
-mv continuum-webapp-$VER.war.sha1 apache-continuum-$VER.war.sha1
-
-echo 'GREAT :-) '
diff --git a/src/main/assembly/src.xml b/src/main/assembly/src.xml
deleted file mode 100644
index 11765e6..0000000
--- a/src/main/assembly/src.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" ?>
-
-<!--
-  ~ 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.
-  -->
-
-<assembly>
-  <id>src</id>
-  <formats>
-    <format>zip</format>
-  </formats>
-  <fileSets>
-    <fileSet>
-      <directory>.</directory>
-      <outputDirectory>/</outputDirectory>
-      <excludes>
-        <exclude>**/target/**</exclude>
-        <exclude>continuum-webapp/src/main/webapp/css/redback/**</exclude>
-        <exclude>continuum-webapp/src/main/webapp/images/redback/**</exclude>
-        <exclude>continuum-webapp/src/main/webapp/META-INF/**</exclude>
-        <exclude>continuum-webapp/src/main/webapp/template/**</exclude>
-        <exclude>continuum-webapp/src/main/webapp/WEB-INF/classes/**</exclude>
-        <exclude>continuum-webapp/src/main/webapp/WEB-INF/lib/**</exclude>
-        <exclude>continuum-webapp/src/main/webapp/WEB-INF/database/**</exclude>
-        <exclude>continuum-webapp/src/main/webapp/WEB-INF/logs/**</exclude>
-        <exclude>continuum-webapp/src/main/webapp/redback/**</exclude>
-        <exclude>continuum-webapp/src/main/webapp/WEB-INF/jsp/redback/**</exclude>
-        <exclude>continuum-webapp/src/main/webapp/WEB-INF/template/redback/**</exclude>
-        <exclude>continuum-webapp/src/main/webapp/WEB-INF/logs/**</exclude>
-        <exclude>continuum-webapp/src/main/webapp/WEB-INF/temp/**</exclude>
-      </excludes>
-    </fileSet>
-    <fileSet>
-      <directory>target/maven-shared-archive-resources/META-INF/</directory>
-      <outputDirectory>/</outputDirectory>
-      <includes>
-        <include>NOTICE</include>
-        <include>LICENSE</include>
-      </includes>
-    </fileSet>
-  </fileSets>
-</assembly>
-
diff --git a/src/site/apt/architecture.apt b/src/site/apt/architecture.apt
new file mode 100644
index 0000000..d44d05d
--- /dev/null
+++ b/src/site/apt/architecture.apt
@@ -0,0 +1,34 @@
+ ---
+Architecture
+ ---
+
+~~ 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.
+
+Continuum Architecture
+
+
+ There has been {{{http://www.nabble.com/separating-the-builder-code-from-the-UI-td16626111.html}some discussion}}
+ of moving the Continuum architecture from
+
+[./images/continuum-now.png]
+
+ to
+
+[./images/continuum-new.png]
+
+ .
diff --git a/src/site/apt/findbugs.apt b/src/site/apt/findbugs.apt
deleted file mode 100644
index 51280fe..0000000
--- a/src/site/apt/findbugs.apt
+++ /dev/null
@@ -1,33 +0,0 @@
- ---------
- FindBugs Bug Detector Reports
- ---------
-
-FindBugs Bug Detector Reports
-
-  Want to help find and fix bugs in Continuum?
-
-  A FindBugs report is available for each module in the Continuum build.
-  Visit the links below to view the reports.  For infomation on interpreting the results,
-  visit the {{{http://findbugs.sourceforge.net/}FindBugs project website}}.
-
-  You can also install FindBugs and launch the GUI with <<<findbugs -project [filename].fbp>>>.
-  FindBugs project files are currently available in the -core and -release modules
-  as well as at the top level for a consolidated view.  You must run 'mvn pacakge' prior
-  to launching the FindBugs GUI, so that the jar will be present in the target directory.
-
-+------+
-cd /path/to/continuum-all/continuum/continuum-core
-mvn package
-findbugs -project continuum-core.fbp
-+------+
-
-  (A future version of the FindBugs Maven plugin should have the ability
-  to launch the GUI from any module with <<<mvn findbugs:gui>>>.)
-
-* FindBugs Reports
-
- * {{{continuum-core/findbugs.html}Continuum Core}}
-
- * {{{continuum-release/findbugs.html}Continuum Release}}
-
- * ...
\ No newline at end of file
diff --git a/src/site/apt/index.apt b/src/site/apt/index.apt
new file mode 100644
index 0000000..529fa92
--- /dev/null
+++ b/src/site/apt/index.apt
@@ -0,0 +1,139 @@
+ ----
+ Welcome
+ ----
+
+~~ 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.
+
+Apache Continuum Developer Documentation
+
+  Welcome!  This site contains the developer documentation for Apache Continuum.  Here you will find Javadocs,
+  information about our unit and functional tests, and some requirements docs.
+
+   * {{{./architecture.html}Architecture}}
+
+   * {{{./requirements.html}Requirements}}
+
+   * {{{./apidocs/index.html}Javadocs}}
+
+   * {{{./xref/index.html}Source cross-reference}}
+
+* Modules
+
+  The following modules contain some reference documentation for their design and code.
+
+   * {{{./continuum-api/index.html}Continuum API}}
+
+   * {{{./continuum-base/continuum-configuration/index.html}Continuum Configuration Library}}
+
+   * {{{./continuum-base/continuum-scm/index.html}Continuum SCM Layer}}
+
+   * {{{./continuum-buildagent/index.html}Continuum Build Agent Modules}}
+
+     * {{{./continuum-buildagent/continuum-buildagent-api/index.html}Continuum Build Agent API}}
+
+     * {{{./continuum-buildagent/continuum-buildagent-core/index.html}Continuum Build Agent Core}}
+
+     * {{{./continuum-buildagent/continuum-buildagent-webdav/index.html}Continuum Build Agent WebDAV interface}}
+
+     * {{{./continuum-buildagent/continuum-buildagent-webdav/index.html}Continuum Build Agent WebDAV client}}
+
+     * {{{./continuum-buildagent/continuum-buildagent-webapp/index.html}Continuum Build Agent Web Application}}
+
+     * {{{./continuum-buildagent/continuum-buildagent-jetty/index.html}Continuum Build Agent Standalone distribution}}
+
+   * {{{./continuum-builder/index.html}Continuum Builder Abstraction}}
+
+   * {{{./continuum-commons/index.html}Continuum Common Library}}
+
+   * {{{./continuum-core/index.html}Continuum Core Library}}
+
+   * {{{./continuum-data-management/index.html}Continuum Data Management Modules}}
+
+     * {{{./continuum-data-management/data-management-api/index.html}Continuum Data Management API}}
+
+     * {{{./continuum-data-management/data-management-jdo/index.html}Continuum Data Management JDO Provider}}
+
+     * {{{./continuum-data-management/data-management-redback-jdo/index.html}Continuum Data Management JDO Provider for Redback}}
+
+     * {{{./continuum-data-management/continuum-legacy/index.html}Continuum Models for Legacy Upgrades}}
+
+     * {{{./continuum-data-management/redback-legacy/index.html}Continuum Models for Legacy Upgrades of Redback}}
+
+     * {{{./continuum-data-management/data-management-cli/index.html}Continuum Data Management CLI}}
+
+   * {{{./continuum-distributed/index.html}Continuum Distributed Build Modules}}
+
+     * {{{./continuum-distributed/continuum-distributed-commons/index.html}Continuum Distributed Builds Commons Library}}
+
+     * {{{./continuum-distributed/continuum-distributed-master/index.html}Continuum Distributed Builds Master Modules}}
+
+       * {{{./continuum-distributed/continuum-distributed-master/continuum-distributed-master-api/index.html}Continuum Distributed Builds Master API}}
+
+       * {{{./continuum-distributed/continuum-distributed-master/continuum-distributed-master-client/index.html}Continuum Distributed Builds Master Client Library}}
+
+       * {{{./continuum-distributed/continuum-distributed-master/continuum-distributed-master-server/index.html}Continuum Distributed Builds Master Server Library}}
+
+     * {{{./continuum-distributed/continuum-distributed-slave/index.html}Continuum Distributed Builds Slave Modules}}
+
+       * {{{./continuum-distributed/continuum-distributed-slave/continuum-distributed-slave-api/index.html}Continuum Distributed Builds Slave API}}
+
+       * {{{./continuum-distributed/continuum-distributed-slave/continuum-distributed-slave-client/index.html}Continuum Distributed Builds Slave Client Library}}
+
+       * {{{./continuum-distributed/continuum-distributed-slave/continuum-distributed-slave-server/index.html}Continuum Distributed Builds Slave Server Library}}
+
+   * {{{./continuum-model/index.html}Continuum Data Model}}
+
+   * {{{./continuum-notifiers/index.html}Continuum Notifier Modules}}
+
+     * {{{./continuum-notifiers/continuum-notifier-api/index.html}Continuum Notifier API}}
+
+     * {{{./continuum-notifiers/continuum-notifier-irc/index.html}Continuum Notifier for IRC}}
+
+     * {{{./continuum-notifiers/continuum-notifier-jabber/index.html}Continuum Notifier for Jabber}}
+
+     * {{{./continuum-notifiers/continuum-notifier-msn/index.html}Continuum Notifier for MSN}}
+
+     * {{{./continuum-notifiers/continuum-notifier-wagon/index.html}Continuum Notifier for Wagon}}
+
+   * {{{./continuum-purge/index.html}Continuum Purge library}}
+
+   * {{{./continuum-release/index.html}Continuum Release library}}
+
+   * {{{./continuum-reports/index.html}Continuum Reports library}}
+
+   * {{{./continuum-security/index.html}Continuum Security integration library}}
+
+   * {{{./continuum-store/index.html}Continuum Data Store library}}
+
+   * {{{./continuum-test/index.html}Continuum Testing Utility library}}
+
+   * {{{./continuum-xmlrpc/index.html}Continuum XMLRPC Modules}}
+
+     * {{{./continuum-xmlrpc/continuum-xmlrpc-api/index.html}Continuum XMLRPC API}}
+
+     * {{{./continuum-xmlrpc/continuum-xmlrpc-backup/index.html}Continuum XMLRPC-based Backup library}}
+
+     * {{{./continuum-xmlrpc/continuum-xmlrpc-server/index.html}Continuum XMLRPC Server library}}
+
+     * {{{./continuum-xmlrpc/continuum-xmlrpc-client/index.html}Continuum XMLRPC Client library}}
+
+   * {{{./continuum-webapp/index.html}Continuum Web Application}}
+
+   * {{{./continuum-jetty/index.html}Continuum Standalone Distribution}}
+
+   * {{{./continuum-webapp-test/index.html}Functional Tests}}
diff --git a/src/site/apt/requirements.apt b/src/site/apt/requirements.apt
new file mode 100644
index 0000000..4d18e81
--- /dev/null
+++ b/src/site/apt/requirements.apt
@@ -0,0 +1,34 @@
+ ----
+ Requirements
+ ----
+
+~~ 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.
+
+Requirements
+
+ The Continuum project does not have formal requirements docs, but there are some general requirements we adhere to.
+
+ * Anything that goes in the database must have a way to come out.  For example, we add build results to the database,
+ and provide a way to delete them through the Web UI and the XML-RPC interface, as well as deleting them automatically
+ when the project they belong to is deleted.
+
+ []
+
+ In addition, we have the following requirements defined:
+
+ * {{{./credentials.html}Credentials Handling}}
diff --git a/src/site/resources/images/continuum-new.png b/src/site/resources/images/continuum-new.png
new file mode 100644
index 0000000..1e9e699
--- /dev/null
+++ b/src/site/resources/images/continuum-new.png
Binary files differ
diff --git a/src/site/resources/images/continuum-now.png b/src/site/resources/images/continuum-now.png
new file mode 100644
index 0000000..2682215
--- /dev/null
+++ b/src/site/resources/images/continuum-now.png
Binary files differ
diff --git a/src/site/resources/images/logos/maven-feather.png b/src/site/resources/images/logos/maven-feather.png
new file mode 100644
index 0000000..b5ada83
--- /dev/null
+++ b/src/site/resources/images/logos/maven-feather.png
Binary files differ
diff --git a/src/site/site.xml b/src/site/site.xml
new file mode 100644
index 0000000..9170892
--- /dev/null
+++ b/src/site/site.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+  ~ 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.
+  -->
+
+<project name="Apache Continuum">
+  <skin>
+    <groupId>org.apache.continuum</groupId>
+    <artifactId>continuum-skin</artifactId>
+    <version>1.0</version>
+  </skin>
+  <body>
+    <breadcrumbs>
+      <item name="Continuum" href="http://continuum.apache.org/" />
+      <item name="Reference Library" href="/"/>
+    </breadcrumbs>
+
+    <menu ref="modules" />
+  </body>
+</project>
diff --git a/src/site/xdoc/credentials.xml b/src/site/xdoc/credentials.xml
new file mode 100644
index 0000000..4050242
--- /dev/null
+++ b/src/site/xdoc/credentials.xml
@@ -0,0 +1,253 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<document xmlns="http://maven.apache.org/XDOC/2.0"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
+
+  <properties>
+    <title>Credentials Handling</title>
+  </properties>
+
+  <body>
+
+    <section name="Credentials Handling">
+
+      <p>This document describes how Continuum should handle credentials for pom retrieval and scm access.</p>
+
+      <table>
+        <tr>
+          <th>Were credentials provided when the project was added?</th>
+          <th>Was 'Use cached credentials if available' checked when the project was added?</th>
+          <th>Are there Subversion credentials cached for the user running Continuum?</th>
+          <th>Were credentials provided during release prepare?</th>
+          <th></th>
+          <th>Initial project add</th>
+          <th>Scheduled or Forced Build</th>
+          <th>Release</th>
+        </tr>
+        <tr>
+          <td>Y</td>
+          <td>Y</td>
+          <td>Y</td>
+          <td>Y</td>
+          <td></td>
+          <td>use the provided credentials for the HTTP GET to
+            retrieve the POM. Rely on cached credentials for the initial checkout [2].
+            Do not store the credentials in the database because the checkbox says we
+            should rely on cached credentials.
+          </td>
+
+          <td>Rely on the cached credentials [2]</td>
+          <td>use the credentials provided during release prepare.
+            Avoid caching these credentials. [1]
+          </td>
+        </tr>
+        <tr>
+          <td>Y</td>
+          <td>Y</td>
+          <td>Y</td>
+          <td>N</td>
+          <td></td>
+          <td>&quot;</td>
+          <td>&quot;</td>
+          <td>Rely on the cached credentials [2]</td>
+        </tr>
+        <tr>
+          <td>Y</td>
+          <td>Y</td>
+          <td>N</td>
+          <td>Y</td>
+          <td></td>
+          <td>&quot;</td>
+          <td>Rely on the cached credentials [2]. Will probably fail because they are missing.</td>
+          <td>use the credentials provided during release prepare. Avoid caching these credentials. [1]</td>
+        </tr>
+        <tr>
+          <td>Y</td>
+          <td>Y</td>
+          <td>N</td>
+          <td>N</td>
+          <td></td>
+          <td>&quot;</td>
+          <td>&quot;</td>
+          <td>Rely on the cached credentials [2].</td>
+        </tr>
+        <tr>
+          <td>Y</td>
+          <td>N</td>
+          <td>Y</td>
+          <td>Y</td>
+          <td></td>
+          <td>use the provided credentials for the HTTP GET to
+            retrieve the pom and for the initial checkout. Store the credentials in the
+            database for later use.
+          </td>
+          <td>Use the credentials from the database [3]</td>
+          <td>use the credentials provided during release prepare.
+            Avoid caching these credentials. [1]
+          </td>
+        </tr>
+        <tr>
+          <td>Y</td>
+          <td>N</td>
+          <td>Y</td>
+          <td>N</td>
+          <td></td>
+          <td>&quot;</td>
+          <td>&quot;</td>
+          <td>Rely on the cached credentials [2].</td>
+        </tr>
+        <tr>
+          <td>Y</td>
+          <td>N</td>
+          <td>N</td>
+
+          <td>Y</td>
+          <td></td>
+          <td>&quot;</td>
+          <td>&quot;</td>
+          <td>use the credentials provided during release prepare.
+            Avoid caching these credentials. [1]
+          </td>
+        </tr>
+        <tr>
+          <td>Y</td>
+          <td>N</td>
+          <td>N</td>
+          <td>N</td>
+          <td></td>
+          <td>&quot;</td>
+          <td>&quot;</td>
+          <td>Rely on unauthenticated access to the scm repo</td>
+        </tr>
+        <tr>
+          <td>N</td>
+          <td>Y</td>
+          <td>Y</td>
+          <td>Y</td>
+          <td></td>
+          <td>GET the pom and do the initial checkout with no
+            credentials
+          </td>
+          <td>Rely on cached credentials or unauthenticated access
+            to the scm repo [2].
+          </td>
+          <td>use the credentials provided during release prepare.
+            Avoid caching these credentials. [1]
+          </td>
+        </tr>
+        <tr>
+          <td>N</td>
+          <td>Y</td>
+          <td>Y</td>
+          <td>N</td>
+          <td></td>
+          <td>&quot;</td>
+          <td>&quot;</td>
+          <td>Rely on the cached credentials [2].</td>
+        </tr>
+        <tr>
+          <td>N</td>
+          <td>Y</td>
+          <td>N</td>
+          <td>Y</td>
+          <td></td>
+          <td>&quot;</td>
+          <td>&quot;</td>
+          <td>use the credentials provided during release prepare.
+            Avoid caching these credentials. [1]
+          </td>
+        </tr>
+        <tr>
+          <td>N</td>
+          <td>Y</td>
+          <td>N</td>
+          <td>N</td>
+          <td></td>
+          <td>&quot;</td>
+          <td>&quot;</td>
+          <td>rely on cached credentials or unauthenticated access to scm [2].</td>
+        </tr>
+        <tr>
+          <td>N</td>
+          <td>N</td>
+          <td>Y</td>
+          <td>Y</td>
+          <td></td>
+          <td>&quot;</td>
+          <td>&quot;</td>
+          <td>use the credentials provided during release prepare. Avoid caching these credentials. [1]</td>
+        </tr>
+        <tr>
+          <td>N</td>
+          <td>N</td>
+          <td>Y</td>
+          <td>N</td>
+          <td></td>
+          <td>&quot;</td>
+          <td>&quot;</td>
+          <td>Rely on the cached credentials [2]</td>
+        </tr>
+        <tr>
+          <td>N</td>
+          <td>N</td>
+          <td>N</td>
+          <td>Y</td>
+          <td></td>
+          <td>&quot;</td>
+          <td>&quot;</td>
+          <td>use the credentials provided during release prepare.
+            Avoid caching these credentials. [1]
+          </td>
+        </tr>
+        <tr>
+          <td>N</td>
+          <td>N</td>
+          <td>N</td>
+          <td>N</td>
+          <td></td>
+          <td>&quot;</td>
+          <td>Rely on unauthenticated access to the scm repo</td>
+          <td>Rely on unauthenticated access to the scm repo</td>
+        </tr>
+      </table>
+
+      <p>A " (double quote) in a table cell means "same as above".</p>
+
+      <p>Implementation Notes for Subversion:
+        <ul>
+          <li>[1] Use --no-cache-credentials on the svn command</li>
+          <li>[2] Do not provide --username and --password on the svn command line</li>
+          <li>[3] Provide --username and --password on the svn command line</li>
+        </ul>
+      </p>
+    </section>
+
+    <section name="Testing">
+      <p>Currently the tests for these features tend to be manual since they require access to a secured website
+        and/or scm repository. This test is currently disabled: AbstractContinuumProjectBuilderTest.
+      </p>
+
+    </section>
+
+  </body>
+
+</document>
\ No newline at end of file