You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by al...@apache.org on 2014/07/09 23:46:46 UTC

[33/50] git commit: Fix recursive call (catalog type == java type)

Fix recursive call (catalog type == java type)


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

Branch: refs/heads/master
Commit: d8c42328ee6e6008c5647153f78846aef745de3a
Parents: c006d20
Author: Aled Sage <al...@gmail.com>
Authored: Tue Jul 8 10:42:31 2014 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Jul 9 22:34:46 2014 +0100

----------------------------------------------------------------------
 .../BrooklynAssemblyTemplateInstantiator.java   |  29 ++++-
 .../BrooklynComponentTemplateResolver.java      |   8 +-
 .../resources/CatalogBundleResourceTest.java    | 128 +++++++++++--------
 3 files changed, 106 insertions(+), 59 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d8c42328/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
index 844fd41..590f35d 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
@@ -58,6 +58,7 @@ import brooklyn.util.flags.TypeCoercions;
 
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
 
 public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpecInstantiator {
 
@@ -213,20 +214,36 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
     }
 
     private List<EntitySpec<?>> buildTemplateServicesAsSpecs(BrooklynClassLoadingContext loader, AssemblyTemplate template, CampPlatform platform) {
+        return buildTemplateServicesAsSpecsImpl(loader, template, platform, Sets.<String>newLinkedHashSet());
+    }
+
+    private List<EntitySpec<?>> buildTemplateServicesAsSpecsImpl(BrooklynClassLoadingContext loader, AssemblyTemplate template, CampPlatform platform, Set<String> encounteredCatalogTypes) {
         List<EntitySpec<?>> result = Lists.newArrayList();
         
         for (ResolvableLink<PlatformComponentTemplate> ctl: template.getPlatformComponentTemplates().links()) {
             PlatformComponentTemplate appChildComponentTemplate = ctl.resolve();
             BrooklynComponentTemplateResolver entityResolver = BrooklynComponentTemplateResolver.Factory.newInstance(loader, appChildComponentTemplate);
             ManagementContext mgmt = loader.getManagementContext();
-            
+
+            String catalogIdOrJavaType = entityResolver.getCatalogIdOrJavaType();
+
             EntitySpec<?> spec;
             
             CatalogItem<Entity, EntitySpec<?>> item = entityResolver.getCatalogItem();
+            
+            // FIXME
+            log.warn("buildTemplateServicesAsSpecsImpl: catalogIdOrJavaType="+catalogIdOrJavaType+"; item="+item+"; loader="+loader+"; template="+template+"; encounteredCatalogTypes="+encounteredCatalogTypes);
+
+
             if (item == null || item.getJavaType() != null) {
                 spec = entityResolver.resolveSpec();
             } else {
-                spec = resolveCatalogYamlReferenceSpec(platform, mgmt, item);
+                boolean firstOccurrence = encounteredCatalogTypes.add(catalogIdOrJavaType);
+                if (firstOccurrence) {
+                    spec = resolveCatalogYamlReferenceSpec(platform, mgmt, item, encounteredCatalogTypes);
+                } else {
+                    throw new IllegalStateException("Recursive reference to " + catalogIdOrJavaType);
+                }
             }
 
             BrooklynClassLoadingContext newLoader = entityResolver.loader;
@@ -239,7 +256,9 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
 
     private EntitySpec<?> resolveCatalogYamlReferenceSpec(CampPlatform platform,
             ManagementContext mgmt,
-            CatalogItem<Entity, EntitySpec<?>> item) {
+            CatalogItem<Entity, EntitySpec<?>> item,
+            Set<String> encounteredCatalogTypes) {
+        
         String yaml = item.getPlanYaml();
         Reader input = new StringReader(yaml);
         
@@ -257,9 +276,9 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
         try {
             AssemblyTemplateInstantiator ati = at.getInstantiator().newInstance();
             if (ati instanceof BrooklynAssemblyTemplateInstantiator) {
-                List<EntitySpec<?>> specs = ((BrooklynAssemblyTemplateInstantiator)ati).buildTemplateServicesAsSpecs(itemLoader, at, platform);
+                List<EntitySpec<?>> specs = ((BrooklynAssemblyTemplateInstantiator)ati).buildTemplateServicesAsSpecsImpl(itemLoader, at, platform, encounteredCatalogTypes);
                 if (specs.size() > 1) {
-                    throw new UnsupportedOperationException("Only supporting single service in catalog item currently");
+                    throw new UnsupportedOperationException("Only supporting single service in catalog item currently: got "+specs);
                 }
                 return specs.get(0);
             } else {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d8c42328/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 61984af..770b97f 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
@@ -191,8 +191,14 @@ public class BrooklynComponentTemplateResolver {
 
     /** returns the entity class, if needed in contexts which scan its statics for example */
     public Class<? extends Entity> loadEntityClass() {
+        return tryLoadEntityClass().get();
+    }
+    
+    /** tries to load the Java entity class */
+    public Maybe<Class<? extends Entity>> tryLoadEntityClass() {
         CatalogItem<Entity, EntitySpec<?>> item = getCatalogItem();
         String typeName = getCatalogIdOrJavaType();
+        
         if (item!=null) {
             // add additional bundles
             loader = new BrooklynClassLoadingContextSequential(mgmt, item.newClassLoadingContext(mgmt), loader);
@@ -214,7 +220,7 @@ public class BrooklynComponentTemplateResolver {
             }
         }
         
-        return loader.loadClass(typeName, Entity.class);
+        return loader.tryLoadClass(typeName, Entity.class);
     }
 
     /** resolves the spec, updating the loader if a catalog item is loaded */

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d8c42328/usage/rest-server/src/test/java/brooklyn/rest/resources/CatalogBundleResourceTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/brooklyn/rest/resources/CatalogBundleResourceTest.java b/usage/rest-server/src/test/java/brooklyn/rest/resources/CatalogBundleResourceTest.java
index 2fc3102..9780d30 100644
--- a/usage/rest-server/src/test/java/brooklyn/rest/resources/CatalogBundleResourceTest.java
+++ b/usage/rest-server/src/test/java/brooklyn/rest/resources/CatalogBundleResourceTest.java
@@ -1,8 +1,10 @@
 package brooklyn.rest.resources;
 
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertTrue;
 
+import java.io.InputStream;
 import java.net.URI;
 
 import javax.ws.rs.core.Response;
@@ -15,6 +17,7 @@ import brooklyn.management.osgi.OsgiStandaloneTest;
 import brooklyn.rest.domain.ApplicationSummary;
 import brooklyn.rest.domain.CatalogEntitySummary;
 import brooklyn.rest.testing.BrooklynRestResourceTest;
+import brooklyn.util.stream.Streams;
 
 import com.google.common.collect.Iterables;
 import com.sun.jersey.api.client.ClientResponse;
@@ -37,29 +40,19 @@ public class CatalogBundleResourceTest extends BrooklynRestResourceTest {
     @Test
     public void testLaunchApplicationYaml() throws Exception {
         String registeredTypeName = "my.catalog.app.id.launch";
-        registerAndLaunch(registeredTypeName, SIMPLE_ENTITY_TYPE);
+        registerAndLaunchAndAssertSimpleEntity(registeredTypeName, SIMPLE_ENTITY_TYPE);
     }
 
     @Test
-    public void testLaunchApplicationLoopYaml() throws Exception {
-        String registeredTypeName = "my.catalog.app.id.launch";
-        registerAndLaunch(registeredTypeName, registeredTypeName);
-    }
+    public void testLaunchApplicationWithCatalogReferencingOtherCatalogYaml() throws Exception {
+        String referencedRegisteredTypeName = "my.catalog.app.id.referenced";
+        String referrerRegisteredTypeName = "my.catalog.app.id.referring";
+        addCatalogOSGiEntity(referencedRegisteredTypeName, SIMPLE_ENTITY_TYPE);
+        addCatalogOSGiEntity(referrerRegisteredTypeName, referencedRegisteredTypeName);
 
-    private void registerAndLaunch(String registeredTypeName, String catalogServiceType) {
-        addCatalogOSGiEntity(registeredTypeName, catalogServiceType);
+        String yaml = "{ name: simple-app-yaml, location: localhost, services: [ { serviceType: "+referrerRegisteredTypeName+" } ] }";
+        ApplicationSummary appSummary = createAndWaitForApp(yaml);
 
-        String yaml = "{ name: simple-app-yaml, location: localhost, services: [ { serviceType: "+registeredTypeName+" } ] }";
-        
-        ClientResponse response = client().resource("/v1/applications")
-            .entity(yaml, "application/x-yaml")
-            .post(ClientResponse.class);
-        assertTrue(response.getStatus()/100 == 2, "response is "+response);
-        
-        // Expect app to be running
-        URI appUri = response.getLocation();
-        waitForApplicationToBeRunning(response.getLocation());
-        ApplicationSummary appSummary = client().resource(appUri).get(ApplicationSummary.class);
         String appId = appSummary.getId();
         assertEquals(appSummary.getSpec().getName(), "simple-app-yaml");
 
@@ -69,23 +62,23 @@ public class CatalogBundleResourceTest extends BrooklynRestResourceTest {
     }
 
     @Test
-    public void testLaunchApplicationWithCatalogReferencingOtherCatalogYaml() throws Exception {
-        String referencedRegisteredTypeName = "my.catalog.app.id.referenced";
-        String referrerRegisteredTypeName = "my.catalog.app.id.referring";
-        addCatalogOSGiEntity(referencedRegisteredTypeName);
-        addCatalogEntityReferencingCatalogEntry(referrerRegisteredTypeName, referencedRegisteredTypeName);
+    public void testLaunchApplicationLoopWithJavaTypeNameInYamlFails() throws Exception {
+        String registeredTypeName = SIMPLE_ENTITY_TYPE;
+        registerAndLaunchFailsWithRecursionError(registeredTypeName, registeredTypeName);
+    }
+
+    @Test
+    public void testLaunchApplicationLoopCatalogIdInYamlFails() throws Exception {
+        String registeredTypeName = "self.referencing.type";
+        registerAndLaunchFailsWithRecursionError(registeredTypeName, registeredTypeName);
+    }
+
+    private void registerAndLaunchAndAssertSimpleEntity(String registeredTypeName, String serviceType) {
+        addCatalogOSGiEntity(registeredTypeName, serviceType);
+
+        String yaml = "{ name: simple-app-yaml, location: localhost, services: [ { serviceType: "+registeredTypeName+" } ] }";
+        ApplicationSummary appSummary = createAndWaitForApp(yaml);
 
-        String yaml = "{ name: simple-app-yaml, location: localhost, services: [ { serviceType: "+referrerRegisteredTypeName+" } ] }";
-        
-        ClientResponse response = client().resource("/v1/applications")
-            .entity(yaml, "application/x-yaml")
-            .post(ClientResponse.class);
-        assertTrue(response.getStatus()/100 == 2, "response is "+response);
-        
-        // Expect app to be running
-        URI appUri = response.getLocation();
-        waitForApplicationToBeRunning(response.getLocation());
-        ApplicationSummary appSummary = client().resource(appUri).get(ApplicationSummary.class);
         String appId = appSummary.getId();
         assertEquals(appSummary.getSpec().getName(), "simple-app-yaml");
 
@@ -94,12 +87,41 @@ public class CatalogBundleResourceTest extends BrooklynRestResourceTest {
         assertEquals(simpleEntity.getEntityType().getName(), SIMPLE_ENTITY_TYPE);
     }
 
+    private void registerAndLaunchFailsWithRecursionError(String registeredTypeName, String serviceType) {
+        addCatalogOSGiEntity(registeredTypeName, serviceType);
+        try {
+            String yaml = "{ name: simple-app-yaml, location: localhost, services: [ { serviceType: "+registeredTypeName+" } ] }";
+            ClientResponse response = client().resource("/v1/applications")
+                    .entity(yaml, "application/x-yaml")
+                    .post(ClientResponse.class);
+    
+            int responseStatus = response.getStatus();
+            String responseContent = getResponseContentAsString(response);
+    
+            assertFalse(responseStatus/100 == 2, "response="+response+"; content="+responseContent);
+            assertTrue(responseContent.contains("Recursive reference to "+registeredTypeName), "content="+responseContent);
+        } finally {
+            deleteCatalogEntity(registeredTypeName);
+        }
+    }
+
+    private ApplicationSummary createAndWaitForApp(String yaml) {
+        ClientResponse response = client().resource("/v1/applications")
+                .entity(yaml, "application/x-yaml")
+                .post(ClientResponse.class);
+        assertTrue(response.getStatus()/100 == 2, "response is "+response);
+
+        URI appUri = response.getLocation();
+        waitForApplicationToBeRunning(response.getLocation());
+        
+        return client().resource(appUri).get(ApplicationSummary.class);
+    }
     
     private void addCatalogOSGiEntity(String registeredTypeName) {
         addCatalogOSGiEntity(registeredTypeName, SIMPLE_ENTITY_TYPE);
     }
     
-    private void addCatalogOSGiEntity(String registeredTypeName, String catalogServiceType) {
+    private void addCatalogOSGiEntity(String registeredTypeName, String serviceType) {
         String catalogYaml =
             "name: "+registeredTypeName+"\n"+
             // FIXME name above should be unnecessary when brooklyn.catalog below is working
@@ -113,24 +135,7 @@ public class CatalogBundleResourceTest extends BrooklynRestResourceTest {
             "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL + "\n"+
             "\n"+
             "services:\n"+
-            "- type: " + catalogServiceType;
-
-        addCatalogEntity(catalogYaml);
-    }
-
-    private void addCatalogEntityReferencingCatalogEntry(String ownRegisteredTypeName, String otherRegisteredTypeName) {
-        String catalogYaml =
-            "name: "+ownRegisteredTypeName+"\n"+
-            // FIXME name above should be unnecessary when brooklyn.catalog below is working
-            "brooklyn.catalog:\n"+
-            "  id: " + ownRegisteredTypeName + "\n"+
-            "  name: My Referrer Catalog App\n"+
-            "  description: My referrer description\n"+
-            "  icon_url: classpath://path/to/myicon.jpg\n"+
-            "  version: 0.2.1\n"+
-            "\n"+
-            "services:\n"+
-            "- type: "+otherRegisteredTypeName+"\n";
+            "- type: " + serviceType;
 
         addCatalogEntity(catalogYaml);
     }
@@ -141,4 +146,21 @@ public class CatalogBundleResourceTest extends BrooklynRestResourceTest {
 
         assertEquals(catalogResponse.getStatus(), Response.Status.CREATED.getStatusCode());
     }
+    
+    private void deleteCatalogEntity(String catalogItem) {
+        ClientResponse catalogResponse = client().resource("/v1/catalog/entities/"+catalogItem)
+            .delete(ClientResponse.class);
+
+        assertEquals(catalogResponse.getStatus(), Response.Status.NO_CONTENT.getStatusCode());
+    }
+    
+    private String getResponseContentAsString(ClientResponse response) {
+        InputStream in = null;
+        try {
+            in = response.getEntityInputStream();
+            return new String(Streams.readFully(in));
+        } finally {
+            Streams.closeQuietly(in);
+        }
+    }
 }