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 java.util.Map;
23  import org.apache.commons.lang.StringUtils;
24  import org.apache.maven.model.Build;
25  import org.apache.maven.model.Plugin;
26  import org.apache.maven.model.PluginManagement;
27  import org.apache.maven.model.Site;
28  import org.apache.maven.plugin.MojoExecutionException;
29  import org.apache.maven.project.MavenProject;
30  import org.codehaus.plexus.util.xml.Xpp3Dom;
31  
32  /**
33   * Deploys the generated site to a staging or mock directory to the site URL
34   * specified in the <code>&lt;distributionManagement&gt;</code> section of the
35   * POM, using <a href="/wagon/">wagon supported protocols</a>
36   *
37   * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
38   * @version $Id: SiteStageDeployMojo.html 816573 2012-05-08 12:11:59Z hboutemy $
39   * @goal stage-deploy
40   * @requiresDependencyResolution test
41   */
42  public class SiteStageDeployMojo
43      extends AbstractDeployMojo
44  {
45      /**
46       * The staged site will be deployed to this URL.
47       *
48       * If you don't specify this, the default-value will be
49       * "${project.distributionManagement.site.url}/staging", where "project" is
50       * either the current project or, in a reactor build, the top level project
51       * in the reactor.
52       * <p>
53       * Note that even if you specify this plugin parameter, you still need to indicate
54       * ${project.distributionManagement.site.url} at least in your top level project
55       * in order for relative links between modules to be resolved correctly.
56       * </p>
57       *
58       * @parameter expression="${stagingSiteURL}"
59       * @see <a href="http://maven.apache.org/maven-model/maven.html#class_site">MavenModel#class_site</a>
60       */
61      private String stagingSiteURL;
62  
63      /**
64       * The identifier of the repository where the staging site will be deployed. This id will be used to lookup a
65       * corresponding <code>&lt;server&gt;</code> entry from the <code>settings.xml</code>. If a matching
66       * <code>&lt;server&gt;</code> entry is found, its configured credentials will be used for authentication.
67       *
68       * If this is not specified, then the corresponding value of <code>distributionManagement.site.id</code>
69       * will be taken as default, unless this is not defined either then the String
70       * <code>"stagingSite"</code> is used. (<strong>Note</strong>:
71       * until v. 2.3 and 3.0-beta-3 the String <code>"stagingSite"</code> is always used.)
72       *
73       * @parameter expression="${stagingRepositoryId}"
74       *
75       * @since 2.0.1
76       */
77      private String stagingRepositoryId;
78  
79      @Override
80      /**
81       * Find the relative path between the distribution URLs of the parent that
82       * supplied the staging deploy URL and the current project.
83       *
84       * @return the relative path or "./" if the two URLs are the same.
85       *
86       * @throws MojoExecutionException
87       */
88      protected String getDeployModuleDirectory()
89          throws MojoExecutionException
90      {
91          // MSITE-602: If the user specified an explicit stagingSiteURL, use a special relative path
92          if( StringUtils.isNotEmpty( stagingSiteURL ) )
93          {
94              // We need to calculate the relative path between this project and
95              // the first one that supplied a stagingSiteURL
96              String relative = siteTool.getRelativePath( getSite( project ).getUrl(),
97                  getSiteForTopMostParentWithStagingSiteURL( project ).getUrl() );
98  
99              // SiteTool.getRelativePath() uses File.separatorChar,
100             // so we need to convert '\' to '/' in order for the URL to be valid for Windows users
101             relative = relative.replace( '\\', '/' );
102 
103             getLog().debug( "The stagingSiteURL is configured, using special way to calculate relative path." );
104             return ( "".equals( relative ) ) ? "./" : relative;
105         }
106         else
107         {
108             getLog().debug( "No stagingSiteURL is configured, using standard way to calculate relative path." );
109             return super.getDeployModuleDirectory();
110         }
111     }
112 
113     @Override
114     protected String getDeployRepositoryID()
115         throws MojoExecutionException
116     {
117         stagingRepositoryId = stagingRepoId( stagingRepositoryId );
118 
119         getLog().info( "Using this server ID for stage deploy: " + stagingRepositoryId );
120 
121         return stagingRepositoryId;
122     }
123 
124     @Override
125     protected String getDeployRepositoryURL()
126         throws MojoExecutionException
127     {
128         String stagingURL = determineStagingSiteURL( stagingSiteURL );
129 
130         getLog().info( "Using this base URL for stage deploy: " + stagingURL );
131 
132         return stagingURL;
133     }
134 
135     /**
136      * Extract the distributionManagement.site of the top most project in the
137      * hierarchy that specifies a stagingSiteURL, starting at the given
138      * MavenProject.
139      * <p/>
140      * This climbs up the project hierarchy and returns the site of the top most
141      * project for which
142      * {@link #getStagingSiteURL(org.apache.maven.project.MavenProject)} returns
143      * a URL.
144      *
145      * @param project the MavenProject. Not null.
146      * @return the site for the top most project that has a stagingSiteURL. Not null.
147      */
148     private Site getSiteForTopMostParentWithStagingSiteURL( MavenProject project )
149     {
150         Site site = project.getDistributionManagement().getSite();
151 
152         MavenProject parent = project;
153 
154         // @todo Should we check that the stagingSiteURL equals the one in this project instead of being non-empty?
155         while ( parent != null
156                 && StringUtils.isNotEmpty( getStagingSiteURL( parent ) ) )
157         {
158             site = parent.getDistributionManagement().getSite();
159 
160             // MSITE-585, MNG-1943
161             parent = siteTool.getParentProject( parent, reactorProjects, localRepository );
162         }
163 
164         return site;
165     }
166 
167     /**
168      * Extract the value of the stagingSiteURL configuration parameter of
169      * maven-site-plugin for the given project.
170      *
171      * @param project The MavenProject, not null
172      * @return The stagingSiteURL for the project, or null if it doesn't have one
173      */
174     private String getStagingSiteURL( MavenProject project )
175     {
176         final String sitePluginKey = "org.apache.maven.plugins:maven-site-plugin";
177 
178         if ( project == null )
179         {
180             return null;
181         }
182 
183         final Build build = project.getBuild();
184         if ( build == null )
185         {
186             return null;
187         }
188 
189         Map<String, Plugin> plugins = build.getPluginsAsMap();
190 
191         Plugin sitePlugin = plugins.get( sitePluginKey );
192         if ( sitePlugin == null )
193         {
194             final PluginManagement buildPluginManagement = build.getPluginManagement();
195             if ( buildPluginManagement == null )
196             {
197                 return null;
198             }
199 
200             plugins = buildPluginManagement.getPluginsAsMap();
201             sitePlugin = plugins.get( sitePluginKey );
202         }
203 
204         if ( sitePlugin == null )
205         {
206             return null;
207         }
208 
209         final Xpp3Dom sitePluginConfiguration = (Xpp3Dom) sitePlugin.getConfiguration();
210         if ( sitePluginConfiguration == null )
211         {
212             return null;
213         }
214 
215         final Xpp3Dom child = sitePluginConfiguration.getChild( "stagingSiteURL" );
216         if ( child == null )
217         {
218             return null;
219         }
220         else
221         {
222             return child.getValue();
223         }
224     }
225 
226     /**
227      * Find the URL where staging will take place.
228      *
229      * @param usersStagingSiteURL The staging site URL as suggested by the user's configuration
230      * 
231      * @return the site URL for staging
232      */
233     private String determineStagingSiteURL( final String usersStagingSiteURL )
234         throws MojoExecutionException
235     {
236         String topLevelURL = null;
237 
238         if ( usersStagingSiteURL != null )
239         {
240             // the user has specified a stagingSiteURL - use it
241             getLog().debug( "stagingSiteURL specified by the user: " + usersStagingSiteURL );
242             topLevelURL = usersStagingSiteURL;
243         }
244         else
245         {
246             // The user didn't specify a URL, use the top level site distribution URL and add "[/]staging/" to it
247             topLevelURL = appendSlash( getRootSite( project ).getUrl() )
248                 + DEFAULT_STAGING_DIRECTORY;
249             getLog().debug( "stagingSiteURL NOT specified, using the top level project: " + topLevelURL );
250         }
251 
252         // Return either
253         //   usersURL
254         // or
255         //   topLevelProjectURL + "staging"
256         return topLevelURL;
257     }
258 
259     private String stagingRepoId( final String stagingRepoId )
260     {
261         if ( stagingRepoId != null )
262         {
263             return stagingRepoId;
264         }
265 
266         try
267         {
268             return getSite( project ).getId();
269         }
270         catch ( MojoExecutionException ex )
271         {
272             return "stagingSite";
273         }
274     }
275 }