test the osgi-prefixing for classes, and improve javadoc
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/9d448f32 Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/9d448f32 Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/9d448f32 Branch: refs/heads/master Commit: 9d448f3204ee26b7f716f5e339fe07d814fb37c3 Parents: f956627 Author: Alex Heneveld <alex.henev...@cloudsoftcorp.com> Authored: Wed Jun 7 14:36:39 2017 +0100 Committer: Alex Heneveld <alex.henev...@cloudsoftcorp.com> Committed: Wed Jun 7 14:43:25 2017 +0100 ---------------------------------------------------------------------- ...rFromStackOfBrooklynClassLoadingContext.java | 5 + .../core/mgmt/persist/XmlMementoSerializer.java | 14 ++- .../util/core/xstream/ClassRenamingMapper.java | 22 ++-- .../util/core/xstream/OsgiClassnameMapper.java | 14 +++ .../util/core/xstream/XmlSerializer.java | 28 ++++- .../core/mgmt/osgi/OsgiStandaloneTest.java | 21 ---- .../brooklyn/util/core/osgi/OsgiTestBase.java | 23 ++++ .../core/xstream/XmlSerializerOsgiTest.java | 111 +++++++++++++++++++ .../brooklyn/util/osgi/OsgiTestResources.java | 3 +- 9 files changed, 200 insertions(+), 41 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/9d448f32/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/ClassLoaderFromStackOfBrooklynClassLoadingContext.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/ClassLoaderFromStackOfBrooklynClassLoadingContext.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/ClassLoaderFromStackOfBrooklynClassLoadingContext.java index f42ecd2..102a27c 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/ClassLoaderFromStackOfBrooklynClassLoadingContext.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/ClassLoaderFromStackOfBrooklynClassLoadingContext.java @@ -62,6 +62,11 @@ public class ClassLoaderFromStackOfBrooklynClassLoadingContext extends ClassLoad protected Class<?> findClass(String name) throws ClassNotFoundException { return currentLoader.get().loadClass(name); } + + @Override + protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { + return findClass(name); + } /** Must be accompanied by a corresponding {@link #popClassLoadingContext()} when finished. */ @SuppressWarnings("deprecation") http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/9d448f32/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java index e83b5ea..9265a1f 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java @@ -90,9 +90,8 @@ public class XmlMementoSerializer<T> extends XmlSerializer<T> implements Memento } public XmlMementoSerializer(ClassLoader classLoader, Map<String, String> deserializingClassRenames) { - super(deserializingClassRenames); - this.delegatingClassLoader = new ClassLoaderFromStackOfBrooklynClassLoadingContext(classLoader); - xstream.setClassLoader(this.delegatingClassLoader); + super(new ClassLoaderFromStackOfBrooklynClassLoadingContext(classLoader), deserializingClassRenames); + this.delegatingClassLoader = (ClassLoaderFromStackOfBrooklynClassLoadingContext) xstream.getClassLoader(); xstream.alias("entity", BasicEntityMemento.class); xstream.alias("location", BasicLocationMemento.class); @@ -128,6 +127,11 @@ public class XmlMementoSerializer<T> extends XmlSerializer<T> implements Memento //For compatibility with existing persistence stores content. xstream.aliasField("registeredTypeName", BasicCatalogItemMemento.class, "symbolicName"); + configureXstreamWithDeprecatedItems(); + } + + @SuppressWarnings("deprecation") + private void configureXstreamWithDeprecatedItems() { xstream.registerLocalConverter(BasicCatalogItemMemento.class, "libraries", new CatalogItemLibrariesConverter()); } @@ -353,9 +357,9 @@ public class XmlMementoSerializer<T> extends XmlSerializer<T> implements Memento // Perhaps context.getRequiredType(); can be used instead? // Other users of xstream (e.g. jenkinsci) manually check for resoved-to and class attributes // for compatibility with older versions of xstream - private static Class readClassType(HierarchicalStreamReader reader, Mapper mapper) { + private static Class<?> readClassType(HierarchicalStreamReader reader, Mapper mapper) { String classAttribute = readClassAttribute(reader, mapper); - Class type; + Class<?> type; if (classAttribute == null) { type = mapper.realClass(reader.getNodeName()); } else { http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/9d448f32/core/src/main/java/org/apache/brooklyn/util/core/xstream/ClassRenamingMapper.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/util/core/xstream/ClassRenamingMapper.java b/core/src/main/java/org/apache/brooklyn/util/core/xstream/ClassRenamingMapper.java index a2fa7ae..5691198 100644 --- a/core/src/main/java/org/apache/brooklyn/util/core/xstream/ClassRenamingMapper.java +++ b/core/src/main/java/org/apache/brooklyn/util/core/xstream/ClassRenamingMapper.java @@ -22,6 +22,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import java.util.Map; +import org.apache.brooklyn.util.exceptions.Exceptions; import org.apache.brooklyn.util.guava.Maybe; import org.apache.brooklyn.util.javalang.Reflections; import org.slf4j.Logger; @@ -79,11 +80,6 @@ public class ClassRenamingMapper extends MapperWrapper { * 3. As mentioned under the use-cases, the rename could include the full bundle name prefix, * or it might just be the classname. We want to handle both, so need to implement yet * more fallback behaviour. - * - * --- - * TODO Wanted to pass xstream, rather than Supplier<ClassLoader>, in constructor. However, - * this caused NPE because of how this is constructed from inside - * XmlMementoSerializer.wrapMapperForNormalUsage, called from within an anonymous subclass of XStream! */ public static final Logger LOG = LoggerFactory.getLogger(ClassRenamingMapper.class); @@ -94,6 +90,12 @@ public class ClassRenamingMapper extends MapperWrapper { public ClassRenamingMapper(Mapper wrapped, Map<String, String> nameToType, Supplier<? extends ClassLoader> classLoaderSupplier) { super(wrapped); this.nameToType = checkNotNull(nameToType, "nameToType"); + /* + * NB: wanted to pass xstream, rather than Supplier<ClassLoader>, in constructor. However, + * this caused NPE because of how this is constructed from inside + * XmlMementoSerializer.wrapMapperForNormalUsage, called from within an anonymous subclass of XStream! + * (Similar as for OsgiClassnameMapper.) + */ this.classLoaderSupplier = checkNotNull(classLoaderSupplier, "classLoaderSupplier"); } @@ -106,10 +108,14 @@ public class ClassRenamingMapper extends MapperWrapper { elementName = elementNameOpt.get(); } - CannotResolveClassException tothrow; + Exception tothrow; try { return super.realClass(elementName); - } catch (CannotResolveClassException e) { + } catch (Exception e) { + Exceptions.propagateIfFatal(e); + // CannotResolveClassException is what should be thrown, but + // sneakily you can get other, e.g. + // IAE if you have a ":" in the name and a URLClassLoader tries to read it LOG.trace("Failed to load class using super.realClass({}), for orig class {}, attempting fallbacks: {}", new Object[] {elementName, elementNamOrig, e}); tothrow = e; } @@ -157,7 +163,7 @@ public class ClassRenamingMapper extends MapperWrapper { } } - throw tothrow; + throw Exceptions.propagate(tothrow); } private boolean hasBundlePrefix(String type) { http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/9d448f32/core/src/main/java/org/apache/brooklyn/util/core/xstream/OsgiClassnameMapper.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/util/core/xstream/OsgiClassnameMapper.java b/core/src/main/java/org/apache/brooklyn/util/core/xstream/OsgiClassnameMapper.java index 7bdf9f7..f82e743 100644 --- a/core/src/main/java/org/apache/brooklyn/util/core/xstream/OsgiClassnameMapper.java +++ b/core/src/main/java/org/apache/brooklyn/util/core/xstream/OsgiClassnameMapper.java @@ -24,6 +24,20 @@ import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.mapper.CannotResolveClassException; import com.thoughtworks.xstream.mapper.MapperWrapper; +/** Attaches a prefix to _all_ classes written out. + * Ensures the xstream class loader is used to read + * (because that's where we set the OSGi-prefix-aware code). + * <p> + * We also have the context in that loader so if we wanted to optimize + * we could scan that for bundles and suppress bundles if it's in scope. + * However if we plan to move to referring to RegisteredTypes for anything + * serialized that's irrelevant. + * <p> + * We could have code that uses the search path from that loader + * to prefers types in local bundles, ignoring the bundle name + * if the class is found there (either always, or just if the bundle is not found / deprecated). + */ +// TODO above, and also see discussion at https://github.com/apache/brooklyn-server/pull/718 public class OsgiClassnameMapper extends MapperWrapper { private final OsgiClassPrefixer prefixer; private final Supplier<XStream> xstream; http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/9d448f32/core/src/main/java/org/apache/brooklyn/util/core/xstream/XmlSerializer.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/util/core/xstream/XmlSerializer.java b/core/src/main/java/org/apache/brooklyn/util/core/xstream/XmlSerializer.java index 26b6788..c0349b6 100644 --- a/core/src/main/java/org/apache/brooklyn/util/core/xstream/XmlSerializer.java +++ b/core/src/main/java/org/apache/brooklyn/util/core/xstream/XmlSerializer.java @@ -50,13 +50,20 @@ public class XmlSerializer<T> { } public XmlSerializer(Map<String, String> deserializingClassRenames) { + this(null, deserializingClassRenames); + } + + public XmlSerializer(ClassLoader loader, Map<String, String> deserializingClassRenames) { this.deserializingClassRenames = deserializingClassRenames; - this.xstream = new XStream() { + xstream = new XStream() { @Override protected MapperWrapper wrapMapper(MapperWrapper next) { return XmlSerializer.this.wrapMapperForNormalUsage( super.wrapMapper(next) ); } }; + if (loader!=null) { + xstream.setClassLoader(loader); + } xstream.registerConverter(newCustomJavaClassConverter(), XStream.PRIORITY_NORMAL); @@ -89,15 +96,18 @@ public class XmlSerializer<T> { } /** - * JCC is used when class names are serialized/deserialized and no alias is defined; - * it is configured in XStream *without* access to the XStream mapper. + * JCC is used when Class instances are serialized/deserialized as a value + * (not as tags) and there are no aliases configured for that type. + * It is configured in XStream default *without* access to the XStream mapper, + * which is meant to apply when serializing the type name for instances of that type. + * <p> * However we need a few selected mappers (see {@link #wrapMapperForAllLowLevelMentions(Mapper)} ) - * in order to effect renames at the low level, but many of the mappers must NOT be used, + * to apply to all class renames, but many of the mappers must NOT be used, * e.g. because some might intercept all Class<? extends Entity> references * (and that interception is only wanted when serializing <i>instances</i>, * as in {@link #wrapMapperForNormalUsage(Mapper)}). * <p> - * This can typically be done simply by registering our own instance (due to order guarantee of PrioritizedList), + * This can typically be done simply by registering our own instance of this (due to order guarantee of PrioritizedList), * after the instance added by XStream.setupConverters() */ private JavaClassConverter newCustomJavaClassConverter() { @@ -105,7 +115,7 @@ public class XmlSerializer<T> { } /** Adds mappers needed for *any* reference to a class, both "normal" usage (when xstream wants a mapper) - * and class conversion (when xstream needs to make a class name and doesn't have an alias). + * and Class conversion (when xstream needs to serialize an instance of Class and doesn't have an alias). * <p> * This should apply when nice names are used for inner classes, or classes are renamed; * however mappers which affect aliases or intercept references to entities are usually @@ -114,6 +124,7 @@ public class XmlSerializer<T> { // so very few fields are populated protected MapperWrapper wrapMapperForAllLowLevelMentions(Mapper next) { MapperWrapper result = new CompilerIndependentOuterClassFieldMapper(next); + Supplier<ClassLoader> classLoaderSupplier = new Supplier<ClassLoader>() { @Override public ClassLoader get() { return xstream.getClassLoaderReference().getReference(); @@ -122,6 +133,11 @@ public class XmlSerializer<T> { result = new ClassRenamingMapper(result, deserializingClassRenames, classLoaderSupplier); result = new OsgiClassnameMapper(new Supplier<XStream>() { @Override public XStream get() { return xstream; } }, result); + // TODO as noted in ClassRenamingMapper that class can be simplified if + // we swap the order of the above calls, because it _will_ be able to rely on + // OsgiClassnameMapper to attempt to load with the xstream reference stack + // (not doing it just now because close to a release) + return result; } /** Extension point where sub-classes can add mappers wanted when instances of a class are serialized, http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/9d448f32/core/src/test/java/org/apache/brooklyn/core/mgmt/osgi/OsgiStandaloneTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/osgi/OsgiStandaloneTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/osgi/OsgiStandaloneTest.java index b21ba28..3bb5358 100644 --- a/core/src/test/java/org/apache/brooklyn/core/mgmt/osgi/OsgiStandaloneTest.java +++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/osgi/OsgiStandaloneTest.java @@ -45,9 +45,6 @@ public class OsgiStandaloneTest extends OsgiTestBase { private static final Logger log = LoggerFactory.getLogger(OsgiStandaloneTest.class); - public static final String BROOKLYN_OSGI_TEST_A_0_1_0_PATH = OsgiTestResources.BROOKLYN_OSGI_TEST_A_0_1_0_PATH; - public static final String BROOKLYN_OSGI_TEST_A_0_1_0_URL = "classpath:"+BROOKLYN_OSGI_TEST_A_0_1_0_PATH; - public static final String BROOKLYN_TEST_OSGI_ENTITIES_PATH = OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_PATH; public static final String BROOKLYN_TEST_OSGI_ENTITIES_SYMBOLIC_NAME_FULL = OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_SYMBOLIC_NAME_FULL; public static final String BROOKLYN_TEST_OSGI_MORE_ENTITIES_0_1_0_PATH = OsgiTestResources.BROOKLYN_TEST_OSGI_MORE_ENTITIES_0_1_0_PATH; @@ -56,24 +53,6 @@ public class OsgiStandaloneTest extends OsgiTestBase { public static final String BROOKLYN_TEST_OSGI_ENTITIES_NAME = "org.apache.brooklyn.test.resources.osgi.brooklyn-test-osgi-entities"; public static final String BROOKLYN_TEST_OSGI_ENTITIES_VERSION = "0.1.0"; - - protected Bundle install(String url) throws BundleException { - try { - return Osgis.install(framework, url); - } catch (Exception e) { - throw new IllegalStateException("test resources not available; may be an IDE issue, so try a mvn rebuild of this project", e); - } - } - - protected Bundle installFromClasspath(String resourceName) throws BundleException { - TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), resourceName); - try { - return Osgis.install(framework, String.format("classpath:%s", resourceName)); - } catch (Exception e) { - throw Exceptions.propagate(e); - } - } - @Test public void testInstallBundle() throws Exception { Bundle bundle = installFromClasspath(BROOKLYN_OSGI_TEST_A_0_1_0_PATH); http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/9d448f32/core/src/test/java/org/apache/brooklyn/util/core/osgi/OsgiTestBase.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/util/core/osgi/OsgiTestBase.java b/core/src/test/java/org/apache/brooklyn/util/core/osgi/OsgiTestBase.java index 0e6d751..4bc1e58 100644 --- a/core/src/test/java/org/apache/brooklyn/util/core/osgi/OsgiTestBase.java +++ b/core/src/test/java/org/apache/brooklyn/util/core/osgi/OsgiTestBase.java @@ -20,9 +20,12 @@ import java.io.IOException; import org.apache.brooklyn.api.mgmt.ManagementContext; import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal; +import org.apache.brooklyn.test.support.TestResourceUnavailableException; import org.apache.brooklyn.util.exceptions.Exceptions; import org.apache.brooklyn.util.os.Os; +import org.apache.brooklyn.util.osgi.OsgiTestResources; import org.apache.commons.io.FileUtils; +import org.osgi.framework.Bundle; import org.osgi.framework.BundleException; import org.osgi.framework.launch.Framework; import org.testng.annotations.AfterMethod; @@ -34,6 +37,26 @@ import org.testng.annotations.BeforeMethod; */ public class OsgiTestBase { + public static final String BROOKLYN_OSGI_TEST_A_0_1_0_PATH = OsgiTestResources.BROOKLYN_OSGI_TEST_A_0_1_0_PATH; + public static final String BROOKLYN_OSGI_TEST_A_0_1_0_URL = "classpath:"+BROOKLYN_OSGI_TEST_A_0_1_0_PATH; + + protected Bundle install(String url) throws BundleException { + try { + return Osgis.install(framework, url); + } catch (Exception e) { + throw new IllegalStateException("test resources not available; may be an IDE issue, so try a mvn rebuild of this project", e); + } + } + + protected Bundle installFromClasspath(String resourceName) throws BundleException { + TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), resourceName); + try { + return Osgis.install(framework, String.format("classpath:%s", resourceName)); + } catch (Exception e) { + throw Exceptions.propagate(e); + } + } + protected Framework framework = null; private File storageTempDir; http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/9d448f32/core/src/test/java/org/apache/brooklyn/util/core/xstream/XmlSerializerOsgiTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/util/core/xstream/XmlSerializerOsgiTest.java b/core/src/test/java/org/apache/brooklyn/util/core/xstream/XmlSerializerOsgiTest.java new file mode 100644 index 0000000..5db2a5f --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/util/core/xstream/XmlSerializerOsgiTest.java @@ -0,0 +1,111 @@ +/* + * 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.core.xstream; + +import static org.testng.Assert.assertEquals; + +import java.util.Arrays; +import java.util.List; + +import org.apache.brooklyn.core.mgmt.classloading.ClassLoaderFromStackOfBrooklynClassLoadingContext; +import org.apache.brooklyn.util.core.osgi.OsgiTestBase; +import org.apache.brooklyn.util.core.osgi.Osgis; +import org.apache.brooklyn.util.osgi.OsgiTestResources; +import org.apache.brooklyn.util.text.Strings; +import org.osgi.framework.Bundle; +import org.osgi.framework.launch.Framework; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; + +public class XmlSerializerOsgiTest extends OsgiTestBase { + + private static final Logger LOG = LoggerFactory.getLogger(XmlSerializerOsgiTest.class); + + protected XmlSerializer<Object> serializer; + + /** Simple osgi-prefix-aware class loader. In the real world this function is done by OsgiManager. */ + public static class OsgiPrefixStrippingClassLoader extends ClassLoader { + private final Framework framework; + + public OsgiPrefixStrippingClassLoader(Framework framework, ClassLoader parent) { + super(parent); + this.framework = framework; + } + + @Override + protected Class<?> findClass(String name) throws ClassNotFoundException { + int separator = name.indexOf(":"); + if (separator>=0) { + Bundle bundle = Osgis.bundleFinder(framework).symbolicName(name.substring(0, separator)).find().get(); + return bundle.loadClass(name.substring(separator+1)); + } else { + return super.findClass(name); + } + } + + @Override + protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { + int separator = name.indexOf(":"); + if (separator>=0) { + Bundle bundle = Osgis.bundleFinder(framework).symbolicName(name.substring(0, separator)).find().get(); + return bundle.loadClass(name.substring(separator+1)); + } else { + return super.loadClass(name, resolve); + } + } + } + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + super.setUp(); + serializer = new XmlSerializer<Object>( + new OsgiPrefixStrippingClassLoader(framework, getClass().getClassLoader()), + ImmutableMap.<String, String>of()); + } + + @Test + public void testPrefixesOnClassAndInstance() throws Exception { + Bundle bundle = installFromClasspath(BROOKLYN_OSGI_TEST_A_0_1_0_PATH); + + final String TYPE = "brooklyn.test.osgi.TestA"; + final String FQTN = OsgiTestResources.BROOKLYN_OSGI_TEST_A_SYMBOLIC_NAME + ":" + TYPE; + + Class<?> aClass = bundle.loadClass(TYPE); + String rc = assertSerializeEqualsAndCanDeserialize(aClass, "<java-class>"+FQTN+"</java-class>"); + + Object aInst = aClass.newInstance(); + String ri = assertSerializeEqualsAndCanDeserialize(aInst, "<"+FQTN+"/>"); + + List<Object> l = Arrays.asList(aClass, aInst); + assertSerializeEqualsAndCanDeserialize(l, "<java.util.Arrays_-ArrayList><a>"+rc+ri+"</a></java.util.Arrays_-ArrayList>"); + } + + protected String assertSerializeEqualsAndCanDeserialize(Object val, String expected) throws Exception { + String xml = serializer.toString(val); + assertEquals(Strings.replaceAllRegex(xml, "\\s+", ""), Strings.replaceAllRegex(expected, "\\s+", "")); + Object result = serializer.fromString(xml); + LOG.debug("val="+val+"'; xml="+xml+"; result="+result); + assertEquals(result.getClass(), val.getClass()); + return expected; + } +} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/9d448f32/utils/common/src/test/java/org/apache/brooklyn/util/osgi/OsgiTestResources.java ---------------------------------------------------------------------- diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/osgi/OsgiTestResources.java b/utils/common/src/test/java/org/apache/brooklyn/util/osgi/OsgiTestResources.java index f9f1998..048e0f5 100644 --- a/utils/common/src/test/java/org/apache/brooklyn/util/osgi/OsgiTestResources.java +++ b/utils/common/src/test/java/org/apache/brooklyn/util/osgi/OsgiTestResources.java @@ -33,7 +33,8 @@ public interface OsgiTestResources { * defines TestA which has a "times" method and a static multiplier field; * we set the multiplier to determine when we are sharing versions and when not */ - public static final String BROOKLYN_OSGI_TEST_A_0_1_0_PATH = "/brooklyn/osgi/brooklyn-osgi-test-a_0.1.0.jar"; + public static final String BROOKLYN_OSGI_TEST_A_SYMBOLIC_NAME = "brooklyn-osgi-test-a"; + public static final String BROOKLYN_OSGI_TEST_A_0_1_0_PATH = "/brooklyn/osgi/" + BROOKLYN_OSGI_TEST_A_SYMBOLIC_NAME + "_0.1.0.jar"; /** * brooklyn-test-osgi-entities (v 0.1.0) -