src/java/org/apache/ivy/plugins/version/MavenTimedSnapshotVersionMatcher.java (76 lines of code) (raw):
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.ivy.plugins.version;
import org.apache.ivy.core.module.id.ModuleRevisionId;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static org.apache.ivy.util.StringUtils.isNullOrEmpty;
/**
* A {@link VersionMatcher} which understands {@code Maven timestamped snapshots}.
*/
public class MavenTimedSnapshotVersionMatcher extends AbstractVersionMatcher {
private static final String SNAPSHOT_SUFFIX = "-SNAPSHOT";
// The timestamped snapshot pattern that Maven uses
private static final Pattern M2_TIMESTAMPED_SNAPSHOT_REV_PATTERN = Pattern.compile("^(.*)-([0-9]{8}.[0-9]{6})-([0-9]+)$");
public MavenTimedSnapshotVersionMatcher() {
super("maven-timed-snapshot");
}
@Override
public boolean isDynamic(final ModuleRevisionId askedMrid) {
if (askedMrid == null) {
return false;
}
// we consider only timestamped snapshots as dynamic, since unlike regular snapshots,
// a timestamped snapshot version of the form x.y.z-<timestamped-part> represents the real
// x.y.z-SNAPSHOT version
final Matcher snapshotPatternMatcher = M2_TIMESTAMPED_SNAPSHOT_REV_PATTERN.matcher(askedMrid.getRevision());
return snapshotPatternMatcher.matches();
}
@Override
public boolean accept(final ModuleRevisionId askedMrid, final ModuleRevisionId foundMrid) {
if (askedMrid == null || foundMrid == null) {
return false;
}
final MavenSnapshotRevision askedSnapshotVersion = computeIfSnapshot(askedMrid.getRevision());
if (askedSnapshotVersion == null) {
// this isn't a snapshot, so we aren't interested in it
return false;
}
// this version matcher only comes into picture if we have been asked to deal with a
// timestamped snapshot. In other words, if the asked version isn't a timestamped snapshot,
// then we don't accept it
if (!askedSnapshotVersion.isTimestampedSnapshot()) {
return false;
}
final MavenSnapshotRevision foundSnapshotVersion = computeIfSnapshot(foundMrid.getRevision());
if (foundSnapshotVersion == null) {
// this isn't a snapshot, so we aren't interested in it
return false;
}
// we compare the base revisions of both these snapshot to see if they are the same revision
// and if they are then we accept the "found" MRID for the "asked" MRID
return askedSnapshotVersion.baseRevision.equals(foundSnapshotVersion.baseRevision);
}
/**
* Parses the passed {@code revision} and returns a {@link MavenSnapshotRevision}, representing
* that {@code revision}, if it is either a regular snapshot (for example: 1.0.2-SNAPSHOT) or a
* timestamped snapshot (for example: 1.0.2-20100925.223013-19).
* If the passed {@code revision} isn't a snapshot revision, then this method returns null
*
* @param revision The revision to parse
* @return MavenSnapshotRevision
*/
public static MavenSnapshotRevision computeIfSnapshot(final String revision) {
if (isNullOrEmpty(revision)) {
return null;
}
final boolean regularSnapshot = revision.endsWith(SNAPSHOT_SUFFIX);
final Matcher snapshotPatternMatcher = M2_TIMESTAMPED_SNAPSHOT_REV_PATTERN.matcher(revision);
final boolean timestampedSnaphost = snapshotPatternMatcher.matches();
if (!regularSnapshot && !timestampedSnaphost) {
// neither a regular snapshot nor a timestamped snapshot
return null;
}
// the revision is now identified as a snapshot (either a regular one or a timestamped one)
return timestampedSnaphost ? new MavenSnapshotRevision(true, revision, snapshotPatternMatcher.group(1))
: new MavenSnapshotRevision(false, revision, revision.substring(0, revision.indexOf(SNAPSHOT_SUFFIX)));
}
/**
* Represents a Maven 2 snapshot version, which is either a regular snapshot
* (for example: 1.0.2-SNAPSHOT) or a timestamped snapshot (for example:
* 1.0.2-20100925.223013-19)
*/
public static final class MavenSnapshotRevision {
private final boolean timedsnapshot;
private final String wholeRevision;
private final String baseRevision;
private MavenSnapshotRevision(final boolean timedsnapshot, final String wholeRevision, final String baseRevision) {
if (wholeRevision == null) {
throw new IllegalArgumentException("Revision, of a Maven snapshot, cannot be null");
}
if (baseRevision == null) {
throw new IllegalArgumentException("Base revision, of a Maven snapshot revision, cannot be null");
}
this.timedsnapshot = timedsnapshot;
this.wholeRevision = wholeRevision;
this.baseRevision = baseRevision;
}
/**
* Returns true if this {@link MavenSnapshotRevision} represents a timestamped snapshot
* version. Else returns false.
*
* @return boolean
*/
public boolean isTimestampedSnapshot() {
return this.timedsnapshot;
}
/**
* Returns the "base" revision that this {@link MavenSnapshotRevision} represents. For
* example, for the regular snapshot revision {@code 1.2.3-SNAPSHOT}, the base revision
* is {@code 1.2.3}. Similarly for timestamped snapshot version
* {@code 1.0.2-20100925.223013-19}, the base revision is {@code 1.0.2}
*
* @return String
*/
public String getBaseRevision() {
return this.baseRevision;
}
/**
* Returns the complete/whole revision this {@link MavenSnapshotRevision} represents. For
* example, if this {@link MavenSnapshotRevision} represents a regular snapshot
* {@code 1.3.4-SNAPSHOT} revision then this method returns {@code 1.3.4-SNAPSHOT}.
* Similarly, if this {@link MavenSnapshotRevision} represents a timestamped snapshot
* {@code 1.0.2-20100925.223013-19} revision, then this method returns
* {@code 1.0.2-20100925.223013-19}
*
* @return String
*/
public String getRevision() {
return this.wholeRevision;
}
}
}