@@ -135,6 +135,18 @@ | |||
<artifactId>java-semver</artifactId> | |||
<version>0.10.2</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.vdurmont</groupId> | |||
<artifactId>semver4j</artifactId> | |||
<version>3.1.0</version> | |||
<optional>true</optional> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.apache.maven</groupId> | |||
<artifactId>maven-artifact</artifactId> | |||
<version>3.8.1</version> | |||
<optional>true</optional> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.ow2.asm</groupId> | |||
<artifactId>asm</artifactId> |
@@ -36,6 +36,16 @@ module org.pf4j { | |||
// automatic module name in their MANIFEST file. | |||
requires com.github.zafarkhaja.semver; | |||
// The semver4j library currently does not provide a module. | |||
// Maybe we should send them a pull request, that at least they provide an | |||
// automatic module name in their MANIFEST file. | |||
requires static semver4j; | |||
// The maven-artifact library currently does not provide a module. | |||
// Maybe we should send them a pull request, that at least they provide an | |||
// automatic module name in their MANIFEST file. | |||
requires static maven.artifact; | |||
// Maybe we should reconsider the package hierarchy, that only classes are | |||
// exported, which are required by 3rd party developers. | |||
exports org.pf4j; |
@@ -0,0 +1,70 @@ | |||
package org.pf4j; | |||
import org.apache.maven.artifact.versioning.DefaultArtifactVersion; | |||
import org.apache.maven.artifact.versioning.VersionRange; | |||
import org.pf4j.util.StringUtils; | |||
/** | |||
* Implementation for {@link VersionManager}. | |||
* This implementation uses Maven . Before using it you have to include the optional dependency maven-artifact | |||
* | |||
* @author Wolfram Haussig | |||
*/ | |||
public class MavenVersionManager implements VersionManager { | |||
/** | |||
* parses a version with the current parser type | |||
* @param version | |||
*/ | |||
protected DefaultArtifactVersion parseVersion(String version) { | |||
if (version == null) | |||
return new DefaultArtifactVersion(""); | |||
return new DefaultArtifactVersion(version); | |||
} | |||
/** | |||
* Checks if a version satisfies the specified SemVer {@link Expression} string. | |||
* If the constraint is empty or null then the method returns true. | |||
* Constraint examples: {@code >2.0.0} (simple), {@code "1.1.1 || 1.2.3 - 2.0.0"} (range). | |||
* See https://github.com/vdurmont/semver4j#requirements for more info. | |||
* | |||
* @param version | |||
* @param constraint | |||
* @return | |||
*/ | |||
@Override | |||
public boolean checkVersionConstraint(String version, String constraint) { | |||
if (StringUtils.isNullOrEmpty(constraint) || "*".equals(constraint)) { | |||
return true; | |||
} | |||
try { | |||
return VersionRange.createFromVersionSpec(constraint).containsVersion(parseVersion(version)); | |||
} catch (org.apache.maven.artifact.versioning.InvalidVersionSpecificationException e) { | |||
//throw custom InvalidVersionSpecificationException as the interface does not declare an exception to be thrown | |||
//so we need a RuntimeException here | |||
throw new InvalidVersionSpecificationException("failed to parse constraint as maven version range: " + constraint, e); | |||
} | |||
} | |||
@Override | |||
public int compareVersions(String v1, String v2) { | |||
return parseVersion(v1).compareTo(parseVersion(v2)); | |||
} | |||
@Override | |||
public boolean isStable(String version) { | |||
DefaultArtifactVersion av = parseVersion(version); | |||
return av.getQualifier() == null || !"SNAPSHOT".equals(av.getQualifier()); | |||
} | |||
public static class InvalidVersionSpecificationException extends RuntimeException | |||
{ | |||
private static final long serialVersionUID = 8636081416771885576L; | |||
public InvalidVersionSpecificationException( String message, Throwable cause ) | |||
{ | |||
super( message, cause); | |||
} | |||
} | |||
} |
@@ -0,0 +1,71 @@ | |||
package org.pf4j; | |||
import org.pf4j.util.StringUtils; | |||
import com.vdurmont.semver4j.Semver; | |||
import com.vdurmont.semver4j.Semver.SemverType; | |||
/** | |||
* Implementation for {@link VersionManager}. | |||
* This implementation uses semver4j (a Java implementation of the SemVer Specification). Before using it you have to include the optional | |||
* dependency semver4j | |||
* | |||
* @author Wolfram Haussig | |||
*/ | |||
public class Semver4jVersionManager implements VersionManager { | |||
/** | |||
* the parser type of the version - see https://github.com/vdurmont/semver4j#the-semver-object for details | |||
*/ | |||
private SemverType type; | |||
/** | |||
* creates a version manager with the given parser type | |||
* @param type | |||
*/ | |||
public Semver4jVersionManager(SemverType type) { | |||
this.type = type; | |||
} | |||
/** | |||
* creates a version manager with the NPM parser type which supports ranges | |||
*/ | |||
public Semver4jVersionManager() { | |||
this(SemverType.NPM); | |||
} | |||
/** | |||
* parses a version with the current parser type | |||
* @param version | |||
*/ | |||
protected Semver parseVersion(String version) { | |||
if (version == null) | |||
return new Semver("", type); | |||
return new Semver(version, type); | |||
} | |||
/** | |||
* Checks if a version satisfies the specified SemVer {@link Expression} string. | |||
* If the constraint is empty or null then the method returns true. | |||
* Constraint examples: {@code >2.0.0} (simple), {@code "1.1.1 || 1.2.3 - 2.0.0"} (range). | |||
* See https://github.com/vdurmont/semver4j#requirements for more info. | |||
* | |||
* @param version | |||
* @param constraint | |||
* @return | |||
*/ | |||
@Override | |||
public boolean checkVersionConstraint(String version, String constraint) { | |||
return StringUtils.isNullOrEmpty(constraint) || "*".equals(constraint) || parseVersion(version).satisfies(constraint); | |||
} | |||
@Override | |||
public int compareVersions(String v1, String v2) { | |||
return parseVersion(v1).compareTo(parseVersion(v2)); | |||
} | |||
@Override | |||
public boolean isStable(String version) { | |||
return parseVersion(version).isStable(); | |||
} | |||
} |
@@ -42,5 +42,14 @@ public interface VersionManager { | |||
* @param v2 the second version to compare | |||
*/ | |||
int compareVersions(String v1, String v2); | |||
/** | |||
* Checks that the given version is stable | |||
* @param version | |||
* @return | |||
*/ | |||
default boolean isStable(String version) { | |||
return true; | |||
} | |||
} |
@@ -16,6 +16,8 @@ | |||
package org.pf4j; | |||
import com.github.zafarkhaja.semver.ParseException; | |||
import com.github.zafarkhaja.semver.expr.LexerException; | |||
import org.junit.jupiter.api.BeforeEach; | |||
import org.junit.jupiter.api.Test; | |||
@@ -56,5 +58,11 @@ public class DefaultVersionManagerTest { | |||
public void compareVersions() { | |||
assertTrue(versionManager.compareVersions("1.1.0", "1.0.0") > 0); | |||
} | |||
@Test | |||
public void unsupportedConstraint() { | |||
assertTrue(versionManager.compareVersions("1.0.0-SNAPSHOT", "1.0.0-SNAPSHOT") >= 0); | |||
assertThrows(LexerException.class, () -> versionManager.checkVersionConstraint("1.0.0", ">=1.0.0-SNAPSHOT")); | |||
} | |||
} |
@@ -0,0 +1,73 @@ | |||
/* | |||
* Copyright (C) 2012-present the original author or authors. | |||
* | |||
* Licensed 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 | |||
* | |||
* http://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.pf4j; | |||
import org.junit.jupiter.api.BeforeEach; | |||
import org.junit.jupiter.api.Test; | |||
import static org.junit.jupiter.api.Assertions.assertFalse; | |||
import static org.junit.jupiter.api.Assertions.assertTrue; | |||
/** | |||
* @author Wolfram Haussig | |||
*/ | |||
public class MavenVersionManagerTest { | |||
private VersionManager versionManager; | |||
@BeforeEach | |||
public void init() { | |||
versionManager = new MavenVersionManager(); | |||
} | |||
@Test | |||
public void checkVersionConstraint() { | |||
assertFalse(versionManager.checkVersionConstraint("1.4.3", "(2.0.0,]")); // simple | |||
// range | |||
assertFalse(versionManager.checkVersionConstraint("1.3.9", "[1.4.0,1.6.0)")); | |||
assertTrue(versionManager.checkVersionConstraint("1.4.0", "[1.4.0,1.6.0)")); | |||
assertTrue(versionManager.checkVersionConstraint("1.4.3", "[1.4.0,1.6.0)")); | |||
assertFalse(versionManager.checkVersionConstraint("1.6.0", "[1.4.0,1.6.0)")); | |||
assertTrue(versionManager.checkVersionConstraint("undefined", "*")); | |||
} | |||
@Test | |||
public void nullOrEmptyVersion() { | |||
assertFalse(versionManager.checkVersionConstraint(null, "(2.0.0,]")); | |||
} | |||
@Test | |||
public void invalidVersion() { | |||
assertFalse(versionManager.checkVersionConstraint("1.0", "(2.0.0,]")); | |||
} | |||
@Test | |||
public void compareVersions() { | |||
assertTrue(versionManager.compareVersions("1.1.0", "1.0.0") > 0); | |||
} | |||
@Test | |||
public void isStable() { | |||
assertTrue(versionManager.isStable("1.1.0")); | |||
assertFalse(versionManager.isStable("1.1.0-SNAPSHOT")); | |||
} | |||
@Test | |||
public void supportsSnapshotVersions() { | |||
assertTrue(versionManager.compareVersions("1.0.0-SNAPSHOT", "1.0.0-SNAPSHOT") >= 0); | |||
assertTrue(versionManager.checkVersionConstraint("1.0.0", "[1.0.0-SNAPSHOT,]")); | |||
} | |||
} |
@@ -0,0 +1,76 @@ | |||
/* | |||
* Copyright (C) 2012-present the original author or authors. | |||
* | |||
* Licensed 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 | |||
* | |||
* http://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.pf4j; | |||
import org.junit.jupiter.api.BeforeEach; | |||
import org.junit.jupiter.api.Test; | |||
import com.vdurmont.semver4j.SemverException; | |||
import static org.junit.jupiter.api.Assertions.assertFalse; | |||
import static org.junit.jupiter.api.Assertions.assertThrows; | |||
import static org.junit.jupiter.api.Assertions.assertTrue; | |||
/** | |||
* @author Wolfram Haussig | |||
*/ | |||
public class Semver4jVersionManagerTest { | |||
private VersionManager versionManager; | |||
@BeforeEach | |||
public void init() { | |||
versionManager = new Semver4jVersionManager(); | |||
} | |||
@Test | |||
public void checkVersionConstraint() { | |||
assertFalse(versionManager.checkVersionConstraint("1.4.3", ">2.0.0")); // simple | |||
// range | |||
assertFalse(versionManager.checkVersionConstraint("1.3.9", ">=1.4.0 <1.6.0")); | |||
assertTrue(versionManager.checkVersionConstraint("1.4.0", ">=1.4.0 <1.6.0")); | |||
assertTrue(versionManager.checkVersionConstraint("1.4.3", ">=1.4.0 <1.6.0")); | |||
assertFalse(versionManager.checkVersionConstraint("1.6.0", ">=1.4.0 <1.6.0")); | |||
assertTrue(versionManager.checkVersionConstraint("undefined", "*")); | |||
} | |||
@Test | |||
public void nullOrEmptyVersion() { | |||
assertThrows(SemverException.class, () -> versionManager.checkVersionConstraint(null, ">2.0.0")); | |||
} | |||
@Test | |||
public void invalidVersion() { | |||
assertFalse(versionManager.checkVersionConstraint("1.0", ">2.0.0")); | |||
} | |||
@Test | |||
public void compareVersions() { | |||
assertTrue(versionManager.compareVersions("1.1.0", "1.0.0") > 0); | |||
} | |||
@Test | |||
public void isStable() { | |||
assertTrue(versionManager.isStable("1.1.0")); | |||
assertFalse(versionManager.isStable("1.1.0-SNAPSHOT")); | |||
} | |||
@Test | |||
public void supportsSnapshotVersions() { | |||
assertTrue(versionManager.compareVersions("1.0.0-SNAPSHOT", "1.0.0-SNAPSHOT") >= 0); | |||
assertTrue(versionManager.checkVersionConstraint("1.0.0", ">=1.0.0-SNAPSHOT")); | |||
} | |||
} |