blob: 7be84d4d5c6fbcefcfdcff760ba5d4c61a8a16fc [file] [log] [blame]
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19package org.apache.felix.bundleplugin.baseline;
20
21import java.io.File;
22import java.io.IOException;
23import java.text.SimpleDateFormat;
24import java.util.Arrays;
25import java.util.Date;
26import java.util.Iterator;
27import java.util.List;
28import java.util.Map;
29import java.util.Set;
30
A. J. David Bosschaert7bd6b712015-05-19 14:26:22 +000031import aQute.bnd.differ.Baseline;
32import aQute.bnd.differ.Baseline.Info;
33import aQute.bnd.differ.DiffPluginImpl;
34import aQute.bnd.osgi.Instructions;
35import aQute.bnd.osgi.Jar;
36import aQute.bnd.osgi.Processor;
37import aQute.bnd.service.diff.Delta;
38import aQute.bnd.service.diff.Diff;
39import aQute.bnd.version.Version;
40import aQute.service.reporter.Reporter;
41
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +000042import org.apache.maven.artifact.Artifact;
43import org.apache.maven.artifact.factory.ArtifactFactory;
44import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
45import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +000046import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
47import org.apache.maven.artifact.resolver.ArtifactResolutionException;
48import org.apache.maven.artifact.resolver.ArtifactResolver;
49import org.apache.maven.artifact.versioning.ArtifactVersion;
50import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
51import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
52import org.apache.maven.artifact.versioning.VersionRange;
Carsten Ziegelerccc30322015-03-03 10:48:44 +000053import org.apache.maven.execution.MavenSession;
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +000054import org.apache.maven.plugin.AbstractMojo;
55import org.apache.maven.plugin.MojoExecutionException;
56import org.apache.maven.plugin.MojoFailureException;
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +000057import org.apache.maven.plugins.annotations.Component;
58import org.apache.maven.plugins.annotations.Parameter;
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +000059import org.apache.maven.project.MavenProject;
60import org.codehaus.plexus.util.StringUtils;
61
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +000062/**
63 * Abstract BND Baseline check between two bundles.
64 */
65abstract class AbstractBaselinePlugin
66 extends AbstractMojo
67{
68
69 /**
70 * Flag to easily skip execution.
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +000071 */
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +000072 @Parameter( property = "baseline.skip", defaultValue = "false" )
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +000073 protected boolean skip;
74
75 /**
76 * Whether to fail on errors.
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +000077 */
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +000078 @Parameter( property = "baseline.failOnError", defaultValue = "true" )
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +000079 protected boolean failOnError;
80
81 /**
82 * Whether to fail on warnings.
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +000083 */
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +000084 @Parameter( property = "baseline.failOnWarning", defaultValue = "false" )
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +000085 protected boolean failOnWarning;
86
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +000087 @Parameter( defaultValue = "${project}", readonly = true, required = true )
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +000088 protected MavenProject project;
89
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +000090 @Parameter( defaultValue = "${session}", readonly = true, required = true )
Carsten Ziegelerccc30322015-03-03 10:48:44 +000091 protected MavenSession session;
92
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +000093 @Parameter( defaultValue = "${project.build.directory}", readonly = true, required = true )
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +000094 private File buildDirectory;
95
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +000096 @Parameter( defaultValue = "${project.build.finalName}", readonly = true, required = true )
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +000097 private String finalName;
98
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +000099 @Component
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000100 protected ArtifactResolver resolver;
101
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +0000102 @Component
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000103 protected ArtifactFactory factory;
104
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +0000105 @Component
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000106 private ArtifactMetadataSource metadataSource;
107
108 /**
Guillaume Nodet10dae652015-07-09 19:44:41 +0000109 * Group id to compare the current code against.
110 */
111 @Parameter( defaultValue = "${project.groupId}", property="comparisonGroupId" )
112 protected String comparisonGroupId;
113
114 /**
115 * Artifact to compare the current code against.
116 */
117 @Parameter( defaultValue = "${project.artifactId}", property="comparisonArtifactId" )
118 protected String comparisonArtifactId;
119
120 /**
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000121 * Version to compare the current code against.
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000122 */
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +0000123 @Parameter( defaultValue = "(,${project.version})", property="comparisonVersion" )
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000124 protected String comparisonVersion;
125
126 /**
Guillaume Nodet10dae652015-07-09 19:44:41 +0000127 * Artifact to compare the current code against.
128 */
129 @Parameter( defaultValue = "${project.packaging}", property="comparisonPackaging" )
130 protected String comparisonPackaging;
131
132 /**
Carsten Ziegeler76e9dbc2014-08-21 09:58:12 +0000133 * Classifier for the artifact to compare the current code against.
Carsten Ziegeler76e9dbc2014-08-21 09:58:12 +0000134 */
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +0000135 @Parameter( property="comparisonClassifier" )
Carsten Ziegeler76e9dbc2014-08-21 09:58:12 +0000136 protected String comparisonClassifier;
137
138 /**
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000139 * A list of packages filter, if empty the whole bundle will be traversed. Values are specified in OSGi package
140 * instructions notation, e.g. <code>!org.apache.felix.bundleplugin</code>.
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000141 */
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +0000142 @Parameter
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000143 private String[] filters;
144
Guillaume Nodet284fb442014-05-22 13:20:16 +0000145 /**
146 * Project types which this plugin supports.
Guillaume Nodet284fb442014-05-22 13:20:16 +0000147 */
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +0000148 @Parameter
Carsten Ziegelerccc30322015-03-03 10:48:44 +0000149 protected List<String> supportedProjectTypes = Arrays.asList( new String[] { "jar", "bundle" } );
Guillaume Nodet284fb442014-05-22 13:20:16 +0000150
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000151 public final void execute()
152 throws MojoExecutionException, MojoFailureException
153 {
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000154 this.execute(null);
155 }
156
157 protected void execute( Object context)
158 throws MojoExecutionException, MojoFailureException
159 {
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000160 if ( skip )
161 {
162 getLog().info( "Skipping Baseline execution" );
163 return;
164 }
165
Guillaume Nodet284fb442014-05-22 13:20:16 +0000166 if ( !supportedProjectTypes.contains( project.getArtifact().getType() ) )
167 {
168 getLog().info("Skipping Baseline (project type " + project.getArtifact().getType() + " not supported)");
169 return;
170 }
171
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000172 // get the bundles that have to be compared
173
174 final Jar currentBundle = getCurrentBundle();
175 if ( currentBundle == null )
176 {
177 getLog().info( "Not generating Baseline report as there is no bundle generated by the project" );
178 return;
179 }
180
Carsten Ziegeler23ecafb2015-02-02 08:26:13 +0000181 final Artifact previousArtifact = getPreviousArtifact();
A. J. David Bosschaert7bd6b712015-05-19 14:26:22 +0000182
183 final Jar previousBundle;
184 if (previousArtifact != null)
185 {
186 previousBundle = openJar(previousArtifact.getFile());
187 }
188 else
189 {
190 previousBundle = null;
191 }
192
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000193 if ( previousBundle == null )
194 {
195 getLog().info( "Not generating Baseline report as there is no previous version of the library to compare against" );
196 return;
197 }
198
199 // preparing the filters
200
201 final Instructions packageFilters;
202 if ( filters == null || filters.length == 0 )
203 {
204 packageFilters = new Instructions();
205 }
206 else
207 {
208 packageFilters = new Instructions( Arrays.asList( filters ) );
209 }
210
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000211
212 String generationDate = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm'Z'" ).format( new Date() );
Carsten Ziegelerccc30322015-03-03 10:48:44 +0000213 final Reporter reporter = new Processor();
214
215 final Info[] infos;
216 try
217 {
218 final Set<Info> infoSet = new Baseline( reporter, new DiffPluginImpl() )
219 .baseline( currentBundle, previousBundle, packageFilters );
220 infos = infoSet.toArray( new Info[infoSet.size()] );
221 Arrays.sort( infos, new InfoComparator() );
222 }
223 catch ( final Exception e )
224 {
225 throw new MojoExecutionException( "Impossible to calculate the baseline", e );
226 }
227 finally
228 {
229 closeJars( currentBundle, previousBundle );
230 }
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000231
232 try
233 {
Carsten Ziegelerccc30322015-03-03 10:48:44 +0000234 // go!
235 context = this.init(context);
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000236 startBaseline( context, generationDate, project.getArtifactId(), project.getVersion(), previousArtifact.getVersion() );
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000237
Carsten Ziegelerccc30322015-03-03 10:48:44 +0000238 for ( final Info info : infos )
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000239 {
240 DiffMessage diffMessage = null;
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000241
Carsten Ziegelerccc30322015-03-03 10:48:44 +0000242 if ( info.suggestedVersion != null )
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000243 {
Carsten Ziegelerccc30322015-03-03 10:48:44 +0000244 if ( info.newerVersion.compareTo( info.suggestedVersion ) > 0 )
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000245 {
246 diffMessage = new DiffMessage( "Excessive version increase", DiffMessage.Type.warning );
247 reporter.warning( "%s: %s; detected %s, suggested %s",
248 info.packageName, diffMessage, info.newerVersion, info.suggestedVersion );
249 }
Carsten Ziegelerccc30322015-03-03 10:48:44 +0000250 else if ( info.newerVersion.compareTo( info.suggestedVersion ) < 0 )
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000251 {
252 diffMessage = new DiffMessage( "Version increase required", DiffMessage.Type.error );
253 reporter.error( "%s: %s; detected %s, suggested %s",
254 info.packageName, diffMessage, info.newerVersion, info.suggestedVersion );
255 }
256 }
257
Carsten Ziegelerccc30322015-03-03 10:48:44 +0000258 switch ( info.packageDiff.getDelta() )
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000259 {
260 case UNCHANGED:
Carsten Ziegelerccc30322015-03-03 10:48:44 +0000261 if ( info.newerVersion.compareTo( info.suggestedVersion ) != 0 )
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000262 {
263 diffMessage = new DiffMessage( "Version has been increased but analysis detected no changes", DiffMessage.Type.warning );
264 reporter.warning( "%s: %s; detected %s, suggested %s",
265 info.packageName, diffMessage, info.newerVersion, info.suggestedVersion );
266 }
267 break;
268
269 case REMOVED:
270 diffMessage = new DiffMessage( "Package removed", DiffMessage.Type.info );
271 reporter.trace( "%s: %s ", info.packageName, diffMessage );
272 break;
273
274 case CHANGED:
275 case MICRO:
276 case MINOR:
277 case MAJOR:
278 case ADDED:
279 default:
280 // ok
281 break;
282 }
283
Carsten Ziegelerccc30322015-03-03 10:48:44 +0000284 startPackage( context,
285 info.mismatch,
286 info.packageName,
287 getShortDelta( info.packageDiff.getDelta() ),
288 StringUtils.lowerCase( String.valueOf( info.packageDiff.getDelta() ) ),
289 info.newerVersion,
290 info.olderVersion,
291 info.suggestedVersion,
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000292 diffMessage,
Carsten Ziegelerccc30322015-03-03 10:48:44 +0000293 info.attributes );
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000294
Carsten Ziegelerccc30322015-03-03 10:48:44 +0000295 if ( Delta.REMOVED != info.packageDiff.getDelta() )
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000296 {
Carsten Ziegelerccc30322015-03-03 10:48:44 +0000297 doPackageDiff( context, info.packageDiff );
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000298 }
299
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000300 endPackage(context);
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000301 }
302
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000303 endBaseline(context);
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000304 }
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000305 finally
306 {
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000307 this.close(context);
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000308 }
309
310 // check if it has to fail if some error has been detected
311
312 boolean fail = false;
313
314 if ( !reporter.isOk() )
315 {
316 for ( String errorMessage : reporter.getErrors() )
317 {
318 getLog().error( errorMessage );
319 }
320
321 if ( failOnError )
322 {
323 fail = true;
324 }
325 }
326
327 // check if it has to fail if some warning has been detected
328
329 if ( !reporter.getWarnings().isEmpty() )
330 {
331 for ( String warningMessage : reporter.getWarnings() )
332 {
333 getLog().warn( warningMessage );
334 }
335
336 if ( failOnWarning )
337 {
338 fail = true;
339 }
340 }
341
Chetan Mehrotraca03f072014-07-29 05:24:26 +0000342 getLog().info( String.format( "Baseline analysis complete, %s error(s), %s warning(s)",
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000343 reporter.getErrors().size(),
344 reporter.getWarnings().size() ) );
345
346 if ( fail )
347 {
348 throw new MojoFailureException( "Baseline failed, see generated report" );
349 }
350 }
351
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000352 private void doPackageDiff( Object context, Diff diff )
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000353 {
354 int depth = 1;
355
356 for ( Diff curDiff : diff.getChildren() )
357 {
358 if ( Delta.UNCHANGED != curDiff.getDelta() )
359 {
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000360 doDiff( context, curDiff, depth );
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000361 }
362 }
363 }
364
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000365 private void doDiff( Object context, Diff diff, int depth )
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000366 {
367 String type = StringUtils.lowerCase( String.valueOf( diff.getType() ) );
368 String shortDelta = getShortDelta( diff.getDelta() );
369 String delta = StringUtils.lowerCase( String.valueOf( diff.getDelta() ) );
370 String name = diff.getName();
371
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000372 startDiff( context, depth, type, name, delta, shortDelta );
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000373
374 for ( Diff curDiff : diff.getChildren() )
375 {
376 if ( Delta.UNCHANGED != curDiff.getDelta() )
377 {
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000378 doDiff( context, curDiff, depth + 1 );
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000379 }
380 }
381
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000382 endDiff( context, depth );
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000383 }
384
385 // extensions APIs
386
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000387 protected abstract Object init(final Object initialContext);
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000388
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000389 protected abstract void close(final Object context);
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000390
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000391 protected abstract void startBaseline( final Object context, String generationDate, String bundleName, String currentVersion, String previousVersion );
392
393 protected abstract void startPackage( final Object context,
394 boolean mismatch,
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000395 String name,
396 String shortDelta,
397 String delta,
Carsten Ziegelerccc30322015-03-03 10:48:44 +0000398 Version newerVersion,
399 Version olderVersion,
400 Version suggestedVersion,
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000401 DiffMessage diffMessage,
402 Map<String,String> attributes );
403
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000404 protected abstract void startDiff( final Object context,
405 int depth,
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000406 String type,
407 String name,
408 String delta,
409 String shortDelta );
410
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000411 protected abstract void endDiff( final Object context, int depth );
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000412
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000413 protected abstract void endPackage(final Object context);
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000414
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000415 protected abstract void endBaseline(final Object context);
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000416
417 // internals
418
419 private Jar getCurrentBundle()
420 throws MojoExecutionException
421 {
422 /*
423 * Resolving the aQute.bnd.osgi.Jar via the produced artifact rather than what is produced in the target/classes
424 * directory would make the Mojo working also in projects where the bundle-plugin is used just to generate the
425 * manifest file and the final jar is assembled via the jar-plugin
426 */
427 File currentBundle = new File( buildDirectory, getBundleName() );
428 if ( !currentBundle.exists() )
429 {
430 getLog().debug( "Produced bundle not found: " + currentBundle );
431 return null;
432 }
433
434 return openJar( currentBundle );
435 }
436
Carsten Ziegeler23ecafb2015-02-02 08:26:13 +0000437 private Artifact getPreviousArtifact()
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000438 throws MojoFailureException, MojoExecutionException
439 {
440 // Find the previous version JAR and resolve it, and it's dependencies
441 final VersionRange range;
442 try
443 {
444 range = VersionRange.createFromVersionSpec( comparisonVersion );
445 }
446 catch ( InvalidVersionSpecificationException e )
447 {
448 throw new MojoFailureException( "Invalid comparison version: " + e.getMessage() );
449 }
450
451 final Artifact previousArtifact;
452 try
453 {
454 previousArtifact =
Guillaume Nodet10dae652015-07-09 19:44:41 +0000455 factory.createDependencyArtifact( comparisonGroupId,
456 comparisonArtifactId,
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000457 range,
Guillaume Nodet10dae652015-07-09 19:44:41 +0000458 comparisonPackaging,
Carsten Ziegeler76e9dbc2014-08-21 09:58:12 +0000459 comparisonClassifier,
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000460 Artifact.SCOPE_COMPILE );
461
462 if ( !previousArtifact.getVersionRange().isSelectedVersionKnown( previousArtifact ) )
463 {
464 getLog().debug( "Searching for versions in range: " + previousArtifact.getVersionRange() );
465 @SuppressWarnings( "unchecked" )
466 // type is konwn
467 List<ArtifactVersion> availableVersions =
Carsten Ziegelerccc30322015-03-03 10:48:44 +0000468 metadataSource.retrieveAvailableVersions( previousArtifact, session.getLocalRepository(),
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000469 project.getRemoteArtifactRepositories() );
470 filterSnapshots( availableVersions );
471 ArtifactVersion version = range.matchVersion( availableVersions );
472 if ( version != null )
473 {
474 previousArtifact.selectVersion( version.toString() );
475 }
476 }
477 }
478 catch ( OverConstrainedVersionException ocve )
479 {
480 throw new MojoFailureException( "Invalid comparison version: " + ocve.getMessage() );
481 }
482 catch ( ArtifactMetadataRetrievalException amre )
483 {
484 throw new MojoExecutionException( "Error determining previous version: " + amre.getMessage(), amre );
485 }
486
487 if ( previousArtifact.getVersion() == null )
488 {
489 getLog().info( "Unable to find a previous version of the project in the repository" );
490 return null;
491 }
492
493 try
494 {
Carsten Ziegelerccc30322015-03-03 10:48:44 +0000495 resolver.resolve( previousArtifact, project.getRemoteArtifactRepositories(), session.getLocalRepository() );
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000496 }
497 catch ( ArtifactResolutionException are )
498 {
Carsten Ziegelerccc30322015-03-03 10:48:44 +0000499 throw new MojoExecutionException( "Artifact " + previousArtifact + " cannot be resolved : " + are.getMessage(), are );
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000500 }
501 catch ( ArtifactNotFoundException anfe )
502 {
503 throw new MojoExecutionException( "Artifact " + previousArtifact
504 + " does not exist on local/remote repositories", anfe );
505 }
506
Carsten Ziegeler23ecafb2015-02-02 08:26:13 +0000507 return previousArtifact;
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000508 }
509
510 private void filterSnapshots( List<ArtifactVersion> versions )
511 {
512 for ( Iterator<ArtifactVersion> versionIterator = versions.iterator(); versionIterator.hasNext(); )
513 {
514 ArtifactVersion version = versionIterator.next();
Guillaume Nodetb7f96682015-07-09 19:46:11 +0000515 if ( version.getQualifier().endsWith( "SNAPSHOT" ) )
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000516 {
517 versionIterator.remove();
518 }
519 }
520 }
521
Carsten Ziegelerccc30322015-03-03 10:48:44 +0000522 private static Jar openJar( final File file )
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000523 throws MojoExecutionException
524 {
525 try
526 {
527 return new Jar( file );
528 }
Carsten Ziegelerccc30322015-03-03 10:48:44 +0000529 catch ( final IOException e )
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000530 {
531 throw new MojoExecutionException( "An error occurred while opening JAR directory: " + file, e );
532 }
533 }
534
Carsten Ziegelerccc30322015-03-03 10:48:44 +0000535 private static void closeJars( final Jar...jars )
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000536 {
537 for ( Jar jar : jars )
538 {
539 jar.close();
540 }
541 }
542
543 private String getBundleName()
544 {
545 String extension;
546 try
547 {
548 extension = project.getArtifact().getArtifactHandler().getExtension();
549 }
550 catch ( Throwable e )
551 {
552 extension = project.getArtifact().getType();
553 }
554
555 if ( StringUtils.isEmpty( extension ) || "bundle".equals( extension ) || "pom".equals( extension ) )
556 {
557 extension = "jar"; // just in case maven gets confused
558 }
559
Carsten Ziegelere153f352014-08-21 11:49:00 +0000560 String classifier = this.comparisonClassifier != null ? this.comparisonClassifier : project.getArtifact().getClassifier();
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000561 if ( null != classifier && classifier.trim().length() > 0 )
562 {
563 return finalName + '-' + classifier + '.' + extension;
564 }
565
566 return finalName + '.' + extension;
567 }
568
569 private static String getShortDelta( Delta delta )
570 {
571 switch ( delta )
572 {
573 case ADDED:
574 return "+";
575
576 case CHANGED:
577 return "~";
578
579 case MAJOR:
580 return ">";
581
582 case MICRO:
583 return "0xB5";
584
585 case MINOR:
586 return "<";
587
588 case REMOVED:
589 return "-";
590
591 case UNCHANGED:
592 return " ";
593
594 default:
595 String deltaString = delta.toString();
596 return String.valueOf( deltaString.charAt( 0 ) );
597 }
598 }
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000599}