View Javadoc

1   /*
2    * Copyright 2012 smartics, Kronseder & Reiner GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package de.smartics.maven.bugzilla;
17  
18  import org.apache.commons.httpclient.HttpClient;
19  import org.apache.maven.model.DeploymentRepository;
20  import org.apache.maven.model.DistributionManagement;
21  import org.apache.maven.plugin.MojoExecutionException;
22  import org.apache.maven.plugin.MojoFailureException;
23  import org.apache.maven.plugin.logging.Log;
24  import org.apache.maven.project.MavenProject;
25  import org.codehaus.plexus.util.StringUtils;
26  
27  import de.smartics.maven.issue.command.CommandException;
28  import de.smartics.maven.issue.util.LogLevel;
29  import de.smartics.maven.issue.util.VersionHelper;
30  import de.smartics.maven.nexus.NexusClient;
31  import de.smartics.maven.nexus.NexusRequest;
32  import de.smartics.maven.nexus.NexusUtils;
33  
34  /**
35   * Used after a release: Updates a product on the issue management server with
36   * information from this project and initializes the version information for
37   * that project.
38   *
39   * @goal sync
40   * @requiresProject
41   * @threadSafe
42   * @since 1.0
43   * @description Synchronizes the product information after a release according
44   *              to best practices.
45   */
46  public class SyncProductMojo extends UpdateProductMojo
47  {
48    // ********************************* Fields *********************************
49  
50    // --- constants ------------------------------------------------------------
51  
52    // --- members --------------------------------------------------------------
53  
54    /**
55     * The released version to add. Also the major, minor and micro increment
56     * milestones are added. If for e.g. the released version is
57     * <code>1.2.3</code>, this version and the milestones <code>1.2.4</code>,
58     * <code>1.3.0</code> and <code>2.0.0</code> are initialized.
59     * <p>
60     * If the released version cannot be recognized by Maven's standard
61     * implementation of a version parser, increment versions will not be added.
62     * </p>
63     * <p>
64     * It is allowed to use the tokens MICRO, MINOR, MAJOR to let the plugin
65     * calculate the previous version by the current version in the POM. For
66     * instance:
67     * </p>
68     * <ul>
69     * <li>1.2.3-SNAPSHOT MICRO -> 1.2.2</li>
70     * <li>1.2.0-SNAPSHOT MINOR -> 1.1.0</li>
71     * <li>1.2.1-SNAPSHOT MINOR -> 1.2.0</li>
72     * <li>2.0.0-SNAPSHOT MAJOR -> 1.0.0</li>
73     * <li>2.0.1-SNAPSHOT MAJOR -> 2.0.0</li>
74     * </ul>
75     * <p>
76     * The following example contexts raise an exception:
77     * </p>
78     * <ul>
79     * <li>1.2.0-SNAPSHOT MICRO -> Failure</li>
80     * <li>1.0.0-SNAPSHOT MINOR -> Failure</li>
81     * <li>0.0.0-SNAPSHOT MAJOR -> Failure</li>
82     * <li>0.1.2-SNAPSHOT MAJOR -> Failure</li>
83     * </ul>
84     * <p>
85     * If the version is not provided, the nexus server will be queried for the
86     * released version.
87     * </p>
88     *
89     * @parameter expression="${releasedVersion}" default-value="NEXUS"
90     * @since 1.0
91     */
92    private String releasedVersion;
93  
94    /**
95     * If <code>releasedVersion</code> is set to <code>NEXUS</code> and the
96     * default searching for the release repository's HTTP URL ending with
97     * <code>/</code> or <code>/nexus</code> would not determine the correct URL,
98     * override it here. This value will take precedence.
99     *
100    * @parameter expression="${nexusServer}"
101    * @since 1.0
102    */
103   private String nexusServer;
104 
105   /**
106    * The repository ID to use to query the Nexus server for the latest released
107    * version if <code>releasedVersion</code> is set to <code>NEXUS</code>. Per
108    * default the plugin will use the identifier of the release repository found
109    * in the <code>distributionManagement</code>. This value overrides the
110    * default behavior.
111    *
112    * @parameter expression="${repositoryId}"
113    * @since 1.0
114    */
115   private String repositoryId;
116 
117   /**
118    * If set to <code>true</code> the Bugzilla product will not be updated.
119    * Usually there are no changes to the components, so that skipping is the
120    * default.
121    *
122    * @parameter expression="${skipProductUpdate}" default-value="true"
123    * @since 1.0
124    */
125   private boolean skipProductUpdate;
126 
127   // ****************************** Initializer *******************************
128 
129   // ****************************** Constructors ******************************
130 
131   // ****************************** Inner Classes *****************************
132 
133   // ********************************* Methods ********************************
134 
135   // --- init -----------------------------------------------------------------
136 
137   // --- get&set --------------------------------------------------------------
138 
139   // --- business -------------------------------------------------------------
140 
141   /**
142    * {@inheritDoc}
143    */
144   @Override
145   public final void run() throws MojoExecutionException, MojoFailureException
146   {
147     if (!skipProductUpdate)
148     {
149       super.run();
150     }
151 
152     final MavenProject project = getProject();
153     final MojoHelperSync helper =
154         new MojoHelperSync(project, commandFactory, console);
155 
156     final String previousVersion = calculatePreviousVersion(project);
157     helper.execute(previousVersion);
158   }
159 
160   // --- object basics --------------------------------------------------------
161 
162   private String calculatePreviousVersion(final MavenProject project)
163     throws MojoExecutionException, MojoFailureException
164   {
165     final Log log = getLog();
166     final LogLevel logLevel = new LogLevel(verbose);
167 
168     final String previousVersion;
169     if ("NEXUS".equals(releasedVersion))
170     {
171       final NexusClient client =
172           new NexusClient(new HttpClient(), log, logLevel);
173       final NexusRequest request = createNexusRequest(project);
174       try
175       {
176         previousVersion = client.getLatestReleaseVersion(request);
177       }
178       catch (final CommandException e)
179       {
180         throw new MojoFailureException(
181             "Cannot determine latest release version on Nexus.", e);
182       }
183     }
184     else
185     {
186       final VersionHelper versionHelper = new VersionHelper(project);
187       try
188       {
189         previousVersion =
190             versionHelper.calculatePreviousVersion(releasedVersion);
191 
192       }
193       catch (final IllegalArgumentException e)
194       {
195         throw new MojoExecutionException("Cannot calculate previous version: "
196                                          + e.getMessage(), e);
197       }
198     }
199 
200     return previousVersion;
201   }
202 
203   private NexusRequest createNexusRequest(final MavenProject project)
204     throws MojoExecutionException
205   {
206     final DeploymentRepository repository =
207         getDeploymentRepository(project.getDistributionManagement());
208     final String nexusServerUrl = getNexusServerUrl(repository);
209     final String repositoryId = getRepositoryId(repository);
210     final String groupId = project.getGroupId();
211     final String artifactId = project.getArtifactId();
212 
213     return new NexusRequest(nexusServerUrl, repositoryId, groupId, artifactId);
214   }
215 
216   private static DeploymentRepository getDeploymentRepository(
217       final DistributionManagement distributionManagement)
218   {
219     if (distributionManagement != null)
220     {
221       final DeploymentRepository repository =
222           distributionManagement.getRepository();
223       return repository;
224     }
225     return null;
226   }
227 
228   private String getNexusServerUrl(final DeploymentRepository repository)
229     throws MojoExecutionException
230   {
231     if (StringUtils.isNotBlank(nexusServer))
232     {
233       return nexusServer;
234     }
235 
236     if (repository != null)
237     {
238       final String url = repository.getUrl();
239 
240       if (StringUtils.isBlank(url))
241       {
242         throw new MojoExecutionException(
243             "No valid Nexus server URL can be determined. Neiter deployment"
244                 + " repository in the POM specified an URL nor is it specified"
245                 + " via nexusServer.");
246       }
247 
248       final String nexusServer = NexusUtils.calcNexusServerUrl(url);
249       if (StringUtils.isNotBlank(nexusServer))
250       {
251         return nexusServer;
252       }
253     }
254 
255     throw new MojoExecutionException(
256         "No valid Nexus server URL can be determined.  Neither a deployment"
257             + " repository specified in the POM nor specified via nexusServer.");
258   }
259 
260   private String getRepositoryId(final DeploymentRepository repository)
261     throws MojoExecutionException
262   {
263     final String id;
264 
265     if (StringUtils.isNotBlank(repositoryId))
266     {
267       id = repositoryId;
268     }
269     else if (repository != null)
270     {
271       id = repository.getId();
272       if (StringUtils.isBlank(id))
273       {
274         throw new MojoExecutionException(
275             "No valid repository ID can be determined. Not found in the"
276                 + " release repository's element nor specified via repositoryId.");
277       }
278     }
279     else
280     {
281       throw new MojoExecutionException(
282           "No valid repository ID can be determined. Neither a deployment"
283               + " repository specified in the POM nor specified via repositoryId.");
284     }
285 
286     return id;
287   }
288 
289 }