You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2017/06/30 14:02:59 UTC
[11/27] brooklyn-server git commit: add routines to convert
brooklyn/osgi versions
add routines to convert brooklyn/osgi versions
and bundle finder supports either, and does the conversion for you
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/ed98e27e
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/ed98e27e
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/ed98e27e
Branch: refs/heads/master
Commit: ed98e27e934ddf54d6c1c80b4a61afaab1225e47
Parents: 45cb10a
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Wed Jun 21 18:26:43 2017 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Wed Jun 21 18:26:43 2017 +0100
----------------------------------------------------------------------
.../apache/brooklyn/core/BrooklynVersion.java | 5 +
.../catalog/internal/BasicBrooklynCatalog.java | 4 +-
.../brooklyn/util/core/ClassLoaderUtils.java | 5 +-
.../apache/brooklyn/util/core/osgi/Osgis.java | 18 +++-
.../core/typereg/RegisteredTypeNamingTest.java | 6 +-
.../util/core/ClassLoaderUtilsTest.java | 2 +-
.../core/xstream/OsgiClassPrefixerTest.java | 2 +-
.../apache/brooklyn/util/osgi/OsgiUtils.java | 4 +
.../util/text/BrooklynVersionSyntax.java | 103 ++++++++++++++++++-
.../brooklyn/util/osgi/OsgiUtilsTest.java | 3 +
.../brooklyn/util/osgi/VersionedNameTest.java | 3 +-
.../util/text/BrooklynVersionSyntaxTest.java | 98 ++++++++++++++++++
12 files changed, 239 insertions(+), 14 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ed98e27e/core/src/main/java/org/apache/brooklyn/core/BrooklynVersion.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/BrooklynVersion.java b/core/src/main/java/org/apache/brooklyn/core/BrooklynVersion.java
index 161eff0..f28d3fb 100644
--- a/core/src/main/java/org/apache/brooklyn/core/BrooklynVersion.java
+++ b/core/src/main/java/org/apache/brooklyn/core/BrooklynVersion.java
@@ -45,6 +45,7 @@ import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.guava.Maybe;
import org.apache.brooklyn.util.osgi.OsgiUtil;
import org.apache.brooklyn.util.stream.Streams;
+import org.apache.brooklyn.util.text.BrooklynVersionSyntax;
import org.apache.brooklyn.util.text.Strings;
import org.apache.brooklyn.util.text.VersionComparator;
import org.osgi.framework.Bundle;
@@ -458,4 +459,8 @@ public class BrooklynVersion implements BrooklynVersionService {
return true;
}
}
+
+ public static String getOsgiVersion() {
+ return BrooklynVersionSyntax.toValidOsgiVersion(get());
+ }
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ed98e27e/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
index 006d3e8..b0d028f 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
@@ -59,8 +59,8 @@ import org.apache.brooklyn.util.guava.Maybe;
import org.apache.brooklyn.util.javalang.AggregateClassLoader;
import org.apache.brooklyn.util.javalang.JavaClassNames;
import org.apache.brooklyn.util.javalang.LoadedClassLoader;
-import org.apache.brooklyn.util.osgi.OsgiUtils;
import org.apache.brooklyn.util.osgi.VersionedName;
+import org.apache.brooklyn.util.text.BrooklynVersionSyntax;
import org.apache.brooklyn.util.text.Strings;
import org.apache.brooklyn.util.time.Duration;
import org.apache.brooklyn.util.time.Time;
@@ -448,7 +448,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
if (Strings.isBlank(version)) {
throw new IllegalStateException("Catalog BOM must define version if bundle is defined");
}
- return new VersionedName(bundle, Version.valueOf(OsgiUtils.toOsgiVersion(version)));
+ return new VersionedName(bundle, Version.valueOf(BrooklynVersionSyntax.toValidOsgiVersion(version)));
}
private void collectCatalogItems(String yaml, List<CatalogItemDtoAbstract<?, ?>> result, Map<?, ?> parentMeta) {
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ed98e27e/core/src/main/java/org/apache/brooklyn/util/core/ClassLoaderUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/ClassLoaderUtils.java b/core/src/main/java/org/apache/brooklyn/util/core/ClassLoaderUtils.java
index a6be53d..8d5cf0f 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/ClassLoaderUtils.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/ClassLoaderUtils.java
@@ -40,6 +40,7 @@ import org.apache.brooklyn.util.core.osgi.Osgis;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.guava.Maybe;
import org.apache.brooklyn.util.osgi.OsgiUtils;
+import org.apache.brooklyn.util.text.BrooklynVersionSyntax;
import org.apache.brooklyn.util.text.Strings;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
@@ -65,7 +66,7 @@ public class ClassLoaderUtils {
static final String WHITE_LIST_KEY = "org.apache.brooklyn.classloader.fallback.bundles";
static final String CLASS_NAME_DELIMITER = ":";
private static final String WHITE_LIST_DEFAULT =
- "org\\.apache\\.brooklyn\\..*:" + OsgiUtils.toOsgiVersion(BrooklynVersion.get());
+ "org\\.apache\\.brooklyn\\..*:" + BrooklynVersion.getOsgiVersion();
// Class.forName gets the class loader from the calling class.
// We don't have access to the same reflection API so need to pass it explicitly.
@@ -307,7 +308,7 @@ public class ClassLoaderUtils {
if (framework != null) {
Maybe<Bundle> bundle = Osgis.bundleFinder(framework)
.symbolicName(symbolicName)
- .version(OsgiUtils.toOsgiVersion(version))
+ .version(version)
.find();
if (bundle.isAbsent()) {
throw new IllegalStateException("Bundle " + toBundleString(symbolicName, version)
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ed98e27e/core/src/main/java/org/apache/brooklyn/util/core/osgi/Osgis.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/osgi/Osgis.java b/core/src/main/java/org/apache/brooklyn/util/core/osgi/Osgis.java
index a33b446..d46f098 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/osgi/Osgis.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/osgi/Osgis.java
@@ -39,6 +39,7 @@ import org.apache.brooklyn.util.net.Urls;
import org.apache.brooklyn.util.os.Os;
import org.apache.brooklyn.util.osgi.OsgiUtils;
import org.apache.brooklyn.util.stream.Streams;
+import org.apache.brooklyn.util.text.BrooklynVersionSyntax;
import org.apache.brooklyn.util.text.Strings;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
@@ -98,6 +99,7 @@ public class Osgis {
return this;
}
+ /** Accepts non-osgi version syntax, converting to OSGi version syntax */
public BundleFinder version(String version) {
this.version = version;
return this;
@@ -174,12 +176,26 @@ public class Osgis {
}
/** Finds all matching bundles, in decreasing version order. */
+ @SuppressWarnings("deprecation")
public List<Bundle> findAll() {
boolean urlMatched = false;
List<Bundle> result = MutableList.of();
+ String v=null, vDep = null;
+ if (version!=null) {
+ v = BrooklynVersionSyntax.toValidOsgiVersion(version);
+ vDep = OsgiUtils.toOsgiVersion(version);
+ }
for (Bundle b: framework.getBundleContext().getBundles()) {
if (symbolicName!=null && !symbolicName.equals(b.getSymbolicName())) continue;
- if (version!=null && !Version.parseVersion(version).equals(b.getVersion())) continue;
+ if (version!=null) {
+ String bv = b.getVersion().toString();
+ if (!v.equals(bv)) {
+ if (!vDep.equals(bv)) {
+ continue;
+ }
+ LOG.warn("Legacy inferred OSGi version string '"+vDep+"' found to match "+symbolicName+":"+version+"; switch to '"+v+"' format to avoid issues with deprecated version syntax");
+ }
+ }
if (!Predicates.and(predicates).apply(b)) continue;
// check url last, because if it isn't mandatory we should only clear if we find a url
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ed98e27e/core/src/test/java/org/apache/brooklyn/core/typereg/RegisteredTypeNamingTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/typereg/RegisteredTypeNamingTest.java b/core/src/test/java/org/apache/brooklyn/core/typereg/RegisteredTypeNamingTest.java
index ec07c8a..3fc8dc3 100644
--- a/core/src/test/java/org/apache/brooklyn/core/typereg/RegisteredTypeNamingTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/typereg/RegisteredTypeNamingTest.java
@@ -88,9 +88,5 @@ public class RegisteredTypeNamingTest {
Assert.assertEquals(RegisteredTypeNaming.isValidOsgiTypeColonVersion(candidate), isOsgi, "osgi name:version '"+candidate+"'");
Assert.assertEquals(RegisteredTypeNaming.isGoodBrooklynTypeColonVersion(candidate), isGood, "good name:version '"+candidate+"'");
}
-
- public void testConvertToOsgiVersion() {
- Assert.assertEquals(OsgiUtils.toOsgiVersion("1-foo"), "1.0.0.foo");
- Assert.assertEquals(OsgiUtils.toOsgiVersion("1"), "1.0.0");
- }
+
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ed98e27e/core/src/test/java/org/apache/brooklyn/util/core/ClassLoaderUtilsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/util/core/ClassLoaderUtilsTest.java b/core/src/test/java/org/apache/brooklyn/util/core/ClassLoaderUtilsTest.java
index a9ea938..1477798 100644
--- a/core/src/test/java/org/apache/brooklyn/util/core/ClassLoaderUtilsTest.java
+++ b/core/src/test/java/org/apache/brooklyn/util/core/ClassLoaderUtilsTest.java
@@ -283,7 +283,7 @@ public class ClassLoaderUtilsTest {
Entity.class.getName());
new ClassLoaderUtils(this, mgmt).loadClass(
"org.apache.brooklyn.api",
- OsgiUtils.toOsgiVersion(BrooklynVersion.get()),
+ BrooklynVersion.getOsgiVersion(),
Entity.class.getName());
try {
new ClassLoaderUtils(this, mgmt).loadClass(
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ed98e27e/core/src/test/java/org/apache/brooklyn/util/core/xstream/OsgiClassPrefixerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/util/core/xstream/OsgiClassPrefixerTest.java b/core/src/test/java/org/apache/brooklyn/util/core/xstream/OsgiClassPrefixerTest.java
index aa2e659..b1d4278 100644
--- a/core/src/test/java/org/apache/brooklyn/util/core/xstream/OsgiClassPrefixerTest.java
+++ b/core/src/test/java/org/apache/brooklyn/util/core/xstream/OsgiClassPrefixerTest.java
@@ -62,7 +62,7 @@ public class OsgiClassPrefixerTest {
public void testGetPrefixWithWhitelistedBundle() throws Exception {
final Bundle bundle = Mockito.mock(Bundle.class);
Mockito.when(bundle.getSymbolicName()).thenReturn("org.apache.brooklyn.my-bundle");
- Mockito.when(bundle.getVersion()).thenReturn(Version.valueOf(OsgiUtils.toOsgiVersion(BrooklynVersion.get())));
+ Mockito.when(bundle.getVersion()).thenReturn(Version.valueOf(BrooklynVersion.getOsgiVersion()));
Function<Class<?>, Optional<Bundle>> bundleRetriever = new Function<Class<?>, Optional<Bundle>>() {
@Override public Optional<Bundle> apply(Class<?> input) {
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ed98e27e/utils/common/src/main/java/org/apache/brooklyn/util/osgi/OsgiUtils.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/osgi/OsgiUtils.java b/utils/common/src/main/java/org/apache/brooklyn/util/osgi/OsgiUtils.java
index df41686..1fe07f5 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/osgi/OsgiUtils.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/osgi/OsgiUtils.java
@@ -25,6 +25,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.brooklyn.util.guava.Maybe;
+import org.apache.brooklyn.util.text.BrooklynVersionSyntax;
import org.apache.brooklyn.util.text.Strings;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
@@ -101,6 +102,9 @@ public class OsgiUtils {
return Maybe.of(new VersionedName(parts[0], v));
}
+ /** @deprecated since 0.12.0 use {@link BrooklynVersionSyntax#toValidOsgiVersion(String)};
+ * but note it has slightly different semantics in some odd cases, e.g. this maps "1x" to "0.0.0.1x" whereas
+ * the new method maps to "1.0.0.x" */
public static String toOsgiVersion(String version) {
if (version != null) {
return DefaultMaven2OsgiConverter.cleanupVersion(version);
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ed98e27e/utils/common/src/main/java/org/apache/brooklyn/util/text/BrooklynVersionSyntax.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/text/BrooklynVersionSyntax.java b/utils/common/src/main/java/org/apache/brooklyn/util/text/BrooklynVersionSyntax.java
index 9a59d11..63c69e1 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/text/BrooklynVersionSyntax.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/text/BrooklynVersionSyntax.java
@@ -18,11 +18,16 @@
*/
package org.apache.brooklyn.util.text;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.google.common.base.Preconditions;
+
/** Utilities for parsing and working with versions following the recommended Brooklyn scheme,
* following <code>major.minor.patch-qualifier</code> syntax,
* with support for mapping to OSGi.
* <p>
- * See {@link VersionComparator} and its tests for examples.
+ * See tests for examples, {@link VersionComparator} for more notes, and its tests for more examples.
*/
public class BrooklynVersionSyntax {
@@ -84,4 +89,100 @@ public class BrooklynVersionSyntax {
return candidate!=null && candidate.matches(VALID_OSGI_VERSION_REGEX);
}
+ /** Creates a string satisfying {@link #isValidOsgiVersion(String)} based on the input.
+ * For input satisfying {@link #isGoodBrooklynVersion(String)} the only change will be in the qualifer separator
+ * (from "-" to ".") and making any "0" minor/patch token explicit (so "1-x" becomes "1.0.0.x"),
+ * and the change can be reversed using {@link #toGoodBrooklynVersion(String)} (modulo insertion of "0"'s for minor/patch numbers if missing).
+ * For input satisfying {@link #isValidOsgiVersion(String)}, the only change will be insertions of 0 for minor/patch.
+ * Precise behaviour for other input is not guaranteed but callers can expect output which resembles the input,
+ * with any major/minor/patch string at the front preserved and internal contiguous alphanumeric sequences preserved. */
+ public static String toValidOsgiVersion(String input) {
+ Preconditions.checkNotNull(input);
+ return toGoodVersion(input, ".", true);
+ /* Note Maven has and used: DefaultMaven2OsgiConverter
+ * from https://github.com/apache/felix/blob/trunk/tools/maven-bundle-plugin/src/main/java/org/apache/maven/shared/osgi/DefaultMaven2OsgiConverter.java
+ * but it (a) is more complicated, and (b) doesn't aggressively find numbers e.g. "1beta" goes to "0.0.0.1beta" instead of "1.0.0.beta"
+ */
+ }
+
+ /** Creates a string satisfying {@link #isGoodBrooklynVersion(String)} based on the input.
+ * For input satisfying {@link #isGoodBrooklynVersion(String)} the input will be returned unchanged.
+ * For input satisfying {@link #isValidOsgiVersion(String)} the qualifier separator will be changed to "-",
+ * and {@link #toValidOsgiVersion(String)} can be used to reverse the input (modulo insertion of "0"'s for minor/patch numbers if missing).
+ * Precise behaviour for other input is not guaranteed but callers can expect output which resembles the input,
+ * with any major/minor/patch string at the front preserved and internal contiguous alphanumeric sequences preserved. */
+ public static String toGoodBrooklynVersion(String input) {
+ return toGoodVersion(input, "-", false);
+ }
+
+ private static String toGoodVersion(String input, String qualifierSeparator, boolean requireMinorAndPatch) {
+ Preconditions.checkNotNull(input);
+ final String FUZZY_REGEX =
+ "(" + NUMBER + "(" + "\\." + NUMBER + "(" + "\\." + NUMBER + ")?)?)?" +
+ "(" + ".*)";
+ Matcher m = Pattern.compile(FUZZY_REGEX).matcher(input);
+ if (!m.matches()) {
+ throw new IllegalStateException("fuzzy matcher should match anything: '"+input+"'"); // sanity check - shouldn't happen
+ }
+ StringBuilder result = new StringBuilder();
+ if (Strings.isEmpty(m.group(1))) {
+ result.append("0.0.0");
+ } else {
+ result.append(m.group(1));
+ if (requireMinorAndPatch) {
+ if (Strings.isEmpty(m.group(2))) {
+ result.append(".0");
+ }
+ if (Strings.isEmpty(m.group(3))) {
+ result.append(".0");
+ }
+ }
+ }
+ String q = m.group(4);
+ if (Strings.isNonEmpty(q)) {
+ boolean collapsedUnsupported = false;
+ boolean starting = true;
+ result.append(qualifierSeparator);
+ for (int i=0; i<q.length(); i++) {
+ char c = q.charAt(i);
+ boolean include;
+ boolean unsupported = false;
+ if (starting) {
+ // treat first char as separator char unless it is a letter/number
+ include = ('A' <= c && 'Z' >= c) || ('a' <= c && 'z' >= c) || ('0' <= c && '9' >= c);
+ starting = false;
+ if (!include) {
+ if (c=='-' || c=='_' || c=='.') {
+ // treat these as separator chars, and drop them
+ if (q.length()==1) {
+ // unless there are no other chars (e.g. version "1." becomes "1-_"
+ unsupported = true;
+ }
+ } else {
+ // treat other chars as unsupported
+ unsupported = true;
+ }
+ }
+ } else {
+ include = ('A' <= c && 'Z' >= c) || ('a' <= c && 'z' >= c) || ('0' <= c && '9' >= c) || c=='-' || c=='_';
+ if (!include) {
+ // treat as unsupported, unless we've collapsed
+ if (!collapsedUnsupported) {
+ unsupported = true;
+ }
+ }
+ }
+ if (include) {
+ result.append(c);
+ collapsedUnsupported = false;
+ } else if (unsupported) {
+ // stick a "_" in for unsupported chars
+ result.append('_');
+ collapsedUnsupported = true;
+ }
+ }
+ }
+ return result.toString();
+ }
+
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ed98e27e/utils/common/src/test/java/org/apache/brooklyn/util/osgi/OsgiUtilsTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/osgi/OsgiUtilsTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/osgi/OsgiUtilsTest.java
index e41b00a..7a8550e 100644
--- a/utils/common/src/test/java/org/apache/brooklyn/util/osgi/OsgiUtilsTest.java
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/osgi/OsgiUtilsTest.java
@@ -21,6 +21,8 @@ import org.testng.annotations.Test;
public class OsgiUtilsTest {
+ // TODO other utils tests ... or maybe other tests in this package are sufficient?
+
@Test
public void testToOsgiVersion() {
assertVersion("0.10.0-20160713.1653", "0.10.0.20160713_1653");
@@ -43,6 +45,7 @@ public class OsgiUtilsTest {
assertVersion("4aug2000r7-dev", "0.0.0.4aug2000r7-dev");
}
+ @Deprecated
private void assertVersion(String ver, String expected) {
assertEquals(OsgiUtils.toOsgiVersion(ver), expected);
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ed98e27e/utils/common/src/test/java/org/apache/brooklyn/util/osgi/VersionedNameTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/osgi/VersionedNameTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/osgi/VersionedNameTest.java
index c838258..f162673 100644
--- a/utils/common/src/test/java/org/apache/brooklyn/util/osgi/VersionedNameTest.java
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/osgi/VersionedNameTest.java
@@ -16,6 +16,7 @@
package org.apache.brooklyn.util.osgi;
import org.apache.brooklyn.util.javalang.coerce.TypeCoercerExtensible;
+import org.apache.brooklyn.util.text.BrooklynVersionSyntax;
import org.osgi.framework.Version;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -37,7 +38,7 @@ public class VersionedNameTest {
@Test
public void testManuallyCorrectingVersion() {
Assert.assertEquals(new VersionedName("foo", new Version("1.0.0.alpha")), VersionedName.fromString("foo:"+
- OsgiUtils.toOsgiVersion("1.0-alpha")));
+ BrooklynVersionSyntax.toValidOsgiVersion("1.0-alpha")));
}
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ed98e27e/utils/common/src/test/java/org/apache/brooklyn/util/text/BrooklynVersionSyntaxTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/text/BrooklynVersionSyntaxTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/text/BrooklynVersionSyntaxTest.java
new file mode 100644
index 0000000..b938935
--- /dev/null
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/text/BrooklynVersionSyntaxTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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
+ *
+ * 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.apache.brooklyn.util.text;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+@Test
+public class BrooklynVersionSyntaxTest {
+
+ public void testVersions() {
+ assertVersion("1", true, true, true);
+ assertVersion("1.0.0", true, true, true);
+ assertVersion("1.0.0.SNAPSHOT", true, true, false);
+ assertVersion("1.0.0-SNAPSHOT", true, false, true);
+
+ assertVersion("", false, false, false);
+ assertVersion(null, false, false, false);
+ assertVersion("1:1", false, false, false);
+
+ assertVersion("1.SNAPSHOT", true, false, false);
+ assertVersion("1.0.0_SNAPSHOT", true, false, false);
+ assertVersion(".1", true, false, false);
+ assertVersion("v1", true, false, false);
+ assertVersion("!$&", true, false, false);
+ }
+
+ public void testConvert() {
+ assertConverts("0", "0", "0.0.0");
+ assertConverts("1.1", "1.1", "1.1.0");
+ assertConverts("x", "0.0.0-x", "0.0.0.x");
+ assertConverts("0.x", "0-x", "0.0.0.x");
+ assertConverts("1.1.x", "1.1-x", "1.1.0.x");
+ assertConverts("1.1.1.1.x", "1.1.1-1_x", "1.1.1.1_x");
+ assertConverts("1x", "1-x", "1.0.0.x");
+ assertConverts("1$", "1-_", "1.0.0._");
+ assertConverts("1-", "1-_", "1.0.0._");
+ assertConverts("1.1.", "1.1-_", "1.1.0._");
+ assertConverts("1$$$", "1-_", "1.0.0._");
+ assertConverts("1._$", "1-__", "1.0.0.__");
+ assertConverts("1a$$$", "1-a_", "1.0.0.a_");
+ assertConverts("1a$$$SNAPSHOT", "1-a_SNAPSHOT", "1.0.0.a_SNAPSHOT");
+ }
+
+ private void assertConverts(String input, String bklyn, String osgi) {
+ Assert.assertEquals(BrooklynVersionSyntax.toGoodBrooklynVersion(input), bklyn, "conversion to good brooklyn");
+ Assert.assertEquals(BrooklynVersionSyntax.toValidOsgiVersion(input), osgi, "conversion to valid osgi");
+ }
+
+ private void assertVersion(String candidate, boolean isUsable, boolean isOsgi, boolean isGood) {
+ Assert.assertEquals(BrooklynVersionSyntax.isUsableVersion(candidate), isUsable, "usable version '"+candidate+"'");
+ Assert.assertEquals(BrooklynVersionSyntax.isValidOsgiVersion(candidate), isOsgi, "osgi version '"+candidate+"'");
+ Assert.assertEquals(BrooklynVersionSyntax.isGoodBrooklynVersion(candidate), isGood, "good version '"+candidate+"'");
+ }
+
+ private void assertOsgiVersion(String input, String osgi) {
+ Assert.assertEquals(BrooklynVersionSyntax.toValidOsgiVersion(input), osgi, "conversion to valid osgi");
+ }
+
+ public void testOsgiVersions() {
+ assertOsgiVersion("0.10.0-20160713.1653", "0.10.0.20160713_1653");
+
+ assertOsgiVersion("2.1.0-SNAPSHOT", "2.1.0.SNAPSHOT");
+ assertOsgiVersion("2.1-SNAPSHOT", "2.1.0.SNAPSHOT");
+ assertOsgiVersion("0.1-SNAPSHOT", "0.1.0.SNAPSHOT");
+ assertOsgiVersion("2-SNAPSHOT", "2.0.0.SNAPSHOT");
+ assertOsgiVersion("2", "2.0.0");
+ assertOsgiVersion("2.1", "2.1.0");
+ assertOsgiVersion("2.1.3", "2.1.3");
+ assertOsgiVersion("2.1.3.4", "2.1.3.4");
+ assertOsgiVersion("1.1-alpha-2", "1.1.0.alpha-2");
+ assertOsgiVersion("1.0-alpha-16-20070122.203121-13", "1.0.0.alpha-16-20070122_203121-13");
+ assertOsgiVersion("1.0-20070119.021432-1", "1.0.0.20070119_021432-1");
+ assertOsgiVersion("1-20070119.021432-1", "1.0.0.20070119_021432-1");
+ assertOsgiVersion("1.4.1-20070217.082013-7", "1.4.1.20070217_082013-7");
+ assertOsgiVersion("0.0.0.4aug2000r7-dev", "0.0.0.4aug2000r7-dev");
+ assertOsgiVersion("0-4aug2000r7-dev", "0.0.0.4aug2000r7-dev");
+ assertOsgiVersion("-4aug2000r7-dev", "0.0.0.4aug2000r7-dev");
+ // potentially surprising, and different to maven (0.0.0.4aug..)
+ assertOsgiVersion("4aug2000r7-dev", "4.0.0.aug2000r7-dev");
+ }
+}