View Javadoc

1   package org.apache.maven.plugins.site;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.artifact.manager.WagonConfigurationException;
23  import org.apache.maven.artifact.manager.WagonManager;
24  import org.apache.maven.plugin.MojoExecutionException;
25  import org.apache.maven.plugin.MojoFailureException;
26  import org.apache.maven.project.MavenProject;
27  import org.apache.maven.settings.Settings;
28  import org.apache.maven.wagon.CommandExecutionException;
29  import org.apache.maven.wagon.CommandExecutor;
30  import org.apache.maven.wagon.ConnectionException;
31  import org.apache.maven.wagon.ResourceDoesNotExistException;
32  import org.apache.maven.wagon.TransferFailedException;
33  import org.apache.maven.wagon.UnsupportedProtocolException;
34  import org.apache.maven.wagon.Wagon;
35  import org.apache.maven.wagon.authentication.AuthenticationException;
36  import org.apache.maven.wagon.authorization.AuthorizationException;
37  import org.apache.maven.wagon.observers.Debug;
38  import org.apache.maven.wagon.proxy.ProxyInfo;
39  import org.apache.maven.wagon.repository.Repository;
40  import org.codehaus.plexus.PlexusConstants;
41  import org.codehaus.plexus.PlexusContainer;
42  import org.codehaus.plexus.context.Context;
43  import org.codehaus.plexus.context.ContextException;
44  import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
45  
46  import java.io.File;
47  import java.util.List;
48  
49  /**
50   * Deploys the generated site to a staging or mock directory to the site URL
51   * specified in the <code>&lt;distributionManagement&gt;</code> section of the
52   * POM. It supports <code>scp</code> and <code>file</code> protocols for
53   * deployment.
54   *
55   * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
56   * @version $Id: SiteStageDeployMojo.html 816556 2012-05-08 11:58:34Z hboutemy $
57   * @goal stage-deploy
58   * @requiresDependencyResolution test
59   */
60  public class SiteStageDeployMojo
61      extends SiteStageMojo implements Contextualizable
62  {
63      /**
64       * The staged site will be deployed to this URL.
65       *
66       * If you don't specify this, the default-value will be
67       * "${project.distributionManagement.site.url}/staging", where "project" is
68       * either the current project or, in a reactor build, the top level project
69       * in the reactor.
70       *
71       * @parameter expression="${stagingSiteURL}"
72       * @see <a href="http://maven.apache.org/maven-model/maven.html#class_site">MavenModel#class_site</a>
73       */
74      private String stagingSiteURL;
75  
76      /**
77       * The identifier of the repository where the staging site will be deployed. This id will be used to lookup a
78       * corresponding <code>&lt;server&gt;</code> entry from the <code>settings.xml</code>. If a matching
79       * <code>&lt;server&gt;</code> entry is found, its configured credentials will be used for authentication.
80       *
81       * @parameter expression="${stagingRepositoryId}" default-value="stagingSite"
82       * @since 2.0.1
83       */
84      private String stagingRepositoryId;
85  
86      /**
87       * Whether to run the "chmod" command on the remote site after the deploy.
88       * Defaults to "true".
89       *
90       * @parameter expression="${maven.site.chmod}" default-value="true"
91       * @since 2.1
92       */
93      private boolean chmod;
94  
95      /**
96       * The mode used by the "chmod" command. Only used if chmod = true.
97       * Defaults to "g+w,a+rX".
98       *
99       * @parameter expression="${maven.site.chmod.mode}" default-value="g+w,a+rX"
100      * @since 2.1
101      */
102     private String chmodMode;
103 
104     /**
105      * The options used by the "chmod" command. Only used if chmod = true.
106      * Defaults to "-Rf".
107      *
108      * @parameter expression="${maven.site.chmod.options}" default-value="-Rf"
109      * @since 2.1
110      */
111     private String chmodOptions;
112 
113     /**
114      * @component
115      */
116     private WagonManager wagonManager;
117 
118     /**
119      * The current user system settings for use in Maven.
120      *
121      * @parameter expression="${settings}"
122      * @required
123      * @readonly
124      */
125     private Settings settings;
126 
127     private PlexusContainer container;
128 
129     /**
130      * {@inheritDoc}
131      */
132     public void execute()
133         throws MojoExecutionException, MojoFailureException
134     {
135         super.execute();
136 
137         deployStagingSite();
138     }
139 
140     /**
141      * Deploy the staging directory using the stagingSiteURL.
142      *
143      * @throws org.apache.maven.plugin.MojoExecutionException
144      *          if any
145      * @throws org.apache.maven.plugin.MojoFailureException
146      *          if any
147      */
148     private void deployStagingSite()
149         throws MojoExecutionException, MojoFailureException
150     {
151         stagingSiteURL = getStagingSiteURL( project, reactorProjects, stagingSiteURL );
152         getLog().info( "Using this URL for staging: " + stagingSiteURL );
153 
154         Repository repository = new Repository( stagingRepositoryId, stagingSiteURL );
155 
156         Wagon wagon;
157         try
158         {
159             wagon = wagonManager.getWagon( repository );
160             SiteDeployMojo.configureWagon( wagon, stagingRepositoryId, settings, container, getLog() );
161         }
162         catch ( UnsupportedProtocolException e )
163         {
164             throw new MojoExecutionException( "Unsupported protocol: '" + repository.getProtocol() + "'", e );
165         }
166         catch ( WagonConfigurationException e )
167         {
168             throw new MojoExecutionException( "Unable to configure Wagon: '" + repository.getProtocol() + "'", e );
169         }
170 
171         if ( !wagon.supportsDirectoryCopy() )
172         {
173             throw new MojoExecutionException(
174                 "Wagon protocol '" + repository.getProtocol() + "' doesn't support directory copying" );
175         }
176 
177         try
178         {
179             Debug debug = new Debug();
180 
181             wagon.addSessionListener( debug );
182 
183             wagon.addTransferListener( debug );
184 
185             ProxyInfo proxyInfo = SiteDeployMojo.getProxyInfo( repository, wagonManager );
186             if ( proxyInfo != null )
187             {
188                 wagon.connect( repository, wagonManager.getAuthenticationInfo( stagingRepositoryId ), proxyInfo );
189             }
190             else
191             {
192                 wagon.connect( repository, wagonManager.getAuthenticationInfo( stagingRepositoryId ) );
193             }
194 
195             wagon.putDirectory( new File( stagingDirectory, getStructure( project, false ) ), "." );
196 
197             if ( chmod && wagon instanceof CommandExecutor )
198             {
199                 CommandExecutor exec = (CommandExecutor) wagon;
200                 exec.executeCommand( "chmod " + chmodOptions + " " + chmodMode + " " + repository.getBasedir() );
201             }
202         }
203         catch ( ResourceDoesNotExistException e )
204         {
205             throw new MojoExecutionException( "Error uploading site", e );
206         }
207         catch ( TransferFailedException e )
208         {
209             throw new MojoExecutionException( "Error uploading site", e );
210         }
211         catch ( AuthorizationException e )
212         {
213             throw new MojoExecutionException( "Error uploading site", e );
214         }
215         catch ( ConnectionException e )
216         {
217             throw new MojoExecutionException( "Error uploading site", e );
218         }
219         catch ( AuthenticationException e )
220         {
221             throw new MojoExecutionException( "Error uploading site", e );
222         }
223         catch ( CommandExecutionException e )
224         {
225             throw new MojoExecutionException( "Error uploading site", e );
226         }
227         finally
228         {
229             try
230             {
231                 wagon.disconnect();
232             }
233             catch ( ConnectionException e )
234             {
235                 getLog().error( "Error disconnecting wagon - ignored", e );
236             }
237         }
238     }
239 
240     public void contextualize( Context context )
241         throws ContextException
242     {
243         container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
244     }
245 
246     /**
247      * Find the URL where staging will take place.
248      *
249      * @param currentProject      The currently executing project
250      * @param reactorProjects     The projects in the reactor
251      * @param usersStagingSiteURL The staging site URL as suggested by the user's configuration
252      * @return the site URL for staging
253      */
254     protected String getStagingSiteURL( MavenProject currentProject, List<MavenProject> reactorProjects,
255                                         String usersStagingSiteURL )
256     {
257         String topLevelURL = null;
258         String relative = "";
259 
260         // If the user has specified a stagingSiteURL - use it
261         if ( usersStagingSiteURL != null )
262         {
263             getLog().debug( "stagingSiteURL specified by the user." );
264             topLevelURL = usersStagingSiteURL;
265         }
266         getLog().debug( "stagingSiteURL NOT specified by the user." );
267 
268         // Find the top level project in the reactor
269         MavenProject topLevelProject = getTopLevelProject( reactorProjects );
270 
271         // Take the distributionManagement site url from the top level project,
272         // if there is one, otherwise take it from the current project
273         if ( topLevelProject == null )
274         {
275             if ( topLevelURL == null )
276             {
277                 // The user didn't specify a URL and there is no top level project in the reactor
278                 // Use current project
279                 getLog().debug( "No top level project found in the reactor, using the current project." );
280                 topLevelURL =
281                     currentProject.getDistributionManagement().getSite().getUrl() + "/" + DEFAULT_STAGING_DIRECTORY;
282             }
283         }
284         else
285         {
286             // Find the relative path between the parent and child distribution URLs, if any
287             relative = "/" + siteTool.getRelativePath( currentProject.getDistributionManagement().getSite().getUrl(),
288                                                        topLevelProject.getDistributionManagement().getSite().getUrl() );
289             // SiteTool.getRelativePath() uses File.separatorChar, so we need to convert '\' to '/' in order for the URL
290             // to be valid for Windows users
291             relative = relative.replace( '\\', '/' );
292 
293             if ( topLevelURL == null )
294             {
295                 // The user didn't specify a URL and there is a top level project in the reactor
296                 // Use the top level project
297                 getLog().debug( "Using the top level project found in the reactor." );
298                 topLevelURL =
299                     topLevelProject.getDistributionManagement().getSite().getUrl() + "/" + DEFAULT_STAGING_DIRECTORY;
300             }
301         }
302 
303         // Return either
304         //   usersURL + relative(from parent, to child)
305         // or
306         //   topLevelProjectURL + staging + relative(from parent, to child)
307         return topLevelURL + relative;
308     }
309 }