You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by sj...@apache.org on 2014/08/27 12:02:18 UTC

[1/6] git commit: Simplifies WebApplicationException class

Repository: incubator-brooklyn
Updated Branches:
  refs/heads/master 5e25133a8 -> 4a2fc266f


Simplifies WebApplicationException class


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

Branch: refs/heads/master
Commit: c74288157552a8b00a8f40d55f3a0c6403840078
Parents: 63e9f1e
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Fri Aug 22 15:00:56 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Fri Aug 22 15:00:56 2014 +0100

----------------------------------------------------------------------
 .../java/brooklyn/rest/domain/ApiError.java     |  4 ++
 .../brooklyn/rest/util/WebResourceUtils.java    | 39 ++++++++++----------
 2 files changed, 24 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c7428815/usage/rest-api/src/main/java/brooklyn/rest/domain/ApiError.java
----------------------------------------------------------------------
diff --git a/usage/rest-api/src/main/java/brooklyn/rest/domain/ApiError.java b/usage/rest-api/src/main/java/brooklyn/rest/domain/ApiError.java
index dd3dcbc..e2689f4 100644
--- a/usage/rest-api/src/main/java/brooklyn/rest/domain/ApiError.java
+++ b/usage/rest-api/src/main/java/brooklyn/rest/domain/ApiError.java
@@ -122,6 +122,10 @@ public class ApiError {
     @JsonSerialize(include=Inclusion.NON_EMPTY)
     private final String details;
 
+    public ApiError(String message) {
+        this(message, null);
+    }
+
     public ApiError(
             @JsonProperty("message") String message,
             @JsonProperty("details") String details) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c7428815/usage/rest-server/src/main/java/brooklyn/rest/util/WebResourceUtils.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/util/WebResourceUtils.java b/usage/rest-server/src/main/java/brooklyn/rest/util/WebResourceUtils.java
index 6c1c2c1..2ef77a4 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/util/WebResourceUtils.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/util/WebResourceUtils.java
@@ -38,40 +38,41 @@ public class WebResourceUtils {
 
     private static final Logger log = LoggerFactory.getLogger(WebResourceUtils.class);
 
-    /** @throws WebApplicationException With code 400 bad request */
-    public static WebApplicationException badRequest(String format, Object... args) {
+    /** @throws WebApplicationException with an ApiError as its body and the given status as its response code. */
+    public static WebApplicationException throwWebApplicationException(Response.Status status, String format, Object... args) {
         String msg = String.format(format, args);
-        if (log.isDebugEnabled()) log.debug("returning 400 bad request ("+msg+")");
-        throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
+        if (log.isDebugEnabled()) {
+            log.debug("responding {} {} ({})",
+                    new Object[]{status.getStatusCode(), status.getReasonPhrase(), msg});
+        }
+        throw new WebApplicationException(Response.status(status)
                 .type(MediaType.APPLICATION_JSON_TYPE)
                 .entity(ApiError.builder().message(msg).build()).build());
     }
 
+    /** @throws WebApplicationException With code 500 internal server error */
+    public static WebApplicationException serverError(String format, Object... args) {
+        return throwWebApplicationException(Response.Status.INTERNAL_SERVER_ERROR, format, args);
+    }
+
+    /** @throws WebApplicationException With code 400 bad request */
+    public static WebApplicationException badRequest(String format, Object... args) {
+        return throwWebApplicationException(Response.Status.BAD_REQUEST, format, args);
+    }
+
     /** @throws WebApplicationException With code 401 unauthorized */
     public static WebApplicationException unauthorized(String format, Object... args) {
-        String msg = String.format(format, args);
-        if (log.isDebugEnabled()) log.debug("returning 401 unauthorized("+msg+")");
-        throw new WebApplicationException(Response.status(Response.Status.UNAUTHORIZED)
-                .type(MediaType.APPLICATION_JSON_TYPE)
-                .entity(ApiError.builder().message(msg).build()).build());
+        return throwWebApplicationException(Response.Status.UNAUTHORIZED, format, args);
     }
 
     /** @throws WebApplicationException With code 404 not found */
     public static WebApplicationException notFound(String format, Object... args) {
-        String msg = String.format(format, args);
-        if (log.isDebugEnabled()) log.debug("returning 404 notFound("+msg+")");
-        throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND)
-                .type(MediaType.APPLICATION_JSON_TYPE)
-                .entity(ApiError.builder().message(msg).build()).build());
+        return throwWebApplicationException(Response.Status.NOT_FOUND, format, args);
     }
 
     /** @throws WebApplicationException With code 412 precondition failed */
     public static WebApplicationException preconditionFailed(String format, Object... args) {
-        String msg = String.format(format, args);
-        if (log.isDebugEnabled()) log.debug("returning 412 preconditionFailed("+msg+")");
-        throw new WebApplicationException(Response.status(Response.Status.PRECONDITION_FAILED)
-                .type(MediaType.APPLICATION_JSON_TYPE)
-                .entity(ApiError.builder().message(msg).build()).build());
+        return throwWebApplicationException(Response.Status.PRECONDITION_FAILED, format, args);
     }
 
     public final static Map<String,com.google.common.net.MediaType> IMAGE_FORMAT_MIME_TYPES = ImmutableMap.<String, com.google.common.net.MediaType>builder()


[2/6] git commit: Build produces Git SHA 1 and branch name metadata

Posted by sj...@apache.org.
Build produces Git SHA 1 and branch name metadata

Incorporated into
* manifests as Implementation-SHA-1 and Implementation-Branch
* REST API at /v1/server/version.
* jsgui (only sha-1) as comment in index.html


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

Branch: refs/heads/master
Commit: 8887561dbd2e61f53b444808c373bff228d39341
Parents: c742881
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Fri Aug 22 15:39:23 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Fri Aug 22 15:39:23 2014 +0100

----------------------------------------------------------------------
 pom.xml                                         | 23 ++++++++
 usage/jsgui/pom.xml                             |  4 ++
 usage/jsgui/src/main/webapp/index.html          |  3 +-
 .../main/java/brooklyn/rest/api/ServerApi.java  |  3 +-
 .../brooklyn/rest/domain/VersionSummary.java    | 61 ++++++++++++++++++++
 usage/rest-server/pom.xml                       |  7 +++
 .../brooklyn/rest/resources/ServerResource.java | 22 ++++++-
 .../main/resources/build-metadata.properties    | 18 ++++++
 .../rest/resources/ServerResourceTest.java      |  5 +-
 9 files changed, 139 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8887561d/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index aca1329..b8caa25 100644
--- a/pom.xml
+++ b/pom.xml
@@ -822,6 +822,14 @@
                     <version>1.4.0</version>
                 </plugin>
                 <plugin>
+                    <groupId>org.codehaus.mojo</groupId>
+                    <artifactId>buildnumber-maven-plugin</artifactId>
+                    <version>1.3</version>
+                    <configuration>
+                        <getRevisionOnlyOnce>true</getRevisionOnlyOnce>
+                    </configuration>
+                </plugin>
+                <plugin>
                     <!-- This configuration is used for Eclipse settings only. -->
                     <groupId>org.eclipse.m2e</groupId>
                     <artifactId>lifecycle-mapping</artifactId>
@@ -913,10 +921,23 @@
                          </lifecycleMappingMetadata>
                     </configuration>
                 </plugin>
+
             </plugins>
         </pluginManagement>
         <plugins>
             <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>buildnumber-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <phase>validate</phase>
+                        <goals>
+                            <goal>create</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
                 <artifactId>maven-enforcer-plugin</artifactId>
                 <executions>
                     <execution>
@@ -1251,6 +1272,8 @@
                                     what is really needed.
                                 -->
                                 <Export-Package>brooklyn.*</Export-Package>
+                                <Implementation-SHA-1>${buildNumber}</Implementation-SHA-1>
+                                <Implementation-Branch>${scmBranch}</Implementation-Branch>
                             </instructions>
                         </configuration>
                     </plugin>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8887561d/usage/jsgui/pom.xml
----------------------------------------------------------------------
diff --git a/usage/jsgui/pom.xml b/usage/jsgui/pom.xml
index 85e90bc..a768298 100644
--- a/usage/jsgui/pom.xml
+++ b/usage/jsgui/pom.xml
@@ -394,6 +394,10 @@
                                     <token>assets/css/styles.css</token>
                                     <value>assets/css/styles.min.css</value>
                                 </replacement>
+                                <replacement>
+                                    <token>GIT_SHA_1</token>
+                                    <value>${buildNumber}</value>
+                                </replacement>
                             </replacements>
                         </configuration>
                     </plugin>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8887561d/usage/jsgui/src/main/webapp/index.html
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/index.html b/usage/jsgui/src/main/webapp/index.html
index 0bdead6..f621f4d 100644
--- a/usage/jsgui/src/main/webapp/index.html
+++ b/usage/jsgui/src/main/webapp/index.html
@@ -1,4 +1,3 @@
-
 <!--
 Licensed to the Apache Software Foundation (ASF) under one
 or more contributor license agreements.  See the NOTICE file
@@ -17,7 +16,7 @@ KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
 -->
-
+<!-- Brooklyn SHA-1: GIT_SHA_1 -->
 <!DOCTYPE html>
 <html>
 <head>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8887561d/usage/rest-api/src/main/java/brooklyn/rest/api/ServerApi.java
----------------------------------------------------------------------
diff --git a/usage/rest-api/src/main/java/brooklyn/rest/api/ServerApi.java b/usage/rest-api/src/main/java/brooklyn/rest/api/ServerApi.java
index 8aae011..fb9d3c1 100644
--- a/usage/rest-api/src/main/java/brooklyn/rest/api/ServerApi.java
+++ b/usage/rest-api/src/main/java/brooklyn/rest/api/ServerApi.java
@@ -29,6 +29,7 @@ import javax.ws.rs.core.MediaType;
 
 import brooklyn.rest.apidoc.Apidoc;
 import brooklyn.rest.domain.HighAvailabilitySummary;
+import brooklyn.rest.domain.VersionSummary;
 
 import com.google.common.annotations.Beta;
 import com.wordnik.swagger.core.ApiOperation;
@@ -57,7 +58,7 @@ public interface ServerApi {
     @GET
     @Path("/version")
     @ApiOperation(value = "Return version identifier information for this Brooklyn instance", responseClass = "String", multiValueResponse = false)
-    public String getVersion();
+    public VersionSummary getVersion();
 
     @GET
     @Path("/status")

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8887561d/usage/rest-api/src/main/java/brooklyn/rest/domain/VersionSummary.java
----------------------------------------------------------------------
diff --git a/usage/rest-api/src/main/java/brooklyn/rest/domain/VersionSummary.java b/usage/rest-api/src/main/java/brooklyn/rest/domain/VersionSummary.java
new file mode 100644
index 0000000..9bcbaea
--- /dev/null
+++ b/usage/rest-api/src/main/java/brooklyn/rest/domain/VersionSummary.java
@@ -0,0 +1,61 @@
+/*
+ * 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 brooklyn.rest.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+public class VersionSummary {
+
+    private final String version;
+    private final String buildSha1;
+    private final String buildBranch;
+
+    public VersionSummary(String version) {
+        this(version, null, null);
+    }
+
+    public VersionSummary(
+            @JsonProperty("version") String version,
+            @JsonProperty("buildSha1")String buildSha1,
+            @JsonProperty("buildBranch") String buildBranch) {
+        this.version = checkNotNull(version, "version");
+        this.buildSha1 = buildSha1;
+        this.buildBranch = buildBranch;
+    }
+
+    @Nonnull
+    public String getVersion() {
+        return version;
+    }
+
+    @Nullable
+    public String getBuildSha1() {
+        return buildSha1;
+    }
+
+    @Nullable
+    public String getBuildBranch() {
+        return buildBranch;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8887561d/usage/rest-server/pom.xml
----------------------------------------------------------------------
diff --git a/usage/rest-server/pom.xml b/usage/rest-server/pom.xml
index 39c6ecb..2a6997d 100644
--- a/usage/rest-server/pom.xml
+++ b/usage/rest-server/pom.xml
@@ -243,6 +243,13 @@
     </dependencies>
 
     <build>
+        <resources>
+            <resource>
+                <directory>${basedir}/src/main/resources</directory>
+                <!-- Required to set values in build-metadata.properties -->
+                <filtering>true</filtering>
+            </resource>
+        </resources>
         <plugins>
 
 <!-- if you want to build a WAR, full or skinny:

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8887561d/usage/rest-server/src/main/java/brooklyn/rest/resources/ServerResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/resources/ServerResource.java b/usage/rest-server/src/main/java/brooklyn/rest/resources/ServerResource.java
index b9b7180..4a52672 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/resources/ServerResource.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/resources/ServerResource.java
@@ -18,8 +18,11 @@
  */
 package brooklyn.rest.resources;
 
+import java.io.IOException;
+import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Properties;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -36,7 +39,9 @@ import brooklyn.management.ha.ManagementPlaneSyncRecord;
 import brooklyn.management.internal.ManagementContextInternal;
 import brooklyn.rest.api.ServerApi;
 import brooklyn.rest.domain.HighAvailabilitySummary;
+import brooklyn.rest.domain.VersionSummary;
 import brooklyn.rest.transform.HighAvailabilityTransformer;
+import brooklyn.util.ResourceUtils;
 import brooklyn.util.time.CountdownTimer;
 import brooklyn.util.time.Duration;
 
@@ -44,6 +49,9 @@ public class ServerResource extends AbstractBrooklynRestResource implements Serv
 
     private static final Logger log = LoggerFactory.getLogger(ServerResource.class);
 
+    private static final String BUILD_SHA_1_PROPERTY = "git-sha-1";
+    private static final String BUILD_BRANCH_PROPERTY = "git-branch-name";
+
     @Override
     public void reloadBrooklynProperties() {
         brooklyn().reloadBrooklynProperties();
@@ -81,8 +89,18 @@ public class ServerResource extends AbstractBrooklynRestResource implements Serv
     }
 
     @Override
-    public String getVersion() {
-        return BrooklynVersion.get();
+    public VersionSummary getVersion() {
+        InputStream input = ResourceUtils.create().getResourceFromUrl("classpath://build-metadata.properties");
+        Properties properties = new Properties();
+        String gitSha1 = null, gitBranch = null;
+        try {
+            properties.load(input);
+            gitSha1 = properties.getProperty(BUILD_SHA_1_PROPERTY);
+            gitBranch = properties.getProperty(BUILD_BRANCH_PROPERTY);
+        } catch (IOException e) {
+            log.error("Failed to load build-metadata.properties", e);
+        }
+        return new VersionSummary(BrooklynVersion.get(), gitSha1, gitBranch);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8887561d/usage/rest-server/src/main/resources/build-metadata.properties
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/resources/build-metadata.properties b/usage/rest-server/src/main/resources/build-metadata.properties
new file mode 100644
index 0000000..eab85ef
--- /dev/null
+++ b/usage/rest-server/src/main/resources/build-metadata.properties
@@ -0,0 +1,18 @@
+# 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.
+git-sha-1 = ${buildNumber}
+git-branch-name = ${scmBranch}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8887561d/usage/rest-server/src/test/java/brooklyn/rest/resources/ServerResourceTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/brooklyn/rest/resources/ServerResourceTest.java b/usage/rest-server/src/test/java/brooklyn/rest/resources/ServerResourceTest.java
index a540046..3e4951a 100644
--- a/usage/rest-server/src/test/java/brooklyn/rest/resources/ServerResourceTest.java
+++ b/usage/rest-server/src/test/java/brooklyn/rest/resources/ServerResourceTest.java
@@ -33,6 +33,7 @@ import brooklyn.BrooklynVersion;
 import brooklyn.management.ManagementContext;
 import brooklyn.management.entitlement.Entitlements;
 import brooklyn.rest.domain.HighAvailabilitySummary;
+import brooklyn.rest.domain.VersionSummary;
 import brooklyn.rest.testing.BrooklynRestResourceTest;
 import brooklyn.test.Asserts;
 
@@ -50,8 +51,8 @@ public class ServerResourceTest extends BrooklynRestResourceTest {
 
     @Test
     public void testGetVersion() throws Exception {
-        String version = client().resource("/v1/server/version").get(String.class);
-        assertEquals(version, BrooklynVersion.get());
+        VersionSummary version = client().resource("/v1/server/version").get(VersionSummary.class);
+        assertEquals(version.getVersion(), BrooklynVersion.get());
     }
 
     @Test


[6/6] git commit: This closes #129

Posted by sj...@apache.org.
This closes #129


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

Branch: refs/heads/master
Commit: 4a2fc266f7e6cc399ea7367e5123f35b0aa8ed52
Parents: d368245 8887561
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Wed Aug 27 11:01:52 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Wed Aug 27 11:01:52 2014 +0100

----------------------------------------------------------------------
 pom.xml                                         | 23 ++++++++
 usage/jsgui/pom.xml                             |  4 ++
 usage/jsgui/src/main/webapp/index.html          |  3 +-
 .../main/java/brooklyn/rest/api/ServerApi.java  |  3 +-
 .../java/brooklyn/rest/domain/ApiError.java     |  4 ++
 .../brooklyn/rest/domain/VersionSummary.java    | 61 ++++++++++++++++++++
 usage/rest-server/pom.xml                       |  7 +++
 .../brooklyn/rest/resources/ServerResource.java | 22 ++++++-
 .../brooklyn/rest/util/WebResourceUtils.java    | 39 +++++++------
 .../main/resources/build-metadata.properties    | 18 ++++++
 .../rest/resources/ServerResourceTest.java      |  5 +-
 11 files changed, 163 insertions(+), 26 deletions(-)
----------------------------------------------------------------------



[4/6] git commit: Unify entity and policy detail views.

Posted by sj...@apache.org.
Unify entity and policy detail views.


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

Branch: refs/heads/master
Commit: 4811e81c0214051ab1acb02e2a7545e91e08d8c1
Parents: eb1c986
Author: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Authored: Tue Aug 26 18:32:55 2014 +0300
Committer: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Committed: Tue Aug 26 18:37:26 2014 +0300

----------------------------------------------------------------------
 usage/jsgui/src/main/webapp/assets/js/view/catalog.js  | 13 +++++++------
 .../main/webapp/assets/tpl/catalog/details-entity.html |  2 ++
 2 files changed, 9 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4811e81c/usage/jsgui/src/main/webapp/assets/js/view/catalog.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/js/view/catalog.js b/usage/jsgui/src/main/webapp/assets/js/view/catalog.js
index 4c38b5a..06ba9ac 100644
--- a/usage/jsgui/src/main/webapp/assets/js/view/catalog.js
+++ b/usage/jsgui/src/main/webapp/assets/js/view/catalog.js
@@ -77,7 +77,7 @@ define([
                 // view directly (e.g. when indicating an error), below handles keeping the
                 // right thing open when navigating from view to view.
                 var open = this.$(".in").attr("id");
-                var newHtml = $(template({model: model}));
+                var newHtml = $(template({model: model, viewName: that.options.name}));
                 $(newHtml).find("#"+open).addClass("in");
                 that.$el.html(newHtml);
                 // rewire events. previous callbacks are removed automatically.
@@ -299,7 +299,7 @@ define([
                 this.activeCid = cid;
                 var model = this.collection.get(cid);
                 Backbone.history.navigate("v1/catalog/" + this.name + "/" + model.id);
-                this.options.onItemSelected(model, $event);
+                this.options.onItemSelected(activeDetailsView, model, $event);
             }
         },
 
@@ -353,7 +353,7 @@ define([
                     autoOpen: this.options.kind == "entities"
                 }),
                 "policies": new AccordionItemView({
-                    onItemSelected: _.partial(this.showCatalogItem, DetailsGenericHtml),
+                    onItemSelected: _.partial(this.showCatalogItem, DetailsEntityHtml),
                     name: "policies",
                     autoOpen: this.options.kind == "policies"
                 }),
@@ -428,14 +428,14 @@ define([
                         } else {
                             activeDetailsView = kind;
                             accordion.activeCid = model.cid;
-                            accordion.options.onItemSelected(model);
+                            accordion.options.onItemSelected(kind, model);
                             accordion.show();
                         }
                     });
             }
         },
 
-        showCatalogItem: function(template, model, $target) {
+        showCatalogItem: function(template, viewName, model, $target) {
             this.$(".accordion-nav-row").removeClass("active");
             if ($target) {
                 $target.addClass("active");
@@ -444,7 +444,8 @@ define([
             }
             var newView = new CatalogItemDetailsView({
                 model: model,
-                template: template
+                template: template,
+                name: viewName
             }).render();
             this.setDetailsView(newView)
         },

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4811e81c/usage/jsgui/src/main/webapp/assets/tpl/catalog/details-entity.html
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/tpl/catalog/details-entity.html b/usage/jsgui/src/main/webapp/assets/tpl/catalog/details-entity.html
index eaab99b..fda1da1 100644
--- a/usage/jsgui/src/main/webapp/assets/tpl/catalog/details-entity.html
+++ b/usage/jsgui/src/main/webapp/assets/tpl/catalog/details-entity.html
@@ -39,6 +39,7 @@ under the License.
                 </div>
             </div>
         </div>
+        <% if (viewName != "policies") { %>
         <div class="accordion-group">
             <div class="accordion-heading">
                 <a class="accordion-toggle" data-toggle="collapse" data-parent="#catalog-details-accordion" href="#collapseConfiguration">
@@ -155,6 +156,7 @@ under the License.
                 </div>
             </div>
         </div>
+        <% } %>
     </div>
 
 </div>


[3/6] git commit: Support for adding YAML defined policies to the catalog.

Posted by sj...@apache.org.
Support for adding YAML defined policies to the catalog.

OSGi support included.


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

Branch: refs/heads/master
Commit: eb1c98679eea88a3957bfc85eac09ab3ee12c358
Parents: e4f6ce3
Author: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Authored: Fri Aug 15 22:22:31 2014 +0300
Committer: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Committed: Tue Aug 26 18:37:15 2014 +0300

----------------------------------------------------------------------
 .../catalog/internal/BasicBrooklynCatalog.java  | 149 +++++++----
 .../catalog/internal/CatalogItemBuilder.java    |  90 +++++++
 .../java/brooklyn/osgi/tests/SimplePolicy.java  |  36 +++
 .../osgi/brooklyn-test-osgi-entities.jar        | Bin 10891 -> 14663 bytes
 .../BrooklynEntityDecorationResolver.java       |  22 +-
 .../camp/brooklyn/CatalogYamlEntityTest.java    | 254 +++++++++++++++++++
 .../camp/brooklyn/CatalogYamlPolicyTest.java    | 170 +++++++++++++
 .../brooklyn/camp/brooklyn/CatalogYamlTest.java | 250 ------------------
 .../rest/domain/CatalogPolicySummary.java       |   3 +-
 .../rest/transform/CatalogTransformer.java      |   3 +-
 .../src/main/java/brooklyn/util/yaml/Yamls.java |  17 +-
 11 files changed, 693 insertions(+), 301 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eb1c9867/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 176975f..f3c3f40 100644
--- a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
@@ -18,6 +18,7 @@
  */
 package brooklyn.catalog.internal;
 
+import static com.google.common.base.Preconditions.checkNotNull;
 import io.brooklyn.camp.CampPlatform;
 import io.brooklyn.camp.spi.AssemblyTemplate;
 import io.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
@@ -40,6 +41,8 @@ import brooklyn.catalog.CatalogPredicates;
 import brooklyn.config.BrooklynServerConfig;
 import brooklyn.management.ManagementContext;
 import brooklyn.management.classloading.BrooklynClassLoadingContext;
+import brooklyn.policy.Policy;
+import brooklyn.policy.PolicySpec;
 import brooklyn.util.collections.MutableMap;
 import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.guava.Maybe;
@@ -50,15 +53,17 @@ import brooklyn.util.stream.Streams;
 import brooklyn.util.text.Strings;
 import brooklyn.util.time.Duration;
 import brooklyn.util.time.Time;
+import brooklyn.util.yaml.Yamls;
 
 import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
 import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 
 public class BasicBrooklynCatalog implements BrooklynCatalog {
+    private static final String POLICIES_KEY = "brooklyn.policies";
 
     private static final Logger log = LoggerFactory.getLogger(BasicBrooklynCatalog.class);
 
@@ -85,7 +90,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     private volatile LoadedClassLoader manualAdditionsClasses;
 
     public BasicBrooklynCatalog(final ManagementContext mgmt, final CatalogDto dto) {
-        this.mgmt = Preconditions.checkNotNull(mgmt, "managementContext");
+        this.mgmt = checkNotNull(mgmt, "managementContext");
         this.catalog = new CatalogDo(mgmt, dto);
     }
 
@@ -124,7 +129,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     @Override
     public void deleteCatalogItem(String id) {
         log.debug("Deleting manual catalog item from "+mgmt+": "+id);
-        Preconditions.checkNotNull(id, "id");
+        checkNotNull(id, "id");
         CatalogItem<?, ?> item = getCatalogItem(id);
         CatalogItemDtoAbstract<?,?> itemDto = getAbstractCatalogItem(item);
         if (itemDto == null) {
@@ -167,38 +172,23 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     @Override
     public <T, SpecT> SpecT createSpec(CatalogItem<T, SpecT> item) {
         CatalogItemDo<T,SpecT> loadedItem = (CatalogItemDo<T, SpecT>) getCatalogItemDo(item.getId());
-        
+
         Class<SpecT> specType = loadedItem.getSpecType();
         if (specType==null) return null;
-            
+
         String yaml = loadedItem.getPlanYaml();
         SpecT spec = null;
-            
+
         if (yaml!=null) {
             DeploymentPlan plan = makePlanFromYaml(yaml);
-            CampPlatform camp = BrooklynServerConfig.getCampPlatform(mgmt).get();
-            
-            // TODO should not register new AT each time we instantiate from the same plan; use some kind of cache
-            AssemblyTemplate at;
-            BrooklynClassLoadingContext loader = loadedItem.newClassLoadingContext(mgmt);
-            BrooklynLoaderTracker.setLoader(loader);
-            try {
-                at = camp.pdp().registerDeploymentPlan(plan);
-            } finally {
-                BrooklynLoaderTracker.unsetLoader(loader);
-            }
-            
-            try {
-                AssemblyTemplateInstantiator instantiator = at.getInstantiator().newInstance();
-                if (instantiator instanceof AssemblyTemplateSpecInstantiator) {
-                    return (SpecT) ((AssemblyTemplateSpecInstantiator)instantiator).createSpec(at, camp);
-                }
-                throw new IllegalStateException("Unable to instantiate YAML; incompatible instantiator "+instantiator+" for "+at);
-            } catch (Exception e) {
-                throw Exceptions.propagate(e);
+            switch (item.getCatalogItemType()) {
+                case ENTITY:return createEntitySpec(loadedItem, plan);
+                case POLICY:return createPolicySpec(loadedItem, plan);
+                default: throw new RuntimeException("Only entity & policy catalog items are supported. Unsupported catalog item type " + item.getCatalogItemType());
             }
+
         }
-            
+
         // revert to legacy mechanism
         try {
             if (loadedItem.getJavaType()!=null) {
@@ -215,7 +205,64 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
 
         return spec;
     }
-    
+
+    @SuppressWarnings("unchecked")
+    private <T, SpecT> SpecT createEntitySpec(
+            CatalogItemDo<T, SpecT> loadedItem, DeploymentPlan plan) {
+        CampPlatform camp = BrooklynServerConfig.getCampPlatform(mgmt).get();
+
+        // TODO should not register new AT each time we instantiate from the same plan; use some kind of cache
+        AssemblyTemplate at;
+        BrooklynClassLoadingContext loader = loadedItem.newClassLoadingContext(mgmt);
+        BrooklynLoaderTracker.setLoader(loader);
+        try {
+            at = camp.pdp().registerDeploymentPlan(plan);
+        } finally {
+            BrooklynLoaderTracker.unsetLoader(loader);
+        }
+
+        try {
+            AssemblyTemplateInstantiator instantiator = at.getInstantiator().newInstance();
+            if (instantiator instanceof AssemblyTemplateSpecInstantiator) {
+                return (SpecT) ((AssemblyTemplateSpecInstantiator)instantiator).createSpec(at, camp);
+            }
+            throw new IllegalStateException("Unable to instantiate YAML; incompatible instantiator "+instantiator+" for "+at);
+        } catch (Exception e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+
+
+    @SuppressWarnings("unchecked")
+    private <T, SpecT> SpecT createPolicySpec(CatalogItemDo<T, SpecT> loadedItem, DeploymentPlan plan) {
+        //Would ideally re-use io.brooklyn.camp.brooklyn.spi.creation.BrooklynEntityDecorationResolver.PolicySpecResolver
+        //but it is CAMP specific and there is no easy way to get hold of it.
+        Object policies = checkNotNull(plan.getCustomAttributes().get(POLICIES_KEY), "policy config");
+        if (!(policies instanceof Iterable<?>)) {
+            throw new IllegalStateException("The value of " + POLICIES_KEY + " must be an Iterable.");
+        }
+
+        Object policy = Iterables.getOnlyElement((Iterable<?>)policies);
+
+        Map<String, Object> policyConfig;
+        if (policy instanceof String) {
+            policyConfig = ImmutableMap.<String, Object>of("type", policy);
+        } else if (policy instanceof Map) {
+            policyConfig = (Map<String, Object>) policy;
+        } else {
+            throw new IllegalStateException("Policy exepcted to be string or map. Unsupported object type " + policy.getClass().getName() + " (" + policy.toString() + ")");
+        }
+
+        String policyType = (String) checkNotNull(Yamls.getMultinameAttribute(policyConfig, "policy_type", "policyType", "type"), "policy type");
+        Map<String, Object> brooklynConfig = (Map<String, Object>) policyConfig.get("brooklyn.config");
+        BrooklynClassLoadingContext loader = loadedItem.newClassLoadingContext(mgmt);
+        PolicySpec<? extends Policy> spec = PolicySpec.create(loader.loadClass(policyType, Policy.class));
+        if (brooklynConfig != null) {
+            spec.configure(brooklynConfig);
+        }
+        return (SpecT) spec;
+    }
+
     @SuppressWarnings("unchecked")
     @Override
     /** @deprecated since 0.7.0 use {@link #createSpec(CatalogItem)} */
@@ -223,7 +270,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     public <T,SpecT> Class<? extends T> loadClass(CatalogItem<T,SpecT> item) {
         if (log.isDebugEnabled())
             log.debug("Loading class for catalog item " + item);
-        Preconditions.checkNotNull(item);
+        checkNotNull(item);
         CatalogItemDo<?,?> loadedItem = getCatalogItemDo(item.getId());
         if (loadedItem==null) throw new NoSuchElementException("Unable to load '"+item.getId()+"' to instantiate it");
         return (Class<? extends T>) loadedItem.getJavaClass();
@@ -253,7 +300,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
 
     private CatalogItemDtoAbstract<?,?> getAbstractCatalogItem(String yaml) {
         DeploymentPlan plan = makePlanFromYaml(yaml);
-        
+
         CatalogLibrariesDto libraries = null;
 
         @SuppressWarnings("rawtypes")
@@ -287,26 +334,38 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
                 }
             }
         }
-        
-        // TODO long-term:  support applications / templates, policies
-        
-        // build the catalog item from the plan (as CatalogItem<Entity> for now)
-        CatalogEntityItemDto dto = CatalogItems.newEntityFromPlan(registeredTypeName, libraries, plan, yaml);
+
+        // TODO long-term:  support applications / templates
+
+        CatalogItemBuilder<?> builder = createItemBuilder(plan, registeredTypeName)
+            .libraries(libraries)
+            .name(plan.getName())
+            .description(plan.getDescription())
+            .plan(yaml);
 
         // and populate other fields
         Maybe<Object> name = catalog.getMaybe("name");
-        if (name.isPresent()) dto.name = (String)name.get();
-        
+        if (name.isPresent()) builder.name((String)name.get());
+
         Maybe<Object> description = catalog.getMaybe("description");
-        if (description.isPresent()) dto.description = (String)description.get();
-        
+        if (description.isPresent()) builder.description((String)description.get());
+
         Maybe<Object> iconUrl = catalog.getMaybe("iconUrl");
         if (iconUrl.isAbsent()) iconUrl = catalog.getMaybe("icon_url");
-        if (iconUrl.isPresent()) dto.iconUrl = (String)iconUrl.get();
+        if (iconUrl.isPresent()) builder.iconUrl((String)iconUrl.get());
 
         // TODO #3 support version info
-        
-        return dto;
+
+        return builder.build();
+    }
+
+    private CatalogItemBuilder<?> createItemBuilder(DeploymentPlan plan, String registeredTypeName) {
+        boolean isPolicy = plan.getCustomAttributes().containsKey(POLICIES_KEY);
+        if (isPolicy) {
+            return CatalogItemBuilder.newPolicy(registeredTypeName);
+        } else {
+            return CatalogItemBuilder.newEntity(registeredTypeName);
+        }
     }
 
     private DeploymentPlan makePlanFromYaml(String yaml) {
@@ -317,7 +376,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     @Override
     public CatalogItem<?,?> addItem(String yaml) {
         log.debug("Adding manual catalog item to "+mgmt+": "+yaml);
-        Preconditions.checkNotNull(yaml, "yaml");
+        checkNotNull(yaml, "yaml");
         if (manualAdditionsCatalog==null) loadManualAdditionsCatalog();
         CatalogItemDtoAbstract<?,?> itemDto = getAbstractCatalogItem(yaml);
         manualAdditionsCatalog.addEntry(itemDto);
@@ -337,7 +396,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     @Override @Deprecated /** @deprecated see super */
     public void addItem(CatalogItem<?,?> item) {
         log.debug("Adding manual catalog item to "+mgmt+": "+item);
-        Preconditions.checkNotNull(item, "item");
+        checkNotNull(item, "item");
         if (manualAdditionsCatalog==null) loadManualAdditionsCatalog();
         manualAdditionsCatalog.addEntry(getAbstractCatalogItem(item));
     }
@@ -345,7 +404,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     @Override @Deprecated /** @deprecated see super */
     public CatalogItem<?,?> addItem(Class<?> type) {
         log.debug("Adding manual catalog item to "+mgmt+": "+type);
-        Preconditions.checkNotNull(type, "type");
+        checkNotNull(type, "type");
         if (manualAdditionsCatalog==null) loadManualAdditionsCatalog();
         manualAdditionsClasses.addClass(type);
         return manualAdditionsCatalog.classpath.addCatalogEntry(type);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eb1c9867/core/src/main/java/brooklyn/catalog/internal/CatalogItemBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemBuilder.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemBuilder.java
new file mode 100644
index 0000000..d0bbe29
--- /dev/null
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemBuilder.java
@@ -0,0 +1,90 @@
+/*
+ * 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 brooklyn.catalog.internal;
+
+import com.google.common.base.Preconditions;
+
+public class CatalogItemBuilder<CatalogItemType extends CatalogItemDtoAbstract<?, ?>> {
+    private CatalogItemType dto;
+
+    public static CatalogItemBuilder<CatalogEntityItemDto> newEntity(String registeredTypeName) {
+        return new CatalogItemBuilder<CatalogEntityItemDto>(new CatalogEntityItemDto())
+                .registeredTypeName(registeredTypeName);
+    }
+
+    public static CatalogItemBuilder<CatalogTemplateItemDto> newTemplate() {
+        return new CatalogItemBuilder<CatalogTemplateItemDto>(new CatalogTemplateItemDto());
+    }
+
+    public static CatalogItemBuilder<CatalogPolicyItemDto> newPolicy(String registeredTypeName) {
+        return new CatalogItemBuilder<CatalogPolicyItemDto>(new CatalogPolicyItemDto())
+                .registeredTypeName(registeredTypeName);
+    }
+
+    public CatalogItemBuilder(CatalogItemType dto) {
+        this.dto = dto;
+        this.dto.libraries = new CatalogLibrariesDto();
+    }
+
+    public CatalogItemBuilder<CatalogItemType> registeredTypeName(String registeredType) {
+        dto.registeredType = registeredType;
+        return this;
+    }
+
+    public CatalogItemBuilder<CatalogItemType> name(String name) {
+        dto.name = name;
+        return this;
+    }
+
+    public CatalogItemBuilder<CatalogItemType> description(String description) {
+        dto.description = description;
+        return this;
+    }
+
+    public CatalogItemBuilder<CatalogItemType> iconUrl(String iconUrl) {
+        dto.iconUrl = iconUrl;
+        return this;
+    }
+
+    public CatalogItemBuilder<CatalogItemType> libraries(CatalogLibrariesDto libraries) {
+        dto.libraries = libraries;
+        return this;
+    }
+
+    public CatalogItemBuilder<CatalogItemType> plan(String yaml) {
+        dto.planYaml = yaml;
+        return this;
+    }
+
+    public CatalogItemType build() {
+        Preconditions.checkNotNull(dto.registeredType);
+
+        if (dto.libraries == null) {
+            dto.libraries = new CatalogLibrariesDto();
+        }
+
+        CatalogItemType ret = dto;
+
+        //prevent mutations through the builder
+        dto = null;
+
+        return ret;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eb1c9867/core/src/test/dependencies/osgi/entities/src/main/java/brooklyn/osgi/tests/SimplePolicy.java
----------------------------------------------------------------------
diff --git a/core/src/test/dependencies/osgi/entities/src/main/java/brooklyn/osgi/tests/SimplePolicy.java b/core/src/test/dependencies/osgi/entities/src/main/java/brooklyn/osgi/tests/SimplePolicy.java
new file mode 100644
index 0000000..10a0094
--- /dev/null
+++ b/core/src/test/dependencies/osgi/entities/src/main/java/brooklyn/osgi/tests/SimplePolicy.java
@@ -0,0 +1,36 @@
+/*
+ * 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 brooklyn.osgi.tests;
+
+
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.config.ConfigKey;
+import brooklyn.policy.basic.AbstractPolicy;
+import brooklyn.util.flags.SetFromFlag;
+
+public class SimplePolicy extends AbstractPolicy {
+    @SetFromFlag("config1")
+    public static final ConfigKey<String> CONFIG1 = ConfigKeys.newStringConfigKey("config1");
+
+    @SetFromFlag("config2")
+    public static final ConfigKey<String> CONFIG2 = ConfigKeys.newStringConfigKey("config2");
+
+    @SetFromFlag("config3")
+    public static final ConfigKey<String> CONFIG3 = ConfigKeys.newStringConfigKey("config3");
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eb1c9867/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-entities.jar
----------------------------------------------------------------------
diff --git a/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-entities.jar b/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-entities.jar
index 4093cd3..42d842c 100644
Binary files a/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-entities.jar and b/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-entities.jar differ

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eb1c9867/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
index 867c775..0025cf8 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
@@ -23,8 +23,11 @@ import io.brooklyn.camp.brooklyn.spi.creation.BrooklynYamlTypeInstantiator.Insta
 import java.util.List;
 import java.util.Map;
 
+import brooklyn.catalog.BrooklynCatalog;
+import brooklyn.catalog.CatalogItem;
 import brooklyn.entity.proxying.EntityInitializer;
 import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.management.ManagementContext;
 import brooklyn.policy.Enricher;
 import brooklyn.policy.EnricherSpec;
 import brooklyn.policy.Policy;
@@ -98,11 +101,24 @@ public abstract class BrooklynEntityDecorationResolver<DT> {
         }
 
         @Override
+        @SuppressWarnings("unchecked")
         protected void addDecorationFromJsonMap(Map<?, ?> decorationJson, List<PolicySpec<?>> decorations) {
             InstantiatorFromKey decoLoader = instantiator.from(decorationJson).prefix("policy");
-            // this pattern of creating a spec could be simplified with a "Configurable" superinterface on *Spec  
-            decorations.add(PolicySpec.create(decoLoader.getType(Policy.class))
-                .configure( decoLoader.getConfigMap() ));
+
+            String policyType = decoLoader.getTypeName().get();
+            ManagementContext mgmt = instantiator.loader.getManagementContext();
+            BrooklynCatalog catalog = mgmt.getCatalog();
+            CatalogItem<?, ?> item = catalog.getCatalogItem(policyType);
+            PolicySpec<? extends Policy> spec;
+            if (item != null) {
+                spec = (PolicySpec<? extends Policy>) catalog.createSpec(item);
+                spec.configure(decoLoader.getConfigMap());
+            } else {
+                // this pattern of creating a spec could be simplified with a "Configurable" superinterface on *Spec  
+                spec = PolicySpec.create(decoLoader.getType(Policy.class))
+                    .configure( decoLoader.getConfigMap() );
+            }
+            decorations.add(spec);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eb1c9867/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/CatalogYamlEntityTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/CatalogYamlEntityTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/CatalogYamlEntityTest.java
new file mode 100644
index 0000000..910edd5
--- /dev/null
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/CatalogYamlEntityTest.java
@@ -0,0 +1,254 @@
+/*
+ * 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 io.brooklyn.camp.brooklyn;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.util.Collection;
+
+import org.testng.annotations.Test;
+
+import brooklyn.catalog.CatalogItem;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.BasicEntity;
+import brooklyn.management.osgi.OsgiStandaloneTest;
+
+import com.google.common.collect.Iterables;
+
+
+public class CatalogYamlEntityTest extends AbstractYamlTest {
+    private static final String SIMPLE_ENTITY_TYPE = "brooklyn.osgi.tests.SimpleEntity";
+
+    @Test
+    public void testAddCatalogItem() throws Exception {
+        String registeredTypeName = "my.catalog.app.id.load";
+        addCatalogOSGiEntity(registeredTypeName);
+
+        CatalogItem<?, ?> item = mgmt().getCatalog().getCatalogItem(registeredTypeName);
+        assertEquals(item.getRegisteredTypeName(), registeredTypeName);
+
+        deleteCatalogEntity(registeredTypeName);
+    }
+
+    @Test
+    public void testLaunchApplicationReferencingCatalog() throws Exception {
+        String registeredTypeName = "my.catalog.app.id.launch";
+        registerAndLaunchAndAssertSimpleEntity(registeredTypeName, SIMPLE_ENTITY_TYPE);
+    }
+
+    @Test
+    public void testLaunchApplicationWithCatalogReferencingOtherCatalog() throws Exception {
+        String referencedRegisteredTypeName = "my.catalog.app.id.referenced";
+        String referrerRegisteredTypeName = "my.catalog.app.id.referring";
+        addCatalogOSGiEntity(referencedRegisteredTypeName, SIMPLE_ENTITY_TYPE);
+        addCatalogOSGiEntity(referrerRegisteredTypeName, referencedRegisteredTypeName);
+
+        String yaml = "name: simple-app-yaml\n" +
+                      "location: localhost\n" +
+                      "services: \n" +
+                      "  - serviceType: "+referrerRegisteredTypeName;
+        Entity app = createAndStartApplication(yaml);
+
+        Entity simpleEntity = Iterables.getOnlyElement(app.getChildren());
+        assertEquals(simpleEntity.getEntityType().getName(), SIMPLE_ENTITY_TYPE);
+
+        deleteCatalogEntity(referencedRegisteredTypeName);
+        deleteCatalogEntity(referrerRegisteredTypeName);
+    }
+
+    @Test
+    public void testLaunchApplicationChildWithCatalogReferencingOtherCatalog() throws Exception {
+        String referencedRegisteredTypeName = "my.catalog.app.id.child.referenced";
+        String referrerRegisteredTypeName = "my.catalog.app.id.child.referring";
+        addCatalogOSGiEntity(referencedRegisteredTypeName, SIMPLE_ENTITY_TYPE);
+        addCatalogChildOSGiEntity(referrerRegisteredTypeName, referencedRegisteredTypeName);
+
+        Entity app = createAndStartApplication(
+            "name: simple-app-yaml",
+            "location: localhost",
+            "services:",
+            "- serviceType: "+BasicEntity.class.getName(),
+            "  brooklyn.children:",
+            "  - type: " + referrerRegisteredTypeName);
+
+        Collection<Entity> children = app.getChildren();
+        assertEquals(children.size(), 1);
+        Entity child = Iterables.getOnlyElement(children);
+        assertEquals(child.getEntityType().getName(), BasicEntity.class.getName());
+        Collection<Entity> grandChildren = child.getChildren();
+        assertEquals(grandChildren.size(), 1);
+        Entity grandChild = Iterables.getOnlyElement(grandChildren);
+        assertEquals(grandChild.getEntityType().getName(), BasicEntity.class.getName());
+        Collection<Entity> grandGrandChildren = grandChild.getChildren();
+        assertEquals(grandGrandChildren.size(), 1);
+        Entity grandGrandChild = Iterables.getOnlyElement(grandGrandChildren);
+        assertEquals(grandGrandChild.getEntityType().getName(), SIMPLE_ENTITY_TYPE);
+
+        deleteCatalogEntity(referencedRegisteredTypeName);
+        deleteCatalogEntity(referrerRegisteredTypeName);
+    }
+
+    @Test
+    public void testLaunchApplicationWithTypeUsingJavaColonPrefix() throws Exception {
+        String registeredTypeName = SIMPLE_ENTITY_TYPE;
+        String serviceName = "java:"+SIMPLE_ENTITY_TYPE;
+        registerAndLaunchAndAssertSimpleEntity(registeredTypeName, serviceName);
+    }
+
+    @Test
+    public void testLaunchApplicationLoopWithJavaTypeName() throws Exception {
+        String registeredTypeName = SIMPLE_ENTITY_TYPE;
+        String serviceName = SIMPLE_ENTITY_TYPE;
+        registerAndLaunchAndAssertSimpleEntity(registeredTypeName, serviceName);
+    }
+
+    @Test
+    public void testLaunchApplicationLoopCatalogIdFails() throws Exception {
+        String registeredTypeName = "self.referencing.type";
+        registerAndLaunchFailsWithRecursionError(registeredTypeName, registeredTypeName);
+    }
+    
+    @Test
+    public void testLaunchApplicationChildLoopCatalogIdFails() throws Exception {
+        String referrerRegisteredTypeName = "my.catalog.app.id.child.referring";
+        addCatalogChildOSGiEntity(referrerRegisteredTypeName, referrerRegisteredTypeName);
+
+        try {
+            createAndStartApplication(
+                "name: simple-app-yaml",
+                "location: localhost",
+                "services:",
+                "- serviceType: "+BasicEntity.class.getName(),
+                "  brooklyn.children:",
+                "  - type: " + referrerRegisteredTypeName);
+
+                fail("Expected to throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            assertTrue(e.getMessage().contains("Recursive reference to "+referrerRegisteredTypeName));
+        }
+
+        deleteCatalogEntity(referrerRegisteredTypeName);
+    }
+
+    /**
+     * Tests that a catalog item referenced by another
+     * catalog item won't have access to the parent's bundles.
+     */
+    @Test
+    public void testParentCatalogDoesNotLeakBundlesToChildCatalogItems() throws Exception {
+        String childCatalogId = "my.catalog.app.id.no_bundles";
+        String parentCatalogId = "my.catalog.app.id.parent";
+        addCatalogItem(
+                "brooklyn.catalog:",
+                "  id: " + childCatalogId,
+                "",
+                "services:",
+                "- type: " + SIMPLE_ENTITY_TYPE);
+
+        addCatalogItem(
+                "brooklyn.catalog:",
+                "  id: " + parentCatalogId,
+                "  libraries:",
+                "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
+                "",
+                "services:",
+                "- type: " + childCatalogId);
+
+        try {
+            createAndStartApplication(
+                    "services:",
+                    "- type: " + parentCatalogId);
+        } catch (UnsupportedOperationException e) {
+            assertTrue(e.getMessage().endsWith("cannot be matched"));
+            assertTrue(e.getMessage().contains(SIMPLE_ENTITY_TYPE));
+        }
+
+        deleteCatalogEntity(parentCatalogId);
+        deleteCatalogEntity(childCatalogId);
+    }
+
+    private void registerAndLaunchAndAssertSimpleEntity(String registeredTypeName, String serviceType) throws Exception {
+        addCatalogOSGiEntity(registeredTypeName, serviceType);
+        String yaml = "name: simple-app-yaml\n" +
+                      "location: localhost\n" +
+                      "services: \n" +
+                      "  - serviceType: "+registeredTypeName;
+        Entity app = createAndStartApplication(yaml);
+
+        Entity simpleEntity = Iterables.getOnlyElement(app.getChildren());
+        assertEquals(simpleEntity.getEntityType().getName(), SIMPLE_ENTITY_TYPE);
+
+        deleteCatalogEntity(registeredTypeName);
+    }
+
+    private void registerAndLaunchFailsWithRecursionError(String registeredTypeName, String serviceType) throws Exception {
+        addCatalogOSGiEntity(registeredTypeName, serviceType);
+        String yaml = "name: simple-app-yaml\n" +
+                      "location: localhost\n" +
+                      "services: \n" +
+                      "  - serviceType: "+registeredTypeName;
+        try {
+            createAndStartApplication(yaml);
+            fail("Expected to throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            assertTrue(e.getMessage().contains("Recursive reference to "+registeredTypeName));
+        }
+
+        deleteCatalogEntity(registeredTypeName);
+    }
+
+    private void addCatalogOSGiEntity(String registeredTypeName) {
+        addCatalogOSGiEntity(registeredTypeName, SIMPLE_ENTITY_TYPE);
+    }
+
+    private void addCatalogOSGiEntity(String registeredTypeName, String serviceType) {
+        addCatalogItem(
+            "brooklyn.catalog:",
+            "  id: " + registeredTypeName,
+            "  name: My Catalog App",
+            "  description: My description",
+            "  icon_url: classpath://path/to/myicon.jpg",
+            "  version: 0.1.2",
+            "  libraries:",
+            "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
+            "",
+            "services:",
+            "- type: " + serviceType);
+    }
+
+    private void addCatalogChildOSGiEntity(String registeredTypeName, String serviceType) {
+        addCatalogItem(
+            "brooklyn.catalog:",
+            "  id: " + registeredTypeName,
+            "  name: My Catalog App",
+            "  description: My description",
+            "  icon_url: classpath://path/to/myicon.jpg",
+            "  version: 0.1.2",
+            "  libraries:",
+            "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
+            "",
+            "services:",
+            "- type: " + BasicEntity.class.getName(),
+            "  brooklyn.children:",
+            "  - type: " + serviceType);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eb1c9867/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/CatalogYamlPolicyTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/CatalogYamlPolicyTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/CatalogYamlPolicyTest.java
new file mode 100644
index 0000000..e7e44d6
--- /dev/null
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/CatalogYamlPolicyTest.java
@@ -0,0 +1,170 @@
+/*
+ * 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 io.brooklyn.camp.brooklyn;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import org.testng.annotations.Test;
+
+import brooklyn.catalog.CatalogItem;
+import brooklyn.catalog.CatalogPredicates;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.BasicEntity;
+import brooklyn.event.basic.BasicConfigKey;
+import brooklyn.management.osgi.OsgiStandaloneTest;
+import brooklyn.policy.Policy;
+
+import com.google.common.collect.Iterables;
+
+public class CatalogYamlPolicyTest extends AbstractYamlTest {
+    private static final String SIMPLE_POLICY_TYPE = "brooklyn.osgi.tests.SimplePolicy";
+    private static final String SIMPLE_ENTITY_TYPE = "brooklyn.osgi.tests.SimpleEntity";
+
+    @Test
+    public void testAddCatalogItem() throws Exception {
+        assertEquals(countCatalogPolicies(), 0);
+
+        String registeredTypeName = "my.catalog.policy.id.load";
+        addCatalogOSGiPolicy(registeredTypeName, SIMPLE_POLICY_TYPE);
+
+        CatalogItem<?, ?> item = mgmt().getCatalog().getCatalogItem(registeredTypeName);
+        assertEquals(item.getRegisteredTypeName(), registeredTypeName);
+        assertEquals(countCatalogPolicies(), 1);
+
+        deleteCatalogEntity(registeredTypeName);
+    }
+
+    @Test
+    public void testLaunchApplicationReferencingPolicy() throws Exception {
+        String registeredTypeName = "my.catalog.policy.id.launch";
+        addCatalogOSGiPolicy(registeredTypeName, SIMPLE_POLICY_TYPE);
+        Entity app = createAndStartApplication(
+            "name: simple-app-yaml",
+            "location: localhost",
+            "services: ",
+            "  - type: brooklyn.entity.basic.BasicEntity\n" +
+            "    brooklyn.policies:\n" +
+            "    - type: " + registeredTypeName,
+            "      brooklyn.config:",
+            "        config2: config2 override",
+            "        config3: config3");
+
+        Entity simpleEntity = Iterables.getOnlyElement(app.getChildren());
+        Policy policy = Iterables.getOnlyElement(simpleEntity.getPolicies());
+        assertEquals(policy.getPolicyType().getName(), SIMPLE_POLICY_TYPE);
+        assertEquals(policy.getConfig(new BasicConfigKey<String>(String.class, "config1")), "config1");
+        assertEquals(policy.getConfig(new BasicConfigKey<String>(String.class, "config2")), "config2 override");
+        assertEquals(policy.getConfig(new BasicConfigKey<String>(String.class, "config3")), "config3");
+
+        deleteCatalogEntity(registeredTypeName);
+    }
+
+    @Test
+    public void testLaunchApplicationWithCatalogReferencingOtherCatalog() throws Exception {
+        String referencedRegisteredTypeName = "my.catalog.policy.id.referenced";
+        String referrerRegisteredTypeName = "my.catalog.policy.id.referring";
+        addCatalogOSGiPolicy(referencedRegisteredTypeName, SIMPLE_POLICY_TYPE);
+
+        addCatalogItem(
+            "brooklyn.catalog:",
+            "  id: " + referrerRegisteredTypeName,
+            "  name: My Catalog App",
+            "  description: My description",
+            "  icon_url: classpath://path/to/myicon.jpg",
+            "  version: 0.1.2",
+            "  libraries:",
+            "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
+            "",
+            "services:",
+            "- type: " + SIMPLE_ENTITY_TYPE,
+            "  brooklyn.policies:",
+            "  - type: " + referencedRegisteredTypeName);
+
+        String yaml = "name: simple-app-yaml\n" +
+                      "location: localhost\n" +
+                      "services: \n" +
+                      "  - serviceType: "+referrerRegisteredTypeName;
+
+        Entity app = createAndStartApplication(yaml);
+
+        Entity simpleEntity = Iterables.getOnlyElement(app.getChildren());
+        Policy policy = Iterables.getOnlyElement(simpleEntity.getPolicies());
+        assertEquals(policy.getPolicyType().getName(), SIMPLE_POLICY_TYPE);
+
+        deleteCatalogEntity(referencedRegisteredTypeName);
+    }
+
+    @Test
+    public void testParentCatalogDoesNotLeakBundlesToChildCatalogItems() throws Exception {
+        String childCatalogId = "my.catalog.policy.id.no_bundles";
+        String parentCatalogId = "my.catalog.policy.id.parent";
+        addCatalogItem(
+            "brooklyn.catalog:",
+            "  id: " + childCatalogId,
+            "",
+            "services:",
+            "- type: " + BasicEntity.class.getName(),
+            "  brooklyn.policies:",
+            "  - type: " + SIMPLE_POLICY_TYPE);
+
+        addCatalogItem(
+            "brooklyn.catalog:",
+            "  id: " + parentCatalogId,
+            "  libraries:",
+            "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
+            "",
+            "services:",
+            "- type: " + childCatalogId);
+
+        try {
+            createAndStartApplication(
+                    "services:",
+                    "- type: " + parentCatalogId);
+        } catch (IllegalStateException e) {
+            assertTrue(e.getMessage().startsWith("Unable to load " + SIMPLE_POLICY_TYPE));
+        }
+
+        deleteCatalogEntity(parentCatalogId);
+        deleteCatalogEntity(childCatalogId);
+    }
+
+    private void addCatalogOSGiPolicy(String registeredTypeName, String serviceType) {
+        addCatalogItem(
+            "brooklyn.catalog:",
+            "  id: " + registeredTypeName,
+            "  name: My Catalog Policy",
+            "  description: My description",
+            "  icon_url: classpath://path/to/myicon.jpg",
+            "  version: 0.1.2",
+            "  libraries:",
+            "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
+            "",
+            "brooklyn.policies:",
+            "- type: " + serviceType,
+            "  brooklyn.config:",
+            "    config1: config1",
+            "    config2: config2");
+    }
+
+    private int countCatalogPolicies() {
+        return Iterables.size(mgmt().getCatalog().getCatalogItems(CatalogPredicates.IS_POLICY));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eb1c9867/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/CatalogYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/CatalogYamlTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/CatalogYamlTest.java
deleted file mode 100644
index 78f7c0d..0000000
--- a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/CatalogYamlTest.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * 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 io.brooklyn.camp.brooklyn;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
-
-import java.util.Collection;
-
-import org.testng.annotations.Test;
-
-import brooklyn.catalog.CatalogItem;
-import brooklyn.entity.Entity;
-import brooklyn.entity.basic.BasicEntity;
-import brooklyn.management.osgi.OsgiStandaloneTest;
-
-import com.google.common.collect.Iterables;
-
-
-public class CatalogYamlTest extends AbstractYamlTest {
-    private static final String SIMPLE_ENTITY_TYPE = "brooklyn.osgi.tests.SimpleEntity";
-
-    @Test
-    public void testAddCatalogItem() throws Exception {
-        String registeredTypeName = "my.catalog.app.id.load";
-        addCatalogOSGiEntity(registeredTypeName);
-        
-        CatalogItem<?, ?> item = mgmt().getCatalog().getCatalogItem(registeredTypeName);
-        assertEquals(item.getRegisteredTypeName(), registeredTypeName);
-    }
-
-    @Test
-    public void testLaunchApplicationReferencingCatalog() throws Exception {
-        String registeredTypeName = "my.catalog.app.id.launch";
-        registerAndLaunchAndAssertSimpleEntity(registeredTypeName, SIMPLE_ENTITY_TYPE);
-    }
-
-    @Test
-    public void testLaunchApplicationWithCatalogReferencingOtherCatalog() throws Exception {
-        String referencedRegisteredTypeName = "my.catalog.app.id.referenced";
-        String referrerRegisteredTypeName = "my.catalog.app.id.referring";
-        addCatalogOSGiEntity(referencedRegisteredTypeName, SIMPLE_ENTITY_TYPE);
-        addCatalogOSGiEntity(referrerRegisteredTypeName, referencedRegisteredTypeName);
-
-        String yaml = "name: simple-app-yaml\n" +
-                      "location: localhost\n" +
-                      "services: \n" +
-                      "  - serviceType: "+referrerRegisteredTypeName;
-        Entity app = createAndStartApplication(yaml);
-        
-        Entity simpleEntity = Iterables.getOnlyElement(app.getChildren());
-        assertEquals(simpleEntity.getEntityType().getName(), SIMPLE_ENTITY_TYPE);
-    }
-
-    @Test
-    public void testLaunchApplicationChildWithCatalogReferencingOtherCatalog() throws Exception {
-        String referencedRegisteredTypeName = "my.catalog.app.id.child.referenced";
-        String referrerRegisteredTypeName = "my.catalog.app.id.child.referring";
-        addCatalogOSGiEntity(referencedRegisteredTypeName, SIMPLE_ENTITY_TYPE);
-        addCatalogChildOSGiEntity(referrerRegisteredTypeName, referencedRegisteredTypeName);
-
-        Entity app = createAndStartApplication(
-            "name: simple-app-yaml",
-            "location: localhost",
-            "services:",
-            "- serviceType: "+BasicEntity.class.getName(),
-            "  brooklyn.children:",
-            "  - type: " + referrerRegisteredTypeName);
-        
-        Collection<Entity> children = app.getChildren();
-        assertEquals(children.size(), 1);
-        Entity child = Iterables.getOnlyElement(children);
-        assertEquals(child.getEntityType().getName(), BasicEntity.class.getName());
-        Collection<Entity> grandChildren = child.getChildren();
-        assertEquals(grandChildren.size(), 1);
-        Entity grandChild = Iterables.getOnlyElement(grandChildren);
-        assertEquals(grandChild.getEntityType().getName(), BasicEntity.class.getName());
-        Collection<Entity> grandGrandChildren = grandChild.getChildren();
-        assertEquals(grandGrandChildren.size(), 1);
-        Entity grandGrandChild = Iterables.getOnlyElement(grandGrandChildren);
-        assertEquals(grandGrandChild.getEntityType().getName(), SIMPLE_ENTITY_TYPE);
-    }
-
-    @Test
-    public void testLaunchApplicationWithTypeUsingJavaColonPrefix() throws Exception {
-        String registeredTypeName = SIMPLE_ENTITY_TYPE;
-        String serviceName = "java:"+SIMPLE_ENTITY_TYPE;
-        registerAndLaunchAndAssertSimpleEntity(registeredTypeName, serviceName);
-    }
-
-    @Test
-    public void testLaunchApplicationLoopWithJavaTypeName() throws Exception {
-        String registeredTypeName = SIMPLE_ENTITY_TYPE;
-        String serviceName = SIMPLE_ENTITY_TYPE;
-        registerAndLaunchAndAssertSimpleEntity(registeredTypeName, serviceName);
-    }
-
-    @Test
-    public void testLaunchApplicationLoopCatalogIdFails() throws Exception {
-        String registeredTypeName = "self.referencing.type";
-        registerAndLaunchFailsWithRecursionError(registeredTypeName, registeredTypeName);
-    }
-    
-    @Test
-    public void testLaunchApplicationChildLoopCatalogIdFails() throws Exception {
-        String referrerRegisteredTypeName = "my.catalog.app.id.child.referring";
-        addCatalogChildOSGiEntity(referrerRegisteredTypeName, referrerRegisteredTypeName);
-
-        try {
-            createAndStartApplication(
-                "name: simple-app-yaml",
-                "location: localhost",
-                "services:",
-                "- serviceType: "+BasicEntity.class.getName(),
-                "  brooklyn.children:",
-                "  - type: " + referrerRegisteredTypeName);
-            
-                fail("Expected to throw IllegalStateException");
-        } catch (IllegalStateException e) {
-            assertTrue(e.getMessage().contains("Recursive reference to "+referrerRegisteredTypeName));
-        } finally {
-            deleteCatalogEntity(referrerRegisteredTypeName);
-        }
-    }
-
-    /**
-     * Tests that a catalog item referenced by another
-     * catalog item won't have access to the parent's bundles.
-     */
-    @Test
-    public void testParentCatalogDoesNotLeakBundlesToChildCatalogItems() throws Exception {
-        String childCatalogId = "my.catalog.app.id.no_bundles";
-        String parentCatalogId = "my.catalog.app.id.parent";
-        addCatalogItem(
-                "brooklyn.catalog:",
-                "  id: " + childCatalogId,
-                "",
-                "services:",
-                "- type: " + SIMPLE_ENTITY_TYPE);
-        
-        addCatalogItem(
-                "brooklyn.catalog:",
-                "  id: " + parentCatalogId,
-                "  libraries:",
-                "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
-                "",
-                "services:",
-                "- type: " + childCatalogId);
-        
-        try {
-            createAndStartApplication(
-                    "services:",
-                    "- type: " + parentCatalogId);
-        } catch (UnsupportedOperationException e) {
-            assertTrue(e.getMessage().endsWith("cannot be matched"));
-            assertTrue(e.getMessage().contains(SIMPLE_ENTITY_TYPE));
-        }
-
-        deleteCatalogEntity(parentCatalogId);
-        deleteCatalogEntity(childCatalogId);
-    }
-
-    private void registerAndLaunchAndAssertSimpleEntity(String registeredTypeName, String serviceType) throws Exception {
-        addCatalogOSGiEntity(registeredTypeName, serviceType);
-        try {
-            String yaml = "name: simple-app-yaml\n" +
-                          "location: localhost\n" +
-                          "services: \n" +
-                          "  - serviceType: "+registeredTypeName;
-            Entity app = createAndStartApplication(yaml);
-    
-            Entity simpleEntity = Iterables.getOnlyElement(app.getChildren());
-            assertEquals(simpleEntity.getEntityType().getName(), SIMPLE_ENTITY_TYPE);
-        } finally {
-            deleteCatalogEntity(registeredTypeName);
-        }
-    }
-
-    private void registerAndLaunchFailsWithRecursionError(String registeredTypeName, String serviceType) throws Exception {
-        addCatalogOSGiEntity(registeredTypeName, serviceType);
-        try {
-            String yaml = "name: simple-app-yaml\n" +
-                          "location: localhost\n" +
-                          "services: \n" +
-                          "  - serviceType: "+registeredTypeName;
-            try {
-                createAndStartApplication(yaml);
-                fail("Expected to throw IllegalStateException");
-            } catch (IllegalStateException e) {
-                assertTrue(e.getMessage().contains("Recursive reference to "+registeredTypeName));
-            }
-        } finally {
-            deleteCatalogEntity(registeredTypeName);
-        }
-    }
-
-    private void addCatalogOSGiEntity(String registeredTypeName) {
-        addCatalogOSGiEntity(registeredTypeName, SIMPLE_ENTITY_TYPE);
-    }
-    
-    private void addCatalogOSGiEntity(String registeredTypeName, String serviceType) {
-        addCatalogItem(
-            "brooklyn.catalog:",
-            "  id: " + registeredTypeName,
-            "  name: My Catalog App",
-            "  description: My description",
-            "  icon_url: classpath://path/to/myicon.jpg",
-            "  version: 0.1.2",
-            "  libraries:",
-            "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
-            "",
-            "services:",
-            "- type: " + serviceType);
-    }
-
-    private void addCatalogChildOSGiEntity(String registeredTypeName, String serviceType) {
-        addCatalogItem(
-            "brooklyn.catalog:",
-            "  id: " + registeredTypeName,
-            "  name: My Catalog App",
-            "  description: My description",
-            "  icon_url: classpath://path/to/myicon.jpg",
-            "  version: 0.1.2",
-            "  libraries:",
-            "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
-            "",
-            "services:",
-            "- type: " + BasicEntity.class.getName(),
-            "  brooklyn.children:",
-            "  - type: " + serviceType);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eb1c9867/usage/rest-api/src/main/java/brooklyn/rest/domain/CatalogPolicySummary.java
----------------------------------------------------------------------
diff --git a/usage/rest-api/src/main/java/brooklyn/rest/domain/CatalogPolicySummary.java b/usage/rest-api/src/main/java/brooklyn/rest/domain/CatalogPolicySummary.java
index 6505d8a..98453d4 100644
--- a/usage/rest-api/src/main/java/brooklyn/rest/domain/CatalogPolicySummary.java
+++ b/usage/rest-api/src/main/java/brooklyn/rest/domain/CatalogPolicySummary.java
@@ -32,12 +32,13 @@ public class CatalogPolicySummary extends CatalogItemSummary {
             @JsonProperty("id") String id,
             @JsonProperty("name") String name,
             @JsonProperty("type") String type,
+            @JsonProperty("planYaml") String planYaml,
             @JsonProperty("description") String description,
             @JsonProperty("iconUrl") String iconUrl,
             @JsonProperty("config") Set<PolicyConfigSummary> config,
             @JsonProperty("links") Map<String, URI> links
         ) {
-        super(id, name, type, type, type, null, description, iconUrl, links);
+        super(id, name, type, type, type, planYaml, description, iconUrl, links);
         // TODO expose config from policies
         this.config = config;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eb1c9867/usage/rest-server/src/main/java/brooklyn/rest/transform/CatalogTransformer.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/transform/CatalogTransformer.java b/usage/rest-server/src/main/java/brooklyn/rest/transform/CatalogTransformer.java
index 33dc4d9..9f232d9 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/transform/CatalogTransformer.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/transform/CatalogTransformer.java
@@ -89,7 +89,8 @@ public class CatalogTransformer {
 
     public static CatalogPolicySummary catalogPolicySummary(BrooklynRestResourceUtils b, CatalogItem<? extends Policy,PolicySpec<?>> item) {
         Set<PolicyConfigSummary> config = ImmutableSet.of();
-        return new CatalogPolicySummary(item.getId(), item.getName(), item.getJavaType(),
+        return new CatalogPolicySummary(item.getId(), item.getName(), item.getRegisteredTypeName(),
+                item.getPlanYaml(),
                 item.getDescription(), tidyIconLink(b, item, item.getIconUrl()), config,
                 makeLinks(item));
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eb1c9867/utils/common/src/main/java/brooklyn/util/yaml/Yamls.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/yaml/Yamls.java b/utils/common/src/main/java/brooklyn/util/yaml/Yamls.java
index a22432f..cad4395 100644
--- a/utils/common/src/main/java/brooklyn/util/yaml/Yamls.java
+++ b/utils/common/src/main/java/brooklyn/util/yaml/Yamls.java
@@ -106,7 +106,22 @@ public class Yamls {
                 if (result==null) result = candidate;
                 else if (!result.equals(candidate)) {
                     log.warn("Different values for attributes "+Arrays.toString(equivalentNames)+"; " +
-                    		"preferring '"+result+"' to '"+candidate+"'");
+                            "preferring '"+result+"' to '"+candidate+"'");
+                }
+            }
+        }
+        return result;
+    }
+
+    public static Object getMultinameAttribute(Map<String,Object> obj, String ...equivalentNames) {
+        Object result = null;
+        for (String name: equivalentNames) {
+            Object candidate = obj.get(name);
+            if (candidate!=null) {
+                if (result==null) result = candidate;
+                else if (!result.equals(candidate)) {
+                    log.warn("Different values for attributes "+Arrays.toString(equivalentNames)+"; " +
+                            "preferring '"+result+"' to '"+candidate+"'");
                 }
             }
         }


[5/6] git commit: This closes #124

Posted by sj...@apache.org.
This closes #124


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

Branch: refs/heads/master
Commit: d3682450cdaaf84ded25aec65d4b4d73b1168060
Parents: 5e25133 4811e81
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Wed Aug 27 11:01:50 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Wed Aug 27 11:01:50 2014 +0100

----------------------------------------------------------------------
 .../catalog/internal/BasicBrooklynCatalog.java  | 149 +++++++----
 .../catalog/internal/CatalogItemBuilder.java    |  90 +++++++
 .../java/brooklyn/osgi/tests/SimplePolicy.java  |  36 +++
 .../osgi/brooklyn-test-osgi-entities.jar        | Bin 10891 -> 14663 bytes
 .../BrooklynEntityDecorationResolver.java       |  22 +-
 .../camp/brooklyn/CatalogYamlEntityTest.java    | 254 +++++++++++++++++++
 .../camp/brooklyn/CatalogYamlPolicyTest.java    | 170 +++++++++++++
 .../brooklyn/camp/brooklyn/CatalogYamlTest.java | 250 ------------------
 .../src/main/webapp/assets/js/view/catalog.js   |  13 +-
 .../assets/tpl/catalog/details-entity.html      |   2 +
 .../rest/domain/CatalogPolicySummary.java       |   3 +-
 .../rest/transform/CatalogTransformer.java      |   3 +-
 .../src/main/java/brooklyn/util/yaml/Yamls.java |  17 +-
 13 files changed, 702 insertions(+), 307 deletions(-)
----------------------------------------------------------------------