added support for build environments when releasing

git-svn-id: https://svn.apache.org/repos/asf/continuum/branches/CONTINUUM-1572@697137 13f79535-47bb-0310-9956-ffa450edef68
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 0496de3..70ec7f0 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
@@ -21,6 +21,7 @@
 
 import org.apache.continuum.model.repository.LocalRepository;
 import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.system.Profile;
 
 import java.io.File;
 import java.util.Map;
@@ -50,6 +51,22 @@
     String prepare( Project project, Properties releaseProperties, Map releaseVersions, Map developmentVersions,
                     ContinuumReleaseManagerListener listener )
         throws ContinuumReleaseException;
+    
+    /**
+     * Prepare a project for release
+     *
+     * @param project
+     * @param releaseProperties
+     * @param releaseVersions
+     * @param developmentVersions
+     * @param listener
+     * @param profile
+     * @return
+     * @throws ContinuumReleaseException
+     */
+    String prepare( Project project, Properties releaseProperties, Map releaseVersions, Map developmentVersions,
+                    ContinuumReleaseManagerListener listener, Profile profile )
+        throws ContinuumReleaseException;
 
     /**
      * Perform a release based on a given releaseId
@@ -99,4 +116,6 @@
     void perform( String releaseId, File buildDirectory, String goals, boolean useReleaseProfile,
                   ContinuumReleaseManagerListener listener, LocalRepository repository )
         throws ContinuumReleaseException;
+    
+    Map<String, String> getEnvironments( Profile profile );
 }
diff --git a/continuum-commons/pom.xml b/continuum-commons/pom.xml
index 4cd9bd3..78fb9ec 100644
--- a/continuum-commons/pom.xml
+++ b/continuum-commons/pom.xml
@@ -43,6 +43,17 @@
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-spring</artifactId>
     </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>
     <!-- === Testing Dependencies === -->
     <dependency>
       <groupId>hsqldb</groupId>
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/utils/shell/DefaultShellCommandHelper.java b/continuum-commons/src/main/java/org/apache/continuum/utils/shell/DefaultShellCommandHelper.java
similarity index 66%
rename from continuum-core/src/main/java/org/apache/maven/continuum/utils/shell/DefaultShellCommandHelper.java
rename to continuum-commons/src/main/java/org/apache/continuum/utils/shell/DefaultShellCommandHelper.java
index be91297..b7d7ce6 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/utils/shell/DefaultShellCommandHelper.java
+++ b/continuum-commons/src/main/java/org/apache/continuum/utils/shell/DefaultShellCommandHelper.java
@@ -1,4 +1,4 @@
-package org.apache.maven.continuum.utils.shell;
+package org.apache.continuum.utils.shell;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -19,7 +19,12 @@
  * 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.logging.AbstractLogEnabled;
+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;
@@ -35,7 +40,7 @@
 /**
  * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
  * @version $Id$
- * @plexus.component role="org.apache.maven.continuum.utils.shell.ShellCommandHelper"
+ * @plexus.component role="org.apache.continuum.utils.shell.ShellCommandHelper"
  * role-hint="default"
  */
 public class DefaultShellCommandHelper
@@ -150,4 +155,68 @@
     {
         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() );
+    		getLogger().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-core/src/main/java/org/apache/maven/continuum/utils/shell/ExecutionResult.java b/continuum-commons/src/main/java/org/apache/continuum/utils/shell/ExecutionResult.java
similarity index 95%
rename from continuum-core/src/main/java/org/apache/maven/continuum/utils/shell/ExecutionResult.java
rename to continuum-commons/src/main/java/org/apache/continuum/utils/shell/ExecutionResult.java
index 48c8a06..72c99cd 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/utils/shell/ExecutionResult.java
+++ b/continuum-commons/src/main/java/org/apache/continuum/utils/shell/ExecutionResult.java
@@ -1,4 +1,4 @@
-package org.apache.maven.continuum.utils.shell;
+package org.apache.continuum.utils.shell;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/utils/shell/ShellCommandHelper.java b/continuum-commons/src/main/java/org/apache/continuum/utils/shell/ShellCommandHelper.java
similarity index 70%
rename from continuum-core/src/main/java/org/apache/maven/continuum/utils/shell/ShellCommandHelper.java
rename to continuum-commons/src/main/java/org/apache/continuum/utils/shell/ShellCommandHelper.java
index 28878a4..a89752b 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/utils/shell/ShellCommandHelper.java
+++ b/continuum-commons/src/main/java/org/apache/continuum/utils/shell/ShellCommandHelper.java
@@ -1,4 +1,4 @@
-package org.apache.maven.continuum.utils.shell;
+package org.apache.continuum.utils.shell;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -22,9 +22,12 @@
 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$
+ * @version $Id: ShellCommandHelper.java 548732 2007-06-19 14:04:13Z evenisse $
  */
 public interface ShellCommandHelper
 {
@@ -41,4 +44,12 @@
     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-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 2cf8550..d6b230fa 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
@@ -19,6 +19,8 @@
  * under the License.
  */
 
+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.installation.InstallationService;
 import org.apache.maven.continuum.model.project.BuildDefinition;
@@ -28,8 +30,6 @@
 import org.apache.maven.continuum.model.system.Profile;
 import org.apache.maven.continuum.project.ContinuumProjectState;
 import org.apache.maven.continuum.utils.WorkingDirectoryService;
-import org.apache.maven.continuum.utils.shell.ExecutionResult;
-import org.apache.maven.continuum.utils.shell.ShellCommandHelper;
 import org.codehaus.plexus.commandline.ExecutableResolver;
 import org.codehaus.plexus.logging.AbstractLogEnabled;
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
diff --git a/continuum-core/src/main/java/org/apache/maven/continuum/profile/DefaultProfileService.java b/continuum-core/src/main/java/org/apache/maven/continuum/profile/DefaultProfileService.java
index 097bb3b..6e4f3d9 100644
--- a/continuum-core/src/main/java/org/apache/maven/continuum/profile/DefaultProfileService.java
+++ b/continuum-core/src/main/java/org/apache/maven/continuum/profile/DefaultProfileService.java
@@ -131,7 +131,14 @@
     public void deleteProfile( int profileId )
         throws ProfileException
     {
-        profileDao.removeProfile( getProfile( profileId ) );
+        try
+        {
+            profileDao.removeProfile( getProfile( profileId ) );
+        }
+        catch ( Exception e )
+        {
+            throw new ProfileException( "Cannot remove the profile", e );
+        }
     }
 
     /**
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 4b8a9a1..265085a 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
@@ -25,14 +25,14 @@
 
 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;
 import org.apache.maven.continuum.configuration.DefaultConfigurationService;
 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.utils.ChrootJailWorkingDirectoryService;
-import org.apache.maven.continuum.utils.shell.ExecutionResult;
-import org.apache.maven.continuum.utils.shell.ShellCommandHelper;
 import org.codehaus.plexus.logging.Logger;
 import org.codehaus.plexus.logging.console.ConsoleLogger;
 import org.jmock.Expectations;
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
new file mode 100644
index 0000000..26b3c78
--- /dev/null
+++ b/continuum-release/src/main/java/org/apache/continuum/release/config/ContinuumPropertiesReleaseDescriptorStore.java
@@ -0,0 +1,348 @@
+package org.apache.continuum.release.config;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES 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.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+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
+{
+    public ReleaseDescriptor read( ReleaseDescriptor mergeDescriptor, File file )
+        throws ReleaseDescriptorStoreException
+    {
+        Properties properties = new Properties();
+    
+        InputStream inStream = null;
+        try
+        {
+            inStream = new FileInputStream( file );
+    
+            properties.load( inStream );
+        }
+        catch ( FileNotFoundException e )
+        {
+            getLogger().debug( file.getName() + " not found - using empty properties" );
+        }
+        catch ( IOException e )
+        {
+            throw new ReleaseDescriptorStoreException(
+                "Error reading properties file '" + file.getName() + "': " + e.getMessage(), e );
+        }
+        finally
+        {
+            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" ) );
+        releaseDescriptor.setScmPrivateKey( properties.getProperty( "scm.privateKey" ) );
+        releaseDescriptor.setScmPrivateKeyPassPhrase( properties.getProperty( "scm.passphrase" ) );
+        releaseDescriptor.setScmTagBase( properties.getProperty( "scm.tagBase" ) );
+        releaseDescriptor.setScmReleaseLabel( properties.getProperty( "scm.tag" ) );
+        releaseDescriptor.setScmCommentPrefix( properties.getProperty( "scm.commentPrefix" ) );
+        releaseDescriptor.setAdditionalArguments( properties.getProperty( "exec.additionalArguments" ) );
+        releaseDescriptor.setPomFileName( properties.getProperty( "exec.pomFileName" ) );
+        releaseDescriptor.setPreparationGoals( properties.getProperty( "preparationGoals" ) );
+    
+        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(); )
+        {
+            String property = (String) i.next();
+            if ( property.startsWith( "project.rel." ) )
+            {
+                releaseDescriptor.mapReleaseVersion( property.substring( "project.rel.".length() ),
+                                                     properties.getProperty( property ) );
+            }
+            else if ( property.startsWith( "project.dev." ) )
+            {
+                releaseDescriptor.mapDevelopmentVersion( property.substring( "project.dev.".length() ),
+                                                         properties.getProperty( property ) );
+            }
+            else if ( property.startsWith( "project.scm." ) )
+            {
+                int index = property.lastIndexOf( '.' );
+                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 )
+                        {
+                            releaseDescriptor.mapOriginalScmInfo( key, null );
+                        }
+                        else
+                        {
+                            Scm scm = new Scm();
+                            scm.setConnection( properties.getProperty( "project.scm." + key + ".connection" ) );
+                            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 );
+                        }
+                    }
+                }
+            }
+            else if ( property.startsWith( "build.env." ) )
+            {
+                releaseDescriptor.mapEnvironments( property.substring( "build.env.".length() ),
+                                                   properties.getProperty( property ) );
+            }
+        }
+    
+        if ( mergeDescriptor != null )
+        {
+            releaseDescriptor = (ContinuumReleaseDescriptor) ReleaseUtils.merge( releaseDescriptor, mergeDescriptor );
+            releaseDescriptor.setEnvironments( ( (ContinuumReleaseDescriptor)mergeDescriptor ).getEnvironments() );
+        }
+    
+        return releaseDescriptor;
+    }
+
+    public void write( ReleaseDescriptor configFile, File file )
+        throws ReleaseDescriptorStoreException
+    {
+        ContinuumReleaseDescriptor config = (ContinuumReleaseDescriptor) configFile;
+        Properties properties = new Properties();
+        properties.setProperty( "completedPhase", config.getCompletedPhase() );
+        properties.setProperty( "scm.url", config.getScmSourceUrl() );
+        if ( config.getScmUsername() != null )
+        {
+            properties.setProperty( "scm.username", config.getScmUsername() );
+        }
+        if ( config.getScmPassword() != null )
+        {
+            properties.setProperty( "scm.password", config.getScmPassword() );
+        }
+        if ( config.getScmPrivateKey() != null )
+        {
+            properties.setProperty( "scm.privateKey", config.getScmPrivateKey() );
+        }
+        if ( config.getScmPrivateKeyPassPhrase() != null )
+        {
+            properties.setProperty( "scm.passphrase", config.getScmPrivateKeyPassPhrase() );
+        }
+        if ( config.getScmTagBase() != null )
+        {
+            properties.setProperty( "scm.tagBase", config.getScmTagBase() );
+        }
+        if ( config.getScmReleaseLabel() != null )
+        {
+            properties.setProperty( "scm.tag", config.getScmReleaseLabel() );
+        }
+        if ( config.getScmCommentPrefix() != null )
+        {
+            properties.setProperty( "scm.commentPrefix", config.getScmCommentPrefix() );
+        }
+        if ( config.getAdditionalArguments() != null )
+        {
+            properties.setProperty( "exec.additionalArguments", config.getAdditionalArguments() );
+        }
+        if ( config.getPomFileName() != null )
+        {
+            properties.setProperty( "exec.pomFileName", config.getPomFileName() );
+        }
+        if ( config.getPreparationGoals() != null )
+        {
+            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(); )
+        {
+            Map.Entry entry = (Map.Entry) i.next();
+            properties.setProperty( "project.rel." + entry.getKey(), (String) entry.getValue() );
+        }
+    
+        for ( Iterator i = config.getDevelopmentVersions().entrySet().iterator(); i.hasNext(); )
+        {
+            Map.Entry entry = (Map.Entry) i.next();
+            properties.setProperty( "project.dev." + entry.getKey(), (String) entry.getValue() );
+        }
+    
+        for ( Iterator i = config.getOriginalScmInfo().entrySet().iterator(); i.hasNext(); )
+        {
+            Map.Entry entry = (Map.Entry) i.next();
+            Scm scm = (Scm) entry.getValue();
+            String prefix = "project.scm." + entry.getKey();
+            if ( scm != null )
+            {
+                if ( scm.getConnection() != null )
+                {
+                    properties.setProperty( prefix + ".connection", scm.getConnection() );
+                }
+                if ( scm.getDeveloperConnection() != null )
+                {
+                    properties.setProperty( prefix + ".developerConnection", scm.getDeveloperConnection() );
+                }
+                if ( scm.getUrl() != null )
+                {
+                    properties.setProperty( prefix + ".url", scm.getUrl() );
+                }
+                if ( scm.getTag() != null )
+                {
+                    properties.setProperty( prefix + ".tag", scm.getTag() );
+                }
+            }
+            else
+            {
+                properties.setProperty( prefix + ".empty", "true" );
+            }
+        }
+
+        for ( Iterator i = config.getEnvironments().entrySet().iterator(); i.hasNext(); )
+        {
+            Map.Entry entry = (Map.Entry) i.next();
+            properties.setProperty( "build.env." + entry.getKey(), (String) entry.getValue() );
+        }
+    
+        if ( ( config.getResolvedSnapshotDependencies() != null ) &&
+            ( config.getResolvedSnapshotDependencies().size() > 0 ) )
+        {
+            processResolvedDependencies( properties, config.getResolvedSnapshotDependencies() );
+        }
+    
+        OutputStream outStream = null;
+        //noinspection OverlyBroadCatchBlock
+        try
+        {
+            outStream = new FileOutputStream( file );
+    
+            properties.store( outStream, "release configuration" );
+        }
+        catch ( IOException e )
+        {
+            throw new ReleaseDescriptorStoreException(
+                "Error writing properties file '" + file.getName() + "': " + e.getMessage(), e );
+        }
+        finally
+        {
+            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 ) );
+        }
+    }
+    
+    private static File getDefaultReleasePropertiesFile( ReleaseDescriptor mergeDescriptor )
+    {
+        return new File( mergeDescriptor.getWorkingDirectory(), "release.properties" );
+    }
+    
+    private void loadResolvedDependencies( Properties prop, ReleaseDescriptor descriptor )
+    {
+        Map resolvedDependencies = new HashMap();
+    
+        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;
+                String artifactVersionlessKey;
+                int startIndex;
+                int endIndex;
+                String versionType;
+    
+                versionMap = new HashMap();
+                startIndex = propertyName.lastIndexOf( "dependency." );
+    
+                if ( propertyName.indexOf( ".development" ) != -1 )
+                {
+                    endIndex = propertyName.indexOf( ".development" );
+                    versionType = ReleaseDescriptor.DEVELOPMENT_KEY;
+                }
+                else
+                {
+                    endIndex = propertyName.indexOf( ".release" );
+                    versionType = ReleaseDescriptor.RELEASE_KEY;
+                }
+    
+                artifactVersionlessKey = propertyName.substring( startIndex, endIndex );
+    
+                if ( resolvedDependencies.containsKey( artifactVersionlessKey ) )
+                {
+                    versionMap = (Map) resolvedDependencies.get( artifactVersionlessKey );
+                }
+                else
+                {
+                    versionMap = new HashMap();
+                    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
new file mode 100644
index 0000000..7047229
--- /dev/null
+++ b/continuum-release/src/main/java/org/apache/continuum/release/config/ContinuumReleaseDescriptor.java
@@ -0,0 +1,68 @@
+package org.apache.continuum.release.config;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES 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.shared.release.config.ReleaseDescriptor;
+
+/**
+ * @author <a href="mailto:ctan@apache.org">Maria Catherine Tan</a>
+ */
+public class ContinuumReleaseDescriptor
+    extends ReleaseDescriptor
+{
+    private Map<String, String> environments;
+
+    public void addEnvironment( String name, String value )
+    {
+        getEnvironments().put( name, value );
+    }
+
+    public Map<String, String> getEnvironments()
+    {
+        if ( environments == null )
+        {
+            environments = new HashMap<String, String>();
+        }
+
+        return environments;
+    }
+
+    public void mapEnvironments( String name, String value)
+    {
+        if ( environments == null )
+        {
+            environments = new HashMap<String, String>();
+        }
+        else
+        {
+            assert !environments.containsKey( name );
+        }
+
+        environments.put( name, value );
+    }
+
+    public void setEnvironments( Map<String, String> environments )
+    {
+        this.environments = environments;
+    }
+}
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
new file mode 100644
index 0000000..c3f980d
--- /dev/null
+++ b/continuum-release/src/main/java/org/apache/continuum/release/phase/AbstractContinuumRunGoalsPhase.java
@@ -0,0 +1,77 @@
+package org.apache.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 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.shared.release.ReleaseExecutionException;
+import org.apache.maven.shared.release.ReleaseResult;
+import org.apache.maven.shared.release.config.ReleaseDescriptor;
+import org.apache.maven.shared.release.phase.AbstractRunGoalsPhase;
+import org.codehaus.plexus.util.StringUtils;
+
+/**
+ * @author <a href="mailto:ctan@apache.org">Maria Catherine Tan</a>
+ */
+public abstract class AbstractContinuumRunGoalsPhase
+    extends AbstractRunGoalsPhase
+{
+    /**
+     * @plexus.requirement
+     */
+    private ShellCommandHelper shellCommandHelper;
+
+    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;
+                
+                if ( releaseDescriptor instanceof ContinuumReleaseDescriptor )
+                {
+                    environments = ( (ContinuumReleaseDescriptor) releaseDescriptor ).getEnvironments();
+                }
+                
+                shellCommandHelper.executeGoals( determineWorkingDirectory( workingDirectory,
+                                                                            releaseDescriptor.getScmRelativePathProjectDirectory() ),
+                                                 goals, releaseDescriptor.isInteractive(), additionalArguments, result, 
+                                                 environments );
+            }
+        }
+        catch ( Exception e )
+        {
+            throw new ReleaseExecutionException( e.getMessage(), e );
+        }
+
+        result.setResultCode( ReleaseResult.SUCCESS );
+
+        return result;
+    }
+}
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
new file mode 100644
index 0000000..f1c9dd3
--- /dev/null
+++ b/continuum-release/src/main/java/org/apache/continuum/release/phase/RunPerformGoalsPhase.java
@@ -0,0 +1,76 @@
+package org.apache.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 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.codehaus.plexus.util.StringUtils;
+
+/**
+ * Run Release Perform Goals
+ * @plexus.component role="org.apache.maven.shared.release.phase.ReleasePhase" role-hint="run-release-perform-goals"
+ */
+public class RunPerformGoalsPhase
+    extends AbstractContinuumRunGoalsPhase
+{
+    @Override
+    protected String getGoals( ReleaseDescriptor releaseDescriptor )
+    {
+        return releaseDescriptor.getPerformGoals();
+    }
+
+    public ReleaseResult execute( ReleaseDescriptor releaseDescriptor, Settings settings, List reactorProjects )
+        throws ReleaseExecutionException, ReleaseFailureException
+    {
+        String additionalArguments = releaseDescriptor.getAdditionalArguments();
+
+        if ( releaseDescriptor.isUseReleaseProfile() )
+        {
+            if ( !StringUtils.isEmpty( additionalArguments ) )
+            {
+                additionalArguments = additionalArguments + " -DperformRelease=true";
+            }
+            else
+            {
+                additionalArguments = "-DperformRelease=true";
+            }
+        }
+
+        return execute( releaseDescriptor, new File( releaseDescriptor.getCheckoutDirectory() ), additionalArguments );
+    }
+
+    public ReleaseResult simulate( ReleaseDescriptor releaseDescriptor, Settings settings, List reactorProjects )
+        throws ReleaseExecutionException, ReleaseFailureException
+    {
+        ReleaseResult result = new ReleaseResult();
+
+        logInfo( result, "Executing perform goals" );
+
+        execute( releaseDescriptor, settings, reactorProjects );
+
+        return result;
+    }
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..9f00bcc
--- /dev/null
+++ b/continuum-release/src/main/java/org/apache/continuum/release/phase/RunPrepareGoalsPhase.java
@@ -0,0 +1,63 @@
+package org.apache.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 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;
+
+/**
+ * Run Release Preparation Goals
+ * @plexus.component role="org.apache.maven.shared.release.phase.ReleasePhase" role-hint="run-release-prepare-goals"
+ */
+public class RunPrepareGoalsPhase
+    extends AbstractContinuumRunGoalsPhase
+{
+    @Override
+    protected String getGoals( ReleaseDescriptor releaseDescriptor )
+    {
+        return releaseDescriptor.getPreparationGoals();
+    }
+
+    public ReleaseResult execute( ReleaseDescriptor releaseDescriptor, Settings settings, List reactorProjects )
+        throws ReleaseExecutionException, ReleaseFailureException
+    {
+        return execute( releaseDescriptor, new File( releaseDescriptor.getWorkingDirectory() ), 
+                        releaseDescriptor.getAdditionalArguments() );
+    }
+
+    public ReleaseResult simulate( ReleaseDescriptor releaseDescriptor, Settings settings, List reactorProjects )
+        throws ReleaseExecutionException, ReleaseFailureException
+    {
+        ReleaseResult result = new ReleaseResult();
+
+        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 );
+
+        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 0808507..0198c2d 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,7 +20,11 @@
  */
 
 import org.apache.continuum.model.repository.LocalRepository;
+import org.apache.continuum.release.config.ContinuumReleaseDescriptor;
+import org.apache.maven.continuum.installation.InstallationService;
 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;
@@ -32,9 +36,13 @@
 import org.codehaus.plexus.taskqueue.Task;
 import org.codehaus.plexus.taskqueue.TaskQueue;
 import org.codehaus.plexus.taskqueue.TaskQueueException;
+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.Map;
 import java.util.Properties;
 
@@ -69,6 +77,11 @@
      * @plexus.requirement
      */
     private WorkingDirectoryService workingDirectoryService;
+
+    /**
+     * @plexus.requirement
+     */
+    private InstallationService installationService;
     
     private Map listeners;
 
@@ -90,16 +103,23 @@
                            ContinuumReleaseManagerListener listener )
         throws ContinuumReleaseException
     {
+        return prepare( project, releaseProperties, relVersions, devVersions, listener, null );
+    }
+
+    public String prepare( Project project, Properties releaseProperties, Map relVersions, Map devVersions,
+                           ContinuumReleaseManagerListener listener, Profile profile )
+        throws ContinuumReleaseException
+    {
         String releaseId = project.getGroupId() + ":" + project.getArtifactId();
 
-        ReleaseDescriptor descriptor = getReleaseDescriptor( project, releaseProperties, relVersions, devVersions );
+        ReleaseDescriptor descriptor = getReleaseDescriptor( project, releaseProperties, relVersions, devVersions, profile );
 
         getListeners().put( releaseId, listener );
 
         try
         {
             prepareReleaseQueue.put(
-                new PrepareReleaseProjectTask( releaseId, descriptor, (ReleaseManagerListener) listener ) );
+                new PrepareReleaseProjectTask( releaseId, descriptor, (ReleaseManagerListener) listener, profile ) );
 
         }
         catch ( TaskQueueException e )
@@ -199,10 +219,43 @@
         return releaseResults;
     }
 
-    private ReleaseDescriptor getReleaseDescriptor( Project project, Properties releaseProperties, Map relVersions,
-                                                    Map devVersions )
+    public Map<String, String> getEnvironments( Profile profile )
     {
-        ReleaseDescriptor descriptor = new ReleaseDescriptor();
+        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 )
+    {
+        ContinuumReleaseDescriptor descriptor = new ContinuumReleaseDescriptor();
         String workingDirectory = workingDirectoryService.getWorkingDirectory( project ).getPath(); 
 
         //release properties from the project
@@ -235,7 +288,10 @@
 
         //forced properties
         descriptor.setInteractive( false );
-
+        
+        //set environments
+        descriptor.setEnvironments( getEnvironments( profile ) );
+        
         return descriptor;
     }
 
@@ -266,4 +322,14 @@
 
         return listeners;
     }
+
+    private String getJavaHomeValue( Profile profile )
+    {
+        Installation jdk = profile.getJdk();
+        if ( jdk == null )
+        {
+            return null;
+        }
+        return jdk.getVarValue();
+    }
 }
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 20c5e02..63d74d0 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,6 +19,7 @@
  * 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;
@@ -37,11 +38,15 @@
 
     private long maxExecutionTime;
 
-    public AbstractReleaseProjectTask( String releaseId, ReleaseDescriptor descriptor, ReleaseManagerListener listener )
+    private Profile profile;
+
+    public AbstractReleaseProjectTask( String releaseId, ReleaseDescriptor descriptor, ReleaseManagerListener listener,
+                                       Profile profile )
     {
         this.releaseId = releaseId;
         this.descriptor = descriptor;
         this.listener = listener;
+        this.profile = profile;
     }
 
     public ReleaseDescriptor getDescriptor()
@@ -83,4 +88,14 @@
     {
         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 a3f7692..af56b2e 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,6 +20,7 @@
  */
 
 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;
 
@@ -42,13 +43,20 @@
     public PerformReleaseProjectTask( String releaseId, ReleaseDescriptor descriptor, File buildDirectory, String goals,
                                       boolean useReleaseProfile, ReleaseManagerListener listener )
     {
-        this( releaseId, descriptor, buildDirectory, goals, useReleaseProfile, listener, null );
+        this( releaseId, descriptor, buildDirectory, goals, useReleaseProfile, listener, null, null );
     }
 
     public PerformReleaseProjectTask( String releaseId, ReleaseDescriptor descriptor, File buildDirectory, String goals,
                                       boolean useReleaseProfile, ReleaseManagerListener listener, LocalRepository repository )
     {
-        super( releaseId, descriptor, listener );
+        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 );
         setBuildDirectory( buildDirectory );
         setGoals( goals );
         setUseReleaseProfile( useReleaseProfile );
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 245ece7..c1ac405 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,6 +19,7 @@
  * 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;
 
@@ -30,6 +31,11 @@
 {
     public PrepareReleaseProjectTask( String releaseId, ReleaseDescriptor descriptor, ReleaseManagerListener listener )
     {
-        super( releaseId, descriptor, listener );
+        this( releaseId, descriptor, listener, null );
+    }
+    
+    public PrepareReleaseProjectTask( String releaseId, ReleaseDescriptor descriptor, ReleaseManagerListener listener, Profile profile )
+    {
+        super( releaseId, descriptor, listener, profile );
     }
 }
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 70e55b7..61ae13e 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,5 +1,6 @@
 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;
 
@@ -30,6 +31,11 @@
 {
     public RollbackReleaseProjectTask( String releaseId, ReleaseDescriptor descriptor, ReleaseManagerListener listener )
     {
-        super( releaseId, descriptor, listener );
+        this( releaseId, descriptor, listener, null );
+    }
+    
+    public RollbackReleaseProjectTask( String releaseId, ReleaseDescriptor descriptor, ReleaseManagerListener listener, Profile profile )
+    {
+        super( releaseId, descriptor, listener, profile );
     }
 }
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 bb26304..7ab42ad 100644
--- a/continuum-release/src/main/resources/META-INF/plexus/components.xml
+++ b/continuum-release/src/main/resources/META-INF/plexus/components.xml
@@ -240,7 +240,7 @@
         </requirement>
         <requirement>
           <role>org.apache.maven.shared.release.config.ReleaseDescriptorStore</role>
-          <role-hint>properties</role-hint>
+          <role-hint>continuum-release-properties</role-hint>
           <field-name>configStore</field-name>
         </requirement>
         <requirement>
@@ -260,7 +260,7 @@
           <phase>map-development-versions</phase>
           <phase>rewrite-poms-for-release</phase>
           <phase>generate-release-poms</phase>
-          <phase>run-preparation-goals</phase>
+          <phase>run-release-prepare-goals</phase>
           <phase>scm-commit-release</phase>
           <phase>scm-tag</phase>
           <phase>rewrite-poms-for-development</phase>
@@ -271,7 +271,7 @@
         <performPhases>
           <phase>verify-completed-prepare-phases</phase>
           <phase>checkout-project-from-scm</phase>
-          <phase>run-perform-goals</phase>
+          <phase>run-release-perform-goals</phase>
         </performPhases>
         <rollbackPhases>
           <phase>generate-reactor-projects</phase>
@@ -304,7 +304,27 @@
         </requirement>
       </requirements>
     </component>
-
+    <component>
+      <role>org.apache.maven.shared.release.phase.ReleasePhase</role>
+      <role-hint>run-release-prepare-goals</role-hint>
+      <implementation>org.apache.continuum.release.phase.RunPrepareGoalsPhase</implementation>
+      <requirements>
+        <requirement>
+          <role>org.apache.continuum.utils.shell.ShellCommandHelper</role>
+        </requirement>
+      </requirements>
+    </component>
+    <component>
+      <role>org.apache.maven.shared.release.phase.ReleasePhase</role>
+      <role-hint>run-release-perform-goals</role-hint>
+      <implementation>org.apache.continuum.release.phase.RunPerformGoalsPhase</implementation>
+      <requirements>
+        <requirement>
+          <role>org.apache.continuum.utils.shell.ShellCommandHelper</role>
+        </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>
@@ -318,12 +338,16 @@
           <role>org.apache.maven.artifact.factory.ArtifactFactory</role>
         </requirement>
         <requirement>
-          <role>org.apache.maven.artifact.repository.metadata.RepositoryMetadataManager</role
->
+          <role>org.apache.maven.artifact.repository.metadata.RepositoryMetadataManager</role>
         </requirement>
       </requirements>
     </component>
 
+    <component>
+      <role>org.apache.maven.shared.release.config.ReleaseDescriptorStore</role>
+      <role-hint>continuum-release-properties</role-hint>
+      <implementation>org.apache.continuum.release.config.ContinuumPropertiesReleaseDescriptorStore</implementation>
+    </component>
   </components>
 
 </component-set>
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 36e0ee1..8ccb635 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
@@ -21,6 +21,7 @@
 
 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;
 import org.apache.maven.continuum.release.tasks.PrepareReleaseProjectTask;
@@ -98,7 +99,7 @@
         File testDir = new File( getBasedir(), "target/test-classes/test-dir" );
         FileUtils.deleteDirectory( testDir );
 
-        ReleaseDescriptor descriptor = new ReleaseDescriptor();
+        ContinuumReleaseDescriptor descriptor = new ContinuumReleaseDescriptor();
         descriptor.setInteractive( false );
         descriptor.setScmSourceUrl( "scm:svn:file://localhost/" + scmPath + "/trunk" );
         descriptor.setWorkingDirectory( workDir.getAbsolutePath() );
@@ -140,7 +141,7 @@
         File testDir = new File( getBasedir(), "target/test-classes/test-dir" );
         FileUtils.deleteDirectory( testDir );
 
-        ReleaseDescriptor descriptor = new ReleaseDescriptor();
+        ContinuumReleaseDescriptor descriptor = new ContinuumReleaseDescriptor();
         descriptor.setInteractive( false );
         descriptor.setScmSourceUrl( "scm:svn:file://localhost/" + scmPath + "/trunk" );
         descriptor.setWorkingDirectory( workDir.getAbsolutePath() );
@@ -185,7 +186,7 @@
         File testDir = new File( getBasedir(), "target/test-classes/test-dir" );
         FileUtils.deleteDirectory( testDir );
 
-        ReleaseDescriptor descriptor = new ReleaseDescriptor();
+        ContinuumReleaseDescriptor descriptor = new ContinuumReleaseDescriptor();
         descriptor.setInteractive( false );
         descriptor.setScmSourceUrl( "scm:svn:file://localhost/" + scmPath + "/trunk" );
         descriptor.setWorkingDirectory( workDir.getAbsolutePath() );
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 e53228a..bf83f4f 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
@@ -20,8 +20,10 @@
  */
 
 import org.apache.continuum.model.repository.LocalRepository;
+import org.apache.continuum.release.config.ContinuumReleaseDescriptor;
 import org.apache.maven.continuum.ContinuumException;
 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;
@@ -31,6 +33,7 @@
 import org.apache.maven.shared.release.config.ReleaseDescriptor;
 
 import java.io.File;
+import java.util.List;
 
 /**
  * @author Edwin Punzalan
@@ -63,6 +66,10 @@
 
     private String projectGroupName = "";
 
+    private List<Profile> profiles;
+
+    private int profileId;
+
     public String inputFromScm()
         throws Exception
     {
@@ -79,6 +86,8 @@
 
         releaseId = "";
 
+        profiles = this.getContinuum().getProfileService().getAllProfiles();
+
         return SUCCESS;
     }
 
@@ -132,12 +141,20 @@
     {
         ContinuumReleaseManager releaseManager = getContinuum().getReleaseManager();
 
-        ReleaseDescriptor descriptor = new ReleaseDescriptor();
+        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 )
+        {
+            profile = getContinuum().getProfileService().getProfile( profileId );
+            descriptor.setEnvironments( releaseManager.getEnvironments( profile ) );
+        }
 
         do
         {
@@ -291,4 +308,25 @@
 
         return projectGroupName;
     }
+
+    public List<Profile> getProfiles()
+    {
+        return profiles;
+    }
+
+    public void setProfiles( List<Profile> profiles )
+    {
+        this.profiles = profiles;
+    }
+
+    public int getProfileId()
+    {
+        return profileId;
+    }
+
+    public void setProfileId( int profileId )
+    {
+        this.profileId = profileId;
+    }
+    
 }
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 416241d..82003f4 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
@@ -21,6 +21,7 @@
 
 import org.apache.maven.continuum.ContinuumException;
 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;
@@ -85,6 +86,10 @@
 
     private String projectGroupName = "";
 
+    private List<Profile> profiles;
+
+    private int profileId;
+
     public String input()
         throws Exception
     {
@@ -138,6 +143,8 @@
 
         processProject( workingDirectory, "pom.xml" );
 
+        profiles = this.getContinuum().getProfileService().getAllProfiles();
+
         return SUCCESS;
     }
 
@@ -210,11 +217,18 @@
         {
             name = project.getArtifactId();
         }
+        
+        Profile profile = null;
+        
+        if ( profileId != -1 )
+        {
+            profile = getContinuum().getProfileService().getProfile( profileId );
+        }
 
         ContinuumReleaseManager releaseManager = getContinuum().getReleaseManager();
 
         releaseId =
-            releaseManager.prepare( project, getReleaseProperties(), getRelVersionMap(), getDevVersionMap(), listener );
+            releaseManager.prepare( project, getReleaseProperties(), getRelVersionMap(), getDevVersionMap(), listener, profile );
 
         return SUCCESS;
     }
@@ -526,4 +540,24 @@
 
         return projectGroupName;
     }
+
+    public List<Profile> getProfiles()
+    {
+        return profiles;
+    }
+
+    public void setProfiles( List<Profile> profiles )
+    {
+        this.profiles = profiles;
+    }
+
+    public int getProfileId()
+    {
+        return profileId;
+    }
+
+    public void setProfileId( int profileId )
+    {
+        this.profileId = profileId;
+    }
 }
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 c39be1d..1f9accc 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
@@ -37,6 +37,7 @@
 import org.codehaus.plexus.redback.xwork.interceptor.SecureActionBundle;
 import org.codehaus.plexus.redback.xwork.interceptor.SecureActionException;
 
+import com.opensymphony.webwork.ServletActionContext;
 import com.opensymphony.xwork.Preparable;
 
 /**
@@ -70,6 +71,8 @@
 
     private List<Installation> profileInstallations;
 
+    private String message;
+
     // -------------------------------------------------------
     //  Webwork Methods
     // -------------------------------------------------------
@@ -84,6 +87,13 @@
     public String list()
         throws Exception
     {
+        String errorMessage = ServletActionContext.getRequest().getParameter( "errorMessage" );
+
+        if ( errorMessage != null )
+        {
+            addActionError( errorMessage );
+        }
+        
         this.profiles = profileService.getAllProfiles();
         return SUCCESS;
     }
@@ -149,10 +159,18 @@
 
     public String delete()
         throws Exception
-    {
-        profileService.deleteProfile( profile.getId() );
-        this.profiles = profileService.getAllProfiles();
-        return SUCCESS;
+    {   
+        try
+        {
+            profileService.deleteProfile( profile.getId() );
+            this.profiles = profileService.getAllProfiles();
+            return SUCCESS;
+        }
+        catch ( ProfileException e )
+        {
+            message = "profile.remove.error";
+            return ERROR;
+        }
     }
 
     public String confirmDelete()
@@ -283,4 +301,14 @@
     {
         this.installationId = installationId;
     }
+
+    public String getMessage()
+    {
+        return message;
+    }
+
+    public void setMessage( String message )
+    {
+        this.message = message;
+    }
 }
diff --git a/continuum-webapp/src/main/resources/localization/Continuum.properties b/continuum-webapp/src/main/resources/localization/Continuum.properties
index 7c9db4b..e06b319 100644
--- a/continuum-webapp/src/main/resources/localization/Continuum.properties
+++ b/continuum-webapp/src/main/resources/localization/Continuum.properties
@@ -654,6 +654,20 @@
 releaseViewResult.noOutput=No Output
 releaseViewResult.projectName=Project Name
 releaseViewResult.releaseGoal=Release Goal
+releasePrepare.scmUsername.label=SCM Username
+releasePrepare.scmPassword.label=SCM Password
+releasePrepare.scmTag.label=SCM Tag
+releasePrepare.scmTagBase.label=SCM Tag Base
+releasePrepare.prepareGoals.label=Preparation Goals
+releasePrepare.buildEnvironment.label=Build Environment
+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.useReleaseProfile.label=Use Release Profile
+releasePerformFromScm.buildEnvironment.label=Build Environment
 
 # ----------------------------------------------------------------------
 # Page: User
@@ -697,6 +711,7 @@
 profile.no.installations = No installations available
 profile.name.already.exists = A Build Environment with the same name already exists
 profile.name.required = You must define a name.
+profile.remove.error = The Build Environment can't be removed, it is probably used by a build definition.
 
 # ----------------------------------------------------------------------
 # Page: Installations List
diff --git a/continuum-webapp/src/main/resources/xwork.xml b/continuum-webapp/src/main/resources/xwork.xml
index 63a5a2a..f90a29c 100644
--- a/continuum-webapp/src/main/resources/xwork.xml
+++ b/continuum-webapp/src/main/resources/xwork.xml
@@ -618,6 +618,12 @@
         <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 name="confirmDeleteBuildEnv" class="profileAdministration" method="confirmDelete">
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 88252d7..810bf01 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
@@ -33,6 +33,14 @@
       <ww:text name="profilesList.section.title"/>
     </h3>
 
+    <c:if test="${!empty actionErrors}">
+      <div class="errormessage">
+        <c:forEach items="${actionErrors}" var="actionError">
+          <p><ww:text name="${actionError}"/></p>
+        </c:forEach>
+      </div>
+    </c:if>
+        
     <ww:if test="${not empty profiles}">
     <ec:table items="profiles"
               var="profile"
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 2a03739..fb4e671 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/releasePerformFromScm.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/releasePerformFromScm.jsp
@@ -31,15 +31,17 @@
         <ww:hidden name="projectId"/>
         <div class="axial">
           <table border="1" cellspacing="2" cellpadding="3" width="100%">
-            <ww:textfield label="SCM Connection URL" name="scmUrl"/>
-            <ww:textfield label="SCM Username" name="scmUsername"/>
-            <ww:password label="SCM Password" name="scmPassword"/>
-            <ww:textfield label="SCM Tag" name="scmTag"/>
+            <ww:textfield label="%{getText('releasePerformFromScm.scmUrl.label')}" name="scmUrl"/>
+            <ww:textfield label="%{getText('releasePerformFromScm.scmUsername.label')}" name="scmUsername"/>
+            <ww:password label="%{getText('releasePerformFromScm.scmPassword.label')}" name="scmPassword"/>
+            <ww:textfield label="%{getText('releasePerformFromScm.scmTag.label')}" name="scmTag"/>
             <c:if test="${!empty (scmTagBase)}">
-              <ww:textfield label="SCM Tag Base" name="scmTagBase"/>
+              <ww:textfield label="%{getText('releasePerformFromScm.scmTagBase.label')}" name="scmTagBase"/>
             </c:if>
-            <ww:textfield label="Maven Arguments" name="goals" value="clean deploy"/>
-            <ww:checkbox label="Use Release Profile" name="useReleaseProfile" value="true"/>
+            <ww:textfield label="%{getText('releasePerformFromScm.goals.label')}" name="goals" value="clean deploy"/>
+            <ww:checkbox label="%{getText('releasePerformFromScm.useReleaseProfile.label')}" name="useReleaseProfile" value="true"/>
+            <ww:select label="%{getText('releasePerformFromScm.buildEnvironment.label')}" name="profileId" list="profiles" listValue="name" 
+                       listKey="id" headerKey="-1" headerValue=""/>
           </table>
         </div>
         <ww:submit/>
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 3201637..63f43e4 100644
--- a/continuum-webapp/src/main/webapp/WEB-INF/jsp/releasePrepare.jsp
+++ b/continuum-webapp/src/main/webapp/WEB-INF/jsp/releasePrepare.jsp
@@ -32,14 +32,16 @@
         <input type="hidden" name="projectId" value="<ww:property value="projectId"/>"/>
         <div class="axial">
           <table border="1" cellspacing="2" cellpadding="3" width="100%">
-            <ww:textfield label="SCM Username" name="scmUsername" required="true"/>
-            <ww:password label="SCM Password" name="scmPassword" required="true"/>
-            <ww:textfield label="SCM Tag" name="scmTag" required="true"/>
+            <ww:textfield label="%{getText('releasePrepare.scmUsername.label')}" name="scmUsername" required="true"/>
+            <ww:password label="%{getText('releasePrepare.scmPassword.label')}" name="scmPassword" required="true"/>
+            <ww:textfield label="%{getText('releasePrepare.scmTag.label')}" name="scmTag" required="true"/>
             <c:if test="${!empty (scmTagBase)}">
-              <ww:textfield label="SCM Tag Base" name="scmTagBase"/>
+              <ww:textfield label="%{getText('releasePrepare.scmTagBase.label')}" name="scmTagBase"/>
             </c:if>
-            <ww:textfield label="Preparation Goals" name="prepareGoals" required="true"/>
-           </table>
+            <ww:textfield label="%{getText('releasePrepare.prepareGoals.label')}" name="prepareGoals" required="true"/>
+            <ww:select label="%{getText('releasePrepare.buildEnvironment.label')}" name="profileId" list="profiles" listValue="name" 
+                       listKey="id" headerKey="-1" headerValue=""/>
+          </table>
         </div>
 
         <ww:iterator value="projects">