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