From 72787ab39a05cad3f0045b4182ee073ad70f81df Mon Sep 17 00:00:00 2001 From: Svetoslav Neykov Date: Wed, 13 Jul 2016 17:50:16 +0300 Subject: [PATCH] Convert versions to OSGi format before passing them to the OSGi runtime. --- .../brooklyn/util/core/ClassLoaderUtils.java | 12 +-- .../util/core/ClassLoaderUtilsTest.java | 24 +++++ .../apache/brooklyn/util/osgi/OsgiUtils.java | 96 +++++++++++++++++++ 3 files changed, 123 insertions(+), 9 deletions(-) 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 5423ba9795..9f24b47d2b 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 @@ -38,6 +38,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.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; @@ -61,7 +62,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\\..*:" + BrooklynVersion.get().replaceFirst("-", "."); + private static final String WHITE_LIST_DEFAULT = "org\\.apache\\.brooklyn\\..*:" + OsgiUtils.toOsgiVersion(BrooklynVersion.get()); // 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. @@ -268,15 +269,8 @@ protected Maybe tryLoadFromBundle(LoaderDispatcher dispatcher, String if (framework != null) { Maybe bundle = Osgis.bundleFinder(framework) .symbolicName(symbolicName) - .version(version) + .version(OsgiUtils.toOsgiVersion(version)) .find(); - if (bundle.isAbsent() && version != null) { - bundle = Osgis.bundleFinder(framework) - .symbolicName(symbolicName) - // Convert X.X.X-SNAPSHOT to X.X.X.SNAPSHOT. Any better way to do it? - .version(version.replace("-", ".")) - .find(); - } if (bundle.isAbsent()) { throw new IllegalStateException("Bundle " + toBundleString(symbolicName, version) + " not found to load " + name); } 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 b0cce9e02a..7ede563d1d 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 @@ -32,6 +32,7 @@ import org.apache.brooklyn.api.entity.Entity; import org.apache.brooklyn.api.entity.EntitySpec; import org.apache.brooklyn.api.mgmt.ManagementContext; +import org.apache.brooklyn.core.BrooklynVersion; import org.apache.brooklyn.core.catalog.internal.CatalogBundleDto; import org.apache.brooklyn.core.catalog.internal.CatalogEntityItemDto; import org.apache.brooklyn.core.catalog.internal.CatalogItemBuilder; @@ -52,7 +53,9 @@ import org.apache.brooklyn.util.maven.MavenArtifact; import org.apache.brooklyn.util.maven.MavenRetriever; import org.apache.brooklyn.util.osgi.OsgiTestResources; +import org.apache.brooklyn.util.osgi.OsgiUtils; import org.osgi.framework.Bundle; +import org.osgi.framework.Version; import org.osgi.framework.launch.Framework; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; @@ -205,6 +208,27 @@ public void testLoadsFromRightGuavaVersion() throws Exception { assertLoadSucceeds(clu, classname, ImmutableList.class); } + @Test + public void testLoadBrooklynClass() throws Exception { + mgmt = LocalManagementContextForTests.builder(true).disableOsgi(false).build(); + new ClassLoaderUtils(this, mgmt).loadClass( + "org.apache.brooklyn.api", + BrooklynVersion.get(), + Entity.class.getName()); + new ClassLoaderUtils(this, mgmt).loadClass( + "org.apache.brooklyn.api", + OsgiUtils.toOsgiVersion(BrooklynVersion.get()), + Entity.class.getName()); + new ClassLoaderUtils(this, mgmt).loadClass( + "org.apache.brooklyn.api", + "0.10.0-SNAPSHOT", + Entity.class.getName()); + new ClassLoaderUtils(this, mgmt).loadClass( + "org.apache.brooklyn.api", + "0.10.0.SNAPSHOT", + Entity.class.getName()); + } + private Bundle installBundle(ManagementContext mgmt, String bundleUrl) throws Exception { OsgiManager osgiManager = ((ManagementContextInternal)mgmt).getOsgiManager().get(); Framework framework = osgiManager.getFramework(); 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 4e2872090f..df416864cc 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 @@ -21,6 +21,9 @@ import java.net.URL; import java.util.jar.Attributes; import java.util.jar.Manifest; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + import org.apache.brooklyn.util.guava.Maybe; import org.apache.brooklyn.util.text.Strings; import org.osgi.framework.Bundle; @@ -98,4 +101,97 @@ public static Maybe parseOsgiIdentifier(String symbolicNameOption return Maybe.of(new VersionedName(parts[0], v)); } + public static String toOsgiVersion(String version) { + if (version != null) { + return DefaultMaven2OsgiConverter.cleanupVersion(version); + } else { + return null; + } + } + + // Maven to OSGi version converter + // Source: https://github.com/apache/felix/blob/trunk/tools/maven-bundle-plugin/src/main/java/org/apache/maven/shared/osgi/DefaultMaven2OsgiConverter.java + private static class DefaultMaven2OsgiConverter { + /** + * Clean up version parameters. Other builders use more fuzzy definitions of + * the version syntax. This method cleans up such a version to match an OSGi + * version. + * + * @param VERSION_STRING + * @return + */ + static final Pattern FUZZY_VERSION = Pattern.compile( "(\\d+)(\\.(\\d+)(\\.(\\d+))?)?([^a-zA-Z0-9](.*))?", + Pattern.DOTALL ); + + + static public String cleanupVersion( String version ) + { + StringBuffer result = new StringBuffer(); + Matcher m = FUZZY_VERSION.matcher( version ); + if ( m.matches() ) + { + String major = m.group( 1 ); + String minor = m.group( 3 ); + String micro = m.group( 5 ); + String qualifier = m.group( 7 ); + + if ( major != null ) + { + result.append( major ); + if ( minor != null ) + { + result.append( "." ); + result.append( minor ); + if ( micro != null ) + { + result.append( "." ); + result.append( micro ); + if ( qualifier != null ) + { + result.append( "." ); + cleanupModifier( result, qualifier ); + } + } + else if ( qualifier != null ) + { + result.append( ".0." ); + cleanupModifier( result, qualifier ); + } + else + { + result.append( ".0" ); + } + } + else if ( qualifier != null ) + { + result.append( ".0.0." ); + cleanupModifier( result, qualifier ); + } + else + { + result.append( ".0.0" ); + } + } + } + else + { + result.append( "0.0.0." ); + cleanupModifier( result, version ); + } + return result.toString(); + } + + static void cleanupModifier( StringBuffer result, String modifier ) + { + for ( int i = 0; i < modifier.length(); i++ ) + { + char c = modifier.charAt( i ); + if ( ( c >= '0' && c <= '9' ) || ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) || c == '_' + || c == '-' ) + result.append( c ); + else + result.append( '_' ); + } + } + } }