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 816550 2012-05-08 11:52:49Z 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       * @component
88       */
89      private WagonManager wagonManager;
90  
91      /**
92       * The current user system settings for use in Maven.
93       *
94       * @parameter expression="${settings}"
95       * @required
96       * @readonly
97       */
98      private Settings settings;
99  
100     private PlexusContainer container;
101 
102     /**
103      * @see org.apache.maven.plugin.Mojo#execute()
104      */
105     public void execute()
106         throws MojoExecutionException, MojoFailureException
107     {
108         super.execute();
109 
110         deployStagingSite();
111     }
112 
113     /**
114      * Deploy the staging directory using the stagingSiteURL.
115      *
116      * @throws org.apache.maven.plugin.MojoExecutionException
117      *          if any
118      * @throws org.apache.maven.plugin.MojoFailureException
119      *          if any
120      */
121     private void deployStagingSite()
122         throws MojoExecutionException, MojoFailureException
123     {
124         stagingSiteURL = getStagingSiteURL( project, reactorProjects, stagingSiteURL );
125         getLog().info( "Using this URL for staging: " + stagingSiteURL );
126 
127         Repository repository = new Repository( stagingRepositoryId, stagingSiteURL );
128 
129         Wagon wagon;
130         try
131         {
132             wagon = wagonManager.getWagon( repository );
133             SiteDeployMojo.configureWagon( wagon, stagingRepositoryId, settings, container, getLog() );
134         }
135         catch ( UnsupportedProtocolException e )
136         {
137             throw new MojoExecutionException( "Unsupported protocol: '" + repository.getProtocol() + "'", e );
138         }
139         catch ( WagonConfigurationException e )
140         {
141             throw new MojoExecutionException( "Unable to configure Wagon: '" + repository.getProtocol() + "'", e );
142         }
143 
144         if ( !wagon.supportsDirectoryCopy() )
145         {
146             throw new MojoExecutionException(
147                 "Wagon protocol '" + repository.getProtocol() + "' doesn't support directory copying" );
148         }
149 
150         try
151         {
152             Debug debug = new Debug();
153 
154             wagon.addSessionListener( debug );
155 
156             wagon.addTransferListener( debug );
157 
158             ProxyInfo proxyInfo = SiteDeployMojo.getProxyInfo( repository, wagonManager );
159             if ( proxyInfo != null )
160             {
161                 wagon.connect( repository, wagonManager.getAuthenticationInfo( stagingRepositoryId ), proxyInfo );
162             }
163             else
164             {
165                 wagon.connect( repository, wagonManager.getAuthenticationInfo( stagingRepositoryId ) );
166             }
167 
168             wagon.putDirectory( new File( stagingDirectory, getStructure( project, false ) ), "." );
169 
170             // TODO: current wagon uses zip which will use the umask on remote host instead of honouring our settings
171             //  Force group writeable
172             if ( wagon instanceof CommandExecutor )
173             {
174                 CommandExecutor exec = (CommandExecutor) wagon;
175                 exec.executeCommand( "chmod -Rf g+w,a+rX " + repository.getBasedir() );
176             }
177         }
178         catch ( ResourceDoesNotExistException e )
179         {
180             throw new MojoExecutionException( "Error uploading site", e );
181         }
182         catch ( TransferFailedException e )
183         {
184             throw new MojoExecutionException( "Error uploading site", e );
185         }
186         catch ( AuthorizationException e )
187         {
188             throw new MojoExecutionException( "Error uploading site", e );
189         }
190         catch ( ConnectionException e )
191         {
192             throw new MojoExecutionException( "Error uploading site", e );
193         }
194         catch ( AuthenticationException e )
195         {
196             throw new MojoExecutionException( "Error uploading site", e );
197         }
198         catch ( CommandExecutionException e )
199         {
200             throw new MojoExecutionException( "Error uploading site", e );
201         }
202         finally
203         {
204             try
205             {
206                 wagon.disconnect();
207             }
208             catch ( ConnectionException e )
209             {
210                 getLog().error( "Error disconnecting wagon - ignored", e );
211             }
212         }
213     }
214 
215     public void contextualize( Context context )
216         throws ContextException
217     {
218         container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
219     }
220 
221     /**
222      * Find the URL where staging will take place.
223      *
224      * @param currentProject      The currently executing project
225      * @param reactorProjects     The projects in the reactor
226      * @param usersStagingSiteURL The staging site URL as suggested by the user's configuration
227      * @return the site URL for staging
228      */
229     protected String getStagingSiteURL( MavenProject currentProject, List reactorProjects, String usersStagingSiteURL )
230     {
231         String topLevelURL = null;
232         String relative = "";
233 
234         // If the user has specified a stagingSiteURL - use it
235         if ( usersStagingSiteURL != null )
236         {
237             getLog().debug( "stagingSiteURL specified by the user." );
238             topLevelURL = usersStagingSiteURL;
239         }
240         getLog().debug( "stagingSiteURL NOT specified by the user." );
241 
242         // Find the top level project in the reactor
243         MavenProject topLevelProject = getTopLevelProject( reactorProjects );
244 
245         // Take the distributionManagement site url from the top level project,
246         // if there is one, otherwise take it from the current project
247         if ( topLevelProject == null )
248         {
249             if ( topLevelURL == null )
250             {
251                 // The user didn't specify a URL and there is no top level project in the reactor
252                 // Use current project
253                 getLog().debug( "No top level project found in the reactor, using the current project." );
254                 topLevelURL =
255                     currentProject.getDistributionManagement().getSite().getUrl() + "/" + DEFAULT_STAGING_DIRECTORY;
256             }
257         }
258         else
259         {
260             // Find the relative path between the parent and child distribution URLs, if any
261             relative = "/" + siteTool.getRelativePath( currentProject.getDistributionManagement().getSite().getUrl(),
262                                                        topLevelProject.getDistributionManagement().getSite().getUrl() );
263             // SiteTool.getRelativePath() uses File.separatorChar, so we need to convert '\' to '/' in order for the URL
264             // to be valid for Windows users
265             relative = relative.replace( '\\', '/' );
266 
267             if ( topLevelURL == null )
268             {
269                 // The user didn't specify a URL and there is a top level project in the reactor
270                 // Use the top level project
271                 getLog().debug( "Using the top level project found in the reactor." );
272                 topLevelURL =
273                     topLevelProject.getDistributionManagement().getSite().getUrl() + "/" + DEFAULT_STAGING_DIRECTORY;
274             }
275         }
276 
277         // Return either
278         //   usersURL + relative(from parent, to child)
279         // or
280         //   topLevelProjectURL + staging + relative(from parent, to child)
281         return topLevelURL + relative;
282     }
283 }