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 2015/05/29 12:36:06 UTC

[06/13] incubator-brooklyn git commit: fix scanning for osgi, and add test for same

fix scanning for osgi, and add test for same


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/1207d991
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/1207d991
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/1207d991

Branch: refs/heads/master
Commit: 1207d9917c0f8e0b6186d24b6b76688f935f9e14
Parents: df21c71
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue May 26 14:44:51 2015 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue May 26 14:45:10 2015 +0100

----------------------------------------------------------------------
 .../catalog/internal/BasicBrooklynCatalog.java  |  48 +++++++++++++----
 .../catalog/internal/CatalogClasspathDo.java    |  39 ++++++++++++--
 .../brooklyn/osgi/tests/more/MoreEntity.java    |   2 +
 .../brooklyn-test-osgi-more-entities_0.2.0.jar  | Bin 12590 -> 13078 bytes
 .../BrooklynComponentTemplateResolver.java      |  12 ++---
 .../camp/brooklyn/AbstractYamlTest.java         |  10 ++--
 .../camp/brooklyn/ReferencedYamlTest.java       |   6 +--
 .../CatalogOsgiVersionMoreEntityTest.java       |  52 +++++++++++++++----
 .../brooklyn/catalog/CatalogYamlCombiTest.java  |   6 +--
 .../brooklyn/catalog/CatalogYamlEntityTest.java |  44 ++++++++--------
 .../catalog/CatalogYamlLocationTest.java        |   4 +-
 .../brooklyn/catalog/CatalogYamlPolicyTest.java |   6 +--
 .../catalog/CatalogYamlTemplateTest.java        |   2 +-
 .../catalog/CatalogYamlVersioningTest.java      |   4 +-
 .../more-entities-osgi-catalog-scan.yaml        |  32 ++++++++++++
 .../src/main/java/brooklyn/util/os/Os.java      |   6 +--
 16 files changed, 199 insertions(+), 74 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1207d991/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
index 8c88974..bba0b73 100644
--- a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
@@ -537,7 +537,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     }
     
     @SuppressWarnings("unchecked")
-    private <T> Maybe<T> getFirstAs(Map<?,?> map, Class<T> type, String firstKey, String ...otherKeys) {
+    private static <T> Maybe<T> getFirstAs(Map<?,?> map, Class<T> type, String firstKey, String ...otherKeys) {
         if (map==null) return Maybe.absent("No map available");
         String foundKey = null;
         Object value = null;
@@ -621,9 +621,9 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         } else {
             // scan for annotations: if libraries here, scan them; if inherited libraries error; else scan classpath
             if (!libraryBundlesNew.isEmpty()) {
-                result.addAll(scanAnnotationsFromBundles(mgmt, libraryBundlesNew));
+                result.addAll(scanAnnotationsFromBundles(mgmt, libraryBundlesNew, catalogMetadata));
             } else if (libraryBundles.isEmpty()) {
-                result.addAll(scanAnnotationsFromLocal(mgmt));
+                result.addAll(scanAnnotationsFromLocal(mgmt, catalogMetadata));
             } else {
                 throw new IllegalStateException("Cannot scan catalog node no local bundles, and with inherited bundles we will not scan the classpath");
             }
@@ -780,13 +780,13 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         return oldValue;
     }
 
-    private Collection<CatalogItemDtoAbstract<?, ?>> scanAnnotationsFromLocal(ManagementContext mgmt) {
+    private Collection<CatalogItemDtoAbstract<?, ?>> scanAnnotationsFromLocal(ManagementContext mgmt, Map<Object, Object> catalogMetadata) {
         CatalogDto dto = CatalogDto.newNamedInstance("Local Scanned Catalog", "All annotated Brooklyn entities detected in the classpath", "scanning-local-classpath");
-        return scanAnnotationsInternal(mgmt, new CatalogDo(dto));
+        return scanAnnotationsInternal(mgmt, new CatalogDo(dto), catalogMetadata);
     }
     
-    private Collection<CatalogItemDtoAbstract<?, ?>> scanAnnotationsFromBundles(ManagementContext mgmt, Collection<CatalogBundle> libraries) {
-        CatalogDto dto = CatalogDto.newNamedInstance("Bundles Scanned Catalog", "All annotated Brooklyn entities detected in the classpath", "scanning-bundles-classpath-"+libraries.hashCode());
+    private Collection<CatalogItemDtoAbstract<?, ?>> scanAnnotationsFromBundles(ManagementContext mgmt, Collection<CatalogBundle> libraries, Map<Object, Object> catalogMetadata) {
+        CatalogDto dto = CatalogDto.newNamedInstance("Bundles Scanned Catalog", "All annotated Brooklyn entities detected in bundles", "scanning-bundles-classpath-"+libraries.hashCode());
         List<String> urls = MutableList.of();
         for (CatalogBundle b: libraries) {
             // TODO currently does not support pre-installed bundles identified by name:version 
@@ -803,10 +803,10 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         
         CatalogDo subCatalog = new CatalogDo(dto);
         subCatalog.addToClasspath(urls.toArray(new String[0]));
-        return scanAnnotationsInternal(mgmt, subCatalog);
+        return scanAnnotationsInternal(mgmt, subCatalog, catalogMetadata);
     }
     
-    private Collection<CatalogItemDtoAbstract<?, ?>> scanAnnotationsInternal(ManagementContext mgmt, CatalogDo subCatalog) {
+    private Collection<CatalogItemDtoAbstract<?, ?>> scanAnnotationsInternal(ManagementContext mgmt, CatalogDo subCatalog, Map<Object, Object> catalogMetadata) {
         // TODO this does java-scanning only;
         // the call when scanning bundles should use the CatalogItem instead and use OSGi when loading for scanning
         // (or another scanning mechanism).  see comments on CatalogClasspathDo.load
@@ -818,7 +818,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         @SuppressWarnings({ "unchecked", "rawtypes" })
         Collection<CatalogItemDtoAbstract<?, ?>> result = (Collection<CatalogItemDtoAbstract<?, ?>>)(Collection)Collections2.transform(
                 (Collection<CatalogItemDo<Object,Object>>)(Collection)subCatalog.getIdCache().values(), 
-                itemDoToDto());
+                itemDoToDtoAddingSelectedMetadataDuringScan(catalogMetadata));
         return result;
     }
 
@@ -1177,6 +1177,34 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
             }
         };
     }
+    
+    private static <T,SpecT> Function<CatalogItemDo<T, SpecT>, CatalogItem<T,SpecT>> itemDoToDtoAddingSelectedMetadataDuringScan(final Map<Object, Object> catalogMetadata) {
+        return new Function<CatalogItemDo<T,SpecT>, CatalogItem<T,SpecT>>() {
+            @Override
+            public CatalogItem<T,SpecT> apply(@Nullable CatalogItemDo<T,SpecT> item) {
+                if (item==null) return null;
+                CatalogItemDtoAbstract<T, SpecT> dto = (CatalogItemDtoAbstract<T, SpecT>) item.getDto();
+
+                // when scanning we only allow version and libraries to be overwritten
+                
+                String version = getFirstAs(catalogMetadata, String.class, "version").orNull();
+                if (Strings.isNonBlank(version)) dto.setVersion(version);
+                
+                Object librariesCombined = catalogMetadata.get("brooklyn.libraries");
+                if (librariesCombined instanceof Collection) {
+                    // will be set by scan -- slightly longwinded way to retrieve, but scanning for osgi needs an overhaul in any case
+                    Collection<CatalogBundle> libraryBundles = CatalogItemDtoAbstract.parseLibraries((Collection<?>) librariesCombined);
+                    dto.setLibraries(libraryBundles);
+                    // must replace java type with plan yaml here for libraries / catalog item to be picked up
+                    dto.setSymbolicName(dto.getJavaType());
+                    dto.setPlanYaml("services: [{ type: "+dto.getJavaType()+" }]");
+                    dto.setJavaType(null);
+                }
+
+                return dto;
+            }
+        };
+    }
 
     transient CatalogXmlSerializer serializer;
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1207d991/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
index c0716c8..077abaa 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
@@ -18,8 +18,10 @@
  */
 package brooklyn.catalog.internal;
 
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
 import java.lang.reflect.Modifier;
-import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.Arrays;
 import java.util.Set;
@@ -39,10 +41,13 @@ import brooklyn.entity.proxying.ImplementedBy;
 import brooklyn.location.Location;
 import brooklyn.management.internal.ManagementContextInternal;
 import brooklyn.policy.Policy;
+import brooklyn.util.ResourceUtils;
 import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.javalang.AggregateClassLoader;
 import brooklyn.util.javalang.ReflectionScanner;
 import brooklyn.util.javalang.UrlClassLoader;
+import brooklyn.util.os.Os;
+import brooklyn.util.stream.Streams;
 import brooklyn.util.text.Strings;
 import brooklyn.util.time.Time;
 
@@ -115,9 +120,35 @@ public class CatalogClasspathDo {
             urls = new URL[classpath.getEntries().size()];
             for (int i=0; i<urls.length; i++) {
                 try {
-                    urls[i] = new URL(classpath.getEntries().get(i));
-                } catch (MalformedURLException e) {
-                    log.error("Invalid URL "+classpath.getEntries().get(i)+" in definition of catalog "+catalog+"; skipping catalog");
+                    String u = classpath.getEntries().get(i);
+                    if (u.startsWith("classpath:")) {
+                        // special support for classpath: url's
+                        // TODO put convenience in ResourceUtils for extracting to a normal url
+                        // (or see below)
+                        InputStream uin = ResourceUtils.create(this).getResourceFromUrl(u);
+                        File f = Os.newTempFile("brooklyn-catalog-"+u, null);
+                        FileOutputStream fout = new FileOutputStream(f);
+                        Streams.copy(uin, fout);
+                        fout.close();
+                        uin.close();
+                        u = f.toURI().toString();
+                    }
+                    urls[i] = new URL(u);
+                    
+                    // TODO potential disk leak above as we have no way to know when the temp file can be removed earlier than server shutdown;
+                    // a better way to handle this is to supply a stream handler:
+//                    urls[i] = new URL(classpath.getEntries().get(i));
+//                    URI uri = URI.create(classpath.getEntries().get(i));
+//                    urls[i] = new URL(uri.getScheme(), uri.getHost(), uri.getPort(), uri.getPath()  // TODO query fragment?
+//                        , new URLStreamHandler() {
+//                            @Override
+//                            protected URLConnection openConnection(URL u) throws IOException {
+//                                new ResourceUtils(null). ???
+//                            }
+//                        });
+                } catch (Exception e) {
+                    Exceptions.propagateIfFatal(e);
+                    log.error("Error loading URL "+classpath.getEntries().get(i)+" in definition of catalog "+catalog+"; skipping definition");
                     throw Exceptions.propagate(e);
                 }
             }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1207d991/core/src/test/dependencies/osgi/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntity.java
----------------------------------------------------------------------
diff --git a/core/src/test/dependencies/osgi/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntity.java b/core/src/test/dependencies/osgi/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntity.java
index 955388c..987a7f8 100644
--- a/core/src/test/dependencies/osgi/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntity.java
+++ b/core/src/test/dependencies/osgi/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntity.java
@@ -19,11 +19,13 @@
 package brooklyn.osgi.tests.more;
 
 
+import brooklyn.catalog.Catalog;
 import brooklyn.entity.Effector;
 import brooklyn.entity.Entity;
 import brooklyn.entity.effector.Effectors;
 import brooklyn.entity.proxying.ImplementedBy;
 
+@Catalog(name="More Entity v2")
 @ImplementedBy(MoreEntityImpl.class)
 public interface MoreEntity extends Entity {
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1207d991/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar
----------------------------------------------------------------------
diff --git a/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar b/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar
index 1567f6e..91cc1e8 100644
Binary files a/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar and b/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar differ

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1207d991/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
index 492ef65..c157e93 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
@@ -230,12 +230,12 @@ public class BrooklynComponentTemplateResolver {
         boolean firstOccurrence = (item == null || encounteredCatalogTypes.add(item.getSymbolicName()));
         boolean recursiveButTryJava = !firstOccurrence;
 
-        // - Load a java class from current loader (item == null || entityResolver.isJavaTypePrefix())
-        // - Load a java class specified in an old-style catalog item (item != null && item.getJavaType() != null)
-        //   Old-style catalog items (can be defined in catalog.xml only) don't have structure, only a single type, so
-        //   they are loaded as a simple java type, only taking the class name from the catalog item instead of the
-        //   type value in the YAML. Classpath entries in the item are also used (through the catalog root classloader).
-        if (item == null || item.getJavaType() != null || isJavaTypePrefix()) {
+        // Load a java class from current loader if explicit java prefix, or if no item, or if item is legacy / 
+        // old-style catalog item (item != null && item.getJavaType() != null).
+        // Old-style catalog items (can be defined in catalog.xml only) don't have structure, only a single type, so
+        // they are loaded as a simple java type, only taking the class name from the catalog item instead of the
+        // type value in the YAML. Classpath entries in the item are also used (through the catalog root classloader).
+        if (isJavaTypePrefix() || item == null || item.getJavaType() != null) {
             return createSpecFromJavaType();
 
         // Same as above case, but this time force java type loading (either as plain class or through an old-style

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1207d991/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/AbstractYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/AbstractYamlTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/AbstractYamlTest.java
index 41489ba..67a2009 100644
--- a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/AbstractYamlTest.java
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/AbstractYamlTest.java
@@ -144,15 +144,15 @@ public abstract class AbstractYamlTest {
         return app;
     }
 
-    protected void addCatalogItem(Iterable<String> catalogYaml) {
-        addCatalogItem(joinLines(catalogYaml));
+    protected void addCatalogItems(Iterable<String> catalogYaml) {
+        addCatalogItems(joinLines(catalogYaml));
     }
 
-    protected void addCatalogItem(String... catalogYaml) {
-        addCatalogItem(joinLines(catalogYaml));
+    protected void addCatalogItems(String... catalogYaml) {
+        addCatalogItems(joinLines(catalogYaml));
     }
 
-    protected void addCatalogItem(String catalogYaml) {
+    protected void addCatalogItems(String catalogYaml) {
         mgmt().getCatalog().addItems(catalogYaml, forceUpdate);
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1207d991/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/ReferencedYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/ReferencedYamlTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/ReferencedYamlTest.java
index d4f079a..683bdc3 100644
--- a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/ReferencedYamlTest.java
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/ReferencedYamlTest.java
@@ -93,7 +93,7 @@ public class ReferencedYamlTest extends AbstractYamlTest {
 
     @Test
     public void testCatalogReferencingYamlUrl() throws Exception {
-        addCatalogItem(
+        addCatalogItems(
             "brooklyn.catalog:",
             "  id: yaml.reference",
             "  version: " + TEST_VERSION,
@@ -111,7 +111,7 @@ public class ReferencedYamlTest extends AbstractYamlTest {
 
     @Test
     public void testYamlUrlReferencingCatalog() throws Exception {
-        addCatalogItem(
+        addCatalogItems(
             "brooklyn.catalog:",
             "  id: yaml.basic",
             "  version: " + TEST_VERSION,
@@ -136,7 +136,7 @@ public class ReferencedYamlTest extends AbstractYamlTest {
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
 
         String parentCatalogId = "my.catalog.app.id.url.parent";
-        addCatalogItem(
+        addCatalogItems(
             "brooklyn.catalog:",
             "  id: " + parentCatalogId,
             "  version: " + TEST_VERSION,

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1207d991/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
index 19c9ef8..5c52c39 100644
--- a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
@@ -21,6 +21,8 @@ package io.brooklyn.camp.brooklyn.catalog;
 import io.brooklyn.camp.brooklyn.AbstractYamlTest;
 import io.brooklyn.camp.brooklyn.spi.creation.BrooklynEntityMatcher;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
@@ -32,12 +34,15 @@ import brooklyn.management.osgi.OsgiVersionMoreEntityTest;
 import brooklyn.policy.Policy;
 import brooklyn.test.TestResourceUnavailableException;
 import brooklyn.util.ResourceUtils;
+import brooklyn.util.text.Strings;
 
 import com.google.common.collect.Iterables;
 
 /** Many of the same tests as per {@link OsgiVersionMoreEntityTest} but using YAML for catalog and entities, so catalog item ID is set automatically */
 public class CatalogOsgiVersionMoreEntityTest extends AbstractYamlTest {
     
+    private static final Logger log = LoggerFactory.getLogger(CatalogOsgiVersionMoreEntityTest.class);
+    
     private static String getLocalResource(String filename) {
         return ResourceUtils.create(CatalogOsgiVersionMoreEntityTest.class).getResourceAsString(
             "classpath:/"+CatalogOsgiVersionMoreEntityTest.class.getPackage().getName().replace('.', '/')+"/"+filename);
@@ -47,7 +52,7 @@ public class CatalogOsgiVersionMoreEntityTest extends AbstractYamlTest {
     public void testMoreEntityV1() throws Exception {
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar");
 
-        addCatalogItem(getLocalResource("more-entity-v1-osgi-catalog.yaml"));
+        addCatalogItems(getLocalResource("more-entity-v1-osgi-catalog.yaml"));
         CatalogItem<?, ?> item = CatalogUtils.getCatalogItemOptionalVersion(mgmt(), "more-entity");
         Assert.assertNotNull(item);
         Assert.assertEquals(item.getVersion(), "1.0");
@@ -69,8 +74,8 @@ public class CatalogOsgiVersionMoreEntityTest extends AbstractYamlTest {
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar");
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-entities.jar");
 
-        addCatalogItem(getLocalResource("simple-policy-osgi-catalog.yaml"));
-        addCatalogItem(getLocalResource("more-entity-v1-with-policy-osgi-catalog.yaml"));
+        addCatalogItems(getLocalResource("simple-policy-osgi-catalog.yaml"));
+        addCatalogItems(getLocalResource("more-entity-v1-with-policy-osgi-catalog.yaml"));
         Entity app = createAndStartApplication("services: [ { type: 'more-entity:1.0' } ]");
         Entity moreEntity = Iterables.getOnlyElement(app.getChildren());
         
@@ -87,7 +92,7 @@ public class CatalogOsgiVersionMoreEntityTest extends AbstractYamlTest {
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar");
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-entities.jar");
 
-        addCatalogItem(getLocalResource("more-entity-v2-osgi-catalog.yaml"));
+        addCatalogItems(getLocalResource("more-entity-v2-osgi-catalog.yaml"));
         Entity app = createAndStartApplication("services: [ { type: 'more-entity:1.0' } ]");
         Entity moreEntity = Iterables.getOnlyElement(app.getChildren());
         
@@ -108,9 +113,9 @@ public class CatalogOsgiVersionMoreEntityTest extends AbstractYamlTest {
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar");
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-entities.jar");
 
-        addCatalogItem(getLocalResource("more-entity-v2-osgi-catalog.yaml"));
+        addCatalogItems(getLocalResource("more-entity-v2-osgi-catalog.yaml"));
         forceCatalogUpdate();
-        addCatalogItem(getLocalResource("more-entity-v1-osgi-catalog.yaml"));
+        addCatalogItems(getLocalResource("more-entity-v1-osgi-catalog.yaml"));
         Entity app = createAndStartApplication("services: [ { type: 'more-entity:1.0' } ]");
         Entity moreEntity = Iterables.getOnlyElement(app.getChildren());
         
@@ -127,9 +132,9 @@ public class CatalogOsgiVersionMoreEntityTest extends AbstractYamlTest {
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar");
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-entities.jar");
 
-        addCatalogItem(getLocalResource("more-entity-v1-osgi-catalog.yaml"));
+        addCatalogItems(getLocalResource("more-entity-v1-osgi-catalog.yaml"));
         forceCatalogUpdate();
-        addCatalogItem(getLocalResource("more-entity-v2-osgi-catalog.yaml"));
+        addCatalogItems(getLocalResource("more-entity-v2-osgi-catalog.yaml"));
         Entity app = createAndStartApplication("services: [ { type: 'more-entity:1.0' } ]");
         Entity moreEntity = Iterables.getOnlyElement(app.getChildren());
         
@@ -143,8 +148,8 @@ public class CatalogOsgiVersionMoreEntityTest extends AbstractYamlTest {
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar");
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-entities.jar");
 
-        addCatalogItem(getLocalResource("more-entity-v1-called-v1-osgi-catalog.yaml"));
-        addCatalogItem(getLocalResource("more-entity-v2-osgi-catalog.yaml"));
+        addCatalogItems(getLocalResource("more-entity-v1-called-v1-osgi-catalog.yaml"));
+        addCatalogItems(getLocalResource("more-entity-v2-osgi-catalog.yaml"));
         Entity v1 = createAndStartApplication("services: [ { type: 'more-entity-v1:1.0' } ]");
         Entity v2 = createAndStartApplication("services: [ { type: 'more-entity:1.0' } ]");
         
@@ -158,5 +163,32 @@ public class CatalogOsgiVersionMoreEntityTest extends AbstractYamlTest {
         OsgiVersionMoreEntityTest.assertV2MethodCall(moreEntityV2);
     }
 
+    @Test
+    public void testMoreEntityV2AutoscanWithClasspath() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar");
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-entities.jar");
+        
+        addCatalogItems(getLocalResource("more-entities-osgi-catalog-scan.yaml"));
+        
+        log.info("autoscan for osgi found catalog items: "+Strings.join(mgmt().getCatalog().getCatalogItems(), ", "));
+
+        CatalogItem<?, ?> item = CatalogUtils.getCatalogItemOptionalVersion(mgmt(), "more-entity");
+        Assert.assertNotNull(item);
+        Assert.assertEquals(item.getVersion(), "2.0.test");
+        Assert.assertEquals(item.getCatalogItemType(), CatalogItemType.ENTITY);
+        
+        // this refers to the java item, where the libraries are defined
+        item = CatalogUtils.getCatalogItemOptionalVersion(mgmt(), "brooklyn.osgi.tests.more.MoreEntity");
+        Assert.assertEquals(item.getVersion(), "2.0.test_java");
+        Assert.assertEquals(item.getLibraries().size(), 2);
+        
+        Entity app = createAndStartApplication("services: [ { type: 'more-entity:2.0.test' } ]");
+        Entity moreEntity = Iterables.getOnlyElement(app.getChildren());
+        
+        Assert.assertEquals(moreEntity.getCatalogItemId(), "more-entity:2.0.test");
+        OsgiVersionMoreEntityTest.assertV2EffectorCall(moreEntity);
+        OsgiVersionMoreEntityTest.assertV2MethodCall(moreEntity);
+    }
+
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1207d991/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlCombiTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlCombiTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlCombiTest.java
index cbb1d1e..4b33276 100644
--- a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlCombiTest.java
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlCombiTest.java
@@ -44,7 +44,7 @@ public class CatalogYamlCombiTest extends AbstractYamlTest {
     
     @Test
     public void testBRefEntityA() throws Exception {
-        addCatalogItem(
+        addCatalogItems(
             "brooklyn.catalog:",
             "  version: "+TEST_VERSION,
             "  items:",
@@ -86,7 +86,7 @@ public class CatalogYamlCombiTest extends AbstractYamlTest {
 
     @Test
     public void testBRefPolicyALocationZ() throws Exception {
-        addCatalogItem(
+        addCatalogItems(
             "brooklyn.catalog:",
             "  version: "+TEST_VERSION,
             "  id: Z",
@@ -94,7 +94,7 @@ public class CatalogYamlCombiTest extends AbstractYamlTest {
             "  - item: ",
             "      type: localhost",
             "      brooklyn.config: { z: 9 }");
-        addCatalogItem(
+        addCatalogItems(
             "brooklyn.catalog:",
             "  version: "+TEST_VERSION,
             "  items:",

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1207d991/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
index 9353108..af3d0b8 100644
--- a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
@@ -52,7 +52,7 @@ public class CatalogYamlEntityTest extends AbstractYamlTest {
     @Test
     public void testAddCatalogItemVerySimple() throws Exception {
         String symbolicName = "my.catalog.app.id.load";
-        addCatalogItem(
+        addCatalogItems(
             "brooklyn.catalog:",
             "  id: " + symbolicName,
             "  version: " + TEST_VERSION,
@@ -81,7 +81,7 @@ public class CatalogYamlEntityTest extends AbstractYamlTest {
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
 
         String symbolicName = "my.catalog.app.id.load";
-        addCatalogItem(
+        addCatalogItems(
             "brooklyn.catalog:",
             "  id: " + symbolicName,
             "  name: My Catalog App",
@@ -103,7 +103,7 @@ public class CatalogYamlEntityTest extends AbstractYamlTest {
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
 
         String symbolicName = "my.catalog.app.id.load";
-        addCatalogItem(
+        addCatalogItems(
             "brooklyn.catalog:",
             "  id: " + symbolicName,
             "  name: My Catalog App",
@@ -126,7 +126,7 @@ public class CatalogYamlEntityTest extends AbstractYamlTest {
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
 
         String symbolicName = "my.catalog.app.id.load";
-        addCatalogItem(
+        addCatalogItems(
             "brooklyn.catalog:",
             "  id: " + symbolicName,
             "  name: My Catalog App",
@@ -150,7 +150,7 @@ public class CatalogYamlEntityTest extends AbstractYamlTest {
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
 
         String id = "unversioned.app";
-        addCatalogItem(
+        addCatalogItems(
             "brooklyn.catalog:",
             "  name: " + id,
             "  libraries:",
@@ -167,7 +167,7 @@ public class CatalogYamlEntityTest extends AbstractYamlTest {
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
 
         String id = "inline_version.app";
-        addCatalogItem(
+        addCatalogItems(
             "brooklyn.catalog:",
             "  name: " + id+":"+TEST_VERSION,
             "  libraries:",
@@ -357,7 +357,7 @@ public class CatalogYamlEntityTest extends AbstractYamlTest {
 
         String firstItemId = "my.catalog.app.id.register_bundle";
         String secondItemId = "my.catalog.app.id.reference_bundle";
-        addCatalogItem(
+        addCatalogItems(
             "brooklyn.catalog:",
             "  id: " + firstItemId,
             "  version: " + TEST_VERSION,
@@ -368,7 +368,7 @@ public class CatalogYamlEntityTest extends AbstractYamlTest {
             "- type: " + SIMPLE_ENTITY_TYPE);
         deleteCatalogEntity(firstItemId);
 
-        addCatalogItem(
+        addCatalogItems(
             "brooklyn.catalog:",
             "  id: " + secondItemId,
             "  version: " + TEST_VERSION,
@@ -387,7 +387,7 @@ public class CatalogYamlEntityTest extends AbstractYamlTest {
         String nonExistentId = "none-existent-id";
         String nonExistentVersion = "9.9.9";
         try {
-            addCatalogItem(
+            addCatalogItems(
                 "brooklyn.catalog:",
                 "  id: my.catalog.app.id.non_existing.ref",
                 "  version: " + TEST_VERSION,
@@ -406,7 +406,7 @@ public class CatalogYamlEntityTest extends AbstractYamlTest {
     @Test
     public void testPartialBundleReferenceFails() {
         try {
-            addCatalogItem(
+            addCatalogItems(
                 "brooklyn.catalog:",
                 "  id: my.catalog.app.id.non_existing.ref",
                 "  version: " + TEST_VERSION,
@@ -420,7 +420,7 @@ public class CatalogYamlEntityTest extends AbstractYamlTest {
             Assert.assertEquals(e.getMessage(), "version");
         }
         try {
-            addCatalogItem(
+            addCatalogItems(
                 "brooklyn.catalog:",
                 "  id: my.catalog.app.id.non_existing.ref",
                 "  version: " + TEST_VERSION,
@@ -440,7 +440,7 @@ public class CatalogYamlEntityTest extends AbstractYamlTest {
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
 
         String itemId = "my.catalog.app.id.full_ref";
-        addCatalogItem(
+        addCatalogItems(
             "brooklyn.catalog:",
             "  id: " + itemId,
             "  version: " + TEST_VERSION,
@@ -466,7 +466,7 @@ public class CatalogYamlEntityTest extends AbstractYamlTest {
         String nonExistentId = "non_existent_id";
         String nonExistentVersion = "9.9.9";
         try {
-            addCatalogItem(
+            addCatalogItems(
                 "brooklyn.catalog:",
                 "  id: " + firstItemId,
                 "  version: " + TEST_VERSION,
@@ -545,7 +545,7 @@ public class CatalogYamlEntityTest extends AbstractYamlTest {
     @Test
     public void testMissingTypeDoesNotRecurse() {
         String symbolicName = "my.catalog.app.id.basic";
-        addCatalogItem(
+        addCatalogItems(
             "brooklyn.catalog:",
             "  id: " + symbolicName,
             "  version: " + TEST_VERSION,
@@ -554,7 +554,7 @@ public class CatalogYamlEntityTest extends AbstractYamlTest {
             "- type: brooklyn.entity.basic.BasicEntity");
 
         try {
-            addCatalogItem(
+            addCatalogItems(
                     "brooklyn.catalog:",
                     "  id: " + symbolicName,
                     "  version: " + TEST_VERSION + "-update",
@@ -570,7 +570,7 @@ public class CatalogYamlEntityTest extends AbstractYamlTest {
     @Test
     public void testVersionedTypeDoesNotRecurse() {
         String symbolicName = "my.catalog.app.id.basic";
-        addCatalogItem(
+        addCatalogItems(
             "brooklyn.catalog:",
             "  id: " + symbolicName,
             "  version: " + TEST_VERSION,
@@ -580,7 +580,7 @@ public class CatalogYamlEntityTest extends AbstractYamlTest {
 
         String versionedId = CatalogUtils.getVersionedId(symbolicName, TEST_VERSION);
         try {
-            addCatalogItem(
+            addCatalogItems(
                 "brooklyn.catalog:",
                 "  id: " + symbolicName,
                 "  version: " + TEST_VERSION + "-update",
@@ -597,7 +597,7 @@ public class CatalogYamlEntityTest extends AbstractYamlTest {
     public void testOsgiNotLeakingToParent() {
         addCatalogOSGiEntity(SIMPLE_ENTITY_TYPE);
         try {
-            addCatalogItem(
+            addCatalogItems(
                     "brooklyn.catalog:",
                     "  id: " + SIMPLE_ENTITY_TYPE,
                     "  version: " + TEST_VERSION + "-update",
@@ -633,7 +633,7 @@ public class CatalogYamlEntityTest extends AbstractYamlTest {
     }
     
     private void addCatalogOSGiEntity(String symbolicName, String serviceType, boolean extraLib) {
-        addCatalogItem(
+        addCatalogItems(
             "brooklyn.catalog:",
             "  id: " + symbolicName,
             "  name: My Catalog App",
@@ -665,10 +665,10 @@ public class CatalogYamlEntityTest extends AbstractYamlTest {
             "      type: " + namesAndTypes[i+1]));
         }
             
-        addCatalogItem(lines);
+        addCatalogItems(lines);
     }
     private void addCatalogChildOSGiEntityWithServicesBlock(String symbolicName, String serviceType) {
-        addCatalogItem(
+        addCatalogItems(
             "brooklyn.catalog:",
             "  id: " + symbolicName,
             "  name: My Catalog App",
@@ -684,7 +684,7 @@ public class CatalogYamlEntityTest extends AbstractYamlTest {
             "      - type: " + serviceType);
     }
     private void addCatalogChildOSGiEntity(String symbolicName, String serviceType) {
-        addCatalogItem(
+        addCatalogItems(
             "brooklyn.catalog:",
             "  id: " + symbolicName,
             "  name: My Catalog App",

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1207d991/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
index c0d41d2..bfc8a9a 100644
--- a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
@@ -216,7 +216,7 @@ public class CatalogYamlLocationTest extends AbstractYamlTest {
                 "      config2: config2");
         
         
-        addCatalogItem(yaml.build());
+        addCatalogItems(yaml.build());
     }
 
     private void addCatalogLocationTopLevelItemSyntax(String symbolicName, String locationType, List<String> libraries) {
@@ -239,7 +239,7 @@ public class CatalogYamlLocationTest extends AbstractYamlTest {
                 "    config2: config2");
         
         
-        addCatalogItem(yaml.build());
+        addCatalogItems(yaml.build());
     }
 
     private int countCatalogLocations() {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1207d991/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java
index d38fee0..f007bae 100644
--- a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java
@@ -121,7 +121,7 @@ public class CatalogYamlPolicyTest extends AbstractYamlTest {
         String referrerSymbolicName = "my.catalog.policy.id.referring";
         addCatalogOsgiPolicy(referencedSymbolicName, SIMPLE_POLICY_TYPE);
 
-        addCatalogItem(
+        addCatalogItems(
             "brooklyn.catalog:",
             "  id: " + referrerSymbolicName,
             "  name: My Catalog App",
@@ -153,7 +153,7 @@ public class CatalogYamlPolicyTest extends AbstractYamlTest {
     private void addCatalogOsgiPolicy(String symbolicName, String policyType) {
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
 
-        addCatalogItem(
+        addCatalogItems(
             "brooklyn.catalog:",
             "  id: " + symbolicName,
             "  name: My Catalog Policy",
@@ -172,7 +172,7 @@ public class CatalogYamlPolicyTest extends AbstractYamlTest {
     private void addCatalogOsgiPolicyTopLevelSyntax(String symbolicName, String policyType) {
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
 
-        addCatalogItem(
+        addCatalogItems(
             "brooklyn.catalog:",
             "  id: " + symbolicName,
             "  name: My Catalog Policy",

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1207d991/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlTemplateTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlTemplateTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlTemplateTest.java
index 8fbcf65..d5a5b9c 100644
--- a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlTemplateTest.java
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlTemplateTest.java
@@ -66,7 +66,7 @@ public class CatalogYamlTemplateTest extends AbstractYamlTest {
     private CatalogItem<?, ?> makeItem() {
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
         
-        addCatalogItem(
+        addCatalogItems(
             "brooklyn.catalog:",
             "  id: t1",
             "  item_type: template",

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1207d991/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlVersioningTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlVersioningTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlVersioningTest.java
index dda60dc..4e43656 100644
--- a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlVersioningTest.java
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlVersioningTest.java
@@ -182,7 +182,7 @@ public class CatalogYamlVersioningTest extends AbstractYamlTest {
     }
 
     private void doTestVersionedReferenceJustAdded(boolean isVersionImplicitSyntax) throws Exception {
-        addCatalogItem(            "brooklyn.catalog:",
+        addCatalogItems(            "brooklyn.catalog:",
             "  version: 0.9",
             "  items:",
             "  - id: referrent",
@@ -243,7 +243,7 @@ public class CatalogYamlVersioningTest extends AbstractYamlTest {
     }
     
     private void addCatalogEntity(String symbolicName, String version, String type, String iconUrl) {
-        addCatalogItem(
+        addCatalogItems(
             "brooklyn.catalog:",
             "  id: " + symbolicName,
             "  name: My Catalog App",

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1207d991/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entities-osgi-catalog-scan.yaml
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entities-osgi-catalog-scan.yaml b/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entities-osgi-catalog-scan.yaml
new file mode 100644
index 0000000..852d9e1
--- /dev/null
+++ b/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entities-osgi-catalog-scan.yaml
@@ -0,0 +1,32 @@
+#
+# 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.
+#
+
+# test case which demonstrates osgi bundles can be scanned, *if* expand classpath is true
+
+brooklyn.catalog:
+  items:
+  - scanJavaAnnotations: true
+    version: 2.0.test_java
+    libraries:
+    - classpath:/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar
+    - classpath:/brooklyn/osgi/brooklyn-test-osgi-entities.jar
+  - item:
+      id: more-entity
+      type: brooklyn.osgi.tests.more.MoreEntity
+      version: 2.0.test

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1207d991/utils/common/src/main/java/brooklyn/util/os/Os.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/os/Os.java b/utils/common/src/main/java/brooklyn/util/os/Os.java
index 3cd1ccb..5278988 100644
--- a/utils/common/src/main/java/brooklyn/util/os/Os.java
+++ b/utils/common/src/main/java/brooklyn/util/os/Os.java
@@ -523,10 +523,10 @@ public class Os {
      * either prefix or ext may be null; 
      * if ext is non-empty and not > 4 chars and not starting with a ., then a dot will be inserted */
     public static File newTempFile(String prefix, String ext) {
-        String sanitizedPrefix = (prefix!=null ? prefix + "-" : "");
-        String sanitizedExt = (ext!=null ? ext.startsWith(".") || ext.length()>4 ? ext : "."+ext : "");
+        String sanitizedPrefix = (Strings.isNonEmpty(prefix) ? Strings.makeValidFilename(prefix) + "-" : "");
+        String extWithPrecedingSeparator = (Strings.isNonEmpty(ext) ? ext.startsWith(".") || ext.length()>4 ? ext : "."+ext : "");
         try {
-            File tempFile = File.createTempFile(sanitizedPrefix, sanitizedExt, new File(tmp()));
+            File tempFile = File.createTempFile(sanitizedPrefix, extWithPrecedingSeparator, new File(tmp()));
             tempFile.deleteOnExit();
             return tempFile;
         } catch (IOException e) {