001    package org.apache.maven.scm.plugin;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     * http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import java.io.File;
023    
024    import org.apache.maven.plugin.MojoExecutionException;
025    import org.apache.maven.scm.ScmResult;
026    import org.apache.maven.scm.command.checkout.CheckOutScmResult;
027    import org.codehaus.plexus.util.StringUtils;
028    import org.codehaus.plexus.util.cli.CommandLineException;
029    import org.codehaus.plexus.util.cli.CommandLineUtils;
030    import org.codehaus.plexus.util.cli.Commandline;
031    import org.codehaus.plexus.util.cli.DefaultConsumer;
032    import org.codehaus.plexus.util.cli.StreamConsumer;
033    
034    /**
035     * Pull the project source from the configured scm and execute the configured goals.
036     *
037     * @author <a href="dantran@gmail.com">Dan T. Tran</a>
038     *
039     * @goal bootstrap
040     * @requiresProject false
041     */
042    public class BootstrapMojo
043        extends CheckoutMojo
044    {
045        /**
046         * The goals to run on the clean checkout of a project for the bootstrap goal.
047         * If none are specified, then the default goal for the project is executed.
048         * Multiple goals should be comma separated.
049         *
050         * @parameter expression="${goals}"
051         */
052        private String goals;
053    
054        /**
055         * A list of profiles to run with the goals.
056         * Multiple profiles must be comma separated with no spaces.
057         *
058         * @parameter expression="${profiles}"
059         */
060        private String profiles;
061    
062        /**
063         * The subdirectory (under the project directory) in which to run the goals.
064         * The project directory is the same as the checkout directory in most cases,
065         * but for some SCMs, it is a subdirectory of the checkout directory.
066         *
067         * @parameter expression="${goalsDirectory}" default-value=""
068         */
069        private String goalsDirectory;
070    
071        /** {@inheritDoc} */
072        public void execute()
073            throws MojoExecutionException
074        {
075            super.execute();
076    
077            if ( this.getCheckoutResult() != null )
078            {
079                
080                ScmResult checkoutResult = this.getCheckoutResult();
081                
082                //At the time of useExport feature is requested only SVN and and CVS have export command implemented
083                // we will deal with this as more user using this feature specially clearcase where we need to 
084                // add relativePathProjectDirectory support to ExportScmResult
085                String relativePathProjectDirectory = "";
086                if ( checkoutResult instanceof CheckOutScmResult )
087                {
088                    relativePathProjectDirectory = ( (CheckOutScmResult) checkoutResult).getRelativePathProjectDirectory();
089                }
090    
091                runGoals( relativePathProjectDirectory );
092            }
093        }
094    
095        /**
096         * @param relativePathProjectDirectory the project directory's path relative to the checkout
097         *                                     directory; or "" if they are the same
098         * @throws MojoExecutionException if any
099         */
100        private void runGoals( String relativePathProjectDirectory )
101            throws MojoExecutionException
102        {
103            Commandline cl = new Commandline();
104            try
105            {
106                cl.addSystemEnvironment();
107            }
108            catch ( Exception e )
109            {
110                throw new MojoExecutionException( "Can't add system environment variables to mvn command line.", e );
111            }
112            cl.addEnvironment( "MAVEN_TERMINATE_CMD", "on" );
113            cl.setExecutable( "mvn" );
114            cl.setWorkingDirectory( determineWorkingDirectoryPath( this.getCheckoutDirectory(),
115                                                                   relativePathProjectDirectory, goalsDirectory ) );
116    
117            if ( this.goals != null )
118            {
119                String[] tokens = StringUtils.split( this.goals, ", " );
120    
121                for ( int i = 0; i < tokens.length; ++i )
122                {
123                    cl.createArg().setValue( tokens[i] );
124                }
125            }
126    
127            if ( ! StringUtils.isEmpty( this.profiles ) )
128            {
129                cl.createArg().setValue( "-P" + this.profiles );
130            }
131    
132            StreamConsumer consumer = new DefaultConsumer();
133    
134            try
135            {
136                int result = CommandLineUtils.executeCommandLine( cl, consumer, consumer );
137    
138                if ( result != 0 )
139                {
140                    throw new MojoExecutionException( "Result of mvn execution is: \'" + result + "\'. Release failed." );
141                }
142            }
143            catch ( CommandLineException e )
144            {
145                throw new MojoExecutionException( "Can't run goal " + goals, e );
146            }
147        }
148    
149        /**
150         * Determines the path of the working directory. By default, this is the checkout directory. For some SCMs,
151         * the project root directory is not the checkout directory itself, but a SCM-specific subdirectory. The
152         * build can furthermore optionally be executed in a subdirectory of this project directory, in case.
153         *
154         * @param checkoutDirectory
155         * @param relativePathProjectDirectory
156         * @param goalsDirectory
157         * @return
158         */
159        protected String determineWorkingDirectoryPath( File checkoutDirectory, String relativePathProjectDirectory,
160                                                        String goalsDirectory )
161        {
162            File projectDirectory;
163            if ( StringUtils.isNotEmpty( relativePathProjectDirectory ) )
164            {
165                projectDirectory = new File( checkoutDirectory, relativePathProjectDirectory );
166            }
167            else
168            {
169                projectDirectory = checkoutDirectory;
170            }
171    
172            if ( StringUtils.isEmpty( goalsDirectory ) )
173            {
174                return projectDirectory.getPath();
175            }
176    
177            return new File( projectDirectory, goalsDirectory ).getPath();
178        }
179    }