You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2014/07/04 11:50:43 UTC

[01/45] import of brooklyncentral/camp-server dependency to apache brooklyn project

Repository: incubator-brooklyn
Updated Branches:
  refs/heads/master f28d9cc6b -> 1a9732e78


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/pom.xml
----------------------------------------------------------------------
diff --git a/camp/pom.xml b/camp/pom.xml
new file mode 100644
index 0000000..0f4432a
--- /dev/null
+++ b/camp/pom.xml
@@ -0,0 +1,1060 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <packaging>pom</packaging>
+
+    <groupId>io.brooklyn.camp</groupId>
+    <artifactId>camp-parent</artifactId>
+    <version>0.1.0-SNAPSHOT</version>  <!-- CAMP_IMPL_VERSION -->
+
+    <name>CAMP Server Parent Project</name>
+    <description>
+        Parent/Root Project for Oasis CAMP Server modules
+    </description>
+    <url>http://brooklyn.io/</url>
+
+    <!-- useful custom properties/defines to specify to control the build:
+
+      camp.explicitModules :: only builds explicit modules (instead of default modules)
+
+      camp.deployTo={cloudsoftFilesystem,cloudsoftArtifactory,sonatype} :: 
+            :: required when deploying; specify the deployment target
+
+      javadoc :: build javadoc (adds a minute or two; enabled automatically for target deploy)
+      
+      skipSources :: don't make the -sources.jar (saves a second or two, not much)
+      
+      skipTests :: does the usual thing (saves a lot of time, but at some cost of build quality!)
+
+
+      simply activate with -Dcamp.theCustomProperty on the mvn build line
+      (some of these are used to trigger profile selection, since maven activeByDefault
+      only works if _no_ profiles are triggered, see suggestion/background at:
+      http://stackoverflow.com/questions/5309379/how-to-keep-maven-profiles-which-are-activebydefault-active-even-if-another-prof )
+    -->
+
+    <licenses>
+        <license>
+            <name>The Apache Software License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+            <distribution>repo</distribution>
+        </license>
+    </licenses>
+
+    <developers>
+        <developer>
+            <name>Brooklyn Committers</name>
+        </developer>
+    </developers>
+
+    <scm>
+        <connection>scm:git:git://github.com/brooklyncentral/camp.git</connection>
+        <developerConnection>scm:git:git@github.com:brooklyncentral/camp.git</developerConnection>
+        <url>http://github.com/brooklyncentral/camp</url>
+    </scm>
+
+    <repositories>
+        <!-- enable sonatype snapshots repo (only for snapshots) -->
+        <repository>
+            <id>sonatype-nexus-snapshots</id>
+            <name>Sonatype Nexus Snapshots</name>
+            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+            <releases> <enabled>false</enabled> </releases>
+            <snapshots> <enabled>true</enabled> </snapshots>
+        </repository>
+    </repositories>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+
+        <camp-impl.version>0.1.0-SNAPSHOT</camp-impl.version>  <!-- CAMP_IMPL_VERSION -->
+
+        <brooklyn.version>0.7.0-SNAPSHOT</brooklyn.version>  <!-- BROOKLYN_VERSION -->
+        <fasterxml.jackson.version>2.2.0</fasterxml.jackson.version>
+        <commons-lang3.version>3.1</commons-lang3.version>
+        <commons-compress.version>1.4</commons-compress.version>
+
+        <surefire.version>2.13</surefire.version>
+        <testng.version>6.8</testng.version>
+        <logback.version>1.0.7</logback.version>
+        <slf4j.version>1.6.6</slf4j.version>
+        <gson.version>2.2.2</gson.version>
+        <commons-io.version>2.4</commons-io.version>
+     
+        <includedTestGroups />
+        <excludedTestGroups>Integration,Acceptance,Live,WIP</excludedTestGroups>
+        
+        <!-- no passphrase by default, so we can do automated deploy builds;
+             you can still supply your own passphrase with -Dgpg.passphrase=XXX -->
+        <gpg.passphrase></gpg.passphrase>
+    </properties>
+
+    <dependencyManagement>
+        <dependencies>
+            <!-- include version numbers for common dependencies 
+            <dependency>
+                <groupId>ch.qos.logback</groupId>
+                <artifactId>logback-classic</artifactId>
+                <version>${logback.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.google.guava</groupId>
+                <artifactId>guava</artifactId>
+                <version>${guava.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.slf4j</groupId>
+                <artifactId>slf4j-api</artifactId>
+                <version>${slf4j.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.testng</groupId>
+                <artifactId>testng</artifactId>
+                <version>${testng.version}</version>
+            </dependency>
+            -->
+        </dependencies>
+    </dependencyManagement>
+
+    <build>
+        <testSourceDirectory>src/test/java</testSourceDirectory>
+        <testResources>
+            <testResource>
+                <directory>src/test/resources</directory>
+            </testResource>
+        </testResources>
+
+        <pluginManagement>
+            <plugins>
+                <plugin>
+                    <artifactId>maven-assembly-plugin</artifactId>
+                    <version>2.3</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-antrun-plugin</artifactId>
+                    <version>1.6</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-clean-plugin</artifactId>
+                    <version>2.4.1</version>
+                    <configuration>
+                        <filesets>
+                            <fileset>
+                                <directory>.</directory>
+                                <includes>
+                                    <include>camp*.log</include>
+                                    <include>camp*.log.*</include>
+                                    <include>stacktrace.log</include>
+                                    <include>test-output</include>
+                                    <include>prodDb.*</include>
+                                </includes>
+                            </fileset>
+                        </filesets>
+                    </configuration>
+                </plugin>
+<!--
+                <plugin>
+                    <artifactId>maven-compiler-plugin</artifactId>
+                    <version>2.3.2</version>
+                    <configuration>
+                        <source>1.6</source>
+                        <target>1.6</target>
+                    </configuration>
+                </plugin>
+-->
+<!-- use the groovy-eclipse-compiler (below) instead of the stack maven/java one (above)
+     because we use an inner-class builder pattern which references private outer class
+     members which gives "has private access" errors with some javac's (fixed in java7?) -->
+                <plugin>
+                  <artifactId>maven-compiler-plugin</artifactId>
+                  <configuration>
+                    <compilerId>groovy-eclipse-compiler</compilerId>
+                    <fork>true</fork>
+                    <verbose>false</verbose>
+                    <source>1.6</source>
+                    <target>1.6</target>
+                  </configuration>
+                  <dependencies>
+                    <dependency>
+                        <groupId>org.codehaus.groovy</groupId>
+                        <artifactId>groovy-eclipse-compiler</artifactId>
+                        <version>2.7.0-01</version>
+                    </dependency>
+                    <dependency>
+                        <groupId>org.codehaus.groovy</groupId>
+                        <artifactId>groovy-eclipse-batch</artifactId>
+                        <version>1.8.6-01</version>
+                    </dependency>
+                  </dependencies>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-deploy-plugin</artifactId>
+                    <version>2.5</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-enforcer-plugin</artifactId>
+                    <version>1.0</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-failsafe-plugin</artifactId>
+                    <version>2.9</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-jar-plugin</artifactId>
+                    <version>2.4</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-source-plugin</artifactId>
+                    <version>2.1.2</version>
+                    <inherited>true</inherited>
+                    <executions>
+                        <execution>
+                            <id>attach-sources</id>
+                            <phase>verify</phase>
+                            <goals>
+                                <goal>jar-no-fork</goal>
+                            </goals>
+                        </execution>
+                    </executions>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-javadoc-plugin</artifactId>
+                    <version>2.8</version>
+                    <inherited>true</inherited>
+                    <configuration>
+                        <links>
+                            <link>http://download.oracle.com/javaee/6/api</link>
+                        </links>
+                        <keywords>true</keywords>
+                        <author>false</author>
+                        <quiet>true</quiet>
+                        <aggregate>false</aggregate>
+                        <detectLinks />
+                        <tags>
+                            <tag>
+                                <name>todo</name>
+                                <placement>a</placement>
+                                <head>To-do:</head>
+                            </tag>
+                        </tags>
+                    </configuration>
+                    <executions>
+                        <execution>
+                            <id>attach-javadocs</id>
+                            <goals>
+                                <goal>jar</goal>
+                            </goals>
+                        </execution>
+                    </executions>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-gpg-plugin</artifactId>
+                    <version>1.1</version>
+                    <executions>
+                        <execution>
+                            <id>sign-artifacts</id>
+                            <phase>verify</phase>
+                            <goals>
+                                <goal>sign</goal>
+                            </goals>
+                        </execution>
+                    </executions>
+                </plugin>
+                <plugin>
+                    <!-- 'release' is not used; easier just to checkout, tag, `mvn deploy` manually
+                         with -Dcamp.deployTo=TARGET ... and note we need to update docs and examples, 
+                         which is a non-maven task!) -->
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-release-plugin</artifactId>
+                    <version>2.1</version>
+                    <configuration>
+                        <mavenExecutorId>forked-path</mavenExecutorId>
+                        <useReleaseProfile>false</useReleaseProfile>
+                        <arguments>-Dcamp.deployTo=sonatype</arguments>
+                    </configuration>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-resources-plugin</artifactId>
+                    <version>2.4.1</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-shade-plugin</artifactId>
+                    <version>1.5</version>
+                    <executions>
+                        <execution>
+                            <phase>package</phase>
+                            <goals>
+                                <goal>shade</goal>
+                            </goals>
+                            <configuration>
+                                <shadedArtifactAttached>true</shadedArtifactAttached>
+                                <shadedClassifierName>with-dependencies</shadedClassifierName>
+                                <filters>
+                                    <filter>
+                                        <artifact>*:*</artifact>
+                                        <excludes>
+                                            <exclude>META-INF/*.SF</exclude>
+                                            <exclude>META-INF/*.DSA</exclude>
+                                            <exclude>META-INF/*.RSA</exclude>
+                                        </excludes>
+                                    </filter>
+                                </filters>
+                                <transformers>
+                                    <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
+                                </transformers>
+                            </configuration>
+                        </execution>
+                    </executions>
+                </plugin>
+                <plugin>
+                     <artifactId>maven-surefire-plugin</artifactId>
+                     <version>${surefire.version}</version>
+                     <configuration>
+                         <argLine>-Xms256m -Xmx512m -XX:MaxPermSize=512m -verbose:gc</argLine>
+                    </configuration>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-site-plugin</artifactId>
+                    <version>3.0</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-eclipse-plugin</artifactId>
+                    <version>2.8</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.felix</groupId>
+                    <artifactId>maven-bundle-plugin</artifactId>
+                    <version>2.3.4</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.codehaus.mojo</groupId>
+                    <artifactId>findbugs-maven-plugin</artifactId>
+                    <version>2.3.2</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.codehaus.mojo</groupId>
+                    <artifactId>build-helper-maven-plugin</artifactId>
+                    <version>1.7</version>
+                </plugin>
+                <plugin>
+                    <groupId>net.sourceforge.cobertura</groupId>
+                    <artifactId>cobertura</artifactId>
+                    <version>${cobertura.version}</version>
+                </plugin>
+                <plugin>
+                    <!-- This configuration is used for Eclipse settings only. -->
+                    <groupId>org.eclipse.m2e</groupId>
+                    <artifactId>lifecycle-mapping</artifactId>
+                    <version>1.0.0</version>
+                    <configuration>
+                        <lifecycleMappingMetadata>
+                            <pluginExecutions>
+                                <pluginExecution>
+                                    <pluginExecutionFilter>
+                                        <groupId>org.apache.maven.plugins</groupId>
+                                        <artifactId>maven-dependency-plugin</artifactId>
+                                        <versionRange>[2.1,)</versionRange>
+                                        <goals>
+                                            <goal>copy</goal>
+                                            <goal>copy-dependencies</goal>
+                                        </goals>
+                                    </pluginExecutionFilter>
+                                    <action>
+                                        <ignore />
+                                    </action>
+                                </pluginExecution>
+                                <pluginExecution>
+                                    <pluginExecutionFilter>
+                                        <groupId>org.apache.felix</groupId>
+                                        <artifactId>maven-bundle-plugin</artifactId>
+                                        <versionRange>[2.3.4,)</versionRange>
+                                        <goals>
+                                            <goal>manifest</goal>
+                                        </goals>
+                                    </pluginExecutionFilter>
+                                    <action>
+                                        <ignore />
+                                    </action>
+                                </pluginExecution>
+                                <pluginExecution>
+                                    <pluginExecutionFilter>
+                                        <groupId>org.apache.maven.plugins</groupId>
+                                        <artifactId>maven-javadoc-plugin</artifactId>
+                                        <versionRange>[2.7,3)</versionRange>
+                                        <goals>
+                                            <goal>jar</goal>
+                                        </goals>
+                                    </pluginExecutionFilter>
+                                    <action>
+                                        <ignore />
+                                    </action>
+                                </pluginExecution>
+                                <pluginExecution>
+                                    <pluginExecutionFilter>
+                                        <groupId>org.apache.maven.plugins</groupId>
+                                        <artifactId>maven-enforcer-plugin</artifactId>
+                                        <versionRange>[1.0,)</versionRange>
+                                        <goals>
+                                            <goal>enforce</goal>
+                                        </goals>
+                                    </pluginExecutionFilter>
+                                    <action>
+                                        <ignore />
+                                    </action>
+                                </pluginExecution>
+                            </pluginExecutions>
+                        </lifecycleMappingMetadata>
+                    </configuration>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+        <plugins>
+            <plugin>
+                <artifactId>maven-enforcer-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>enforce</id>
+                        <phase>none</phase>
+                    </execution>
+                    <execution>
+                        <id>custom-build-req</id>
+                        <goals>
+                            <goal>enforce</goal>
+                        </goals>
+                        <inherited>true</inherited>
+                        <configuration>
+                            <rules>
+                                <requireJavaVersion>
+                                    <version>1.6.0</version>
+                                </requireJavaVersion>
+                                <requireMavenVersion>
+                                    <version>[3.0.0,)</version>
+                                </requireMavenVersion>
+                            </rules>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-resources-plugin</artifactId>
+                <configuration>
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                </configuration>
+            </plugin>
+            <!--  workaround for src/main/resources excluding all in eclipse, as per
+                  https://issues.sonatype.org/browse/MNGECLIPSE-864 -->
+            <plugin>
+                <groupId>com.google.code.maven-replacer-plugin</groupId>
+                <artifactId>maven-replacer-plugin</artifactId>
+                <version>1.4.0</version>
+                <executions>
+                    <execution>
+                        <phase>clean</phase>
+                        <goals>
+                            <goal>replace</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <ignoreMissingFile>true</ignoreMissingFile>
+                    <file>.classpath</file>
+                    <regex>false</regex>
+                    <replacements>
+                        <replacement>
+                            <xpath>/classpath/classpathentry[@path='src/main/resources' and @kind='src' and @excluding='**']/@excluding</xpath>
+                            <token>**</token>
+                            <value></value>
+                        </replacement>
+                    </replacements>
+                </configuration>
+            </plugin>
+        </plugins>
+        <extensions>
+            <extension>
+                <groupId>org.apache.maven.wagon</groupId>
+                <artifactId>wagon-ssh-external</artifactId>
+                <version>1.0</version>
+            </extension>
+        </extensions>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>Essentials</id>
+            <activation> <property><name> !camp.explicitModules </name></property> </activation>
+            <modules>
+                <module>camp-base</module>
+                <module>camp-server</module>
+            </modules>
+        </profile>
+
+        <profile>
+            <id>Documentation</id>
+            <reporting>
+                <excludeDefaults>true</excludeDefaults>
+                <plugins>
+                    <plugin>
+                        <artifactId>maven-project-info-reports-plugin</artifactId>
+                        <version>2.4</version>
+                        <reportSets>
+                            <reportSet>
+                                <reports>
+                                    <report>index</report>
+                                    <report>modules</report>
+                                </reports>
+                            </reportSet>
+                        </reportSets>
+                    </plugin>
+                    <plugin>
+                        <artifactId>maven-javadoc-plugin</artifactId>
+                        <version>2.8</version>
+                        <configuration>
+                            <links>
+                                <link>http://download.oracle.com/javaee/6/api</link>
+                            </links>
+                            <keywords>true</keywords>
+                            <author>false</author>
+                            <quiet>true</quiet>
+                            <aggregate>false</aggregate>
+                            <detectLinks />
+                            <tags>
+                                <tag>
+                                    <name>todo</name>
+                                    <placement>a</placement>
+                                    <head>To-do:</head>
+                                </tag>
+                            </tags>
+                        </configuration>
+                        <reportSets>
+                            <reportSet>
+                                <id>javadoc</id>
+                                <reports>
+                                    <report>javadoc</report>
+                                </reports>
+                            </reportSet>
+                        </reportSets>
+                    </plugin>
+                </plugins>
+            </reporting>
+        </profile>
+        <profile>
+            <id>Bundle</id>
+            <activation>
+                <file>
+                    <exists>${basedir}/src</exists>
+                </file>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.felix</groupId>
+                        <artifactId>maven-bundle-plugin</artifactId>
+                        <extensions>true</extensions>
+                        <executions>
+                            <execution>
+                                <id>create-bundle-manifest</id>
+                                <phase>process-classes</phase>
+                                <goals>
+                                    <goal>manifest</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
+            <id>Tests</id>
+            <activation>
+                <file> <exists>${basedir}/src/test</exists> </file>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <version>${surefire.version}</version>
+                        <configuration>
+                            <properties>
+                                <property>
+                                    <name>listener</name>
+                                    <value>brooklyn.test.LoggingVerboseReporter</value>
+                                </property>
+                            </properties>
+                            <enableAssertions>true</enableAssertions>
+                            <groups>${includedTestGroups}</groups>
+                            <excludedGroups>${excludedTestGroups}</excludedGroups>
+                            <testFailureIgnore>false</testFailureIgnore>
+                            <systemPropertyVariables>
+                                <verbose>-1</verbose>
+                                <net.sourceforge.cobertura.datafile>${project.build.directory}/cobertura/cobertura.ser</net.sourceforge.cobertura.datafile>
+                                <cobertura.user.java.nio>false</cobertura.user.java.nio>
+                            </systemPropertyVariables>
+                            <printSummary>true</printSummary>
+                        </configuration>
+                    </plugin>
+                    <plugin>
+                        <artifactId>maven-jar-plugin</artifactId>
+                        <inherited>true</inherited>
+                        <executions>
+                            <execution>
+                                <id>test-jar-creation</id>
+                                <goals>
+                                    <goal>test-jar</goal>
+                                </goals>
+                                <configuration>
+                                    <forceCreation>true</forceCreation>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>Integration</id>
+            <properties>
+                <includedTestGroups>Integration</includedTestGroups>
+                <excludedTestGroups>Acceptance,Live,WIP</excludedTestGroups>
+            </properties>
+            <build>
+                <plugins>
+                    <plugin>
+                        <artifactId>maven-antrun-plugin</artifactId>
+                        <inherited>true</inherited>
+                        <executions>
+                            <execution>
+                                <id>run-tests</id>
+                                <goals>
+                                    <goal>run</goal>
+                                </goals>
+                                <phase>integration-test</phase>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <artifactId>maven-jar-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>test-jar-creation</id>
+                                <configuration>
+                                    <skip>true</skip>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>Acceptance</id>
+            <properties>
+                <includedTestGroups>Acceptance</includedTestGroups>
+                <excludedTestGroups>Integration,Live,WIP</excludedTestGroups>
+            </properties>
+            <build>
+                <plugins>
+                    <plugin>
+                        <artifactId>maven-antrun-plugin</artifactId>
+                        <inherited>true</inherited>
+                        <executions>
+                            <execution>
+                                <id>run-tests</id>
+                                <goals>
+                                    <goal>run</goal>
+                                </goals>
+                                <phase>integration-test</phase>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <artifactId>maven-jar-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>test-jar-creation</id>
+                                <configuration>
+                                    <skip>true</skip>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>Live</id>
+            <properties>
+                <includedTestGroups>Live</includedTestGroups>
+                <excludedTestGroups>Acceptance,WIP</excludedTestGroups>
+            </properties>
+            <build>
+                <plugins>
+                <!-- 
+                    <plugin>
+                        <artifactId>maven-antrun-plugin</artifactId>
+                        <inherited>true</inherited>
+                        <executions>
+                            <execution>
+                                <id>run-tests</id>
+                                <goals>
+                                    <goal>run</goal>
+                                </goals>
+                                <phase>integration-test</phase>
+                            </execution>
+                        </executions>
+                    </plugin>
+                 -->
+                    <plugin>
+                        <artifactId>maven-jar-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>test-jar-creation</id>
+                                <configuration>
+                                    <skip>true</skip>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
+            <id>CI</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>findbugs-maven-plugin</artifactId>
+                        <configuration>
+                            <xmlOutput>true</xmlOutput>
+                            <xmlOutputDirectory>target/site</xmlOutputDirectory>
+                        </configuration>
+                        <executions>
+                            <execution>
+                                <phase>process-classes</phase>
+                                <goals>
+                                    <goal>findbugs</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <artifactId>maven-source-plugin</artifactId>
+                    </plugin>
+                    <plugin>
+                        <artifactId>maven-pmd-plugin</artifactId>
+                        <version>2.5</version>
+                        <inherited>true</inherited>
+                        <configuration>
+                            <failOnViolation>false</failOnViolation>
+                            <linkXref>true</linkXref>
+                            <sourceEncoding>utf-8</sourceEncoding>
+                            <minimumTokens>100</minimumTokens>
+                            <targetJdk>1.6</targetJdk>
+                            <excludes>
+                                <exclude>**/*Test.java</exclude>
+                                <exclude>**/tests/**/*.java</exclude>
+                                <!-- add any more generated source code directories here -->
+                            </excludes>
+                            <excludeRoots>
+                                <excludeRoot>
+                                    ${pom.basedir}/target/generated-sources/groovy-stubs/main
+                                </excludeRoot>
+                            </excludeRoots>
+                        </configuration>
+                        <executions>
+                            <execution>
+                                <phase>process-classes</phase>
+                                <goals>
+                                    <goal>check</goal>
+                                    <goal>cpd-check</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>Coverage</id>
+            <dependencies>
+                <dependency>
+                    <groupId>net.sourceforge.cobertura</groupId>
+                    <artifactId>cobertura</artifactId>
+                    <version>${cobertura.version}</version>
+                    <scope>test</scope>
+                </dependency>
+            </dependencies>
+            <build>
+                <plugins>
+                    <plugin>
+                        <artifactId>maven-source-plugin</artifactId>
+                    </plugin>
+                    <plugin>
+                        <artifactId>maven-antrun-plugin</artifactId>
+                        <inherited>true</inherited>
+                        <executions>
+                            <execution>
+                                <id>run-tests</id>
+                            </execution>
+                            <execution>
+                                <id>instrument classes</id>
+                                <goals>
+                                    <goal>run</goal>
+                                </goals>
+                                <phase>process-test-classes</phase>
+                                <configuration>
+                                    <target>
+                                        <taskdef resource="net/sf/antcontrib/antcontrib.properties" classpathref="maven.plugin.classpath" />
+                                        <taskdef resource="tasks.properties" classpathref="maven.plugin.classpath" />
+                                        <if>
+                                            <available property="gogocobertura" file="target/test-classes" />
+                                            <then>
+                                                <echo message="INSTRUMENTING CLASSES FOR COBERTURA" />
+                                                <!-- Ensure any and all bits of our project are copied in first -->
+                                                <copy todir="target/cobertura/coverage-classes">
+                                                    <fileset erroronmissingdir="false" dir="target/classes" />
+                                                </copy>
+                                                <cobertura-instrument datafile="target/cobertura/cobertura.ser"
+                                                    todir="target/test-classes">
+                                                    <fileset erroronmissingdir="false" dir="target/classes">
+                                                        <include name="**/*.class" />
+                                                        <exclude name="**/*Test.class" />
+                                                    </fileset>
+                                                    <fileset erroronmissingdir="false" dir="target/cobertura/dependency-classes">
+                                                        <include name="**/*.class" />
+                                                        <exclude name="**/*Test.class" />
+                                                    </fileset>
+                                                </cobertura-instrument>
+                                            </then>
+                                        </if>
+                                    </target>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>coverage report</id>
+                                <goals>
+                                    <goal>run</goal>
+                                </goals>
+                                <phase>post-integration-test</phase>
+                                <configuration>
+                                    <target>
+                                        <taskdef resource="net/sf/antcontrib/antcontrib.properties" classpathref="maven.plugin.classpath" />
+                                        <taskdef resource="tasks.properties" classpathref="maven.plugin.classpath" />
+                                        <if>
+                                            <available property="gogocobertura" file="target/cobertura/cobertura.ser" />
+                                            <then>
+                                                <echo message="GENERATING COBERTURA COVERAGE REPORT" />
+                                                <cobertura-report format="xml" destdir="target/site/cobertura"
+                                                    datafile="target/cobertura/cobertura.ser">
+                                                    <fileset erroronmissingdir="false" dir="src/java" />
+                                                    <fileset erroronmissingdir="false" dir="target/cobertura/dependency-sources" />
+                                                </cobertura-report>
+                                            </then>
+                                        </if>
+                                    </target>
+                                </configuration>
+                            </execution>
+                        </executions>
+                        <dependencies>
+                            <dependency>
+                                <groupId>ant-contrib</groupId>
+                                <artifactId>ant-contrib</artifactId>
+                                <version>1.0b3</version>
+                                <exclusions>
+                                    <exclusion>
+                                        <groupId>ant</groupId>
+                                        <artifactId>ant</artifactId>
+                                    </exclusion>
+                                </exclusions>
+                            </dependency>
+                            <dependency>
+                                <groupId>org.apache.ant</groupId>
+                                <artifactId>ant-launcher</artifactId>
+                                <version>${ant.version}</version>
+                            </dependency>
+                            <dependency>
+                                <groupId>org.apache.ant</groupId>
+                                <artifactId>ant</artifactId>
+                                <version>${ant.version}</version>
+                            </dependency>
+                            <dependency>
+                                <groupId>org.testng</groupId>
+                                <artifactId>testng</artifactId>
+                                <version>${testng.version}</version>
+                            </dependency>
+                            <dependency>
+                                <groupId>net.sourceforge.cobertura</groupId>
+                                <artifactId>cobertura</artifactId>
+                                <version>${cobertura.version}</version>
+                            </dependency>
+                        </dependencies>
+                    </plugin>
+                    <plugin>
+                        <artifactId>maven-dependency-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>unpack-coverage-sources</id>
+                                <phase>generate-sources</phase>
+                                <goals>
+                                    <goal>unpack-dependencies</goal>
+                                </goals>
+                                <configuration>
+                                    <classifier>sources</classifier>
+                                    <includeScope>compile</includeScope>
+                                    <includeGroupIds>io.brooklyn.camp</includeGroupIds>
+                                    <outputDirectory>
+                                        ${project.build.directory}/cobertura/dependency-sources
+                                    </outputDirectory>
+                                    <failOnMissingClassifierArtifact>false</failOnMissingClassifierArtifact>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>unpack-coverage-classes</id>
+                                <phase>compile</phase>
+                                <goals>
+                                    <goal>unpack-dependencies</goal>
+                                </goals>
+                                <configuration>
+                                    <type>jar</type>
+                                    <includeScope>compile</includeScope>
+                                    <includeGroupIds>io.brooklyn.camp</includeGroupIds>
+                                    <outputDirectory>
+                                        ${project.build.directory}/cobertura/dependency-classes
+                                    </outputDirectory>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <version>${surefire.version}</version>
+                        <inherited>true</inherited>
+                        <configuration>
+                            <reportFormat>xml</reportFormat>
+                            <classesDirectory>${project.build.directory}/cobertura/coverage-classes</classesDirectory>
+                            <systemProperties>
+                                <property>
+                                    <name>net.sourceforge.cobertura.datafile</name>
+                                    <value>${project.build.directory}/cobertura/cobertura.ser
+                                    </value>
+                                </property>
+                                <property>
+                                    <name>cobertura.user.java.nio</name>
+                                    <value>false</value>
+                                </property>
+                            </systemProperties>
+                        </configuration>
+                    </plugin>
+                    <plugin>
+                        <artifactId>maven-jar-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>test-jar-creation</id>
+                                <configuration>
+                                    <skip>true</skip>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <artifactId>maven-deploy-plugin</artifactId>
+                        <configuration>
+                            <skip>true</skip>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <!-- build sources jars by default, it's quick -->
+        <profile>
+            <id>make-sources-jar</id>
+            <activation> <property><name>!skipSources</name></property> </activation>
+            <build><plugins><plugin>
+                <artifactId>maven-source-plugin</artifactId>
+            </plugin></plugins></build>
+        </profile>
+        
+        <!-- only build javadoc if asked, or if deploying (it's slow) -->
+        <profile>
+            <id>make-javadoc-jar</id>
+            <activation> <property><name>javadoc</name></property> </activation>            
+            <build><plugins><plugin>
+                <artifactId>maven-javadoc-plugin</artifactId>
+            </plugin></plugins></build>
+        </profile>
+        
+        <!-- sign and make javadoc when deploying; note, this means you'll need gpg set up to deploy -->
+        <profile>
+            <id>make-more-things-when-deploying</id>
+            <activation> <property><name>camp.deployTo</name></property> </activation>            
+            <build><plugins>
+                <plugin>
+                    <artifactId>maven-javadoc-plugin</artifactId>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-gpg-plugin</artifactId>
+                </plugin>
+            </plugins></build>
+        </profile>
+
+        <!-- different properties used to deploy to different locations depending on profiles;
+             default is cloudsoft filesystem repo, but some sources still use cloudsoft artifactory as source
+             (and soon we will support artifactory) -->
+        <profile>
+            <id>cloudsoft-filesystem-repo</id>
+            <activation> <property><name>camp.deployTo</name><value>cloudsoftFilesystem</value></property> </activation>
+            <distributionManagement>
+                <repository>
+                    <id>cloudsoft-deploy-cloudfront-origin-releases</id>
+                    <name>Cloudsoft Release Filesystem repo (used as origin for cloudfront)</name>
+                    <url>scpexe://root@developers-origin.cloudsoftcorp.com/var/www/developers/maven/releases/</url>
+                </repository>
+                <snapshotRepository>
+                    <id>cloudsoft-deploy-cloudfront-origin-snapshots</id>
+                    <name>Cloudsoft Snapshot Filesystem repo (used as origin for cloudfront)</name>
+                    <url>scpexe://root@developers-origin.cloudsoftcorp.com/var/www/developers/maven/snapshots/</url>
+                </snapshotRepository>
+            </distributionManagement>
+        </profile>
+        <profile>
+            <id>cloudsoft-artifactory-repo</id>
+            <activation> <property><name>camp.deployTo</name><value>cloudsoftArtifactory</value></property> </activation>
+            <distributionManagement>
+                <repository>
+                    <id>cloudsoft-deploy-artifactory-release</id>
+                    <name>Cloudsoft Artifactory libs-release-local repo</name>
+                    <url>http://ccweb.cloudsoftcorp.com/maven/libs-release-local/</url>
+                </repository>
+                <snapshotRepository>
+                    <id>cloudsoft-deploy-artifactory-snapshot</id>
+                    <name>Cloudsoft Artifactory libs-snapshot-local repo</name>
+                    <url>http://ccweb.cloudsoftcorp.com/maven/libs-snapshot-local/</url>
+                </snapshotRepository>
+            </distributionManagement>
+        </profile>
+        <profile>
+            <id>sonatype-nexus-repo</id>
+            <activation> <property><name>camp.deployTo</name><value>sonatype</value></property> </activation>
+            <distributionManagement>
+                <repository>
+                    <id>sonatype-nexus-staging</id>
+                    <name>Nexus Release Repository</name>
+                    <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
+                </repository>
+                <snapshotRepository>
+                    <id>sonatype-nexus-snapshots</id>
+                    <name>Sonatype Nexus Snapshots</name>
+                    <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
+                </snapshotRepository>
+            </distributionManagement>
+        </profile>
+    </profiles>
+
+</project>


[11/45] git commit: Fix infinite recursion in Osgis.getBundle

Posted by he...@apache.org.
Fix infinite recursion in Osgis.getBundle


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

Branch: refs/heads/master
Commit: b0bd80894e1b4cc93821361abeec5d6aaf3e70fd
Parents: b6d2364
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Mon Jun 30 12:54:44 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Tue Jul 1 13:37:37 2014 +0100

----------------------------------------------------------------------
 .../src/main/java/brooklyn/util/osgi/Osgis.java | 31 +++++++++++++-------
 1 file changed, 21 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b0bd8089/core/src/main/java/brooklyn/util/osgi/Osgis.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/osgi/Osgis.java b/core/src/main/java/brooklyn/util/osgi/Osgis.java
index 5edca46..e6aff48 100644
--- a/core/src/main/java/brooklyn/util/osgi/Osgis.java
+++ b/core/src/main/java/brooklyn/util/osgi/Osgis.java
@@ -23,6 +23,7 @@ import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.guava.Maybe;
 
 import com.google.common.annotations.Beta;
+import com.google.common.base.Joiner;
 import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 
@@ -50,19 +51,24 @@ public class Osgis {
     public static List<Bundle> getBundlesByName(Framework framework, String symbolicName) {
         return getBundlesByName(framework, symbolicName, Predicates.<Version>alwaysTrue());
     }
-    
+
+    /**
+     * Tries to find a bundle in the given framework with name matching either `name' or `name:version'.
+     */
     public static Maybe<Bundle> getBundle(Framework framework, String symbolicNameOptionallyWithVersion) {
         String[] parts = symbolicNameOptionallyWithVersion.split(":");
-        List<Bundle> matches;
-        if (parts.length==2) {
-            return getBundle(framework, symbolicNameOptionallyWithVersion);
-        } else if (parts.length==1) {
-            matches = getBundlesByName(framework, symbolicNameOptionallyWithVersion);
-            if (matches.isEmpty()) return Maybe.absent("no bundles matching "+symbolicNameOptionallyWithVersion);
-            return Maybe.of(matches.iterator().next());
+        Maybe<Bundle> result = Maybe.absent("No bundles matching "+symbolicNameOptionallyWithVersion);
+        if (parts.length == 2) {
+            result = getBundle(framework, parts[0], parts[1]);
+        } else if (parts.length == 1) {
+            List<Bundle> matches = getBundlesByName(framework, symbolicNameOptionallyWithVersion);
+            if (!matches.isEmpty()) {
+                result = Maybe.of(matches.iterator().next());
+            }
         } else {
             throw new IllegalArgumentException("Cannot parse symbolic-name:version string '"+symbolicNameOptionallyWithVersion+"'");
         }
+        return result;
     }
     
     public static Maybe<Bundle> getBundle(Framework framework, String symbolicName, String version) {
@@ -70,8 +76,13 @@ public class Osgis {
     }
 
     public static Maybe<Bundle> getBundle(Framework framework, String symbolicName, Version version) {
-        List<Bundle> matches = getBundlesByName(framework, symbolicName, Predicates.<Version>equalTo(version));
-        if (matches.isEmpty()) return Maybe.absent("no bundles matching "+symbolicName+":"+version);
+        List<Bundle> matches = getBundlesByName(framework, symbolicName, Predicates.equalTo(version));
+        if (matches.isEmpty()) {
+            return Maybe.absent("No bundles matching name=" + symbolicName + " version=" + version);
+        } else if (matches.size() > 1) {
+            LOG.warn("More than one bundle in framework={} matched name={}, version={}! Returning first of matches={}",
+                    new Object[]{framework, symbolicName, version, Joiner.on(", ").join(matches)});
+        }
         return Maybe.of(matches.iterator().next());
     }
 


[21/45] git commit: BROOKLYN-13: Registers bundles when catalogue is loaded

Posted by he...@apache.org.
BROOKLYN-13: Registers bundles when catalogue is loaded

load() method added to CatalogDo to register bundles with management context.

BasicBrooklynCatalog altered to not auto-load in another thread because it caused
a deadlock (management context locked, claims lock for catalogDo.load. BBC
constructor runs task in thread that claims catalogDo.load lock, then tries to claim
management context lock when getting the OsgiManager)


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

Branch: refs/heads/master
Commit: 7fec791f01b0efc6f29d53550fb433d030fae34e
Parents: 3a2f680
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Wed Jul 2 12:10:11 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Wed Jul 2 12:10:11 2014 +0100

----------------------------------------------------------------------
 .../catalog/internal/BasicBrooklynCatalog.java  | 24 +++++-----
 .../catalog/internal/CatalogClasspathDo.java    | 48 +++++++++-----------
 .../brooklyn/catalog/internal/CatalogDo.java    | 26 ++++++++---
 .../internal/CatalogItemDtoAbstract.java        |  4 ++
 .../catalog/internal/CatalogLibrariesDo.java    | 35 ++++++++++++++
 .../catalog/internal/CatalogLibrariesDto.java   |  7 ++-
 .../brooklyn/management/ha/OsgiManager.java     | 10 ++--
 .../internal/AbstractManagementContext.java     |  2 +-
 .../internal/ManagementContextInternal.java     |  6 ++-
 .../src/main/java/brooklyn/util/osgi/Osgis.java | 15 ++++--
 10 files changed, 120 insertions(+), 57 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7fec791f/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 4db16bd..7f5f305 100644
--- a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
@@ -41,17 +41,8 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     public BasicBrooklynCatalog(final ManagementContext mgmt, final CatalogDto dto) {
         this.mgmt = Preconditions.checkNotNull(mgmt, "managementContext");
         this.catalog = new CatalogDo(mgmt, dto);
-        
-        mgmt.getExecutionManager().submit(MutableMap.of("name", "loading catalog"), new Runnable() {
-            public void run() {
-                log.debug("Loading catalog for "+mgmt);
-                catalog.load(mgmt, null);
-                if (log.isDebugEnabled())
-                    log.debug("Loaded catalog for "+mgmt+": "+catalog+"; search classpath is "+catalog.getRootClassLoader());
-            }
-        });
     }
-    
+
     public boolean blockIfNotLoaded(Duration timeout) {
         try {
             return getCatalog().blockIfNotLoaded(timeout);
@@ -89,7 +80,18 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     public ClassLoader getRootClassLoader() {
         return catalog.getRootClassLoader();
     }
-    
+
+    /**
+     * Loads this catalog
+     */
+    public void load() {
+        log.debug("Loading catalog for " + mgmt);
+        getCatalog().load(mgmt, null);
+        if (log.isDebugEnabled()) {
+            log.debug("Loaded catalog for " + mgmt + ": " + catalog + "; search classpath is " + catalog.getRootClassLoader());
+        }
+    }
+
     @SuppressWarnings("unchecked")
     @Override
     public <T> Class<? extends T> loadClass(CatalogItem<T> item) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7fec791f/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
index ffe6e9c..de5a7fb 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
@@ -87,10 +87,11 @@ public class CatalogClasspathDo {
     /** causes all scanning-based classpaths to scan the classpaths
     * (but does _not_ load all JARs) */
     synchronized void load() {
-        if (classpath==null) return;
+        if (classpath == null || isLoaded) return;
 
-        if (classpath.getEntries()==null) urls = new URL[0];
-        else {
+        if (classpath.getEntries() == null) {
+            urls = new URL[0];
+        } else {
             urls = new URL[classpath.getEntries().size()];
             for (int i=0; i<urls.length; i++) {
                 try {
@@ -114,34 +115,29 @@ public class CatalogClasspathDo {
         ReflectionScanner scanner = null;
         if (!catalog.isLocal()) {
             log.warn("Scanning not supported for remote catalogs; ignoring scan request in "+catalog);
-        } else if (classpath.getEntries()==null || classpath.getEntries().isEmpty()) {
-            // no entries; check if we are local, and if so scan the default classpath
-            if (!catalog.isLocal()) {
-                log.warn("Scanning not supported for remote catalogs; ignoring scan request in "+catalog);
-            } else {                
-                // scan default classpath:
-                ClassLoader baseCL = null;
-                Iterable<URL> baseCP = null;
-                if (catalog.mgmt instanceof ManagementContextInternal) {
-                    baseCL = ((ManagementContextInternal)catalog.mgmt).getBaseClassLoader();
+        } else if (classpath.getEntries() == null || classpath.getEntries().isEmpty()) {
+            // scan default classpath:
+            ClassLoader baseCL = null;
+            Iterable<URL> baseCP = null;
+            if (catalog.mgmt instanceof ManagementContextInternal) {
+                baseCL = ((ManagementContextInternal)catalog.mgmt).getBaseClassLoader();
+                baseCP = ((ManagementContextInternal)catalog.mgmt).getBaseClassPathForScanning();
+            }
+            scanner = new ReflectionScanner(baseCP, prefix, baseCL, catalog.getRootClassLoader());
+            if (scanner.getSubTypesOf(Entity.class).isEmpty()) {
+                try {
+                    ((ManagementContextInternal)catalog.mgmt).setBaseClassPathForScanning(ClasspathHelper.forJavaClassPath());
+                    log.debug("Catalog scan of default classloader returned nothing; reverting to java.class.path");
                     baseCP = ((ManagementContextInternal)catalog.mgmt).getBaseClassPathForScanning();
-                }
-                scanner = new ReflectionScanner(baseCP, prefix, baseCL, catalog.getRootClassLoader());
-                if (scanner.getSubTypesOf(Entity.class).isEmpty()) {
-                    try {
-                        ((ManagementContextInternal)catalog.mgmt).setBaseClassPathForScanning(ClasspathHelper.forJavaClassPath());
-                        log.debug("Catalog scan of default classloader returned nothing; reverting to java.class.path");
-                        baseCP = ((ManagementContextInternal)catalog.mgmt).getBaseClassPathForScanning();
-                        scanner = new ReflectionScanner(baseCP, prefix, baseCL, catalog.getRootClassLoader());
-                    } catch (Exception e) {
-                        log.info("Catalog scan is empty, and unable to use java.class.path (base classpath is "+baseCP+")");
-                        Exceptions.propagateIfFatal(e);
-                    }
+                    scanner = new ReflectionScanner(baseCP, prefix, baseCL, catalog.getRootClassLoader());
+                } catch (Exception e) {
+                    log.info("Catalog scan is empty, and unable to use java.class.path (base classpath is "+baseCP+")");
+                    Exceptions.propagateIfFatal(e);
                 }
             }
         } else {
             // scan specified jars:
-            scanner = new ReflectionScanner(urls==null || urls.length==0 ? null : Arrays.asList(urls), prefix, getLocalClassLoader()); 
+            scanner = new ReflectionScanner(urls==null || urls.length==0 ? null : Arrays.asList(urls), prefix, getLocalClassLoader());
         }
         
         if (scanner!=null) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7fec791f/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
index c478e59..b8759a4 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
@@ -5,7 +5,6 @@ import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.TimeoutException;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -20,6 +19,7 @@ import brooklyn.util.time.CountdownTimer;
 import brooklyn.util.time.Duration;
 
 import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
 
 public class CatalogDo {
 
@@ -61,7 +61,7 @@ public class CatalogDo {
         getCache();
         return this;
     }
-    
+
     protected synchronized void loadThisCatalog(ManagementContext mgmt, CatalogDo parent) {
         if (isLoaded()) return;
         if (this.parent!=null && !this.parent.equals(parent))
@@ -70,8 +70,17 @@ public class CatalogDo {
             log.warn("Catalog "+this+" being initialised with different mgmt "+mgmt+" when already managed by "+this.mgmt, new Throwable("source of reparented "+this));
         this.parent = parent;
         this.mgmt = mgmt;
+        dto.populateFromUrl();
+        loadCatalogClasspath();
+        loadCatalogItems();
+        isLoaded = true;
+        synchronized (this) {
+            notifyAll();
+        }
+    }
+
+    private void loadCatalogClasspath() {
         try {
-            dto.populateFromUrl();
             classpath = new CatalogClasspathDo(this);
             classpath.load();
         } catch (Exception e) {
@@ -79,9 +88,14 @@ public class CatalogDo {
             log.error("Unable to load catalog "+this+" (ignoring): "+e);
             log.info("Trace for failure to load "+this+": "+e, e);
         }
-        isLoaded = true;
-        synchronized (this) {
-            notifyAll();
+    }
+
+    private void loadCatalogItems() {
+        List<CatalogLibrariesDo> loadedLibraries = Lists.newLinkedList();
+        for (CatalogItemDtoAbstract entry : dto.entries) {
+            CatalogLibrariesDo library = new CatalogLibrariesDo(entry.getLibrariesDto());
+            library.load(mgmt);
+            loadedLibraries.add(library);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7fec791f/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
index dcee2fa..d834911 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
@@ -42,6 +42,10 @@ public abstract class CatalogItemDtoAbstract<T> implements CatalogItem<T> {
     @Nonnull
     @Override
     public CatalogItemLibraries getLibraries() {
+        return getLibrariesDto();
+    }
+
+    public CatalogLibrariesDto getLibrariesDto() {
         return libraries;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7fec791f/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java
index 04a8f80..86295a1 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java
@@ -2,14 +2,27 @@ package brooklyn.catalog.internal;
 
 import java.util.List;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Joiner;
 import com.google.common.base.Preconditions;
+import com.google.common.base.Stopwatch;
 
 import brooklyn.catalog.CatalogItem;
+import brooklyn.management.ManagementContext;
+import brooklyn.management.ha.OsgiManager;
+import brooklyn.management.internal.ManagementContextInternal;
+import brooklyn.util.guava.Maybe;
+import brooklyn.util.text.Strings;
+import brooklyn.util.time.Time;
 
 public class CatalogLibrariesDo implements CatalogItem.CatalogItemLibraries {
 
+    private static final Logger LOG = LoggerFactory.getLogger(CatalogLibrariesDo.class);
     private final CatalogLibrariesDto librariesDto;
 
+
     public CatalogLibrariesDo(CatalogLibrariesDto librariesDto) {
         this.librariesDto = Preconditions.checkNotNull(librariesDto, "librariesDto");
     }
@@ -19,4 +32,26 @@ public class CatalogLibrariesDo implements CatalogItem.CatalogItemLibraries {
         return librariesDto.getBundles();
     }
 
+    /**
+     * Registers all bundles with the management context's OSGi framework.
+     */
+    void load(ManagementContext managementContext) {
+        ManagementContextInternal mgmt = (ManagementContextInternal) managementContext;
+        Maybe<OsgiManager> osgi = mgmt.getOsgiManager();
+        List<String> bundles = getBundles();
+        if (osgi.isAbsent()) {
+            LOG.warn("{} not loading bundles in {} because osgi manager is unavailable. Bundles: {}",
+                    new Object[]{this, managementContext, Joiner.on(", ").join(bundles)});
+            return;
+        } else if (LOG.isDebugEnabled()) {
+            LOG.debug("{} loading bundles in {}: {}",
+                    new Object[]{this, managementContext, Joiner.on(", ").join(bundles)});
+        }
+        Stopwatch timer = Stopwatch.createStarted();
+        for (String bundleUrl : bundles) {
+            osgi.get().registerBundle(bundleUrl);
+        }
+        LOG.debug("Catalog registered {} bundles in {}", bundles.size(), Time.makeTimeStringRounded(timer));
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7fec791f/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
index 2a49cfd..3c05387 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
@@ -3,18 +3,21 @@ package brooklyn.catalog.internal;
 import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
 
+import com.google.common.collect.ImmutableList;
+
 import brooklyn.catalog.CatalogItem;
 
 public class CatalogLibrariesDto implements CatalogItem.CatalogItemLibraries {
 
-    List<String> bundles = new CopyOnWriteArrayList<String>();
+    private List<String> bundles = new CopyOnWriteArrayList<String>();
 
     public void addBundle(String url) {
         bundles.add(url);
     }
 
+    /** @return An immutable copy of the bundle URLs referenced by this object */
     public List<String> getBundles() {
-        return bundles;
+        return ImmutableList.copyOf(bundles);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7fec791f/core/src/main/java/brooklyn/management/ha/OsgiManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/ha/OsgiManager.java b/core/src/main/java/brooklyn/management/ha/OsgiManager.java
index d519af5..a968660 100644
--- a/core/src/main/java/brooklyn/management/ha/OsgiManager.java
+++ b/core/src/main/java/brooklyn/management/ha/OsgiManager.java
@@ -49,12 +49,14 @@ public class OsgiManager {
         framework = null;
     }
 
-    // TODO: throws BundleException appropriate?
-    public void registerBundle(String bundleUrl) throws BundleException {
-        Osgis.install(framework, bundleUrl);
+    public void registerBundle(String bundleUrl) {
+        try {
+            Osgis.install(framework, bundleUrl);
+        } catch (BundleException e) {
+            throw Throwables.propagate(e);
+        }
     }
 
-    // TODO: Handle .get failing
     public <T> Maybe<Class<T>> tryResolveClass(String bundleUrl, String type) {
         try {
             Maybe<Bundle> bundle = Osgis.getBundle(framework, bundleUrl);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7fec791f/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java b/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
index bb9db2e..ae94534 100644
--- a/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
+++ b/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
@@ -334,7 +334,7 @@ public abstract class AbstractManagementContext implements ManagementContextInte
             if (log.isDebugEnabled())
                 log.debug("Loaded default (local classpath) catalog: "+catalog);
         }
-        catalog.getCatalog().load(this, null);
+        catalog.load();
         
         this.catalog = catalog;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7fec791f/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java b/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java
index 4707a7f..64c5b5e 100644
--- a/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java
+++ b/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java
@@ -60,8 +60,10 @@ public interface ManagementContextInternal extends ManagementContext {
 
     UsageManager getUsageManager();
     
-    /** returns OSGi manager, if available; may be absent if OSGi not supported, e.g. in test contexts
-     * (but major contexts will support this) */
+    /**
+     * @return The OSGi manager, if available; may be absent if OSGi is not supported,
+     * e.g. in test contexts (but will be supported in all major contexts).
+     */
     Maybe<OsgiManager> getOsgiManager();
 
     InternalEntityFactory getEntityFactory();

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7fec791f/core/src/main/java/brooklyn/util/osgi/Osgis.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/osgi/Osgis.java b/core/src/main/java/brooklyn/util/osgi/Osgis.java
index 4c6e351..05fac8e 100644
--- a/core/src/main/java/brooklyn/util/osgi/Osgis.java
+++ b/core/src/main/java/brooklyn/util/osgi/Osgis.java
@@ -91,7 +91,7 @@ public class Osgis {
     
     /*
      * loading framework factory and starting framework based on:
-     * http://felix.apache.org/documentation/subprojects/apache-felix-framework/apache-felix-framework-launching-and-embedding.html :
+     * http://felix.apache.org/documentation/subprojects/apache-felix-framework/apache-felix-framework-launching-and-embedding.html
      */
     
     public static FrameworkFactory newFrameworkFactory() {
@@ -138,13 +138,18 @@ public class Osgis {
         return framework;
     }
 
-    /** install a bundle from the given URL, doing a check if already installed, and
-     * using the {@link ResourceUtils} loader for this project (brooklyn core) */
+    /**
+     * Installs a bundle from the given URL, doing a check if already installed, and
+     * using the {@link ResourceUtils} loader for this project (brooklyn core)
+     */
     public static Bundle install(Framework framework, String url) throws BundleException {
         Bundle bundle = framework.getBundleContext().getBundle(url);
-        if (bundle != null) return bundle;
-        
+        if (bundle != null) {
+            return bundle;
+        }
+
         // use our URL resolution so we get classpath items
+        LOG.debug("Installing bundle into {} from url: {}", framework, url);
         InputStream stream = ResourceUtils.create(Osgis.class).getResourceFromUrl(url);
         return framework.getBundleContext().installBundle(url, stream);
     }


[40/45] git commit: Sample OSGi bundle defining empty entity and application.

Posted by he...@apache.org.
Sample OSGi bundle defining empty entity and application.


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

Branch: refs/heads/master
Commit: b7922769e0cb66803dd8ebb0a33803f74848b62b
Parents: 343fe33
Author: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Authored: Thu Jul 3 19:34:47 2014 +0300
Committer: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Committed: Thu Jul 3 19:34:47 2014 +0300

----------------------------------------------------------------------
 .../osgi/brooklyn-tests-osgi-entities-0.1.0.jar     | Bin 0 -> 4810 bytes
 1 file changed, 0 insertions(+), 0 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b7922769/core/src/test/resources/brooklyn/osgi/brooklyn-tests-osgi-entities-0.1.0.jar
----------------------------------------------------------------------
diff --git a/core/src/test/resources/brooklyn/osgi/brooklyn-tests-osgi-entities-0.1.0.jar b/core/src/test/resources/brooklyn/osgi/brooklyn-tests-osgi-entities-0.1.0.jar
new file mode 100644
index 0000000..82d4f2e
Binary files /dev/null and b/core/src/test/resources/brooklyn/osgi/brooklyn-tests-osgi-entities-0.1.0.jar differ


[34/45] git commit: address @aledsage's code review comments, and fix some failing tests (libraries sometimes null, and name not taken from template when app is promoted)

Posted by he...@apache.org.
address @aledsage's code review comments, and fix some failing tests (libraries sometimes null, and name not taken from template when app is promoted)


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

Branch: refs/heads/master
Commit: e96af92dc69e7dd97d3187d3c296290da9326d58
Parents: 13aa4af
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Jul 3 16:08:48 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu Jul 3 16:08:48 2014 +0100

----------------------------------------------------------------------
 .../main/java/brooklyn/catalog/CatalogItem.java |  6 ++-
 .../catalog/internal/BasicBrooklynCatalog.java  |  2 +-
 .../catalog/internal/CatalogItemDo.java         |  6 ++-
 .../internal/CatalogItemDtoAbstract.java        | 53 +-----------------
 .../brooklyn/catalog/internal/CatalogItems.java | 56 ++++++++++++++++++++
 .../catalog/internal/CatalogLibrariesDto.java   |  2 +-
 .../brooklyn/camp/lite/CampYamlLiteTest.java    |  2 +-
 .../catalog/internal/CatalogDtoTest.java        |  6 +--
 .../BrooklynAssemblyTemplateInstantiator.java   | 44 +++++++--------
 .../brooklyn/launcher/BrooklynLauncher.java     |  2 -
 .../rest/transform/CatalogTransformer.java      |  4 +-
 .../rest/resources/CatalogResourceTest.java     |  2 +-
 12 files changed, 95 insertions(+), 90 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e96af92d/api/src/main/java/brooklyn/catalog/CatalogItem.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/catalog/CatalogItem.java b/api/src/main/java/brooklyn/catalog/CatalogItem.java
index 7cfbdd6..ebcdae8 100644
--- a/api/src/main/java/brooklyn/catalog/CatalogItem.java
+++ b/api/src/main/java/brooklyn/catalog/CatalogItem.java
@@ -5,6 +5,9 @@ import java.util.List;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
+import com.google.common.annotations.Beta;
+
+@Beta
 public interface CatalogItem<T,SpecT> {
     
     public static enum CatalogItemType {
@@ -24,7 +27,8 @@ public interface CatalogItem<T,SpecT> {
     /** the explicit ID of this item, or the type if not supplied */
     public String getId();
     
-    /** the type name registered in the catalog for this item */ 
+    /** the type name registered in the catalog for this item */
+    @Nonnull
     public String getRegisteredTypeName();
     
     /** the underlying java type of the item represented, or null if not known (e.g. if it comes from yaml) */

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e96af92d/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 f4f0150..2f45bb7 100644
--- a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
@@ -208,7 +208,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         // TODO applications / templates
         // TODO long-term support policies etc
         
-        return CatalogItemDtoAbstract.newEntityFromPlan(name, libraries, plan, yaml);
+        return CatalogItems.newEntityFromPlan(name, libraries, plan, yaml);
     }
 
     private DeploymentPlan makePlanFromYaml(String yaml) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e96af92d/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
index 65133fe..6939a55 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
@@ -75,7 +75,7 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT> {
         return itemDto.getVersion();
     }
 
-    @Nonnull
+    @Nonnull  // but it is still null sometimes, see in CatalogDo.loadJavaClass
     @Override
     public CatalogItemLibraries getLibraries() {
         return itemDto.getLibraries();
@@ -97,7 +97,9 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT> {
 
             if (mgmt!=null) {
                 Maybe<OsgiManager> osgi = ((ManagementContextInternal)mgmt).getOsgiManager();
-                if (osgi.isPresent()) {
+                if (osgi.isPresent() && getLibraries()!=null) {
+                    // TODO getLibraries() should never be null but sometimes it is still
+                    // e.g. run CatalogResourceTest without the above check
                     List<String> bundles = getLibraries().getBundles();
                     if (bundles!=null && !bundles.isEmpty()) {
                         clazz = osgi.get().tryResolveClass(getJavaType(), bundles);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e96af92d/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
index b9b633d..21f0091 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
@@ -1,8 +1,7 @@
 package brooklyn.catalog.internal;
 
-import io.brooklyn.camp.spi.pdp.DeploymentPlan;
-
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 import brooklyn.catalog.CatalogItem;
 
@@ -70,59 +69,11 @@ public abstract class CatalogItemDtoAbstract<T,SpecT> implements CatalogItem<T,S
         return libraries;
     }
 
-    @Override
+    @Nullable @Override
     public String getPlanYaml() {
         return planYaml;
     }
 
-    public static CatalogTemplateItemDto newTemplateFromJava(String javaType, String name) {
-        return newTemplateFromJava(null, javaType, name, null);
-    }
-    public static CatalogTemplateItemDto newTemplateFromJava(String id, String javaType, String name, String description) {
-        return newTemplateFromJava(id, javaType, name, description, null);
-    }
-    public static CatalogTemplateItemDto newTemplateFromJava(String id, String javaType, String name, String description, CatalogLibrariesDto libraries) {
-        return set(new CatalogTemplateItemDto(), id, javaType, javaType, name, description, libraries);
-    }
-
-    public static CatalogEntityItemDto newEntityFromPlan(String registeredTypeName, CatalogLibrariesDto libraries, DeploymentPlan plan, String underlyingPlanYaml) {
-        CatalogEntityItemDto target = set(new CatalogEntityItemDto(), null, registeredTypeName, null, plan.getName(), plan.getDescription(), libraries);
-        target.planYaml = underlyingPlanYaml;
-        return target;
-    }
-    
-    public static CatalogEntityItemDto newEntityFromJava(String javaType, String name) {
-        return newEntityFromJava(null, javaType, name, null);
-    }
-    public static CatalogEntityItemDto newEntityFromJava(String id, String javaType, String name, String description) {
-        return newEntityFromJava(id, javaType, name, description, null);
-    }
-    public static CatalogEntityItemDto newEntityFromJava(String id, String javaType, String name, String description, CatalogLibrariesDto libraries) {
-        return set(new CatalogEntityItemDto(), id, javaType, javaType, name, description, libraries);
-    }
-
-    public static CatalogPolicyItemDto newPolicyFromJava(String javaType, String name) {
-        return newPolicyFromJava(null, javaType, name, null);
-    }
-    public static CatalogPolicyItemDto newPolicyFromJava(String id, String javaType, String name, String description) {
-        return newPolicyFromJava(id, javaType, name, description, null);
-    }
-    public static CatalogPolicyItemDto newPolicyFromJava(String id, String javaType, String name, String description, CatalogLibrariesDto libraries) {
-        return set(new CatalogPolicyItemDto(), id, javaType, javaType, name, description, libraries);
-    }
-
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    private static <T extends CatalogItemDtoAbstract> T set(T target, String id, String registeredType, String javaType, String name,
-            String description, CatalogLibrariesDto libraries) {
-        target.id = id;
-        target.registeredType = registeredType;
-        target.javaType = javaType;
-        target.name = name;
-        target.description = description;
-        target.libraries = libraries != null ? libraries : new CatalogLibrariesDto();
-        return target;
-    }
-
     @Override
     public String toString() {
         return getClass().getSimpleName()+"["+getId()+"/"+getName()+"]";

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e96af92d/core/src/main/java/brooklyn/catalog/internal/CatalogItems.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItems.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItems.java
new file mode 100644
index 0000000..18fc571
--- /dev/null
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItems.java
@@ -0,0 +1,56 @@
+package brooklyn.catalog.internal;
+
+import io.brooklyn.camp.spi.pdp.DeploymentPlan;
+
+/** Deliberately package-private. Only for internal use. */
+class CatalogItems {
+
+    public static CatalogTemplateItemDto newTemplateFromJava(String javaType, String name) {
+        return newTemplateFromJava(null, javaType, name, null);
+    }
+    public static CatalogTemplateItemDto newTemplateFromJava(String id, String javaType, String name, String description) {
+        return newTemplateFromJava(id, javaType, name, description, null);
+    }
+    public static CatalogTemplateItemDto newTemplateFromJava(String id, String javaType, String name, String description, CatalogLibrariesDto libraries) {
+        return set(new CatalogTemplateItemDto(), id, javaType, javaType, name, description, libraries);
+    }
+
+    public static CatalogEntityItemDto newEntityFromPlan(String registeredTypeName, CatalogLibrariesDto libraries, DeploymentPlan plan, String underlyingPlanYaml) {
+        CatalogEntityItemDto target = set(new CatalogEntityItemDto(), null, registeredTypeName, null, plan.getName(), plan.getDescription(), libraries);
+        target.planYaml = underlyingPlanYaml;
+        return target;
+    }
+    
+    public static CatalogEntityItemDto newEntityFromJava(String javaType, String name) {
+        return newEntityFromJava(null, javaType, name, null);
+    }
+    public static CatalogEntityItemDto newEntityFromJava(String id, String javaType, String name, String description) {
+        return newEntityFromJava(id, javaType, name, description, null);
+    }
+    public static CatalogEntityItemDto newEntityFromJava(String id, String javaType, String name, String description, CatalogLibrariesDto libraries) {
+        return set(new CatalogEntityItemDto(), id, javaType, javaType, name, description, libraries);
+    }
+
+    public static CatalogPolicyItemDto newPolicyFromJava(String javaType, String name) {
+        return newPolicyFromJava(null, javaType, name, null);
+    }
+    public static CatalogPolicyItemDto newPolicyFromJava(String id, String javaType, String name, String description) {
+        return newPolicyFromJava(id, javaType, name, description, null);
+    }
+    public static CatalogPolicyItemDto newPolicyFromJava(String id, String javaType, String name, String description, CatalogLibrariesDto libraries) {
+        return set(new CatalogPolicyItemDto(), id, javaType, javaType, name, description, libraries);
+    }
+ 
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    private static <T extends CatalogItemDtoAbstract> T set(T target, String id, String registeredType, String javaType, String name,
+            String description, CatalogLibrariesDto libraries) {
+        target.id = id;
+        target.registeredType = registeredType;
+        target.javaType = javaType;
+        target.name = name;
+        target.description = description;
+        target.libraries = libraries != null ? libraries : new CatalogLibrariesDto();
+        return target;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e96af92d/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
index a408921..4df1333 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
@@ -14,7 +14,7 @@ public class CatalogLibrariesDto implements CatalogItem.CatalogItemLibraries {
     private List<String> bundles = new CopyOnWriteArrayList<String>();
 
     public void addBundle(String url) {
-        Preconditions.checkNotNull(url, "Cannot add a bundle to a deserialized DTO");
+        Preconditions.checkNotNull(bundles, "Cannot add a bundle to a deserialized DTO");
         bundles.add( Preconditions.checkNotNull(url) );
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e96af92d/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java b/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
index 9bbadf7..c1bfefc 100644
--- a/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
+++ b/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
@@ -78,7 +78,7 @@ public class CampYamlLiteTest {
         Assert.assertEquals( map.get("desc"), MockWebPlatform.APPSERVER.getDescription() );
     }
 
-    @Test(groups="WIP")
+    @Test
     public void testYamlServiceForCatalog() {
         MockWebPlatform.populate(platform, TestAppAssemblyInstantiator.class);
         

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e96af92d/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java b/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
index 1989cb2..88bb020 100644
--- a/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
+++ b/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
@@ -71,9 +71,9 @@ public class CatalogDtoTest {
         CatalogDo testEntitiesJavaCatalog = new CatalogDo(CatalogDto.newNamedInstance("Test Entities from Java", null));
         testEntitiesJavaCatalog.setClasspathScanForEntities(CatalogScanningModes.NONE);
         testEntitiesJavaCatalog.addToClasspath(MavenRetriever.localUrl(BrooklynMavenArtifacts.artifact("", "brooklyn-core", "jar", "tests")));
-        testEntitiesJavaCatalog.addEntry(CatalogItemDtoAbstract.newTemplateFromJava(
+        testEntitiesJavaCatalog.addEntry(CatalogItems.newTemplateFromJava(
                 TestApplication.class.getCanonicalName(), "Test App from JAR"));
-        testEntitiesJavaCatalog.addEntry(CatalogItemDtoAbstract.newEntityFromJava(
+        testEntitiesJavaCatalog.addEntry(CatalogItems.newEntityFromJava(
                 TestEntity.class.getCanonicalName(), "Test Entity from JAR"));
         root.addCatalog(testEntitiesJavaCatalog.dto);
 
@@ -85,7 +85,7 @@ public class CatalogDtoTest {
         CatalogDo osgiCatalog = new CatalogDo(CatalogDto.newNamedInstance("Test Entities from OSGi",
                 "A catalog whose entries define their libraries as a list of OSGi bundles"));
         osgiCatalog.setClasspathScanForEntities(CatalogScanningModes.NONE);
-        CatalogEntityItemDto osgiEntity = CatalogItemDtoAbstract.newEntityFromJava(TestEntity.class.getCanonicalName(), "Test Entity from OSGi");
+        CatalogEntityItemDto osgiEntity = CatalogItems.newEntityFromJava(TestEntity.class.getCanonicalName(), "Test Entity from OSGi");
         // NB: this is not actually an OSGi bundle, but it's okay as we don't instantiate the bundles ahead of time (currently)
         osgiEntity.libraries.addBundle(MavenRetriever.localUrl(BrooklynMavenArtifacts.artifact("", "brooklyn-core", "jar", "tests")));
         testEntitiesJavaCatalog.addEntry(osgiEntity);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e96af92d/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 cc9dd44..7633fb7 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
@@ -221,30 +221,6 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
         final ManagementContext mgmt = getBrooklynManagementContext(platform);
 
         Map<Entity, EntitySpec<?>> allEntities = Maps.newLinkedHashMap();
-//<<<<<<< HEAD
-//        /* FIXME there is a subtlety here, and tests failing;
-//         * OT1H we might not want/need the wrapper application if we are creating a single one,   
-//         * but OTOH we might need a guarantee of an app at root, if we are creating certain nested entities
-//         * 
-//         * i (alex) think the solution is to use the new createSpec(...) and interrogate it
-//         * to see if we need the wrapper or not
-//         */
-//        buildEntities(template, rootEntities, allEntities, mgmt);
-//        
-//        EntitySpec<StartableApplication> appSpec;
-//        StartableApplication app;
-//        if(shouldWrapInApp(template, rootEntities)) {
-//            BrooklynComponentTemplateResolver appResolver = BrooklynComponentTemplateResolver.Factory.newInstance(mgmt, template);
-//            appSpec = appResolver.resolveSpec(StartableApplication.class, BasicApplicationImpl.class);
-//            app = appResolver.newEntity(appSpec);
-//            setEntitiesParent(rootEntities, app);
-//            allEntities.put(app, appSpec);
-//        } else {
-//            Entry<Entity, EntitySpec<?>> entry = rootEntities.entrySet().iterator().next();
-//            app = (StartableApplication)entry.getKey();
-//            appSpec = (EntitySpec<StartableApplication>)entry.getValue();
-//            applyLocations(mgmt, template, app);
-//=======
         StartableApplication rootApp = buildRootApp(template, platform, allEntities);
         initEntities(mgmt, allEntities);
         log.info("CAMP placing '{}' under management", allEntities.get(rootApp));
@@ -277,7 +253,16 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
         final ManagementContext mgmt = getBrooklynManagementContext(platform);
         
         ResolvableLink<PlatformComponentTemplate> promotedAppTemplate = template.getPlatformComponentTemplates().links().get(0);
-        StartableApplication app = (StartableApplication)buildEntity(null, promotedAppTemplate, allEntities, mgmt);
+        
+        PlatformComponentTemplate appChildComponentTemplate = promotedAppTemplate.resolve();
+        BrooklynComponentTemplateResolver entityResolver = BrooklynComponentTemplateResolver.Factory.newInstance(mgmt, appChildComponentTemplate);
+        EntitySpec<?> spec = buildEntitySpecNonHierarchical(null, appChildComponentTemplate, allEntities, mgmt, entityResolver);
+
+        // and this is needed in case 'name' was set at template level (eg ApplicationResourceTest.testDeployApplicationYaml)
+        if (spec.getDisplayName()==null && template.getName()!=null)
+            spec.displayName(template.getName());
+            
+        StartableApplication app = (StartableApplication) buildEntityHierarchical(spec, appChildComponentTemplate, allEntities, mgmt, entityResolver);
         
         // TODO i (alex) think we need this because locations defined at the root of the template could have been lost otherwise?
         applyLocations(mgmt, template, app);
@@ -296,10 +281,19 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
             Map<Entity, EntitySpec<?>> allEntities, ManagementContext mgmt) {
         PlatformComponentTemplate appChildComponentTemplate = ctl.resolve();
         BrooklynComponentTemplateResolver entityResolver = BrooklynComponentTemplateResolver.Factory.newInstance(mgmt, appChildComponentTemplate);
+        EntitySpec<?> spec = buildEntitySpecNonHierarchical(parent, appChildComponentTemplate, allEntities, mgmt, entityResolver);
+        return buildEntityHierarchical(spec, appChildComponentTemplate, allEntities, mgmt, entityResolver);
+    }
+    private EntitySpec<?> buildEntitySpecNonHierarchical(StartableApplication parent, PlatformComponentTemplate appChildComponentTemplate,
+            Map<Entity, EntitySpec<?>> allEntities, ManagementContext mgmt, BrooklynComponentTemplateResolver entityResolver) {
         EntitySpec<? extends Entity> spec = entityResolver.resolveSpec();
         if(parent != null) {
             spec.parent(parent);
         }
+        return spec;
+    }
+    private Entity buildEntityHierarchical(EntitySpec<?> spec, PlatformComponentTemplate appChildComponentTemplate,
+            Map<Entity, EntitySpec<?>> allEntities, ManagementContext mgmt, BrooklynComponentTemplateResolver entityResolver) {
         Entity entity = entityResolver.newEntity(spec);
         allEntities.put(entity, spec);
         buildEntityHierarchy(mgmt, allEntities, entity, entityResolver.getChildren(appChildComponentTemplate.getCustomAttributes()));

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e96af92d/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
index 7d94e9e..64ef089 100644
--- a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
+++ b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
@@ -32,7 +32,6 @@ import brooklyn.entity.Application;
 import brooklyn.entity.basic.ApplicationBuilder;
 import brooklyn.entity.basic.BrooklynShutdownHooks;
 import brooklyn.entity.basic.Entities;
-import brooklyn.entity.basic.EntityInternal;
 import brooklyn.entity.basic.StartableApplication;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.entity.rebind.PersistenceExceptionHandler;
@@ -645,7 +644,6 @@ public class BrooklynLauncher {
             throw Exceptions.propagate(e);
         }
         Application app = instantiator.create(at, campPlatform);
-//        ((EntityInternal)app).addLocations(XXX);
         return app;
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e96af92d/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 4d24974..76cc02a 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
@@ -50,7 +50,7 @@ public class CatalogTransformer {
 
         return new CatalogEntitySummary(item.getId(), item.getName(), 
             item.getRegisteredTypeName(), item.getJavaType(), 
-            item.getRegisteredTypeName()!=null ? item.getRegisteredTypeName() : item.getJavaType(),
+            item.getRegisteredTypeName(),
             item.getPlanYaml(),
                 item.getDescription(), tidyIconLink(b, item, item.getIconUrl()),
                 config, sensors, effectors,
@@ -60,7 +60,7 @@ public class CatalogTransformer {
     public static CatalogItemSummary catalogItemSummary(BrooklynRestResourceUtils b, CatalogItem<?,?> item) {
         return new CatalogItemSummary(item.getId(), item.getName(), 
                 item.getRegisteredTypeName(), item.getJavaType(), 
-                item.getRegisteredTypeName()!=null ? item.getRegisteredTypeName() : item.getJavaType(),
+                item.getRegisteredTypeName(),
                 item.getPlanYaml(),
                 item.getDescription(), tidyIconLink(b, item, item.getIconUrl()), makeLinks(item));
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e96af92d/usage/rest-server/src/test/java/brooklyn/rest/resources/CatalogResourceTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/brooklyn/rest/resources/CatalogResourceTest.java b/usage/rest-server/src/test/java/brooklyn/rest/resources/CatalogResourceTest.java
index 810e6e3..84e60f3 100644
--- a/usage/rest-server/src/test/java/brooklyn/rest/resources/CatalogResourceTest.java
+++ b/usage/rest-server/src/test/java/brooklyn/rest/resources/CatalogResourceTest.java
@@ -49,7 +49,7 @@ public class CatalogResourceTest extends BrooklynRestResourceTest {
     String registeredTypeName = "my.catalog.app.id";
     String yaml =
         "name: "+registeredTypeName+"\n"+
-        // TODO name above should be unnecessary when brooklyn.catalog below is working
+        // FIXME name above should be unnecessary when brooklyn.catalog below is working
         "brooklyn.catalog:\n"+
         "- id: " + registeredTypeName + "\n"+
         "- name: My Catalog App\n"+


[12/45] git commit: Adds context element to catalogue entries

Posted by he...@apache.org.
Adds context element to catalogue entries


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

Branch: refs/heads/master
Commit: b6d236493d7bdf01654c3ee9e44bcc80f0002208
Parents: 06c10c4
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Sat Jun 28 17:11:16 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Tue Jul 1 13:37:37 2014 +0100

----------------------------------------------------------------------
 .../main/java/brooklyn/catalog/CatalogItem.java | 11 ++++++--
 .../catalog/internal/CatalogContextDo.java      | 24 ++++++++++++++++
 .../catalog/internal/CatalogContextDto.java     | 20 ++++++++++++++
 .../catalog/internal/CatalogItemDo.java         |  7 ++++-
 .../internal/CatalogItemDtoAbstract.java        | 29 ++++++++++++++++----
 .../catalog/internal/CatalogXmlSerializer.java  | 13 +++++----
 .../catalog/internal/CatalogDtoTest.java        | 11 +++++++-
 7 files changed, 101 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b6d23649/api/src/main/java/brooklyn/catalog/CatalogItem.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/catalog/CatalogItem.java b/api/src/main/java/brooklyn/catalog/CatalogItem.java
index f0450d1..ab01496 100644
--- a/api/src/main/java/brooklyn/catalog/CatalogItem.java
+++ b/api/src/main/java/brooklyn/catalog/CatalogItem.java
@@ -1,11 +1,17 @@
 package brooklyn.catalog;
 
+import java.util.List;
+
 public interface CatalogItem<T> {
     
     public static enum CatalogItemType {
         TEMPLATE, ENTITY, POLICY, CONFIGURATION
     }
-    
+
+    public static interface CatalogItemContext {
+        List<String> getBundles();
+    }
+
     public CatalogItemType getCatalogItemType();
     public Class<T> getCatalogItemJavaType();
     
@@ -14,7 +20,8 @@ public interface CatalogItem<T> {
     public String getName();
     public String getDescription();
     public String getIconUrl();
-    
+    public CatalogItemContext getContext();
+
     public String toXmlString();
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b6d23649/core/src/main/java/brooklyn/catalog/internal/CatalogContextDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogContextDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogContextDo.java
new file mode 100644
index 0000000..6560b35
--- /dev/null
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogContextDo.java
@@ -0,0 +1,24 @@
+package brooklyn.catalog.internal;
+
+import java.util.List;
+
+import com.google.common.base.Preconditions;
+
+import brooklyn.catalog.CatalogItem;
+
+public class CatalogContextDo implements CatalogItem.CatalogItemContext {
+
+//    private final CatalogDo catalog;
+    private final CatalogContextDto contextDto;
+
+    public CatalogContextDo(/*CatalogDo catalog,*/ CatalogContextDto contextDto) {
+//        this.catalog = Preconditions.checkNotNull(catalog, "catalog");
+        this.contextDto = Preconditions.checkNotNull(contextDto, "contextDto");
+    }
+
+    @Override
+    public List<String> getBundles() {
+        return contextDto.getBundles();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b6d23649/core/src/main/java/brooklyn/catalog/internal/CatalogContextDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogContextDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogContextDto.java
new file mode 100644
index 0000000..ef4fefa
--- /dev/null
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogContextDto.java
@@ -0,0 +1,20 @@
+package brooklyn.catalog.internal;
+
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import brooklyn.catalog.CatalogItem;
+
+public class CatalogContextDto implements CatalogItem.CatalogItemContext {
+
+    List<String> bundles = new CopyOnWriteArrayList<String>();
+
+    public void addBundle(String url) {
+        bundles.add(url);
+    }
+
+    public List<String> getBundles() {
+        return bundles;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b6d23649/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
index 9b89722..d576c0a 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
@@ -55,7 +55,12 @@ public class CatalogItemDo<T> implements CatalogItem<T> {
     public String getIconUrl() {
         return itemDto.getIconUrl();
     }
-    
+
+    @Override
+    public CatalogItemContext getContext() {
+        return itemDto.getContext();
+    }
+
     public Class<T> getJavaClass() {
         if (javaClass==null) loadJavaClass();
         return javaClass;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b6d23649/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
index af74931..ad0fa71 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
@@ -1,5 +1,7 @@
 package brooklyn.catalog.internal;
 
+import javax.annotation.Nullable;
+
 import brooklyn.catalog.CatalogItem;
 
 public abstract class CatalogItemDtoAbstract<T> implements CatalogItem<T> {
@@ -9,6 +11,7 @@ public abstract class CatalogItemDtoAbstract<T> implements CatalogItem<T> {
     String name;
     String description;
     String iconUrl;
+    CatalogItemContext context;
     
     public String getId() {
         if (id!=null) return id;
@@ -30,34 +33,50 @@ public abstract class CatalogItemDtoAbstract<T> implements CatalogItem<T> {
     public String getIconUrl() {
         return iconUrl;
     }
-    
+
+    @Override
+    public CatalogItemContext getContext() {
+        return context;
+    }
+
     public static CatalogTemplateItemDto newTemplate(String type, String name) {
         return newTemplate(null, type, name, null);
     }
     public static CatalogTemplateItemDto newTemplate(String id, String type, String name, String description){
-        return set(new CatalogTemplateItemDto(), id, type, name, description);
+        return newTemplate(id, type, name, description, null);
+    }
+    public static CatalogTemplateItemDto newTemplate(String id, String type, String name, String description, CatalogContextDto context){
+        return set(new CatalogTemplateItemDto(), id, type, name, description, context);
     }
 
     public static CatalogEntityItemDto newEntity(String type, String name) {
         return newEntity(null, type, name, null);
     }
     public static CatalogEntityItemDto newEntity(String id, String type, String name, String description){
-        return set(new CatalogEntityItemDto(), id, type, name, description);
+        return newEntity(id, type, name, description, null);
+    }
+    public static CatalogEntityItemDto newEntity(String id, String type, String name, String description, CatalogContextDto context){
+        return set(new CatalogEntityItemDto(), id, type, name, description, context);
     }
 
     public static CatalogPolicyItemDto newPolicy(String type, String name) {
         return newPolicy(null, type, name, null);
     }
     public static CatalogPolicyItemDto newPolicy(String id, String type, String name, String description){
-        return set(new CatalogPolicyItemDto(), id, type, name, description);
+        return newPolicy(id, type, name, description, null);
+    }
+    public static CatalogPolicyItemDto newPolicy(String id, String type, String name, String description, CatalogContextDto context){
+        return set(new CatalogPolicyItemDto(), id, type, name, description, context);
     }
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
-    private static <T extends CatalogItemDtoAbstract> T set(T target, String id, String type, String name, String description) {
+    private static <T extends CatalogItemDtoAbstract> T set(T target, String id, String type, String name,
+            String description, CatalogContextDto context) {
         target.id = id;
         target.type = type;
         target.name = name;
         target.description = description;
+        target.context = context;
         return target;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b6d23649/core/src/main/java/brooklyn/catalog/internal/CatalogXmlSerializer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogXmlSerializer.java b/core/src/main/java/brooklyn/catalog/internal/CatalogXmlSerializer.java
index bf0ea96..9cdbffe 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogXmlSerializer.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogXmlSerializer.java
@@ -8,7 +8,7 @@ import brooklyn.util.xstream.EnumCaseForgivingSingleValueConverter;
 import brooklyn.util.xstream.XmlSerializer;
 
 public class CatalogXmlSerializer extends XmlSerializer<Object> {
-    
+
     public CatalogXmlSerializer() {
         xstream.aliasType("list", List.class);
         xstream.aliasType("map", Map.class);
@@ -21,17 +21,20 @@ public class CatalogXmlSerializer extends XmlSerializer<Object> {
         xstream.addImplicitCollection(CatalogDto.class, "entries", CatalogTemplateItemDto.class);
         xstream.addImplicitCollection(CatalogDto.class, "entries", CatalogEntityItemDto.class);
         xstream.addImplicitCollection(CatalogDto.class, "entries", CatalogPolicyItemDto.class);
-        
+
         xstream.aliasType("template", CatalogTemplateItemDto.class);
         xstream.aliasType("entity", CatalogEntityItemDto.class);
         xstream.aliasType("policy", CatalogPolicyItemDto.class);
-        
+
         xstream.useAttributeFor(CatalogItemDtoAbstract.class, "type");
         xstream.useAttributeFor(CatalogItemDtoAbstract.class, "name");
-        
+
         xstream.useAttributeFor(CatalogClasspathDto.class, "scan");
         xstream.addImplicitCollection(CatalogClasspathDto.class, "entries", "entry", String.class);
         xstream.registerConverter(new EnumCaseForgivingSingleValueConverter(CatalogScanningModes.class));
+
+        xstream.aliasType("context", CatalogContextDto.class);
+        xstream.addImplicitCollection(CatalogContextDto.class, "bundles", "bundle", String.class);
     }
-    
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b6d23649/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java b/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
index db94f46..c8e14ee 100644
--- a/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
+++ b/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
@@ -47,7 +47,7 @@ public class CatalogDtoTest {
     }
 
     protected void checkHadoopsExample(CatalogDto root) {
-        Assert.assertEquals(root.catalogs.size(), 4);
+        Assert.assertEquals(root.catalogs.size(), 5);
         CatalogDo loader = new CatalogDo(root).load(managementContext, null);
         
         CatalogItemDo<?> worker = loader.getCache().get("io.brooklyn.mapr.m3.WorkerNode");
@@ -83,6 +83,15 @@ public class CatalogDtoTest {
                 "RECOMMENDED: CDH Hadoop Application with Cloudera Manager"));
         root.addCatalog(cdhCatalog.dto);
 
+        CatalogDo osgiCatalog = new CatalogDo(CatalogDto.newNamedInstance("OSGi",
+                "A catalog whose entries define their context as a list of OSGi bundles"));
+        osgiCatalog.setClasspathScanForEntities(CatalogScanningModes.NONE);
+        CatalogContextDto m3Context = new CatalogContextDto();
+        m3Context.addBundle("file://~/.m2/repository/io/cloudsoft/brooklyn-mapr/1.0.0-SNAPSHOT/brooklyn-mapr.jar");
+        osgiCatalog.addEntry(CatalogItemDtoAbstract.newTemplate("M3App", "io.brooklyn.mapr.M3App", "M3 Application",
+                "Description", m3Context));
+        root.addCatalog(osgiCatalog.dto);
+
         root.addCatalog(CatalogDto.newLinkedInstance("http://cloudsoftcorp.com/amp-brooklyn-catalog.xml"));
         root.addCatalog(CatalogDto.newLinkedInstance("http://microsoot.com/oofice-catalog.xml"));
         return root.dto;


[18/45] git commit: BROOKLYN-13: Merge CatalogDto and CatalogDtoUtils

Posted by he...@apache.org.
BROOKLYN-13: Merge CatalogDto and CatalogDtoUtils

There aren't enough methods on the latter to justify the separate 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/3a2f680b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/3a2f680b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/3a2f680b

Branch: refs/heads/master
Commit: 3a2f680bddd97fb5786bca08975fbbbbe425d78f
Parents: 30093bb
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Tue Jul 1 16:06:12 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Tue Jul 1 16:06:12 2014 +0100

----------------------------------------------------------------------
 .../catalog/internal/BasicBrooklynCatalog.java  |  8 ++-
 .../catalog/internal/CatalogClasspathDo.java    |  1 -
 .../brooklyn/catalog/internal/CatalogDo.java    |  6 +-
 .../brooklyn/catalog/internal/CatalogDto.java   | 68 +++++++++++++++++---
 .../catalog/internal/CatalogDtoUtils.java       | 52 ---------------
 .../catalog/internal/CatalogItemDo.java         |  2 +-
 .../internal/AbstractManagementContext.java     |  8 +--
 7 files changed, 71 insertions(+), 74 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3a2f680b/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 d6b5ff0..4db16bd 100644
--- a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
@@ -33,7 +33,11 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     private final CatalogDo catalog;
     private volatile CatalogDo manualAdditionsCatalog;
     private volatile LoadedClassLoader manualAdditionsClasses;
-    
+
+    public BasicBrooklynCatalog(ManagementContext mgmt, String catalogUrl) {
+        this(mgmt, CatalogDto.newDtoFromUrl(catalogUrl));
+    }
+
     public BasicBrooklynCatalog(final ManagementContext mgmt, final CatalogDto dto) {
         this.mgmt = Preconditions.checkNotNull(mgmt, "managementContext");
         this.catalog = new CatalogDo(mgmt, dto);
@@ -90,7 +94,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     @Override
     public <T> Class<? extends T> loadClass(CatalogItem<T> item) {
         if (log.isDebugEnabled())
-            log.debug("Loading class for catalog item "+item);
+            log.debug("Loading class for catalog item " + item);
         Preconditions.checkNotNull(item);
         CatalogItemDo<?> loadedItem = getCatalogItemDo(item.getId());
         if (loadedItem==null) throw new NoSuchElementException("Unable to load '"+item.getId()+"' to instantiate it");

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3a2f680b/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
index 66a2bba..ffe6e9c 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
@@ -66,7 +66,6 @@ public class CatalogClasspathDo {
         TYPES
     }
     
-
     private static final Logger log = LoggerFactory.getLogger(CatalogClasspathDo.class);
     
     private final CatalogDo catalog;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3a2f680b/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
index 9573eb1..c478e59 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
@@ -66,19 +66,17 @@ public class CatalogDo {
         if (isLoaded()) return;
         if (this.parent!=null && !this.parent.equals(parent))
             log.warn("Catalog "+this+" being initialised with different parent "+parent+" when already parented by "+this.parent, new Throwable("source of reparented "+this));
-        this.parent = parent;
         if (this.mgmt!=null && !this.mgmt.equals(mgmt))
             log.warn("Catalog "+this+" being initialised with different mgmt "+mgmt+" when already managed by "+this.mgmt, new Throwable("source of reparented "+this));
+        this.parent = parent;
         this.mgmt = mgmt;
         try {
-            if (dto.url!=null)
-                CatalogDtoUtils.populateFromUrl(dto, dto.url);
+            dto.populateFromUrl();
             classpath = new CatalogClasspathDo(this);
             classpath.load();
         } catch (Exception e) {
             Exceptions.propagateIfFatal(e);
             log.error("Unable to load catalog "+this+" (ignoring): "+e);
-//            log.debug("Trace for failure to load "+this+": "+e, e);
             log.info("Trace for failure to load "+this+": "+e, e);
         }
         isLoaded = true;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3a2f680b/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java
index 7e7f33a..f222215 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java
@@ -1,9 +1,21 @@
 package brooklyn.catalog.internal;
 
+import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.util.List;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Objects;
+
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.exceptions.Exceptions;
+
 public class CatalogDto {
-    
+
+    private static final Logger LOG = LoggerFactory.getLogger(CatalogDto.class);
+
     String id;
     String url;
     String name;
@@ -15,6 +27,26 @@ public class CatalogDto {
     // in this class which does copy-on-write
     List<CatalogDto> catalogs = null;
 
+    public static CatalogDto newDefaultLocalScanningDto(CatalogClasspathDo.CatalogScanningModes scanMode) {
+        CatalogDo result = new CatalogDo(
+                CatalogDto.newNamedInstance("Local Scanned Catalog", "All annotated Brooklyn entities detected in the default classpath") );
+        result.setClasspathScanForEntities(scanMode);
+        return result.dto;
+    }
+
+    public static CatalogDto newDtoFromUrl(String url) {
+        if (LOG.isDebugEnabled()) LOG.debug("Retrieving catalog from: {}", url);
+        try {
+            InputStream source = ResourceUtils.create().getResourceFromUrl(url);
+            CatalogDto result = (CatalogDto) new CatalogXmlSerializer().deserialize(new InputStreamReader(source));
+            if (LOG.isDebugEnabled()) LOG.debug("Retrieved catalog from: {}", url);
+            return result;
+        } catch (Throwable t) {
+            LOG.debug("Unable to retrieve catalog from: " + url + " (" + t + ")");
+            throw Exceptions.propagate(t);
+        }
+    }
+
     public static CatalogDto newNamedInstance(String name, String description) {
         CatalogDto result = new CatalogDto();
         result.name = name;
@@ -28,15 +60,6 @@ public class CatalogDto {
         return result;
     }
 
-    @Override
-    public String toString() {
-        return getClass().getSimpleName()+"["+
-                (url!=null ? url+"; " : "")+
-                (name!=null ? name+":" : "")+
-                (id!=null ? id : "")+
-                "]";
-    }
-
     /**
      * @throws NullPointerException If source is null (and !skipNulls)
      */
@@ -54,4 +77,29 @@ public class CatalogDto {
         if (!skipNulls || source.entries != null) entries = source.entries;
     }
 
+    /**
+     * Populates this Dto by loading the catalog at its {@link #url}. Takes no action if url is null.
+     * Throws if there are any problems in retrieving or copying from url.
+     */
+    void populateFromUrl() {
+        if (url != null) {
+            CatalogDto remoteDto = newDtoFromUrl(url);
+            try {
+                copyFrom(remoteDto, true);
+            } catch (Exception e) {
+                Exceptions.propagate(e);
+            }
+        }
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this)
+                .omitNullValues()
+                .add("name", name)
+                .add("id", id)
+                .add("url", url)
+                .toString();
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3a2f680b/core/src/main/java/brooklyn/catalog/internal/CatalogDtoUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogDtoUtils.java b/core/src/main/java/brooklyn/catalog/internal/CatalogDtoUtils.java
deleted file mode 100644
index 86a499b..0000000
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogDtoUtils.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package brooklyn.catalog.internal;
-
-import java.io.InputStream;
-import java.io.InputStreamReader;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.exceptions.Exceptions;
-
-public class CatalogDtoUtils {
-
-    private static final Logger log = LoggerFactory.getLogger(CatalogDtoUtils.class);
-    
-    public static CatalogDto newDefaultLocalScanningDto(CatalogScanningModes scanMode) {
-        CatalogDo result = new CatalogDo(
-                CatalogDto.newNamedInstance("Local Scanned Catalog", "All annotated Brooklyn entities detected in the default classpath") );
-        result.setClasspathScanForEntities(scanMode);
-        return result.dto;
-    }
-
-    /** throws if there are any problems in retrieving or copying */
-    public static void populateFromUrl(CatalogDto dto, String url) {
-        CatalogDto remoteDto = newDtoFromUrl(url);
-        try {
-            copyDto(remoteDto, dto, true);
-        } catch (Exception e) {
-            Exceptions.propagate(e);
-        }
-    }
-
-    /** does a shallow copy.
-     * "skipNulls" means not to copy any fields from the source which are null */ 
-    static void copyDto(CatalogDto source, CatalogDto target, boolean skipNulls) throws IllegalArgumentException, IllegalAccessException {
-        target.copyFrom(source, skipNulls);
-    }
-
-    public static CatalogDto newDtoFromUrl(String url) {
-        if (log.isDebugEnabled()) log.debug("Retrieving catalog from: {}", url);
-        try {
-            InputStream source = ResourceUtils.create().getResourceFromUrl(url);
-            CatalogDto result = (CatalogDto) new CatalogXmlSerializer().deserialize(new InputStreamReader(source));
-            if (log.isDebugEnabled()) log.debug("Retrieved catalog from: {}", url);
-            return result;
-        } catch (Throwable t) {
-            log.debug("Unable to retrieve catalog from: "+url+" ("+t+")");
-            throw Exceptions.propagate(t);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3a2f680b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
index d857c45..edce2e7 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
@@ -24,7 +24,7 @@ public class CatalogItemDo<T> implements CatalogItem<T> {
     }
 
     @Override
-    public brooklyn.catalog.CatalogItem.CatalogItemType getCatalogItemType() {
+    public CatalogItemType getCatalogItemType() {
         return itemDto.getCatalogItemType();
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3a2f680b/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java b/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
index cd86bb8..bb9db2e 100644
--- a/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
+++ b/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
@@ -19,7 +19,7 @@ import org.slf4j.LoggerFactory;
 import brooklyn.catalog.BrooklynCatalog;
 import brooklyn.catalog.internal.BasicBrooklynCatalog;
 import brooklyn.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
-import brooklyn.catalog.internal.CatalogDtoUtils;
+import brooklyn.catalog.internal.CatalogDto;
 import brooklyn.config.BrooklynProperties;
 import brooklyn.config.StringConfigMap;
 import brooklyn.entity.Effector;
@@ -267,7 +267,7 @@ public abstract class AbstractManagementContext implements ManagementContextInte
      * Returns the actual task (if it is local) or a proxy task (if it is remote);
      * if management for the entity has not yet started this may start it.
      * 
-     * @deprecated since 0.6.0 use effectors (or support {@link #runAtEntity(Entity, Task)} if something else is needed);
+     * @deprecated since 0.6.0 use effectors (or support {@code runAtEntity(Entity, Task)} if something else is needed);
      * (Callable with Map flags is too open-ended, bothersome to support, and not used much) 
      */
     @Deprecated
@@ -311,7 +311,7 @@ public abstract class AbstractManagementContext implements ManagementContextInte
         
         try {
             if (!Strings.isEmpty(catalogUrl)) {
-                catalog = new BasicBrooklynCatalog(this, CatalogDtoUtils.newDtoFromUrl(catalogUrl));
+                catalog = new BasicBrooklynCatalog(this, catalogUrl);
                 if (log.isDebugEnabled())
                     log.debug("Loaded catalog from "+catalogUrl+": "+catalog);
             }
@@ -330,7 +330,7 @@ public abstract class AbstractManagementContext implements ManagementContextInte
         }
         if (catalog==null) {
             // retry, either an error, or was blank
-            catalog = new BasicBrooklynCatalog(this, CatalogDtoUtils.newDefaultLocalScanningDto(CatalogScanningModes.ANNOTATIONS));
+            catalog = new BasicBrooklynCatalog(this, CatalogDto.newDefaultLocalScanningDto(CatalogScanningModes.ANNOTATIONS));
             if (log.isDebugEnabled())
                 log.debug("Loaded default (local classpath) catalog: "+catalog);
         }


[27/45] git commit: allow access to CAMP from brooklyn catalog

Posted by he...@apache.org.
allow access to CAMP from brooklyn catalog


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

Branch: refs/heads/master
Commit: 5c3d32ce1f473341d30e3aedaec9c88d1b8f42f0
Parents: c664f5e
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Wed Jul 2 16:38:01 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Wed Jul 2 16:38:01 2014 +0100

----------------------------------------------------------------------
 .../catalog/internal/BasicBrooklynCatalog.java  | 25 ++++++++++++++++----
 .../brooklyn/config/BrooklynServerConfig.java   | 12 ++++++++++
 .../entity/basic/BrooklynConfigKeys.java        |  6 +++--
 .../camp/brooklyn/BrooklynCampConstants.java    |  5 ++--
 4 files changed, 39 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5c3d32ce/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 237b140..67cbbe1 100644
--- a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
@@ -1,5 +1,8 @@
 package brooklyn.catalog.internal;
 
+import io.brooklyn.camp.CampPlatform;
+import io.brooklyn.camp.spi.pdp.DeploymentPlan;
+
 import java.util.NoSuchElementException;
 
 import javax.annotation.Nullable;
@@ -10,11 +13,12 @@ import org.slf4j.LoggerFactory;
 import brooklyn.catalog.BrooklynCatalog;
 import brooklyn.catalog.CatalogItem;
 import brooklyn.catalog.CatalogPredicates;
+import brooklyn.config.BrooklynServerConfig;
 import brooklyn.management.ManagementContext;
-import brooklyn.util.collections.MutableMap;
 import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.javalang.AggregateClassLoader;
 import brooklyn.util.javalang.LoadedClassLoader;
+import brooklyn.util.stream.Streams;
 import brooklyn.util.time.Duration;
 import brooklyn.util.time.Time;
 
@@ -115,6 +119,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         return (Class<? extends T>) loadClass(resultI);
     }
 
+    @Deprecated
     private <T> CatalogItemDtoAbstract<T> getAbstractCatalogItem(CatalogItem<T> item) {
         while (item instanceof CatalogItemDo) item = ((CatalogItemDo<T>)item).itemDto;
         if (item==null) return null;
@@ -123,7 +128,19 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     }
 
     private <T> CatalogItemDtoAbstract<T> getAbstractCatalogItem(String yaml) {
-        // FIXME Need to parse yaml to extract CatalogItem info
+        CampPlatform camp = BrooklynServerConfig.getCampPlatform(mgmt).get();
+        
+        DeploymentPlan plan = camp.pdp().parseDeploymentPlan(Streams.newReaderWithContents(yaml));
+        
+        // TODO #2 parse brooklyn.catalog metadata, bundles etc.
+        // for now take the name from the plan or from a single service type therein
+        
+        // TODO #3 version info
+        
+        // TODO #1 build the catalog item from the plan (as CatalogItem<Entity> ?)
+//        plan.getName()
+        // TODO #2 then support instantiating from the item, replacing 
+        
         throw new UnsupportedOperationException();
     }
 
@@ -137,7 +154,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         return itemDto;
     }
 
-    @Override
+    @Override @Deprecated
     public void addItem(CatalogItem<?> item) {
         log.debug("Adding manual catalog item to "+mgmt+": "+item);
         Preconditions.checkNotNull(item, "item");
@@ -145,7 +162,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         manualAdditionsCatalog.addEntry(getAbstractCatalogItem(item));
     }
 
-    @Override
+    @Override @Deprecated
     public CatalogItem<?> addItem(Class<?> type) {
         log.debug("Adding manual catalog item to "+mgmt+": "+type);
         Preconditions.checkNotNull(type, "type");

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5c3d32ce/core/src/main/java/brooklyn/config/BrooklynServerConfig.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/config/BrooklynServerConfig.java b/core/src/main/java/brooklyn/config/BrooklynServerConfig.java
index f564176..1222392 100644
--- a/core/src/main/java/brooklyn/config/BrooklynServerConfig.java
+++ b/core/src/main/java/brooklyn/config/BrooklynServerConfig.java
@@ -1,6 +1,7 @@
 package brooklyn.config;
 
 import static brooklyn.entity.basic.ConfigKeys.newStringConfigKey;
+import io.brooklyn.camp.CampPlatform;
 
 import java.io.File;
 import java.util.Map;
@@ -12,6 +13,7 @@ import org.slf4j.LoggerFactory;
 import brooklyn.entity.basic.ConfigKeys;
 import brooklyn.management.ManagementContext;
 import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.guava.Maybe;
 import brooklyn.util.os.Os;
 
 /** config keys for the brooklyn server */
@@ -134,4 +136,14 @@ public class BrooklynServerConfig {
     public static final ConfigKey<Boolean> USE_OSGI = ConfigKeys.newBooleanConfigKey("brooklyn.osgi.enabled",
         "Whether OSGi is enabled, defaulting to true", true);
 
+    public static final ConfigKey<CampPlatform> CAMP_PLATFORM = ConfigKeys.newConfigKey(CampPlatform.class, "brooklyn.camp.platform",
+        "Config set at brooklyn management platform to find the CampPlatform instance (bi-directional)");
+
+    /** Returns the CAMP platform associated with a management context, if there is one. */
+    public static Maybe<CampPlatform> getCampPlatform(ManagementContext mgmt) {
+        CampPlatform result = mgmt.getConfig().getConfig(BrooklynServerConfig.CAMP_PLATFORM);
+        if (result!=null) return Maybe.of(result);
+        return Maybe.absent("No CAMP Platform is registered with this Brooklyn management context.");
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5c3d32ce/core/src/main/java/brooklyn/entity/basic/BrooklynConfigKeys.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/BrooklynConfigKeys.java b/core/src/main/java/brooklyn/entity/basic/BrooklynConfigKeys.java
index 90e52ee..4ed5b88 100644
--- a/core/src/main/java/brooklyn/entity/basic/BrooklynConfigKeys.java
+++ b/core/src/main/java/brooklyn/entity/basic/BrooklynConfigKeys.java
@@ -1,13 +1,15 @@
 package brooklyn.entity.basic;
 
-import static brooklyn.entity.basic.ConfigKeys.*;
+import static brooklyn.entity.basic.ConfigKeys.newBooleanConfigKey;
+import static brooklyn.entity.basic.ConfigKeys.newConfigKey;
+import static brooklyn.entity.basic.ConfigKeys.newConfigKeyWithPrefix;
+import static brooklyn.entity.basic.ConfigKeys.newStringConfigKey;
 import brooklyn.config.BrooklynServerConfig;
 import brooklyn.config.ConfigKey;
 import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
 import brooklyn.event.basic.TemplatedStringAttributeSensorAndConfigKey;
 import brooklyn.util.internal.ssh.ShellTool;
 import brooklyn.util.internal.ssh.SshTool;
-import brooklyn.util.os.Os;
 import brooklyn.util.time.Duration;
 
 import com.google.common.base.Preconditions;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5c3d32ce/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/BrooklynCampConstants.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/BrooklynCampConstants.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/BrooklynCampConstants.java
index b1821b9..9798407 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/BrooklynCampConstants.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/BrooklynCampConstants.java
@@ -1,9 +1,9 @@
 package io.brooklyn.camp.brooklyn;
 
 import io.brooklyn.camp.CampPlatform;
+import brooklyn.config.BrooklynServerConfig;
 import brooklyn.config.ConfigKey;
 import brooklyn.config.ConfigKey.HasConfigKey;
-import brooklyn.entity.basic.ConfigKeys;
 import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
 
 public class BrooklynCampConstants {
@@ -19,7 +19,6 @@ public class BrooklynCampConstants {
     public static final HasConfigKey<String> TEMPLATE_ID = new BasicAttributeSensorAndConfigKey<String>(String.class, "camp.template.id", 
         "UID of the component in the CAMP template from which this entity was created");
 
-    public static final ConfigKey<CampPlatform> CAMP_PLATFORM = ConfigKeys.newConfigKey(CampPlatform.class, "brooklyn.camp.platform",
-        "Config set at brooklyn management platform to find the CampPlatform instance (bi-directional)");
+    public static final ConfigKey<CampPlatform> CAMP_PLATFORM = BrooklynServerConfig.CAMP_PLATFORM;
 
 }


[22/45] git commit: Conditional wrapping of YAML app.

Posted by he...@apache.org.
Conditional wrapping of YAML app.

When loading YAML with a single application in the services list don't
create a wrapper application, use the one from the services list.
To explicitly force wrapping use custom attribute "wrapApp: true".

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

Branch: refs/heads/master
Commit: c43eb16fdc209a09f4cc7ee895816298bf48a785
Parents: 9bb861b
Author: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Authored: Wed Jul 2 12:52:17 2014 +0300
Committer: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Committed: Wed Jul 2 16:36:13 2014 +0300

----------------------------------------------------------------------
 .../BrooklynAssemblyTemplateInstantiator.java   | 80 +++++++++++++++-----
 .../io/brooklyn/camp/brooklyn/WrapAppTest.java  | 75 ++++++++++++++++++
 2 files changed, 134 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c43eb16f/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 4ec821f..9492104 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
@@ -13,6 +13,7 @@ import java.lang.reflect.Constructor;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -211,39 +212,76 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateIns
         // AssemblyTemplates created via PDP, _specifying_ then entities to put in
         final ManagementContext mgmt = getBrooklynManagementContext(platform);
 
-        Map<Entity, EntitySpec<?>> entitySpecs = Maps.newLinkedHashMap();
-
-        BrooklynComponentTemplateResolver appResolver = BrooklynComponentTemplateResolver.Factory.newInstance(mgmt, template);
-        EntitySpec<StartableApplication> appSpec = appResolver.resolveSpec(StartableApplication.class, BasicApplicationImpl.class);
-        Application app = appResolver.newEntity(appSpec);
-        entitySpecs.put(app, appSpec);
+        Map<Entity, EntitySpec<?>> rootEntities = Maps.newLinkedHashMap();
+        Map<Entity, EntitySpec<?>> allEntities = Maps.newLinkedHashMap();
+        buildEntities(template, rootEntities, allEntities, mgmt);
         
-        for (ResolvableLink<PlatformComponentTemplate> ctl: template.getPlatformComponentTemplates().links()) {
-            PlatformComponentTemplate appChildComponentTemplate = ctl.resolve();
-            BrooklynComponentTemplateResolver entityResolver = BrooklynComponentTemplateResolver.Factory.newInstance(mgmt, appChildComponentTemplate);
-            EntitySpec<? extends Entity> spec = entityResolver.resolveSpec();
+        EntitySpec<StartableApplication> appSpec;
+        StartableApplication app;
+        if(shouldWrapInApp(template, rootEntities)) {
+            BrooklynComponentTemplateResolver appResolver = BrooklynComponentTemplateResolver.Factory.newInstance(mgmt, template);
+            appSpec = appResolver.resolveSpec(StartableApplication.class, BasicApplicationImpl.class);
+            app = appResolver.newEntity(appSpec);
+            setEntitiesParent(rootEntities, app);
+            allEntities.put(app, appSpec);
+        } else {
+            Entry<Entity, EntitySpec<?>> entry = rootEntities.entrySet().iterator().next();
+            app = (StartableApplication)entry.getKey();
+            appSpec = (EntitySpec<StartableApplication>)entry.getValue();
+        }
+        
+        initEntities(mgmt, allEntities);
+        
+        log.info("CAMP placing '{}' under management", appSpec);
+        Entities.startManagement(app, mgmt);
 
-            spec.parent(app);
-            Entity entity = entityResolver.newEntity(spec);
-            entitySpecs.put(entity, spec);
-            buildEntityHierarchy(mgmt, entitySpecs, entity, entityResolver.getChildren(appChildComponentTemplate.getCustomAttributes()));
+        return app;
+    }
+
+    private void setEntitiesParent(Map<Entity, EntitySpec<?>> entities, Application parentApp) {
+        for(Entry<Entity, EntitySpec<?>> entry : entities.entrySet()) {
+            entry.getValue().parent(parentApp);
+            entry.getKey().setParent(parentApp);
         }
+    }
 
-        for (final Entity entity : entitySpecs.keySet()) {
-            final EntitySpec<?> spec = entitySpecs.get(entity);
+    private void initEntities(final ManagementContext mgmt, Map<Entity, EntitySpec<?>> entities) {
+        for (Entry<Entity, EntitySpec<?>> entry : entities.entrySet()) {
+            final Entity entity = entry.getKey();
+            
+            @SuppressWarnings("unchecked")
+            final EntitySpec<Entity> spec = (EntitySpec<Entity>)entry.getValue();
             
             ((EntityInternal) entity).getExecutionContext().submit(MutableMap.of(), new Runnable() {
                 @Override
                 public void run() {
-                    initEntity(mgmt, entity, (EntitySpec<Entity>)spec);
+                    initEntity(mgmt, entity, spec);
                 }
             }).getUnchecked();
         }
-        
-        log.info("CAMP placing '{}' under management", appSpec);
-        Entities.startManagement(app, mgmt);
+    }
 
-        return app;
+    private boolean shouldWrapInApp(AssemblyTemplate template, Map<Entity, EntitySpec<?>> rootEntities) {
+        return isWrapAppRequested(template) ||
+                rootEntities.size() != 1 ||
+                !(rootEntities.keySet().iterator().next() instanceof StartableApplication);
+    }
+
+    private boolean isWrapAppRequested(AssemblyTemplate template) {
+        return Boolean.TRUE.equals(template.getCustomAttributes().get("wrappedApp"));
+    }
+
+    private void buildEntities(AssemblyTemplate template, Map<Entity, EntitySpec<?>> parentEntities, 
+            Map<Entity, EntitySpec<?>> allEntities, ManagementContext mgmt) {
+        for (ResolvableLink<PlatformComponentTemplate> ctl: template.getPlatformComponentTemplates().links()) {
+            PlatformComponentTemplate appChildComponentTemplate = ctl.resolve();
+            BrooklynComponentTemplateResolver entityResolver = BrooklynComponentTemplateResolver.Factory.newInstance(mgmt, appChildComponentTemplate);
+            EntitySpec<? extends Entity> spec = entityResolver.resolveSpec();
+            Entity entity = entityResolver.newEntity(spec);
+            parentEntities.put(entity, spec);
+            allEntities.put(entity, spec);
+            buildEntityHierarchy(mgmt, allEntities, entity, entityResolver.getChildren(appChildComponentTemplate.getCustomAttributes()));
+        }
     }
 
     protected <T extends Entity> void initEntity(ManagementContext mgmt, T entity, EntitySpec<T> spec) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c43eb16f/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/WrapAppTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/WrapAppTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/WrapAppTest.java
new file mode 100644
index 0000000..31e9a66
--- /dev/null
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/WrapAppTest.java
@@ -0,0 +1,75 @@
+package io.brooklyn.camp.brooklyn;
+
+import java.io.StringReader;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.basic.StartableApplication;
+
+public class WrapAppTest extends AbstractYamlTest {
+    private static final String NO_WRAP_APP_IMPLICIT =
+            "name: Empty App\n" +
+            "services:\n" +
+            "   - type: brooklyn.test.entity.TestApplication";
+        
+    private static final String NO_WRAP_APP_EXPLICIT =
+            "name: Empty App\n" +
+            "wrappedApp: false\n" +
+            "services:\n" +
+            "   - type: brooklyn.test.entity.TestApplication";
+        
+    private static final String WRAP_APP_IMPLICIT =
+            "name: Empty App\n" +
+            "services:\n" +
+            "   - type: brooklyn.test.entity.TestApplication\n" +
+            "   - type: brooklyn.test.entity.TestApplication";
+        
+    private static final String WRAP_APP_EXPLICIT =
+            "name: Empty App\n" +
+            "wrappedApp: true\n" +
+            "services:\n" +
+            "   - type: brooklyn.test.entity.TestApplication";
+    
+    private static final String WRAP_ENTITY =
+            "name: Empty App\n" +
+            "services:\n" +
+            "   - type: brooklyn.test.entity.TestEntity";
+    
+    @Test
+    public void testNoWrapAppImplicit() throws Exception {
+        StartableApplication app = createApp(NO_WRAP_APP_IMPLICIT);
+        Assert.assertTrue(app.getChildren().size() == 0);
+    }
+    
+    @Test
+    public void testNoWrapAppExplicit() throws Exception {
+        StartableApplication app = createApp(NO_WRAP_APP_EXPLICIT);
+        Assert.assertTrue(app.getChildren().size() == 0);
+    }
+    
+    @Test
+    public void testWrapAppImplicit() throws Exception {
+        StartableApplication app = createApp(WRAP_APP_IMPLICIT);
+        Assert.assertTrue(app.getChildren().size() == 2);
+    }
+    
+    @Test
+    public void testWrapAppExplicit() throws Exception {
+        StartableApplication app = createApp(WRAP_APP_EXPLICIT);
+        Assert.assertTrue(app.getChildren().size() == 1);
+    }
+    
+    @Test
+    public void testWrapEntity() throws Exception {
+        StartableApplication app = createApp(WRAP_ENTITY);
+        Assert.assertTrue(app.getChildren().size() == 1);
+    }
+    
+    private StartableApplication createApp(String yaml) throws Exception {
+        StringReader in = new StringReader(yaml);
+        StartableApplication app = (StartableApplication)createAndStartApplication(in);
+        in.close();
+        return app;
+    }
+}


[39/45] git commit: Fix malformed HTML in add-app-wizard dialog

Posted by he...@apache.org.
Fix malformed HTML in add-app-wizard dialog

Error caused the drop-down lists for enum config keys to be rendered
incorrectly.


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

Branch: refs/heads/master
Commit: a64c601ea481d5b41367470006e1996f4abf0bbd
Parents: f28d9cc
Author: Richard Downer <ri...@apache.org>
Authored: Thu Jul 3 16:51:40 2014 +0100
Committer: Richard Downer <ri...@apache.org>
Committed: Thu Jul 3 16:51:40 2014 +0100

----------------------------------------------------------------------
 .../webapp/assets/tpl/app-add-wizard/required-config-entry.html    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a64c601e/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/required-config-entry.html
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/required-config-entry.html b/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/required-config-entry.html
index 838466e..2e9f774 100644
--- a/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/required-config-entry.html
+++ b/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/required-config-entry.html
@@ -14,7 +14,7 @@
             element = null;
         for (var i = 0; i < length; i++) {
           element = data.possibleValues[i]; %>
-        <option value="<%= element.value %>"><% if (data.defaultValue == element.value) { %> selected="selected"<% } %>><%= element.description %></option>
+        <option value="<%= element.value %>"<% if (data.defaultValue == element.value) { %> selected="selected"<% } %>><%= element.description %></option>
         <% } %>
       </select>
     <% } else { %>


[08/45] git commit: Ground work to load classes from bundles in blueprints

Posted by he...@apache.org.
Ground work to load classes from bundles in blueprints


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

Branch: refs/heads/master
Commit: 06c10c4318374009d1b8e0ed5b314d5481a40c7c
Parents: 79ebcc3
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Thu Jun 26 14:28:24 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Tue Jul 1 13:37:37 2014 +0100

----------------------------------------------------------------------
 .../java/brooklyn/event/feed/ssh/SshFeed.java   |  2 +-
 .../brooklyn/management/ha/OsgiManager.java     | 16 ++++++++++++++
 .../internal/LocalManagementContext.java        |  5 +++--
 .../internal/ManagementContextInternal.java     |  5 +++--
 .../NonDeploymentManagementContext.java         |  4 ++--
 .../src/main/java/brooklyn/util/osgi/Osgis.java | 15 +++++++------
 .../BrooklynAssemblyTemplateInstantiator.java   | 17 ++++++++++++---
 .../creation/BrooklynEntityClassResolver.java   | 23 +++++++++++++++++---
 8 files changed, 67 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/06c10c43/core/src/main/java/brooklyn/event/feed/ssh/SshFeed.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/feed/ssh/SshFeed.java b/core/src/main/java/brooklyn/event/feed/ssh/SshFeed.java
index 7492f75..ab3df25 100644
--- a/core/src/main/java/brooklyn/event/feed/ssh/SshFeed.java
+++ b/core/src/main/java/brooklyn/event/feed/ssh/SshFeed.java
@@ -168,7 +168,7 @@ public class SshFeed extends AbstractFeed {
     
     // Treat as immutable once built
     private final SetMultimap<SshPollIdentifier, SshPollConfig<?>> polls = HashMultimap.<SshPollIdentifier,SshPollConfig<?>>create();
-    
+
     /** @deprecated since 0.7.0, use static convenience on {@link Locations} */
     @Deprecated
     public static SshMachineLocation getMachineOfEntity(Entity entity) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/06c10c43/core/src/main/java/brooklyn/management/ha/OsgiManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/ha/OsgiManager.java b/core/src/main/java/brooklyn/management/ha/OsgiManager.java
index 07400ec..c161190 100644
--- a/core/src/main/java/brooklyn/management/ha/OsgiManager.java
+++ b/core/src/main/java/brooklyn/management/ha/OsgiManager.java
@@ -9,6 +9,7 @@ import brooklyn.config.BrooklynServerConfig;
 import brooklyn.config.ConfigKey;
 import brooklyn.util.collections.MutableMap;
 import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.guava.Maybe;
 import brooklyn.util.os.Os;
 import brooklyn.util.osgi.Osgis;
 
@@ -45,4 +46,19 @@ public class OsgiManager {
         framework = null;
     }
 
+    // TODO: throws BundleException appropriate?
+    public void registerBundle(String bundleUrl) throws BundleException {
+        Osgis.install(framework, bundleUrl);
+    }
+
+    // TODO: Handle .get failing
+    public <T> Maybe<Class<T>> tryResolveClass(String bundleUrl, String type) {
+        try {
+            Class<T> clazz = (Class<T>) Osgis.getBundle(framework, bundleUrl).get().loadClass(type);
+            return Maybe.of(clazz);
+        } catch (Exception e) {
+            Exceptions.propagateIfFatal(e);
+            return Maybe.absent(e);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/06c10c43/core/src/main/java/brooklyn/management/internal/LocalManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/LocalManagementContext.java b/core/src/main/java/brooklyn/management/internal/LocalManagementContext.java
index 0d3deb9..4b70799 100644
--- a/core/src/main/java/brooklyn/management/internal/LocalManagementContext.java
+++ b/core/src/main/java/brooklyn/management/internal/LocalManagementContext.java
@@ -36,6 +36,7 @@ import brooklyn.management.SubscriptionManager;
 import brooklyn.management.Task;
 import brooklyn.management.ha.OsgiManager;
 import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.guava.Maybe;
 import brooklyn.util.task.BasicExecutionContext;
 import brooklyn.util.task.BasicExecutionManager;
 import brooklyn.util.text.Strings;
@@ -255,9 +256,9 @@ public class LocalManagementContext extends AbstractManagementContext {
     }
     
     @Override
-    public synchronized OsgiManager getOsgiManager() {
+    public synchronized Maybe<OsgiManager> getOsgiManager() {
         if (!isRunning()) throw new IllegalStateException("Management context no longer running");
-        return osgiManager;        
+        return Maybe.of(osgiManager);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/06c10c43/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java b/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java
index fb50641..4707a7f 100644
--- a/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java
+++ b/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java
@@ -19,6 +19,7 @@ import brooklyn.location.Location;
 import brooklyn.management.ManagementContext;
 import brooklyn.management.Task;
 import brooklyn.management.ha.OsgiManager;
+import brooklyn.util.guava.Maybe;
 import brooklyn.util.task.TaskTags;
 
 public interface ManagementContextInternal extends ManagementContext {
@@ -59,9 +60,9 @@ public interface ManagementContextInternal extends ManagementContext {
 
     UsageManager getUsageManager();
     
-    /** returns OSGi manager, if available; may be null if OSGi not supported, e.g. in test contexts
+    /** returns OSGi manager, if available; may be absent if OSGi not supported, e.g. in test contexts
      * (but major contexts will support this) */
-    OsgiManager getOsgiManager();
+    Maybe<OsgiManager> getOsgiManager();
 
     InternalEntityFactory getEntityFactory();
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/06c10c43/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java b/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
index 61826ef..5c9278c 100644
--- a/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
+++ b/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
@@ -178,8 +178,8 @@ public class NonDeploymentManagementContext implements ManagementContextInternal
     }
     
     @Override
-    public OsgiManager getOsgiManager() {
-        return null;
+    public Maybe<OsgiManager> getOsgiManager() {
+        return Maybe.absent();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/06c10c43/core/src/main/java/brooklyn/util/osgi/Osgis.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/osgi/Osgis.java b/core/src/main/java/brooklyn/util/osgi/Osgis.java
index 2cfc5a7..5edca46 100644
--- a/core/src/main/java/brooklyn/util/osgi/Osgis.java
+++ b/core/src/main/java/brooklyn/util/osgi/Osgis.java
@@ -13,6 +13,8 @@ import org.osgi.framework.BundleException;
 import org.osgi.framework.Constants;
 import org.osgi.framework.Version;
 import org.osgi.framework.launch.Framework;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import brooklyn.util.ResourceUtils;
 import brooklyn.util.collections.MutableList;
@@ -33,13 +35,13 @@ import com.google.common.base.Predicates;
 @Beta
 public class Osgis {
 
+    private static final Logger LOG = LoggerFactory.getLogger(Osgis.class);
+
     public static List<Bundle> getBundlesByName(Framework framework, String symbolicName, Predicate<Version> versionMatcher) {
         List<Bundle> result = MutableList.of();
         for (Bundle b: framework.getBundleContext().getBundles()) {
-            if (symbolicName.equals(b.getSymbolicName())) {
-                if (versionMatcher.apply(b.getVersion())) {
-                    result.add(b);
-                }
+            if (symbolicName.equals(b.getSymbolicName()) && versionMatcher.apply(b.getVersion())) {
+                result.add(b);
             }
         }
         return result;
@@ -115,7 +117,7 @@ public class Osgis {
         try {
             framework.init();
             // nothing needs auto-loading, currently (and this needs a new dependency)
-//            AutoProcessor.process(configProps, m_fwk.getBundleContext());
+            // AutoProcessor.process(configProps, m_fwk.getBundleContext());
             framework.start();
         } catch (Exception e) {
             // framework bundle start exceptions are not interesting to caller...
@@ -128,12 +130,11 @@ public class Osgis {
      * using the {@link ResourceUtils} loader for this project (brooklyn core) */
     public static Bundle install(Framework framework, String url) throws BundleException {
         Bundle bundle = framework.getBundleContext().getBundle(url);
-        if (bundle!=null) return bundle;
+        if (bundle != null) return bundle;
         
         // use our URL resolution so we get classpath items
         InputStream stream = ResourceUtils.create(Osgis.class).getResourceFromUrl(url);
         return framework.getBundleContext().installBundle(url, stream);
     }
-    
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/06c10c43/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 4ec821f..a06d716 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
@@ -53,7 +53,7 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateIns
         Application app = create(template, platform);
         Task<?> task = start(app, platform);
         log.info("CAMP created "+app+"; starting in "+task);
-        return ((BrooklynCampPlatform)platform).assemblies().get(app.getApplicationId());
+        return platform.assemblies().get(app.getApplicationId());
     }
 
     // note: based on BrooklynRestResourceUtils, but modified to not allow child entities (yet)
@@ -65,6 +65,18 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateIns
         BrooklynCatalog catalog = mgmt.getCatalog();
         CatalogItem<?> item = catalog.getCatalogItem(template.getId());
 
+        if (item == null) {
+            // This doesn't seem the most appropriate way to do this!
+            // Especially since YAML will only reach here if a services section was given (so that
+            // PdpProcessor calls into BrooklynEntityMatcher [via applyMatchers] which sets the
+            // instantiator to BrooklynAssemblyTemplateInstantiator). So services must be given
+            // but will be disregarded.
+            Object customId = template.getCustomAttributes().get("id");
+            if (customId != null) {
+                item = catalog.getCatalogItem(customId.toString());
+            }
+        }
+
         if (item==null) {
             return createApplicationFromNonCatalogCampTemplate(template, platform);
         } else {
@@ -139,8 +151,7 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateIns
     }
 
     private ManagementContext getBrooklynManagementContext(CampPlatform platform) {
-        ManagementContext mgmt = ((HasBrooklynManagementContext)platform).getBrooklynManagementContext();
-        return mgmt;
+        return ((HasBrooklynManagementContext)platform).getBrooklynManagementContext();
     }
     
     public Task<?> start(Application app, CampPlatform platform) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/06c10c43/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityClassResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityClassResolver.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityClassResolver.java
index fe560da..7e71bb5 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityClassResolver.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityClassResolver.java
@@ -9,6 +9,8 @@ import org.slf4j.LoggerFactory;
 
 import brooklyn.entity.Entity;
 import brooklyn.management.ManagementContext;
+import brooklyn.management.ha.OsgiManager;
+import brooklyn.management.internal.ManagementContextInternal;
 import brooklyn.util.guava.Maybe;
 
 /**
@@ -20,7 +22,7 @@ public class BrooklynEntityClassResolver {
     private static final Logger LOG = LoggerFactory.getLogger(BrooklynEntityClassResolver.class);
 
     /**
-     * Loads the class represented by {@link #entityType} with the given management context.
+     * Loads the class represented by entityTypeName with the given management context.
      * Tries the context's catalogue first, then from its root classloader.
      * @throws java.lang.IllegalStateException if no class extending {@link Entity} is found
      */
@@ -36,7 +38,22 @@ public class BrooklynEntityClassResolver {
             LOG.warn("Found class {} on classpath but it is not assignable to {}", entityTypeName, Entity.class);
             throw new IllegalStateException("Unable to load class "+ entityTypeName +" (extending Entity) from catalogue or classpath: wrong type "+entityClazz.get());
         }
-        return (Class<T>) entityClazz.get();
+        return entityClazz.get();
+    }
+
+    /** Tries to load the entity with the given class name from the given bundle. */
+    public static <T extends Entity> Maybe<Class<T>> tryLoadEntityFromBundle(String entityTypeName, String bundleUrl, ManagementContext mgmt) {
+        Maybe<OsgiManager> osgiManager = ((ManagementContextInternal) mgmt).getOsgiManager();
+        if (!osgiManager.isPresentAndNonNull()) {
+            LOG.debug("Asked to resolve class {} from bundle {} but osgi manager is unavailable in context {}",
+                    new Object[]{entityTypeName, bundleUrl, mgmt});
+            return Maybe.absent();
+        }
+        Maybe<Class<T>> clazz = osgiManager.get().tryResolveClass(bundleUrl, entityTypeName);
+        if (!clazz.isPresent() || !Entity.class.isAssignableFrom(clazz.get())) {
+            return Maybe.absent();
+        }
+        return clazz;
     }
 
     @SuppressWarnings("unchecked")
@@ -59,6 +76,6 @@ public class BrooklynEntityClassResolver {
             return Maybe.absent(new Throwable("Could not find "+typeName+" on classpath"));
         }
 
-        return Maybe.<Class<T>>of(clazz);
+        return Maybe.of(clazz);
     }
 }


[19/45] git commit: update poms to build and use local camp-base and camp-server, now versioned with brooklyn.

Posted by he...@apache.org.
update poms to build and use local camp-base and camp-server, now versioned with brooklyn.


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

Branch: refs/heads/master
Commit: 7d5ce73cdeb9510d126d03cf328d6d6fa9a2ed85
Parents: d2191c9
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Wed Jul 2 10:29:17 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Wed Jul 2 10:29:17 2014 +0100

----------------------------------------------------------------------
 camp/camp-base/pom.xml   |    4 +-
 camp/camp-server/pom.xml |    8 +-
 camp/pom.xml             | 1055 +----------------------------------------
 core/pom.xml             |    5 +
 pom.xml                  |    3 +
 usage/camp/pom.xml       |    6 +-
 usage/launcher/pom.xml   |    8 +-
 7 files changed, 28 insertions(+), 1061 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d5ce73c/camp/camp-base/pom.xml
----------------------------------------------------------------------
diff --git a/camp/camp-base/pom.xml b/camp/camp-base/pom.xml
index 678fa69..5492896 100644
--- a/camp/camp-base/pom.xml
+++ b/camp/camp-base/pom.xml
@@ -1,6 +1,6 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
-    <packaging>bundle</packaging>
+    <packaging>jar</packaging>
 
     <artifactId>camp-base</artifactId>
 
@@ -12,7 +12,7 @@
     <parent>
         <groupId>io.brooklyn.camp</groupId>
         <artifactId>camp-parent</artifactId>
-        <version>0.1.0-SNAPSHOT</version>  <!-- CAMP_IMPL_VERSION -->
+        <version>0.7.0-SNAPSHOT</version>  <!-- BROOKLYN_VERSION -->
         <relativePath>../pom.xml</relativePath>
     </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d5ce73c/camp/camp-server/pom.xml
----------------------------------------------------------------------
diff --git a/camp/camp-server/pom.xml b/camp/camp-server/pom.xml
index 08a58b8..369184f 100644
--- a/camp/camp-server/pom.xml
+++ b/camp/camp-server/pom.xml
@@ -1,6 +1,6 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
-    <packaging>bundle</packaging>
+    <packaging>jar</packaging>
 
     <artifactId>camp-server</artifactId>
 
@@ -12,7 +12,7 @@
     <parent>
         <groupId>io.brooklyn.camp</groupId>
         <artifactId>camp-parent</artifactId>
-        <version>0.1.0-SNAPSHOT</version>  <!-- CAMP_IMPL_VERSION -->
+        <version>0.7.0-SNAPSHOT</version>  <!-- BROOKLYN_VERSION -->
         <relativePath>../pom.xml</relativePath>
     </parent>
 
@@ -25,13 +25,13 @@
         <dependency>
             <groupId>io.brooklyn.camp</groupId>
             <artifactId>camp-base</artifactId>
-            <version>${camp-impl.version}</version>
+            <version>${project.version}</version>
         </dependency>
 
         <dependency>
             <groupId>io.brooklyn.camp</groupId>
             <artifactId>camp-base</artifactId>
-            <version>${camp-impl.version}</version>
+            <version>${project.version}</version>
             <classifier>tests</classifier>
             <scope>test</scope>
         </dependency>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d5ce73c/camp/pom.xml
----------------------------------------------------------------------
diff --git a/camp/pom.xml b/camp/pom.xml
index 0f4432a..67e5c6b 100644
--- a/camp/pom.xml
+++ b/camp/pom.xml
@@ -6,1055 +6,22 @@
 
     <groupId>io.brooklyn.camp</groupId>
     <artifactId>camp-parent</artifactId>
-    <version>0.1.0-SNAPSHOT</version>  <!-- CAMP_IMPL_VERSION -->
 
     <name>CAMP Server Parent Project</name>
     <description>
         Parent/Root Project for Oasis CAMP Server modules
     </description>
-    <url>http://brooklyn.io/</url>
 
-    <!-- useful custom properties/defines to specify to control the build:
-
-      camp.explicitModules :: only builds explicit modules (instead of default modules)
-
-      camp.deployTo={cloudsoftFilesystem,cloudsoftArtifactory,sonatype} :: 
-            :: required when deploying; specify the deployment target
-
-      javadoc :: build javadoc (adds a minute or two; enabled automatically for target deploy)
-      
-      skipSources :: don't make the -sources.jar (saves a second or two, not much)
-      
-      skipTests :: does the usual thing (saves a lot of time, but at some cost of build quality!)
-
-
-      simply activate with -Dcamp.theCustomProperty on the mvn build line
-      (some of these are used to trigger profile selection, since maven activeByDefault
-      only works if _no_ profiles are triggered, see suggestion/background at:
-      http://stackoverflow.com/questions/5309379/how-to-keep-maven-profiles-which-are-activebydefault-active-even-if-another-prof )
-    -->
-
-    <licenses>
-        <license>
-            <name>The Apache Software License, Version 2.0</name>
-            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
-            <distribution>repo</distribution>
-        </license>
-    </licenses>
-
-    <developers>
-        <developer>
-            <name>Brooklyn Committers</name>
-        </developer>
-    </developers>
-
-    <scm>
-        <connection>scm:git:git://github.com/brooklyncentral/camp.git</connection>
-        <developerConnection>scm:git:git@github.com:brooklyncentral/camp.git</developerConnection>
-        <url>http://github.com/brooklyncentral/camp</url>
-    </scm>
-
-    <repositories>
-        <!-- enable sonatype snapshots repo (only for snapshots) -->
-        <repository>
-            <id>sonatype-nexus-snapshots</id>
-            <name>Sonatype Nexus Snapshots</name>
-            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
-            <releases> <enabled>false</enabled> </releases>
-            <snapshots> <enabled>true</enabled> </snapshots>
-        </repository>
-    </repositories>
-
-    <properties>
-        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
-
-        <camp-impl.version>0.1.0-SNAPSHOT</camp-impl.version>  <!-- CAMP_IMPL_VERSION -->
-
-        <brooklyn.version>0.7.0-SNAPSHOT</brooklyn.version>  <!-- BROOKLYN_VERSION -->
-        <fasterxml.jackson.version>2.2.0</fasterxml.jackson.version>
-        <commons-lang3.version>3.1</commons-lang3.version>
-        <commons-compress.version>1.4</commons-compress.version>
-
-        <surefire.version>2.13</surefire.version>
-        <testng.version>6.8</testng.version>
-        <logback.version>1.0.7</logback.version>
-        <slf4j.version>1.6.6</slf4j.version>
-        <gson.version>2.2.2</gson.version>
-        <commons-io.version>2.4</commons-io.version>
-     
-        <includedTestGroups />
-        <excludedTestGroups>Integration,Acceptance,Live,WIP</excludedTestGroups>
-        
-        <!-- no passphrase by default, so we can do automated deploy builds;
-             you can still supply your own passphrase with -Dgpg.passphrase=XXX -->
-        <gpg.passphrase></gpg.passphrase>
-    </properties>
-
-    <dependencyManagement>
-        <dependencies>
-            <!-- include version numbers for common dependencies 
-            <dependency>
-                <groupId>ch.qos.logback</groupId>
-                <artifactId>logback-classic</artifactId>
-                <version>${logback.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>com.google.guava</groupId>
-                <artifactId>guava</artifactId>
-                <version>${guava.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.slf4j</groupId>
-                <artifactId>slf4j-api</artifactId>
-                <version>${slf4j.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.testng</groupId>
-                <artifactId>testng</artifactId>
-                <version>${testng.version}</version>
-            </dependency>
-            -->
-        </dependencies>
-    </dependencyManagement>
-
-    <build>
-        <testSourceDirectory>src/test/java</testSourceDirectory>
-        <testResources>
-            <testResource>
-                <directory>src/test/resources</directory>
-            </testResource>
-        </testResources>
-
-        <pluginManagement>
-            <plugins>
-                <plugin>
-                    <artifactId>maven-assembly-plugin</artifactId>
-                    <version>2.3</version>
-                </plugin>
-                <plugin>
-                    <artifactId>maven-antrun-plugin</artifactId>
-                    <version>1.6</version>
-                </plugin>
-                <plugin>
-                    <artifactId>maven-clean-plugin</artifactId>
-                    <version>2.4.1</version>
-                    <configuration>
-                        <filesets>
-                            <fileset>
-                                <directory>.</directory>
-                                <includes>
-                                    <include>camp*.log</include>
-                                    <include>camp*.log.*</include>
-                                    <include>stacktrace.log</include>
-                                    <include>test-output</include>
-                                    <include>prodDb.*</include>
-                                </includes>
-                            </fileset>
-                        </filesets>
-                    </configuration>
-                </plugin>
-<!--
-                <plugin>
-                    <artifactId>maven-compiler-plugin</artifactId>
-                    <version>2.3.2</version>
-                    <configuration>
-                        <source>1.6</source>
-                        <target>1.6</target>
-                    </configuration>
-                </plugin>
--->
-<!-- use the groovy-eclipse-compiler (below) instead of the stack maven/java one (above)
-     because we use an inner-class builder pattern which references private outer class
-     members which gives "has private access" errors with some javac's (fixed in java7?) -->
-                <plugin>
-                  <artifactId>maven-compiler-plugin</artifactId>
-                  <configuration>
-                    <compilerId>groovy-eclipse-compiler</compilerId>
-                    <fork>true</fork>
-                    <verbose>false</verbose>
-                    <source>1.6</source>
-                    <target>1.6</target>
-                  </configuration>
-                  <dependencies>
-                    <dependency>
-                        <groupId>org.codehaus.groovy</groupId>
-                        <artifactId>groovy-eclipse-compiler</artifactId>
-                        <version>2.7.0-01</version>
-                    </dependency>
-                    <dependency>
-                        <groupId>org.codehaus.groovy</groupId>
-                        <artifactId>groovy-eclipse-batch</artifactId>
-                        <version>1.8.6-01</version>
-                    </dependency>
-                  </dependencies>
-                </plugin>
-                <plugin>
-                    <artifactId>maven-deploy-plugin</artifactId>
-                    <version>2.5</version>
-                </plugin>
-                <plugin>
-                    <artifactId>maven-enforcer-plugin</artifactId>
-                    <version>1.0</version>
-                </plugin>
-                <plugin>
-                    <artifactId>maven-failsafe-plugin</artifactId>
-                    <version>2.9</version>
-                </plugin>
-                <plugin>
-                    <artifactId>maven-jar-plugin</artifactId>
-                    <version>2.4</version>
-                </plugin>
-                <plugin>
-                    <artifactId>maven-source-plugin</artifactId>
-                    <version>2.1.2</version>
-                    <inherited>true</inherited>
-                    <executions>
-                        <execution>
-                            <id>attach-sources</id>
-                            <phase>verify</phase>
-                            <goals>
-                                <goal>jar-no-fork</goal>
-                            </goals>
-                        </execution>
-                    </executions>
-                </plugin>
-                <plugin>
-                    <artifactId>maven-javadoc-plugin</artifactId>
-                    <version>2.8</version>
-                    <inherited>true</inherited>
-                    <configuration>
-                        <links>
-                            <link>http://download.oracle.com/javaee/6/api</link>
-                        </links>
-                        <keywords>true</keywords>
-                        <author>false</author>
-                        <quiet>true</quiet>
-                        <aggregate>false</aggregate>
-                        <detectLinks />
-                        <tags>
-                            <tag>
-                                <name>todo</name>
-                                <placement>a</placement>
-                                <head>To-do:</head>
-                            </tag>
-                        </tags>
-                    </configuration>
-                    <executions>
-                        <execution>
-                            <id>attach-javadocs</id>
-                            <goals>
-                                <goal>jar</goal>
-                            </goals>
-                        </execution>
-                    </executions>
-                </plugin>
-                <plugin>
-                    <groupId>org.apache.maven.plugins</groupId>
-                    <artifactId>maven-gpg-plugin</artifactId>
-                    <version>1.1</version>
-                    <executions>
-                        <execution>
-                            <id>sign-artifacts</id>
-                            <phase>verify</phase>
-                            <goals>
-                                <goal>sign</goal>
-                            </goals>
-                        </execution>
-                    </executions>
-                </plugin>
-                <plugin>
-                    <!-- 'release' is not used; easier just to checkout, tag, `mvn deploy` manually
-                         with -Dcamp.deployTo=TARGET ... and note we need to update docs and examples, 
-                         which is a non-maven task!) -->
-                    <groupId>org.apache.maven.plugins</groupId>
-                    <artifactId>maven-release-plugin</artifactId>
-                    <version>2.1</version>
-                    <configuration>
-                        <mavenExecutorId>forked-path</mavenExecutorId>
-                        <useReleaseProfile>false</useReleaseProfile>
-                        <arguments>-Dcamp.deployTo=sonatype</arguments>
-                    </configuration>
-                </plugin>
-                <plugin>
-                    <artifactId>maven-resources-plugin</artifactId>
-                    <version>2.4.1</version>
-                </plugin>
-                <plugin>
-                    <artifactId>maven-shade-plugin</artifactId>
-                    <version>1.5</version>
-                    <executions>
-                        <execution>
-                            <phase>package</phase>
-                            <goals>
-                                <goal>shade</goal>
-                            </goals>
-                            <configuration>
-                                <shadedArtifactAttached>true</shadedArtifactAttached>
-                                <shadedClassifierName>with-dependencies</shadedClassifierName>
-                                <filters>
-                                    <filter>
-                                        <artifact>*:*</artifact>
-                                        <excludes>
-                                            <exclude>META-INF/*.SF</exclude>
-                                            <exclude>META-INF/*.DSA</exclude>
-                                            <exclude>META-INF/*.RSA</exclude>
-                                        </excludes>
-                                    </filter>
-                                </filters>
-                                <transformers>
-                                    <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
-                                </transformers>
-                            </configuration>
-                        </execution>
-                    </executions>
-                </plugin>
-                <plugin>
-                     <artifactId>maven-surefire-plugin</artifactId>
-                     <version>${surefire.version}</version>
-                     <configuration>
-                         <argLine>-Xms256m -Xmx512m -XX:MaxPermSize=512m -verbose:gc</argLine>
-                    </configuration>
-                </plugin>
-                <plugin>
-                    <artifactId>maven-site-plugin</artifactId>
-                    <version>3.0</version>
-                </plugin>
-                <plugin>
-                    <artifactId>maven-eclipse-plugin</artifactId>
-                    <version>2.8</version>
-                </plugin>
-                <plugin>
-                    <groupId>org.apache.felix</groupId>
-                    <artifactId>maven-bundle-plugin</artifactId>
-                    <version>2.3.4</version>
-                </plugin>
-                <plugin>
-                    <groupId>org.codehaus.mojo</groupId>
-                    <artifactId>findbugs-maven-plugin</artifactId>
-                    <version>2.3.2</version>
-                </plugin>
-                <plugin>
-                    <groupId>org.codehaus.mojo</groupId>
-                    <artifactId>build-helper-maven-plugin</artifactId>
-                    <version>1.7</version>
-                </plugin>
-                <plugin>
-                    <groupId>net.sourceforge.cobertura</groupId>
-                    <artifactId>cobertura</artifactId>
-                    <version>${cobertura.version}</version>
-                </plugin>
-                <plugin>
-                    <!-- This configuration is used for Eclipse settings only. -->
-                    <groupId>org.eclipse.m2e</groupId>
-                    <artifactId>lifecycle-mapping</artifactId>
-                    <version>1.0.0</version>
-                    <configuration>
-                        <lifecycleMappingMetadata>
-                            <pluginExecutions>
-                                <pluginExecution>
-                                    <pluginExecutionFilter>
-                                        <groupId>org.apache.maven.plugins</groupId>
-                                        <artifactId>maven-dependency-plugin</artifactId>
-                                        <versionRange>[2.1,)</versionRange>
-                                        <goals>
-                                            <goal>copy</goal>
-                                            <goal>copy-dependencies</goal>
-                                        </goals>
-                                    </pluginExecutionFilter>
-                                    <action>
-                                        <ignore />
-                                    </action>
-                                </pluginExecution>
-                                <pluginExecution>
-                                    <pluginExecutionFilter>
-                                        <groupId>org.apache.felix</groupId>
-                                        <artifactId>maven-bundle-plugin</artifactId>
-                                        <versionRange>[2.3.4,)</versionRange>
-                                        <goals>
-                                            <goal>manifest</goal>
-                                        </goals>
-                                    </pluginExecutionFilter>
-                                    <action>
-                                        <ignore />
-                                    </action>
-                                </pluginExecution>
-                                <pluginExecution>
-                                    <pluginExecutionFilter>
-                                        <groupId>org.apache.maven.plugins</groupId>
-                                        <artifactId>maven-javadoc-plugin</artifactId>
-                                        <versionRange>[2.7,3)</versionRange>
-                                        <goals>
-                                            <goal>jar</goal>
-                                        </goals>
-                                    </pluginExecutionFilter>
-                                    <action>
-                                        <ignore />
-                                    </action>
-                                </pluginExecution>
-                                <pluginExecution>
-                                    <pluginExecutionFilter>
-                                        <groupId>org.apache.maven.plugins</groupId>
-                                        <artifactId>maven-enforcer-plugin</artifactId>
-                                        <versionRange>[1.0,)</versionRange>
-                                        <goals>
-                                            <goal>enforce</goal>
-                                        </goals>
-                                    </pluginExecutionFilter>
-                                    <action>
-                                        <ignore />
-                                    </action>
-                                </pluginExecution>
-                            </pluginExecutions>
-                        </lifecycleMappingMetadata>
-                    </configuration>
-                </plugin>
-            </plugins>
-        </pluginManagement>
-        <plugins>
-            <plugin>
-                <artifactId>maven-enforcer-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>enforce</id>
-                        <phase>none</phase>
-                    </execution>
-                    <execution>
-                        <id>custom-build-req</id>
-                        <goals>
-                            <goal>enforce</goal>
-                        </goals>
-                        <inherited>true</inherited>
-                        <configuration>
-                            <rules>
-                                <requireJavaVersion>
-                                    <version>1.6.0</version>
-                                </requireJavaVersion>
-                                <requireMavenVersion>
-                                    <version>[3.0.0,)</version>
-                                </requireMavenVersion>
-                            </rules>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <artifactId>maven-resources-plugin</artifactId>
-                <configuration>
-                    <encoding>${project.build.sourceEncoding}</encoding>
-                </configuration>
-            </plugin>
-            <!--  workaround for src/main/resources excluding all in eclipse, as per
-                  https://issues.sonatype.org/browse/MNGECLIPSE-864 -->
-            <plugin>
-                <groupId>com.google.code.maven-replacer-plugin</groupId>
-                <artifactId>maven-replacer-plugin</artifactId>
-                <version>1.4.0</version>
-                <executions>
-                    <execution>
-                        <phase>clean</phase>
-                        <goals>
-                            <goal>replace</goal>
-                        </goals>
-                    </execution>
-                </executions>
-                <configuration>
-                    <ignoreMissingFile>true</ignoreMissingFile>
-                    <file>.classpath</file>
-                    <regex>false</regex>
-                    <replacements>
-                        <replacement>
-                            <xpath>/classpath/classpathentry[@path='src/main/resources' and @kind='src' and @excluding='**']/@excluding</xpath>
-                            <token>**</token>
-                            <value></value>
-                        </replacement>
-                    </replacements>
-                </configuration>
-            </plugin>
-        </plugins>
-        <extensions>
-            <extension>
-                <groupId>org.apache.maven.wagon</groupId>
-                <artifactId>wagon-ssh-external</artifactId>
-                <version>1.0</version>
-            </extension>
-        </extensions>
-    </build>
-
-    <profiles>
-        <profile>
-            <id>Essentials</id>
-            <activation> <property><name> !camp.explicitModules </name></property> </activation>
-            <modules>
-                <module>camp-base</module>
-                <module>camp-server</module>
-            </modules>
-        </profile>
-
-        <profile>
-            <id>Documentation</id>
-            <reporting>
-                <excludeDefaults>true</excludeDefaults>
-                <plugins>
-                    <plugin>
-                        <artifactId>maven-project-info-reports-plugin</artifactId>
-                        <version>2.4</version>
-                        <reportSets>
-                            <reportSet>
-                                <reports>
-                                    <report>index</report>
-                                    <report>modules</report>
-                                </reports>
-                            </reportSet>
-                        </reportSets>
-                    </plugin>
-                    <plugin>
-                        <artifactId>maven-javadoc-plugin</artifactId>
-                        <version>2.8</version>
-                        <configuration>
-                            <links>
-                                <link>http://download.oracle.com/javaee/6/api</link>
-                            </links>
-                            <keywords>true</keywords>
-                            <author>false</author>
-                            <quiet>true</quiet>
-                            <aggregate>false</aggregate>
-                            <detectLinks />
-                            <tags>
-                                <tag>
-                                    <name>todo</name>
-                                    <placement>a</placement>
-                                    <head>To-do:</head>
-                                </tag>
-                            </tags>
-                        </configuration>
-                        <reportSets>
-                            <reportSet>
-                                <id>javadoc</id>
-                                <reports>
-                                    <report>javadoc</report>
-                                </reports>
-                            </reportSet>
-                        </reportSets>
-                    </plugin>
-                </plugins>
-            </reporting>
-        </profile>
-        <profile>
-            <id>Bundle</id>
-            <activation>
-                <file>
-                    <exists>${basedir}/src</exists>
-                </file>
-            </activation>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.felix</groupId>
-                        <artifactId>maven-bundle-plugin</artifactId>
-                        <extensions>true</extensions>
-                        <executions>
-                            <execution>
-                                <id>create-bundle-manifest</id>
-                                <phase>process-classes</phase>
-                                <goals>
-                                    <goal>manifest</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <profile>
-            <id>Tests</id>
-            <activation>
-                <file> <exists>${basedir}/src/test</exists> </file>
-            </activation>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <version>${surefire.version}</version>
-                        <configuration>
-                            <properties>
-                                <property>
-                                    <name>listener</name>
-                                    <value>brooklyn.test.LoggingVerboseReporter</value>
-                                </property>
-                            </properties>
-                            <enableAssertions>true</enableAssertions>
-                            <groups>${includedTestGroups}</groups>
-                            <excludedGroups>${excludedTestGroups}</excludedGroups>
-                            <testFailureIgnore>false</testFailureIgnore>
-                            <systemPropertyVariables>
-                                <verbose>-1</verbose>
-                                <net.sourceforge.cobertura.datafile>${project.build.directory}/cobertura/cobertura.ser</net.sourceforge.cobertura.datafile>
-                                <cobertura.user.java.nio>false</cobertura.user.java.nio>
-                            </systemPropertyVariables>
-                            <printSummary>true</printSummary>
-                        </configuration>
-                    </plugin>
-                    <plugin>
-                        <artifactId>maven-jar-plugin</artifactId>
-                        <inherited>true</inherited>
-                        <executions>
-                            <execution>
-                                <id>test-jar-creation</id>
-                                <goals>
-                                    <goal>test-jar</goal>
-                                </goals>
-                                <configuration>
-                                    <forceCreation>true</forceCreation>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>Integration</id>
-            <properties>
-                <includedTestGroups>Integration</includedTestGroups>
-                <excludedTestGroups>Acceptance,Live,WIP</excludedTestGroups>
-            </properties>
-            <build>
-                <plugins>
-                    <plugin>
-                        <artifactId>maven-antrun-plugin</artifactId>
-                        <inherited>true</inherited>
-                        <executions>
-                            <execution>
-                                <id>run-tests</id>
-                                <goals>
-                                    <goal>run</goal>
-                                </goals>
-                                <phase>integration-test</phase>
-                            </execution>
-                        </executions>
-                    </plugin>
-                    <plugin>
-                        <artifactId>maven-jar-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>test-jar-creation</id>
-                                <configuration>
-                                    <skip>true</skip>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>Acceptance</id>
-            <properties>
-                <includedTestGroups>Acceptance</includedTestGroups>
-                <excludedTestGroups>Integration,Live,WIP</excludedTestGroups>
-            </properties>
-            <build>
-                <plugins>
-                    <plugin>
-                        <artifactId>maven-antrun-plugin</artifactId>
-                        <inherited>true</inherited>
-                        <executions>
-                            <execution>
-                                <id>run-tests</id>
-                                <goals>
-                                    <goal>run</goal>
-                                </goals>
-                                <phase>integration-test</phase>
-                            </execution>
-                        </executions>
-                    </plugin>
-                    <plugin>
-                        <artifactId>maven-jar-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>test-jar-creation</id>
-                                <configuration>
-                                    <skip>true</skip>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>Live</id>
-            <properties>
-                <includedTestGroups>Live</includedTestGroups>
-                <excludedTestGroups>Acceptance,WIP</excludedTestGroups>
-            </properties>
-            <build>
-                <plugins>
-                <!-- 
-                    <plugin>
-                        <artifactId>maven-antrun-plugin</artifactId>
-                        <inherited>true</inherited>
-                        <executions>
-                            <execution>
-                                <id>run-tests</id>
-                                <goals>
-                                    <goal>run</goal>
-                                </goals>
-                                <phase>integration-test</phase>
-                            </execution>
-                        </executions>
-                    </plugin>
-                 -->
-                    <plugin>
-                        <artifactId>maven-jar-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>test-jar-creation</id>
-                                <configuration>
-                                    <skip>true</skip>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <profile>
-            <id>CI</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>findbugs-maven-plugin</artifactId>
-                        <configuration>
-                            <xmlOutput>true</xmlOutput>
-                            <xmlOutputDirectory>target/site</xmlOutputDirectory>
-                        </configuration>
-                        <executions>
-                            <execution>
-                                <phase>process-classes</phase>
-                                <goals>
-                                    <goal>findbugs</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                    </plugin>
-                    <plugin>
-                        <artifactId>maven-source-plugin</artifactId>
-                    </plugin>
-                    <plugin>
-                        <artifactId>maven-pmd-plugin</artifactId>
-                        <version>2.5</version>
-                        <inherited>true</inherited>
-                        <configuration>
-                            <failOnViolation>false</failOnViolation>
-                            <linkXref>true</linkXref>
-                            <sourceEncoding>utf-8</sourceEncoding>
-                            <minimumTokens>100</minimumTokens>
-                            <targetJdk>1.6</targetJdk>
-                            <excludes>
-                                <exclude>**/*Test.java</exclude>
-                                <exclude>**/tests/**/*.java</exclude>
-                                <!-- add any more generated source code directories here -->
-                            </excludes>
-                            <excludeRoots>
-                                <excludeRoot>
-                                    ${pom.basedir}/target/generated-sources/groovy-stubs/main
-                                </excludeRoot>
-                            </excludeRoots>
-                        </configuration>
-                        <executions>
-                            <execution>
-                                <phase>process-classes</phase>
-                                <goals>
-                                    <goal>check</goal>
-                                    <goal>cpd-check</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>Coverage</id>
-            <dependencies>
-                <dependency>
-                    <groupId>net.sourceforge.cobertura</groupId>
-                    <artifactId>cobertura</artifactId>
-                    <version>${cobertura.version}</version>
-                    <scope>test</scope>
-                </dependency>
-            </dependencies>
-            <build>
-                <plugins>
-                    <plugin>
-                        <artifactId>maven-source-plugin</artifactId>
-                    </plugin>
-                    <plugin>
-                        <artifactId>maven-antrun-plugin</artifactId>
-                        <inherited>true</inherited>
-                        <executions>
-                            <execution>
-                                <id>run-tests</id>
-                            </execution>
-                            <execution>
-                                <id>instrument classes</id>
-                                <goals>
-                                    <goal>run</goal>
-                                </goals>
-                                <phase>process-test-classes</phase>
-                                <configuration>
-                                    <target>
-                                        <taskdef resource="net/sf/antcontrib/antcontrib.properties" classpathref="maven.plugin.classpath" />
-                                        <taskdef resource="tasks.properties" classpathref="maven.plugin.classpath" />
-                                        <if>
-                                            <available property="gogocobertura" file="target/test-classes" />
-                                            <then>
-                                                <echo message="INSTRUMENTING CLASSES FOR COBERTURA" />
-                                                <!-- Ensure any and all bits of our project are copied in first -->
-                                                <copy todir="target/cobertura/coverage-classes">
-                                                    <fileset erroronmissingdir="false" dir="target/classes" />
-                                                </copy>
-                                                <cobertura-instrument datafile="target/cobertura/cobertura.ser"
-                                                    todir="target/test-classes">
-                                                    <fileset erroronmissingdir="false" dir="target/classes">
-                                                        <include name="**/*.class" />
-                                                        <exclude name="**/*Test.class" />
-                                                    </fileset>
-                                                    <fileset erroronmissingdir="false" dir="target/cobertura/dependency-classes">
-                                                        <include name="**/*.class" />
-                                                        <exclude name="**/*Test.class" />
-                                                    </fileset>
-                                                </cobertura-instrument>
-                                            </then>
-                                        </if>
-                                    </target>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>coverage report</id>
-                                <goals>
-                                    <goal>run</goal>
-                                </goals>
-                                <phase>post-integration-test</phase>
-                                <configuration>
-                                    <target>
-                                        <taskdef resource="net/sf/antcontrib/antcontrib.properties" classpathref="maven.plugin.classpath" />
-                                        <taskdef resource="tasks.properties" classpathref="maven.plugin.classpath" />
-                                        <if>
-                                            <available property="gogocobertura" file="target/cobertura/cobertura.ser" />
-                                            <then>
-                                                <echo message="GENERATING COBERTURA COVERAGE REPORT" />
-                                                <cobertura-report format="xml" destdir="target/site/cobertura"
-                                                    datafile="target/cobertura/cobertura.ser">
-                                                    <fileset erroronmissingdir="false" dir="src/java" />
-                                                    <fileset erroronmissingdir="false" dir="target/cobertura/dependency-sources" />
-                                                </cobertura-report>
-                                            </then>
-                                        </if>
-                                    </target>
-                                </configuration>
-                            </execution>
-                        </executions>
-                        <dependencies>
-                            <dependency>
-                                <groupId>ant-contrib</groupId>
-                                <artifactId>ant-contrib</artifactId>
-                                <version>1.0b3</version>
-                                <exclusions>
-                                    <exclusion>
-                                        <groupId>ant</groupId>
-                                        <artifactId>ant</artifactId>
-                                    </exclusion>
-                                </exclusions>
-                            </dependency>
-                            <dependency>
-                                <groupId>org.apache.ant</groupId>
-                                <artifactId>ant-launcher</artifactId>
-                                <version>${ant.version}</version>
-                            </dependency>
-                            <dependency>
-                                <groupId>org.apache.ant</groupId>
-                                <artifactId>ant</artifactId>
-                                <version>${ant.version}</version>
-                            </dependency>
-                            <dependency>
-                                <groupId>org.testng</groupId>
-                                <artifactId>testng</artifactId>
-                                <version>${testng.version}</version>
-                            </dependency>
-                            <dependency>
-                                <groupId>net.sourceforge.cobertura</groupId>
-                                <artifactId>cobertura</artifactId>
-                                <version>${cobertura.version}</version>
-                            </dependency>
-                        </dependencies>
-                    </plugin>
-                    <plugin>
-                        <artifactId>maven-dependency-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>unpack-coverage-sources</id>
-                                <phase>generate-sources</phase>
-                                <goals>
-                                    <goal>unpack-dependencies</goal>
-                                </goals>
-                                <configuration>
-                                    <classifier>sources</classifier>
-                                    <includeScope>compile</includeScope>
-                                    <includeGroupIds>io.brooklyn.camp</includeGroupIds>
-                                    <outputDirectory>
-                                        ${project.build.directory}/cobertura/dependency-sources
-                                    </outputDirectory>
-                                    <failOnMissingClassifierArtifact>false</failOnMissingClassifierArtifact>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>unpack-coverage-classes</id>
-                                <phase>compile</phase>
-                                <goals>
-                                    <goal>unpack-dependencies</goal>
-                                </goals>
-                                <configuration>
-                                    <type>jar</type>
-                                    <includeScope>compile</includeScope>
-                                    <includeGroupIds>io.brooklyn.camp</includeGroupIds>
-                                    <outputDirectory>
-                                        ${project.build.directory}/cobertura/dependency-classes
-                                    </outputDirectory>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                    <plugin>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <version>${surefire.version}</version>
-                        <inherited>true</inherited>
-                        <configuration>
-                            <reportFormat>xml</reportFormat>
-                            <classesDirectory>${project.build.directory}/cobertura/coverage-classes</classesDirectory>
-                            <systemProperties>
-                                <property>
-                                    <name>net.sourceforge.cobertura.datafile</name>
-                                    <value>${project.build.directory}/cobertura/cobertura.ser
-                                    </value>
-                                </property>
-                                <property>
-                                    <name>cobertura.user.java.nio</name>
-                                    <value>false</value>
-                                </property>
-                            </systemProperties>
-                        </configuration>
-                    </plugin>
-                    <plugin>
-                        <artifactId>maven-jar-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>test-jar-creation</id>
-                                <configuration>
-                                    <skip>true</skip>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                    <plugin>
-                        <artifactId>maven-deploy-plugin</artifactId>
-                        <configuration>
-                            <skip>true</skip>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <!-- build sources jars by default, it's quick -->
-        <profile>
-            <id>make-sources-jar</id>
-            <activation> <property><name>!skipSources</name></property> </activation>
-            <build><plugins><plugin>
-                <artifactId>maven-source-plugin</artifactId>
-            </plugin></plugins></build>
-        </profile>
-        
-        <!-- only build javadoc if asked, or if deploying (it's slow) -->
-        <profile>
-            <id>make-javadoc-jar</id>
-            <activation> <property><name>javadoc</name></property> </activation>            
-            <build><plugins><plugin>
-                <artifactId>maven-javadoc-plugin</artifactId>
-            </plugin></plugins></build>
-        </profile>
-        
-        <!-- sign and make javadoc when deploying; note, this means you'll need gpg set up to deploy -->
-        <profile>
-            <id>make-more-things-when-deploying</id>
-            <activation> <property><name>camp.deployTo</name></property> </activation>            
-            <build><plugins>
-                <plugin>
-                    <artifactId>maven-javadoc-plugin</artifactId>
-                </plugin>
-                <plugin>
-                    <artifactId>maven-gpg-plugin</artifactId>
-                </plugin>
-            </plugins></build>
-        </profile>
-
-        <!-- different properties used to deploy to different locations depending on profiles;
-             default is cloudsoft filesystem repo, but some sources still use cloudsoft artifactory as source
-             (and soon we will support artifactory) -->
-        <profile>
-            <id>cloudsoft-filesystem-repo</id>
-            <activation> <property><name>camp.deployTo</name><value>cloudsoftFilesystem</value></property> </activation>
-            <distributionManagement>
-                <repository>
-                    <id>cloudsoft-deploy-cloudfront-origin-releases</id>
-                    <name>Cloudsoft Release Filesystem repo (used as origin for cloudfront)</name>
-                    <url>scpexe://root@developers-origin.cloudsoftcorp.com/var/www/developers/maven/releases/</url>
-                </repository>
-                <snapshotRepository>
-                    <id>cloudsoft-deploy-cloudfront-origin-snapshots</id>
-                    <name>Cloudsoft Snapshot Filesystem repo (used as origin for cloudfront)</name>
-                    <url>scpexe://root@developers-origin.cloudsoftcorp.com/var/www/developers/maven/snapshots/</url>
-                </snapshotRepository>
-            </distributionManagement>
-        </profile>
-        <profile>
-            <id>cloudsoft-artifactory-repo</id>
-            <activation> <property><name>camp.deployTo</name><value>cloudsoftArtifactory</value></property> </activation>
-            <distributionManagement>
-                <repository>
-                    <id>cloudsoft-deploy-artifactory-release</id>
-                    <name>Cloudsoft Artifactory libs-release-local repo</name>
-                    <url>http://ccweb.cloudsoftcorp.com/maven/libs-release-local/</url>
-                </repository>
-                <snapshotRepository>
-                    <id>cloudsoft-deploy-artifactory-snapshot</id>
-                    <name>Cloudsoft Artifactory libs-snapshot-local repo</name>
-                    <url>http://ccweb.cloudsoftcorp.com/maven/libs-snapshot-local/</url>
-                </snapshotRepository>
-            </distributionManagement>
-        </profile>
-        <profile>
-            <id>sonatype-nexus-repo</id>
-            <activation> <property><name>camp.deployTo</name><value>sonatype</value></property> </activation>
-            <distributionManagement>
-                <repository>
-                    <id>sonatype-nexus-staging</id>
-                    <name>Nexus Release Repository</name>
-                    <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
-                </repository>
-                <snapshotRepository>
-                    <id>sonatype-nexus-snapshots</id>
-                    <name>Sonatype Nexus Snapshots</name>
-                    <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
-                </snapshotRepository>
-            </distributionManagement>
-        </profile>
-    </profiles>
+    <parent>
+        <groupId>io.brooklyn</groupId>
+        <artifactId>brooklyn-parent</artifactId>
+        <version>0.7.0-SNAPSHOT</version>  <!-- BROOKLYN_VERSION -->
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <modules>
+        <module>camp-base</module>
+        <module>camp-server</module>
+    </modules>
 
 </project>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d5ce73c/core/pom.xml
----------------------------------------------------------------------
diff --git a/core/pom.xml b/core/pom.xml
index 1056ad1..a7c6846 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -32,6 +32,11 @@
             <artifactId>brooklyn-utils-groovy</artifactId>
             <version>${brooklyn.version}</version>
         </dependency>
+        <dependency>
+            <groupId>io.brooklyn.camp</groupId>
+            <artifactId>camp-base</artifactId>
+            <version>${brooklyn.version}</version>
+        </dependency>
 
         <dependency>
             <groupId>net.schmizz</groupId>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d5ce73c/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 2052356..c5165d3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -122,6 +122,8 @@
         <osgi-core.version>4.3.0</osgi-core.version>
         <commons-io.version>2.4</commons-io.version>
         <hazelcast.version>3.0</hazelcast.version>
+        <commons-lang3.version>3.1</commons-lang3.version>
+        <commons-compress.version>1.4</commons-compress.version>
 
         <includedTestGroups />
         <excludedTestGroups>Integration,Acceptance,Live,WIP</excludedTestGroups>
@@ -681,6 +683,7 @@
                 <module>utils/groovy</module>
                 <module>api</module>
                 <module>usage/test-support</module>
+                <module>camp</module>
                 <module>core</module>
                 <module>policy</module>
                 <module>storage/hazelcast</module>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d5ce73c/usage/camp/pom.xml
----------------------------------------------------------------------
diff --git a/usage/camp/pom.xml b/usage/camp/pom.xml
index af9b39d..f529283 100644
--- a/usage/camp/pom.xml
+++ b/usage/camp/pom.xml
@@ -15,10 +15,6 @@
         <relativePath>../../pom.xml</relativePath>
     </parent>
 
-    <properties>
-        <camp-impl.version>0.1.0-SNAPSHOT</camp-impl.version>
-    </properties>
-
     <dependencies>
         
         <dependency>
@@ -30,7 +26,7 @@
         <dependency>
             <groupId>io.brooklyn.camp</groupId>
             <artifactId>camp-base</artifactId>
-            <version>${camp-impl.version}</version>
+            <version>${brooklyn.version}</version>
         </dependency>
         
         <!-- TODO not enamoured of including software-base here, but it allows us to reference chef and vanilla for short names;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d5ce73c/usage/launcher/pom.xml
----------------------------------------------------------------------
diff --git a/usage/launcher/pom.xml b/usage/launcher/pom.xml
index d9c056b..229544e 100644
--- a/usage/launcher/pom.xml
+++ b/usage/launcher/pom.xml
@@ -18,10 +18,6 @@
         <relativePath>../../pom.xml</relativePath>
     </parent>
 
-    <properties>
-        <camp.version>0.1.0-SNAPSHOT</camp.version>
-    </properties>
-
     <dependencies>
         <dependency>
             <groupId>io.brooklyn</groupId>
@@ -40,12 +36,12 @@
         <dependency>
             <groupId>io.brooklyn.camp</groupId>
             <artifactId>camp-server</artifactId>
-            <version>${camp.version}</version>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>io.brooklyn.camp</groupId>
             <artifactId>camp-server</artifactId>
-            <version>${camp.version}</version>
+            <version>${project.version}</version>
             <scope>test</scope>
             <classifier>tests</classifier>
         </dependency>


[10/45] git commit: Adds version to catalogue items and tests deserialisation

Posted by he...@apache.org.
Adds version to catalogue items and tests deserialisation


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

Branch: refs/heads/master
Commit: 45e1494f74ffe1829b0ded954a450846c3cef2a3
Parents: 494291d
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Mon Jun 30 15:23:35 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Tue Jul 1 13:37:37 2014 +0100

----------------------------------------------------------------------
 .../main/java/brooklyn/catalog/CatalogItem.java |  4 ++
 .../catalog/internal/CatalogItemDo.java         |  8 ++++
 .../internal/CatalogItemDtoAbstract.java        |  5 +++
 .../catalog/internal/CatalogXmlSerializer.java  |  1 +
 .../catalog/internal/CatalogLoadTest.java       | 46 ++++++++++++++++++++
 .../brooklyn/catalog/internal/osgi-catalog.xml  | 11 +++++
 6 files changed, 75 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/45e1494f/api/src/main/java/brooklyn/catalog/CatalogItem.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/catalog/CatalogItem.java b/api/src/main/java/brooklyn/catalog/CatalogItem.java
index ab01496..b9ae3c0 100644
--- a/api/src/main/java/brooklyn/catalog/CatalogItem.java
+++ b/api/src/main/java/brooklyn/catalog/CatalogItem.java
@@ -1,6 +1,7 @@
 package brooklyn.catalog;
 
 import java.util.List;
+import javax.annotation.Nonnull;
 
 public interface CatalogItem<T> {
     
@@ -20,6 +21,9 @@ public interface CatalogItem<T> {
     public String getName();
     public String getDescription();
     public String getIconUrl();
+    public String getVersion();
+
+    @Nonnull
     public CatalogItemContext getContext();
 
     public String toXmlString();

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/45e1494f/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
index d576c0a..91ed93a 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
@@ -1,5 +1,7 @@
 package brooklyn.catalog.internal;
 
+import javax.annotation.Nonnull;
+
 import com.google.common.base.Preconditions;
 
 import brooklyn.catalog.CatalogItem;
@@ -57,6 +59,12 @@ public class CatalogItemDo<T> implements CatalogItem<T> {
     }
 
     @Override
+    public String getVersion() {
+        return itemDto.getVersion();
+    }
+
+    @Nonnull
+    @Override
     public CatalogItemContext getContext() {
         return itemDto.getContext();
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/45e1494f/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
index 043758b..a774930 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
@@ -21,6 +21,7 @@ public abstract class CatalogItemDtoAbstract<T> implements CatalogItem<T> {
     String name;
     String description;
     String iconUrl;
+    String version;
     CatalogItemContext context;
     
     public String getId() {
@@ -44,6 +45,10 @@ public abstract class CatalogItemDtoAbstract<T> implements CatalogItem<T> {
         return iconUrl;
     }
 
+    public String getVersion() {
+        return version;
+    }
+
     @Nonnull
     @Override
     public CatalogItemContext getContext() {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/45e1494f/core/src/main/java/brooklyn/catalog/internal/CatalogXmlSerializer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogXmlSerializer.java b/core/src/main/java/brooklyn/catalog/internal/CatalogXmlSerializer.java
index 9cdbffe..63c2382 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogXmlSerializer.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogXmlSerializer.java
@@ -28,6 +28,7 @@ public class CatalogXmlSerializer extends XmlSerializer<Object> {
 
         xstream.useAttributeFor(CatalogItemDtoAbstract.class, "type");
         xstream.useAttributeFor(CatalogItemDtoAbstract.class, "name");
+        xstream.useAttributeFor(CatalogItemDtoAbstract.class, "version");
 
         xstream.useAttributeFor(CatalogClasspathDto.class, "scan");
         xstream.addImplicitCollection(CatalogClasspathDto.class, "entries", "entry", String.class);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/45e1494f/core/src/test/java/brooklyn/catalog/internal/CatalogLoadTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/catalog/internal/CatalogLoadTest.java b/core/src/test/java/brooklyn/catalog/internal/CatalogLoadTest.java
new file mode 100644
index 0000000..46394c7
--- /dev/null
+++ b/core/src/test/java/brooklyn/catalog/internal/CatalogLoadTest.java
@@ -0,0 +1,46 @@
+package brooklyn.catalog.internal;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
+
+import brooklyn.util.ResourceUtils;
+
+public class CatalogLoadTest {
+
+    CatalogXmlSerializer serializer;
+
+    @BeforeMethod
+    public void setUp() {
+        serializer = new CatalogXmlSerializer();
+    }
+
+    private String loadFile(String file) {
+        return ResourceUtils.create(this).getResourceAsString(file);
+    }
+
+    @Test
+    public void testLoadCatalog() {
+        CatalogDto catalog = (CatalogDto) serializer.fromString(
+                loadFile("classpath://brooklyn/catalog/internal/osgi-catalog.xml"));
+        assertNotNull(catalog);
+        assertEquals(catalog.name, "OSGi catalogue");
+        assertEquals(catalog.entries.size(), 1, "Catalog entries = " + Joiner.on(", ").join(catalog.entries));
+
+        CatalogItemDtoAbstract<?> template = Iterables.getOnlyElement(catalog.entries);
+        assertEquals(template.getName(), "Entity name");
+        assertEquals(template.getVersion(), "9.1.3");
+        assertEquals(template.getJavaType(), "com.example.ExampleApp");
+        assertEquals(template.getContext().getBundles().size(), 2,
+                "Template bundles=" + Joiner.on(", ").join(template.getContext().getBundles()));
+        assertEquals(Sets.newHashSet(template.getContext().getBundles()),
+                Sets.newHashSet("file://path/to/bundle.jar", "http://www.url.com/for/bundle.jar"));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/45e1494f/core/src/test/resources/brooklyn/catalog/internal/osgi-catalog.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/brooklyn/catalog/internal/osgi-catalog.xml b/core/src/test/resources/brooklyn/catalog/internal/osgi-catalog.xml
new file mode 100644
index 0000000..c8ea685
--- /dev/null
+++ b/core/src/test/resources/brooklyn/catalog/internal/osgi-catalog.xml
@@ -0,0 +1,11 @@
+<catalog>
+    <name>OSGi catalogue</name>
+
+    <template name="Entity name" version="9.1.3" type="com.example.ExampleApp">
+        <description>An example application</description>
+        <context class="context">
+            <bundle>file://path/to/bundle.jar</bundle>
+            <bundle>http://www.url.com/for/bundle.jar</bundle>
+        </context>
+    </template>
+</catalog>


[29/45] git commit: create specs from catalog items, and use these in many places. also fix some NPE and serialization issues.

Posted by he...@apache.org.
create specs from catalog items, and use these in many places.  also fix some NPE and serialization issues.


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

Branch: refs/heads/master
Commit: 468d788542d19810062d3e0b8a41019aa699f740
Parents: 407de80
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Jul 3 02:29:47 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu Jul 3 02:29:47 2014 +0100

----------------------------------------------------------------------
 .../main/java/brooklyn/catalog/CatalogItem.java | 17 +++-
 .../camp/test/mock/web/MockWebPlatform.java     | 15 ++-
 .../api/AssemblyTemplateSpecInstantiator.java   | 12 +++
 .../api/HasBrooklynManagementContext.java       |  9 ++
 .../brooklyn/catalog/CatalogPredicates.java     |  9 ++
 .../catalog/internal/BasicBrooklynCatalog.java  | 99 ++++++++++++++++----
 .../catalog/internal/CatalogClasspathDo.java    | 10 +-
 .../internal/CatalogConfigurationDto.java       | 11 +++
 .../brooklyn/catalog/internal/CatalogDo.java    | 13 ++-
 .../brooklyn/catalog/internal/CatalogDto.java   |  9 +-
 .../catalog/internal/CatalogEntityItemDto.java  | 12 +++
 .../catalog/internal/CatalogItemDo.java         | 32 ++++++-
 .../internal/CatalogItemDtoAbstract.java        | 74 ++++++++++-----
 .../catalog/internal/CatalogLibrariesDo.java    |  9 +-
 .../catalog/internal/CatalogLibrariesDto.java   |  9 +-
 .../catalog/internal/CatalogPolicyItemDto.java  |  6 ++
 .../internal/CatalogTemplateItemDto.java        | 10 +-
 .../dto/BasicManagementNodeSyncRecord.java      | 12 ++-
 .../lite/CampPlatformWithJustBrooklynMgmt.java  | 23 +++++
 .../brooklyn/camp/lite/CampYamlLiteTest.java    | 37 ++++++--
 .../camp/lite/TestAppAssemblyInstantiator.java  | 40 ++++++--
 .../catalog/internal/CatalogDtoTest.java        | 74 +++++++--------
 .../camp/brooklyn/BrooklynCampPlatform.java     |  2 +-
 .../BrooklynAssemblyTemplateInstantiator.java   | 35 +++++--
 .../platform/BrooklynImmutableCampPlatform.java |  1 +
 .../platform/HasBrooklynManagementContext.java  |  9 --
 .../brooklyn/EmptySoftwareProcessYamlTest.java  |  5 +-
 usage/cli/src/main/java/brooklyn/cli/Main.java  |  8 +-
 .../brooklyn/launcher/BrooklynLauncher.java     | 10 +-
 .../resources/AbstractBrooklynRestResource.java |  5 +-
 30 files changed, 465 insertions(+), 152 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/api/src/main/java/brooklyn/catalog/CatalogItem.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/catalog/CatalogItem.java b/api/src/main/java/brooklyn/catalog/CatalogItem.java
index fe844b8..276eba4 100644
--- a/api/src/main/java/brooklyn/catalog/CatalogItem.java
+++ b/api/src/main/java/brooklyn/catalog/CatalogItem.java
@@ -1,7 +1,9 @@
 package brooklyn.catalog;
 
 import java.util.List;
+
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 public interface CatalogItem<T,SpecT> {
     
@@ -14,15 +16,28 @@ public interface CatalogItem<T,SpecT> {
     }
 
     public CatalogItemType getCatalogItemType();
+    /** the high-level type of this entity, e.g. Entity (not a specific Entity class) */
     public Class<T> getCatalogItemJavaType();
+    /** the type of the spec e.g. EntitySpec corresponding to {@link #getCatalogItemJavaType()} */
+    public Class<SpecT> getSpecType();
     
+    /** the explicit ID of this item, or the type if not supplied */
     public String getId();
-    public String getJavaType();
+    
+    /** the type name registered in the catalog for this item */ 
+    public String getRegisteredTypeName();
+    
+    /** the underlying java type of the item represented, or null if not known (e.g. if it comes from yaml) */
+    // TODO references to this should probably query getRegisteredType
+    @Nullable public String getJavaType();
+    
     public String getName();
     public String getDescription();
     public String getIconUrl();
     public String getVersion();
 
+    // FIXME many of the static methods in CatalogItemAbstractDto which create CatalogItems set this as null
+    // I (alex) suggest removing the annotation, here, and in subclasses where the method is defined
     @Nonnull
     public CatalogItemLibraries getLibraries();
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/camp/camp-base/src/test/java/io/brooklyn/camp/test/mock/web/MockWebPlatform.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/test/java/io/brooklyn/camp/test/mock/web/MockWebPlatform.java b/camp/camp-base/src/test/java/io/brooklyn/camp/test/mock/web/MockWebPlatform.java
index e547d91..389ec41 100644
--- a/camp/camp-base/src/test/java/io/brooklyn/camp/test/mock/web/MockWebPlatform.java
+++ b/camp/camp-base/src/test/java/io/brooklyn/camp/test/mock/web/MockWebPlatform.java
@@ -1,5 +1,7 @@
 package io.brooklyn.camp.test.mock.web;
 
+import javax.annotation.Nullable;
+
 import brooklyn.util.guava.Maybe;
 import io.brooklyn.camp.BasicCampPlatform;
 import io.brooklyn.camp.spi.ApplicationComponentTemplate;
@@ -7,6 +9,7 @@ import io.brooklyn.camp.spi.AssemblyTemplate;
 import io.brooklyn.camp.spi.PlatformComponentTemplate;
 import io.brooklyn.camp.spi.collection.BasicResourceLookup;
 import io.brooklyn.camp.spi.collection.ResolvableLink;
+import io.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
 import io.brooklyn.camp.spi.pdp.Artifact;
 import io.brooklyn.camp.spi.pdp.AssemblyTemplateConstructor;
 import io.brooklyn.camp.spi.pdp.Service;
@@ -57,7 +60,7 @@ public class MockWebPlatform {
         }
     };
 
-    public static final PdpMatcher newLiteralServiceTypeToPlatformComponentTemplateMatcher(final BasicCampPlatform platform) {
+    public static final PdpMatcher newLiteralServiceTypeToPlatformComponentTemplateMatcher(final BasicCampPlatform platform, @Nullable final Class<? extends AssemblyTemplateInstantiator> instantiator) {
         return new PdpMatcher() {
             public boolean apply(Object item, AssemblyTemplateConstructor atc) {
                 if (!(item instanceof Service)) return false;
@@ -71,8 +74,11 @@ public class MockWebPlatform {
                             .customAttribute("serviceType", type)
                             .description(Maybe.fromNullable(svc.getDescription()).or(t.resolve().getDescription()))
                             .build();
-                        if (atc!=null)
+                        if (atc!=null) {
                             atc.add(pct);
+                            if (instantiator!=null)
+                                atc.instantiator(instantiator);
+                        }
                         return true;
                     }
                 }
@@ -87,12 +93,15 @@ public class MockWebPlatform {
     }
     
     public static <T extends BasicCampPlatform> T populate(T platform) {
+        return populate(platform, null);
+    }
+    public static <T extends BasicCampPlatform> T populate(T platform, @Nullable Class<? extends AssemblyTemplateInstantiator> instantiator) {
         platform.platformComponentTemplates().addAll(APPSERVER, DATABASE);
         platform.applicationComponentTemplates().add(WAR);
         platform.assemblyTemplates().add(ASSEMBLY1);
         
         platform.pdp().addMatcher(WAR_GETS_WAR_MATCHER);
-        platform.pdp().addMatcher(newLiteralServiceTypeToPlatformComponentTemplateMatcher(platform));
+        platform.pdp().addMatcher(newLiteralServiceTypeToPlatformComponentTemplateMatcher(platform, instantiator));
         
         return platform;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java b/core/src/main/java/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java
new file mode 100644
index 0000000..0054a80
--- /dev/null
+++ b/core/src/main/java/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java
@@ -0,0 +1,12 @@
+package brooklyn.camp.brooklyn.api;
+
+import io.brooklyn.camp.CampPlatform;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+import io.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
+import brooklyn.entity.proxying.EntitySpec;
+
+public interface AssemblyTemplateSpecInstantiator extends AssemblyTemplateInstantiator {
+
+    EntitySpec<?> createSpec(AssemblyTemplate template, CampPlatform platform);
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/camp/brooklyn/api/HasBrooklynManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/camp/brooklyn/api/HasBrooklynManagementContext.java b/core/src/main/java/brooklyn/camp/brooklyn/api/HasBrooklynManagementContext.java
new file mode 100644
index 0000000..e21bff1
--- /dev/null
+++ b/core/src/main/java/brooklyn/camp/brooklyn/api/HasBrooklynManagementContext.java
@@ -0,0 +1,9 @@
+package brooklyn.camp.brooklyn.api;
+
+import brooklyn.management.ManagementContext;
+
+public interface HasBrooklynManagementContext {
+
+    public ManagementContext getBrooklynManagementContext();
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/catalog/CatalogPredicates.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/CatalogPredicates.java b/core/src/main/java/brooklyn/catalog/CatalogPredicates.java
index 5c3d884..6dfe89a 100644
--- a/core/src/main/java/brooklyn/catalog/CatalogPredicates.java
+++ b/core/src/main/java/brooklyn/catalog/CatalogPredicates.java
@@ -47,6 +47,15 @@ public class CatalogPredicates {
         };
     }
 
+    public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> registeredType(final Predicate<? super String> filter) {
+        return new Predicate<CatalogItem<T,SpecT>>() {
+            @Override
+            public boolean apply(@Nullable CatalogItem<T,SpecT> item) {
+                return (item != null) && filter.apply(item.getRegisteredTypeName());
+            }
+        };
+    }
+
     public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> javaType(final Predicate<? super String> filter) {
         return new Predicate<CatalogItem<T,SpecT>>() {
             @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/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 4bbb02c..6a4f3d2 100644
--- a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
@@ -1,7 +1,10 @@
 package brooklyn.catalog.internal;
 
 import io.brooklyn.camp.CampPlatform;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+import io.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
 import io.brooklyn.camp.spi.pdp.DeploymentPlan;
+import io.brooklyn.camp.spi.pdp.Service;
 
 import java.util.NoSuchElementException;
 
@@ -10,6 +13,7 @@ import javax.annotation.Nullable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator;
 import brooklyn.catalog.BrooklynCatalog;
 import brooklyn.catalog.CatalogItem;
 import brooklyn.catalog.CatalogPredicates;
@@ -18,7 +22,9 @@ import brooklyn.management.ManagementContext;
 import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.javalang.AggregateClassLoader;
 import brooklyn.util.javalang.LoadedClassLoader;
+import brooklyn.util.javalang.Reflections;
 import brooklyn.util.stream.Streams;
+import brooklyn.util.text.Strings;
 import brooklyn.util.time.Duration;
 import brooklyn.util.time.Time;
 
@@ -96,14 +102,57 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         }
     }
 
+    @SuppressWarnings("unchecked")
     @Override
     public <T, SpecT> SpecT createSpec(CatalogItem<T, SpecT> item) {
-        // TODO #2
-        throw new UnsupportedOperationException();
+        CatalogItemDo<T,SpecT> loadedItem = (CatalogItemDo<T, SpecT>) getCatalogItemDo(item.getId());
+        
+        Class<SpecT> specType = loadedItem.getSpecType();
+        if (specType==null) return null;
+            
+        String yaml = loadedItem.getYaml();
+        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 = camp.pdp().registerDeploymentPlan(plan);
+            
+            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);
+            }
+        }
+            
+        // revert to legacy mechanism
+        try {
+            if (loadedItem.getJavaType()!=null) {
+                @SuppressWarnings({ "deprecation" })
+                SpecT specT = (SpecT) Reflections.findMethod(specType, "create", Class.class).invoke(null, loadedItem.getJavaClass());
+                spec = specT;
+            }
+        } catch (Exception e) {
+            Exceptions.propagateIfFatal(e);
+            throw new IllegalStateException("Unsupported creation of spec type "+specType+"; it must have a public static create(Class) method", e);
+        }
+
+        if (spec==null) 
+            throw new IllegalStateException("Unknown how to create instance of "+this);
+
+        return spec;
     }
     
     @SuppressWarnings("unchecked")
     @Override
+    /** @deprecated since 0.7.0 use {@link #createSpec(CatalogItem)} */
+    @Deprecated
     public <T,SpecT> Class<? extends T> loadClass(CatalogItem<T,SpecT> item) {
         if (log.isDebugEnabled())
             log.debug("Loading class for catalog item " + item);
@@ -115,6 +164,8 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     
     @SuppressWarnings("unchecked")
     @Override
+    /** @deprecated since 0.7.0 use {@link #createSpec(CatalogItem)} */
+    @Deprecated
     public <T> Class<? extends T> loadClassByType(String typeName, Class<T> typeClass) {
         Iterable<CatalogItem<Object,Object>> resultL = getCatalogItems(CatalogPredicates.javaType(Predicates.equalTo(typeName)));
         if (Iterables.isEmpty(resultL)) throw new NoSuchElementException("Unable to find catalog item for type "+typeName);
@@ -125,7 +176,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         return (Class<? extends T>) loadClass(resultI);
     }
 
-    @Deprecated
+    @Deprecated /** @deprecated since 0.7.0 only used by other deprecated items */ 
     private <T,SpecT> CatalogItemDtoAbstract<T,SpecT> getAbstractCatalogItem(CatalogItem<T,SpecT> item) {
         while (item instanceof CatalogItemDo) item = ((CatalogItemDo<T,SpecT>)item).itemDto;
         if (item==null) return null;
@@ -133,21 +184,37 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         throw new IllegalStateException("Cannot unwrap catalog item '"+item+"' (type "+item.getClass()+") to restore DTO");
     }
 
-    private <T,SpecT> CatalogItemDtoAbstract<T,SpecT> getAbstractCatalogItem(String yaml) {
-        CampPlatform camp = BrooklynServerConfig.getCampPlatform(mgmt).get();
+    private CatalogItemDtoAbstract<?,?> getAbstractCatalogItem(String yaml) {
+        DeploymentPlan plan = makePlanFromYaml(yaml);
         
-        DeploymentPlan plan = camp.pdp().parseDeploymentPlan(Streams.newReaderWithContents(yaml));
+        // TODO #2 parse brooklyn.catalog for metadata - name, bundles/libraries, etc
+        // (for now we default to taking the name from the plan or from a single service type therein, below)
+        String name = null;
+        CatalogLibrariesDto libraries = null;
         
-        // TODO #2 parse brooklyn.catalog metadata, bundles etc.
-        // for now take the name from the plan or from a single service type therein
+        // TODO #3 support version info
         
-        // TODO #3 version info
+        // take name from plan if not specified in brooklyn.catalog section not supplied
+        if (Strings.isBlank(name)) {
+            name = plan.getName();
+            if (Strings.isBlank(name)) {
+                if (plan.getServices().size()==1) {
+                    Service svc = Iterables.getOnlyElement(plan.getServices());
+                    name = svc.getServiceType();
+                }
+            }
+        }
         
-        // TODO #1 build the catalog item from the plan (as CatalogItem<Entity> ?)
-//        plan.getName()
-        // TODO #2 then support instantiating from the item, replacing 
+        // build the catalog item from the plan (as CatalogItem<Entity> for now)
+        // TODO applications / templates
+        // TODO long-term support policies etc
         
-        throw new UnsupportedOperationException();
+        return CatalogItemDtoAbstract.newEntityFromPlan(name, libraries, plan, yaml);
+    }
+
+    private DeploymentPlan makePlanFromYaml(String yaml) {
+        CampPlatform camp = BrooklynServerConfig.getCampPlatform(mgmt).get();
+        return camp.pdp().parseDeploymentPlan(Streams.newReaderWithContents(yaml));
     }
 
     @Override
@@ -160,7 +227,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         return itemDto;
     }
 
-    @Override @Deprecated
+    @Override @Deprecated /** @deprecated see super */
     public void addItem(CatalogItem<?,?> item) {
         log.debug("Adding manual catalog item to "+mgmt+": "+item);
         Preconditions.checkNotNull(item, "item");
@@ -168,7 +235,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         manualAdditionsCatalog.addEntry(getAbstractCatalogItem(item));
     }
 
-    @Override @Deprecated
+    @Override @Deprecated /** @deprecated see super */
     public CatalogItem<?,?> addItem(Class<?> type) {
         log.debug("Adding manual catalog item to "+mgmt+": "+type);
         Preconditions.checkNotNull(type, "type");
@@ -177,7 +244,6 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         return manualAdditionsCatalog.classpath.addCatalogEntry(type);
     }
 
-    @Deprecated
     private synchronized void loadManualAdditionsCatalog() {
         if (manualAdditionsCatalog!=null) return;
         CatalogDto manualAdditionsCatalogDto = CatalogDto.newNamedInstance(
@@ -218,7 +284,6 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         return Iterables.transform(filtered, BasicBrooklynCatalog.<T,SpecT>itemDoToDto());
     }
 
-    @SuppressWarnings({ "unchecked" })
     private static <T,SpecT> Function<CatalogItemDo<T,SpecT>, CatalogItem<T,SpecT>> itemDoToDto() {
         return new Function<CatalogItemDo<T,SpecT>, CatalogItem<T,SpecT>>() {
             @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
index 06d0914..badf319 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
@@ -207,7 +207,9 @@ public class CatalogClasspathDo {
         return Iterables.filter(input, f);
     }
 
-    /** augments the given item with annotations and class data for the given class, then adds to catalog */
+    /** augments the given item with annotations and class data for the given class, then adds to catalog
+     * @deprecated since 0.7.0 the classpath DO is replaced by libraries */
+    @Deprecated
     public CatalogItem<?,?> addCatalogEntry(Class<?> c) {
         if (Application.class.isAssignableFrom(c)) return addCatalogEntry(new CatalogTemplateItemDto(), c);
         if (ApplicationBuilder.class.isAssignableFrom(c)) return addCatalogEntry(new CatalogTemplateItemDto(), c);
@@ -217,10 +219,12 @@ public class CatalogClasspathDo {
     }
     
     /** augments the given item with annotations and class data for the given class, then adds to catalog 
-     */
+     * @deprecated since 0.7.0 the classpath DO is replaced by libraries */
+    @Deprecated
     public CatalogItem<?,?> addCatalogEntry(CatalogItemDtoAbstract<?,?> item, Class<?> c) {
         Catalog annotations = c.getAnnotation(Catalog.class);
-        item.type = c.getName();
+        item.registeredType = c.getName();
+        item.javaType = c.getName();
         item.name = firstNonEmpty(c.getSimpleName(), c.getName());
         if (annotations!=null) {
             item.name = firstNonEmpty(annotations.name(), item.name);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/catalog/internal/CatalogConfigurationDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogConfigurationDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogConfigurationDto.java
index d52b539..f07c942 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogConfigurationDto.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogConfigurationDto.java
@@ -12,4 +12,15 @@ public class CatalogConfigurationDto extends CatalogItemDtoAbstract<ConfigKey,Vo
     }
 
     public Class<ConfigKey> getCatalogItemJavaType() { return ConfigKey.class; }
+
+    @Override
+    public String getRegisteredTypeName() {
+        return getJavaType();
+    }
+    
+    @Override
+    public Class<Void> getSpecType() {
+        return null;
+    }
+    
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
index c571585..5cda68d 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
@@ -92,10 +92,15 @@ public class CatalogDo {
 
     private void loadCatalogItems() {
         List<CatalogLibrariesDo> loadedLibraries = Lists.newLinkedList();
-        for (CatalogItemDtoAbstract<?,?> entry : dto.entries) {
-            CatalogLibrariesDo library = new CatalogLibrariesDo(entry.getLibrariesDto());
-            library.load(mgmt);
-            loadedLibraries.add(library);
+        List<CatalogItemDtoAbstract<?, ?>> entries = dto.entries;
+        if (entries!=null) {
+            for (CatalogItemDtoAbstract<?,?> entry : entries) {
+                if (entry.getLibrariesDto()!=null) {
+                    CatalogLibrariesDo library = new CatalogLibrariesDo(entry.getLibrariesDto());
+                    library.load(mgmt);
+                    loadedLibraries.add(library);
+                }
+            }
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java
index bd34020..655ed29 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java
@@ -7,10 +7,11 @@ import java.util.List;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Objects;
-
 import brooklyn.util.ResourceUtils;
 import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.exceptions.PropagatedRuntimeException;
+
+import com.google.common.base.Objects;
 
 public class CatalogDto {
 
@@ -42,8 +43,8 @@ public class CatalogDto {
             if (LOG.isDebugEnabled()) LOG.debug("Retrieved catalog from: {}", url);
             return result;
         } catch (Throwable t) {
-            LOG.debug("Unable to retrieve catalog from: " + url + " (" + t + ")");
-            throw Exceptions.propagate(t);
+            Exceptions.propagateIfFatal(t);
+            throw new PropagatedRuntimeException("Unable to retrieve catalog from " + url + ": " + t, t);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/catalog/internal/CatalogEntityItemDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogEntityItemDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogEntityItemDto.java
index 8a61f24..60d6fbe 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogEntityItemDto.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogEntityItemDto.java
@@ -6,6 +6,8 @@ import brooklyn.entity.proxying.EntitySpec;
 
 public class CatalogEntityItemDto extends CatalogItemDtoAbstract<Entity,EntitySpec<?>> {
     
+    String planYaml;
+
     @Override
     public CatalogItemType getCatalogItemType() {
         return CatalogItemType.ENTITY;
@@ -16,4 +18,14 @@ public class CatalogEntityItemDto extends CatalogItemDtoAbstract<Entity,EntitySp
         return Entity.class;
     }
 
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Override
+    public Class<EntitySpec<?>> getSpecType() {
+        return (Class)EntitySpec.class;
+    }
+
+    public String getPlanYaml() {
+        return planYaml;
+    }
+    
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
index 1a6c804..200db52 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
@@ -1,22 +1,23 @@
 package brooklyn.catalog.internal;
 
 import javax.annotation.Nonnull;
-
-import com.google.common.base.Preconditions;
+import javax.annotation.Nullable;
 
 import brooklyn.catalog.CatalogItem;
 import brooklyn.util.exceptions.Exceptions;
 
+import com.google.common.base.Preconditions;
+
 public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT> {
 
     protected final CatalogDo catalog;
-    protected final CatalogItem<T,SpecT> itemDto;
+    protected final CatalogItemDtoAbstract<T,SpecT> itemDto;
 
     protected volatile Class<T> javaClass; 
     
     public CatalogItemDo(CatalogDo catalog, CatalogItem<T,SpecT> itemDto) {
         this.catalog = Preconditions.checkNotNull(catalog, "catalog");
-        this.itemDto = Preconditions.checkNotNull(itemDto, "itemDto");
+        this.itemDto = (CatalogItemDtoAbstract<T, SpecT>) Preconditions.checkNotNull(itemDto, "itemDto");
     }
 
     public CatalogItem<T,SpecT> getDto() {
@@ -39,6 +40,11 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT> {
     }
 
     @Override
+    public String getRegisteredTypeName() {
+        return itemDto.getRegisteredTypeName();
+    }
+    
+    @Override
     public String getJavaType() {
         return itemDto.getJavaType();
     }
@@ -69,6 +75,17 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT> {
         return itemDto.getLibraries();
     }
 
+    @Nullable
+    public String getYaml() {
+        if (itemDto instanceof CatalogEntityItemDto) {
+            return ((CatalogEntityItemDto)itemDto).getPlanYaml();
+        }
+        return null;
+    }
+    
+    /** @deprecated since 0.7.0 this is the legacy mechanism; still needed for policies and apps, but being phased out.
+     * new items should use {@link #getYaml()} */
+    @Deprecated
     public Class<T> getJavaClass() {
         if (javaClass==null) loadJavaClass();
         return javaClass;
@@ -78,6 +95,9 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT> {
     protected Class<? extends T> loadJavaClass() {
         try {
             if (javaClass!=null) return javaClass;
+            
+            // TODO use OSGi
+            
             javaClass = (Class<T>) catalog.getRootClassLoader().loadClass(getJavaType());
             return javaClass;
         } catch (ClassNotFoundException e) {
@@ -93,5 +113,9 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT> {
     public String toXmlString() {
         return itemDto.toXmlString();
     }
+
+    public Class<SpecT> getSpecType() {
+        return itemDto.getSpecType();
+    }
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
index 771e37b..4957474 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
@@ -1,26 +1,45 @@
 package brooklyn.catalog.internal;
 
+import io.brooklyn.camp.spi.pdp.DeploymentPlan;
+
 import javax.annotation.Nonnull;
 
 import brooklyn.catalog.CatalogItem;
 
 public abstract class CatalogItemDtoAbstract<T,SpecT> implements CatalogItem<T,SpecT> {
 
+    // TODO are ID and registeredType the same?
     String id;
-    String type;
+    String registeredType;
+    
+    String javaType;
     String name;
     String description;
     String iconUrl;
     String version;
     CatalogLibrariesDto libraries;
     
+    /** @deprecated since 0.7.0.
+     * used for backwards compatibility when deserializing.
+     * when catalogs are converted to new yaml format, this can be removed. */
+    @Deprecated
+    String type;
+    
     public String getId() {
         if (id!=null) return id;
-        return type;
+        return getRegisteredTypeName();
+    }
+    
+    @Override
+    public String getRegisteredTypeName() {
+        if (registeredType!=null) return registeredType;
+        return getJavaType();
     }
     
     public String getJavaType() {
-        return type;
+        if (javaType!=null) return javaType;
+        if (type!=null) return type;
+        return null;
     }
     
     public String getName() {
@@ -49,41 +68,48 @@ public abstract class CatalogItemDtoAbstract<T,SpecT> implements CatalogItem<T,S
         return libraries;
     }
 
-    public static CatalogTemplateItemDto newTemplate(String type, String name) {
-        return newTemplate(null, type, name, null);
+    public static CatalogTemplateItemDto newTemplateFromJava(String javaType, String name) {
+        return newTemplateFromJava(null, javaType, name, null);
     }
-    public static CatalogTemplateItemDto newTemplate(String id, String type, String name, String description) {
-        return newTemplate(id, type, name, description, null);
+    public static CatalogTemplateItemDto newTemplateFromJava(String id, String javaType, String name, String description) {
+        return newTemplateFromJava(id, javaType, name, description, null);
     }
-    public static CatalogTemplateItemDto newTemplate(String id, String type, String name, String description, CatalogLibrariesDto libraries) {
-        return set(new CatalogTemplateItemDto(), id, type, name, description, libraries);
+    public static CatalogTemplateItemDto newTemplateFromJava(String id, String javaType, String name, String description, CatalogLibrariesDto libraries) {
+        return set(new CatalogTemplateItemDto(), id, javaType, javaType, name, description, libraries);
     }
 
-    public static CatalogEntityItemDto newEntity(String type, String name) {
-        return newEntity(null, type, name, null);
+    public static CatalogEntityItemDto newEntityFromPlan(String registeredTypeName, CatalogLibrariesDto libraries, DeploymentPlan plan, String underlyingPlanYaml) {
+        CatalogEntityItemDto target = set(new CatalogEntityItemDto(), null, registeredTypeName, null, plan.getName(), plan.getDescription(), libraries);
+        target.planYaml = underlyingPlanYaml;
+        return target;
     }
-    public static CatalogEntityItemDto newEntity(String id, String type, String name, String description) {
-        return newEntity(id, type, name, description, null);
+    
+    public static CatalogEntityItemDto newEntityFromJava(String javaType, String name) {
+        return newEntityFromJava(null, javaType, name, null);
+    }
+    public static CatalogEntityItemDto newEntityFromJava(String id, String javaType, String name, String description) {
+        return newEntityFromJava(id, javaType, name, description, null);
     }
-    public static CatalogEntityItemDto newEntity(String id, String type, String name, String description, CatalogLibrariesDto libraries) {
-        return set(new CatalogEntityItemDto(), id, type, name, description, libraries);
+    public static CatalogEntityItemDto newEntityFromJava(String id, String javaType, String name, String description, CatalogLibrariesDto libraries) {
+        return set(new CatalogEntityItemDto(), id, javaType, javaType, name, description, libraries);
     }
 
-    public static CatalogPolicyItemDto newPolicy(String type, String name) {
-        return newPolicy(null, type, name, null);
+    public static CatalogPolicyItemDto newPolicyFromJava(String javaType, String name) {
+        return newPolicyFromJava(null, javaType, name, null);
     }
-    public static CatalogPolicyItemDto newPolicy(String id, String type, String name, String description) {
-        return newPolicy(id, type, name, description, null);
+    public static CatalogPolicyItemDto newPolicyFromJava(String id, String javaType, String name, String description) {
+        return newPolicyFromJava(id, javaType, name, description, null);
     }
-    public static CatalogPolicyItemDto newPolicy(String id, String type, String name, String description, CatalogLibrariesDto libraries) {
-        return set(new CatalogPolicyItemDto(), id, type, name, description, libraries);
+    public static CatalogPolicyItemDto newPolicyFromJava(String id, String javaType, String name, String description, CatalogLibrariesDto libraries) {
+        return set(new CatalogPolicyItemDto(), id, javaType, javaType, name, description, libraries);
     }
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
-    private static <T extends CatalogItemDtoAbstract> T set(T target, String id, String type, String name,
+    private static <T extends CatalogItemDtoAbstract> T set(T target, String id, String registeredType, String javaType, String name,
             String description, CatalogLibrariesDto libraries) {
         target.id = id;
-        target.type = type;
+        target.registeredType = registeredType;
+        target.javaType = javaType;
         target.name = name;
         target.description = description;
         target.libraries = libraries != null ? libraries : new CatalogLibrariesDto();
@@ -106,5 +132,7 @@ public abstract class CatalogItemDtoAbstract<T,SpecT> implements CatalogItem<T,S
         if (serializer==null) 
             serializer = new CatalogXmlSerializer();
     }
+
+    public abstract Class<SpecT> getSpecType();
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java
index 86295a1..0892c31 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java
@@ -5,18 +5,17 @@ import java.util.List;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Joiner;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Stopwatch;
-
 import brooklyn.catalog.CatalogItem;
 import brooklyn.management.ManagementContext;
 import brooklyn.management.ha.OsgiManager;
 import brooklyn.management.internal.ManagementContextInternal;
 import brooklyn.util.guava.Maybe;
-import brooklyn.util.text.Strings;
 import brooklyn.util.time.Time;
 
+import com.google.common.base.Joiner;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Stopwatch;
+
 public class CatalogLibrariesDo implements CatalogItem.CatalogItemLibraries {
 
     private static final Logger LOG = LoggerFactory.getLogger(CatalogLibrariesDo.class);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
index 3c05387..a408921 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
@@ -1,8 +1,10 @@
 package brooklyn.catalog.internal;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
 
+import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import brooklyn.catalog.CatalogItem;
@@ -12,11 +14,16 @@ public class CatalogLibrariesDto implements CatalogItem.CatalogItemLibraries {
     private List<String> bundles = new CopyOnWriteArrayList<String>();
 
     public void addBundle(String url) {
-        bundles.add(url);
+        Preconditions.checkNotNull(url, "Cannot add a bundle to a deserialized DTO");
+        bundles.add( Preconditions.checkNotNull(url) );
     }
 
     /** @return An immutable copy of the bundle URLs referenced by this object */
     public List<String> getBundles() {
+        if (bundles==null)  {
+            // can be null on deserialization
+            return Collections.emptyList();
+        }
         return ImmutableList.copyOf(bundles);
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/catalog/internal/CatalogPolicyItemDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogPolicyItemDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogPolicyItemDto.java
index 00ba3f6..a077819 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogPolicyItemDto.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogPolicyItemDto.java
@@ -16,4 +16,10 @@ public class CatalogPolicyItemDto extends CatalogItemDtoAbstract<Policy,PolicySp
         return Policy.class;
     }
 
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Override
+    public Class<PolicySpec<?>> getSpecType() {
+        return (Class)PolicySpec.class;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/catalog/internal/CatalogTemplateItemDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogTemplateItemDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogTemplateItemDto.java
index e4016d9..76531e9 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogTemplateItemDto.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogTemplateItemDto.java
@@ -3,7 +3,7 @@ package brooklyn.catalog.internal;
 import brooklyn.entity.Application;
 import brooklyn.entity.proxying.EntitySpec;
 
-public class CatalogTemplateItemDto extends CatalogItemDtoAbstract<Application,EntitySpec<?>> {
+public class CatalogTemplateItemDto extends CatalogItemDtoAbstract<Application,EntitySpec<? extends Application>> {
 
     @Override
     public CatalogItemType getCatalogItemType() {
@@ -14,5 +14,11 @@ public class CatalogTemplateItemDto extends CatalogItemDtoAbstract<Application,E
     public Class<Application> getCatalogItemJavaType() {
         return Application.class;
     }
-    
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Override
+    public Class<EntitySpec<? extends Application>> getSpecType() {
+        return (Class)EntitySpec.class;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/entity/rebind/plane/dto/BasicManagementNodeSyncRecord.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/plane/dto/BasicManagementNodeSyncRecord.java b/core/src/main/java/brooklyn/entity/rebind/plane/dto/BasicManagementNodeSyncRecord.java
index e731f4b..2d9ea91 100644
--- a/core/src/main/java/brooklyn/entity/rebind/plane/dto/BasicManagementNodeSyncRecord.java
+++ b/core/src/main/java/brooklyn/entity/rebind/plane/dto/BasicManagementNodeSyncRecord.java
@@ -78,8 +78,14 @@ public class BasicManagementNodeSyncRecord implements ManagementNodeSyncRecord,
     private String nodeId;
     private URI uri;
     private ManagementNodeState status;
-    private long localTimestamp;
+    private Long localTimestamp;
     private Long remoteTimestamp;
+    
+    /** @deprecated since 0.7.0, use {@link #localTimestamp} or {@link #remoteTimestamp},
+     * but kept (or rather added back in) to support deserializing previous instances */
+    @Deprecated
+    private Long timestampUtc;
+
 
     // for de-serialization
     @SuppressWarnings("unused")
@@ -118,7 +124,9 @@ public class BasicManagementNodeSyncRecord implements ManagementNodeSyncRecord,
     
     @Override
     public long getLocalTimestamp() {
-        return localTimestamp;
+        if (localTimestamp!=null) return localTimestamp;
+        if (timestampUtc!=null) return timestampUtc;
+        throw new NullPointerException("localTimestamp not known for "+getNodeId());
     }
     
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/test/java/brooklyn/camp/lite/CampPlatformWithJustBrooklynMgmt.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/camp/lite/CampPlatformWithJustBrooklynMgmt.java b/core/src/test/java/brooklyn/camp/lite/CampPlatformWithJustBrooklynMgmt.java
new file mode 100644
index 0000000..89e6b2e
--- /dev/null
+++ b/core/src/test/java/brooklyn/camp/lite/CampPlatformWithJustBrooklynMgmt.java
@@ -0,0 +1,23 @@
+package brooklyn.camp.lite;
+
+import io.brooklyn.camp.BasicCampPlatform;
+import brooklyn.camp.brooklyn.api.HasBrooklynManagementContext;
+import brooklyn.config.BrooklynProperties;
+import brooklyn.config.BrooklynServerConfig;
+import brooklyn.management.ManagementContext;
+
+public class CampPlatformWithJustBrooklynMgmt extends BasicCampPlatform implements HasBrooklynManagementContext {
+
+    private ManagementContext mgmt;
+
+    public CampPlatformWithJustBrooklynMgmt(ManagementContext mgmt) {
+        this.mgmt = mgmt;
+        ((BrooklynProperties)mgmt.getConfig()).put(BrooklynServerConfig.CAMP_PLATFORM, this);
+    }
+    
+    @Override
+    public ManagementContext getBrooklynManagementContext() {
+        return mgmt;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java b/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
index 6a17c28..9bbadf7 100644
--- a/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
+++ b/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
@@ -1,12 +1,10 @@
 package brooklyn.camp.lite;
 
-import io.brooklyn.camp.BasicCampPlatform;
 import io.brooklyn.camp.spi.Assembly;
 import io.brooklyn.camp.spi.AssemblyTemplate;
 import io.brooklyn.camp.spi.pdp.PdpYamlTest;
 import io.brooklyn.camp.test.mock.web.MockWebPlatform;
 
-import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.Reader;
 import java.util.Map;
@@ -18,12 +16,17 @@ import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import brooklyn.catalog.CatalogItem;
+import brooklyn.catalog.CatalogPredicates;
 import brooklyn.entity.Entity;
+import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.management.internal.LocalManagementContext;
 import brooklyn.test.entity.LocalManagementContextForTests;
 import brooklyn.test.entity.TestApplication;
 import brooklyn.test.entity.TestEntity;
+import brooklyn.util.stream.Streams;
 
+import com.google.common.base.Predicates;
 import com.google.common.collect.Iterables;
 
 /** Tests of lightweight CAMP integration. Since the "real" integration is in brooklyn-camp project,
@@ -33,10 +36,12 @@ public class CampYamlLiteTest {
     private static final Logger log = LoggerFactory.getLogger(CampYamlLiteTest.class);
     
     protected LocalManagementContext mgmt;
+    protected CampPlatformWithJustBrooklynMgmt platform;
     
     @BeforeMethod(alwaysRun=true)
     public void setUp() {
-        mgmt = new LocalManagementContextForTests();        
+        mgmt = new LocalManagementContextForTests();
+        platform = new CampPlatformWithJustBrooklynMgmt(mgmt);
     }
     
     @AfterMethod(alwaysRun=true)
@@ -47,8 +52,9 @@ public class CampYamlLiteTest {
     /** based on {@link PdpYamlTest} for parsing,
      * then creating a {@link TestAppAssembly} */
     @Test
-    public void testYamlServiceMatchAndBrooklynInstantiate() throws IOException {
-        BasicCampPlatform platform = MockWebPlatform.populate(new BasicCampPlatform());
+    public void testYamlServiceMatchAndBrooklynInstantiate() throws Exception {
+        MockWebPlatform.populate(platform, TestAppAssemblyInstantiator.class);
+        
         Reader input = new InputStreamReader(getClass().getResourceAsStream("test-app-service-blueprint.yaml"));
         AssemblyTemplate at = platform.pdp().registerDeploymentPlan(input);
         log.info("AT is:\n"+at.toString());
@@ -56,7 +62,7 @@ public class CampYamlLiteTest {
         Assert.assertEquals(at.getPlatformComponentTemplates().links().size(), 1);
         
         // now use brooklyn to instantiate
-        Assembly assembly = new TestAppAssemblyInstantiator(mgmt).instantiate(at, platform);
+        Assembly assembly = at.getInstantiator().newInstance().instantiate(at, platform);
         
         TestApplication app = ((TestAppAssembly)assembly).getBrooklynApp();
         Assert.assertEquals( app.getConfig(TestEntity.CONF_NAME), "sample" );
@@ -71,5 +77,22 @@ public class CampYamlLiteTest {
         // desc ensures we got the information from the matcher, as this value is NOT in the yaml
         Assert.assertEquals( map.get("desc"), MockWebPlatform.APPSERVER.getDescription() );
     }
-    
+
+    @Test(groups="WIP")
+    public void testYamlServiceForCatalog() {
+        MockWebPlatform.populate(platform, TestAppAssemblyInstantiator.class);
+        
+        CatalogItem<?, ?> realItem = mgmt.getCatalog().addItem(Streams.readFullyString(getClass().getResourceAsStream("test-app-service-blueprint.yaml")));
+        Iterable<CatalogItem<Object, Object>> retrievedItems = mgmt.getCatalog().getCatalogItems(CatalogPredicates.registeredType(Predicates.equalTo("sample")));
+        
+        Assert.assertEquals(Iterables.size(retrievedItems), 1, "Wrong retrieved items: "+retrievedItems);
+        CatalogItem<Object, Object> retrievedItem = Iterables.getOnlyElement(retrievedItems);
+        Assert.assertEquals(retrievedItem, realItem);
+        
+        EntitySpec<?> spec1 = (EntitySpec<?>) mgmt.getCatalog().createSpec(retrievedItem);
+        Assert.assertNotNull(spec1);
+        Assert.assertEquals(spec1.getConfig().get(TestEntity.CONF_NAME), "sample");
+        
+        // TODO other assertions, about children
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/test/java/brooklyn/camp/lite/TestAppAssemblyInstantiator.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/camp/lite/TestAppAssemblyInstantiator.java b/core/src/test/java/brooklyn/camp/lite/TestAppAssemblyInstantiator.java
index a00a3bf..e8b7ff8 100644
--- a/core/src/test/java/brooklyn/camp/lite/TestAppAssemblyInstantiator.java
+++ b/core/src/test/java/brooklyn/camp/lite/TestAppAssemblyInstantiator.java
@@ -6,9 +6,11 @@ import io.brooklyn.camp.spi.AssemblyTemplate;
 import io.brooklyn.camp.spi.PlatformComponentTemplate;
 import io.brooklyn.camp.spi.collection.ResolvableLink;
 import io.brooklyn.camp.spi.instantiate.BasicAssemblyTemplateInstantiator;
+import brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator;
+import brooklyn.camp.brooklyn.api.HasBrooklynManagementContext;
 import brooklyn.entity.basic.ApplicationBuilder;
 import brooklyn.entity.proxying.EntitySpec;
-import brooklyn.management.internal.LocalManagementContext;
+import brooklyn.management.ManagementContext;
 import brooklyn.test.entity.TestApplication;
 import brooklyn.test.entity.TestEntity;
 import brooklyn.util.collections.MutableMap;
@@ -17,16 +19,20 @@ import brooklyn.util.collections.MutableMap;
  * all setting {@link TestEntity#CONF_NAME} for the name in the plan and in the service specs
  * <p>
  * the "real" instantiator for brooklyn is in brooklyn-camp project, not visible here, so let's have something we can test */
-public class TestAppAssemblyInstantiator extends BasicAssemblyTemplateInstantiator {
+public class TestAppAssemblyInstantiator extends BasicAssemblyTemplateInstantiator implements AssemblyTemplateSpecInstantiator {
 
-    protected final LocalManagementContext mgmt;
-    
-    public TestAppAssemblyInstantiator(LocalManagementContext mgmt) {
-        this.mgmt = mgmt;
-    }
-    
     @Override
     public Assembly instantiate(AssemblyTemplate template, CampPlatform platform) {
+        if (!(platform instanceof HasBrooklynManagementContext)) {
+            throw new IllegalStateException("Instantiator can only be used with CAMP platforms with a Brooklyn management context");
+        }
+        ManagementContext mgmt = ((HasBrooklynManagementContext)platform).getBrooklynManagementContext();
+        
+        // TODO when createSpec is working:
+//        TestApplication app = (TestApplication) mgmt.getEntityManager().createEntity( createSpec(template, platform) );
+//        mgmt.getEntityManager().manage(app);
+        
+        // workaround until above is reacy
         TestApplication app = ApplicationBuilder.newManagedApp(EntitySpec.create(TestApplication.class)
             .configure(TestEntity.CONF_NAME, template.getName())
             .configure(TestEntity.CONF_MAP_THING, MutableMap.of("type", template.getType(), "desc", template.getDescription()))
@@ -37,7 +43,25 @@ public class TestAppAssemblyInstantiator extends BasicAssemblyTemplateInstantiat
                 .configure(TestEntity.CONF_MAP_THING, MutableMap.of("type", t.resolve().getType(), "desc", t.resolve().getDescription()))
                 );
         }
+
         return new TestAppAssembly(app);
     }
 
+    @Override
+    public EntitySpec<?> createSpec(AssemblyTemplate template, CampPlatform platform) {
+        EntitySpec<TestApplication> app = EntitySpec.create(TestApplication.class)
+            .configure(TestEntity.CONF_NAME, template.getName())
+            .configure(TestEntity.CONF_MAP_THING, MutableMap.of("type", template.getType(), "desc", template.getDescription()));
+        
+        for (ResolvableLink<PlatformComponentTemplate> t: template.getPlatformComponentTemplates().links()) {
+            // TODO use EntitySpec.child(...)
+//            app.child(EntitySpec.create(TestEntity.class)
+//                .configure(TestEntity.CONF_NAME, t.getName())
+//                .configure(TestEntity.CONF_MAP_THING, MutableMap.of("type", t.resolve().getType(), "desc", t.resolve().getDescription()))
+//                );
+        }
+        
+        return app;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java b/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
index 51c60ee..1989cb2 100644
--- a/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
+++ b/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
@@ -11,6 +11,10 @@ import brooklyn.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
 import brooklyn.entity.basic.Entities;
 import brooklyn.management.internal.LocalManagementContext;
 import brooklyn.test.entity.LocalManagementContextForTests;
+import brooklyn.test.entity.TestApplication;
+import brooklyn.test.entity.TestEntity;
+import brooklyn.util.BrooklynMavenArtifacts;
+import brooklyn.util.maven.MavenRetriever;
 
 public class CatalogDtoTest {
 
@@ -31,28 +35,31 @@ public class CatalogDtoTest {
     @Test(groups="Integration")
     public void testCatalogLookup() {
         CatalogDto root = buildExampleCatalog();
-        checkHadoopsExample(root);
+        checkCatalogHealthy(root);
     }
     
     @Test(groups="Integration")
     public void testCatalogSerializeAndLookup() {
         CatalogDto root = buildExampleCatalog();
-        CatalogXmlSerializer seriailizer = new CatalogXmlSerializer();
+        CatalogXmlSerializer serializer = new CatalogXmlSerializer();
         
-        String xml = seriailizer.toString(root);
-        log.info("Hadoops example catalog serialized as:\n"+xml);
+        String xml = serializer.toString(root);
+        log.info("Example catalog serialized as:\n"+xml);
         
-        CatalogDto root2 = (CatalogDto) seriailizer.fromString(xml);
-        checkHadoopsExample(root2);
+        CatalogDto root2 = (CatalogDto) serializer.fromString(xml);
+        checkCatalogHealthy(root2);
     }
 
-    protected void checkHadoopsExample(CatalogDto root) {
-        Assert.assertEquals(root.catalogs.size(), 5);
+    protected void checkCatalogHealthy(CatalogDto root) {
+        Assert.assertEquals(root.catalogs.size(), 4);
         CatalogDo loader = new CatalogDo(root).load(managementContext, null);
         
-        CatalogItemDo<?,?> worker = loader.getCache().get("io.brooklyn.mapr.m3.WorkerNode");
+        // test app comes from jar, by default
+        CatalogItemDo<?,?> worker = loader.getCache().get(TestApplication.class.getCanonicalName());
         Assert.assertNotNull(worker);
-        Assert.assertEquals(worker.getName(), "M3 Worker Node");
+        Assert.assertEquals(worker.getName(), "Test App from JAR");
+        
+        // TODO can test scanned elements, links to other catalogs, etc
     }
 
     public static CatalogDto buildExampleCatalog() {
@@ -61,39 +68,30 @@ public class CatalogDtoTest {
         		"intended partly as a teaching example for what can be expressed, and how"));
         root.setClasspathScanForEntities(CatalogScanningModes.NONE);
         
-        CatalogDo m3Catalog = new CatalogDo(CatalogDto.newNamedInstance("MapR M3", null));
-        m3Catalog.addToClasspath("file://~/.m2/repository/io/cloudsoft/brooklyn-mapr/1.0.0-SNAPSHOT/brooklyn-mapr.jar");
-        m3Catalog.addEntry(CatalogItemDtoAbstract.newTemplate(
-                "io.brooklyn.mapr.M3App", "M3 Application"));
-        m3Catalog.addEntry(CatalogItemDtoAbstract.newEntity(
-                "io.brooklyn.mapr.m3.ZookeperWorkerNode", "M3 Zookeeper+Worker Node"));
-        m3Catalog.addEntry(CatalogItemDtoAbstract.newEntity(
-                "io.brooklyn.mapr.m3.WorkerNode", "M3 Worker Node"));
-        root.addCatalog(m3Catalog.dto);
-        
-        CatalogDo cdhCatalog = new CatalogDo(CatalogDto.newNamedInstance("Cloudera", 
-                "CDH catalog, pointing to JARs as I have them installed on my machine already, "+
-                "tweaked for my preferences (overriding templates scanned from these JARs)"));
-        cdhCatalog.setClasspathScanForEntities(CatalogScanningModes.ANNOTATIONS);
-        cdhCatalog.addToClasspath(
-                "file://~/.m2/repository/io/cloudsoft/brooklyn-cdh/1.0.0-SNAPSHOT/brooklyn-cdh.jar",
-                "file://~/.m2/repository/io/cloudsoft/brooklyn-cdh/1.0.0-SNAPSHOT/whirr-cm.jar");
-        cdhCatalog.addEntry(CatalogItemDtoAbstract.newTemplate(
-                "io.brooklyn.cloudera.ClouderaForHadoopWithManager",
-                "RECOMMENDED: CDH Hadoop Application with Cloudera Manager"));
-        root.addCatalog(cdhCatalog.dto);
+        CatalogDo testEntitiesJavaCatalog = new CatalogDo(CatalogDto.newNamedInstance("Test Entities from Java", null));
+        testEntitiesJavaCatalog.setClasspathScanForEntities(CatalogScanningModes.NONE);
+        testEntitiesJavaCatalog.addToClasspath(MavenRetriever.localUrl(BrooklynMavenArtifacts.artifact("", "brooklyn-core", "jar", "tests")));
+        testEntitiesJavaCatalog.addEntry(CatalogItemDtoAbstract.newTemplateFromJava(
+                TestApplication.class.getCanonicalName(), "Test App from JAR"));
+        testEntitiesJavaCatalog.addEntry(CatalogItemDtoAbstract.newEntityFromJava(
+                TestEntity.class.getCanonicalName(), "Test Entity from JAR"));
+        root.addCatalog(testEntitiesJavaCatalog.dto);
 
-        CatalogDo osgiCatalog = new CatalogDo(CatalogDto.newNamedInstance("OSGi",
+        CatalogDo testEntitiesJavaCatalogScanning = new CatalogDo(CatalogDto.newNamedInstance("Test Entities from Java Scanning", null));
+        testEntitiesJavaCatalogScanning.addToClasspath(MavenRetriever.localUrl(BrooklynMavenArtifacts.artifact("", "brooklyn-core", "jar", "tests")));
+        testEntitiesJavaCatalogScanning.setClasspathScanForEntities(CatalogScanningModes.ANNOTATIONS);
+        root.addCatalog(testEntitiesJavaCatalogScanning.dto);
+        
+        CatalogDo osgiCatalog = new CatalogDo(CatalogDto.newNamedInstance("Test Entities from OSGi",
                 "A catalog whose entries define their libraries as a list of OSGi bundles"));
         osgiCatalog.setClasspathScanForEntities(CatalogScanningModes.NONE);
-        CatalogLibrariesDto m3Context = new CatalogLibrariesDto();
-        m3Context.addBundle("file://~/.m2/repository/io/cloudsoft/brooklyn-mapr/1.0.0-SNAPSHOT/brooklyn-mapr.jar");
-        osgiCatalog.addEntry(CatalogItemDtoAbstract.newTemplate("M3App", "io.brooklyn.mapr.M3App", "M3 Application",
-                "Description", m3Context));
+        CatalogEntityItemDto osgiEntity = CatalogItemDtoAbstract.newEntityFromJava(TestEntity.class.getCanonicalName(), "Test Entity from OSGi");
+        // NB: this is not actually an OSGi bundle, but it's okay as we don't instantiate the bundles ahead of time (currently)
+        osgiEntity.libraries.addBundle(MavenRetriever.localUrl(BrooklynMavenArtifacts.artifact("", "brooklyn-core", "jar", "tests")));
+        testEntitiesJavaCatalog.addEntry(osgiEntity);
         root.addCatalog(osgiCatalog.dto);
 
-        root.addCatalog(CatalogDto.newLinkedInstance("http://cloudsoftcorp.com/amp-brooklyn-catalog.xml"));
-        root.addCatalog(CatalogDto.newLinkedInstance("http://microsoot.com/oofice-catalog.xml"));
+        root.addCatalog(CatalogDto.newLinkedInstance("classpath://brooklyn-catalog-empty.xml"));
         return root.dto;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/BrooklynCampPlatform.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/BrooklynCampPlatform.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/BrooklynCampPlatform.java
index f0f2b9d..32102ee 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/BrooklynCampPlatform.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/BrooklynCampPlatform.java
@@ -5,8 +5,8 @@ import io.brooklyn.camp.CampPlatform;
 import io.brooklyn.camp.brooklyn.spi.creation.BrooklynEntityMatcher;
 import io.brooklyn.camp.brooklyn.spi.dsl.BrooklynDslInterpreter;
 import io.brooklyn.camp.brooklyn.spi.platform.BrooklynImmutableCampPlatform;
-import io.brooklyn.camp.brooklyn.spi.platform.HasBrooklynManagementContext;
 import io.brooklyn.camp.spi.PlatformRootSummary;
+import brooklyn.camp.brooklyn.api.HasBrooklynManagementContext;
 import brooklyn.config.BrooklynProperties;
 import brooklyn.management.ManagementContext;
 import brooklyn.management.ManagementContext.PropertiesReloadListener;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/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 2652c59..fbdd5ec 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
@@ -1,12 +1,10 @@
 package io.brooklyn.camp.brooklyn.spi.creation;
 
 import io.brooklyn.camp.CampPlatform;
-import io.brooklyn.camp.brooklyn.spi.platform.HasBrooklynManagementContext;
 import io.brooklyn.camp.spi.Assembly;
 import io.brooklyn.camp.spi.AssemblyTemplate;
 import io.brooklyn.camp.spi.PlatformComponentTemplate;
 import io.brooklyn.camp.spi.collection.ResolvableLink;
-import io.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
 
 import java.lang.reflect.Constructor;
 import java.util.LinkedHashMap;
@@ -17,6 +15,8 @@ import java.util.Map.Entry;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator;
+import brooklyn.camp.brooklyn.api.HasBrooklynManagementContext;
 import brooklyn.catalog.BrooklynCatalog;
 import brooklyn.catalog.CatalogItem;
 import brooklyn.config.ConfigKey;
@@ -44,7 +44,7 @@ import brooklyn.util.text.Strings;
 
 import com.google.common.collect.Maps;
 
-public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateInstantiator {
+public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpecInstantiator {
 
     private static final Logger log = LoggerFactory.getLogger(BrooklynAssemblyTemplateInstantiator.class);
     
@@ -76,6 +76,11 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateIns
         }
     }
 
+    public EntitySpec<?> createSpec(AssemblyTemplate template, CampPlatform platform) {
+        // TODO rewrite this class so everything below returns a spec, then rewrite above just to instantiate (and start?) the spec
+        throw new UnsupportedOperationException();
+    }
+    
     protected Application createApplicationFromCatalog(CampPlatform platform, CatalogItem<?,?> item, AssemblyTemplate template) {
         ManagementContext mgmt = getBrooklynManagementContext(platform);
 
@@ -112,9 +117,7 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateIns
                 appBuilder.configure( convertFlagsToKeys(appBuilder.getType(), configO) );
                 instance = appBuilder.manage(mgmt);
                 
-                List<Location> locations = new BrooklynYamlLocationResolver(mgmt).resolveLocations(template.getCustomAttributes(), false);
-                if (locations!=null)
-                    ((EntityInternal)instance).addLocations(locations);
+                applyLocations(mgmt, template, instance);
                 
             } else if (Application.class.isAssignableFrom(clazz)) {
                 // TODO use resolver's configureEntitySpec instead
@@ -126,9 +129,7 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateIns
                 log.info("CAMP placing '{}' under management", instance);
                 Entities.startManagement(instance, mgmt);
                 
-                List<Location> locations = new BrooklynYamlLocationResolver(mgmt).resolveLocations(template.getCustomAttributes(), false);
-                if (locations!=null)
-                    ((EntityInternal)instance).addLocations(locations);
+                applyLocations(mgmt, template, instance);
                 
             } else {
                 throw new IllegalArgumentException("Class "+clazz+" must extend one of ApplicationBuilder or Application");
@@ -142,6 +143,12 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateIns
         }
     }
 
+    private void applyLocations(ManagementContext mgmt, AssemblyTemplate template, final Application instance) {
+        List<Location> locations = new BrooklynYamlLocationResolver(mgmt).resolveLocations(template.getCustomAttributes(), false);
+        if (locations!=null)
+            ((EntityInternal)instance).addLocations(locations);
+    }
+
     private ManagementContext getBrooklynManagementContext(CampPlatform platform) {
         return ((HasBrooklynManagementContext)platform).getBrooklynManagementContext();
     }
@@ -216,6 +223,13 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateIns
 
         Map<Entity, EntitySpec<?>> rootEntities = Maps.newLinkedHashMap();
         Map<Entity, EntitySpec<?>> allEntities = Maps.newLinkedHashMap();
+        /* FIXME there is a subtlety here, and tests failing;
+         * OT1H we might not want/need the wrapper application if we are creating a single one,   
+         * but OTOH we might need a guarantee of an app at root, if we are creating certain nested entities
+         * 
+         * i (alex) think the solution is to use the new createSpec(...) and interrogate it
+         * to see if we need the wrapper or not
+         */
         buildEntities(template, rootEntities, allEntities, mgmt);
         
         EntitySpec<StartableApplication> appSpec;
@@ -230,11 +244,12 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateIns
             Entry<Entity, EntitySpec<?>> entry = rootEntities.entrySet().iterator().next();
             app = (StartableApplication)entry.getKey();
             appSpec = (EntitySpec<StartableApplication>)entry.getValue();
+            applyLocations(mgmt, template, app);
         }
         
         initEntities(mgmt, allEntities);
         
-        log.info("CAMP placing '{}' under management", appSpec);
+        log.info("CAMP placing '{}' under`` management", appSpec);
         Entities.startManagement(app, mgmt);
 
         return app;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/platform/BrooklynImmutableCampPlatform.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/platform/BrooklynImmutableCampPlatform.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/platform/BrooklynImmutableCampPlatform.java
index e52327f..8ddcdda 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/platform/BrooklynImmutableCampPlatform.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/platform/BrooklynImmutableCampPlatform.java
@@ -16,6 +16,7 @@ import io.brooklyn.camp.spi.PlatformTransaction;
 import io.brooklyn.camp.spi.collection.BasicResourceLookup;
 import io.brooklyn.camp.spi.collection.ResourceLookup;
 import io.brooklyn.camp.spi.collection.ResourceLookup.EmptyResourceLookup;
+import brooklyn.camp.brooklyn.api.HasBrooklynManagementContext;
 import brooklyn.management.ManagementContext;
 
 /** Immutable CAMP platform which reflects things in the underlying Brooklyn system */

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/platform/HasBrooklynManagementContext.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/platform/HasBrooklynManagementContext.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/platform/HasBrooklynManagementContext.java
deleted file mode 100644
index a91a32a..0000000
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/platform/HasBrooklynManagementContext.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package io.brooklyn.camp.brooklyn.spi.platform;
-
-import brooklyn.management.ManagementContext;
-
-public interface HasBrooklynManagementContext {
-
-    public ManagementContext getBrooklynManagementContext();
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/EmptySoftwareProcessYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/EmptySoftwareProcessYamlTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/EmptySoftwareProcessYamlTest.java
index f5bea03..c4703e8 100644
--- a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/EmptySoftwareProcessYamlTest.java
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/EmptySoftwareProcessYamlTest.java
@@ -55,14 +55,14 @@ public class EmptySoftwareProcessYamlTest extends AbstractYamlTest {
 
     @Test
     // for issue #1377
-    // currently provisions in the loopback-on-app location, rather surprisingly;
-    // but not sure that's the desired behaviour
     public void testWithAppAndEntityLocations() throws Exception {
         Entity app = createAndStartApplication(Streams.newReaderWithContents("services:\n"+
             "- serviceType: "+EmptySoftwareProcess.class.getName()+"\n"+
             "  location: localhost:(name=localhost on entity)"+"\n"+
             "location: byon:(hosts=\"127.0.0.1\", name=loopback on app)"));
         waitForApplicationTasks(app);
+        Entities.dumpInfo(app);
+        
         Assert.assertEquals(app.getLocations().size(), 1);
         Assert.assertEquals(app.getChildren().size(), 1);
         Entity entity = app.getChildren().iterator().next();
@@ -75,6 +75,7 @@ public class EmptySoftwareProcessYamlTest extends AbstractYamlTest {
         Assert.assertEquals(entityLocationIterator.next().getDisplayName(), "localhost on entity");
         Location actualMachine = entityLocationIterator.next();
         Assert.assertTrue(actualMachine instanceof SshMachineLocation, "wrong location: "+actualMachine);
+        // TODO this, below, probably should be 'localhost on entity', see #1377
         Assert.assertEquals(actualMachine.getParent().getDisplayName(), "loopback on app");
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/usage/cli/src/main/java/brooklyn/cli/Main.java
----------------------------------------------------------------------
diff --git a/usage/cli/src/main/java/brooklyn/cli/Main.java b/usage/cli/src/main/java/brooklyn/cli/Main.java
index 339c0fe..0a0e67b 100644
--- a/usage/cli/src/main/java/brooklyn/cli/Main.java
+++ b/usage/cli/src/main/java/brooklyn/cli/Main.java
@@ -402,7 +402,13 @@ public class Main {
             BrooklynServerDetails server = launcher.getServerDetails();
             ManagementContext ctx = server.getManagementContext();
             
-            populateCatalog(launcher.getServerDetails().getManagementContext().getCatalog());
+            try {
+                populateCatalog(launcher.getServerDetails().getManagementContext().getCatalog());
+            } catch (Exception e) {
+                Exceptions.propagateIfFatal(e);
+                // don't fail to start just because catalog is not available
+                log.error("Error populating catalog: "+e, e);
+            }
 
             if (verbose) {
                 Entities.dumpInfo(launcher.getApplications());

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
index 8fba37b..9e8c01a 100644
--- a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
+++ b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
@@ -32,6 +32,7 @@ import brooklyn.entity.Application;
 import brooklyn.entity.basic.ApplicationBuilder;
 import brooklyn.entity.basic.BrooklynShutdownHooks;
 import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityInternal;
 import brooklyn.entity.basic.StartableApplication;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.entity.rebind.RebindManager;
@@ -628,9 +629,8 @@ public class BrooklynLauncher {
     }
 
     protected Application getAppFromYaml(String input) {
-        AssemblyTemplate at = campPlatform.pdp()
-                .registerDeploymentPlan(new StringReader(input));
-         BrooklynAssemblyTemplateInstantiator instantiator;
+        AssemblyTemplate at = campPlatform.pdp().registerDeploymentPlan(new StringReader(input));
+        BrooklynAssemblyTemplateInstantiator instantiator;
         try {
             AssemblyTemplateInstantiator ati = at.getInstantiator().newInstance();
             if (ati instanceof BrooklynAssemblyTemplateInstantiator) {
@@ -641,7 +641,9 @@ public class BrooklynLauncher {
         } catch (Exception e) {
             throw Exceptions.propagate(e);
         }
-        return instantiator.create(at, campPlatform);
+        Application app = instantiator.create(at, campPlatform);
+//        ((EntityInternal)app).addLocations(XXX);
+        return app;
     }
     
     protected void startApps() {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/usage/rest-server/src/main/java/brooklyn/rest/resources/AbstractBrooklynRestResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/resources/AbstractBrooklynRestResource.java b/usage/rest-server/src/main/java/brooklyn/rest/resources/AbstractBrooklynRestResource.java
index 2b8151b..6dc15ad 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/resources/AbstractBrooklynRestResource.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/resources/AbstractBrooklynRestResource.java
@@ -8,6 +8,7 @@ import javax.ws.rs.core.Context;
 
 import org.codehaus.jackson.map.ObjectMapper;
 
+import brooklyn.config.BrooklynServerConfig;
 import brooklyn.config.BrooklynServiceAttributes;
 import brooklyn.management.ManagementContext;
 import brooklyn.rest.util.BrooklynRestResourceUtils;
@@ -63,9 +64,7 @@ public abstract class AbstractBrooklynRestResource {
     }
 
     protected CampPlatform camp() {
-        CampPlatform camp = mgmt().getConfig().getConfig(BrooklynCampConstants.CAMP_PLATFORM);
-        if (camp!=null) return camp;
-        throw new IllegalStateException("CAMP platform server not enabled");
+        return BrooklynServerConfig.getCampPlatform(mgmt()).get();
     }
     
 }


[02/45] import of brooklyncentral/camp-server dependency to apache brooklyn project

Posted by he...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/dto/PlatformDto.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/dto/PlatformDto.java b/camp/camp-server/src/main/java/io/brooklyn/camp/dto/PlatformDto.java
new file mode 100644
index 0000000..f86fd05
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/dto/PlatformDto.java
@@ -0,0 +1,113 @@
+package io.brooklyn.camp.dto;
+
+import io.brooklyn.camp.rest.resource.ApidocRestResource;
+import io.brooklyn.camp.rest.util.DtoFactory;
+import io.brooklyn.camp.spi.ApplicationComponent;
+import io.brooklyn.camp.spi.ApplicationComponentTemplate;
+import io.brooklyn.camp.spi.Assembly;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+import io.brooklyn.camp.spi.Link;
+import io.brooklyn.camp.spi.PlatformComponent;
+import io.brooklyn.camp.spi.PlatformComponentTemplate;
+import io.brooklyn.camp.spi.PlatformRootSummary;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+
+public class PlatformDto extends ResourceDto {
+
+    // defined as a constant so can be used in Swagger REST API annotations
+    public static final String CLASS_NAME = "io.brooklyn.camp.dto.PlatformDto";
+    static { assert CLASS_NAME.equals(PlatformDto.class.getCanonicalName()); }
+
+    protected PlatformDto() {}
+    protected PlatformDto(DtoFactory dtoFactory, PlatformRootSummary x) {
+        super(dtoFactory, x);
+        platformComponentTemplates = new ArrayList<LinkDto>();
+        for (Link<PlatformComponentTemplate> t: dtoFactory.getPlatform().platformComponentTemplates().links()) {
+            platformComponentTemplates.add(LinkDto.newInstance(dtoFactory, PlatformComponentTemplate.class, t));
+        }
+        
+        applicationComponentTemplates = new ArrayList<LinkDto>();
+        for (Link<ApplicationComponentTemplate> t: dtoFactory.getPlatform().applicationComponentTemplates().links()) {
+            applicationComponentTemplates.add(LinkDto.newInstance(dtoFactory, ApplicationComponentTemplate.class, t));
+        }
+
+        assemblyTemplates = new ArrayList<LinkDto>();
+        for (Link<AssemblyTemplate> t: dtoFactory.getPlatform().assemblyTemplates().links()) {
+            assemblyTemplates.add(LinkDto.newInstance(dtoFactory, AssemblyTemplate.class, t));
+        }
+
+        platformComponents = new ArrayList<LinkDto>();
+        for (Link<PlatformComponent> t: dtoFactory.getPlatform().platformComponents().links()) {
+            platformComponents.add(LinkDto.newInstance(dtoFactory, PlatformComponent.class, t));
+        }
+        
+        applicationComponents = new ArrayList<LinkDto>();
+        for (Link<ApplicationComponent> t: dtoFactory.getPlatform().applicationComponents().links()) {
+            applicationComponents.add(LinkDto.newInstance(dtoFactory, ApplicationComponent.class, t));
+        }
+
+        assemblies = new ArrayList<LinkDto>();
+        for (Link<Assembly> t: dtoFactory.getPlatform().assemblies().links()) {
+            assemblies.add(LinkDto.newInstance(dtoFactory, Assembly.class, t));
+        }
+
+        // TODO set custom fields
+
+        apidoc = LinkDto.newInstance(
+                dtoFactory.getUriFactory().uriOfRestResource(ApidocRestResource.class),
+                "API documentation");
+    }
+
+    // TODO add custom fields
+    private List<LinkDto> assemblyTemplates;
+    private List<LinkDto> platformComponentTemplates;
+    private List<LinkDto> applicationComponentTemplates;
+    private List<LinkDto> assemblies;
+    private List<LinkDto> platformComponents;
+    private List<LinkDto> applicationComponents;
+    
+    // non-CAMP, but useful
+    private LinkDto apidoc;
+    
+    public List<LinkDto> getAssemblyTemplates() {
+        return assemblyTemplates;
+    }
+    
+    public List<LinkDto> getPlatformComponentTemplates() {
+        return platformComponentTemplates;
+    }
+    
+    public List<LinkDto> getApplicationComponentTemplates() {
+        return applicationComponentTemplates;
+    }
+    
+    public List<LinkDto> getAssemblies() {
+        return assemblies;
+    }
+    
+    @JsonInclude(Include.NON_EMPTY)
+    public List<LinkDto> getPlatformComponents() {
+        return platformComponents;
+    }
+    
+    @JsonInclude(Include.NON_EMPTY)
+    public List<LinkDto> getApplicationComponents() {
+        return applicationComponents;
+    }
+    
+    public LinkDto getApidoc() {
+        return apidoc;
+    }
+    
+    // --- building ---
+
+    public static PlatformDto newInstance(DtoFactory dtoFactory, PlatformRootSummary x) {
+        return new PlatformDto(dtoFactory, x);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/dto/ResourceDto.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/dto/ResourceDto.java b/camp/camp-server/src/main/java/io/brooklyn/camp/dto/ResourceDto.java
new file mode 100644
index 0000000..93caaf1
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/dto/ResourceDto.java
@@ -0,0 +1,94 @@
+package io.brooklyn.camp.dto;
+
+import io.brooklyn.camp.commontypes.RepresentationSkew;
+import io.brooklyn.camp.rest.util.DtoFactory;
+import io.brooklyn.camp.spi.AbstractResource;
+
+import java.util.Date;
+import java.util.List;
+
+import brooklyn.util.time.Time;
+
+import com.fasterxml.jackson.annotation.JsonGetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonSetter;
+import com.fasterxml.jackson.databind.util.ISO8601Utils;
+
+public class ResourceDto extends DtoCustomAttributes {
+
+    protected ResourceDto() {}
+    protected ResourceDto(DtoFactory dtoFactory, AbstractResource x) {
+        type = x.getType();
+        name = x.getName();
+
+        description = x.getDescription();
+        setCreated(x.getCreated());
+        tags = x.getTags();
+        representationSkew = x.getRepresentationSkew();
+        
+        if (x.getCustomAttributes()!=null && !x.getCustomAttributes().isEmpty())
+            newInstanceCustomAttributes(x.getCustomAttributes());
+        
+        uri = dtoFactory.uri(x);
+    }
+    
+    private String uri;
+    private String type;
+    
+    private String name;
+    private String description;
+    private Date created;
+    private List<String> tags;
+    private RepresentationSkew representationSkew;
+
+    public String getUri() {
+        return uri;
+    }
+    
+    public String getName() {
+        return name;
+    }
+    
+    @JsonInclude(Include.NON_NULL)
+    public String getDescription() {
+        return description;
+    }
+    
+    @JsonGetter("created")
+    public String getCreatedAsString() {
+        return created==null ? null : ISO8601Utils.format(created);
+    }
+    
+    @JsonSetter
+    private void setCreated(Date created) {
+        this.created = Time.dropMilliseconds(created);
+    }
+
+    @JsonIgnore
+    public Date getCreated() {
+        return created;
+    }
+    
+    @JsonInclude(Include.NON_EMPTY)
+    public List<String> getTags() {
+        return tags;
+    }
+    
+    public String getType() {
+        return type;
+    }
+    
+    @JsonInclude(Include.NON_NULL)
+    public RepresentationSkew getRepresentationSkew() {
+        return representationSkew;
+    }
+
+    // --- building ---
+
+    public static ResourceDto newInstance(DtoFactory dtoFactory, AbstractResource x) {
+        return new ResourceDto(dtoFactory, x);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/AbstractCampRestResource.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/AbstractCampRestResource.java b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/AbstractCampRestResource.java
new file mode 100644
index 0000000..735ac39
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/AbstractCampRestResource.java
@@ -0,0 +1,38 @@
+package io.brooklyn.camp.rest.resource;
+
+import io.brooklyn.camp.CampPlatform;
+import io.brooklyn.camp.rest.util.CampRestContext;
+import io.brooklyn.camp.rest.util.DtoFactory;
+import io.brooklyn.camp.rest.util.WebResourceUtils;
+import io.brooklyn.camp.spi.AbstractResource;
+import io.brooklyn.camp.spi.collection.ResourceLookup;
+
+import javax.servlet.ServletContext;
+import javax.ws.rs.core.Context;
+
+public abstract class AbstractCampRestResource {
+
+    // can be injected by jersey when not injected manually
+    // (seems there is no way to make this optional so note it _must_ be injected; if needed
+    // see notes on workarounds for test frameworks in original AbstractBrooklynRestResource)
+    @Context ServletContext servletContext;
+    
+    private CampRestContext campRestContext;
+    
+    public synchronized CampRestContext context() {
+        if (campRestContext!=null) return campRestContext;
+        campRestContext = new CampRestContext(servletContext);
+        return campRestContext;
+    }
+    
+    public CampPlatform camp() { return context().camp(); }
+    public DtoFactory dto() { return context().dto(); }
+
+    public static <T extends AbstractResource> T lookup(ResourceLookup<T> list, String id) {
+        T result = list.get(id);
+        if (result==null)
+            throw WebResourceUtils.notFound("No such element: %s", id);
+        return result;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/ApidocRestResource.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/ApidocRestResource.java b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/ApidocRestResource.java
new file mode 100644
index 0000000..53b3311
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/ApidocRestResource.java
@@ -0,0 +1,13 @@
+package io.brooklyn.camp.rest.resource;
+
+import javax.ws.rs.Path;
+
+import brooklyn.rest.apidoc.Apidoc;
+
+@Path(ApidocRestResource.API_URI_PATH)
+@Apidoc("Web API Documentation")
+public class ApidocRestResource extends brooklyn.rest.apidoc.ApidocResource {
+
+    public static final String API_URI_PATH = PlatformRestResource.CAMP_URI_PATH + "/apidoc";
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/ApplicationComponentRestResource.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/ApplicationComponentRestResource.java b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/ApplicationComponentRestResource.java
new file mode 100644
index 0000000..7f100fc
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/ApplicationComponentRestResource.java
@@ -0,0 +1,32 @@
+package io.brooklyn.camp.rest.resource;
+
+import io.brooklyn.camp.dto.ApplicationComponentDto;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+
+import brooklyn.rest.apidoc.Apidoc;
+
+import com.wordnik.swagger.core.ApiOperation;
+import com.wordnik.swagger.core.ApiParam;
+
+@Path(ApplicationComponentRestResource.URI_PATH)
+@Apidoc("Application Component resources")
+@Produces("application/json")
+public class ApplicationComponentRestResource extends AbstractCampRestResource {
+
+    public static final String URI_PATH = PlatformRestResource.CAMP_URI_PATH + "/application-components";
+
+    @Path("/{id}")
+    @ApiOperation(value = "Get a specific application component",
+        responseClass = ApplicationComponentDto.CLASS_NAME)
+    @GET
+    public ApplicationComponentDto get(
+            @ApiParam(value = "ID of item being retrieved", required = true)
+            @PathParam("id") String id) {
+        return dto().adapt(lookup(camp().applicationComponents(), id));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/ApplicationComponentTemplateRestResource.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/ApplicationComponentTemplateRestResource.java b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/ApplicationComponentTemplateRestResource.java
new file mode 100644
index 0000000..1ab5e19
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/ApplicationComponentTemplateRestResource.java
@@ -0,0 +1,32 @@
+package io.brooklyn.camp.rest.resource;
+
+import io.brooklyn.camp.dto.ApplicationComponentTemplateDto;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+
+import brooklyn.rest.apidoc.Apidoc;
+
+import com.wordnik.swagger.core.ApiOperation;
+import com.wordnik.swagger.core.ApiParam;
+
+@Path(ApplicationComponentTemplateRestResource.URI_PATH)
+@Apidoc("Application Component Template resources")
+@Produces("application/json")
+public class ApplicationComponentTemplateRestResource extends AbstractCampRestResource {
+
+    public static final String URI_PATH = PlatformRestResource.CAMP_URI_PATH + "/application-component-templates";
+
+    @Path("/{id}")
+    @ApiOperation(value = "Get a specific application component template",
+        responseClass = ApplicationComponentTemplateDto.CLASS_NAME)
+    @GET
+    public ApplicationComponentTemplateDto get(
+            @ApiParam(value = "ID of item being retrieved", required = true)
+            @PathParam("id") String id) {
+        return dto().adapt(lookup(camp().applicationComponentTemplates(), id));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/AssemblyRestResource.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/AssemblyRestResource.java b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/AssemblyRestResource.java
new file mode 100644
index 0000000..c04c29b
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/AssemblyRestResource.java
@@ -0,0 +1,34 @@
+package io.brooklyn.camp.rest.resource;
+
+import io.brooklyn.camp.dto.AssemblyDto;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+
+import brooklyn.rest.apidoc.Apidoc;
+
+import com.wordnik.swagger.core.ApiOperation;
+import com.wordnik.swagger.core.ApiParam;
+
+@Path(AssemblyRestResource.URI_PATH)
+@Apidoc("Assembly resources")
+@Produces("application/json")
+public class AssemblyRestResource extends AbstractCampRestResource {
+
+//    private static final Logger log = LoggerFactory.getLogger(AssemblyRestResource.class);
+    
+    public static final String URI_PATH = PlatformRestResource.CAMP_URI_PATH + "/assemblies";
+
+    @Path("/{id}")
+    @ApiOperation(value = "Get a specific assembly",
+            responseClass = AssemblyDto.CLASS_NAME)
+    @GET
+    public AssemblyDto get(
+            @ApiParam(value = "ID of item being retrieved", required = true)
+            @PathParam("id") String id) {
+        return dto().adapt(lookup(camp().assemblies(), id));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/AssemblyTemplateRestResource.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/AssemblyTemplateRestResource.java b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/AssemblyTemplateRestResource.java
new file mode 100644
index 0000000..ce78e0f
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/AssemblyTemplateRestResource.java
@@ -0,0 +1,70 @@
+package io.brooklyn.camp.rest.resource;
+
+import io.brooklyn.camp.dto.AssemblyTemplateDto;
+import io.brooklyn.camp.spi.Assembly;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+
+import java.net.URI;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.rest.apidoc.Apidoc;
+import brooklyn.util.exceptions.Exceptions;
+
+import com.wordnik.swagger.core.ApiOperation;
+import com.wordnik.swagger.core.ApiParam;
+
+@Path(AssemblyTemplateRestResource.URI_PATH)
+@Apidoc("Assembly Template resources")
+@Produces("application/json")
+public class AssemblyTemplateRestResource extends AbstractCampRestResource {
+
+    private static final Logger log = LoggerFactory.getLogger(AssemblyTemplateRestResource.class);
+    
+    public static final String URI_PATH = PlatformRestResource.CAMP_URI_PATH + "/assembly-templates";
+
+    @Path("/{id}")
+    @ApiOperation(value = "Get a specific assembly template",
+            responseClass = AssemblyTemplateDto.CLASS_NAME)
+    @GET
+    public AssemblyTemplateDto get(
+            @ApiParam(value = "ID of item being retrieved", required = true)
+            @PathParam("id") String id) {
+        return dto().adapt(lookup(camp().assemblyTemplates(), id));
+    }
+
+    @Path("/{id}")
+    @ApiOperation(value = "Instantiate a specific assembly template"
+    // TODO AssemblyDto, or location thereto?
+//            , responseClass = AssemblyTemplateDto.CLASS_NAME
+            )
+    @POST
+    public Response post(
+            @Context UriInfo info,
+            @ApiParam(value = "ID of item being retrieved", required = true)
+            @PathParam("id") String id) {
+        try {
+            log.info("CAMP REST instantiating AT "+id);
+            AssemblyTemplate at = lookup(camp().assemblyTemplates(), id);
+            Assembly assembly = at.getInstantiator().newInstance().instantiate(at, camp());
+            // see http://stackoverflow.com/questions/13702481/javax-response-prepends-method-path-when-setting-location-header-path-on-status
+            // for why we have to return absolute path
+            URI assemblyUri = info.getBaseUriBuilder().path( dto().adapt(assembly).getUri() ).build();
+            return Response.created(assemblyUri).build();
+        } catch (Exception e) {
+            log.error("Unable to create AT "+id+": "+e);
+            throw Exceptions.propagate(e);
+        }
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/PlatformComponentRestResource.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/PlatformComponentRestResource.java b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/PlatformComponentRestResource.java
new file mode 100644
index 0000000..e5b6f98
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/PlatformComponentRestResource.java
@@ -0,0 +1,32 @@
+package io.brooklyn.camp.rest.resource;
+
+import io.brooklyn.camp.dto.PlatformComponentDto;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+
+import brooklyn.rest.apidoc.Apidoc;
+
+import com.wordnik.swagger.core.ApiOperation;
+import com.wordnik.swagger.core.ApiParam;
+
+@Path(PlatformComponentRestResource.URI_PATH)
+@Apidoc("Platform Component resources")
+@Produces("application/json")
+public class PlatformComponentRestResource extends AbstractCampRestResource {
+
+    public static final String URI_PATH = PlatformRestResource.CAMP_URI_PATH + "/platform-components";
+
+    @Path("/{id}")
+    @ApiOperation(value = "Get a specific platform component",
+            responseClass = PlatformComponentDto.CLASS_NAME)
+    @GET
+    public PlatformComponentDto get(
+            @ApiParam(value = "ID of item being retrieved", required = true)
+            @PathParam("id") String id) {
+        return dto().adapt(lookup(camp().platformComponents(), id));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/PlatformComponentTemplateRestResource.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/PlatformComponentTemplateRestResource.java b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/PlatformComponentTemplateRestResource.java
new file mode 100644
index 0000000..0baa4ec
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/PlatformComponentTemplateRestResource.java
@@ -0,0 +1,32 @@
+package io.brooklyn.camp.rest.resource;
+
+import io.brooklyn.camp.dto.PlatformComponentTemplateDto;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+
+import brooklyn.rest.apidoc.Apidoc;
+
+import com.wordnik.swagger.core.ApiOperation;
+import com.wordnik.swagger.core.ApiParam;
+
+@Path(PlatformComponentTemplateRestResource.URI_PATH)
+@Apidoc("Platform Component Template resources")
+@Produces("application/json")
+public class PlatformComponentTemplateRestResource extends AbstractCampRestResource {
+
+    public static final String URI_PATH = PlatformRestResource.CAMP_URI_PATH + "/platform-component-templates";
+
+    @Path("/{id}")
+    @ApiOperation(value = "Get a specific platform component template",
+            responseClass = PlatformComponentTemplateDto.CLASS_NAME)
+    @GET
+    public PlatformComponentTemplateDto get(
+            @ApiParam(value = "ID of item being retrieved", required = true)
+            @PathParam("id") String id) {
+        return dto().adapt(lookup(camp().platformComponentTemplates(), id));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/PlatformRestResource.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/PlatformRestResource.java b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/PlatformRestResource.java
new file mode 100644
index 0000000..cf647f6
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/resource/PlatformRestResource.java
@@ -0,0 +1,71 @@
+package io.brooklyn.camp.rest.resource;
+
+import io.brooklyn.camp.dto.PlatformDto;
+import io.brooklyn.camp.rest.util.WebResourceUtils;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+
+import java.io.InputStream;
+import java.io.StringReader;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.rest.apidoc.Apidoc;
+
+import com.wordnik.swagger.core.ApiOperation;
+
+//import io.brooklyn.camp.rest.apidoc.Apidoc;
+
+@Path(PlatformRestResource.CAMP_URI_PATH)
+@Apidoc("Platform (root)")
+@Produces("application/json")
+public class PlatformRestResource extends AbstractCampRestResource {
+
+    private static final Logger log = LoggerFactory.getLogger(PlatformRestResource.class);
+    
+    public static final String CAMP_URI_PATH = "/camp/v11";
+    
+    @ApiOperation(value = "Return the Platform (root) resource",
+            responseClass = PlatformDto.CLASS_NAME)
+    @GET
+    public PlatformDto get() {
+        return dto().adapt(camp().root());
+    }
+    
+    @POST
+    @Consumes({MediaType.APPLICATION_JSON})
+    public Response postJson(@Context UriInfo info, String json) {
+        return postYaml(info, json);
+    }
+
+    @POST
+    @Consumes({"application/x-yaml"})
+    public Response postYaml(@Context UriInfo info, String yaml) {
+        log.debug("YAML pdp:\n"+yaml);
+        AssemblyTemplate template = camp().pdp().registerDeploymentPlan(new StringReader(yaml));
+        return created(info, template);
+    }
+
+    @POST
+    @Consumes({"application/x-tar", "application/x-tgz", "application/x-zip"})
+    public Response postArchive(@Context UriInfo info, InputStream archiveInput) {
+        log.debug("ARCHIVE pdp");
+        AssemblyTemplate template = camp().pdp().registerPdpFromArchive(archiveInput);
+        return created(info, template);
+    }
+
+    protected Response created(UriInfo info, AssemblyTemplate template) {
+        return WebResourceUtils.created(info, dto().adapt(template).getUri());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/util/CampJsons.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/util/CampJsons.java b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/util/CampJsons.java
new file mode 100644
index 0000000..094ab4d
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/util/CampJsons.java
@@ -0,0 +1,21 @@
+package io.brooklyn.camp.rest.util;
+
+import brooklyn.util.exceptions.Exceptions;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+
+public class CampJsons {
+
+    public static String prettyJson(Object o) {
+        try {
+            ObjectMapper mapper = new ObjectMapper();
+            mapper.enable(SerializationFeature.INDENT_OUTPUT);
+            return mapper.writeValueAsString(o);
+        } catch (JsonProcessingException e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/util/CampRestContext.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/util/CampRestContext.java b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/util/CampRestContext.java
new file mode 100644
index 0000000..c533bd2
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/util/CampRestContext.java
@@ -0,0 +1,32 @@
+package io.brooklyn.camp.rest.util;
+
+import javax.servlet.ServletContext;
+
+import com.google.common.base.Preconditions;
+
+import io.brooklyn.camp.CampPlatform;
+import io.brooklyn.camp.CampServer;
+
+public class CampRestContext {
+
+    private final ServletContext servletContext;
+    private CampPlatform platform;
+    private DtoFactory dto;
+    
+    public CampRestContext(ServletContext servletContext) {
+        this.servletContext = servletContext;
+    }
+
+    public synchronized CampPlatform camp() {
+        if (platform!=null) return platform;
+        platform = (CampPlatform) servletContext.getAttribute(CampServer.CAMP_PLATFORM_ATTRIBUTE);
+        return Preconditions.checkNotNull(platform, "CAMP platform instance not available from ServletContext");
+    }
+
+    public DtoFactory dto() {
+        if (dto!=null) return dto;
+        dto = (DtoFactory) servletContext.getAttribute(CampServer.DTO_FACTORY);
+        return Preconditions.checkNotNull(dto, "CAMP DTO factory instance not available from ServletContext");
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/util/CampRestGuavas.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/util/CampRestGuavas.java b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/util/CampRestGuavas.java
new file mode 100644
index 0000000..ffded5e
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/util/CampRestGuavas.java
@@ -0,0 +1,14 @@
+package io.brooklyn.camp.rest.util;
+
+import io.brooklyn.camp.spi.AbstractResource;
+
+import com.google.common.base.Function;
+
+public class CampRestGuavas {
+
+    public static final Function<AbstractResource,String> IDENTITY_OF_REST_RESOURCE = 
+            new Function<AbstractResource,String>() {
+                public String apply(AbstractResource input) { return input.getId(); }
+            };
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/util/DtoFactory.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/util/DtoFactory.java b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/util/DtoFactory.java
new file mode 100644
index 0000000..8d3e593
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/util/DtoFactory.java
@@ -0,0 +1,158 @@
+package io.brooklyn.camp.rest.util;
+
+import io.brooklyn.camp.CampPlatform;
+import io.brooklyn.camp.dto.ApplicationComponentDto;
+import io.brooklyn.camp.dto.ApplicationComponentTemplateDto;
+import io.brooklyn.camp.dto.AssemblyDto;
+import io.brooklyn.camp.dto.AssemblyTemplateDto;
+import io.brooklyn.camp.dto.PlatformComponentDto;
+import io.brooklyn.camp.dto.PlatformComponentTemplateDto;
+import io.brooklyn.camp.dto.PlatformDto;
+import io.brooklyn.camp.rest.resource.AbstractCampRestResource;
+import io.brooklyn.camp.rest.resource.ApplicationComponentRestResource;
+import io.brooklyn.camp.rest.resource.ApplicationComponentTemplateRestResource;
+import io.brooklyn.camp.rest.resource.AssemblyRestResource;
+import io.brooklyn.camp.rest.resource.AssemblyTemplateRestResource;
+import io.brooklyn.camp.rest.resource.PlatformComponentRestResource;
+import io.brooklyn.camp.rest.resource.PlatformComponentTemplateRestResource;
+import io.brooklyn.camp.rest.resource.PlatformRestResource;
+import io.brooklyn.camp.spi.AbstractResource;
+import io.brooklyn.camp.spi.ApplicationComponent;
+import io.brooklyn.camp.spi.ApplicationComponentTemplate;
+import io.brooklyn.camp.spi.Assembly;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+import io.brooklyn.camp.spi.PlatformComponent;
+import io.brooklyn.camp.spi.PlatformComponentTemplate;
+import io.brooklyn.camp.spi.PlatformRootSummary;
+
+import java.util.Map;
+
+import javax.ws.rs.Path;
+
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.net.Urls;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+
+public class DtoFactory {
+
+    private CampPlatform platform;
+    private String uriBase;
+    
+    private UriFactory uriFactory;
+
+    public DtoFactory(CampPlatform campPlatform, String uriBase) {
+        this.platform = campPlatform;
+        this.uriBase = uriBase;
+        
+        uriFactory = new UriFactory();
+        uriFactory.registerIdentifiableRestResource(PlatformRootSummary.class, PlatformRestResource.class);
+        uriFactory.registerIdentifiableRestResource(AssemblyTemplate.class, AssemblyTemplateRestResource.class);
+        uriFactory.registerIdentifiableRestResource(PlatformComponentTemplate.class, PlatformComponentTemplateRestResource.class);
+        uriFactory.registerIdentifiableRestResource(ApplicationComponentTemplate.class, ApplicationComponentTemplateRestResource.class);
+        uriFactory.registerIdentifiableRestResource(Assembly.class, AssemblyRestResource.class);
+        uriFactory.registerIdentifiableRestResource(PlatformComponent.class, PlatformComponentRestResource.class);
+        uriFactory.registerIdentifiableRestResource(ApplicationComponent.class, ApplicationComponentRestResource.class);
+    }
+
+    public CampPlatform getPlatform() {
+        return platform;
+    }
+
+    public UriFactory getUriFactory() {
+        return uriFactory;
+    }
+
+    public String uri(AbstractResource x) {
+        return getUriFactory().uri(x);
+    }
+        
+    public String uri(Class<? extends AbstractResource> targetType, String id) {
+        return getUriFactory().uri(targetType, id);
+    }
+
+    public AssemblyTemplateDto adapt(AssemblyTemplate assemblyTemplate) {
+        return AssemblyTemplateDto.newInstance(this, assemblyTemplate);
+    }
+    public PlatformComponentTemplateDto adapt(PlatformComponentTemplate platformComponentTemplate) {
+        return PlatformComponentTemplateDto.newInstance(this, platformComponentTemplate);
+    }
+    public ApplicationComponentTemplateDto adapt(ApplicationComponentTemplate applicationComponentTemplate) {
+        return ApplicationComponentTemplateDto.newInstance(this, applicationComponentTemplate);
+    }
+
+    public AssemblyDto adapt(Assembly assembly) {
+        return AssemblyDto.newInstance(this, assembly);
+    }
+    public PlatformComponentDto adapt(PlatformComponent platformComponent) {
+        return PlatformComponentDto.newInstance(this, platformComponent);
+    }
+    public ApplicationComponentDto adapt(ApplicationComponent applicationComponent) {
+        return ApplicationComponentDto.newInstance(this, applicationComponent);
+    }
+
+    public PlatformDto adapt(PlatformRootSummary root) {
+        return PlatformDto.newInstance(this, root);
+    }
+
+    public class UriFactory {
+        /** registry of generating a URI given an object */
+        Map<Class<?>,Function<Object,String>> registryResource = new MutableMap<Class<?>, Function<Object,String>>();
+        /** registry of generating a URI given an ID */
+        Map<Class<?>,Function<String,String>> registryId = new MutableMap<Class<?>, Function<String,String>>();
+
+        /** registers a function which generates a URI given a type; note that this method cannot be used for links */
+        @SuppressWarnings("unchecked")
+        public synchronized <T> void registerResourceUriFunction(Class<T> type, Function<T,String> fnUri) {
+            registryResource.put(type, (Function<Object, String>) fnUri);
+        }
+
+        /** registers a type to generate a URI which concatenates the given base with the
+         * result of the given function to generate an ID against an object of the given type */
+        public synchronized <T> void registerIdentityFunction(Class<T> type, final String resourceTypeUriBase, final Function<T,String> fnIdentity) {
+            final Function<String,String> fnUriFromId = new Function<String,String>() {
+                public String apply(String id) {
+                    return Urls.mergePaths(resourceTypeUriBase, id);
+                }
+            };
+            registryId.put(type, (Function<String, String>) fnUriFromId);
+            registerResourceUriFunction(type, new Function<T,String>() {
+                public String apply(T input) {
+                    return fnUriFromId.apply(fnIdentity.apply(input));
+                }
+            });
+        }
+
+        /** registers a CAMP Resource type against a RestResource, generating the URI
+         * by concatenating the @Path annotation on the RestResource with the ID of the CAMP resource */
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        public synchronized <T extends AbstractResource> void registerIdentifiableRestResource(Class<T> type, Class<? extends AbstractCampRestResource> restResource) {
+            registerIdentityFunction(type, 
+                    uriOfRestResource(restResource),
+                    (Function) CampRestGuavas.IDENTITY_OF_REST_RESOURCE);
+        }
+        
+        public String uri(Class<? extends AbstractResource> targetType, String id) {
+            return Preconditions.checkNotNull(registryId.get(targetType), 
+                    "No REST ID converter registered for %s (id %s)", targetType, id)
+                    .apply(id);
+        }
+
+        public String uri(AbstractResource x) {
+            return Preconditions.checkNotNull(registryResource.get(x.getClass()), 
+                    "No REST converter registered for %s (%s)", x.getClass(), x)
+                    .apply(x);
+        }
+        
+        public String uriOfRestResource(Class<?> restResourceClass) {
+            return Urls.mergePaths(uriBase, 
+                    Preconditions.checkNotNull(restResourceClass.getAnnotation(Path.class),
+                            "No @Path on type %s", restResourceClass)
+                    .value());
+        }
+            
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/util/WebResourceUtils.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/rest/util/WebResourceUtils.java b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/util/WebResourceUtils.java
new file mode 100644
index 0000000..3e162e0
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/rest/util/WebResourceUtils.java
@@ -0,0 +1,42 @@
+package io.brooklyn.camp.rest.util;
+
+import io.brooklyn.camp.dto.ApiErrorDto;
+
+import java.net.URI;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class WebResourceUtils {
+
+    private static final Logger log = LoggerFactory.getLogger(WebResourceUtils.class);
+    
+    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(ApiErrorDto.builder().message(msg).build()).build());
+    }
+
+    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(ApiErrorDto.builder().message(msg).build()).build());
+    }
+
+    public static Response created(UriInfo info, String resourceUriPath) {
+        // see http://stackoverflow.com/questions/13702481/javax-response-prepends-method-path-when-setting-location-header-path-on-status
+        // for why we have to return absolute path
+        URI resourceUri = info.getBaseUriBuilder().path( resourceUriPath ).build();
+        return Response.created(resourceUri).build();
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/test/java/io/brooklyn/camp/dto/ApplicationCompomentTemplateDtoTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/test/java/io/brooklyn/camp/dto/ApplicationCompomentTemplateDtoTest.java b/camp/camp-server/src/test/java/io/brooklyn/camp/dto/ApplicationCompomentTemplateDtoTest.java
new file mode 100644
index 0000000..36686e2
--- /dev/null
+++ b/camp/camp-server/src/test/java/io/brooklyn/camp/dto/ApplicationCompomentTemplateDtoTest.java
@@ -0,0 +1,31 @@
+package io.brooklyn.camp.dto;
+
+import io.brooklyn.camp.CampPlatform;
+import io.brooklyn.camp.rest.util.DtoFactory;
+import io.brooklyn.camp.spi.ApplicationComponentTemplate;
+import io.brooklyn.camp.test.mock.web.MockWebPlatform;
+import junit.framework.Assert;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.Test;
+
+public class ApplicationCompomentTemplateDtoTest {
+
+    private static final Logger log = LoggerFactory.getLogger(ApplicationCompomentTemplateDtoTest.class);
+    
+    @Test
+    public void testAppServerPct() {
+        CampPlatform p = MockWebPlatform.newPlatform();
+        DtoFactory f = new DtoFactory(p, "");
+        
+        ApplicationComponentTemplate t = MockWebPlatform.WAR;
+        ApplicationComponentTemplateDto dto = f.adapt(t);
+        
+        log.info("War PCT serialized as: "+BasicDtoTest.tree(dto));
+        Assert.assertEquals(dto.getName(), t.getName());
+        Assert.assertNotNull(dto.getCreatedAsString());
+        Assert.assertTrue(dto.getCreatedAsString().startsWith("20"));
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/test/java/io/brooklyn/camp/dto/BasicDtoTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/test/java/io/brooklyn/camp/dto/BasicDtoTest.java b/camp/camp-server/src/test/java/io/brooklyn/camp/dto/BasicDtoTest.java
new file mode 100644
index 0000000..a21c3fd
--- /dev/null
+++ b/camp/camp-server/src/test/java/io/brooklyn/camp/dto/BasicDtoTest.java
@@ -0,0 +1,72 @@
+package io.brooklyn.camp.dto;
+
+import java.io.IOException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/** Tests identity methods and custom attributes for DTO, including Jackson JSON serialization */
+public class BasicDtoTest {
+
+    private static final Logger log = LoggerFactory.getLogger(BasicDtoTest.class);
+    
+    @Test
+    public void testSimple() throws IOException {
+        DtoCustomAttributes l = new DtoCustomAttributes(null);
+        
+        JsonNode t = tree(l);
+        Assert.assertEquals(t.size(), 0);
+        Assert.assertTrue(l.getCustomAttributes()==null || l.getCustomAttributes().isEmpty());
+        
+        Assert.assertEquals(l, new ObjectMapper().readValue(t.toString(), DtoCustomAttributes.class));
+    }
+
+    @Test
+    public void testCustomAttrs() throws IOException {
+        DtoCustomAttributes l = new DtoCustomAttributes(MutableMap.of("bar", "bee"));
+        
+        JsonNode t = tree(l);
+        Assert.assertEquals(t.size(), 1);
+        Assert.assertEquals(t.get("bar").asText(), l.getCustomAttributes().get("bar"));
+        
+        Assert.assertEquals(l, new ObjectMapper().readValue(t.toString(), DtoCustomAttributes.class));
+    }
+
+    @Test
+    public void testIdentity() throws IOException {
+        DtoCustomAttributes l1 = new DtoCustomAttributes(null);
+        DtoCustomAttributes l2 = new DtoCustomAttributes(MutableMap.of("bar", "bee"));
+        DtoCustomAttributes l2o = new DtoCustomAttributes(MutableMap.of("bar", "bee"));
+        
+        Assert.assertEquals(l1, l1);
+        Assert.assertEquals(l2, l2);
+        Assert.assertEquals(l2, l2o);
+        Assert.assertNotEquals(l1, l2);
+        
+        Assert.assertEquals(l1.hashCode(), l1.hashCode());
+        Assert.assertEquals(l2.hashCode(), l2.hashCode());
+        Assert.assertEquals(l2.hashCode(), l2o.hashCode());
+        Assert.assertNotEquals(l1.hashCode(), l2.hashCode());
+    }
+    
+    public static JsonNode tree(Object l) {
+        try {
+            ObjectMapper m = new ObjectMapper();
+            String s = m.writeValueAsString(l);
+            log.info(l.toString()+" -> "+s);
+            JsonNode t = m.readTree(s);
+            return t;
+        } catch (Exception e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/test/java/io/brooklyn/camp/dto/LinkDtoTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/test/java/io/brooklyn/camp/dto/LinkDtoTest.java b/camp/camp-server/src/test/java/io/brooklyn/camp/dto/LinkDtoTest.java
new file mode 100644
index 0000000..da2c344
--- /dev/null
+++ b/camp/camp-server/src/test/java/io/brooklyn/camp/dto/LinkDtoTest.java
@@ -0,0 +1,44 @@
+package io.brooklyn.camp.dto;
+
+import java.io.IOException;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import brooklyn.util.collections.MutableMap;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@Test
+public class LinkDtoTest {
+
+//    private static final Logger log = LoggerFactory.getLogger(LinkDtoTest.class);
+    
+    @Test
+    public void testSimple() throws IOException {
+        LinkDto l = LinkDto.newInstance("http://foo", "Foo");
+        
+        JsonNode t = BasicDtoTest.tree(l);
+        Assert.assertEquals(t.size(), 2);
+        Assert.assertEquals(t.get("href").asText(), l.getHref());
+        Assert.assertEquals(t.get("targetName").asText(), l.getTargetName());
+        Assert.assertTrue(l.getCustomAttributes()==null || l.getCustomAttributes().isEmpty());
+        
+        Assert.assertEquals(l, new ObjectMapper().readValue(t.toString(), LinkDto.class));
+    }
+
+    @Test
+    public void testCustomAttrs() throws IOException {
+        LinkDto l = LinkDto.newInstance("http://foo", "Foo", MutableMap.of("bar", "bee"));
+        
+        JsonNode t = BasicDtoTest.tree(l);
+        Assert.assertEquals(t.size(), 3);
+        Assert.assertEquals(t.get("href").asText(), l.getHref());
+        Assert.assertEquals(t.get("targetName").asText(), l.getTargetName());
+        Assert.assertEquals(t.get("bar").asText(), l.getCustomAttributes().get("bar"));
+        
+        Assert.assertEquals(l, new ObjectMapper().readValue(t.toString(), LinkDto.class));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/test/java/io/brooklyn/camp/dto/PlatformCompomentTemplateDtoTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/test/java/io/brooklyn/camp/dto/PlatformCompomentTemplateDtoTest.java b/camp/camp-server/src/test/java/io/brooklyn/camp/dto/PlatformCompomentTemplateDtoTest.java
new file mode 100644
index 0000000..25b9f29
--- /dev/null
+++ b/camp/camp-server/src/test/java/io/brooklyn/camp/dto/PlatformCompomentTemplateDtoTest.java
@@ -0,0 +1,31 @@
+package io.brooklyn.camp.dto;
+
+import io.brooklyn.camp.CampPlatform;
+import io.brooklyn.camp.rest.util.DtoFactory;
+import io.brooklyn.camp.spi.PlatformComponentTemplate;
+import io.brooklyn.camp.test.mock.web.MockWebPlatform;
+import junit.framework.Assert;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.Test;
+
+public class PlatformCompomentTemplateDtoTest {
+
+    private static final Logger log = LoggerFactory.getLogger(PlatformCompomentTemplateDtoTest.class);
+    
+    @Test
+    public void testAppServerPct() {
+        CampPlatform p = MockWebPlatform.newPlatform();
+        DtoFactory f = new DtoFactory(p, "");
+        
+        PlatformComponentTemplate t = MockWebPlatform.APPSERVER;
+        PlatformComponentTemplateDto dto = f.adapt(t);
+        
+        log.info("Web PCT serialized as: "+BasicDtoTest.tree(dto));
+        Assert.assertEquals(dto.getName(), t.getName());
+        Assert.assertNotNull(dto.getCreatedAsString());
+        Assert.assertTrue(dto.getCreatedAsString().startsWith("20"));
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/test/java/io/brooklyn/camp/dto/ResourceDtoTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/test/java/io/brooklyn/camp/dto/ResourceDtoTest.java b/camp/camp-server/src/test/java/io/brooklyn/camp/dto/ResourceDtoTest.java
new file mode 100644
index 0000000..ed8c4cd
--- /dev/null
+++ b/camp/camp-server/src/test/java/io/brooklyn/camp/dto/ResourceDtoTest.java
@@ -0,0 +1,59 @@
+package io.brooklyn.camp.dto;
+
+import io.brooklyn.camp.BasicCampPlatform;
+import io.brooklyn.camp.CampServer;
+import io.brooklyn.camp.commontypes.RepresentationSkew;
+import io.brooklyn.camp.rest.util.CampRestGuavas;
+import io.brooklyn.camp.spi.AbstractResource;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@Test
+public class ResourceDtoTest {
+
+//    private static final Logger log = LoggerFactory.getLogger(ResourceDtoTest.class);
+    
+    CampServer s;
+    AbstractResource rr;
+    ResourceDto r;
+    
+    @SuppressWarnings("unchecked")
+    protected void initSimpleDto() {
+        s = new CampServer(new BasicCampPlatform(), "http://atest/");
+        s.getDtoFactory().getUriFactory().registerIdentityFunction(AbstractResource.class, "basic", CampRestGuavas.IDENTITY_OF_REST_RESOURCE);
+        rr = AbstractResource.builder().name("Name").description("a description").
+                tags(Arrays.asList("tag1", "tag 2")).representationSkew(RepresentationSkew.NONE).build();
+        r = ResourceDto.newInstance(s.getDtoFactory(), rr);
+    }
+    
+    @Test
+    public void testSimpleCreation() throws IOException {
+        initSimpleDto();
+        
+        Assert.assertNotNull(r.getCreatedAsString());
+        Assert.assertEquals(r.getName(), "Name");
+        Assert.assertEquals(r.getDescription(), "a description");
+        Assert.assertEquals(r.getTags(), Arrays.asList("tag1", "tag 2"));
+        Assert.assertEquals(r.getRepresentationSkew(), RepresentationSkew.NONE);
+    }
+    
+    public void testSimpleSerializationAndDeserialization() throws IOException {
+        initSimpleDto();
+        
+        JsonNode t = BasicDtoTest.tree(r);
+        
+//        Assert.assertEquals(t.get("uri").asText(), r.getUri());
+        ResourceDto r2 = new ObjectMapper().readValue(t.toString(), ResourceDto.class);
+        Assert.assertNotNull(r2.getCreated());
+        Assert.assertEquals(r, r2);
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/test/java/io/brooklyn/camp/rest/resource/PlatformRestResourceTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/test/java/io/brooklyn/camp/rest/resource/PlatformRestResourceTest.java b/camp/camp-server/src/test/java/io/brooklyn/camp/rest/resource/PlatformRestResourceTest.java
new file mode 100644
index 0000000..1db19ad
--- /dev/null
+++ b/camp/camp-server/src/test/java/io/brooklyn/camp/rest/resource/PlatformRestResourceTest.java
@@ -0,0 +1,24 @@
+package io.brooklyn.camp.rest.resource;
+
+import io.brooklyn.camp.dto.PlatformComponentTemplateDto;
+import io.brooklyn.camp.dto.PlatformDto;
+import io.brooklyn.camp.test.fixture.AbstractRestResourceTest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class PlatformRestResourceTest extends AbstractRestResourceTest {
+
+    private static final Logger log = LoggerFactory.getLogger(PlatformRestResourceTest.class);
+    
+    @Test
+    public void testPlatformIncludesList() {
+        PlatformDto p = load(PlatformRestResource.CAMP_URI_PATH, PlatformDto.class);
+        PlatformComponentTemplateDto pct = load(p.getPlatformComponentTemplates().get(0).getHref(), PlatformComponentTemplateDto.class);
+        log.debug("Loaded PCT via REST: "+pct);
+        Assert.assertNotNull(pct.getName());
+    }
+        
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/test/java/io/brooklyn/camp/test/fixture/AbstractRestResourceTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/test/java/io/brooklyn/camp/test/fixture/AbstractRestResourceTest.java b/camp/camp-server/src/test/java/io/brooklyn/camp/test/fixture/AbstractRestResourceTest.java
new file mode 100644
index 0000000..d4c6f01
--- /dev/null
+++ b/camp/camp-server/src/test/java/io/brooklyn/camp/test/fixture/AbstractRestResourceTest.java
@@ -0,0 +1,68 @@
+package io.brooklyn.camp.test.fixture;
+
+import java.net.URL;
+
+import io.brooklyn.camp.BasicCampPlatform;
+import io.brooklyn.camp.CampServer;
+import io.brooklyn.camp.test.mock.web.MockWebPlatform;
+
+import org.junit.AfterClass;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.BeforeClass;
+import org.testng.reporters.Files;
+
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.net.Urls;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class AbstractRestResourceTest {
+
+    private static final Logger log = LoggerFactory.getLogger(AbstractRestResourceTest.class);
+    
+    protected BasicCampPlatform platform;
+    protected CampServer server;
+    
+    @BeforeClass
+    public void startServer() {
+        platform = new BasicCampPlatform();
+        populate();
+        
+        // new server
+        server = new CampServer(platform, "").start();
+    }
+    
+    protected void populate() {
+        MockWebPlatform.populate(platform);
+    }
+
+    @AfterClass 
+    public void stopServer() {
+        if (server!=null)
+            server.stop();
+    }
+    
+    public String load(String path) {
+        try {
+            String base = "http://localhost:"+server.getPort();
+            String x = path.startsWith(base) ? path : Urls.mergePaths(base, path);
+            log.debug("Reading from: "+x);
+            String s = Files.streamToString(new URL(x).openStream());
+            log.debug("Result from "+x+": "+s);
+            return s;
+        } catch (Exception e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+    
+    public <T> T load(String path, Class<T> type) {
+        try {
+            String data = load(path);
+            return new ObjectMapper().readValue(data, type);
+        } catch (Exception e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/test/java/io/brooklyn/camp/test/fixture/InMemoryCamp.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/test/java/io/brooklyn/camp/test/fixture/InMemoryCamp.java b/camp/camp-server/src/test/java/io/brooklyn/camp/test/fixture/InMemoryCamp.java
new file mode 100644
index 0000000..a873117
--- /dev/null
+++ b/camp/camp-server/src/test/java/io/brooklyn/camp/test/fixture/InMemoryCamp.java
@@ -0,0 +1,35 @@
+package io.brooklyn.camp.test.fixture;
+
+import io.brooklyn.camp.BasicCampPlatform;
+import io.brooklyn.camp.CampServer;
+import io.brooklyn.camp.test.mock.web.MockWebPlatform;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class InMemoryCamp {
+    
+    private static final Logger log = LoggerFactory.getLogger(InMemoryCamp.class);
+
+    
+    public static void main(String[] args) {
+        
+        // new platform with some mock types and some data structures
+        
+            // interface CampComponent
+            // getComponentTemplate() -> operations, links, etc
+        
+            // platformView.getComponent(id) -> returns instance of domain-specific component type
+        BasicCampPlatform p = new BasicCampPlatform();
+        MockWebPlatform.populate(p);
+        
+        // new server
+        CampServer s = new CampServer(p, "").start();
+        
+        log.info("Running at: "+s.getUriBase());
+        // requests against server
+        
+    }
+    
+    
+}


[09/45] git commit: Rename catalog context to libraries

Posted by he...@apache.org.
Rename catalog context to libraries


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

Branch: refs/heads/master
Commit: 0263fa1ca53082f10f07031edad24a1b7a894e88
Parents: 45e1494
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Mon Jun 30 16:07:10 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Tue Jul 1 13:37:37 2014 +0100

----------------------------------------------------------------------
 .../main/java/brooklyn/catalog/CatalogItem.java |  4 +--
 .../catalog/internal/CatalogContextDo.java      | 24 -------------
 .../catalog/internal/CatalogContextDto.java     | 20 -----------
 .../catalog/internal/CatalogItemDo.java         |  4 +--
 .../internal/CatalogItemDtoAbstract.java        | 38 ++++++++------------
 .../catalog/internal/CatalogLibrariesDo.java    | 22 ++++++++++++
 .../catalog/internal/CatalogLibrariesDto.java   | 20 +++++++++++
 .../catalog/internal/CatalogXmlSerializer.java  |  4 +--
 .../catalog/internal/CatalogDtoTest.java        |  4 +--
 .../catalog/internal/CatalogLoadTest.java       |  6 ++--
 .../brooklyn/catalog/internal/osgi-catalog.xml  |  4 +--
 11 files changed, 69 insertions(+), 81 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0263fa1c/api/src/main/java/brooklyn/catalog/CatalogItem.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/catalog/CatalogItem.java b/api/src/main/java/brooklyn/catalog/CatalogItem.java
index b9ae3c0..9888901 100644
--- a/api/src/main/java/brooklyn/catalog/CatalogItem.java
+++ b/api/src/main/java/brooklyn/catalog/CatalogItem.java
@@ -9,7 +9,7 @@ public interface CatalogItem<T> {
         TEMPLATE, ENTITY, POLICY, CONFIGURATION
     }
 
-    public static interface CatalogItemContext {
+    public static interface CatalogItemLibraries {
         List<String> getBundles();
     }
 
@@ -24,7 +24,7 @@ public interface CatalogItem<T> {
     public String getVersion();
 
     @Nonnull
-    public CatalogItemContext getContext();
+    public CatalogItemLibraries getLibraries();
 
     public String toXmlString();
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0263fa1c/core/src/main/java/brooklyn/catalog/internal/CatalogContextDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogContextDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogContextDo.java
deleted file mode 100644
index 6560b35..0000000
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogContextDo.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package brooklyn.catalog.internal;
-
-import java.util.List;
-
-import com.google.common.base.Preconditions;
-
-import brooklyn.catalog.CatalogItem;
-
-public class CatalogContextDo implements CatalogItem.CatalogItemContext {
-
-//    private final CatalogDo catalog;
-    private final CatalogContextDto contextDto;
-
-    public CatalogContextDo(/*CatalogDo catalog,*/ CatalogContextDto contextDto) {
-//        this.catalog = Preconditions.checkNotNull(catalog, "catalog");
-        this.contextDto = Preconditions.checkNotNull(contextDto, "contextDto");
-    }
-
-    @Override
-    public List<String> getBundles() {
-        return contextDto.getBundles();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0263fa1c/core/src/main/java/brooklyn/catalog/internal/CatalogContextDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogContextDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogContextDto.java
deleted file mode 100644
index ef4fefa..0000000
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogContextDto.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package brooklyn.catalog.internal;
-
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-import brooklyn.catalog.CatalogItem;
-
-public class CatalogContextDto implements CatalogItem.CatalogItemContext {
-
-    List<String> bundles = new CopyOnWriteArrayList<String>();
-
-    public void addBundle(String url) {
-        bundles.add(url);
-    }
-
-    public List<String> getBundles() {
-        return bundles;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0263fa1c/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
index 91ed93a..d857c45 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
@@ -65,8 +65,8 @@ public class CatalogItemDo<T> implements CatalogItem<T> {
 
     @Nonnull
     @Override
-    public CatalogItemContext getContext() {
-        return itemDto.getContext();
+    public CatalogItemLibraries getLibraries() {
+        return itemDto.getLibraries();
     }
 
     public Class<T> getJavaClass() {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0263fa1c/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
index a774930..dcee2fa 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
@@ -1,28 +1,18 @@
 package brooklyn.catalog.internal;
 
-import java.util.Collections;
-import java.util.List;
-
 import javax.annotation.Nonnull;
 
 import brooklyn.catalog.CatalogItem;
 
 public abstract class CatalogItemDtoAbstract<T> implements CatalogItem<T> {
 
-    private static final CatalogItemContext EMPTY_CONTEXT = new CatalogItemContext() {
-        @Override
-        public List<String> getBundles() {
-            return Collections.emptyList();
-        }
-    };
-
     String id;
     String type;
     String name;
     String description;
     String iconUrl;
     String version;
-    CatalogItemContext context;
+    CatalogLibrariesDto libraries;
     
     public String getId() {
         if (id!=null) return id;
@@ -51,48 +41,48 @@ public abstract class CatalogItemDtoAbstract<T> implements CatalogItem<T> {
 
     @Nonnull
     @Override
-    public CatalogItemContext getContext() {
-        return context;
+    public CatalogItemLibraries getLibraries() {
+        return libraries;
     }
 
     public static CatalogTemplateItemDto newTemplate(String type, String name) {
         return newTemplate(null, type, name, null);
     }
-    public static CatalogTemplateItemDto newTemplate(String id, String type, String name, String description){
+    public static CatalogTemplateItemDto newTemplate(String id, String type, String name, String description) {
         return newTemplate(id, type, name, description, null);
     }
-    public static CatalogTemplateItemDto newTemplate(String id, String type, String name, String description, CatalogContextDto context){
-        return set(new CatalogTemplateItemDto(), id, type, name, description, context);
+    public static CatalogTemplateItemDto newTemplate(String id, String type, String name, String description, CatalogLibrariesDto libraries) {
+        return set(new CatalogTemplateItemDto(), id, type, name, description, libraries);
     }
 
     public static CatalogEntityItemDto newEntity(String type, String name) {
         return newEntity(null, type, name, null);
     }
-    public static CatalogEntityItemDto newEntity(String id, String type, String name, String description){
+    public static CatalogEntityItemDto newEntity(String id, String type, String name, String description) {
         return newEntity(id, type, name, description, null);
     }
-    public static CatalogEntityItemDto newEntity(String id, String type, String name, String description, CatalogContextDto context){
-        return set(new CatalogEntityItemDto(), id, type, name, description, context);
+    public static CatalogEntityItemDto newEntity(String id, String type, String name, String description, CatalogLibrariesDto libraries) {
+        return set(new CatalogEntityItemDto(), id, type, name, description, libraries);
     }
 
     public static CatalogPolicyItemDto newPolicy(String type, String name) {
         return newPolicy(null, type, name, null);
     }
-    public static CatalogPolicyItemDto newPolicy(String id, String type, String name, String description){
+    public static CatalogPolicyItemDto newPolicy(String id, String type, String name, String description) {
         return newPolicy(id, type, name, description, null);
     }
-    public static CatalogPolicyItemDto newPolicy(String id, String type, String name, String description, CatalogContextDto context){
-        return set(new CatalogPolicyItemDto(), id, type, name, description, context);
+    public static CatalogPolicyItemDto newPolicy(String id, String type, String name, String description, CatalogLibrariesDto libraries) {
+        return set(new CatalogPolicyItemDto(), id, type, name, description, libraries);
     }
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
     private static <T extends CatalogItemDtoAbstract> T set(T target, String id, String type, String name,
-            String description, CatalogContextDto context) {
+            String description, CatalogLibrariesDto libraries) {
         target.id = id;
         target.type = type;
         target.name = name;
         target.description = description;
-        target.context = context != null ? context : EMPTY_CONTEXT;
+        target.libraries = libraries != null ? libraries : new CatalogLibrariesDto();
         return target;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0263fa1c/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java
new file mode 100644
index 0000000..04a8f80
--- /dev/null
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java
@@ -0,0 +1,22 @@
+package brooklyn.catalog.internal;
+
+import java.util.List;
+
+import com.google.common.base.Preconditions;
+
+import brooklyn.catalog.CatalogItem;
+
+public class CatalogLibrariesDo implements CatalogItem.CatalogItemLibraries {
+
+    private final CatalogLibrariesDto librariesDto;
+
+    public CatalogLibrariesDo(CatalogLibrariesDto librariesDto) {
+        this.librariesDto = Preconditions.checkNotNull(librariesDto, "librariesDto");
+    }
+
+    @Override
+    public List<String> getBundles() {
+        return librariesDto.getBundles();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0263fa1c/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
new file mode 100644
index 0000000..2a49cfd
--- /dev/null
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
@@ -0,0 +1,20 @@
+package brooklyn.catalog.internal;
+
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import brooklyn.catalog.CatalogItem;
+
+public class CatalogLibrariesDto implements CatalogItem.CatalogItemLibraries {
+
+    List<String> bundles = new CopyOnWriteArrayList<String>();
+
+    public void addBundle(String url) {
+        bundles.add(url);
+    }
+
+    public List<String> getBundles() {
+        return bundles;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0263fa1c/core/src/main/java/brooklyn/catalog/internal/CatalogXmlSerializer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogXmlSerializer.java b/core/src/main/java/brooklyn/catalog/internal/CatalogXmlSerializer.java
index 63c2382..36949a8 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogXmlSerializer.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogXmlSerializer.java
@@ -34,8 +34,8 @@ public class CatalogXmlSerializer extends XmlSerializer<Object> {
         xstream.addImplicitCollection(CatalogClasspathDto.class, "entries", "entry", String.class);
         xstream.registerConverter(new EnumCaseForgivingSingleValueConverter(CatalogScanningModes.class));
 
-        xstream.aliasType("context", CatalogContextDto.class);
-        xstream.addImplicitCollection(CatalogContextDto.class, "bundles", "bundle", String.class);
+        xstream.aliasType("libraries", CatalogLibrariesDto.class);
+        xstream.addImplicitCollection(CatalogLibrariesDto.class, "bundles", "bundle", String.class);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0263fa1c/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java b/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
index c8e14ee..ba5a863 100644
--- a/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
+++ b/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
@@ -84,9 +84,9 @@ public class CatalogDtoTest {
         root.addCatalog(cdhCatalog.dto);
 
         CatalogDo osgiCatalog = new CatalogDo(CatalogDto.newNamedInstance("OSGi",
-                "A catalog whose entries define their context as a list of OSGi bundles"));
+                "A catalog whose entries define their libraries as a list of OSGi bundles"));
         osgiCatalog.setClasspathScanForEntities(CatalogScanningModes.NONE);
-        CatalogContextDto m3Context = new CatalogContextDto();
+        CatalogLibrariesDto m3Context = new CatalogLibrariesDto();
         m3Context.addBundle("file://~/.m2/repository/io/cloudsoft/brooklyn-mapr/1.0.0-SNAPSHOT/brooklyn-mapr.jar");
         osgiCatalog.addEntry(CatalogItemDtoAbstract.newTemplate("M3App", "io.brooklyn.mapr.M3App", "M3 Application",
                 "Description", m3Context));

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0263fa1c/core/src/test/java/brooklyn/catalog/internal/CatalogLoadTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/catalog/internal/CatalogLoadTest.java b/core/src/test/java/brooklyn/catalog/internal/CatalogLoadTest.java
index 46394c7..9961d3a 100644
--- a/core/src/test/java/brooklyn/catalog/internal/CatalogLoadTest.java
+++ b/core/src/test/java/brooklyn/catalog/internal/CatalogLoadTest.java
@@ -37,9 +37,9 @@ public class CatalogLoadTest {
         assertEquals(template.getName(), "Entity name");
         assertEquals(template.getVersion(), "9.1.3");
         assertEquals(template.getJavaType(), "com.example.ExampleApp");
-        assertEquals(template.getContext().getBundles().size(), 2,
-                "Template bundles=" + Joiner.on(", ").join(template.getContext().getBundles()));
-        assertEquals(Sets.newHashSet(template.getContext().getBundles()),
+        assertEquals(template.getLibraries().getBundles().size(), 2,
+                "Template bundles=" + Joiner.on(", ").join(template.getLibraries().getBundles()));
+        assertEquals(Sets.newHashSet(template.getLibraries().getBundles()),
                 Sets.newHashSet("file://path/to/bundle.jar", "http://www.url.com/for/bundle.jar"));
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0263fa1c/core/src/test/resources/brooklyn/catalog/internal/osgi-catalog.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/brooklyn/catalog/internal/osgi-catalog.xml b/core/src/test/resources/brooklyn/catalog/internal/osgi-catalog.xml
index c8ea685..6b40130 100644
--- a/core/src/test/resources/brooklyn/catalog/internal/osgi-catalog.xml
+++ b/core/src/test/resources/brooklyn/catalog/internal/osgi-catalog.xml
@@ -3,9 +3,9 @@
 
     <template name="Entity name" version="9.1.3" type="com.example.ExampleApp">
         <description>An example application</description>
-        <context class="context">
+        <libraries>
             <bundle>file://path/to/bundle.jar</bundle>
             <bundle>http://www.url.com/for/bundle.jar</bundle>
-        </context>
+        </libraries>
     </template>
 </catalog>


[45/45] git commit: This closes #46

Posted by he...@apache.org.
This closes #46


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

Branch: refs/heads/master
Commit: 1a9732e785cbdb22950877073d73d84a00b64a3c
Parents: 437a776 0fc7107
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Fri Jul 4 10:48:53 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri Jul 4 10:48:53 2014 +0100

----------------------------------------------------------------------
 .../java/brooklyn/catalog/BrooklynCatalog.java  |  67 +++--
 .../main/java/brooklyn/catalog/CatalogItem.java |  39 ++-
 .../brooklyn/entity/proxying/EntitySpec.java    |  23 +-
 camp/README.md                                  |  17 ++
 camp/camp-base/notes.txt                        |  64 +++++
 camp/camp-base/pom.xml                          |  67 +++++
 .../brooklyn/camp/AggregatingCampPlatform.java  | 113 +++++++++
 .../io/brooklyn/camp/BasicCampPlatform.java     | 122 +++++++++
 .../java/io/brooklyn/camp/CampPlatform.java     |  58 +++++
 .../camp/commontypes/RepresentationSkew.java    |   5 +
 .../io/brooklyn/camp/spi/AbstractResource.java  | 176 +++++++++++++
 .../brooklyn/camp/spi/ApplicationComponent.java |  78 ++++++
 .../camp/spi/ApplicationComponentTemplate.java  |  39 +++
 .../java/io/brooklyn/camp/spi/Assembly.java     |  94 +++++++
 .../io/brooklyn/camp/spi/AssemblyTemplate.java  | 102 ++++++++
 .../main/java/io/brooklyn/camp/spi/Link.java    |  22 ++
 .../io/brooklyn/camp/spi/PlatformComponent.java |  86 +++++++
 .../camp/spi/PlatformComponentTemplate.java     |  37 +++
 .../brooklyn/camp/spi/PlatformRootSummary.java  |  55 +++++
 .../brooklyn/camp/spi/PlatformTransaction.java  |  28 +++
 .../spi/collection/AbstractResourceLookup.java  |  17 ++
 .../collection/AggregatingResourceLookup.java   |  38 +++
 .../spi/collection/BasicResourceLookup.java     |  53 ++++
 .../camp/spi/collection/ResolvableLink.java     |  19 ++
 .../camp/spi/collection/ResourceLookup.java     |  29 +++
 .../AssemblyTemplateInstantiator.java           |  12 +
 .../BasicAssemblyTemplateInstantiator.java      |  18 ++
 .../java/io/brooklyn/camp/spi/pdp/Artifact.java |  82 +++++++
 .../brooklyn/camp/spi/pdp/ArtifactContent.java  |  47 ++++
 .../camp/spi/pdp/ArtifactRequirement.java       |  55 +++++
 .../spi/pdp/AssemblyTemplateConstructor.java    |  76 ++++++
 .../brooklyn/camp/spi/pdp/DeploymentPlan.java   | 118 +++++++++
 .../java/io/brooklyn/camp/spi/pdp/Service.java  |  77 ++++++
 .../camp/spi/pdp/ServiceCharacteristic.java     |  55 +++++
 .../brooklyn/camp/spi/resolve/PdpMatcher.java   |  33 +++
 .../brooklyn/camp/spi/resolve/PdpProcessor.java | 154 ++++++++++++
 .../camp/spi/resolve/PlanInterpreter.java       |  95 +++++++
 .../interpret/PlanInterpretationContext.java    | 134 ++++++++++
 .../interpret/PlanInterpretationNode.java       | 245 +++++++++++++++++++
 .../main/java/io/brooklyn/util/yaml/Yamls.java  |  89 +++++++
 .../src/main/resources/logback-custom.xml       |   9 +
 .../pdp/DeploymentPlanToyInterpreterTest.java   |  96 ++++++++
 .../io/brooklyn/camp/spi/pdp/PdpYamlTest.java   |  60 +++++
 .../web/MockAssemblyTemplateInstantiator.java   |  20 ++
 .../camp/test/mock/web/MockWebPlatform.java     | 113 +++++++++
 .../test/platform/BasicCampPlatformTest.java    |  69 ++++++
 .../camp/spi/pdp/pdp-single-artifact.yaml       |   9 +
 .../camp/spi/pdp/pdp-single-service.yaml        |  11 +
 .../pdp/yaml-sample-toy-interpreter-result.yaml |   4 +
 .../spi/pdp/yaml-sample-toy-interpreter.yaml    |  10 +
 camp/camp-server/pom.xml                        | 115 +++++++++
 .../io/brooklyn/camp/CampRestResources.java     |  52 ++++
 .../main/java/io/brooklyn/camp/CampServer.java  | 167 +++++++++++++
 .../java/io/brooklyn/camp/dto/ApiErrorDto.java  | 101 ++++++++
 .../camp/dto/ApplicationComponentDto.java       |  54 ++++
 .../dto/ApplicationComponentTemplateDto.java    |  26 ++
 .../java/io/brooklyn/camp/dto/AssemblyDto.java  |  59 +++++
 .../brooklyn/camp/dto/AssemblyTemplateDto.java  |  54 ++++
 .../main/java/io/brooklyn/camp/dto/DtoBase.java |  13 +
 .../brooklyn/camp/dto/DtoCustomAttributes.java  |  48 ++++
 .../main/java/io/brooklyn/camp/dto/LinkDto.java |  54 ++++
 .../brooklyn/camp/dto/PlatformComponentDto.java |  64 +++++
 .../camp/dto/PlatformComponentTemplateDto.java  |  26 ++
 .../java/io/brooklyn/camp/dto/PlatformDto.java  | 113 +++++++++
 .../java/io/brooklyn/camp/dto/ResourceDto.java  |  94 +++++++
 .../rest/resource/AbstractCampRestResource.java |  38 +++
 .../camp/rest/resource/ApidocRestResource.java  |  13 +
 .../ApplicationComponentRestResource.java       |  32 +++
 ...pplicationComponentTemplateRestResource.java |  32 +++
 .../rest/resource/AssemblyRestResource.java     |  34 +++
 .../resource/AssemblyTemplateRestResource.java  |  70 ++++++
 .../resource/PlatformComponentRestResource.java |  32 +++
 .../PlatformComponentTemplateRestResource.java  |  32 +++
 .../rest/resource/PlatformRestResource.java     |  71 ++++++
 .../io/brooklyn/camp/rest/util/CampJsons.java   |  21 ++
 .../camp/rest/util/CampRestContext.java         |  32 +++
 .../brooklyn/camp/rest/util/CampRestGuavas.java |  14 ++
 .../io/brooklyn/camp/rest/util/DtoFactory.java  | 158 ++++++++++++
 .../camp/rest/util/WebResourceUtils.java        |  42 ++++
 .../ApplicationCompomentTemplateDtoTest.java    |  31 +++
 .../java/io/brooklyn/camp/dto/BasicDtoTest.java |  72 ++++++
 .../java/io/brooklyn/camp/dto/LinkDtoTest.java  |  44 ++++
 .../dto/PlatformCompomentTemplateDtoTest.java   |  31 +++
 .../io/brooklyn/camp/dto/ResourceDtoTest.java   |  59 +++++
 .../rest/resource/PlatformRestResourceTest.java |  24 ++
 .../test/fixture/AbstractRestResourceTest.java  |  68 +++++
 .../camp/test/fixture/InMemoryCamp.java         |  35 +++
 camp/pom.xml                                    |  27 ++
 core/pom.xml                                    |  18 ++
 .../api/AssemblyTemplateSpecInstantiator.java   |  12 +
 .../api/HasBrooklynManagementContext.java       |   9 +
 .../brooklyn/catalog/CatalogPredicates.java     |  51 ++--
 .../catalog/internal/BasicBrooklynCatalog.java  | 221 ++++++++++++-----
 .../catalog/internal/CatalogClasspathDo.java    |  65 +++--
 .../internal/CatalogConfigurationDto.java       |  13 +-
 .../brooklyn/catalog/internal/CatalogDo.java    |  53 ++--
 .../brooklyn/catalog/internal/CatalogDto.java   |  71 +++++-
 .../catalog/internal/CatalogDtoUtils.java       |  52 ----
 .../catalog/internal/CatalogEntityItemDto.java  |   9 +-
 .../catalog/internal/CatalogItemDo.java         |  82 ++++++-
 .../internal/CatalogItemDtoAbstract.java        |  71 +++---
 .../brooklyn/catalog/internal/CatalogItems.java |  56 +++++
 .../catalog/internal/CatalogLibrariesDo.java    |  56 +++++
 .../catalog/internal/CatalogLibrariesDto.java   |  64 +++++
 .../catalog/internal/CatalogPolicyItemDto.java  |   9 +-
 .../internal/CatalogTemplateItemDto.java        |  11 +-
 .../catalog/internal/CatalogXmlSerializer.java  |  14 +-
 .../brooklyn/config/BrooklynServerConfig.java   |  15 ++
 .../entity/basic/BrooklynConfigKeys.java        |   6 +-
 .../entity/proxying/InternalEntityFactory.java  |   7 +-
 .../dto/BasicManagementNodeSyncRecord.java      |  12 +-
 .../java/brooklyn/event/feed/ssh/SshFeed.java   |   2 +-
 .../brooklyn/management/ha/OsgiManager.java     | 105 ++++++++
 .../internal/AbstractManagementContext.java     |  10 +-
 .../internal/LocalManagementContext.java        |  18 ++
 .../internal/ManagementContextInternal.java     |   8 +
 .../NonDeploymentManagementContext.java         |   6 +
 .../src/main/java/brooklyn/util/osgi/Osgis.java | 157 ++++++++++++
 .../lite/CampPlatformWithJustBrooklynMgmt.java  |  23 ++
 .../brooklyn/camp/lite/CampYamlLiteTest.java    | 107 ++++++++
 .../brooklyn/camp/lite/TestAppAssembly.java     |  18 ++
 .../camp/lite/TestAppAssemblyInstantiator.java  |  67 +++++
 .../catalog/internal/CatalogDtoTest.java        |  69 +++---
 .../catalog/internal/CatalogLoadTest.java       |  46 ++++
 .../catalog/internal/CatalogScanTest.java       |  15 +-
 .../brooklyn/entity/basic/EntitySpecTest.java   |  16 ++
 .../management/osgi/OsgiStandaloneTest.java     | 120 +++++++++
 .../entity/LocalManagementContextForTests.java  |   9 +-
 .../camp/lite/test-app-service-blueprint.yaml   |  20 ++
 .../brooklyn/catalog/internal/osgi-catalog.xml  |  11 +
 .../osgi/brooklyn-osgi-test-a_0.1.0.jar         | Bin 0 -> 2055 bytes
 .../osgi/brooklyn-tests-osgi-entities-0.1.0.jar | Bin 0 -> 4810 bytes
 pom.xml                                         |   4 +
 usage/camp/pom.xml                              |   6 +-
 .../camp/brooklyn/BrooklynCampConstants.java    |   5 +-
 .../camp/brooklyn/BrooklynCampPlatform.java     |   2 +-
 .../BrooklynAssemblyTemplateInstantiator.java   | 167 ++++++++++---
 .../creation/BrooklynEntityClassResolver.java   |  69 +++++-
 .../spi/creation/BrooklynEntityMatcher.java     |  88 +++----
 .../spi/creation/BrooklynYamlTypeLoader.java    |  11 +-
 .../spi/dsl/BrooklynDslInterpreter.java         |   2 +-
 .../lookup/AbstractTemplateBrooklynLookup.java  |   7 +-
 .../lookup/AssemblyTemplateBrooklynLookup.java  |  18 +-
 ...PlatformComponentTemplateBrooklynLookup.java |   7 +-
 .../platform/BrooklynImmutableCampPlatform.java |   1 +
 .../platform/HasBrooklynManagementContext.java  |   9 -
 .../brooklyn/EmptySoftwareProcessYamlTest.java  |   5 +-
 .../io/brooklyn/camp/brooklyn/WrapAppTest.java  |  75 ++++++
 usage/cli/src/main/java/brooklyn/cli/Main.java  |   8 +-
 usage/launcher/pom.xml                          |   8 +-
 .../brooklyn/launcher/BrooklynLauncher.java     |   8 +-
 .../main/java/brooklyn/rest/api/CatalogApi.java |  14 +-
 .../rest/domain/CatalogEntitySummary.java       |   5 +-
 .../rest/domain/CatalogItemSummary.java         |  28 ++-
 .../rest/domain/CatalogPolicySummary.java       |   2 +-
 .../resources/AbstractBrooklynRestResource.java |   5 +-
 .../rest/resources/CatalogResource.java         |  37 ++-
 .../rest/transform/CatalogTransformer.java      |  26 +-
 .../rest/util/BrooklynRestResourceUtils.java    |   9 +-
 .../rest/util/DefaultExceptionMapper.java       |   2 +-
 .../rest/resources/CatalogResourceTest.java     |  48 ++--
 161 files changed, 7162 insertions(+), 509 deletions(-)
----------------------------------------------------------------------



[15/45] git commit: BROOKLYN-13: adds BrooklynCatalog.addItem(yaml)

Posted by he...@apache.org.
BROOKLYN-13: adds BrooklynCatalog.addItem(yaml)

- not yet implemented in BasicBrooklynCatalog, as can’t yet parse yaml


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

Branch: refs/heads/master
Commit: 195410954dd0ece53bc941c93662591470e13272
Parents: 30093bb
Author: Aled Sage <al...@gmail.com>
Authored: Tue Jul 1 13:59:49 2014 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Tue Jul 1 14:17:19 2014 +0100

----------------------------------------------------------------------
 .../main/java/brooklyn/catalog/BrooklynCatalog.java  |  8 ++++++++
 .../catalog/internal/BasicBrooklynCatalog.java       | 15 +++++++++++++++
 2 files changed, 23 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/19541095/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java b/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
index 29fd1c8..0bbd9d3 100644
--- a/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
+++ b/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
@@ -26,6 +26,14 @@ public interface BrooklynCatalog {
     <T> Class<? extends T> loadClass(CatalogItem<T> item);
     <T> Class<? extends T> loadClassByType(String typeName, Class<T> typeClass);
 
+    
+    /**
+     * Adds an item (represented in yaml) to the catalog.
+     * 
+     * @throws IllegalArgumentException if the yaml was invalid
+     */
+    CatalogItem<?> addItem(String yaml);
+    
     /**
      * adds an item to the 'manual' catalog;
      * this does not update the classpath or have a record to the java Class

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/19541095/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 d6b5ff0..f3547dd 100644
--- a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
@@ -116,6 +116,21 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         throw new IllegalStateException("Cannot unwrap catalog item '"+item+"' (type "+item.getClass()+") to restore DTO");
     }
 
+    private <T> CatalogItemDtoAbstract<T> getAbstractCatalogItem(String yaml) {
+        // FIXME Need to parse yaml to extract CatalogItem info
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public CatalogItem<?> addItem(String yaml) {
+        log.debug("Adding manual catalog item to "+mgmt+": "+yaml);
+        Preconditions.checkNotNull(yaml, "yaml");
+        if (manualAdditionsCatalog==null) loadManualAdditionsCatalog();
+        CatalogItemDtoAbstract<Object> itemDto = getAbstractCatalogItem(yaml);
+        manualAdditionsCatalog.addEntry(itemDto);
+        return itemDto;
+    }
+
     @Override
     public void addItem(CatalogItem<?> item) {
         log.debug("Adding manual catalog item to "+mgmt+": "+item);


[07/45] git commit: Deprecate BrooklynCatalog.addItem and remove addToClasspath

Posted by he...@apache.org.
Deprecate BrooklynCatalog.addItem and remove addToClasspath


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

Branch: refs/heads/master
Commit: edcaee4d5df5ec1b2b1a577ead0646b335735516
Parents: 0263fa1
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Mon Jun 30 17:23:37 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Tue Jul 1 13:37:37 2014 +0100

----------------------------------------------------------------------
 .../java/brooklyn/catalog/BrooklynCatalog.java  | 42 ++++++++++----------
 .../catalog/internal/BasicBrooklynCatalog.java  | 21 +---------
 2 files changed, 24 insertions(+), 39 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/edcaee4d/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java b/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
index 720a2bc..29fd1c8 100644
--- a/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
+++ b/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
@@ -4,47 +4,49 @@ import com.google.common.base.Predicate;
 
 public interface BrooklynCatalog {
 
-    /** finds the item with the given ID, or null if not found */
+    /** @return The item with the given ID, or null if not found */
     CatalogItem<?> getCatalogItem(String id);
-    
+
+
     /** variant of {@link #getCatalogItem(String)} which checks (and casts) type for convenience
      * (returns null if type does not match) */
     <T> CatalogItem<T> getCatalogItem(Class<T> type, String id);
-    
-    /** returns all items in the catalog */
+
+    /** @return All items in the catalog */
     <T> Iterable<CatalogItem<T>> getCatalogItems();
 
     /** convenience for filtering items in the catalog; see CatalogPredicates for useful filters */
     <T> Iterable<CatalogItem<T>> getCatalogItems(Predicate<? super CatalogItem<T>> filter);
 
-    /** returns the classloader which should be used to load classes and entities;
+    /** @return The classloader which should be used to load classes and entities;
      * this includes all the catalog's classloaders in the right order */
     public ClassLoader getRootClassLoader();
-    
+
     /** throws exceptions if any problems */
     <T> Class<? extends T> loadClass(CatalogItem<T> item);
     <T> Class<? extends T> loadClassByType(String typeName, Class<T> typeClass);
-    
-    /** adds an item to the 'manual' catalog;
-     * this does not update the classpath or have a record to the java Class,
-     * so callers of this method will typically also need to call 
-     * {@link #addToClasspath(String)} or {@link #addToClasspath(ClassLoader)} */
+
+    /**
+     * adds an item to the 'manual' catalog;
+     * this does not update the classpath or have a record to the java Class
+     *
+     * @deprecated since 0.7.0 Construct catalogs with OSGi bundles instead
+     */
+    @Deprecated
     void addItem(CatalogItem<?> item);
-    
+
     /** creates a catalog item and adds it to the 'manual' catalog,
      * with the corresponding Class definition (loaded by a classloader)
      * registered and available in the classloader.
-     * <p> 
+     * <p>
      * note that the class will be available for this session only,
      * although the record of the item will appear in the catalog DTO if exported,
      * so it is recommended to edit the 'manual' catalog DTO if using it to
-     * generate a catalog, either adding the appropriate classpath URL or removing this entry. */
+     * generate a catalog, either adding the appropriate classpath URL or removing this entry.
+     *
+     * @deprecated since 0.7.0 Construct catalogs with OSGi bundles instead
+     */
+    @Deprecated
     CatalogItem<?> addItem(Class<?> clazz);
 
-    /** adds a classpath entry which will be used by the 'manual' catalog */
-    void addToClasspath(ClassLoader loader);
-
-    /** adds a classpath entry which will be used by the 'manual' catalog */
-    void addToClasspath(String url);
-    
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/edcaee4d/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 02cbcf1..d6b5ff0 100644
--- a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
@@ -1,7 +1,5 @@
 package brooklyn.catalog.internal;
 
-import java.net.MalformedURLException;
-import java.net.URL;
 import java.util.NoSuchElementException;
 
 import javax.annotation.Nullable;
@@ -134,23 +132,8 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         manualAdditionsClasses.addClass(type);
         return manualAdditionsCatalog.classpath.addCatalogEntry(type);
     }
-    
-    @Override
-    public void addToClasspath(ClassLoader loader) {
-        if (manualAdditionsCatalog==null) loadManualAdditionsCatalog();
-        manualAdditionsCatalog.classpath.addToClasspath(loader);
-    }
-    
-    @Override
-    public void addToClasspath(String url) {
-        if (manualAdditionsCatalog==null) loadManualAdditionsCatalog();
-        try {
-            manualAdditionsCatalog.classpath.addToClasspath(new URL(url), true);
-        } catch (MalformedURLException e) {
-            throw Exceptions.propagate(e);
-        }
-    }
-    
+
+    @Deprecated
     private synchronized void loadManualAdditionsCatalog() {
         if (manualAdditionsCatalog!=null) return;
         CatalogDto manualAdditionsCatalogDto = CatalogDto.newNamedInstance(


[26/45] git commit: Merge remote-tracking branch 'ahgittin/camp-in-brooklyn' into osgi2

Posted by he...@apache.org.
Merge remote-tracking branch 'ahgittin/camp-in-brooklyn' into osgi2


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

Branch: refs/heads/master
Commit: c664f5eb3fdbdef676312ca62398d0226d86b1a5
Parents: a391522 646e202
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Wed Jul 2 16:13:19 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Wed Jul 2 16:13:19 2014 +0100

----------------------------------------------------------------------
 camp/README.md                                  |  17 ++
 camp/camp-base/notes.txt                        |  64 +++++
 camp/camp-base/pom.xml                          |  67 +++++
 .../brooklyn/camp/AggregatingCampPlatform.java  | 113 +++++++++
 .../io/brooklyn/camp/BasicCampPlatform.java     | 122 +++++++++
 .../java/io/brooklyn/camp/CampPlatform.java     |  58 +++++
 .../camp/commontypes/RepresentationSkew.java    |   5 +
 .../io/brooklyn/camp/spi/AbstractResource.java  | 176 +++++++++++++
 .../brooklyn/camp/spi/ApplicationComponent.java |  78 ++++++
 .../camp/spi/ApplicationComponentTemplate.java  |  39 +++
 .../java/io/brooklyn/camp/spi/Assembly.java     |  94 +++++++
 .../io/brooklyn/camp/spi/AssemblyTemplate.java  | 102 ++++++++
 .../main/java/io/brooklyn/camp/spi/Link.java    |  22 ++
 .../io/brooklyn/camp/spi/PlatformComponent.java |  86 +++++++
 .../camp/spi/PlatformComponentTemplate.java     |  37 +++
 .../brooklyn/camp/spi/PlatformRootSummary.java  |  55 +++++
 .../brooklyn/camp/spi/PlatformTransaction.java  |  28 +++
 .../spi/collection/AbstractResourceLookup.java  |  17 ++
 .../collection/AggregatingResourceLookup.java   |  38 +++
 .../spi/collection/BasicResourceLookup.java     |  53 ++++
 .../camp/spi/collection/ResolvableLink.java     |  19 ++
 .../camp/spi/collection/ResourceLookup.java     |  29 +++
 .../AssemblyTemplateInstantiator.java           |  12 +
 .../BasicAssemblyTemplateInstantiator.java      |  18 ++
 .../java/io/brooklyn/camp/spi/pdp/Artifact.java |  82 +++++++
 .../brooklyn/camp/spi/pdp/ArtifactContent.java  |  47 ++++
 .../camp/spi/pdp/ArtifactRequirement.java       |  55 +++++
 .../spi/pdp/AssemblyTemplateConstructor.java    |  76 ++++++
 .../brooklyn/camp/spi/pdp/DeploymentPlan.java   |  93 +++++++
 .../java/io/brooklyn/camp/spi/pdp/Service.java  |  77 ++++++
 .../camp/spi/pdp/ServiceCharacteristic.java     |  55 +++++
 .../brooklyn/camp/spi/resolve/PdpMatcher.java   |  33 +++
 .../brooklyn/camp/spi/resolve/PdpProcessor.java | 154 ++++++++++++
 .../camp/spi/resolve/PlanInterpreter.java       |  95 +++++++
 .../interpret/PlanInterpretationContext.java    | 134 ++++++++++
 .../interpret/PlanInterpretationNode.java       | 245 +++++++++++++++++++
 .../main/java/io/brooklyn/util/yaml/Yamls.java  |  89 +++++++
 .../src/main/resources/logback-custom.xml       |   9 +
 .../pdp/DeploymentPlanToyInterpreterTest.java   |  96 ++++++++
 .../io/brooklyn/camp/spi/pdp/PdpYamlTest.java   |  60 +++++
 .../web/MockAssemblyTemplateInstantiator.java   |  20 ++
 .../camp/test/mock/web/MockWebPlatform.java     | 104 ++++++++
 .../test/platform/BasicCampPlatformTest.java    |  69 ++++++
 .../camp/spi/pdp/pdp-single-artifact.yaml       |   9 +
 .../camp/spi/pdp/pdp-single-service.yaml        |  11 +
 .../pdp/yaml-sample-toy-interpreter-result.yaml |   4 +
 .../spi/pdp/yaml-sample-toy-interpreter.yaml    |  10 +
 camp/camp-server/pom.xml                        | 115 +++++++++
 .../io/brooklyn/camp/CampRestResources.java     |  52 ++++
 .../main/java/io/brooklyn/camp/CampServer.java  | 167 +++++++++++++
 .../java/io/brooklyn/camp/dto/ApiErrorDto.java  | 101 ++++++++
 .../camp/dto/ApplicationComponentDto.java       |  54 ++++
 .../dto/ApplicationComponentTemplateDto.java    |  26 ++
 .../java/io/brooklyn/camp/dto/AssemblyDto.java  |  59 +++++
 .../brooklyn/camp/dto/AssemblyTemplateDto.java  |  54 ++++
 .../main/java/io/brooklyn/camp/dto/DtoBase.java |  13 +
 .../brooklyn/camp/dto/DtoCustomAttributes.java  |  48 ++++
 .../main/java/io/brooklyn/camp/dto/LinkDto.java |  54 ++++
 .../brooklyn/camp/dto/PlatformComponentDto.java |  64 +++++
 .../camp/dto/PlatformComponentTemplateDto.java  |  26 ++
 .../java/io/brooklyn/camp/dto/PlatformDto.java  | 113 +++++++++
 .../java/io/brooklyn/camp/dto/ResourceDto.java  |  94 +++++++
 .../rest/resource/AbstractCampRestResource.java |  38 +++
 .../camp/rest/resource/ApidocRestResource.java  |  13 +
 .../ApplicationComponentRestResource.java       |  32 +++
 ...pplicationComponentTemplateRestResource.java |  32 +++
 .../rest/resource/AssemblyRestResource.java     |  34 +++
 .../resource/AssemblyTemplateRestResource.java  |  70 ++++++
 .../resource/PlatformComponentRestResource.java |  32 +++
 .../PlatformComponentTemplateRestResource.java  |  32 +++
 .../rest/resource/PlatformRestResource.java     |  71 ++++++
 .../io/brooklyn/camp/rest/util/CampJsons.java   |  21 ++
 .../camp/rest/util/CampRestContext.java         |  32 +++
 .../brooklyn/camp/rest/util/CampRestGuavas.java |  14 ++
 .../io/brooklyn/camp/rest/util/DtoFactory.java  | 158 ++++++++++++
 .../camp/rest/util/WebResourceUtils.java        |  42 ++++
 .../ApplicationCompomentTemplateDtoTest.java    |  31 +++
 .../java/io/brooklyn/camp/dto/BasicDtoTest.java |  72 ++++++
 .../java/io/brooklyn/camp/dto/LinkDtoTest.java  |  44 ++++
 .../dto/PlatformCompomentTemplateDtoTest.java   |  31 +++
 .../io/brooklyn/camp/dto/ResourceDtoTest.java   |  59 +++++
 .../rest/resource/PlatformRestResourceTest.java |  24 ++
 .../test/fixture/AbstractRestResourceTest.java  |  68 +++++
 .../camp/test/fixture/InMemoryCamp.java         |  35 +++
 camp/pom.xml                                    |  27 ++
 core/pom.xml                                    |  12 +
 .../brooklyn/camp/lite/CampYamlLiteTest.java    |  75 ++++++
 .../brooklyn/camp/lite/TestAppAssembly.java     |  18 ++
 .../camp/lite/TestAppAssemblyInstantiator.java  |  43 ++++
 .../camp/lite/test-app-service-blueprint.yaml   |  11 +
 pom.xml                                         |   3 +
 usage/camp/pom.xml                              |   6 +-
 usage/launcher/pom.xml                          |   8 +-
 93 files changed, 5193 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c664f5eb/core/pom.xml
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c664f5eb/pom.xml
----------------------------------------------------------------------


[43/45] git commit: This closes #44

Posted by he...@apache.org.
This closes #44


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

Branch: refs/heads/master
Commit: 6bc36e30882c75223c8a0867d61f4386019be311
Parents: f28d9cc a64c601
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Fri Jul 4 10:43:52 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri Jul 4 10:43:52 2014 +0100

----------------------------------------------------------------------
 .../webapp/assets/tpl/app-add-wizard/required-config-entry.html    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------



[38/45] git commit: Merge pull request #1 from sjcorbett/feature/brooklyn-catalogue-yaml

Posted by he...@apache.org.
Merge pull request #1 from sjcorbett/feature/brooklyn-catalogue-yaml

Feature/brooklyn catalogue yaml

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

Branch: refs/heads/master
Commit: 343fe332ae86c1237eeabf8b9a506b69330033a2
Parents: d709b7e f03f52f
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Jul 3 18:28:55 2014 +0300
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu Jul 3 18:28:55 2014 +0300

----------------------------------------------------------------------
 .../brooklyn/camp/spi/pdp/DeploymentPlan.java   | 27 +++++-
 .../catalog/internal/BasicBrooklynCatalog.java  | 24 +++++-
 .../catalog/internal/CatalogLibrariesDto.java   | 40 ++++++++-
 .../brooklyn/camp/lite/CampYamlLiteTest.java    | 13 ++-
 .../camp/lite/test-app-service-blueprint.yaml   |  9 ++
 .../spi/creation/BrooklynEntityMatcher.java     | 88 ++++++++++----------
 .../spi/dsl/BrooklynDslInterpreter.java         |  2 +-
 7 files changed, 150 insertions(+), 53 deletions(-)
----------------------------------------------------------------------



[16/45] git commit: BROOKLYN-13: REST PUT /catalog expects yaml rather than groovy

Posted by he...@apache.org.
BROOKLYN-13: REST PUT /catalog expects yaml rather than groovy


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

Branch: refs/heads/master
Commit: b3d2c03681cc4d1e16818430b96bcbe2342f2a46
Parents: 1954109
Author: Aled Sage <al...@gmail.com>
Authored: Tue Jul 1 14:00:08 2014 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Tue Jul 1 14:17:19 2014 +0100

----------------------------------------------------------------------
 .../main/java/brooklyn/rest/api/CatalogApi.java | 14 +++----
 .../rest/resources/CatalogResource.java         | 26 ++++++++++--
 .../rest/util/BrooklynRestResourceUtils.java    |  3 +-
 .../rest/util/DefaultExceptionMapper.java       |  2 +-
 .../rest/resources/CatalogResourceTest.java     | 43 ++++++++++----------
 5 files changed, 54 insertions(+), 34 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b3d2c036/usage/rest-api/src/main/java/brooklyn/rest/api/CatalogApi.java
----------------------------------------------------------------------
diff --git a/usage/rest-api/src/main/java/brooklyn/rest/api/CatalogApi.java b/usage/rest-api/src/main/java/brooklyn/rest/api/CatalogApi.java
index fbcb37f..8e0d213 100644
--- a/usage/rest-api/src/main/java/brooklyn/rest/api/CatalogApi.java
+++ b/usage/rest-api/src/main/java/brooklyn/rest/api/CatalogApi.java
@@ -25,19 +25,19 @@ import java.util.List;
 public interface CatalogApi {
 
     @POST
-    @ApiOperation(value = "Add a new entity or policy type to the catalog by uploading a Groovy script from browser using multipart/form-data",
+    @ApiOperation(value = "Add a catalog item (e.g. new entity or policy type) by uploading YAML descriptor from browser using multipart/form-data",
         responseClass = "String")
     @Consumes(MediaType.MULTIPART_FORM_DATA)
     public Response createFromMultipart(
-        @ApiParam(name = "groovyCode", value = "multipart/form-data file input field")
-        @FormDataParam("groovyCode") InputStream uploadedInputStream,
-        @FormDataParam("groovyCode") FormDataContentDisposition fileDetail) throws IOException ;
+        @ApiParam(name = "yaml", value = "multipart/form-data file input field")
+        @FormDataParam("yaml") InputStream uploadedInputStream,
+        @FormDataParam("yaml") FormDataContentDisposition fileDetail) throws IOException ;
     
     @POST
-    @ApiOperation(value = "Add a new entity or policy type by uploading a Groovy script", responseClass = "String")
+    @ApiOperation(value = "Add a catalog item (e.g. new entity or policy type) by uploading YAML descriptor", responseClass = "String")
     public Response create(
-            @ApiParam(name = "groovyCode", value = "Groovy code for the entity or policy", required = true)
-            @Valid String groovyCode
+            @ApiParam(name = "yaml", value = "YAML descriptor of catalog item", required = true)
+            @Valid String yaml
     ) ;
 
     @GET

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b3d2c036/usage/rest-server/src/main/java/brooklyn/rest/resources/CatalogResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/resources/CatalogResource.java b/usage/rest-server/src/main/java/brooklyn/rest/resources/CatalogResource.java
index 746f29d..fe266cf 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/resources/CatalogResource.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/resources/CatalogResource.java
@@ -19,6 +19,7 @@ import brooklyn.catalog.CatalogItem;
 import brooklyn.catalog.CatalogPredicates;
 import brooklyn.entity.Entity;
 import brooklyn.rest.api.CatalogApi;
+import brooklyn.rest.domain.ApiError;
 import brooklyn.rest.domain.CatalogEntitySummary;
 import brooklyn.rest.domain.CatalogItemSummary;
 import brooklyn.rest.transform.CatalogTransformer;
@@ -51,12 +52,31 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
 
     @Override
     public Response createFromMultipart(InputStream uploadedInputStream, FormDataContentDisposition fileDetail) throws IOException {
-      return brooklyn().createCatalogEntryFromGroovyCode(CharStreams.toString(new InputStreamReader(uploadedInputStream, Charsets.UTF_8)));
+      return create(CharStreams.toString(new InputStreamReader(uploadedInputStream, Charsets.UTF_8)));
     }
 
     @Override
-    public Response create(String groovyCode ) {
-        return brooklyn().createCatalogEntryFromGroovyCode(groovyCode);
+    public Response create(String yaml) {
+        CatalogItem<?> item;
+        try {
+            item = brooklyn().getCatalog().addItem(yaml);
+        } catch (IllegalArgumentException e) {
+            return Response.status(Status.BAD_REQUEST)
+                    .type(MediaType.APPLICATION_JSON)
+                    .entity(ApiError.of(e))
+                    .build();
+        }
+        String itemId = item.getId();
+        log.info("REST created catalog item: "+item);
+        
+        // FIXME configurations/ not supported
+        switch (item.getCatalogItemType()) {
+        case TEMPLATE: return Response.created(URI.create("applications/" + itemId)).build();
+        case ENTITY: return Response.created(URI.create("entities/" + itemId)).build();
+        case POLICY: return Response.created(URI.create("policies/" + itemId)).build();
+        case CONFIGURATION: return Response.created(URI.create("configurations/" + itemId)).build();
+        default: throw new IllegalStateException("Unsupported catalog item type "+item.getCatalogItemType()+": "+item);
+        }
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b3d2c036/usage/rest-server/src/main/java/brooklyn/rest/util/BrooklynRestResourceUtils.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/util/BrooklynRestResourceUtils.java b/usage/rest-server/src/main/java/brooklyn/rest/util/BrooklynRestResourceUtils.java
index d6ed824..4803175 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/util/BrooklynRestResourceUtils.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/util/BrooklynRestResourceUtils.java
@@ -2,7 +2,6 @@ package brooklyn.rest.util;
 
 import static brooklyn.rest.util.WebResourceUtils.notFound;
 import static com.google.common.collect.Iterables.transform;
-
 import brooklyn.management.entitlement.Entitlements;
 import groovy.lang.GroovyClassLoader;
 
@@ -24,6 +23,7 @@ import org.slf4j.LoggerFactory;
 
 import brooklyn.catalog.BrooklynCatalog;
 import brooklyn.catalog.CatalogItem;
+import brooklyn.catalog.CatalogItem.CatalogItemType;
 import brooklyn.config.ConfigKey;
 import brooklyn.enricher.Enrichers;
 import brooklyn.entity.Application;
@@ -411,6 +411,7 @@ public class BrooklynRestResourceUtils {
     }
 
 
+    @Deprecated
     @SuppressWarnings({ "rawtypes" })
     public Response createCatalogEntryFromGroovyCode(String groovyCode) {
         ClassLoader parent = getCatalog().getRootClassLoader();

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b3d2c036/usage/rest-server/src/main/java/brooklyn/rest/util/DefaultExceptionMapper.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/util/DefaultExceptionMapper.java b/usage/rest-server/src/main/java/brooklyn/rest/util/DefaultExceptionMapper.java
index 5d33c91..4809c63 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/util/DefaultExceptionMapper.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/util/DefaultExceptionMapper.java
@@ -43,7 +43,7 @@ public class DefaultExceptionMapper implements ExceptionMapper<Throwable> {
             return wae.getResponse();
         }
 
-        // Assume ClassCoercionExceptions are caused by TypeCoercions from input paramters gone wrong.
+        // Assume ClassCoercionExceptions are caused by TypeCoercions from input parameters gone wrong.
         if (throwable instanceof ClassCoercionException)
             return responseBadRequestJson(ApiError.of(throwable));
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b3d2c036/usage/rest-server/src/test/java/brooklyn/rest/resources/CatalogResourceTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/brooklyn/rest/resources/CatalogResourceTest.java b/usage/rest-server/src/test/java/brooklyn/rest/resources/CatalogResourceTest.java
index b9f9d51..2a25dfd 100644
--- a/usage/rest-server/src/test/java/brooklyn/rest/resources/CatalogResourceTest.java
+++ b/usage/rest-server/src/test/java/brooklyn/rest/resources/CatalogResourceTest.java
@@ -44,34 +44,33 @@ public class CatalogResourceTest extends BrooklynRestResourceTest {
     addResource(new CatalogResource());
   }
 
-  @Test
+  @Test(enabled=false, groups="WIP") // FIXME broken until BasicBrooklynCatalog can parse the yaml
   public void testRegisterCustomEntity() {
-    String groovyScript = "package brooklyn.rest.entities.custom\n" +
-        "" +
-        "import brooklyn.entity.basic.AbstractEntity\n" +
-        "import brooklyn.entity.Entity\n" +
-        "import brooklyn.event.basic.BasicConfigKey\n" +
-        "" +
-        "class DummyEntity extends AbstractEntity {\n" +
-        "  public static final BasicConfigKey<String> DUMMY_CFG = [ String, \"dummy.config\", \"Dummy Config\", \"xxx\" ]\n" +
-        "  public DummyEntity(Map properties=[:], Entity parent=null) {\n" +
-        "        super(properties, parent)" +
-        "  }" +
-        "}\n";
+    String yaml =
+        "brooklyn.catalog:\n"+
+        "- id: my.catalog.app.id\n"+
+        "- name: My Catalog App\n"+
+        "- description: My description\n"+
+        "- icon_url: classpath://path/to/myicon.jpg\n"+
+        "- version: 0.1.2\n"+
+        "- bundles:\n"+
+        "- url: http://myurl/my.jar\n"+
+        "\n"+
+        "services:\n"+
+        "- type: brooklyn.test.entity.TestEntity\n";
 
     ClientResponse response = client().resource("/v1/catalog")
-        .post(ClientResponse.class, groovyScript);
+        .post(ClientResponse.class, yaml);
 
     assertEquals(response.getStatus(), Response.Status.CREATED.getStatusCode());
 
-    Set<String> entities = client().resource("/v1/catalog/entities?name=dummy")
-        .get(new GenericType<Set<String>>() {
-        });
-    assertTrue(entities.contains("brooklyn.rest.entities.custom.DummyEntity"));
-
-    CatalogEntitySummary entity = client().resource(response.getLocation())
-        .get(CatalogEntitySummary.class);
-    assertTrue(entity.toString().contains("dummy.config"), "ENTITY was: "+entity);
+    CatalogEntitySummary entityItem = client().resource("/v1/catalog/entities/my.catalog.app.id")
+            .get(CatalogEntitySummary.class);
+    assertEquals(entityItem.getId(), "my.catalog.app.id");
+    assertEquals(entityItem.getName(), "My Catalog App");
+    assertEquals(entityItem.getDescription(), "My description");
+    assertEquals(entityItem.getIconUrl(), "classpath://path/to/myicon.jpg");
+    assertEquals(entityItem.getType(), "brooklyn.test.entity.TestEntity");
   }
 
   @Test


[20/45] git commit: add README for CAMP and test in core that it can access some of the CAMP assembly items, with simple instantiators

Posted by he...@apache.org.
add README for CAMP and test in core that it can access some of the CAMP assembly items, with simple instantiators


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

Branch: refs/heads/master
Commit: 646e20229cac1ea1d22da867fd972bb59412f197
Parents: 7d5ce73
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Wed Jul 2 11:52:28 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Wed Jul 2 11:53:52 2014 +0100

----------------------------------------------------------------------
 camp/README.md                                  | 17 +++++
 .../camp/test/mock/web/MockWebPlatform.java     | 33 +++++++++
 core/pom.xml                                    |  7 ++
 .../brooklyn/camp/lite/CampYamlLiteTest.java    | 75 ++++++++++++++++++++
 .../brooklyn/camp/lite/TestAppAssembly.java     | 18 +++++
 .../camp/lite/TestAppAssemblyInstantiator.java  | 43 +++++++++++
 .../camp/lite/test-app-service-blueprint.yaml   | 11 +++
 7 files changed, 204 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/646e2022/camp/README.md
----------------------------------------------------------------------
diff --git a/camp/README.md b/camp/README.md
new file mode 100644
index 0000000..db71dd5
--- /dev/null
+++ b/camp/README.md
@@ -0,0 +1,17 @@
+OASIS CAMP Server
+=================
+
+The projects in this directory provide the necessary components for a server which 
+speaks the CAMP REST API and which understands the CAMP YAML plan language.
+
+It is not dependent on Brooklyn (apart from utils) and does not expose any
+types.  The brooklyn-camp project provides the links for Brooklyn entities
+to be available through the CAMP REST API, and for Brooklyn to deploy blueprints
+described using the CAMP YAML.
+
+The projects in this directory are designed so they could be used to build
+other CAMP servers not based on Brooklyn, if desired.
+
+These projects are part of the Apache Software Foundation Brooklyn project
+(brooklyn.io) and released under the Apache License 2.0.
+

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/646e2022/camp/camp-base/src/test/java/io/brooklyn/camp/test/mock/web/MockWebPlatform.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/test/java/io/brooklyn/camp/test/mock/web/MockWebPlatform.java b/camp/camp-base/src/test/java/io/brooklyn/camp/test/mock/web/MockWebPlatform.java
index 9ad8d33..e547d91 100644
--- a/camp/camp-base/src/test/java/io/brooklyn/camp/test/mock/web/MockWebPlatform.java
+++ b/camp/camp-base/src/test/java/io/brooklyn/camp/test/mock/web/MockWebPlatform.java
@@ -1,12 +1,15 @@
 package io.brooklyn.camp.test.mock.web;
 
+import brooklyn.util.guava.Maybe;
 import io.brooklyn.camp.BasicCampPlatform;
 import io.brooklyn.camp.spi.ApplicationComponentTemplate;
 import io.brooklyn.camp.spi.AssemblyTemplate;
 import io.brooklyn.camp.spi.PlatformComponentTemplate;
 import io.brooklyn.camp.spi.collection.BasicResourceLookup;
+import io.brooklyn.camp.spi.collection.ResolvableLink;
 import io.brooklyn.camp.spi.pdp.Artifact;
 import io.brooklyn.camp.spi.pdp.AssemblyTemplateConstructor;
+import io.brooklyn.camp.spi.pdp.Service;
 import io.brooklyn.camp.spi.resolve.PdpMatcher;
 
 public class MockWebPlatform {
@@ -53,6 +56,35 @@ public class MockWebPlatform {
             return true;
         }
     };
+
+    public static final PdpMatcher newLiteralServiceTypeToPlatformComponentTemplateMatcher(final BasicCampPlatform platform) {
+        return new PdpMatcher() {
+            public boolean apply(Object item, AssemblyTemplateConstructor atc) {
+                if (!(item instanceof Service)) return false;
+                Service svc = (Service)item;
+                String type = svc.getServiceType();
+                
+                for (ResolvableLink<PlatformComponentTemplate> t: platform.platformComponentTemplates().links()) {
+                    if (type.equals(t.getName())) {
+                        PlatformComponentTemplate pct = PlatformComponentTemplate.builder()
+                            .name(svc.getName())
+                            .customAttribute("serviceType", type)
+                            .description(Maybe.fromNullable(svc.getDescription()).or(t.resolve().getDescription()))
+                            .build();
+                        if (atc!=null)
+                            atc.add(pct);
+                        return true;
+                    }
+                }
+                return false;
+            }
+
+            @Override
+            public boolean accepts(Object deploymentPlanItem) {
+                return apply(deploymentPlanItem, null);
+            }
+        };
+    }
     
     public static <T extends BasicCampPlatform> T populate(T platform) {
         platform.platformComponentTemplates().addAll(APPSERVER, DATABASE);
@@ -60,6 +92,7 @@ public class MockWebPlatform {
         platform.assemblyTemplates().add(ASSEMBLY1);
         
         platform.pdp().addMatcher(WAR_GETS_WAR_MATCHER);
+        platform.pdp().addMatcher(newLiteralServiceTypeToPlatformComponentTemplateMatcher(platform));
         
         return platform;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/646e2022/core/pom.xml
----------------------------------------------------------------------
diff --git a/core/pom.xml b/core/pom.xml
index a7c6846..05dd10b 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -37,6 +37,13 @@
             <artifactId>camp-base</artifactId>
             <version>${brooklyn.version}</version>
         </dependency>
+        <dependency>
+            <groupId>io.brooklyn.camp</groupId>
+            <artifactId>camp-base</artifactId>
+            <version>${brooklyn.version}</version>
+            <classifier>tests</classifier>
+            <scope>test</scope>
+        </dependency>
 
         <dependency>
             <groupId>net.schmizz</groupId>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/646e2022/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java b/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
new file mode 100644
index 0000000..6a17c28
--- /dev/null
+++ b/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
@@ -0,0 +1,75 @@
+package brooklyn.camp.lite;
+
+import io.brooklyn.camp.BasicCampPlatform;
+import io.brooklyn.camp.spi.Assembly;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+import io.brooklyn.camp.spi.pdp.PdpYamlTest;
+import io.brooklyn.camp.test.mock.web.MockWebPlatform;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.Entity;
+import brooklyn.management.internal.LocalManagementContext;
+import brooklyn.test.entity.LocalManagementContextForTests;
+import brooklyn.test.entity.TestApplication;
+import brooklyn.test.entity.TestEntity;
+
+import com.google.common.collect.Iterables;
+
+/** Tests of lightweight CAMP integration. Since the "real" integration is in brooklyn-camp project,
+ * but some aspects of CAMP we want to be able to test here. */
+public class CampYamlLiteTest {
+
+    private static final Logger log = LoggerFactory.getLogger(CampYamlLiteTest.class);
+    
+    protected LocalManagementContext mgmt;
+    
+    @BeforeMethod(alwaysRun=true)
+    public void setUp() {
+        mgmt = new LocalManagementContextForTests();        
+    }
+    
+    @AfterMethod(alwaysRun=true)
+    public void tearDown() {
+        if (mgmt!=null) mgmt.terminate();
+    }
+    
+    /** based on {@link PdpYamlTest} for parsing,
+     * then creating a {@link TestAppAssembly} */
+    @Test
+    public void testYamlServiceMatchAndBrooklynInstantiate() throws IOException {
+        BasicCampPlatform platform = MockWebPlatform.populate(new BasicCampPlatform());
+        Reader input = new InputStreamReader(getClass().getResourceAsStream("test-app-service-blueprint.yaml"));
+        AssemblyTemplate at = platform.pdp().registerDeploymentPlan(input);
+        log.info("AT is:\n"+at.toString());
+        Assert.assertEquals(at.getName(), "sample");
+        Assert.assertEquals(at.getPlatformComponentTemplates().links().size(), 1);
+        
+        // now use brooklyn to instantiate
+        Assembly assembly = new TestAppAssemblyInstantiator(mgmt).instantiate(at, platform);
+        
+        TestApplication app = ((TestAppAssembly)assembly).getBrooklynApp();
+        Assert.assertEquals( app.getConfig(TestEntity.CONF_NAME), "sample" );
+        Map<String, String> map = app.getConfig(TestEntity.CONF_MAP_THING);
+        Assert.assertEquals( map.get("desc"), "Tomcat sample JSP and servlet application." );
+        
+        Assert.assertEquals( app.getChildren().size(), 1 );
+        Entity svc = Iterables.getOnlyElement(app.getChildren());
+        Assert.assertEquals( svc.getConfig(TestEntity.CONF_NAME), "Hello WAR" );
+        map = svc.getConfig(TestEntity.CONF_MAP_THING);
+        Assert.assertEquals( map.get("type"), MockWebPlatform.APPSERVER.getType() );
+        // desc ensures we got the information from the matcher, as this value is NOT in the yaml
+        Assert.assertEquals( map.get("desc"), MockWebPlatform.APPSERVER.getDescription() );
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/646e2022/core/src/test/java/brooklyn/camp/lite/TestAppAssembly.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/camp/lite/TestAppAssembly.java b/core/src/test/java/brooklyn/camp/lite/TestAppAssembly.java
new file mode 100644
index 0000000..0f220a7
--- /dev/null
+++ b/core/src/test/java/brooklyn/camp/lite/TestAppAssembly.java
@@ -0,0 +1,18 @@
+package brooklyn.camp.lite;
+
+import io.brooklyn.camp.spi.Assembly;
+import brooklyn.test.entity.TestApplication;
+
+public class TestAppAssembly extends Assembly {
+
+    private TestApplication brooklynApp;
+
+    public TestAppAssembly(TestApplication brooklynApp) {
+        this.brooklynApp = brooklynApp;
+    }
+    
+    public TestApplication getBrooklynApp() {
+        return brooklynApp;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/646e2022/core/src/test/java/brooklyn/camp/lite/TestAppAssemblyInstantiator.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/camp/lite/TestAppAssemblyInstantiator.java b/core/src/test/java/brooklyn/camp/lite/TestAppAssemblyInstantiator.java
new file mode 100644
index 0000000..a00a3bf
--- /dev/null
+++ b/core/src/test/java/brooklyn/camp/lite/TestAppAssemblyInstantiator.java
@@ -0,0 +1,43 @@
+package brooklyn.camp.lite;
+
+import io.brooklyn.camp.CampPlatform;
+import io.brooklyn.camp.spi.Assembly;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+import io.brooklyn.camp.spi.PlatformComponentTemplate;
+import io.brooklyn.camp.spi.collection.ResolvableLink;
+import io.brooklyn.camp.spi.instantiate.BasicAssemblyTemplateInstantiator;
+import brooklyn.entity.basic.ApplicationBuilder;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.management.internal.LocalManagementContext;
+import brooklyn.test.entity.TestApplication;
+import brooklyn.test.entity.TestEntity;
+import brooklyn.util.collections.MutableMap;
+
+/** simple illustrative instantiator which always makes a {@link TestApplication}, populated with {@link TestEntity} children,
+ * all setting {@link TestEntity#CONF_NAME} for the name in the plan and in the service specs
+ * <p>
+ * the "real" instantiator for brooklyn is in brooklyn-camp project, not visible here, so let's have something we can test */
+public class TestAppAssemblyInstantiator extends BasicAssemblyTemplateInstantiator {
+
+    protected final LocalManagementContext mgmt;
+    
+    public TestAppAssemblyInstantiator(LocalManagementContext mgmt) {
+        this.mgmt = mgmt;
+    }
+    
+    @Override
+    public Assembly instantiate(AssemblyTemplate template, CampPlatform platform) {
+        TestApplication app = ApplicationBuilder.newManagedApp(EntitySpec.create(TestApplication.class)
+            .configure(TestEntity.CONF_NAME, template.getName())
+            .configure(TestEntity.CONF_MAP_THING, MutableMap.of("type", template.getType(), "desc", template.getDescription()))
+            , mgmt);
+        for (ResolvableLink<PlatformComponentTemplate> t: template.getPlatformComponentTemplates().links()) {
+            app.createAndManageChild(EntitySpec.create(TestEntity.class)
+                .configure(TestEntity.CONF_NAME, t.getName())
+                .configure(TestEntity.CONF_MAP_THING, MutableMap.of("type", t.resolve().getType(), "desc", t.resolve().getDescription()))
+                );
+        }
+        return new TestAppAssembly(app);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/646e2022/core/src/test/resources/brooklyn/camp/lite/test-app-service-blueprint.yaml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/brooklyn/camp/lite/test-app-service-blueprint.yaml b/core/src/test/resources/brooklyn/camp/lite/test-app-service-blueprint.yaml
new file mode 100644
index 0000000..96db31c
--- /dev/null
+++ b/core/src/test/resources/brooklyn/camp/lite/test-app-service-blueprint.yaml
@@ -0,0 +1,11 @@
+name: sample
+description: Tomcat sample JSP and servlet application.
+origin: http://www.oracle.com/nCAMP/Hand
+services:
+  -
+    type: io.camp.mock:AppServer
+    name: Hello WAR
+    wars:
+        /: hello.war
+    controller.spec:
+        port: 80


[37/45] git commit: add support for EntitySpec.child and .children

Posted by he...@apache.org.
add support for EntitySpec.child and .children


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

Branch: refs/heads/master
Commit: d709b7e5109cf2b7ba629d6394cbc6173cf98e54
Parents: e96af92
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Jul 3 16:26:35 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu Jul 3 16:26:35 2014 +0100

----------------------------------------------------------------------
 .../brooklyn/entity/proxying/EntitySpec.java    | 23 ++++++++++++++++++--
 .../entity/proxying/InternalEntityFactory.java  |  7 +++++-
 .../brooklyn/entity/basic/EntitySpecTest.java   | 16 ++++++++++++++
 3 files changed, 43 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d709b7e5/api/src/main/java/brooklyn/entity/proxying/EntitySpec.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/entity/proxying/EntitySpec.java b/api/src/main/java/brooklyn/entity/proxying/EntitySpec.java
index a23975e..3055064 100644
--- a/api/src/main/java/brooklyn/entity/proxying/EntitySpec.java
+++ b/api/src/main/java/brooklyn/entity/proxying/EntitySpec.java
@@ -97,7 +97,8 @@ public class EntitySpec<T extends Entity> implements Serializable {
                 .policies(spec.getPolicies())
                 .enricherSpecs(spec.getEnricherSpecs())
                 .enrichers(spec.getEnrichers())
-                .addInitializers(spec.getInitializers());
+                .addInitializers(spec.getInitializers())
+                .children(spec.getChildren());
         
         if (spec.getParent() != null) result.parent(spec.getParent());
         if (spec.getImplementation() != null) result.impl(spec.getImplementation());
@@ -123,6 +124,7 @@ public class EntitySpec<T extends Entity> implements Serializable {
     private final List<Location> locations = Lists.newArrayList();
     private final Set<Class<?>> additionalInterfaces = Sets.newLinkedHashSet();
     private final List<EntityInitializer> entityInitializers = Lists.newArrayList();
+    private final List<EntitySpec<?>> children = Lists.newArrayList();
     private volatile boolean immutable;
     
     public EntitySpec(Class<T> type) {
@@ -174,6 +176,10 @@ public class EntitySpec<T extends Entity> implements Serializable {
         return entityInitializers;
     }
     
+    public List<EntitySpec<?>> getChildren() {
+        return children;
+    }
+    
     /**
      * @return The entity's parent
      */
@@ -272,7 +278,20 @@ public class EntitySpec<T extends Entity> implements Serializable {
         }
         return this;
     }
-        
+
+    public EntitySpec<T> children(Iterable<? extends EntitySpec<?>> children) {
+        checkMutable();
+        Iterables.addAll(this.children, children);
+        return this;
+    }
+
+    /** The supplied class must have a public no-arg constructor. */
+    public EntitySpec<T> child(EntitySpec<?> child) {
+        checkMutable();
+        children.add(child);
+        return this;
+    }
+
     public EntitySpec<T> parent(Entity val) {
         checkMutable();
         parent = checkNotNull(val, "parent");

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d709b7e5/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java b/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
index 67a0208..74b7ad2 100644
--- a/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
+++ b/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
@@ -171,7 +171,12 @@ public class InternalEntityFactory {
             for (Map.Entry<ConfigKey<?>, Object> entry : spec.getConfig().entrySet()) {
                 ((EntityLocal)entity).setConfig((ConfigKey)entry.getKey(), entry.getValue());
             }
-            
+
+            for (EntitySpec<?> childSpec : spec.getChildren()) {
+                Entity child = createEntity(childSpec);
+                ((EntityLocal)entity).addChild(child);
+            }
+
             /* Marked transient so that the task is not needlessly kept around at the highest level.
              * Note that the task is not normally visible in the GUI, because 
              * (a) while it is running, the entity is parentless (and so not in the tree);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d709b7e5/core/src/test/java/brooklyn/entity/basic/EntitySpecTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/basic/EntitySpecTest.java b/core/src/test/java/brooklyn/entity/basic/EntitySpecTest.java
index ef53cc0..6233350 100644
--- a/core/src/test/java/brooklyn/entity/basic/EntitySpecTest.java
+++ b/core/src/test/java/brooklyn/entity/basic/EntitySpecTest.java
@@ -8,6 +8,7 @@ import org.testng.annotations.Test;
 
 import brooklyn.enricher.basic.AbstractEnricher;
 import brooklyn.entity.BrooklynAppUnitTestSupport;
+import brooklyn.entity.Entity;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.event.basic.BasicConfigKey;
 import brooklyn.location.basic.SimulatedLocation;
@@ -44,6 +45,21 @@ public class EntitySpecTest extends BrooklynAppUnitTestSupport {
     }
 
     @Test
+    public void testAddsChidlren() throws Exception {
+        entity = app.createAndManageChild( EntitySpec.create(TestEntity.class)
+            .displayName("child")
+            .child(EntitySpec.create(TestEntity.class)
+                .displayName("grandchild")) );
+        
+        Entity child = Iterables.getOnlyElement(app.getChildren());
+        assertEquals(child, entity);
+        assertEquals(child.getDisplayName(), "child");
+        Entity grandchild = Iterables.getOnlyElement(child.getChildren());
+        assertEquals(grandchild.getDisplayName(), "grandchild");
+    }
+    
+
+    @Test
     public void testAddsPolicySpec() throws Exception {
         entity = app.createAndManageChild(EntitySpec.create(TestEntity.class)
                 .policy(PolicySpec.create(MyPolicy.class)


[23/45] git commit: Merge remote-tracking branch 'sjcorbett/yaml-context' into osgi2

Posted by he...@apache.org.
Merge remote-tracking branch 'sjcorbett/yaml-context' into osgi2


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

Branch: refs/heads/master
Commit: 3e71512b3dd21bb0113316c4e49df48bed92beb3
Parents: 1c04ec9 acd41f7
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Wed Jul 2 16:12:47 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Wed Jul 2 16:12:47 2014 +0100

----------------------------------------------------------------------
 .../java/brooklyn/catalog/BrooklynCatalog.java  |  48 +++---
 .../main/java/brooklyn/catalog/CatalogItem.java |  15 +-
 core/pom.xml                                    |   6 +
 .../catalog/internal/BasicBrooklynCatalog.java  |  36 +++--
 .../catalog/internal/CatalogItemDo.java         |  15 +-
 .../internal/CatalogItemDtoAbstract.java        |  43 ++++--
 .../catalog/internal/CatalogLibrariesDo.java    |  22 +++
 .../catalog/internal/CatalogLibrariesDto.java   |  20 +++
 .../catalog/internal/CatalogXmlSerializer.java  |  14 +-
 .../brooklyn/config/BrooklynServerConfig.java   |   3 +
 .../java/brooklyn/event/feed/ssh/SshFeed.java   |   2 +-
 .../brooklyn/management/ha/OsgiManager.java     |  72 +++++++++
 .../internal/LocalManagementContext.java        |  18 +++
 .../internal/ManagementContextInternal.java     |   6 +
 .../NonDeploymentManagementContext.java         |   6 +
 .../src/main/java/brooklyn/util/osgi/Osgis.java | 152 +++++++++++++++++++
 .../catalog/internal/CatalogDtoTest.java        |  11 +-
 .../catalog/internal/CatalogLoadTest.java       |  46 ++++++
 .../management/osgi/OsgiStandaloneTest.java     | 120 +++++++++++++++
 .../entity/LocalManagementContextForTests.java  |   9 +-
 .../brooklyn/catalog/internal/osgi-catalog.xml  |  11 ++
 .../osgi/brooklyn-osgi-test-a_0.1.0.jar         | Bin 0 -> 2055 bytes
 pom.xml                                         |   1 +
 .../BrooklynAssemblyTemplateInstantiator.java   |  10 +-
 .../creation/BrooklynEntityClassResolver.java   |  56 ++++++-
 .../spi/creation/BrooklynYamlTypeLoader.java    |  11 +-
 .../main/java/brooklyn/rest/api/CatalogApi.java |  14 +-
 .../rest/resources/CatalogResource.java         |  26 +++-
 .../rest/util/BrooklynRestResourceUtils.java    |   2 +
 .../rest/util/DefaultExceptionMapper.java       |   2 +-
 .../rest/resources/CatalogResourceTest.java     |  43 +++---
 31 files changed, 735 insertions(+), 105 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3e71512b/pom.xml
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3e71512b/usage/rest-server/src/main/java/brooklyn/rest/util/BrooklynRestResourceUtils.java
----------------------------------------------------------------------


[36/45] git commit: Supports brooklyn.catalog in yaml and its usage in BasicBrooklynCatalog

Posted by he...@apache.org.
Supports brooklyn.catalog in yaml and its usage in BasicBrooklynCatalog


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

Branch: refs/heads/master
Commit: f03f52fc0152b0355c860def523563e644f71327
Parents: 24c78d5
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Thu Jul 3 16:22:56 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Thu Jul 3 16:22:56 2014 +0100

----------------------------------------------------------------------
 .../brooklyn/camp/spi/pdp/DeploymentPlan.java   | 27 ++++++++++++-
 .../catalog/internal/BasicBrooklynCatalog.java  | 24 ++++++++++--
 .../catalog/internal/CatalogLibrariesDto.java   | 40 ++++++++++++++++++--
 .../brooklyn/camp/lite/CampYamlLiteTest.java    | 13 ++++++-
 .../camp/lite/test-app-service-blueprint.yaml   |  9 +++++
 .../spi/creation/BrooklynEntityMatcher.java     | 19 ++++++++++
 .../spi/dsl/BrooklynDslInterpreter.java         |  2 +-
 7 files changed, 123 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f03f52fc/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/DeploymentPlan.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/DeploymentPlan.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/DeploymentPlan.java
index e5fb05e..1af3ff9 100644
--- a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/DeploymentPlan.java
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/DeploymentPlan.java
@@ -7,6 +7,7 @@ import java.util.Map;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 
 import brooklyn.util.collections.MutableMap;
+import brooklyn.util.guava.Maybe;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
@@ -69,22 +70,46 @@ public class DeploymentPlan {
     public String getName() {
         return name;
     }
+
     public String getDescription() {
         return description;
     }
+
     public String getOrigin() {
         return origin;
     }
+
     public List<Artifact> getArtifacts() {
         return ImmutableList.copyOf(artifacts);
     }
+
     public List<Service> getServices() {
         return ImmutableList.copyOf(services);
     }
+
     public Map<String, Object> getCustomAttributes() {
         return ImmutableMap.copyOf(customAttributes);
     }
-    
+
+    /**
+     * Returns a present {@link Maybe} of the custom attribute with the given name if the attribute is
+     * non-null and is an instance of the given type. Otherwise returns absent.
+     * <p/>
+     * Does not remove the attribute from the custom attribute map.
+     */
+    @SuppressWarnings("unchecked")
+    public <T> Maybe<T> getCustomAttribute(String attributeName, Class<T> type) {
+        Object attribute = customAttributes.get(attributeName);
+        if (attribute == null) {
+            return Maybe.absent("Custom attributes does not contain " + attributeName);
+        } else if (!type.isAssignableFrom(attribute.getClass())) {
+            return Maybe.absent("Custom attribute " + attributeName + " is not of expected type: " +
+                    "expected=" + type.getName() + " actual=" + attribute.getClass().getName());
+        } else {
+            return Maybe.of((T) attribute);
+        }
+    }
+
     @Override
     public String toString() {
         return ToStringBuilder.reflectionToString(this);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f03f52fc/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 2f45bb7..9411863 100644
--- a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
@@ -1,11 +1,14 @@
 package brooklyn.catalog.internal;
 
+import brooklyn.util.guava.Maybe;
 import io.brooklyn.camp.CampPlatform;
 import io.brooklyn.camp.spi.AssemblyTemplate;
 import io.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
 import io.brooklyn.camp.spi.pdp.DeploymentPlan;
 import io.brooklyn.camp.spi.pdp.Service;
 
+import java.util.List;
+import java.util.Map;
 import java.util.NoSuchElementException;
 
 import javax.annotation.Nullable;
@@ -186,13 +189,26 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     private CatalogItemDtoAbstract<?,?> getAbstractCatalogItem(String yaml) {
         DeploymentPlan plan = makePlanFromYaml(yaml);
         
-        // TODO #2 parse brooklyn.catalog for metadata - name, bundles/libraries, etc
-        // (for now we default to taking the name from the plan or from a single service type therein, below)
         String name = null;
         CatalogLibrariesDto libraries = null;
-        
+
+        Maybe<Map> possibleCatalog = plan.getCustomAttribute("brooklyn.catalog", Map.class);
+        if (possibleCatalog.isPresent()) {
+            Map catalog = possibleCatalog.get();
+            Map<String, Object> cast = (Map<String, Object>) possibleCatalog.get();
+            if (catalog.containsKey("name") && catalog.get("name") != null) {
+                name = String.valueOf(catalog.get("name"));
+            }
+            Object possibleLibraries = catalog.get("libraries");
+            if (possibleLibraries != null) {
+                if (possibleLibraries instanceof List) {
+                    libraries = CatalogLibrariesDto.fromList((List<?>) possibleLibraries);
+                }
+            }
+        }
+
         // TODO #3 support version info
-        
+
         // take name from plan if not specified in brooklyn.catalog section not supplied
         if (Strings.isBlank(name)) {
             name = plan.getName();

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f03f52fc/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
index 4df1333..7f8f41d 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
@@ -2,8 +2,12 @@ package brooklyn.catalog.internal;
 
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.CopyOnWriteArrayList;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
@@ -11,20 +15,50 @@ import brooklyn.catalog.CatalogItem;
 
 public class CatalogLibrariesDto implements CatalogItem.CatalogItemLibraries {
 
+    private static Logger LOG = LoggerFactory.getLogger(CatalogLibrariesDto.class);
+
+    // TODO: Incorporate name and version into entries
     private List<String> bundles = new CopyOnWriteArrayList<String>();
 
     public void addBundle(String url) {
         Preconditions.checkNotNull(bundles, "Cannot add a bundle to a deserialized DTO");
-        bundles.add( Preconditions.checkNotNull(url) );
+        bundles.add(Preconditions.checkNotNull(url, "url"));
     }
 
-    /** @return An immutable copy of the bundle URLs referenced by this object */
+    /**
+     * @return An immutable copy of the bundle URLs referenced by this object
+     */
     public List<String> getBundles() {
-        if (bundles==null)  {
+        if (bundles == null) {
             // can be null on deserialization
             return Collections.emptyList();
         }
         return ImmutableList.copyOf(bundles);
     }
 
+    /**
+     * Parses an instance of CatalogLibrariesDto from the given List. Expects the list entries
+     * to be maps of string -> string. Will skip items that are not.
+     */
+    public static CatalogLibrariesDto fromList(List<?> possibleLibraries) {
+        CatalogLibrariesDto dto = new CatalogLibrariesDto();
+        for (Object object : possibleLibraries) {
+            if (object instanceof Map) {
+                Map entry = (Map) object;
+                String name = stringValOrNull(entry, "name");
+                String version = stringValOrNull(entry, "version");
+                String url = stringValOrNull(entry, "url");
+                dto.addBundle(url);
+            } else {
+                LOG.debug("Unexpected entry in libraries list not instance of map: " + object);
+            }
+        }
+
+        return dto;
+    }
+
+    private static String stringValOrNull(Map map, String key) {
+        Object val = map.get(key);
+        return val != null ? String.valueOf(val) : null;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f03f52fc/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java b/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
index c1bfefc..de89b0f 100644
--- a/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
+++ b/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
@@ -8,6 +8,7 @@ import io.brooklyn.camp.test.mock.web.MockWebPlatform;
 import java.io.InputStreamReader;
 import java.io.Reader;
 import java.util.Map;
+import java.util.Set;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -28,6 +29,7 @@ import brooklyn.util.stream.Streams;
 
 import com.google.common.base.Predicates;
 import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
 
 /** Tests of lightweight CAMP integration. Since the "real" integration is in brooklyn-camp project,
  * but some aspects of CAMP we want to be able to test here. */
@@ -83,16 +85,23 @@ public class CampYamlLiteTest {
         MockWebPlatform.populate(platform, TestAppAssemblyInstantiator.class);
         
         CatalogItem<?, ?> realItem = mgmt.getCatalog().addItem(Streams.readFullyString(getClass().getResourceAsStream("test-app-service-blueprint.yaml")));
-        Iterable<CatalogItem<Object, Object>> retrievedItems = mgmt.getCatalog().getCatalogItems(CatalogPredicates.registeredType(Predicates.equalTo("sample")));
+        Iterable<CatalogItem<Object, Object>> retrievedItems = mgmt.getCatalog()
+                .getCatalogItems(CatalogPredicates.registeredType(Predicates.equalTo("catalog-name")));
         
         Assert.assertEquals(Iterables.size(retrievedItems), 1, "Wrong retrieved items: "+retrievedItems);
         CatalogItem<Object, Object> retrievedItem = Iterables.getOnlyElement(retrievedItems);
         Assert.assertEquals(retrievedItem, realItem);
-        
+
+        Set<String> expectedBundles = Sets.newHashSet("http://www.example.com/bundle.jar");
+        Assert.assertEquals(retrievedItem.getLibraries().getBundles(), expectedBundles);
+        // Assert.assertEquals(retrievedItem.getVersion(), "0.9");
+
+
         EntitySpec<?> spec1 = (EntitySpec<?>) mgmt.getCatalog().createSpec(retrievedItem);
         Assert.assertNotNull(spec1);
         Assert.assertEquals(spec1.getConfig().get(TestEntity.CONF_NAME), "sample");
         
         // TODO other assertions, about children
     }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f03f52fc/core/src/test/resources/brooklyn/camp/lite/test-app-service-blueprint.yaml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/brooklyn/camp/lite/test-app-service-blueprint.yaml b/core/src/test/resources/brooklyn/camp/lite/test-app-service-blueprint.yaml
index 96db31c..13a4189 100644
--- a/core/src/test/resources/brooklyn/camp/lite/test-app-service-blueprint.yaml
+++ b/core/src/test/resources/brooklyn/camp/lite/test-app-service-blueprint.yaml
@@ -9,3 +9,12 @@ services:
         /: hello.war
     controller.spec:
         port: 80
+
+brooklyn.catalog:
+  name: catalog-name
+  type: io.camp.mock.MyApplication
+  version: 0.9
+  libraries:
+  - name: lib1
+    version: v1
+    url: http://www.example.com/bundle.jar
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f03f52fc/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
index d8e8fc6..76ffbe3 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
@@ -22,6 +22,7 @@ import brooklyn.util.flags.FlagUtils.FlagConfigKeyAndValueRecord;
 import brooklyn.util.text.Strings;
 
 import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
 
 public class BrooklynEntityMatcher implements PdpMatcher {
 
@@ -115,6 +116,7 @@ public class BrooklynEntityMatcher implements PdpMatcher {
         addCustomListAttributeIfNonNull(builder, attrs, "brooklyn.enrichers");
         addCustomListAttributeIfNonNull(builder, attrs, "brooklyn.initializers");
         addCustomListAttributeIfNonNull(builder, attrs, "brooklyn.children");
+        addCustomMapAttributeIfNonNull(builder, attrs, "brooklyn.catalog");
 
         if (!attrs.isEmpty()) {
             log.warn("Ignoring PDP attributes on "+deploymentPlanItem+": "+attrs);
@@ -142,6 +144,23 @@ public class BrooklynEntityMatcher implements PdpMatcher {
                 throw new IllegalArgumentException(key + " must be a list, is: " + items.getClass().getName());
             }
         }
+    }
+
+    /**
+     * Looks for the given key in the map of attributes and adds it to the given builder
+     * as a custom attribute with type Map.
+     * @throws java.lang.IllegalArgumentException if map[key] is not an instance of Map
+     */
+    private void addCustomMapAttributeIfNonNull(Builder<? extends PlatformComponentTemplate> builder, Map attrs, String key) {
+        Object items = attrs.remove(key);
+        if (items != null) {
+            if (items instanceof Map) {
+                Map<?, ?> itemMap = (Map<?, ?>) items;
+                if (!itemMap.isEmpty()) {
+                    builder.customAttribute(key, Maps.newHashMap(itemMap));
+                }
+            } else {
+                throw new IllegalArgumentException(key + " must be a map, is: " + items.getClass().getName());
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f03f52fc/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslInterpreter.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslInterpreter.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslInterpreter.java
index 9d1153c..a7ec34c 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslInterpreter.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslInterpreter.java
@@ -76,7 +76,7 @@ public class BrooklynDslInterpreter extends PlanInterpreterAdapter {
     
     @Override
     public boolean applyMapEntry(PlanInterpretationNode node, Map<Object, Object> mapIn, Map<Object, Object> mapOut,
-                            PlanInterpretationNode key, PlanInterpretationNode value) {
+            PlanInterpretationNode key, PlanInterpretationNode value) {
         if (key.getNewValue() instanceof FunctionWithArgs) {
             try {
                 currentNode.set(node);


[44/45] git commit: This closes #45

Posted by he...@apache.org.
This closes #45


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

Branch: refs/heads/master
Commit: 437a77665f5b641a15616c1bf4635286cfae772d
Parents: 6bc36e3 8094765
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Fri Jul 4 10:48:52 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri Jul 4 10:48:52 2014 +0100

----------------------------------------------------------------------
 .../java/brooklyn/entity/basic/BrooklynShutdownHooks.java     | 2 +-
 .../main/java/brooklyn/entity/rebind/RebindManagerImpl.java   | 2 ++
 .../java/brooklyn/internal/BrooklynFeatureEnablement.java     | 7 ++++++-
 3 files changed, 9 insertions(+), 2 deletions(-)
----------------------------------------------------------------------



[28/45] git commit: update generics for CatalogItem so it can supply a Spec, and add BrooklynCatalog.createSpec deprecating the loadClass methods

Posted by he...@apache.org.
update generics for CatalogItem so it can supply a Spec, and add BrooklynCatalog.createSpec deprecating the loadClass methods


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

Branch: refs/heads/master
Commit: 407de80ae9f0b975ad45e283146adfcf881fdfb6
Parents: 5c3d32c
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Wed Jul 2 17:17:25 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Wed Jul 2 17:17:25 2014 +0100

----------------------------------------------------------------------
 .../java/brooklyn/catalog/BrooklynCatalog.java  | 25 ++++++---
 .../main/java/brooklyn/catalog/CatalogItem.java |  2 +-
 .../brooklyn/catalog/CatalogPredicates.java     | 42 +++++++-------
 .../catalog/internal/BasicBrooklynCatalog.java  | 58 +++++++++++---------
 .../catalog/internal/CatalogClasspathDo.java    |  6 +-
 .../internal/CatalogConfigurationDto.java       |  2 +-
 .../brooklyn/catalog/internal/CatalogDo.java    | 20 +++----
 .../brooklyn/catalog/internal/CatalogDto.java   |  2 +-
 .../catalog/internal/CatalogEntityItemDto.java  |  3 +-
 .../catalog/internal/CatalogItemDo.java         |  8 +--
 .../internal/CatalogItemDtoAbstract.java        |  2 +-
 .../catalog/internal/CatalogPolicyItemDto.java  |  3 +-
 .../internal/CatalogTemplateItemDto.java        |  3 +-
 .../catalog/internal/CatalogDtoTest.java        |  2 +-
 .../catalog/internal/CatalogLoadTest.java       |  2 +-
 .../catalog/internal/CatalogScanTest.java       | 15 ++---
 .../BrooklynAssemblyTemplateInstantiator.java   |  4 +-
 .../lookup/AbstractTemplateBrooklynLookup.java  |  7 ++-
 .../lookup/AssemblyTemplateBrooklynLookup.java  | 18 ++++--
 ...PlatformComponentTemplateBrooklynLookup.java |  7 ++-
 .../rest/resources/CatalogResource.java         | 13 +++--
 .../rest/transform/CatalogTransformer.java      | 12 ++--
 .../rest/util/BrooklynRestResourceUtils.java    |  9 ++-
 23 files changed, 149 insertions(+), 116 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/407de80a/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java b/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
index 0bbd9d3..38583cb 100644
--- a/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
+++ b/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
@@ -5,25 +5,32 @@ import com.google.common.base.Predicate;
 public interface BrooklynCatalog {
 
     /** @return The item with the given ID, or null if not found */
-    CatalogItem<?> getCatalogItem(String id);
+    CatalogItem<?,?> getCatalogItem(String id);
 
 
     /** variant of {@link #getCatalogItem(String)} which checks (and casts) type for convenience
      * (returns null if type does not match) */
-    <T> CatalogItem<T> getCatalogItem(Class<T> type, String id);
+    <T,SpecT> CatalogItem<T,SpecT> getCatalogItem(Class<T> type, String id);
 
     /** @return All items in the catalog */
-    <T> Iterable<CatalogItem<T>> getCatalogItems();
+    <T,SpecT> Iterable<CatalogItem<T,SpecT>> getCatalogItems();
 
     /** convenience for filtering items in the catalog; see CatalogPredicates for useful filters */
-    <T> Iterable<CatalogItem<T>> getCatalogItems(Predicate<? super CatalogItem<T>> filter);
+    <T,SpecT> Iterable<CatalogItem<T,SpecT>> getCatalogItems(Predicate<? super CatalogItem<T,SpecT>> filter);
 
     /** @return The classloader which should be used to load classes and entities;
      * this includes all the catalog's classloaders in the right order */
     public ClassLoader getRootClassLoader();
 
-    /** throws exceptions if any problems */
-    <T> Class<? extends T> loadClass(CatalogItem<T> item);
+    /** creates a spec for the given catalog item, throwing exceptions if any problems */
+    <T,SpecT> SpecT createSpec(CatalogItem<T,SpecT> item);
+    
+    /** throws exceptions if any problems 
+     * @deprecated since 0.7.0 use {@link #createSpec(CatalogItem)} */
+    @Deprecated
+    <T,SpecT> Class<? extends T> loadClass(CatalogItem<T,SpecT> item);
+    /** @deprecated since 0.7.0 use {@link #createSpec(CatalogItem)} */
+    @Deprecated
     <T> Class<? extends T> loadClassByType(String typeName, Class<T> typeClass);
 
     
@@ -32,7 +39,7 @@ public interface BrooklynCatalog {
      * 
      * @throws IllegalArgumentException if the yaml was invalid
      */
-    CatalogItem<?> addItem(String yaml);
+    CatalogItem<?,?> addItem(String yaml);
     
     /**
      * adds an item to the 'manual' catalog;
@@ -41,7 +48,7 @@ public interface BrooklynCatalog {
      * @deprecated since 0.7.0 Construct catalogs with OSGi bundles instead
      */
     @Deprecated
-    void addItem(CatalogItem<?> item);
+    void addItem(CatalogItem<?,?> item);
 
     /** creates a catalog item and adds it to the 'manual' catalog,
      * with the corresponding Class definition (loaded by a classloader)
@@ -55,6 +62,6 @@ public interface BrooklynCatalog {
      * @deprecated since 0.7.0 Construct catalogs with OSGi bundles instead
      */
     @Deprecated
-    CatalogItem<?> addItem(Class<?> clazz);
+    CatalogItem<?,?> addItem(Class<?> clazz);
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/407de80a/api/src/main/java/brooklyn/catalog/CatalogItem.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/catalog/CatalogItem.java b/api/src/main/java/brooklyn/catalog/CatalogItem.java
index 9888901..fe844b8 100644
--- a/api/src/main/java/brooklyn/catalog/CatalogItem.java
+++ b/api/src/main/java/brooklyn/catalog/CatalogItem.java
@@ -3,7 +3,7 @@ package brooklyn.catalog;
 import java.util.List;
 import javax.annotation.Nonnull;
 
-public interface CatalogItem<T> {
+public interface CatalogItem<T,SpecT> {
     
     public static enum CatalogItemType {
         TEMPLATE, ENTITY, POLICY, CONFIGURATION

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/407de80a/core/src/main/java/brooklyn/catalog/CatalogPredicates.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/CatalogPredicates.java b/core/src/main/java/brooklyn/catalog/CatalogPredicates.java
index 7112282..5c3d884 100644
--- a/core/src/main/java/brooklyn/catalog/CatalogPredicates.java
+++ b/core/src/main/java/brooklyn/catalog/CatalogPredicates.java
@@ -5,59 +5,61 @@ import javax.annotation.Nullable;
 import brooklyn.catalog.CatalogItem.CatalogItemType;
 import brooklyn.entity.Application;
 import brooklyn.entity.Entity;
+import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.policy.Policy;
+import brooklyn.policy.PolicySpec;
 
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 
 public class CatalogPredicates {
 
-    public static <T> Predicate<CatalogItem<T>> isCatalogItemType(final CatalogItemType ciType) {
-        return new Predicate<CatalogItem<T>>() {
+    public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> isCatalogItemType(final CatalogItemType ciType) {
+        return new Predicate<CatalogItem<T,SpecT>>() {
             @Override
-            public boolean apply(@Nullable CatalogItem<T> item) {
+            public boolean apply(@Nullable CatalogItem<T,SpecT> item) {
                 return (item != null) && item.getCatalogItemType()==ciType;
             }
         };
     }
 
-    public static final Predicate<CatalogItem<Application>> IS_TEMPLATE = 
-            CatalogPredicates.<Application>isCatalogItemType(CatalogItemType.TEMPLATE);
-    public static final Predicate<CatalogItem<Entity>> IS_ENTITY = 
-            CatalogPredicates.<Entity>isCatalogItemType(CatalogItemType.ENTITY);
-    public static final Predicate<CatalogItem<Policy>> IS_POLICY = 
-            CatalogPredicates.<Policy>isCatalogItemType(CatalogItemType.POLICY);
+    public static final Predicate<CatalogItem<Application,EntitySpec<? extends Application>>> IS_TEMPLATE = 
+            CatalogPredicates.<Application,EntitySpec<? extends Application>>isCatalogItemType(CatalogItemType.TEMPLATE);
+    public static final Predicate<CatalogItem<Entity,EntitySpec<?>>> IS_ENTITY = 
+            CatalogPredicates.<Entity,EntitySpec<?>>isCatalogItemType(CatalogItemType.ENTITY);
+    public static final Predicate<CatalogItem<Policy,PolicySpec<?>>> IS_POLICY = 
+            CatalogPredicates.<Policy,PolicySpec<?>>isCatalogItemType(CatalogItemType.POLICY);
     
-    public static final Function<CatalogItem<?>,String> ID_OF_ITEM_TRANSFORMER = new Function<CatalogItem<?>, String>() {
+    public static final Function<CatalogItem<?,?>,String> ID_OF_ITEM_TRANSFORMER = new Function<CatalogItem<?,?>, String>() {
         @Override @Nullable
-        public String apply(@Nullable CatalogItem<?> input) {
+        public String apply(@Nullable CatalogItem<?,?> input) {
             if (input==null) return null;
             return input.getId();
         }
     };
 
-    public static <T> Predicate<CatalogItem<T>> name(final Predicate<? super String> filter) {
-        return new Predicate<CatalogItem<T>>() {
+    public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> name(final Predicate<? super String> filter) {
+        return new Predicate<CatalogItem<T,SpecT>>() {
             @Override
-            public boolean apply(@Nullable CatalogItem<T> item) {
+            public boolean apply(@Nullable CatalogItem<T,SpecT> item) {
                 return (item != null) && filter.apply(item.getName());
             }
         };
     }
 
-    public static <T> Predicate<CatalogItem<T>> javaType(final Predicate<? super String> filter) {
-        return new Predicate<CatalogItem<T>>() {
+    public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> javaType(final Predicate<? super String> filter) {
+        return new Predicate<CatalogItem<T,SpecT>>() {
             @Override
-            public boolean apply(@Nullable CatalogItem<T> item) {
+            public boolean apply(@Nullable CatalogItem<T,SpecT> item) {
                 return (item != null) && filter.apply(item.getJavaType());
             }
         };
     }
 
-    public static <T> Predicate<CatalogItem<T>> xml(final Predicate<? super String> filter) {
-        return new Predicate<CatalogItem<T>>() {
+    public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> xml(final Predicate<? super String> filter) {
+        return new Predicate<CatalogItem<T,SpecT>>() {
             @Override
-            public boolean apply(@Nullable CatalogItem<T> item) {
+            public boolean apply(@Nullable CatalogItem<T,SpecT> item) {
                 return (item != null) && filter.apply(item.toXmlString());
             }
         };

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/407de80a/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 67cbbe1..4bbb02c 100644
--- a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
@@ -59,25 +59,25 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         return catalog;
     }
 
-    protected CatalogItemDo<?> getCatalogItemDo(String id) {
+    protected CatalogItemDo<?,?> getCatalogItemDo(String id) {
         return catalog.getCache().get(id);
     }
     
     @Override
-    public CatalogItem<?> getCatalogItem(String id) {
+    public CatalogItem<?,?> getCatalogItem(String id) {
         if (id==null) return null;
-        CatalogItemDo<?> itemDo = getCatalogItemDo(id);
+        CatalogItemDo<?,?> itemDo = getCatalogItemDo(id);
         if (itemDo==null) return null;
         return itemDo.getDto();
     }
     
     @SuppressWarnings("unchecked")
     @Override
-    public <T> CatalogItem<T> getCatalogItem(Class<T> type, String id) {
+    public <T,SpecT> CatalogItem<T,SpecT> getCatalogItem(Class<T> type, String id) {
         if (id==null) return null;
-        CatalogItem<?> result = getCatalogItem(id);
+        CatalogItem<?,?> result = getCatalogItem(id);
         if (type==null || type.isAssignableFrom(result.getCatalogItemJavaType())) 
-            return (CatalogItem<T>)result;
+            return (CatalogItem<T,SpecT>)result;
         return null;
     }
     
@@ -96,13 +96,19 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         }
     }
 
+    @Override
+    public <T, SpecT> SpecT createSpec(CatalogItem<T, SpecT> item) {
+        // TODO #2
+        throw new UnsupportedOperationException();
+    }
+    
     @SuppressWarnings("unchecked")
     @Override
-    public <T> Class<? extends T> loadClass(CatalogItem<T> item) {
+    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);
-        CatalogItemDo<?> loadedItem = getCatalogItemDo(item.getId());
+        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();
     }
@@ -110,9 +116,9 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     @SuppressWarnings("unchecked")
     @Override
     public <T> Class<? extends T> loadClassByType(String typeName, Class<T> typeClass) {
-        Iterable<CatalogItem<Object>> resultL = getCatalogItems(CatalogPredicates.javaType(Predicates.equalTo(typeName)));
+        Iterable<CatalogItem<Object,Object>> resultL = getCatalogItems(CatalogPredicates.javaType(Predicates.equalTo(typeName)));
         if (Iterables.isEmpty(resultL)) throw new NoSuchElementException("Unable to find catalog item for type "+typeName);
-        CatalogItem<Object> resultI = resultL.iterator().next();
+        CatalogItem<?,?> resultI = resultL.iterator().next();
         if (log.isDebugEnabled() && Iterables.size(resultL)>1) {
             log.debug("Found "+Iterables.size(resultL)+" matches in catalog for type "+typeName+"; returning the first, "+resultI);
         }
@@ -120,14 +126,14 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     }
 
     @Deprecated
-    private <T> CatalogItemDtoAbstract<T> getAbstractCatalogItem(CatalogItem<T> item) {
-        while (item instanceof CatalogItemDo) item = ((CatalogItemDo<T>)item).itemDto;
+    private <T,SpecT> CatalogItemDtoAbstract<T,SpecT> getAbstractCatalogItem(CatalogItem<T,SpecT> item) {
+        while (item instanceof CatalogItemDo) item = ((CatalogItemDo<T,SpecT>)item).itemDto;
         if (item==null) return null;
-        if (item instanceof CatalogItemDtoAbstract) return (CatalogItemDtoAbstract<T>) item;
+        if (item instanceof CatalogItemDtoAbstract) return (CatalogItemDtoAbstract<T,SpecT>) item;
         throw new IllegalStateException("Cannot unwrap catalog item '"+item+"' (type "+item.getClass()+") to restore DTO");
     }
 
-    private <T> CatalogItemDtoAbstract<T> getAbstractCatalogItem(String yaml) {
+    private <T,SpecT> CatalogItemDtoAbstract<T,SpecT> getAbstractCatalogItem(String yaml) {
         CampPlatform camp = BrooklynServerConfig.getCampPlatform(mgmt).get();
         
         DeploymentPlan plan = camp.pdp().parseDeploymentPlan(Streams.newReaderWithContents(yaml));
@@ -145,17 +151,17 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     }
 
     @Override
-    public CatalogItem<?> addItem(String yaml) {
+    public CatalogItem<?,?> addItem(String yaml) {
         log.debug("Adding manual catalog item to "+mgmt+": "+yaml);
         Preconditions.checkNotNull(yaml, "yaml");
         if (manualAdditionsCatalog==null) loadManualAdditionsCatalog();
-        CatalogItemDtoAbstract<Object> itemDto = getAbstractCatalogItem(yaml);
+        CatalogItemDtoAbstract<?,?> itemDto = getAbstractCatalogItem(yaml);
         manualAdditionsCatalog.addEntry(itemDto);
         return itemDto;
     }
 
     @Override @Deprecated
-    public void addItem(CatalogItem<?> item) {
+    public void addItem(CatalogItem<?,?> item) {
         log.debug("Adding manual catalog item to "+mgmt+": "+item);
         Preconditions.checkNotNull(item, "item");
         if (manualAdditionsCatalog==null) loadManualAdditionsCatalog();
@@ -163,7 +169,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     }
 
     @Override @Deprecated
-    public CatalogItem<?> addItem(Class<?> type) {
+    public CatalogItem<?,?> addItem(Class<?> type) {
         log.debug("Adding manual catalog item to "+mgmt+": "+type);
         Preconditions.checkNotNull(type, "type");
         if (manualAdditionsCatalog==null) loadManualAdditionsCatalog();
@@ -201,23 +207,23 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
     @Override
-    public <T> Iterable<CatalogItem<T>> getCatalogItems() {
+    public <T,SpecT> Iterable<CatalogItem<T,SpecT>> getCatalogItems() {
         return ImmutableList.copyOf((Iterable)catalog.getCache().values());
     }
     
     @SuppressWarnings({ "unchecked", "rawtypes" })
     @Override
-    public <T> Iterable<CatalogItem<T>> getCatalogItems(Predicate<? super CatalogItem<T>> filter) {
-        Iterable<CatalogItemDo<T>> filtered = Iterables.filter((Iterable)catalog.getCache().values(), (Predicate<CatalogItem<T>>)(Predicate) filter);
-        return Iterables.transform(filtered, BasicBrooklynCatalog.<T,T>itemDoToDto());
+    public <T,SpecT> Iterable<CatalogItem<T,SpecT>> getCatalogItems(Predicate<? super CatalogItem<T,SpecT>> filter) {
+        Iterable<CatalogItemDo<T,SpecT>> filtered = Iterables.filter((Iterable)catalog.getCache().values(), (Predicate<CatalogItem<T,SpecT>>)(Predicate) filter);
+        return Iterables.transform(filtered, BasicBrooklynCatalog.<T,SpecT>itemDoToDto());
     }
 
     @SuppressWarnings({ "unchecked" })
-    private static <T2,T> Function<CatalogItemDo<T2>, CatalogItem<T>> itemDoToDto() {
-        return new Function<CatalogItemDo<T2>, CatalogItem<T>>() {
+    private static <T,SpecT> Function<CatalogItemDo<T,SpecT>, CatalogItem<T,SpecT>> itemDoToDto() {
+        return new Function<CatalogItemDo<T,SpecT>, CatalogItem<T,SpecT>>() {
             @Override
-            public CatalogItem<T> apply(@Nullable CatalogItemDo<T2> item) {
-                return (CatalogItem<T>) item.getDto();
+            public CatalogItem<T,SpecT> apply(@Nullable CatalogItemDo<T,SpecT> item) {
+                return item.getDto();
             }
         };
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/407de80a/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
index de5a7fb..06d0914 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
@@ -146,7 +146,7 @@ public class CatalogClasspathDo {
                 Set<Class<?>> catalogClasses = scanner.getTypesAnnotatedWith(Catalog.class);
                 for (Class<?> c: catalogClasses) {
                     try {
-                        CatalogItem<?> item = addCatalogEntry(c);
+                        CatalogItem<?,?> item = addCatalogEntry(c);
                         count++;
                         if (CatalogTemplateItemDto.class.isInstance(item)) countApps++;
                     } catch (Exception e) {
@@ -208,7 +208,7 @@ public class CatalogClasspathDo {
     }
 
     /** augments the given item with annotations and class data for the given class, then adds to catalog */
-    public CatalogItem<?> addCatalogEntry(Class<?> c) {
+    public CatalogItem<?,?> addCatalogEntry(Class<?> c) {
         if (Application.class.isAssignableFrom(c)) return addCatalogEntry(new CatalogTemplateItemDto(), c);
         if (ApplicationBuilder.class.isAssignableFrom(c)) return addCatalogEntry(new CatalogTemplateItemDto(), c);
         if (Entity.class.isAssignableFrom(c)) return addCatalogEntry(new CatalogEntityItemDto(), c);
@@ -218,7 +218,7 @@ public class CatalogClasspathDo {
     
     /** augments the given item with annotations and class data for the given class, then adds to catalog 
      */
-    public CatalogItem<?> addCatalogEntry(CatalogItemDtoAbstract<?> item, Class<?> c) {
+    public CatalogItem<?,?> addCatalogEntry(CatalogItemDtoAbstract<?,?> item, Class<?> c) {
         Catalog annotations = c.getAnnotation(Catalog.class);
         item.type = c.getName();
         item.name = firstNonEmpty(c.getSimpleName(), c.getName());

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/407de80a/core/src/main/java/brooklyn/catalog/internal/CatalogConfigurationDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogConfigurationDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogConfigurationDto.java
index 9a6694e..d52b539 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogConfigurationDto.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogConfigurationDto.java
@@ -4,7 +4,7 @@ import brooklyn.config.ConfigKey;
 
 
 @SuppressWarnings("rawtypes")
-public class CatalogConfigurationDto extends CatalogItemDtoAbstract<ConfigKey> {
+public class CatalogConfigurationDto extends CatalogItemDtoAbstract<ConfigKey,Void> {
     
     @Override
     public CatalogItemType getCatalogItemType() {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/407de80a/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
index b8759a4..c571585 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
@@ -32,7 +32,7 @@ public class CatalogDo {
     
     List<CatalogDo> childrenCatalogs = new ArrayList<CatalogDo>();
     CatalogClasspathDo classpath;
-    Map<String, CatalogItemDo<?>> cache;
+    Map<String, CatalogItemDo<?,?>> cache;
     
     AggregateClassLoader childrenClassLoader = AggregateClassLoader.newInstanceWithNoLoaders();
     ClassLoader recursiveClassLoader;
@@ -92,7 +92,7 @@ public class CatalogDo {
 
     private void loadCatalogItems() {
         List<CatalogLibrariesDo> loadedLibraries = Lists.newLinkedList();
-        for (CatalogItemDtoAbstract entry : dto.entries) {
+        for (CatalogItemDtoAbstract<?,?> entry : dto.entries) {
             CatalogLibrariesDo library = new CatalogLibrariesDo(entry.getLibrariesDto());
             library.load(mgmt);
             loadedLibraries.add(library);
@@ -128,20 +128,20 @@ public class CatalogDo {
         return childL;
     }
 
-    protected Map<String, CatalogItemDo<?>> getCache() {
-        Map<String, CatalogItemDo<?>> cache = this.cache;
+    protected Map<String, CatalogItemDo<?,?>> getCache() {
+        Map<String, CatalogItemDo<?,?>> cache = this.cache;
         if (cache==null) cache = buildCache();
         return cache;
     }
     
     @SuppressWarnings({ "unchecked", "rawtypes" })
-    protected synchronized Map<String, CatalogItemDo<?>> buildCache() {
+    protected synchronized Map<String, CatalogItemDo<?,?>> buildCache() {
         if (cache!=null) return cache;
         log.debug("Building cache for "+this);
         if (!isLoaded()) 
             log.debug("Catalog not fully loaded when loading cache of "+this);
         
-        Map<String, CatalogItemDo<?>> cache = new LinkedHashMap<String, CatalogItemDo<?>>();
+        Map<String, CatalogItemDo<?,?>> cache = new LinkedHashMap<String, CatalogItemDo<?,?>>();
         
         // build the cache; first from children catalogs, then from local entities
         // so that root and near-root takes precedence over deeper items;
@@ -155,9 +155,9 @@ public class CatalogDo {
                 cache.putAll(child.getCache());
         }
         if (dto.entries!=null) {
-            List<CatalogItemDtoAbstract<?>> entriesReversed = new ArrayList<CatalogItemDtoAbstract<?>>(dto.entries);
+            List<CatalogItemDtoAbstract<?,?>> entriesReversed = new ArrayList<CatalogItemDtoAbstract<?,?>>(dto.entries);
             Collections.reverse(entriesReversed);
-            for (CatalogItemDtoAbstract<?> entry: entriesReversed)
+            for (CatalogItemDtoAbstract<?,?> entry: entriesReversed)
                 cache.put(entry.getId(), new CatalogItemDo(this, entry));
         }
         
@@ -175,9 +175,9 @@ public class CatalogDo {
      * callers may prefer {@link CatalogClasspathDo#addCatalogEntry(CatalogItemDtoAbstract, Class)}
      */
     @SuppressWarnings({ "unchecked", "rawtypes" })
-    public synchronized void addEntry(CatalogItemDtoAbstract<?> entry) {
+    public synchronized void addEntry(CatalogItemDtoAbstract<?,?> entry) {
         if (dto.entries==null) 
-            dto.entries = new ArrayList<CatalogItemDtoAbstract<?>>();
+            dto.entries = new ArrayList<CatalogItemDtoAbstract<?,?>>();
         dto.entries.add(entry);
         if (cache!=null)
             cache.put(entry.getId(), new CatalogItemDo(this, entry));

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/407de80a/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java
index f222215..bd34020 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java
@@ -21,7 +21,7 @@ public class CatalogDto {
     String name;
     String description;
     CatalogClasspathDto classpath;
-    List<CatalogItemDtoAbstract<?>> entries = null;
+    List<CatalogItemDtoAbstract<?,?>> entries = null;
     
     // for thread-safety, any dynamic additions to this should be handled by a method 
     // in this class which does copy-on-write

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/407de80a/core/src/main/java/brooklyn/catalog/internal/CatalogEntityItemDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogEntityItemDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogEntityItemDto.java
index 234de98..8a61f24 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogEntityItemDto.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogEntityItemDto.java
@@ -1,9 +1,10 @@
 package brooklyn.catalog.internal;
 
 import brooklyn.entity.Entity;
+import brooklyn.entity.proxying.EntitySpec;
 
 
-public class CatalogEntityItemDto extends CatalogItemDtoAbstract<Entity> {
+public class CatalogEntityItemDto extends CatalogItemDtoAbstract<Entity,EntitySpec<?>> {
     
     @Override
     public CatalogItemType getCatalogItemType() {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/407de80a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
index edce2e7..1a6c804 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
@@ -7,19 +7,19 @@ import com.google.common.base.Preconditions;
 import brooklyn.catalog.CatalogItem;
 import brooklyn.util.exceptions.Exceptions;
 
-public class CatalogItemDo<T> implements CatalogItem<T> {
+public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT> {
 
     protected final CatalogDo catalog;
-    protected final CatalogItem<T> itemDto;
+    protected final CatalogItem<T,SpecT> itemDto;
 
     protected volatile Class<T> javaClass; 
     
-    public CatalogItemDo(CatalogDo catalog, CatalogItem<T> itemDto) {
+    public CatalogItemDo(CatalogDo catalog, CatalogItem<T,SpecT> itemDto) {
         this.catalog = Preconditions.checkNotNull(catalog, "catalog");
         this.itemDto = Preconditions.checkNotNull(itemDto, "itemDto");
     }
 
-    public CatalogItem<?> getDto() {
+    public CatalogItem<T,SpecT> getDto() {
         return itemDto;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/407de80a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
index d834911..771e37b 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
@@ -4,7 +4,7 @@ import javax.annotation.Nonnull;
 
 import brooklyn.catalog.CatalogItem;
 
-public abstract class CatalogItemDtoAbstract<T> implements CatalogItem<T> {
+public abstract class CatalogItemDtoAbstract<T,SpecT> implements CatalogItem<T,SpecT> {
 
     String id;
     String type;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/407de80a/core/src/main/java/brooklyn/catalog/internal/CatalogPolicyItemDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogPolicyItemDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogPolicyItemDto.java
index 032a352..00ba3f6 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogPolicyItemDto.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogPolicyItemDto.java
@@ -1,9 +1,10 @@
 package brooklyn.catalog.internal;
 
 import brooklyn.policy.Policy;
+import brooklyn.policy.PolicySpec;
 
 
-public class CatalogPolicyItemDto extends CatalogItemDtoAbstract<Policy> {
+public class CatalogPolicyItemDto extends CatalogItemDtoAbstract<Policy,PolicySpec<?>> {
     
     @Override
     public CatalogItemType getCatalogItemType() {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/407de80a/core/src/main/java/brooklyn/catalog/internal/CatalogTemplateItemDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogTemplateItemDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogTemplateItemDto.java
index 32b4313..e4016d9 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogTemplateItemDto.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogTemplateItemDto.java
@@ -1,8 +1,9 @@
 package brooklyn.catalog.internal;
 
 import brooklyn.entity.Application;
+import brooklyn.entity.proxying.EntitySpec;
 
-public class CatalogTemplateItemDto extends CatalogItemDtoAbstract<Application> {
+public class CatalogTemplateItemDto extends CatalogItemDtoAbstract<Application,EntitySpec<?>> {
 
     @Override
     public CatalogItemType getCatalogItemType() {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/407de80a/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java b/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
index ba5a863..51c60ee 100644
--- a/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
+++ b/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
@@ -50,7 +50,7 @@ public class CatalogDtoTest {
         Assert.assertEquals(root.catalogs.size(), 5);
         CatalogDo loader = new CatalogDo(root).load(managementContext, null);
         
-        CatalogItemDo<?> worker = loader.getCache().get("io.brooklyn.mapr.m3.WorkerNode");
+        CatalogItemDo<?,?> worker = loader.getCache().get("io.brooklyn.mapr.m3.WorkerNode");
         Assert.assertNotNull(worker);
         Assert.assertEquals(worker.getName(), "M3 Worker Node");
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/407de80a/core/src/test/java/brooklyn/catalog/internal/CatalogLoadTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/catalog/internal/CatalogLoadTest.java b/core/src/test/java/brooklyn/catalog/internal/CatalogLoadTest.java
index 9961d3a..b2c4fdd 100644
--- a/core/src/test/java/brooklyn/catalog/internal/CatalogLoadTest.java
+++ b/core/src/test/java/brooklyn/catalog/internal/CatalogLoadTest.java
@@ -33,7 +33,7 @@ public class CatalogLoadTest {
         assertEquals(catalog.name, "OSGi catalogue");
         assertEquals(catalog.entries.size(), 1, "Catalog entries = " + Joiner.on(", ").join(catalog.entries));
 
-        CatalogItemDtoAbstract<?> template = Iterables.getOnlyElement(catalog.entries);
+        CatalogItemDtoAbstract<?,?> template = Iterables.getOnlyElement(catalog.entries);
         assertEquals(template.getName(), "Entity name");
         assertEquals(template.getVersion(), "9.1.3");
         assertEquals(template.getJavaType(), "com.example.ExampleApp");

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/407de80a/core/src/test/java/brooklyn/catalog/internal/CatalogScanTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/catalog/internal/CatalogScanTest.java b/core/src/test/java/brooklyn/catalog/internal/CatalogScanTest.java
index 86b62ef..538f9cc 100644
--- a/core/src/test/java/brooklyn/catalog/internal/CatalogScanTest.java
+++ b/core/src/test/java/brooklyn/catalog/internal/CatalogScanTest.java
@@ -16,6 +16,7 @@ import brooklyn.catalog.internal.MyCatalogItems.MySillyAppTemplate;
 import brooklyn.config.BrooklynProperties;
 import brooklyn.entity.Application;
 import brooklyn.entity.basic.Entities;
+import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.management.internal.LocalManagementContext;
 import brooklyn.util.net.Urls;
 import brooklyn.util.text.Strings;
@@ -80,17 +81,17 @@ public class CatalogScanTest {
         loadAnnotationsOnlyCatalog();
         BrooklynCatalog c = annotsCatalog;
         
-        Iterable<CatalogItem<Object>> bases = c.getCatalogItems(CatalogPredicates.name(Predicates.containsPattern("MyBaseEntity")));
+        Iterable<CatalogItem<Object,Object>> bases = c.getCatalogItems(CatalogPredicates.name(Predicates.containsPattern("MyBaseEntity")));
         Assert.assertEquals(Iterables.size(bases), 0, "should have been empty: "+bases);
         
-        Iterable<CatalogItem<Object>> asdfjkls = c.getCatalogItems(CatalogPredicates.name(Predicates.containsPattern("__asdfjkls__shouldnotbefound")));
+        Iterable<CatalogItem<Object,Object>> asdfjkls = c.getCatalogItems(CatalogPredicates.name(Predicates.containsPattern("__asdfjkls__shouldnotbefound")));
         Assert.assertEquals(Iterables.size(asdfjkls), 0);
         
-        Iterable<CatalogItem<Object>> silly1 = c.getCatalogItems(CatalogPredicates.name(Predicates.equalTo("MySillyAppTemplate")));
-        Iterable<CatalogItem<Object>> silly2 = c.getCatalogItems(CatalogPredicates.javaType(Predicates.equalTo(MySillyAppTemplate.class.getName())));
+        Iterable<CatalogItem<Object,Object>> silly1 = c.getCatalogItems(CatalogPredicates.name(Predicates.equalTo("MySillyAppTemplate")));
+        Iterable<CatalogItem<Object,Object>> silly2 = c.getCatalogItems(CatalogPredicates.javaType(Predicates.equalTo(MySillyAppTemplate.class.getName())));
         Assert.assertEquals(Iterables.getOnlyElement(silly1), Iterables.getOnlyElement(silly2));
         
-        CatalogItem<Application> s1 = c.getCatalogItem(Application.class, silly1.iterator().next().getId());
+        CatalogItem<Application,EntitySpec<? extends Application>> s1 = c.getCatalogItem(Application.class, silly1.iterator().next().getId());
         Assert.assertEquals(s1, Iterables.getOnlyElement(silly1));
         
         Assert.assertEquals(s1.getDescription(), "Some silly app test");
@@ -106,14 +107,14 @@ public class CatalogScanTest {
     @Test
     public void testAnnotationLoadsSomeApps() {
         loadAnnotationsOnlyCatalog();
-        Iterable<CatalogItem<Object>> silly1 = annotsCatalog.getCatalogItems(CatalogPredicates.name(Predicates.equalTo("MySillyAppTemplate")));
+        Iterable<CatalogItem<Object,Object>> silly1 = annotsCatalog.getCatalogItems(CatalogPredicates.name(Predicates.equalTo("MySillyAppTemplate")));
         Assert.assertEquals(Iterables.getOnlyElement(silly1).getDescription(), "Some silly app test");
     }
     
     @Test
     public void testAnnotationLoadsSomeAppBuilders() {
         loadAnnotationsOnlyCatalog();
-        Iterable<CatalogItem<Object>> silly1 = annotsCatalog.getCatalogItems(CatalogPredicates.name(Predicates.equalTo("MySillyAppBuilderTemplate")));
+        Iterable<CatalogItem<Object,Object>> silly1 = annotsCatalog.getCatalogItems(CatalogPredicates.name(Predicates.equalTo("MySillyAppBuilderTemplate")));
         Assert.assertEquals(Iterables.getOnlyElement(silly1).getDescription(), "Some silly app builder test");
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/407de80a/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 9e5ad6f..2652c59 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
@@ -67,7 +67,7 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateIns
         // createApplicationFromCatalog branch below is never taken.  If `id'
         // key is given in blueprint it is available with:
         // Object customId = template.getCustomAttributes().get("id");
-        CatalogItem<?> item = catalog.getCatalogItem(template.getId());
+        CatalogItem<?,?> item = catalog.getCatalogItem(template.getId());
 
         if (item==null) {
             return createApplicationFromNonCatalogCampTemplate(template, platform);
@@ -76,7 +76,7 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateIns
         }
     }
 
-    protected Application createApplicationFromCatalog(CampPlatform platform, CatalogItem<?> item, AssemblyTemplate template) {
+    protected Application createApplicationFromCatalog(CampPlatform platform, CatalogItem<?,?> item, AssemblyTemplate template) {
         ManagementContext mgmt = getBrooklynManagementContext(platform);
 
         if (!template.getApplicationComponentTemplates().isEmpty() ||

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/407de80a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/AbstractTemplateBrooklynLookup.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/AbstractTemplateBrooklynLookup.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/AbstractTemplateBrooklynLookup.java
index 8a5acf8..3680091 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/AbstractTemplateBrooklynLookup.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/AbstractTemplateBrooklynLookup.java
@@ -9,6 +9,7 @@ import org.slf4j.LoggerFactory;
 
 import brooklyn.catalog.CatalogItem;
 import brooklyn.entity.Entity;
+import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.management.ManagementContext;
 
 public abstract class AbstractTemplateBrooklynLookup<T extends AbstractResource>  extends AbstractBrooklynResourceLookup<T> {
@@ -21,7 +22,7 @@ public abstract class AbstractTemplateBrooklynLookup<T extends AbstractResource>
 
     @Override
     public T get(String id) {
-        CatalogItem<?> item = bmc.getCatalog().getCatalogItem(id);
+        CatalogItem<?,?> item = bmc.getCatalog().getCatalogItem(id);
         if (item==null) {
             log.warn("Could not find item '"+id+"' in Brooklyn catalog; returning null");
             return null;
@@ -29,9 +30,9 @@ public abstract class AbstractTemplateBrooklynLookup<T extends AbstractResource>
         return adapt(item);
     }
 
-    public abstract T adapt(CatalogItem<?> item);
+    public abstract T adapt(CatalogItem<?,?> item);
 
-    protected ResolvableLink<T> newLink(CatalogItem<? extends Entity> li) {
+    protected ResolvableLink<T> newLink(CatalogItem<? extends Entity,EntitySpec<?>> li) {
         return newLink(li.getId(), li.getName());
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/407de80a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/AssemblyTemplateBrooklynLookup.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/AssemblyTemplateBrooklynLookup.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/AssemblyTemplateBrooklynLookup.java
index e818073..5057c2f 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/AssemblyTemplateBrooklynLookup.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/AssemblyTemplateBrooklynLookup.java
@@ -11,6 +11,8 @@ import java.util.List;
 import brooklyn.catalog.CatalogItem;
 import brooklyn.catalog.CatalogPredicates;
 import brooklyn.entity.Application;
+import brooklyn.entity.Entity;
+import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.management.ManagementContext;
 
 public class AssemblyTemplateBrooklynLookup extends AbstractTemplateBrooklynLookup<AssemblyTemplate> {
@@ -20,7 +22,7 @@ public class AssemblyTemplateBrooklynLookup extends AbstractTemplateBrooklynLook
     }
 
     @Override
-    public AssemblyTemplate adapt(CatalogItem<?> item) {
+    public AssemblyTemplate adapt(CatalogItem<?,?> item) {
         return AssemblyTemplate.builder().
                 name(item.getName()).
                 id(item.getId()).
@@ -30,12 +32,20 @@ public class AssemblyTemplateBrooklynLookup extends AbstractTemplateBrooklynLook
                 build();
     }
 
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    // why can I not pass an EntitySpec<? extends Application> to    newLink(EntitySpec<?> spec)  ?
+    // feels to me (alexheneveld) that `? extends Application` should be both covariant and contravariant to `?` ..
+    // but it's not, so we introduce this conversion method
+    protected ResolvableLink<AssemblyTemplate> newApplicationLink(CatalogItem<? extends Entity, EntitySpec<? extends Application>> li) {
+        return super.newLink((CatalogItem)li);
+    }
+    
     @Override
     public List<ResolvableLink<AssemblyTemplate>> links() {
-        Iterable<CatalogItem<Application>> l = bmc.getCatalog().getCatalogItems(CatalogPredicates.IS_TEMPLATE);
+        Iterable<CatalogItem<Application,EntitySpec<? extends Application>>> l = bmc.getCatalog().getCatalogItems(CatalogPredicates.IS_TEMPLATE);
         List<ResolvableLink<AssemblyTemplate>> result = new ArrayList<ResolvableLink<AssemblyTemplate>>();
-        for (CatalogItem<Application> li: l)
-            result.add(newLink(li));
+        for (CatalogItem<Application,EntitySpec<? extends Application>> li: l)
+            result.add(newApplicationLink(li));
         return result;
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/407de80a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/PlatformComponentTemplateBrooklynLookup.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/PlatformComponentTemplateBrooklynLookup.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/PlatformComponentTemplateBrooklynLookup.java
index 891b96d..f0b6cce 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/PlatformComponentTemplateBrooklynLookup.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/PlatformComponentTemplateBrooklynLookup.java
@@ -10,6 +10,7 @@ import java.util.List;
 import brooklyn.catalog.CatalogItem;
 import brooklyn.catalog.CatalogPredicates;
 import brooklyn.entity.Entity;
+import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.management.ManagementContext;
 
 public class PlatformComponentTemplateBrooklynLookup extends AbstractTemplateBrooklynLookup<PlatformComponentTemplate> {
@@ -19,7 +20,7 @@ public class PlatformComponentTemplateBrooklynLookup extends AbstractTemplateBro
     }
 
     @Override
-    public PlatformComponentTemplate adapt(CatalogItem<?> item) {
+    public PlatformComponentTemplate adapt(CatalogItem<?,?> item) {
         return PlatformComponentTemplate.builder().
                 name(item.getName()).
                 id(item.getId()).
@@ -30,9 +31,9 @@ public class PlatformComponentTemplateBrooklynLookup extends AbstractTemplateBro
 
     @Override
     public List<ResolvableLink<PlatformComponentTemplate>> links() {
-        Iterable<CatalogItem<Entity>> l = bmc.getCatalog().getCatalogItems(CatalogPredicates.IS_ENTITY);
+        Iterable<CatalogItem<Entity,EntitySpec<?>>> l = bmc.getCatalog().getCatalogItems(CatalogPredicates.IS_ENTITY);
         List<ResolvableLink<PlatformComponentTemplate>> result = new ArrayList<ResolvableLink<PlatformComponentTemplate>>();
-        for (CatalogItem<Entity> li: l)
+        for (CatalogItem<Entity,EntitySpec<?>> li: l)
             result.add(newLink(li));
         return result;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/407de80a/usage/rest-server/src/main/java/brooklyn/rest/resources/CatalogResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/resources/CatalogResource.java b/usage/rest-server/src/main/java/brooklyn/rest/resources/CatalogResource.java
index fe266cf..78ca63c 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/resources/CatalogResource.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/resources/CatalogResource.java
@@ -18,6 +18,7 @@ import org.slf4j.LoggerFactory;
 import brooklyn.catalog.CatalogItem;
 import brooklyn.catalog.CatalogPredicates;
 import brooklyn.entity.Entity;
+import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.rest.api.CatalogApi;
 import brooklyn.rest.domain.ApiError;
 import brooklyn.rest.domain.CatalogEntitySummary;
@@ -57,7 +58,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
 
     @Override
     public Response create(String yaml) {
-        CatalogItem<?> item;
+        CatalogItem<?,?> item;
         try {
             item = brooklyn().getCatalog().addItem(yaml);
         } catch (IllegalArgumentException e) {
@@ -98,12 +99,12 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
     @Override
     @SuppressWarnings("unchecked")
     public CatalogEntitySummary getEntity(String entityId) throws Exception {
-      CatalogItem<?> result = brooklyn().getCatalog().getCatalogItem(entityId);
+      CatalogItem<?,?> result = brooklyn().getCatalog().getCatalogItem(entityId);
       if (result==null) {
         throw WebResourceUtils.notFound("Entity with id '%s' not found", entityId);
       }
 
-      return CatalogTransformer.catalogEntitySummary(brooklyn(), (CatalogItem<? extends Entity>) result);
+      return CatalogTransformer.catalogEntitySummary(brooklyn(), (CatalogItem<? extends Entity,EntitySpec<?>>) result);
     }
 
     @Override
@@ -117,7 +118,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
     @Override
     public CatalogItemSummary getPolicy(
         String policyId) throws Exception {
-        CatalogItem<?> result = brooklyn().getCatalog().getCatalogItem(policyId);
+        CatalogItem<?,?> result = brooklyn().getCatalog().getCatalogItem(policyId);
         if (result==null) {
           throw WebResourceUtils.notFound("Policy with id '%s' not found", policyId);
         }
@@ -126,7 +127,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
     }
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
-    private <T> List<CatalogItemSummary> getCatalogItemSummariesMatchingRegexFragment(Predicate<CatalogItem<T>> type, String regex, String fragment) {
+    private <T,SpecT> List<CatalogItemSummary> getCatalogItemSummariesMatchingRegexFragment(Predicate<CatalogItem<T,SpecT>> type, String regex, String fragment) {
         List filters = new ArrayList();
         filters.add(type);
         if (Strings.isNonEmpty(regex))
@@ -140,7 +141,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
 
     @Override
     public Response getIcon(String itemId) {
-        CatalogItem<?> result = brooklyn().getCatalog().getCatalogItem(itemId);
+        CatalogItem<?,?> result = brooklyn().getCatalog().getCatalogItem(itemId);
         String url = result.getIconUrl();
         if (url==null) {
             log.debug("No icon available for "+result+"; returning "+Status.NO_CONTENT);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/407de80a/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 5d2cf80..8b05bd9 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
@@ -13,8 +13,10 @@ import brooklyn.entity.Entity;
 import brooklyn.entity.EntityType;
 import brooklyn.entity.basic.EntityDynamicType;
 import brooklyn.entity.basic.EntityTypes;
+import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.event.Sensor;
 import brooklyn.policy.Policy;
+import brooklyn.policy.PolicySpec;
 import brooklyn.rest.domain.CatalogEntitySummary;
 import brooklyn.rest.domain.CatalogItemSummary;
 import brooklyn.rest.domain.CatalogPolicySummary;
@@ -33,7 +35,7 @@ public class CatalogTransformer {
     @SuppressWarnings("unused")
     private static final org.slf4j.Logger log = LoggerFactory.getLogger(CatalogTransformer.class);
     
-    public static CatalogEntitySummary catalogEntitySummary(BrooklynRestResourceUtils b, CatalogItem<? extends Entity> item) {
+    public static CatalogEntitySummary catalogEntitySummary(BrooklynRestResourceUtils b, CatalogItem<? extends Entity,EntitySpec<?>> item) {
         Class<? extends Entity> clazz = b.getCatalog().loadClass(item);
         EntityDynamicType typeMap = EntityTypes.getDefinedEntityType(clazz);
         EntityType type = typeMap.getSnapshot();
@@ -52,23 +54,23 @@ public class CatalogTransformer {
                 makeLinks(item));
     }
 
-    public static CatalogItemSummary catalogItemSummary(BrooklynRestResourceUtils b, CatalogItem<?> item) {
+    public static CatalogItemSummary catalogItemSummary(BrooklynRestResourceUtils b, CatalogItem<?,?> item) {
         return new CatalogItemSummary(item.getId(), item.getName(), item.getJavaType(),
                 item.getDescription(), tidyIconLink(b, item, item.getIconUrl()), makeLinks(item));
     }
 
-    public static CatalogPolicySummary catalogPolicySummary(BrooklynRestResourceUtils b, CatalogItem<? extends Policy> item) {
+    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(),
                 item.getDescription(), tidyIconLink(b, item, item.getIconUrl()), config,
                 makeLinks(item));
     }
 
-    protected static Map<String, URI> makeLinks(CatalogItem<?> item) {
+    protected static Map<String, URI> makeLinks(CatalogItem<?,?> item) {
         return MutableMap.<String, URI>of();
     }
     
-    private static String tidyIconLink(BrooklynRestResourceUtils b, CatalogItem<?> item, String iconUrl) {
+    private static String tidyIconLink(BrooklynRestResourceUtils b, CatalogItem<?,?> item, String iconUrl) {
         if (b.isUrlServerSideAndSafe(iconUrl))
             return "/v1/catalog/icon/"+item.getId();
         return iconUrl;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/407de80a/usage/rest-server/src/main/java/brooklyn/rest/util/BrooklynRestResourceUtils.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/util/BrooklynRestResourceUtils.java b/usage/rest-server/src/main/java/brooklyn/rest/util/BrooklynRestResourceUtils.java
index 8fc83bc..9fb3ca7 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/util/BrooklynRestResourceUtils.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/util/BrooklynRestResourceUtils.java
@@ -2,7 +2,6 @@ package brooklyn.rest.util;
 
 import static brooklyn.rest.util.WebResourceUtils.notFound;
 import static com.google.common.collect.Iterables.transform;
-import brooklyn.management.entitlement.Entitlements;
 import groovy.lang.GroovyClassLoader;
 
 import java.lang.reflect.Constructor;
@@ -23,7 +22,6 @@ import org.slf4j.LoggerFactory;
 
 import brooklyn.catalog.BrooklynCatalog;
 import brooklyn.catalog.CatalogItem;
-import brooklyn.catalog.CatalogItem.CatalogItemType;
 import brooklyn.config.ConfigKey;
 import brooklyn.enricher.Enrichers;
 import brooklyn.entity.Application;
@@ -40,6 +38,7 @@ import brooklyn.location.Location;
 import brooklyn.location.LocationRegistry;
 import brooklyn.management.ManagementContext;
 import brooklyn.management.Task;
+import brooklyn.management.entitlement.Entitlements;
 import brooklyn.policy.Policy;
 import brooklyn.policy.basic.AbstractPolicy;
 import brooklyn.rest.domain.ApplicationSpec;
@@ -346,7 +345,7 @@ public class BrooklynRestResourceUtils {
 
     protected Map<?, ?> getRenderingConfigurationFor(String catalogId) {
         MutableMap<Object, Object> result = MutableMap.of();
-        CatalogItem<?> item = mgmt.getCatalog().getCatalogItem(catalogId);
+        CatalogItem<?,?> item = mgmt.getCatalog().getCatalogItem(catalogId);
         if (item==null) return result;
         
         result.addIfNotNull("iconUrl", item.getIconUrl());
@@ -432,12 +431,12 @@ public class BrooklynRestResourceUtils {
         Class clazz = loader.parseClass(groovyCode);
 
         if (AbstractEntity.class.isAssignableFrom(clazz)) {
-            CatalogItem<?> item = getCatalog().addItem(clazz);
+            CatalogItem<?,?> item = getCatalog().addItem(clazz);
             log.info("REST created "+item);
             return Response.created(URI.create("entities/" + clazz.getName())).build();
 
         } else if (AbstractPolicy.class.isAssignableFrom(clazz)) {
-            CatalogItem<?> item = getCatalog().addItem(clazz);
+            CatalogItem<?,?> item = getCatalog().addItem(clazz);
             log.info("REST created "+item);
             return Response.created(URI.create("policies/" + clazz.getName())).build();
         }


[33/45] git commit: use an OSGi cache, and connect catalog items to OsgiManager class loading

Posted by he...@apache.org.
use an OSGi cache, and connect catalog items to OsgiManager class loading


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

Branch: refs/heads/master
Commit: 13aa4af9447fc2536da660ff592fb0c0175b1d0d
Parents: d4d17b7
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Jul 3 15:06:28 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu Jul 3 15:06:28 2014 +0100

----------------------------------------------------------------------
 .../catalog/internal/BasicBrooklynCatalog.java  |  3 +-
 .../catalog/internal/CatalogItemDo.java         | 34 ++++++++++--
 .../brooklyn/management/ha/OsgiManager.java     | 57 +++++++++++++++-----
 .../creation/BrooklynEntityClassResolver.java   | 39 +++++++++-----
 4 files changed, 100 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/13aa4af9/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 f924869..f4f0150 100644
--- a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
@@ -134,8 +134,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         // revert to legacy mechanism
         try {
             if (loadedItem.getJavaType()!=null) {
-                @SuppressWarnings({ "deprecation" })
-                SpecT specT = (SpecT) Reflections.findMethod(specType, "create", Class.class).invoke(null, loadedItem.getJavaClass());
+                SpecT specT = (SpecT) Reflections.findMethod(specType, "create", Class.class).invoke(null, loadedItem.loadJavaClass(mgmt));
                 spec = specT;
             }
         } catch (Exception e) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/13aa4af9/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
index d1d8d82..65133fe 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
@@ -1,10 +1,16 @@
 package brooklyn.catalog.internal;
 
+import java.util.List;
+
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
 import brooklyn.catalog.CatalogItem;
+import brooklyn.management.ManagementContext;
+import brooklyn.management.ha.OsgiManager;
+import brooklyn.management.internal.ManagementContextInternal;
 import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.guava.Maybe;
 
 import com.google.common.base.Preconditions;
 
@@ -79,20 +85,38 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT> {
      * new items should use {@link #getYaml()} */
     @Deprecated
     public Class<T> getJavaClass() {
-        if (javaClass==null) loadJavaClass();
+        if (javaClass==null) loadJavaClass(null);
         return javaClass;
     }
     
     @SuppressWarnings("unchecked")
-    protected Class<? extends T> loadJavaClass() {
+    protected Class<? extends T> loadJavaClass(ManagementContext mgmt) {
+        Maybe<Class<Object>> clazz = null;
         try {
             if (javaClass!=null) return javaClass;
-            
-            // TODO use OSGi
+
+            if (mgmt!=null) {
+                Maybe<OsgiManager> osgi = ((ManagementContextInternal)mgmt).getOsgiManager();
+                if (osgi.isPresent()) {
+                    List<String> bundles = getLibraries().getBundles();
+                    if (bundles!=null && !bundles.isEmpty()) {
+                        clazz = osgi.get().tryResolveClass(getJavaType(), bundles);
+                        if (clazz.isPresent()) {
+                            return (Class<? extends T>) clazz.get();
+                        }
+                    }
+                }
+            }
             
             javaClass = (Class<T>) catalog.getRootClassLoader().loadClass(getJavaType());
             return javaClass;
-        } catch (ClassNotFoundException e) {
+        } catch (Throwable e) {
+            Exceptions.propagateIfFatal(e);
+            if (clazz!=null) {
+                // if OSGi bundles were defined and failed, then prefer to throw its error message
+                clazz.get();
+            }
+            // else throw the java error
             throw Exceptions.propagate(e);
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/13aa4af9/core/src/main/java/brooklyn/management/ha/OsgiManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/ha/OsgiManager.java b/core/src/main/java/brooklyn/management/ha/OsgiManager.java
index a968660..709bf34 100644
--- a/core/src/main/java/brooklyn/management/ha/OsgiManager.java
+++ b/core/src/main/java/brooklyn/management/ha/OsgiManager.java
@@ -1,12 +1,14 @@
 package brooklyn.management.ha;
 
 import java.io.File;
+import java.util.Arrays;
+import java.util.Map;
 
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleException;
 import org.osgi.framework.launch.Framework;
-
-import com.google.common.base.Throwables;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import brooklyn.config.BrooklynServerConfig;
 import brooklyn.config.ConfigKey;
@@ -16,14 +18,19 @@ import brooklyn.util.guava.Maybe;
 import brooklyn.util.os.Os;
 import brooklyn.util.osgi.Osgis;
 
+import com.google.common.base.Throwables;
+
 public class OsgiManager {
 
+    private static final Logger log = LoggerFactory.getLogger(OsgiManager.class);
+    
     public static final ConfigKey<Boolean> USE_OSGI = BrooklynServerConfig.USE_OSGI;
     
     /* see Osgis for info on starting framework etc */
     
     protected Framework framework;
     protected File osgiTempDir;
+    protected Map<String,String> bundleUrlToNameVersionString = MutableMap.of();
     
     public void start() {
         try {
@@ -51,24 +58,48 @@ public class OsgiManager {
 
     public void registerBundle(String bundleUrl) {
         try {
-            Osgis.install(framework, bundleUrl);
+            String nv = bundleUrlToNameVersionString.get(bundleUrl);
+            if (nv!=null) {
+                if (Osgis.getBundle(framework, nv).isPresent()) {
+                    log.debug("Bundle from "+bundleUrl+" already installed as "+nv+"; not re-registering");
+                    return;
+                }
+            }
+            Bundle b = Osgis.install(framework, bundleUrl);
+            log.debug("Bundle from "+bundleUrl+" successfully installed as "+nv);
+            bundleUrlToNameVersionString.put(bundleUrl, b.getSymbolicName()+":"+b.getVersion().toString());
         } catch (BundleException e) {
+            log.debug("Bundle from "+bundleUrl+" failed to install (rethrowing): "+e);
             throw Throwables.propagate(e);
         }
     }
 
-    public <T> Maybe<Class<T>> tryResolveClass(String bundleUrl, String type) {
-        try {
-            Maybe<Bundle> bundle = Osgis.getBundle(framework, bundleUrl);
-            if (bundle.isPresent()) {
-                Class<T> clazz = (Class<T>) bundle.get().loadClass(type);
-                return Maybe.of(clazz);
-            } else {
-                return Maybe.absent("No bundle found in " + framework + " at URL: " + bundleUrl);
+    public <T> Maybe<Class<T>> tryResolveClass(String type, String... bundleUrlsOrNameVersionString) {
+        return tryResolveClass(type, Arrays.asList(bundleUrlsOrNameVersionString));
+    }
+    public <T> Maybe<Class<T>> tryResolveClass(String type, Iterable<String> bundleUrlsOrNameVersionString) {
+        Map<String,Throwable> bundleProblems = MutableMap.of();
+        for (String bundleUrlOrNameVersionString: bundleUrlsOrNameVersionString) {
+            try {
+                String bundleNameVersion = bundleUrlToNameVersionString.get(bundleUrlOrNameVersionString);
+                if (bundleNameVersion==null) {
+                    bundleNameVersion = bundleUrlOrNameVersionString;
+                }
+                
+                Maybe<Bundle> bundle = Osgis.getBundle(framework, bundleNameVersion);
+                if (bundle.isPresent()) {
+                    @SuppressWarnings("unchecked")
+                    Class<T> clazz = (Class<T>) bundle.get().loadClass(type);
+                    return Maybe.of(clazz);
+                } else {
+                    bundleProblems.put(bundleUrlOrNameVersionString, new IllegalStateException("Unable to find bundle "+bundleUrlOrNameVersionString));
+                }
+            } catch (Throwable e) {
+                Exceptions.propagateIfFatal(e);
+                bundleProblems.put(bundleUrlOrNameVersionString, e);
             }
-        } catch (ClassNotFoundException e) {
-            return Maybe.absent(e);
         }
+        return Maybe.absent("Unable to resolve class "+type+": "+bundleProblems);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/13aa4af9/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityClassResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityClassResolver.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityClassResolver.java
index df096dc..97df227 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityClassResolver.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityClassResolver.java
@@ -2,6 +2,7 @@ package io.brooklyn.camp.brooklyn.spi.creation;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.NoSuchElementException;
@@ -39,16 +40,18 @@ public class BrooklynEntityClassResolver {
      */
     public static <T extends Entity> Class<T> resolveEntity(String entityTypeName, ManagementContext mgmt, List<String> context) {
         checkNotNull(mgmt, "management context");
-        Maybe<Class<T>> entityClazz = Maybe.absent();
-        // TODO: What if context not empty but class not found? Throw?
-        if (context != null) {
-            for (String bundleUrl : context) {
-                entityClazz = tryLoadEntityFromBundle(entityTypeName, bundleUrl, mgmt);
-                if (entityClazz.isPresent()) {
-                    break;
-                }
+        Maybe<Class<T>> entityClazz = Maybe.absent("No bundles defined");
+        Maybe<Class<T>> bestError = null;
+        
+        if (context!=null && !context.isEmpty()) {
+            entityClazz = tryLoadEntityFromBundle(entityTypeName, mgmt, context);
+            if (!entityClazz.isPresent()) {
+                LOG.warn("Unable to find class "+entityTypeName+" in suggested bundles "+context+"; continuing other mechanisms");
+                // we should prefer the error message from above if context is non-empty but class can't be found
+                bestError = entityClazz;
             }
         }
+        
 
         if (!entityClazz.isPresent()) {
             entityClazz = tryLoadEntityFromCatalogue(entityTypeName, mgmt);
@@ -64,19 +67,29 @@ public class BrooklynEntityClassResolver {
             LOG.warn("Found class {} on classpath but it is not assignable to {}", entityTypeName, Entity.class);
             throw new IllegalStateException("Unable to load class "+ entityTypeName +" (extending Entity) from catalogue or classpath: wrong type "+entityClazz.get());
         }
+        if (!entityClazz.isPresent() && bestError!=null) {
+            // prefer best error if not found
+            bestError.get();
+        }
         return entityClazz.get();
     }
 
+    // TODO deprecate the ones below, make them protected or private
+    
     /** Tries to load the entity with the given class name from the given bundle. */
-    public static <T extends Entity> Maybe<Class<T>> tryLoadEntityFromBundle(String entityTypeName, String bundleUrl, ManagementContext mgmt) {
-        LOG.debug("Trying to resolve class {} from bundle {}", entityTypeName, bundleUrl);
+    public static <T extends Entity> Maybe<Class<T>> tryLoadEntityFromBundle(String entityTypeName, ManagementContext mgmt, String... bundleUrls) {
+        return tryLoadEntityFromBundle(entityTypeName, mgmt, Arrays.asList(bundleUrls));
+    }
+    public static <T extends Entity> Maybe<Class<T>> tryLoadEntityFromBundle(String entityTypeName, ManagementContext mgmt, Iterable<String> bundleUrls) {
+        LOG.debug("Trying to resolve class {} from bundle {}", entityTypeName, bundleUrls);
         Maybe<OsgiManager> osgiManager = ((ManagementContextInternal) mgmt).getOsgiManager();
         if (!osgiManager.isPresentAndNonNull()) {
-            LOG.debug("Asked to resolve class {} from bundle {} but osgi manager is unavailable in context {}",
-                    new Object[]{entityTypeName, bundleUrl, mgmt});
+            if (LOG.isDebugEnabled())
+                LOG.debug("Asked to resolve class {} from bundles {} but osgi manager is unavailable in context {}",
+                    new Object[]{entityTypeName, bundleUrls, mgmt});
             return Maybe.absent();
         }
-        Maybe<Class<T>> clazz = osgiManager.get().tryResolveClass(bundleUrl, entityTypeName);
+        Maybe<Class<T>> clazz = osgiManager.get().tryResolveClass(entityTypeName, bundleUrls);
         if (!clazz.isPresent() || !Entity.class.isAssignableFrom(clazz.get())) {
             return Maybe.absent();
         }


[35/45] git commit: Simplify custom attributes in BrooklynEntityMatcher

Posted by he...@apache.org.
Simplify custom attributes in BrooklynEntityMatcher


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

Branch: refs/heads/master
Commit: 24c78d5e71b0c979ce0077416e5aac6f4793d17e
Parents: e96af92
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Thu Jul 3 15:04:19 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Thu Jul 3 16:18:54 2014 +0100

----------------------------------------------------------------------
 .../spi/creation/BrooklynEntityMatcher.java     | 69 ++++++++------------
 1 file changed, 27 insertions(+), 42 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/24c78d5e/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
index fd58bac..d8e8fc6 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
@@ -110,48 +110,12 @@ public class BrooklynEntityMatcher implements PdpMatcher {
         // (any other brooklyn config goes here)
         if (!brooklynConfig.isEmpty())
             builder.customAttribute("brooklyn.config", brooklynConfig);
-        
-        List<Object> brooklynPolicies = Lists.newArrayList();
-        Object origBrooklynPolicies = attrs.remove("brooklyn.policies");
-        if (origBrooklynPolicies != null) {
-            if (!(origBrooklynPolicies instanceof List))
-                throw new IllegalArgumentException("brooklyn.policies must be a list of brooklyn policy definitions");
-            brooklynPolicies.addAll((List<?>)origBrooklynPolicies);
-        }
-        if (!brooklynPolicies.isEmpty())
-            builder.customAttribute("brooklyn.policies", brooklynPolicies);
-        
-        List<Object> brooklynEnrichers = Lists.newArrayList();
-        Object origBrooklynEnrichers = attrs.remove("brooklyn.enrichers");
-        if (origBrooklynEnrichers != null) {
-            if (!(origBrooklynEnrichers instanceof List))
-                throw new IllegalArgumentException("brooklyn.enrichers must be a list of brooklyn enricher definitions");
-            brooklynEnrichers.addAll((List<?>)origBrooklynEnrichers);
-        }
-        if (!brooklynEnrichers.isEmpty())
-            builder.customAttribute("brooklyn.enrichers", brooklynEnrichers);
-
-        List<Object> brooklynInitializers = Lists.newArrayList();
-        Object origBrooklynInitializers = attrs.remove("brooklyn.initializers");
-        if (origBrooklynInitializers != null) {
-            if (!(origBrooklynInitializers instanceof List))
-                throw new IllegalArgumentException("brooklyn.initializers must be a list of brooklyn initializer definitions");
-            brooklynInitializers.addAll((List<?>)origBrooklynInitializers);
-        }
-        if (!brooklynInitializers.isEmpty())
-            builder.customAttribute("brooklyn.initializers", brooklynInitializers);
-
-        List<Object> brooklynChildren = Lists.newArrayList();
-        Object origBrooklynChildren = attrs.remove("brooklyn.children");
-        if (origBrooklynChildren != null) {
-            if (!(origBrooklynChildren instanceof List))
-                throw new IllegalArgumentException("brooklyn.children must be a list of brooklyn entity definitions");
-            brooklynChildren.addAll((List<?>)origBrooklynChildren);
-        }
-        
-        if (!brooklynChildren.isEmpty())
-            builder.customAttribute("brooklyn.children",  brooklynChildren);
-        
+
+        addCustomListAttributeIfNonNull(builder, attrs, "brooklyn.policies");
+        addCustomListAttributeIfNonNull(builder, attrs, "brooklyn.enrichers");
+        addCustomListAttributeIfNonNull(builder, attrs, "brooklyn.initializers");
+        addCustomListAttributeIfNonNull(builder, attrs, "brooklyn.children");
+
         if (!attrs.isEmpty()) {
             log.warn("Ignoring PDP attributes on "+deploymentPlanItem+": "+attrs);
         }
@@ -161,6 +125,27 @@ public class BrooklynEntityMatcher implements PdpMatcher {
         return true;
     }
 
+    /**
+     * Looks for the given key in the map of attributes and adds it to the given builder
+     * as a custom attribute with type List.
+     * @throws java.lang.IllegalArgumentException if map[key] is not an instance of List
+     */
+    private void addCustomListAttributeIfNonNull(Builder<? extends PlatformComponentTemplate> builder, Map attrs, String key) {
+        Object items = attrs.remove(key);
+        if (items != null) {
+            if (items instanceof List) {
+                List<?> itemList = (List<?>) items;
+                if (!itemList.isEmpty()) {
+                    builder.customAttribute(key, Lists.newArrayList(itemList));
+                }
+            } else {
+                throw new IllegalArgumentException(key + " must be a list, is: " + items.getClass().getName());
+            }
+        }
+            }
+        }
+    }
+
     /** finds flags and keys on the given typeName which are present in the given map;
      * returns those (using the config key name), and removes them from attrs
      */


[13/45] git commit: Incorporate loading from bundles into BrooklynEntityClassResolver

Posted by he...@apache.org.
Incorporate loading from bundles into BrooklynEntityClassResolver


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

Branch: refs/heads/master
Commit: 494291d8029d6e5fa02f1444a3e5d218ca3ef902
Parents: b0bd808
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Mon Jun 30 13:19:51 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Tue Jul 1 13:37:37 2014 +0100

----------------------------------------------------------------------
 .../java/brooklyn/catalog/BrooklynCatalog.java  |  2 ++
 .../internal/CatalogItemDtoAbstract.java        | 17 ++++++++--
 .../management/osgi/OsgiStandaloneTest.java     |  1 +
 .../creation/BrooklynEntityClassResolver.java   | 33 ++++++++++++++++++--
 .../spi/creation/BrooklynYamlTypeLoader.java    | 11 ++++---
 5 files changed, 54 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/494291d8/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java b/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
index 622241f..720a2bc 100644
--- a/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
+++ b/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
@@ -13,6 +13,7 @@ public interface BrooklynCatalog {
     
     /** returns all items in the catalog */
     <T> Iterable<CatalogItem<T>> getCatalogItems();
+
     /** convenience for filtering items in the catalog; see CatalogPredicates for useful filters */
     <T> Iterable<CatalogItem<T>> getCatalogItems(Predicate<? super CatalogItem<T>> filter);
 
@@ -42,6 +43,7 @@ public interface BrooklynCatalog {
 
     /** adds a classpath entry which will be used by the 'manual' catalog */
     void addToClasspath(ClassLoader loader);
+
     /** adds a classpath entry which will be used by the 'manual' catalog */
     void addToClasspath(String url);
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/494291d8/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
index ad0fa71..043758b 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
@@ -1,11 +1,21 @@
 package brooklyn.catalog.internal;
 
-import javax.annotation.Nullable;
+import java.util.Collections;
+import java.util.List;
+
+import javax.annotation.Nonnull;
 
 import brooklyn.catalog.CatalogItem;
 
 public abstract class CatalogItemDtoAbstract<T> implements CatalogItem<T> {
-    
+
+    private static final CatalogItemContext EMPTY_CONTEXT = new CatalogItemContext() {
+        @Override
+        public List<String> getBundles() {
+            return Collections.emptyList();
+        }
+    };
+
     String id;
     String type;
     String name;
@@ -34,6 +44,7 @@ public abstract class CatalogItemDtoAbstract<T> implements CatalogItem<T> {
         return iconUrl;
     }
 
+    @Nonnull
     @Override
     public CatalogItemContext getContext() {
         return context;
@@ -76,7 +87,7 @@ public abstract class CatalogItemDtoAbstract<T> implements CatalogItem<T> {
         target.type = type;
         target.name = name;
         target.description = description;
-        target.context = context;
+        target.context = context != null ? context : EMPTY_CONTEXT;
         return target;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/494291d8/core/src/test/java/brooklyn/management/osgi/OsgiStandaloneTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/osgi/OsgiStandaloneTest.java b/core/src/test/java/brooklyn/management/osgi/OsgiStandaloneTest.java
index 7ffaf2d..2461f27 100644
--- a/core/src/test/java/brooklyn/management/osgi/OsgiStandaloneTest.java
+++ b/core/src/test/java/brooklyn/management/osgi/OsgiStandaloneTest.java
@@ -110,6 +110,7 @@ public class OsgiStandaloneTest {
         Object result = aClass.getMethod("times", int.class).invoke(aInst, input);
         Assert.assertEquals(result, output);
     }
+
     protected void setAMultiplier(Bundle bundle, int newMultiplier) throws Exception {
         Assert.assertNotNull(bundle);
         Class<?> aClass = bundle.loadClass("brooklyn.test.osgi.TestA");

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/494291d8/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityClassResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityClassResolver.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityClassResolver.java
index 7e71bb5..df096dc 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityClassResolver.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityClassResolver.java
@@ -2,6 +2,8 @@ package io.brooklyn.camp.brooklyn.spi.creation;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
+import java.util.Collections;
+import java.util.List;
 import java.util.NoSuchElementException;
 
 import org.slf4j.Logger;
@@ -27,9 +29,33 @@ public class BrooklynEntityClassResolver {
      * @throws java.lang.IllegalStateException if no class extending {@link Entity} is found
      */
     public static <T extends Entity> Class<T> resolveEntity(String entityTypeName, ManagementContext mgmt) {
+        return resolveEntity(entityTypeName, mgmt, Collections.<String>emptyList());
+    }
+
+    /**
+     * Loads the class represented by entityTypeName with the given management context.
+     * Tries the context's catalogue first, then from its root classloader.
+     * @throws java.lang.IllegalStateException if no class extending {@link Entity} is found
+     */
+    public static <T extends Entity> Class<T> resolveEntity(String entityTypeName, ManagementContext mgmt, List<String> context) {
         checkNotNull(mgmt, "management context");
-        Maybe<Class<T>> entityClazz = tryLoadEntityFromCatalogue(entityTypeName, mgmt);
-        if (!entityClazz.isPresent()) entityClazz = tryLoadFromClasspath(entityTypeName, mgmt);
+        Maybe<Class<T>> entityClazz = Maybe.absent();
+        // TODO: What if context not empty but class not found? Throw?
+        if (context != null) {
+            for (String bundleUrl : context) {
+                entityClazz = tryLoadEntityFromBundle(entityTypeName, bundleUrl, mgmt);
+                if (entityClazz.isPresent()) {
+                    break;
+                }
+            }
+        }
+
+        if (!entityClazz.isPresent()) {
+            entityClazz = tryLoadEntityFromCatalogue(entityTypeName, mgmt);
+        }
+        if (!entityClazz.isPresent()) {
+            entityClazz = tryLoadFromClasspath(entityTypeName, mgmt);
+        }
         if (!entityClazz.isPresent()) {
             LOG.warn("No catalog item for {} and could not load class directly; throwing", entityTypeName);
             throw new IllegalStateException("Unable to load class "+ entityTypeName +" (extending Entity) from catalogue or classpath: not found");
@@ -43,6 +69,7 @@ public class BrooklynEntityClassResolver {
 
     /** Tries to load the entity with the given class name from the given bundle. */
     public static <T extends Entity> Maybe<Class<T>> tryLoadEntityFromBundle(String entityTypeName, String bundleUrl, ManagementContext mgmt) {
+        LOG.debug("Trying to resolve class {} from bundle {}", entityTypeName, bundleUrl);
         Maybe<OsgiManager> osgiManager = ((ManagementContextInternal) mgmt).getOsgiManager();
         if (!osgiManager.isPresentAndNonNull()) {
             LOG.debug("Asked to resolve class {} from bundle {} but osgi manager is unavailable in context {}",
@@ -58,6 +85,7 @@ public class BrooklynEntityClassResolver {
 
     @SuppressWarnings("unchecked")
     public static <T extends Entity> Maybe<Class<T>> tryLoadEntityFromCatalogue(String entityTypeName, ManagementContext mgmt) {
+        LOG.debug("Trying to resolve class {} from catalog", entityTypeName);
         try {
             return (Maybe<Class<T>>)(Maybe<?>) Maybe.<Class<? extends Entity>>of(mgmt.getCatalog().loadClassByType(entityTypeName, Entity.class));
         } catch (NoSuchElementException e) {
@@ -68,6 +96,7 @@ public class BrooklynEntityClassResolver {
 
     @SuppressWarnings("unchecked")
     public static <T> Maybe<Class<T>> tryLoadFromClasspath(String typeName, ManagementContext mgmt) {
+        LOG.debug("Trying to resolve class {} from classpath", typeName);
         Class<T> clazz;
         try {
             clazz = (Class<T>) mgmt.getCatalog().getRootClassLoader().loadClass(typeName);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/494291d8/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeLoader.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeLoader.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeLoader.java
index 77c8580..747e507 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeLoader.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeLoader.java
@@ -15,6 +15,7 @@ import brooklyn.util.config.ConfigBag;
 import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.guava.Maybe;
 import brooklyn.util.javalang.Reflections;
+import brooklyn.util.osgi.Osgis;
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.Optional;
@@ -167,23 +168,23 @@ public abstract class BrooklynYamlTypeLoader {
         return loadClass(type, getTypeName().get(), factory.mgmt, factory.contextForLogging);
     }
 
-    /** 
+    /**
      * TODO in future will want OSGi-based resolver here (eg create from osgi:<bundle>: prefix
      * would use that OSGi mechanism here
      */
     @SuppressWarnings("unchecked")
     private static <T> Class<T> loadClass(@Nullable Class<T> optionalSupertype, String typeName, ManagementContext mgmt, Object otherContext) {
         try {
-            if (optionalSupertype!=null && Entity.class.isAssignableFrom(optionalSupertype)) 
+            if (optionalSupertype != null && Entity.class.isAssignableFrom(optionalSupertype))
                 return (Class<T>) BrooklynEntityClassResolver.<Entity>resolveEntity(typeName, mgmt);
             else
                 return BrooklynEntityClassResolver.<T>tryLoadFromClasspath(typeName, mgmt).get();
         } catch (Exception e) {
             Exceptions.propagateIfFatal(e);
-            log.warn("Unable to resolve "+typeName+" in spec "+otherContext);
+            log.warn("Unable to resolve " + typeName + " in spec " + otherContext);
             throw Exceptions.propagate(new IllegalStateException("Unable to resolve "
-                + (optionalSupertype!=null ? optionalSupertype.getSimpleName()+" " : "")
-                + "type '"+typeName+"'", e));
+                    + (optionalSupertype != null ? optionalSupertype.getSimpleName() + " " : "")
+                    + "type '" + typeName + "'", e));
         }
     }
 


[06/45] git commit: Note problem with BrooklynAssemblyTemplateInstantiator catalog path

Posted by he...@apache.org.
Note problem with BrooklynAssemblyTemplateInstantiator catalog path


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

Branch: refs/heads/master
Commit: 76ff185a0675ae916c053470609480d987a16128
Parents: edcaee4
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Mon Jun 30 17:24:33 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Tue Jul 1 13:37:37 2014 +0100

----------------------------------------------------------------------
 .../BrooklynAssemblyTemplateInstantiator.java      | 17 ++++-------------
 1 file changed, 4 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/76ff185a/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 a06d716..05d6efb 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
@@ -1,7 +1,6 @@
 package io.brooklyn.camp.brooklyn.spi.creation;
 
 import io.brooklyn.camp.CampPlatform;
-import io.brooklyn.camp.brooklyn.BrooklynCampPlatform;
 import io.brooklyn.camp.brooklyn.spi.platform.HasBrooklynManagementContext;
 import io.brooklyn.camp.spi.Assembly;
 import io.brooklyn.camp.spi.AssemblyTemplate;
@@ -63,20 +62,12 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateIns
         
         ManagementContext mgmt = getBrooklynManagementContext(platform);
         BrooklynCatalog catalog = mgmt.getCatalog();
+        // TODO: item is always null because template.id is a random String, so
+        // createApplicationFromCatalog branch below is never taken.  If `id'
+        // key is given in blueprint it is available with:
+        // Object customId = template.getCustomAttributes().get("id");
         CatalogItem<?> item = catalog.getCatalogItem(template.getId());
 
-        if (item == null) {
-            // This doesn't seem the most appropriate way to do this!
-            // Especially since YAML will only reach here if a services section was given (so that
-            // PdpProcessor calls into BrooklynEntityMatcher [via applyMatchers] which sets the
-            // instantiator to BrooklynAssemblyTemplateInstantiator). So services must be given
-            // but will be disregarded.
-            Object customId = template.getCustomAttributes().get("id");
-            if (customId != null) {
-                item = catalog.getCatalogItem(customId.toString());
-            }
-        }
-
         if (item==null) {
             return createApplicationFromNonCatalogCampTemplate(template, platform);
         } else {


[25/45] git commit: Merge remote-tracking branch 'neykov/yaml-promote-app' into osgi2

Posted by he...@apache.org.
Merge remote-tracking branch 'neykov/yaml-promote-app' into osgi2


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

Branch: refs/heads/master
Commit: a3915225ee0bb337159c49837344399757d58994
Parents: 74ddd83 c43eb16
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Wed Jul 2 16:13:03 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Wed Jul 2 16:13:03 2014 +0100

----------------------------------------------------------------------
 .../BrooklynAssemblyTemplateInstantiator.java   | 80 +++++++++++++++-----
 .../io/brooklyn/camp/brooklyn/WrapAppTest.java  | 75 ++++++++++++++++++
 2 files changed, 134 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a3915225/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
----------------------------------------------------------------------


[42/45] git commit: fix failing tests by restoring feature defaults on feature cache clear

Posted by he...@apache.org.
fix failing tests by restoring feature defaults on feature cache clear


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

Branch: refs/heads/master
Commit: 8094765dbf862053bc21fd534376345b33d23d00
Parents: f28d9cc
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Fri Jul 4 10:36:06 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri Jul 4 10:37:45 2014 +0100

----------------------------------------------------------------------
 .../java/brooklyn/entity/basic/BrooklynShutdownHooks.java     | 2 +-
 .../main/java/brooklyn/entity/rebind/RebindManagerImpl.java   | 2 ++
 .../java/brooklyn/internal/BrooklynFeatureEnablement.java     | 7 ++++++-
 3 files changed, 9 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8094765d/core/src/main/java/brooklyn/entity/basic/BrooklynShutdownHooks.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/BrooklynShutdownHooks.java b/core/src/main/java/brooklyn/entity/basic/BrooklynShutdownHooks.java
index 3692237..178c3d8 100644
--- a/core/src/main/java/brooklyn/entity/basic/BrooklynShutdownHooks.java
+++ b/core/src/main/java/brooklyn/entity/basic/BrooklynShutdownHooks.java
@@ -175,7 +175,7 @@ public class BrooklynShutdownHooks {
             if (entitiesToStop.isEmpty()) {
                 log.debug("Brooklyn shutdown: no entities to stop");
             } else {
-                log.info("Brooklyn stopdown: stopping entities "+entitiesToStop);
+                log.info("Brooklyn shutdown: stopping entities "+entitiesToStop);
                 destroyAndWait(entitiesToStop, shutdownTimeout);
             }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8094765d/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
index f105efe..5775dc4 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
@@ -135,6 +135,8 @@ public class RebindManagerImpl implements RebindManager {
         rebindFailureMode = managementContext.getConfig().getConfig(REBIND_FAILURE_MODE);
         addPolicyFailureMode = managementContext.getConfig().getConfig(ADD_POLICY_FAILURE_MODE);
         loadPolicyFailureMode = managementContext.getConfig().getConfig(LOAD_POLICY_FAILURE_MODE);
+        
+        LOG.debug("Persistence in "+this+" of: policies="+persistEnrichersEnabled+" enrichers="+persistEnrichersEnabled);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8094765d/core/src/main/java/brooklyn/internal/BrooklynFeatureEnablement.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/internal/BrooklynFeatureEnablement.java b/core/src/main/java/brooklyn/internal/BrooklynFeatureEnablement.java
index 8838b46..9bfc188 100644
--- a/core/src/main/java/brooklyn/internal/BrooklynFeatureEnablement.java
+++ b/core/src/main/java/brooklyn/internal/BrooklynFeatureEnablement.java
@@ -22,7 +22,7 @@ public class BrooklynFeatureEnablement {
 
     private static final Object MUTEX = new Object();
     
-    static {
+    static void setDefaults() {
         // Idea is here one can put experimental features that are *enabled* by default, but 
         // that can be turned off via system properties, or vice versa.
         // Typically this is useful where a feature is deemed risky!
@@ -31,6 +31,10 @@ public class BrooklynFeatureEnablement {
         setDefault(FEATURE_ENRICHER_PERSISTENCE_PROPERTY, true);
     }
     
+    static {
+        setDefaults();
+    }
+    
     public static boolean isEnabled(String property) {
         synchronized (MUTEX) {
             if (!FEATURE_ENABLEMENTS.containsKey(property)) {
@@ -72,6 +76,7 @@ public class BrooklynFeatureEnablement {
     static void clearCache() {
         synchronized (MUTEX) {
             FEATURE_ENABLEMENTS.clear();
+            setDefaults();
         }
     }
 }


[05/45] git commit: osgi wip

Posted by he...@apache.org.
osgi wip


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

Branch: refs/heads/master
Commit: 79ebcc3382cdd3e8725967aa2c139696ce1f2294
Parents: 1809b36
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Jun 10 20:27:57 2014 -0700
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Tue Jul 1 13:37:36 2014 +0100

----------------------------------------------------------------------
 core/pom.xml                                    |   6 +
 .../brooklyn/config/BrooklynServerConfig.java   |   3 +
 .../brooklyn/management/ha/OsgiManager.java     |  48 +++++++
 .../internal/LocalManagementContext.java        |  17 +++
 .../internal/ManagementContextInternal.java     |   5 +
 .../NonDeploymentManagementContext.java         |   6 +
 .../src/main/java/brooklyn/util/osgi/Osgis.java | 139 +++++++++++++++++++
 .../management/osgi/OsgiStandaloneTest.java     | 119 ++++++++++++++++
 .../entity/LocalManagementContextForTests.java  |   9 +-
 .../osgi/brooklyn-osgi-test-a_0.1.0.jar         | Bin 0 -> 2055 bytes
 pom.xml                                         |   1 +
 11 files changed, 351 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/79ebcc33/core/pom.xml
----------------------------------------------------------------------
diff --git a/core/pom.xml b/core/pom.xml
index 1056ad1..f80aa24 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -85,6 +85,12 @@
         </dependency>
 
         <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.framework</artifactId>
+            <version>${felix.framework.version}</version>
+        </dependency>
+
+        <dependency>
             <groupId>org.reflections</groupId>
             <artifactId>reflections</artifactId>
             <version>${reflections.version}</version>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/79ebcc33/core/src/main/java/brooklyn/config/BrooklynServerConfig.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/config/BrooklynServerConfig.java b/core/src/main/java/brooklyn/config/BrooklynServerConfig.java
index 6154ba6..f564176 100644
--- a/core/src/main/java/brooklyn/config/BrooklynServerConfig.java
+++ b/core/src/main/java/brooklyn/config/BrooklynServerConfig.java
@@ -131,4 +131,7 @@ public class BrooklynServerConfig {
         "or empty for no URL (use default scanner)", 
         new File(Os.fromHome(".brooklyn/catalog.xml")).toURI().toString());
     
+    public static final ConfigKey<Boolean> USE_OSGI = ConfigKeys.newBooleanConfigKey("brooklyn.osgi.enabled",
+        "Whether OSGi is enabled, defaulting to true", true);
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/79ebcc33/core/src/main/java/brooklyn/management/ha/OsgiManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/ha/OsgiManager.java b/core/src/main/java/brooklyn/management/ha/OsgiManager.java
new file mode 100644
index 0000000..07400ec
--- /dev/null
+++ b/core/src/main/java/brooklyn/management/ha/OsgiManager.java
@@ -0,0 +1,48 @@
+package brooklyn.management.ha;
+
+import java.io.File;
+
+import org.osgi.framework.BundleException;
+import org.osgi.framework.launch.Framework;
+
+import brooklyn.config.BrooklynServerConfig;
+import brooklyn.config.ConfigKey;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.os.Os;
+import brooklyn.util.osgi.Osgis;
+
+public class OsgiManager {
+
+    public static final ConfigKey<Boolean> USE_OSGI = BrooklynServerConfig.USE_OSGI;
+    
+    /* see Osgis for info on starting framework etc */
+    
+    protected Framework framework;
+    protected File osgiTempDir;
+    
+    public void start() {
+        try {
+            // TODO any extra startup args?
+            // TODO dir to come from brooklyn properties;
+            // note dir must be different for each if starting multiple instances
+            osgiTempDir = Os.newTempDir("brooklyn-osgi-cache");
+            framework = Osgis.newFrameworkStarted(osgiTempDir.getAbsolutePath(), false, MutableMap.of());
+            
+        } catch (Exception e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+
+    public void stop() {
+        try {
+            if (framework!=null)
+                framework.stop();
+        } catch (BundleException e) {
+            throw Exceptions.propagate(e);
+        }
+        osgiTempDir = Os.deleteRecursively(osgiTempDir).asNullOrThrowing();
+        framework = null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/79ebcc33/core/src/main/java/brooklyn/management/internal/LocalManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/LocalManagementContext.java b/core/src/main/java/brooklyn/management/internal/LocalManagementContext.java
index c84a200..0d3deb9 100644
--- a/core/src/main/java/brooklyn/management/internal/LocalManagementContext.java
+++ b/core/src/main/java/brooklyn/management/internal/LocalManagementContext.java
@@ -34,6 +34,7 @@ import brooklyn.management.ExecutionManager;
 import brooklyn.management.ManagementContext;
 import brooklyn.management.SubscriptionManager;
 import brooklyn.management.Task;
+import brooklyn.management.ha.OsgiManager;
 import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.task.BasicExecutionContext;
 import brooklyn.util.task.BasicExecutionManager;
@@ -99,6 +100,7 @@ public class LocalManagementContext extends AbstractManagementContext {
     private final LocalLocationManager locationManager;
     private final LocalAccessManager accessManager;
     private final LocalUsageManager usageManager;
+    private OsgiManager osgiManager;
     
     public final Throwable constructionStackTrace = new Throwable("for construction stacktrace").fillInStackTrace();
     
@@ -160,6 +162,11 @@ public class LocalManagementContext extends AbstractManagementContext {
         this.accessManager = new LocalAccessManager();
         this.usageManager = new LocalUsageManager(this);
         
+        if (configMap.getConfig(OsgiManager.USE_OSGI)) {
+            this.osgiManager = new OsgiManager();
+            osgiManager.start();
+        }
+        
         INSTANCES.add(this);
         log.debug("Created management context "+this);
     }
@@ -246,6 +253,12 @@ public class LocalManagementContext extends AbstractManagementContext {
         if (!isRunning()) throw new IllegalStateException("Management context no longer running");
         return usageManager;
     }
+    
+    @Override
+    public synchronized OsgiManager getOsgiManager() {
+        if (!isRunning()) throw new IllegalStateException("Management context no longer running");
+        return osgiManager;        
+    }
 
     @Override
     public synchronized AccessController getAccessController() {
@@ -277,6 +290,10 @@ public class LocalManagementContext extends AbstractManagementContext {
     public void terminate() {
         INSTANCES.remove(this);
         super.terminate();
+        if (osgiManager!=null) {
+            osgiManager.stop();
+            osgiManager = null;
+        }
         if (execution != null) execution.shutdownNow();
         if (gc != null) gc.shutdownNow();
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/79ebcc33/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java b/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java
index 2565b40..fb50641 100644
--- a/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java
+++ b/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java
@@ -18,6 +18,7 @@ import brooklyn.internal.storage.BrooklynStorage;
 import brooklyn.location.Location;
 import brooklyn.management.ManagementContext;
 import brooklyn.management.Task;
+import brooklyn.management.ha.OsgiManager;
 import brooklyn.util.task.TaskTags;
 
 public interface ManagementContextInternal extends ManagementContext {
@@ -57,6 +58,10 @@ public interface ManagementContextInternal extends ManagementContext {
     AccessManager getAccessManager();
 
     UsageManager getUsageManager();
+    
+    /** returns OSGi manager, if available; may be null if OSGi not supported, e.g. in test contexts
+     * (but major contexts will support this) */
+    OsgiManager getOsgiManager();
 
     InternalEntityFactory getEntityFactory();
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/79ebcc33/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java b/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
index 85b7029..61826ef 100644
--- a/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
+++ b/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
@@ -44,6 +44,7 @@ import brooklyn.management.ha.HighAvailabilityMode;
 import brooklyn.management.ha.ManagementNodeState;
 import brooklyn.management.ha.ManagementPlaneSyncRecord;
 import brooklyn.management.ha.ManagementPlaneSyncRecordPersister;
+import brooklyn.management.ha.OsgiManager;
 import brooklyn.mementos.BrooklynMementoPersister;
 import brooklyn.util.guava.Maybe;
 import brooklyn.util.time.Duration;
@@ -175,6 +176,11 @@ public class NonDeploymentManagementContext implements ManagementContextInternal
     public UsageManager getUsageManager() {
         return usageManager;
     }
+    
+    @Override
+    public OsgiManager getOsgiManager() {
+        return null;
+    }
 
     @Override
     public AccessController getAccessController() {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/79ebcc33/core/src/main/java/brooklyn/util/osgi/Osgis.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/osgi/Osgis.java b/core/src/main/java/brooklyn/util/osgi/Osgis.java
new file mode 100644
index 0000000..2cfc5a7
--- /dev/null
+++ b/core/src/main/java/brooklyn/util/osgi/Osgis.java
@@ -0,0 +1,139 @@
+package brooklyn.util.osgi;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.framework.FrameworkFactory;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
+import org.osgi.framework.launch.Framework;
+
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.guava.Maybe;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+
+/** 
+ * utilities for working with osgi.
+ * osgi support is in early days (June 2014) so this class is beta, subject to change,
+ * particularly in how framework is started and bundles installed.
+ * 
+ * @since 0.7.0  */
+@Beta
+public class Osgis {
+
+    public static List<Bundle> getBundlesByName(Framework framework, String symbolicName, Predicate<Version> versionMatcher) {
+        List<Bundle> result = MutableList.of();
+        for (Bundle b: framework.getBundleContext().getBundles()) {
+            if (symbolicName.equals(b.getSymbolicName())) {
+                if (versionMatcher.apply(b.getVersion())) {
+                    result.add(b);
+                }
+            }
+        }
+        return result;
+    }
+
+    public static List<Bundle> getBundlesByName(Framework framework, String symbolicName) {
+        return getBundlesByName(framework, symbolicName, Predicates.<Version>alwaysTrue());
+    }
+    
+    public static Maybe<Bundle> getBundle(Framework framework, String symbolicNameOptionallyWithVersion) {
+        String[] parts = symbolicNameOptionallyWithVersion.split(":");
+        List<Bundle> matches;
+        if (parts.length==2) {
+            return getBundle(framework, symbolicNameOptionallyWithVersion);
+        } else if (parts.length==1) {
+            matches = getBundlesByName(framework, symbolicNameOptionallyWithVersion);
+            if (matches.isEmpty()) return Maybe.absent("no bundles matching "+symbolicNameOptionallyWithVersion);
+            return Maybe.of(matches.iterator().next());
+        } else {
+            throw new IllegalArgumentException("Cannot parse symbolic-name:version string '"+symbolicNameOptionallyWithVersion+"'");
+        }
+    }
+    
+    public static Maybe<Bundle> getBundle(Framework framework, String symbolicName, String version) {
+        return getBundle(framework, symbolicName, Version.parseVersion(version));
+    }
+
+    public static Maybe<Bundle> getBundle(Framework framework, String symbolicName, Version version) {
+        List<Bundle> matches = getBundlesByName(framework, symbolicName, Predicates.<Version>equalTo(version));
+        if (matches.isEmpty()) return Maybe.absent("no bundles matching "+symbolicName+":"+version);
+        return Maybe.of(matches.iterator().next());
+    }
+
+    // -------- creating
+    
+    /*
+     * loading framework factory and starting framework based on:
+     * http://felix.apache.org/documentation/subprojects/apache-felix-framework/apache-felix-framework-launching-and-embedding.html :
+     */
+    
+    public static FrameworkFactory newFrameworkFactory() {
+        URL url = Osgis.class.getClassLoader().getResource(
+                "META-INF/services/org.osgi.framework.launch.FrameworkFactory");
+        if (url != null) {
+            try {
+                BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
+                try {
+                    for (String s = br.readLine(); s != null; s = br.readLine()) {
+                        s = s.trim();
+                        // load the first non-empty, non-commented line
+                        if ((s.length() > 0) && (s.charAt(0) != '#')) {
+                            return (FrameworkFactory) Class.forName(s).newInstance();
+                        }
+                    }
+                } finally {
+                    if (br != null) br.close();
+                }
+            } catch (Exception e) {
+                // class creation exceptions are not interesting to caller...
+                throw Exceptions.propagate(e);
+            }
+        }
+        throw new IllegalStateException("Could not find framework factory.");
+    }
+    
+    public static Framework newFrameworkStarted(String felixCacheDir, boolean clean, Map<?,?> extraStartupConfig) {
+        Map<Object,Object> cfg = MutableMap.copyOf(extraStartupConfig);
+        if (clean) cfg.put(Constants.FRAMEWORK_STORAGE_CLEAN, "onFirstInit");
+        if (felixCacheDir!=null) cfg.put(Constants.FRAMEWORK_STORAGE, felixCacheDir);
+        FrameworkFactory factory = newFrameworkFactory();
+        
+        Framework framework = factory.newFramework(cfg);
+        try {
+            framework.init();
+            // nothing needs auto-loading, currently (and this needs a new dependency)
+//            AutoProcessor.process(configProps, m_fwk.getBundleContext());
+            framework.start();
+        } catch (Exception e) {
+            // framework bundle start exceptions are not interesting to caller...
+            throw Exceptions.propagate(e);
+        }
+        return framework;
+    }
+
+    /** install a bundle from the given URL, doing a check if already installed, and
+     * using the {@link ResourceUtils} loader for this project (brooklyn core) */
+    public static Bundle install(Framework framework, String url) throws BundleException {
+        Bundle bundle = framework.getBundleContext().getBundle(url);
+        if (bundle!=null) return bundle;
+        
+        // use our URL resolution so we get classpath items
+        InputStream stream = ResourceUtils.create(Osgis.class).getResourceFromUrl(url);
+        return framework.getBundleContext().installBundle(url, stream);
+    }
+    
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/79ebcc33/core/src/test/java/brooklyn/management/osgi/OsgiStandaloneTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/osgi/OsgiStandaloneTest.java b/core/src/test/java/brooklyn/management/osgi/OsgiStandaloneTest.java
new file mode 100644
index 0000000..7ffaf2d
--- /dev/null
+++ b/core/src/test/java/brooklyn/management/osgi/OsgiStandaloneTest.java
@@ -0,0 +1,119 @@
+package brooklyn.management.osgi;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.commons.io.FileUtils;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.launch.Framework;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.util.os.Os;
+import brooklyn.util.osgi.Osgis;
+
+/** tests some assumptions about OSGi behaviour, in standalone mode (not part of brooklyn).
+ * 
+ * relies on the following bundles, which exist in the classpath (and contain their sources):
+ * 
+ * <li>brooklyn-osgi-test-a_0.1.0 -
+ *     defines TestA which has a "times" method and a static multiplier field;
+ *     we set the multiplier to determine when we are sharing versions and when not
+ *     
+ *  */
+public class OsgiStandaloneTest {
+
+    public static final String BROOKLYN_OSGI_TEST_A_0_1_0_URL = "classpath:///brooklyn/osgi/brooklyn-osgi-test-a_0.1.0.jar";
+    
+    protected Framework framework = null;
+    private File storageTempDir;
+
+    @BeforeMethod
+    public void setUp() throws Exception {
+        storageTempDir = Os.newTempDir("osgi-standalone");
+        framework = Osgis.newFrameworkStarted(storageTempDir.getAbsolutePath(), true, null);
+    }
+
+    @AfterMethod
+    public void tearDown() throws BundleException, IOException {
+        if (framework!=null) {
+            framework.stop();
+            framework = null;
+        }
+        if (storageTempDir!=null) {
+            FileUtils.deleteDirectory(storageTempDir);
+            storageTempDir = null;
+        }
+    }
+
+    protected Bundle install(String url) throws BundleException {
+        try {
+            return Osgis.install(framework, url);
+        } catch (Exception e) {
+            throw new IllegalStateException("test resources not available; may be an IDE issue, so try a mvn rebuild of this project", e);
+        }
+    }
+    
+    @Test
+    public void testInstallBundle() throws Exception {
+        Bundle bundle = install(BROOKLYN_OSGI_TEST_A_0_1_0_URL);
+        checkMath(bundle, 3, 6);
+    }
+
+    @Test
+    public void testAMultiplier() throws Exception {
+        Bundle bundle = install(BROOKLYN_OSGI_TEST_A_0_1_0_URL);
+        checkMath(bundle, 3, 6);
+        setAMultiplier(bundle, 5);
+        checkMath(bundle, 3, 15);
+    }
+
+    /** run two multiplier tests to ensure that irrespective of order the tests run in, 
+     * on a fresh install the multiplier is reset */
+    @Test
+    public void testANOtherMultiple() throws Exception {
+        Bundle bundle = install(BROOKLYN_OSGI_TEST_A_0_1_0_URL);
+        checkMath(bundle, 3, 6);
+        setAMultiplier(bundle, 14);
+        checkMath(bundle, 3, 42);
+    }
+
+    @Test
+    public void testGetBundle() throws Exception {
+        Bundle bundle = install(BROOKLYN_OSGI_TEST_A_0_1_0_URL);
+        setAMultiplier(bundle, 3);
+
+        // can look it up based on the same location string (no other "location identifier" reference string seems to work here, however) 
+        Bundle bundle2 = install(BROOKLYN_OSGI_TEST_A_0_1_0_URL);
+        checkMath(bundle2, 3, 9);
+    }
+
+    @Test
+    public void testUninstallAndReinstallBundle() throws Exception {
+        Bundle bundle = install(BROOKLYN_OSGI_TEST_A_0_1_0_URL);
+        checkMath(bundle, 3, 6);
+        setAMultiplier(bundle, 3);
+        checkMath(bundle, 3, 9);
+        bundle.uninstall();
+        
+        Bundle bundle2 = install(BROOKLYN_OSGI_TEST_A_0_1_0_URL);
+        checkMath(bundle2, 3, 6);
+    }
+
+    protected void checkMath(Bundle bundle, int input, int output) throws Exception {
+        Assert.assertNotNull(bundle);
+        Class<?> aClass = bundle.loadClass("brooklyn.test.osgi.TestA");
+        Object aInst = aClass.newInstance();
+        Object result = aClass.getMethod("times", int.class).invoke(aInst, input);
+        Assert.assertEquals(result, output);
+    }
+    protected void setAMultiplier(Bundle bundle, int newMultiplier) throws Exception {
+        Assert.assertNotNull(bundle);
+        Class<?> aClass = bundle.loadClass("brooklyn.test.osgi.TestA");
+        aClass.getField("multiplier").set(null, newMultiplier);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/79ebcc33/core/src/test/java/brooklyn/test/entity/LocalManagementContextForTests.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/test/entity/LocalManagementContextForTests.java b/core/src/test/java/brooklyn/test/entity/LocalManagementContextForTests.java
index 2b2a884..3631ff4 100644
--- a/core/src/test/java/brooklyn/test/entity/LocalManagementContextForTests.java
+++ b/core/src/test/java/brooklyn/test/entity/LocalManagementContextForTests.java
@@ -2,7 +2,6 @@ package brooklyn.test.entity;
 
 import brooklyn.config.BrooklynProperties;
 import brooklyn.config.BrooklynServerConfig;
-import brooklyn.management.internal.AbstractManagementContext;
 import brooklyn.management.internal.LocalManagementContext;
 
 /** management context which forces an empty catalog to prevent scanning / interacting with local filesystem.
@@ -21,7 +20,13 @@ public class LocalManagementContextForTests extends LocalManagementContext {
 
     public static BrooklynProperties setEmptyCatalogAsDefault(BrooklynProperties brooklynProperties) {
         if (brooklynProperties==null) return null;
-        brooklynProperties.putIfAbsent(AbstractManagementContext.BROOKLYN_CATALOG_URL, "classpath://brooklyn-catalog-empty.xml");
+        brooklynProperties.putIfAbsent(BrooklynServerConfig.BROOKLYN_CATALOG_URL, "classpath://brooklyn-catalog-empty.xml");
+        return brooklynProperties;
+    }
+    
+    public static BrooklynProperties disableOsgi(BrooklynProperties brooklynProperties) {
+        if (brooklynProperties==null) return null;
+        brooklynProperties.putIfAbsent(BrooklynServerConfig.USE_OSGI, false);
         return brooklynProperties;
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/79ebcc33/core/src/test/resources/brooklyn/osgi/brooklyn-osgi-test-a_0.1.0.jar
----------------------------------------------------------------------
diff --git a/core/src/test/resources/brooklyn/osgi/brooklyn-osgi-test-a_0.1.0.jar b/core/src/test/resources/brooklyn/osgi/brooklyn-osgi-test-a_0.1.0.jar
new file mode 100644
index 0000000..b4c777c
Binary files /dev/null and b/core/src/test/resources/brooklyn/osgi/brooklyn-osgi-test-a_0.1.0.jar differ

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/79ebcc33/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index f95beca..70a128b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -99,6 +99,7 @@
         <mx4j.version>3.0.1</mx4j.version>
         <bouncycastle.version>1.49</bouncycastle.version>
         <sshj.version>0.8.1</sshj.version>
+        <felix.framework.version>4.4.0</felix.framework.version>
         <reflections.version>0.9.9-RC1</reflections.version>
         <jetty.version>8.1.4.v20120524</jetty.version>
         <airline.version>0.6</airline.version>


[14/45] git commit: BROOKLYN-13: Handle absent bundle in OsgiManager.tryResolveClass

Posted by he...@apache.org.
BROOKLYN-13: Handle absent bundle in OsgiManager.tryResolveClass


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

Branch: refs/heads/master
Commit: 30093bb4a076f20e2fd3eac9451fc5c1ce36db48
Parents: 76ff185
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Tue Jul 1 13:38:45 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Tue Jul 1 13:38:45 2014 +0100

----------------------------------------------------------------------
 .../java/brooklyn/management/ha/OsgiManager.java    | 16 ++++++++++++----
 core/src/main/java/brooklyn/util/osgi/Osgis.java    |  1 +
 2 files changed, 13 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/30093bb4/core/src/main/java/brooklyn/management/ha/OsgiManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/ha/OsgiManager.java b/core/src/main/java/brooklyn/management/ha/OsgiManager.java
index c161190..d519af5 100644
--- a/core/src/main/java/brooklyn/management/ha/OsgiManager.java
+++ b/core/src/main/java/brooklyn/management/ha/OsgiManager.java
@@ -2,9 +2,12 @@ package brooklyn.management.ha;
 
 import java.io.File;
 
+import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleException;
 import org.osgi.framework.launch.Framework;
 
+import com.google.common.base.Throwables;
+
 import brooklyn.config.BrooklynServerConfig;
 import brooklyn.config.ConfigKey;
 import brooklyn.util.collections.MutableMap;
@@ -54,11 +57,16 @@ public class OsgiManager {
     // TODO: Handle .get failing
     public <T> Maybe<Class<T>> tryResolveClass(String bundleUrl, String type) {
         try {
-            Class<T> clazz = (Class<T>) Osgis.getBundle(framework, bundleUrl).get().loadClass(type);
-            return Maybe.of(clazz);
-        } catch (Exception e) {
-            Exceptions.propagateIfFatal(e);
+            Maybe<Bundle> bundle = Osgis.getBundle(framework, bundleUrl);
+            if (bundle.isPresent()) {
+                Class<T> clazz = (Class<T>) bundle.get().loadClass(type);
+                return Maybe.of(clazz);
+            } else {
+                return Maybe.absent("No bundle found in " + framework + " at URL: " + bundleUrl);
+            }
+        } catch (ClassNotFoundException e) {
             return Maybe.absent(e);
         }
     }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/30093bb4/core/src/main/java/brooklyn/util/osgi/Osgis.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/osgi/Osgis.java b/core/src/main/java/brooklyn/util/osgi/Osgis.java
index e6aff48..4c6e351 100644
--- a/core/src/main/java/brooklyn/util/osgi/Osgis.java
+++ b/core/src/main/java/brooklyn/util/osgi/Osgis.java
@@ -61,6 +61,7 @@ public class Osgis {
         if (parts.length == 2) {
             result = getBundle(framework, parts[0], parts[1]);
         } else if (parts.length == 1) {
+            // TODO: Select latest version rather than first result
             List<Bundle> matches = getBundlesByName(framework, symbolicNameOptionallyWithVersion);
             if (!matches.isEmpty()) {
                 result = Maybe.of(matches.iterator().next());


[30/45] git commit: Merge remote-tracking branch 'apache-git/master' into osgi

Posted by he...@apache.org.
Merge remote-tracking branch 'apache-git/master' into osgi


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

Branch: refs/heads/master
Commit: 492ccb7f8110b17a23e7befe32230b857a369cb0
Parents: 468d788 f28d9cc
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Jul 3 11:43:28 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu Jul 3 11:43:28 2014 +0100

----------------------------------------------------------------------
 api/src/main/java/brooklyn/entity/Entity.java   |  15 +-
 .../rebind/PersistenceExceptionHandler.java     |  32 +++
 .../brooklyn/entity/rebind/RebindContext.java   |   3 +-
 .../entity/rebind/RebindExceptionHandler.java   |  15 ++
 .../brooklyn/entity/rebind/RebindManager.java   |   2 +
 .../brooklyn/entity/rebind/RebindSupport.java   |   8 +-
 .../mementos/BrooklynMementoPersister.java      |   7 +-
 .../brooklyn/config/render/RendererHints.java   |  10 +
 .../brooklyn/entity/basic/AbstractEntity.java   |   9 +-
 .../entity/basic/AbstractGroupImpl.java         |   1 +
 .../brooklyn/entity/basic/DynamicGroup.java     |   5 +
 .../java/brooklyn/entity/basic/Entities.java    |   9 +
 .../brooklyn/entity/effector/Effectors.java     |   8 +-
 .../entity/group/QuarantineGroupImpl.java       |  15 +-
 .../rebind/BasicEnricherRebindSupport.java      |  13 +-
 .../entity/rebind/BasicEntityRebindSupport.java |  60 +++---
 .../rebind/BasicLocationRebindSupport.java      |  14 +-
 .../entity/rebind/BasicPolicyRebindSupport.java |  14 +-
 .../rebind/ImmediateDeltaChangeListener.java    |  22 ++-
 .../rebind/PeriodicDeltaChangeListener.java     |  24 +--
 .../rebind/PersistenceExceptionHandlerImpl.java | 102 ++++++++++
 .../entity/rebind/RebindContextImpl.java        |  21 +-
 .../rebind/RebindExceptionHandlerImpl.java      | 196 +++++++++++++++++--
 .../entity/rebind/RebindManagerImpl.java        | 103 ++++++++--
 .../AbstractBrooklynMementoPersister.java       |   5 +-
 .../BrooklynMementoPersisterInMemory.java       |  22 ++-
 .../BrooklynMementoPersisterToFile.java         |   9 +-
 .../BrooklynMementoPersisterToMultiFile.java    |  19 +-
 .../BrooklynMementoPersisterToObjectStore.java  |  54 ++---
 .../internal/BrooklynFeatureEnablement.java     |   8 +-
 .../management/internal/LocalEntityManager.java |  11 ++
 .../NonDeploymentManagementContext.java         |   6 +
 .../util/xstream/ImmutableListConverter.java    |  14 +-
 .../util/xstream/ImmutableMapConverter.java     |  38 ++++
 .../util/xstream/ImmutableSetConverter.java     |  36 ++++
 .../brooklyn/util/xstream/XmlSerializer.java    |   2 +
 .../brooklyn/entity/basic/DynamicGroupTest.java |  20 +-
 .../java/brooklyn/entity/group/GroupTest.java   | 105 ++++++++++
 .../entity/rebind/RebindFailuresTest.java       |  78 ++++++++
 .../brooklyn/entity/rebind/RebindGroupTest.java | 106 ++++++++++
 .../entity/rebind/RebindLocationTest.java       |   4 +-
 .../entity/rebind/RebindPolicyTest.java         |  55 ++++++
 .../entity/rebind/RebindTestFixture.java        |  31 +--
 .../brooklyn/entity/rebind/RebindTestUtils.java |   8 +-
 .../rebind/RecordingRebindExceptionHandler.java |   2 +-
 .../BrooklynMementoPersisterTestFixture.java    |   2 +-
 ...BrooklynMementoPersisterToMultiFileTest.java |   3 +-
 .../persister/XmlMementoSerializerTest.java     |  70 ++++++-
 .../HighAvailabilityManagerSplitBrainTest.java  |   3 +-
 .../ha/HighAvailabilityManagerTestFixture.java  |   3 +-
 .../AbstractWebAppFixtureIntegrationTest.java   |   5 +-
 .../brooklyn/launcher/BrooklynLauncher.java     |   5 +-
 52 files changed, 1231 insertions(+), 201 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/492ccb7f/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/492ccb7f/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
----------------------------------------------------------------------
diff --cc usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
index 9e8c01a,6cdcf04..7d94e9e
--- a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
+++ b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
@@@ -32,9 -32,10 +32,11 @@@ import brooklyn.entity.Application
  import brooklyn.entity.basic.ApplicationBuilder;
  import brooklyn.entity.basic.BrooklynShutdownHooks;
  import brooklyn.entity.basic.Entities;
 +import brooklyn.entity.basic.EntityInternal;
  import brooklyn.entity.basic.StartableApplication;
  import brooklyn.entity.proxying.EntitySpec;
+ import brooklyn.entity.rebind.PersistenceExceptionHandler;
+ import brooklyn.entity.rebind.PersistenceExceptionHandlerImpl;
  import brooklyn.entity.rebind.RebindManager;
  import brooklyn.entity.rebind.RebindManagerImpl;
  import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;


[32/45] git commit: support more catalog type info and yaml via REST API, and make getPlanYaml available (nullable) on CatalogItem API; starting to fix CatalogResourceTest of POSTing a YAML

Posted by he...@apache.org.
support more catalog type info and yaml via REST API, and make getPlanYaml available (nullable) on CatalogItem API;
starting to fix CatalogResourceTest of POSTing a YAML


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

Branch: refs/heads/master
Commit: d4d17b720f6a27086615131720e0f4080d6abbec
Parents: f99fb58
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Jul 3 14:39:45 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu Jul 3 14:39:45 2014 +0100

----------------------------------------------------------------------
 .../main/java/brooklyn/catalog/CatalogItem.java |  5 ++--
 .../catalog/internal/BasicBrooklynCatalog.java  |  2 +-
 .../catalog/internal/CatalogEntityItemDto.java  |  6 -----
 .../catalog/internal/CatalogItemDo.java         | 13 ++++-----
 .../internal/CatalogItemDtoAbstract.java        |  7 +++++
 .../rest/domain/CatalogEntitySummary.java       |  5 +++-
 .../rest/domain/CatalogItemSummary.java         | 28 ++++++++++++++++++--
 .../rest/domain/CatalogPolicySummary.java       |  2 +-
 .../rest/transform/CatalogTransformer.java      | 14 +++++++---
 .../rest/resources/CatalogResourceTest.java     | 25 ++++++++++-------
 10 files changed, 72 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d4d17b72/api/src/main/java/brooklyn/catalog/CatalogItem.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/catalog/CatalogItem.java b/api/src/main/java/brooklyn/catalog/CatalogItem.java
index 276eba4..7cfbdd6 100644
--- a/api/src/main/java/brooklyn/catalog/CatalogItem.java
+++ b/api/src/main/java/brooklyn/catalog/CatalogItem.java
@@ -36,12 +36,13 @@ public interface CatalogItem<T,SpecT> {
     public String getIconUrl();
     public String getVersion();
 
-    // FIXME many of the static methods in CatalogItemAbstractDto which create CatalogItems set this as null
-    // I (alex) suggest removing the annotation, here, and in subclasses where the method is defined
     @Nonnull
     public CatalogItemLibraries getLibraries();
 
     public String toXmlString();
+    
+    /** return underlying YAML for this item, if known */ 
+    @Nullable public String getPlanYaml();
 
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d4d17b72/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 6a4f3d2..f924869 100644
--- a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
@@ -110,7 +110,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         Class<SpecT> specType = loadedItem.getSpecType();
         if (specType==null) return null;
             
-        String yaml = loadedItem.getYaml();
+        String yaml = loadedItem.getPlanYaml();
         SpecT spec = null;
             
         if (yaml!=null) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d4d17b72/core/src/main/java/brooklyn/catalog/internal/CatalogEntityItemDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogEntityItemDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogEntityItemDto.java
index 60d6fbe..e130052 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogEntityItemDto.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogEntityItemDto.java
@@ -6,8 +6,6 @@ import brooklyn.entity.proxying.EntitySpec;
 
 public class CatalogEntityItemDto extends CatalogItemDtoAbstract<Entity,EntitySpec<?>> {
     
-    String planYaml;
-
     @Override
     public CatalogItemType getCatalogItemType() {
         return CatalogItemType.ENTITY;
@@ -24,8 +22,4 @@ public class CatalogEntityItemDto extends CatalogItemDtoAbstract<Entity,EntitySp
         return (Class)EntitySpec.class;
     }
 
-    public String getPlanYaml() {
-        return planYaml;
-    }
-    
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d4d17b72/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
index 200db52..d1d8d82 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
@@ -75,14 +75,6 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT> {
         return itemDto.getLibraries();
     }
 
-    @Nullable
-    public String getYaml() {
-        if (itemDto instanceof CatalogEntityItemDto) {
-            return ((CatalogEntityItemDto)itemDto).getPlanYaml();
-        }
-        return null;
-    }
-    
     /** @deprecated since 0.7.0 this is the legacy mechanism; still needed for policies and apps, but being phased out.
      * new items should use {@link #getYaml()} */
     @Deprecated
@@ -117,5 +109,10 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT> {
     public Class<SpecT> getSpecType() {
         return itemDto.getSpecType();
     }
+
+    @Nullable @Override
+    public String getPlanYaml() {
+        return itemDto.getPlanYaml();
+    }
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d4d17b72/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
index 4957474..b9b633d 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
@@ -19,6 +19,8 @@ public abstract class CatalogItemDtoAbstract<T,SpecT> implements CatalogItem<T,S
     String version;
     CatalogLibrariesDto libraries;
     
+    String planYaml;
+    
     /** @deprecated since 0.7.0.
      * used for backwards compatibility when deserializing.
      * when catalogs are converted to new yaml format, this can be removed. */
@@ -68,6 +70,11 @@ public abstract class CatalogItemDtoAbstract<T,SpecT> implements CatalogItem<T,S
         return libraries;
     }
 
+    @Override
+    public String getPlanYaml() {
+        return planYaml;
+    }
+
     public static CatalogTemplateItemDto newTemplateFromJava(String javaType, String name) {
         return newTemplateFromJava(null, javaType, name, null);
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d4d17b72/usage/rest-api/src/main/java/brooklyn/rest/domain/CatalogEntitySummary.java
----------------------------------------------------------------------
diff --git a/usage/rest-api/src/main/java/brooklyn/rest/domain/CatalogEntitySummary.java b/usage/rest-api/src/main/java/brooklyn/rest/domain/CatalogEntitySummary.java
index ce8b73b..679064b 100644
--- a/usage/rest-api/src/main/java/brooklyn/rest/domain/CatalogEntitySummary.java
+++ b/usage/rest-api/src/main/java/brooklyn/rest/domain/CatalogEntitySummary.java
@@ -15,7 +15,10 @@ public class CatalogEntitySummary extends CatalogItemSummary {
     public CatalogEntitySummary(
             @JsonProperty("id") String id,
             @JsonProperty("name") String name,
+            @JsonProperty("registeredType") String registeredType,
+            @JsonProperty("javaType") String javaType,
             @JsonProperty("type") String type,
+            @JsonProperty("planYaml") String planYaml,
             @JsonProperty("description") String description,
             @JsonProperty("iconUrl") String iconUrl,
             @JsonProperty("config") Set<EntityConfigSummary> config, 
@@ -23,7 +26,7 @@ public class CatalogEntitySummary extends CatalogItemSummary {
             @JsonProperty("effectors") Set<EffectorSummary> effectors,
             @JsonProperty("links") Map<String, URI> links
         ) {
-        super(id, name, type, description, iconUrl, links);
+        super(id, name, registeredType, javaType, type, planYaml, description, iconUrl, links);
         this.config = config;
         this.sensors = sensors;
         this.effectors = effectors;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d4d17b72/usage/rest-api/src/main/java/brooklyn/rest/domain/CatalogItemSummary.java
----------------------------------------------------------------------
diff --git a/usage/rest-api/src/main/java/brooklyn/rest/domain/CatalogItemSummary.java b/usage/rest-api/src/main/java/brooklyn/rest/domain/CatalogItemSummary.java
index 34d87ac..fb66d7f 100644
--- a/usage/rest-api/src/main/java/brooklyn/rest/domain/CatalogItemSummary.java
+++ b/usage/rest-api/src/main/java/brooklyn/rest/domain/CatalogItemSummary.java
@@ -16,26 +16,38 @@ import com.google.common.collect.ImmutableMap;
 public class CatalogItemSummary {
 
     private final String id;
+    
+    // TODO too many types, see in CatalogItem
     private final String type;
+    private final String javaType;
+    private final String registeredType;
+    
     private final String name;
     @JsonSerialize(include=Inclusion.NON_EMPTY)
     private final String description;
     @JsonSerialize(include=Inclusion.NON_EMPTY)
     private final String iconUrl;
+    private final String planYaml;
     
     private final Map<String, URI> links;
 
     public CatalogItemSummary(
             @JsonProperty("id") String id,
             @JsonProperty("name") String name,
-            @JsonProperty("type") String type,
+            @JsonProperty("registeredType") String registeredType,
+            @JsonProperty("javaType") String javaType,
+            @JsonProperty("type") String highLevelType,
+            @JsonProperty("planYaml") String planYaml,
             @JsonProperty("description") String description,
             @JsonProperty("iconUrl") String iconUrl,
             @JsonProperty("links") Map<String, URI> links
         ) {
         this.id = id;
         this.name = name;
-        this.type = type;
+        this.javaType = javaType;
+        this.registeredType = registeredType;
+        this.type = highLevelType;
+        this.planYaml = planYaml;
         this.description = description;
         this.iconUrl = iconUrl;
         this.links = ImmutableMap.copyOf(links);
@@ -49,6 +61,18 @@ public class CatalogItemSummary {
         return type;
     }
 
+    public String getJavaType() {
+        return javaType;
+    }
+
+    public String getRegisteredType() {
+        return registeredType;
+    }
+
+    public String getPlanYaml() {
+        return planYaml;
+    }
+    
     public String getName() {
         return name;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d4d17b72/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 8f74dce..43ee8f5 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
@@ -19,7 +19,7 @@ public class CatalogPolicySummary extends CatalogItemSummary {
             @JsonProperty("config") Set<PolicyConfigSummary> config,
             @JsonProperty("links") Map<String, URI> links
         ) {
-        super(id, name, type, description, iconUrl, links);
+        super(id, name, type, type, type, null, description, iconUrl, links);
         // TODO expose config from policies
         this.config = config;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d4d17b72/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 8b05bd9..4d24974 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
@@ -36,8 +36,8 @@ public class CatalogTransformer {
     private static final org.slf4j.Logger log = LoggerFactory.getLogger(CatalogTransformer.class);
     
     public static CatalogEntitySummary catalogEntitySummary(BrooklynRestResourceUtils b, CatalogItem<? extends Entity,EntitySpec<?>> item) {
-        Class<? extends Entity> clazz = b.getCatalog().loadClass(item);
-        EntityDynamicType typeMap = EntityTypes.getDefinedEntityType(clazz);
+        EntitySpec<?> spec = b.getCatalog().createSpec(item);
+        EntityDynamicType typeMap = EntityTypes.getDefinedEntityType(spec.getType());
         EntityType type = typeMap.getSnapshot();
 
         Set<EntityConfigSummary> config = Sets.newLinkedHashSet();
@@ -48,14 +48,20 @@ public class CatalogTransformer {
         for (Sensor<?> x: type.getSensors()) sensors.add(SensorTransformer.sensorSummaryForCatalog(x));
         for (Effector<?> x: type.getEffectors()) effectors.add(EffectorTransformer.effectorSummaryForCatalog(x));
 
-        return new CatalogEntitySummary(item.getId(), item.getName(), item.getJavaType(),
+        return new CatalogEntitySummary(item.getId(), item.getName(), 
+            item.getRegisteredTypeName(), item.getJavaType(), 
+            item.getRegisteredTypeName()!=null ? item.getRegisteredTypeName() : item.getJavaType(),
+            item.getPlanYaml(),
                 item.getDescription(), tidyIconLink(b, item, item.getIconUrl()),
                 config, sensors, effectors,
                 makeLinks(item));
     }
 
     public static CatalogItemSummary catalogItemSummary(BrooklynRestResourceUtils b, CatalogItem<?,?> item) {
-        return new CatalogItemSummary(item.getId(), item.getName(), item.getJavaType(),
+        return new CatalogItemSummary(item.getId(), item.getName(), 
+                item.getRegisteredTypeName(), item.getJavaType(), 
+                item.getRegisteredTypeName()!=null ? item.getRegisteredTypeName() : item.getJavaType(),
+                item.getPlanYaml(),
                 item.getDescription(), tidyIconLink(b, item, item.getIconUrl()), makeLinks(item));
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d4d17b72/usage/rest-server/src/test/java/brooklyn/rest/resources/CatalogResourceTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/brooklyn/rest/resources/CatalogResourceTest.java b/usage/rest-server/src/test/java/brooklyn/rest/resources/CatalogResourceTest.java
index 2a25dfd..810e6e3 100644
--- a/usage/rest-server/src/test/java/brooklyn/rest/resources/CatalogResourceTest.java
+++ b/usage/rest-server/src/test/java/brooklyn/rest/resources/CatalogResourceTest.java
@@ -44,17 +44,20 @@ public class CatalogResourceTest extends BrooklynRestResourceTest {
     addResource(new CatalogResource());
   }
 
-  @Test(enabled=false, groups="WIP") // FIXME broken until BasicBrooklynCatalog can parse the yaml
+  @Test(enabled=false, groups="WIP")
   public void testRegisterCustomEntity() {
+    String registeredTypeName = "my.catalog.app.id";
     String yaml =
+        "name: "+registeredTypeName+"\n"+
+        // TODO name above should be unnecessary when brooklyn.catalog below is working
         "brooklyn.catalog:\n"+
-        "- id: my.catalog.app.id\n"+
+        "- id: " + registeredTypeName + "\n"+
         "- name: My Catalog App\n"+
         "- description: My description\n"+
         "- icon_url: classpath://path/to/myicon.jpg\n"+
         "- version: 0.1.2\n"+
-        "- bundles:\n"+
-        "- url: http://myurl/my.jar\n"+
+        "- brooklyn.libraries:\n"+
+        "  - url: http://myurl/my.jar\n"+
         "\n"+
         "services:\n"+
         "- type: brooklyn.test.entity.TestEntity\n";
@@ -64,13 +67,15 @@ public class CatalogResourceTest extends BrooklynRestResourceTest {
 
     assertEquals(response.getStatus(), Response.Status.CREATED.getStatusCode());
 
-    CatalogEntitySummary entityItem = client().resource("/v1/catalog/entities/my.catalog.app.id")
+    CatalogEntitySummary entityItem = client().resource("/v1/catalog/entities/"+registeredTypeName)
             .get(CatalogEntitySummary.class);
-    assertEquals(entityItem.getId(), "my.catalog.app.id");
-    assertEquals(entityItem.getName(), "My Catalog App");
-    assertEquals(entityItem.getDescription(), "My description");
-    assertEquals(entityItem.getIconUrl(), "classpath://path/to/myicon.jpg");
-    assertEquals(entityItem.getType(), "brooklyn.test.entity.TestEntity");
+    // TODO more checks, when  brooklyn.catalog  working
+//    assertEquals(entityItem.getId(), registeredTypeName);
+//    assertEquals(entityItem.getName(), "My Catalog App");
+//    assertEquals(entityItem.getDescription(), "My description");
+//    assertEquals(entityItem.getIconUrl(), "classpath://path/to/myicon.jpg");
+    assertEquals(entityItem.getRegisteredType(), registeredTypeName);
+    assertEquals(entityItem.getJavaType(), "brooklyn.test.entity.TestEntity");
   }
 
   @Test


[31/45] git commit: Create the wrapper app before building the children.

Posted by he...@apache.org.
Create the wrapper app before building the children.

Reorganize the code so that the wrapper app is created (if necessary) before initializing the template so that nested entity creation doesn't throw exceptions. The existence of the root app is mandatory.
The main change is the check whether the single serviceType is an application (see isSingleApp) before having it instantiated.

Conflicts:
	usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java

Adding back in the one extra applyLocation which was needed.


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

Branch: refs/heads/master
Commit: f99fb581657840e1761402d073074f4968d3c0b1
Parents: 492ccb7
Author: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Authored: Thu Jul 3 13:53:46 2014 +0300
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu Jul 3 12:19:14 2014 +0100

----------------------------------------------------------------------
 .../BrooklynAssemblyTemplateInstantiator.java   | 152 ++++++++++++-------
 1 file changed, 99 insertions(+), 53 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f99fb581/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 fbdd5ec..cc9dd44 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
@@ -216,52 +216,121 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
         }
     }
     
-    @SuppressWarnings("unchecked")
     protected Application createApplicationFromNonCatalogCampTemplate(AssemblyTemplate template, CampPlatform platform) {
         // AssemblyTemplates created via PDP, _specifying_ then entities to put in
         final ManagementContext mgmt = getBrooklynManagementContext(platform);
 
-        Map<Entity, EntitySpec<?>> rootEntities = Maps.newLinkedHashMap();
         Map<Entity, EntitySpec<?>> allEntities = Maps.newLinkedHashMap();
-        /* FIXME there is a subtlety here, and tests failing;
-         * OT1H we might not want/need the wrapper application if we are creating a single one,   
-         * but OTOH we might need a guarantee of an app at root, if we are creating certain nested entities
-         * 
-         * i (alex) think the solution is to use the new createSpec(...) and interrogate it
-         * to see if we need the wrapper or not
-         */
-        buildEntities(template, rootEntities, allEntities, mgmt);
-        
-        EntitySpec<StartableApplication> appSpec;
-        StartableApplication app;
-        if(shouldWrapInApp(template, rootEntities)) {
-            BrooklynComponentTemplateResolver appResolver = BrooklynComponentTemplateResolver.Factory.newInstance(mgmt, template);
-            appSpec = appResolver.resolveSpec(StartableApplication.class, BasicApplicationImpl.class);
-            app = appResolver.newEntity(appSpec);
-            setEntitiesParent(rootEntities, app);
-            allEntities.put(app, appSpec);
+//<<<<<<< HEAD
+//        /* FIXME there is a subtlety here, and tests failing;
+//         * OT1H we might not want/need the wrapper application if we are creating a single one,   
+//         * but OTOH we might need a guarantee of an app at root, if we are creating certain nested entities
+//         * 
+//         * i (alex) think the solution is to use the new createSpec(...) and interrogate it
+//         * to see if we need the wrapper or not
+//         */
+//        buildEntities(template, rootEntities, allEntities, mgmt);
+//        
+//        EntitySpec<StartableApplication> appSpec;
+//        StartableApplication app;
+//        if(shouldWrapInApp(template, rootEntities)) {
+//            BrooklynComponentTemplateResolver appResolver = BrooklynComponentTemplateResolver.Factory.newInstance(mgmt, template);
+//            appSpec = appResolver.resolveSpec(StartableApplication.class, BasicApplicationImpl.class);
+//            app = appResolver.newEntity(appSpec);
+//            setEntitiesParent(rootEntities, app);
+//            allEntities.put(app, appSpec);
+//        } else {
+//            Entry<Entity, EntitySpec<?>> entry = rootEntities.entrySet().iterator().next();
+//            app = (StartableApplication)entry.getKey();
+//            appSpec = (EntitySpec<StartableApplication>)entry.getValue();
+//            applyLocations(mgmt, template, app);
+//=======
+        StartableApplication rootApp = buildRootApp(template, platform, allEntities);
+        initEntities(mgmt, allEntities);
+        log.info("CAMP placing '{}' under management", allEntities.get(rootApp));
+        Entities.startManagement(rootApp, mgmt);
+        return rootApp;
+    }
+
+    private StartableApplication buildRootApp(AssemblyTemplate template, CampPlatform platform, Map<Entity, EntitySpec<?>> allEntities) {
+        if (shouldWrapInApp(template, platform)) {
+            return buildWrappedApp(template, platform, allEntities);
         } else {
-            Entry<Entity, EntitySpec<?>> entry = rootEntities.entrySet().iterator().next();
-            app = (StartableApplication)entry.getKey();
-            appSpec = (EntitySpec<StartableApplication>)entry.getValue();
-            applyLocations(mgmt, template, app);
+            return buildPromotedApp(template, platform, allEntities);
         }
+    }
+
+    private StartableApplication buildWrappedApp(AssemblyTemplate template, CampPlatform platform, Map<Entity, EntitySpec<?>> allEntities) {
+        final ManagementContext mgmt = getBrooklynManagementContext(platform);
         
-        initEntities(mgmt, allEntities);
+        BrooklynComponentTemplateResolver appResolver = BrooklynComponentTemplateResolver.Factory.newInstance(mgmt, template);
+        EntitySpec<StartableApplication> wrapAppSpec = appResolver.resolveSpec(StartableApplication.class, BasicApplicationImpl.class);
+        StartableApplication wrapApp = appResolver.newEntity(wrapAppSpec);
+        allEntities.put(wrapApp, wrapAppSpec);
+        
+        buildEntities(template, wrapApp, wrapAppSpec, allEntities, mgmt);
         
-        log.info("CAMP placing '{}' under`` management", appSpec);
-        Entities.startManagement(app, mgmt);
+        return wrapApp;
+    }
 
+    private StartableApplication buildPromotedApp(AssemblyTemplate template, CampPlatform platform, Map<Entity, EntitySpec<?>> allEntities) {
+        final ManagementContext mgmt = getBrooklynManagementContext(platform);
+        
+        ResolvableLink<PlatformComponentTemplate> promotedAppTemplate = template.getPlatformComponentTemplates().links().get(0);
+        StartableApplication app = (StartableApplication)buildEntity(null, promotedAppTemplate, allEntities, mgmt);
+        
+        // TODO i (alex) think we need this because locations defined at the root of the template could have been lost otherwise?
+        applyLocations(mgmt, template, app);
+        
         return app;
     }
 
-    private void setEntitiesParent(Map<Entity, EntitySpec<?>> entities, Application parentApp) {
-        for(Entry<Entity, EntitySpec<?>> entry : entities.entrySet()) {
-            entry.getValue().parent(parentApp);
-            entry.getKey().setParent(parentApp);
+    private void buildEntities(AssemblyTemplate template, StartableApplication app, EntitySpec<StartableApplication> appSpec,
+            Map<Entity, EntitySpec<?>> allEntities, ManagementContext mgmt) {
+        for (ResolvableLink<PlatformComponentTemplate> ctl: template.getPlatformComponentTemplates().links()) {
+            buildEntity(app, ctl, allEntities, mgmt);
         }
     }
 
+    private Entity buildEntity(StartableApplication parent, ResolvableLink<PlatformComponentTemplate> ctl,
+            Map<Entity, EntitySpec<?>> allEntities, ManagementContext mgmt) {
+        PlatformComponentTemplate appChildComponentTemplate = ctl.resolve();
+        BrooklynComponentTemplateResolver entityResolver = BrooklynComponentTemplateResolver.Factory.newInstance(mgmt, appChildComponentTemplate);
+        EntitySpec<? extends Entity> spec = entityResolver.resolveSpec();
+        if(parent != null) {
+            spec.parent(parent);
+        }
+        Entity entity = entityResolver.newEntity(spec);
+        allEntities.put(entity, spec);
+        buildEntityHierarchy(mgmt, allEntities, entity, entityResolver.getChildren(appChildComponentTemplate.getCustomAttributes()));
+        return entity;
+    }
+
+    private boolean shouldWrapInApp(AssemblyTemplate template, CampPlatform platform) {
+        return isWrapAppRequested(template) ||
+                !isSingleApp(template, platform);
+    }
+
+    private boolean isWrapAppRequested(AssemblyTemplate template) {
+        return Boolean.TRUE.equals(template.getCustomAttributes().get("wrappedApp"));
+    }
+
+    protected boolean isSingleApp(AssemblyTemplate template, CampPlatform platform) {
+        // AssemblyTemplates created via PDP, _specifying_ then entities to put in
+        final ManagementContext mgmt = getBrooklynManagementContext(platform);
+
+        List<ResolvableLink<PlatformComponentTemplate>> pct = template.getPlatformComponentTemplates().links();
+        if(pct.size() == 1) {
+            ResolvableLink<PlatformComponentTemplate> res = pct.get(0);
+            PlatformComponentTemplate templ = res.resolve();
+            Class<Entity> entity = BrooklynComponentTemplateResolver.Factory.newInstance(mgmt, templ).loadEntityClass();
+            if(StartableApplication.class.isAssignableFrom(entity)) {
+                return true;
+            }
+        }
+        return false;
+    }
+    
     private void initEntities(final ManagementContext mgmt, Map<Entity, EntitySpec<?>> entities) {
         for (Entry<Entity, EntitySpec<?>> entry : entities.entrySet()) {
             final Entity entity = entry.getKey();
@@ -278,29 +347,6 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
         }
     }
 
-    private boolean shouldWrapInApp(AssemblyTemplate template, Map<Entity, EntitySpec<?>> rootEntities) {
-        return isWrapAppRequested(template) ||
-                rootEntities.size() != 1 ||
-                !(rootEntities.keySet().iterator().next() instanceof StartableApplication);
-    }
-
-    private boolean isWrapAppRequested(AssemblyTemplate template) {
-        return Boolean.TRUE.equals(template.getCustomAttributes().get("wrappedApp"));
-    }
-
-    private void buildEntities(AssemblyTemplate template, Map<Entity, EntitySpec<?>> parentEntities, 
-            Map<Entity, EntitySpec<?>> allEntities, ManagementContext mgmt) {
-        for (ResolvableLink<PlatformComponentTemplate> ctl: template.getPlatformComponentTemplates().links()) {
-            PlatformComponentTemplate appChildComponentTemplate = ctl.resolve();
-            BrooklynComponentTemplateResolver entityResolver = BrooklynComponentTemplateResolver.Factory.newInstance(mgmt, appChildComponentTemplate);
-            EntitySpec<? extends Entity> spec = entityResolver.resolveSpec();
-            Entity entity = entityResolver.newEntity(spec);
-            parentEntities.put(entity, spec);
-            allEntities.put(entity, spec);
-            buildEntityHierarchy(mgmt, allEntities, entity, entityResolver.getChildren(appChildComponentTemplate.getCustomAttributes()));
-        }
-    }
-
     protected <T extends Entity> void initEntity(ManagementContext mgmt, T entity, EntitySpec<T> spec) {
         InternalEntityFactory entityFactory = ((ManagementContextInternal)mgmt).getEntityFactory();
         entityFactory.initEntity(entity, spec);


[17/45] git commit: Merge pull request #1 from aledsage/sjcorbett/yaml-context

Posted by he...@apache.org.
Merge pull request #1 from aledsage/sjcorbett/yaml-context

REST api for adding catalog item using yaml

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

Branch: refs/heads/master
Commit: acd41f71769cd94a10dffd78e902e042c35186c2
Parents: 30093bb b3d2c03
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Tue Jul 1 14:29:18 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Tue Jul 1 14:29:18 2014 +0100

----------------------------------------------------------------------
 .../java/brooklyn/catalog/BrooklynCatalog.java  |  8 ++++
 .../catalog/internal/BasicBrooklynCatalog.java  | 15 +++++++
 .../main/java/brooklyn/rest/api/CatalogApi.java | 14 +++----
 .../rest/resources/CatalogResource.java         | 26 ++++++++++--
 .../rest/util/BrooklynRestResourceUtils.java    |  3 +-
 .../rest/util/DefaultExceptionMapper.java       |  2 +-
 .../rest/resources/CatalogResourceTest.java     | 43 ++++++++++----------
 7 files changed, 77 insertions(+), 34 deletions(-)
----------------------------------------------------------------------



[03/45] import of brooklyncentral/camp-server dependency to apache brooklyn project

Posted by he...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/resolve/PdpProcessor.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/resolve/PdpProcessor.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/resolve/PdpProcessor.java
new file mode 100644
index 0000000..e307ee0
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/resolve/PdpProcessor.java
@@ -0,0 +1,154 @@
+package io.brooklyn.camp.spi.resolve;
+
+import io.brooklyn.camp.CampPlatform;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+import io.brooklyn.camp.spi.instantiate.BasicAssemblyTemplateInstantiator;
+import io.brooklyn.camp.spi.pdp.Artifact;
+import io.brooklyn.camp.spi.pdp.AssemblyTemplateConstructor;
+import io.brooklyn.camp.spi.pdp.DeploymentPlan;
+import io.brooklyn.camp.spi.pdp.Service;
+import io.brooklyn.camp.spi.resolve.interpret.PlanInterpretationContext;
+import io.brooklyn.camp.spi.resolve.interpret.PlanInterpretationNode;
+import io.brooklyn.util.yaml.Yamls;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.compress.archivers.ArchiveEntry;
+import org.apache.commons.compress.archivers.ArchiveInputStream;
+import org.apache.commons.compress.archivers.ArchiveStreamFactory;
+import org.yaml.snakeyaml.error.YAMLException;
+
+import brooklyn.util.exceptions.Exceptions;
+
+import com.google.common.annotations.VisibleForTesting;
+
+public class PdpProcessor {
+
+    final CampPlatform campPlatform;
+    
+    final List<PdpMatcher> matchers = new ArrayList<PdpMatcher>();
+    final List<PlanInterpreter> interpreters = new ArrayList<PlanInterpreter>();
+    
+    public PdpProcessor(CampPlatform campPlatform) {
+        this.campPlatform = campPlatform;
+    }
+
+    @SuppressWarnings("unchecked")
+    public DeploymentPlan parseDeploymentPlan(Reader yaml) {
+        Iterable<Object> template = Yamls.parseAll(yaml);
+        
+        Map<String, Object> dpRootUninterpreted = null;
+        try {
+            dpRootUninterpreted = Yamls.getAs(template, Map.class);
+        } catch (Exception e) {
+            Exceptions.propagateIfFatal(e);
+            throw new YAMLException("Plan not in acceptable format: "+(e.getMessage()!=null ? e.getMessage() : ""+e), e);
+        }
+        Map<String, Object> dpRootInterpreted = applyInterpreters(dpRootUninterpreted);
+        
+		return DeploymentPlan.of( dpRootInterpreted );
+    }
+    
+    /** create and return an AssemblyTemplate based on the given DP (yaml) */
+    public AssemblyTemplate registerDeploymentPlan(Reader yaml) {
+        DeploymentPlan plan = parseDeploymentPlan(yaml);
+        return registerDeploymentPlan(plan);
+    }
+
+    /** applies matchers to the given deployment plan to create an assembly template */
+    public AssemblyTemplate registerDeploymentPlan(DeploymentPlan plan) {
+        AssemblyTemplateConstructor atc = new AssemblyTemplateConstructor(campPlatform);
+        
+        if (plan.getName()!=null) atc.name(plan.getName());
+        if (plan.getDescription()!=null) atc.description(plan.getDescription());
+        // nothing done with origin just now...
+        
+        if (plan.getServices()!=null) {
+            for (Service svc: plan.getServices()) {
+                applyMatchers(svc, atc);
+            }
+        }
+
+        if (plan.getArtifacts()!=null) {
+            for (Artifact art: plan.getArtifacts()) {
+                applyMatchers(art, atc);
+            }
+        }
+
+        Map<String, Object> attrs = plan.getCustomAttributes();
+        if (attrs!=null && !attrs.isEmpty())
+            atc.addCustomAttributes(attrs);
+        
+        if (atc.getInstantiator()==null)
+            // set a default instantiator which just invokes the component's instantiators
+            // (or throws unsupported exceptions, currently!)
+            atc.instantiator(BasicAssemblyTemplateInstantiator.class);
+
+        return atc.commit();
+    }
+    
+    public AssemblyTemplate registerPdpFromArchive(InputStream archiveInput) {
+        try {
+            ArchiveInputStream input = new ArchiveStreamFactory()
+                .createArchiveInputStream(archiveInput);
+            
+            while (true) {
+                ArchiveEntry entry = input.getNextEntry();
+                if (entry==null) break;
+                // TODO unpack entry, create a space on disk holding the archive ?
+            }
+
+            // use yaml...
+            throw new UnsupportedOperationException("in progress");
+            
+        } catch (Exception e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+
+
+    // ----------------------------
+    
+    public void addMatcher(PdpMatcher m) {
+        // TODO a list is a crude way to do matching ... but good enough to start
+        matchers.add(m);
+    }
+
+    public List<PdpMatcher> getMatchers() {
+        return matchers;
+    }
+
+
+    protected void applyMatchers(Object deploymentPlanItem, AssemblyTemplateConstructor atc) {
+        for (PdpMatcher matcher: getMatchers()) {
+            if (matcher.accepts(deploymentPlanItem)) {
+                // TODO first accepting is a crude way to do matching ... but good enough to start
+                if (matcher.apply(deploymentPlanItem, atc))
+                    return;
+            }
+        }
+        throw new UnsupportedOperationException("Deployment plan item "+deploymentPlanItem+" cannot be matched");
+    }
+
+    // ----------------------------
+
+    public void addInterpreter(PlanInterpreter interpreter) {
+    	interpreters.add(interpreter);
+    }
+    
+    /** returns a DeploymentPlan object which is the result of running the interpretation
+     * (with all interpreters) against the supplied deployment plan YAML object,
+     * essentially a post-parse processing step before matching */
+    @SuppressWarnings("unchecked")
+    @VisibleForTesting
+	public Map<String, Object> applyInterpreters(Map<String, Object> originalDeploymentPlan) {
+    	PlanInterpretationNode interpretation = new PlanInterpretationNode(
+    			new PlanInterpretationContext(originalDeploymentPlan, interpreters));
+		return (Map<String, Object>) interpretation.getNewValue();
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/resolve/PlanInterpreter.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/resolve/PlanInterpreter.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/resolve/PlanInterpreter.java
new file mode 100644
index 0000000..4758369
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/resolve/PlanInterpreter.java
@@ -0,0 +1,95 @@
+package io.brooklyn.camp.spi.resolve;
+
+import io.brooklyn.camp.spi.resolve.interpret.PlanInterpretationNode;
+
+import java.util.List;
+import java.util.Map;
+
+/** Interpreters modify the deployment plan, in a depth-first evaluation,
+ * typically by looking for items which begin with "$namespace:"
+ * <p>
+ * Most common usages simple need to supply {@link #applyYamlPrimitive(PlanInterpretationNode)} which can invoke
+ * {@link PlanInterpretationNode#setNewValue(Object)} to change.
+ * The {@link PlanInterpreterAdapter} makes this easy by supplying all methods but that.
+ * <p>
+ * For more sophisticated usages, to act on entire maps or lists,
+ * there are a number of other hook functions, described below.
+ *  */
+public interface PlanInterpreter {
+
+    /** guard to prevent any apply calls when an Interpreter is not interested in a node */
+    boolean isInterestedIn(PlanInterpretationNode node);
+    
+    /** provides an opportunity for an interpreter to change the value at a node,
+     * using {@link PlanInterpretationNode#get()} and {@link PlanInterpretationNode#setNewValue(Object)} */
+    void applyYamlPrimitive(PlanInterpretationNode node);
+
+    /** invoked at a Map node in a YAML tree, before any conversion to mapOut.
+     * mapIn is initially a copy of {@link PlanInterpretationNode#get()}, but it is mutable,
+     * and any mutations are passed to subsequent interpreters and used for recursion.
+     * <p>
+     * the return value indicates whether to recurse into the item.
+     * if any interpreters return false, the node is not recursed. 
+     * (callers may use {@link PlanInterpretationNode#setNewValue(Object)} to set a custom return value.) */
+    boolean applyMapBefore(PlanInterpretationNode node, Map<Object, Object> mapIn);
+
+    /** invoked at a Map node in a YAML tree, after {@link #applyMapBefore(PlanInterpretationNode, Map)},
+     * and after recursing into the value and then key arguments supplied here,
+     * but before inserting it into the mapOut for this node. 
+     * <p>
+     * the return value indicates whether to add this key-value to the mapOut.
+     * if any interpreters return false, the entry is not added. 
+     * (callers may modify mapOut to add/change values, or may modify key/value directly.) */
+    boolean applyMapEntry(PlanInterpretationNode node, Map<Object, Object> mapIn, Map<Object, Object> mapOut,
+                            PlanInterpretationNode key, PlanInterpretationNode value);
+
+    /** invoked at a Map node in a YAML tree, after all entries have been passed to all interpreters' 
+     * {@link #applyMapEntry(PlanInterpretationNode, Map, Map, PlanInterpretationNode, PlanInterpretationNode)}.
+     * mapOut can be modified yet further. */
+    void applyMapAfter(PlanInterpretationNode node, Map<Object, Object> mapIn, Map<Object, Object> mapOut);
+
+    /** as {@link #applyMapBefore(PlanInterpretationNode, Map)} but for lists */
+    boolean applyListBefore(PlanInterpretationNode node, List<Object> listIn);
+
+    /** as {@link #applyMapEntry(PlanInterpretationNode, Map, Map, PlanInterpretationNode, PlanInterpretationNode) but for lists */
+    boolean applyListEntry(PlanInterpretationNode node, List<Object> listIn, List<Object> listOut,
+                            PlanInterpretationNode value);
+
+    /** as {@link #applyMapAfter(PlanInterpretationNode, Map, Map)} but for lists  */
+    void applyListAfter(PlanInterpretationNode node, List<Object> listIn, List<Object> listOut);
+
+    
+    public abstract static class PlanInterpreterAdapter implements PlanInterpreter {
+
+        @Override
+        public boolean applyMapBefore(PlanInterpretationNode node, Map<Object, Object> mapIn) {
+            return true;
+        }
+
+        @Override
+        public boolean applyMapEntry(PlanInterpretationNode node, Map<Object, Object> mapIn, Map<Object, Object> mapOut,
+                                PlanInterpretationNode key, PlanInterpretationNode value) {
+            return true;
+        }
+
+        @Override
+        public void applyMapAfter(PlanInterpretationNode node, Map<Object, Object> mapIn, Map<Object, Object> mapOut) {
+        }
+
+        @Override
+        public boolean applyListBefore(PlanInterpretationNode node, List<Object> listIn) {
+            return true;
+        }
+
+        @Override
+        public boolean applyListEntry(PlanInterpretationNode node, List<Object> listIn, List<Object> listOut,
+                                PlanInterpretationNode value) {
+            return true;
+        }
+
+        @Override
+        public void applyListAfter(PlanInterpretationNode node, List<Object> listIn, List<Object> listOut) {
+        }
+        
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/resolve/interpret/PlanInterpretationContext.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/resolve/interpret/PlanInterpretationContext.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/resolve/interpret/PlanInterpretationContext.java
new file mode 100644
index 0000000..cc63e75
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/resolve/interpret/PlanInterpretationContext.java
@@ -0,0 +1,134 @@
+package io.brooklyn.camp.spi.resolve.interpret;
+
+import io.brooklyn.camp.spi.resolve.PlanInterpreter;
+
+import java.util.List;
+import java.util.Map;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+public class PlanInterpretationContext {
+
+    private final Map<String,Object> originalDeploymentPlan;
+    private final List<PlanInterpreter> interpreters;
+    private final PlanInterpreter allInterpreter;
+
+    public PlanInterpretationContext(Map<String,Object> originalDeploymentPlan, List<PlanInterpreter> interpreters) {
+        super();
+        this.originalDeploymentPlan = ImmutableMap.copyOf(originalDeploymentPlan);
+        this.interpreters = ImmutableList.copyOf(interpreters);
+        this.allInterpreter = new PlanInterpreter() {
+            @Override
+            public boolean isInterestedIn(PlanInterpretationNode node) {
+                return true;
+            }
+            
+            @Override
+            public void applyYamlPrimitive(PlanInterpretationNode node) {
+                for (PlanInterpreter i: PlanInterpretationContext.this.interpreters) {
+                    if (node.isExcluded())
+                        break;
+                    if (i.isInterestedIn(node)) {
+                        i.applyYamlPrimitive(node);
+                    }
+                }
+            }
+
+            @Override
+            public boolean applyMapBefore(PlanInterpretationNode node, Map<Object, Object> mapIn) {
+                boolean result = true;
+                for (PlanInterpreter i: PlanInterpretationContext.this.interpreters) {
+                    if (node.isExcluded())
+                        break;
+                    if (i.isInterestedIn(node)) {
+                        boolean ri= i.applyMapBefore(node, mapIn);
+                        result &= ri;
+                    }
+                }
+                return result;
+            }
+
+            @Override
+            public boolean applyMapEntry(PlanInterpretationNode node, Map<Object, Object> mapIn, Map<Object, Object> mapOut, 
+                                    PlanInterpretationNode key, PlanInterpretationNode value) {
+                boolean result = true;
+                for (PlanInterpreter i: PlanInterpretationContext.this.interpreters) { 
+                    if (node.isExcluded())
+                        break;
+                    if (i.isInterestedIn(key)) {
+                        boolean ri = i.applyMapEntry(node, mapIn, mapOut, key, value);
+                        result &= ri;
+                    }
+                }
+                return result;
+            }
+
+            @Override
+            public void applyMapAfter(PlanInterpretationNode node, Map<Object, Object> mapIn, Map<Object, Object> mapOut) {
+                for (PlanInterpreter i: PlanInterpretationContext.this.interpreters) { 
+                    if (node.isExcluded())
+                        break;
+                    if (i.isInterestedIn(node)) {
+                        i.applyMapAfter(node, mapIn, mapOut);
+                    }
+                }
+            }
+
+            @Override
+            public boolean applyListBefore(PlanInterpretationNode node, List<Object> listIn) {
+                boolean result = true;
+                for (PlanInterpreter i: PlanInterpretationContext.this.interpreters) { 
+                    if (node.isExcluded())
+                        break;
+                    if (i.isInterestedIn(node)) {
+                        boolean ri = i.applyListBefore(node, listIn);
+                        result &= ri;
+                    }
+                }
+                return result;
+            }
+
+            @Override
+            public boolean applyListEntry(PlanInterpretationNode node, List<Object> listIn, List<Object> listOut, 
+                                    PlanInterpretationNode value) {
+                boolean result = true;
+                for (PlanInterpreter i: PlanInterpretationContext.this.interpreters) { 
+                    if (node.isExcluded())
+                        break;
+                    if (i.isInterestedIn(value)) {
+                        boolean ri = i.applyListEntry(node, listIn, listOut, value);
+                        result &= ri;
+                    }
+                }
+                return result;
+            }
+
+            @Override
+            public void applyListAfter(PlanInterpretationNode node, List<Object> listIn, List<Object> listOut) {
+                for (PlanInterpreter i: PlanInterpretationContext.this.interpreters) { 
+                    if (node.isExcluded())
+                        break;
+                    if (i.isInterestedIn(node)) {
+                        i.applyListAfter(node, listIn, listOut);
+                    }
+                }
+            }
+
+        };
+    }
+
+    /** returns an interpreter which recurses through all interpreters */
+    PlanInterpreter getAllInterpreter() {
+        return allInterpreter;
+    }
+
+    public Map<String,Object> getOriginalDeploymentPlan() {
+        return originalDeploymentPlan;
+    }
+
+    public List<PlanInterpreter> getInterpreters() {
+        return interpreters;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/resolve/interpret/PlanInterpretationNode.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/resolve/interpret/PlanInterpretationNode.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/resolve/interpret/PlanInterpretationNode.java
new file mode 100644
index 0000000..788833f
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/resolve/interpret/PlanInterpretationNode.java
@@ -0,0 +1,245 @@
+package io.brooklyn.camp.spi.resolve.interpret;
+
+import io.brooklyn.camp.spi.resolve.PlanInterpreter;
+
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.text.StringPredicates;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+
+/** Helper class for {@link PlanInterpreter} instances, doing the recursive work */
+public class PlanInterpretationNode {
+
+    private static final Logger log = LoggerFactory.getLogger(PlanInterpretationNode.class);
+    
+    public enum Role { MAP_KEY, MAP_VALUE, LIST_ENTRY, YAML_PRIMITIVE }
+
+    protected final PlanInterpretationNode parent;
+    protected final Role roleInParent;
+    protected final Object originalValue;
+    protected final PlanInterpretationContext context;
+    protected Object newValue = null;
+    protected Boolean changed = null;
+    protected boolean excluded = false;
+    protected boolean immutable = false;
+
+    /** creates a root node with {@link #apply()} called */
+    public PlanInterpretationNode(PlanInterpretationContext context) {
+        this.parent = null;
+        this.roleInParent = null;
+        this.originalValue = context.getOriginalDeploymentPlan();
+        this.context = context;
+        apply();
+    }
+
+    /** internal use: creates an internal node on which {@link #apply()} has *not* been called */
+    protected PlanInterpretationNode(PlanInterpretationNode parent, Role roleInParent, Object originalItem) {
+        this.parent = parent;
+        this.roleInParent = roleInParent;
+        this.originalValue = originalItem;
+        this.context = parent.getContext();
+    }
+
+    public PlanInterpretationContext getContext() {
+        return context;
+    }
+
+    public PlanInterpretationNode getParent() {
+        return parent;
+    }
+    
+    public Role getRoleInParent() {
+        return roleInParent;
+    }
+    
+    protected void apply() {
+        if (changed!=null) throw new IllegalStateException("can only be applied once");
+
+        if (!excluded) {
+            if (originalValue instanceof Map) {
+                applyToMap();
+                immutable();
+            } else if (originalValue instanceof Iterable) {
+                applyToIterable();
+                immutable();
+            } else {
+                applyToYamlPrimitive();
+            }
+        }
+        
+        if (changed==null) changed = false;
+    }
+
+    /** convenience for interpreters, tests if nodes are not excluded, and if not:
+     * for string nodes, true iff the current value equals the given target;
+     * for nodes which are currently maps or lists,
+     * true iff not excluded and the value contains such an entry (key, in the case of map)
+     **/
+    public boolean matchesLiteral(String target) {
+        if (isExcluded()) return false; 
+        if (getNewValue() instanceof CharSequence)
+            return getNewValue().toString().equals(target);
+        if (getNewValue() instanceof Map)
+            return ((Map<?,?>)getOriginalValue()).containsKey(target);
+        if (getNewValue() instanceof Iterable)
+            return Iterables.contains((Iterable<?>)getOriginalValue(), target);
+        return false;
+    }
+
+    /** convenience for interpreters, tests if nodes are not excluded, and if not:
+     * for string nodes, true iff the current value starts with the given prefix;
+     * for nodes which are currently maps or lists,
+     * true iff not excluded and the value contains such an entry (key, in the case of map) */
+    public boolean matchesPrefix(String prefix) {
+        if (isExcluded()) return false; 
+        if (getNewValue() instanceof CharSequence)
+            return getNewValue().toString().startsWith(prefix);
+        if (getNewValue() instanceof Map)
+            return Iterables.tryFind(((Map<?,?>)getNewValue()).keySet(), StringPredicates.isStringStartingWith(prefix)).isPresent();
+        if (getNewValue() instanceof Iterable)
+            return Iterables.tryFind((Iterable<?>)getNewValue(), StringPredicates.isStringStartingWith(prefix)).isPresent();
+        return false;
+    }
+    
+    // TODO matchesRegex ?
+
+    public Object getOriginalValue() {
+        return originalValue;
+    }
+
+    public Object getNewValue() {
+        if (changed==null || !isChanged()) return originalValue;
+        return newValue;
+    }
+
+    public boolean isChanged() {
+        if (changed==null) throw new IllegalStateException("not yet applied");
+        return changed;
+    }
+
+    public boolean isExcluded() {
+        return excluded;
+    }
+    
+    /** indicates that a node should no longer be translated */
+    public PlanInterpretationNode exclude() {
+        this.excluded = true;
+        return this;
+    }
+    
+    public PlanInterpretationNode setNewValue(Object newItem) {
+        if (immutable)
+            throw new IllegalStateException("Node "+this+" has been set immutable");
+        this.newValue = newItem;
+        this.changed = true;
+        return this;
+    }
+
+    protected PlanInterpretationNode newPlanInterpretation(PlanInterpretationNode parent, Role roleInParent, Object item) {
+        return new PlanInterpretationNode(parent, roleInParent, item);
+    }
+
+    protected void applyToMap() {
+        Map<Object, Object> input = MutableMap.<Object,Object>copyOf((Map<?,?>)originalValue);
+        Map<Object, Object> result = MutableMap.<Object,Object>of();
+        newValue = result;
+
+        // first do a "whole-node" application
+        if (getContext().getAllInterpreter().applyMapBefore(this, input)) {
+
+            for (Map.Entry<Object,Object> entry: input.entrySet()) {
+                // then recurse in to this node and do various in-the-node applications
+                PlanInterpretationNode value = newPlanInterpretation(this, Role.MAP_VALUE, entry.getValue());
+                value.apply();
+
+                PlanInterpretationNode key = newPlanInterpretation(this, Role.MAP_KEY, entry.getKey());
+                key.apply();
+
+                if (key.isChanged() || value.isChanged()) 
+                    changed = true;
+
+                if (getContext().getAllInterpreter().applyMapEntry(this, input, result, key, value))
+                    result.put(key.getNewValue(), value.getNewValue());
+                else
+                    changed = true;
+            }
+
+            // finally try applying to this node again
+            getContext().getAllInterpreter().applyMapAfter(this, input, result);
+        }
+
+        if (changed==null) changed = false;
+    }
+
+    protected void applyToIterable() {
+        MutableList<Object> input = MutableList.copyOf((Iterable<?>)originalValue);
+        MutableList<Object> result = new MutableList<Object>();
+        newValue = result;
+
+        // first do a "whole-node" application
+        if (getContext().getAllInterpreter().applyListBefore(this, input)) {
+
+            for (Object entry: input) {
+                // then recurse in to this node and do various in-the-node applications
+                PlanInterpretationNode value = newPlanInterpretation(this, Role.LIST_ENTRY, entry);
+                value.apply();
+
+                if (value.isChanged()) 
+                    changed = true;
+
+                if (getContext().getAllInterpreter().applyListEntry(this, input, result, value))
+                    result.add(value.getNewValue());
+            }
+
+            // finally try applying to this node again
+            getContext().getAllInterpreter().applyListAfter(this, input, result);
+        }
+
+        if (changed==null) changed = false;
+    }
+
+    protected void applyToYamlPrimitive() {
+        getContext().getAllInterpreter().applyYamlPrimitive(this);
+    }
+
+    public void immutable() {
+        if (!isChanged()) {
+            if (!testCollectionImmutable(getNewValue())) {
+                // results of Yaml parse are not typically immutable,
+                // so force them to be changed so result of interpretation is immutable
+                changed = true;
+                setNewValue(immutable(getNewValue()));
+            }
+        } else {
+            setNewValue(immutable(getNewValue()));
+        }
+        checkImmutable(getNewValue());
+        immutable = true;
+    }
+    
+    private void checkImmutable(Object in) {
+        if (!testCollectionImmutable(in))
+            log.warn("Node original value "+in+" at "+this+" should be immutable");
+    }
+    
+    private static boolean testCollectionImmutable(Object in) {
+        if (in instanceof Map) return (in instanceof ImmutableMap);
+        if (in instanceof Iterable) return (in instanceof ImmutableList);
+        return true;
+    }
+
+    private static Object immutable(Object in) {
+        if (in instanceof Map) return ImmutableMap.copyOf((Map<?,?>)in);
+        if (in instanceof Iterable) return ImmutableList.copyOf((Iterable<?>)in);
+        return in;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/util/yaml/Yamls.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/util/yaml/Yamls.java b/camp/camp-base/src/main/java/io/brooklyn/util/yaml/Yamls.java
new file mode 100644
index 0000000..1e9275b
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/util/yaml/Yamls.java
@@ -0,0 +1,89 @@
+package io.brooklyn.util.yaml;
+
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Iterables;
+
+public class Yamls {
+
+    private static final Logger log = LoggerFactory.getLogger(Yamls.class);
+    
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public static <T> T getAs(Object x, Class<T> type) {
+        if (x==null) return null;
+        if (x instanceof Iterable || x instanceof Iterator) {
+            List result = new ArrayList();
+            Iterator xi;
+            if (Iterator.class.isAssignableFrom(x.getClass())) {
+                xi = (Iterator)x;
+            } else {
+                xi = ((Iterable)x).iterator();
+            }
+            while (xi.hasNext()) {
+                    result.add( xi.next() );
+            }
+            if (type.isAssignableFrom(Iterable.class)) return (T)result;
+            if (type.isAssignableFrom(Iterator.class)) return (T)result.iterator();
+            if (type.isAssignableFrom(List.class)) return (T)result;
+            x = Iterables.getOnlyElement(result);
+        }
+        // TODO more coercion?
+        return (T)x;
+    }
+
+    @SuppressWarnings("rawtypes")
+    public static void dump(int depth, Object r) {
+        if (r instanceof Iterable) {
+            for (Object ri : ((Iterable)r))
+                dump(depth+1, ri);
+        } else if (r instanceof Map) {
+            for (Object re: ((Map)r).entrySet()) {
+                for (int i=0; i<depth; i++) System.out.print(" ");
+                System.out.println(((Entry)re).getKey()+":");
+                dump(depth+1, ((Entry)re).getValue());
+            }
+        } else {
+            for (int i=0; i<depth; i++) System.out.print(" ");
+            if (r==null) System.out.println("<null>");
+            else System.out.println("<"+r.getClass().getSimpleName()+">"+" "+r);
+        }
+    }
+
+    /** simplifies new Yaml().loadAll, and converts to list to prevent single-use iterable bug in yaml */
+    @SuppressWarnings("unchecked")
+    public static Iterable<Object> parseAll(String yaml) {
+        Iterable<Object> result = new org.yaml.snakeyaml.Yaml().loadAll(yaml);
+        return (List<Object>) getAs(result, List.class);
+    }
+
+    /** as {@link #parseAll(String)} */
+    @SuppressWarnings("unchecked")
+    public static Iterable<Object> parseAll(Reader yaml) {
+        Iterable<Object> result = new org.yaml.snakeyaml.Yaml().loadAll(yaml);
+        return (List<Object>) getAs(result, List.class);
+    }
+
+    public static Object removeMultinameAttribute(Map<String,Object> obj, String ...equivalentNames) {
+        Object result = null;
+        for (String name: equivalentNames) {
+            Object candidate = obj.remove(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+"'");
+                }
+            }
+        }
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/resources/logback-custom.xml
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/resources/logback-custom.xml b/camp/camp-base/src/main/resources/logback-custom.xml
new file mode 100644
index 0000000..f7783a9
--- /dev/null
+++ b/camp/camp-base/src/main/resources/logback-custom.xml
@@ -0,0 +1,9 @@
+<included>
+
+    <!-- include everything in this project at debug level -->
+    <logger name="io.cloudsoft.cloudera" level="DEBUG"/>    
+    
+    <!-- log to simple-web-cluster.log -->
+    <property name="logging.basename" scope="context" value="brooklyn-camp" />
+
+</included>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/test/java/io/brooklyn/camp/spi/pdp/DeploymentPlanToyInterpreterTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/test/java/io/brooklyn/camp/spi/pdp/DeploymentPlanToyInterpreterTest.java b/camp/camp-base/src/test/java/io/brooklyn/camp/spi/pdp/DeploymentPlanToyInterpreterTest.java
new file mode 100644
index 0000000..949d197
--- /dev/null
+++ b/camp/camp-base/src/test/java/io/brooklyn/camp/spi/pdp/DeploymentPlanToyInterpreterTest.java
@@ -0,0 +1,96 @@
+package io.brooklyn.camp.spi.pdp;
+
+import io.brooklyn.camp.BasicCampPlatform;
+import io.brooklyn.camp.spi.resolve.PlanInterpreter.PlanInterpreterAdapter;
+import io.brooklyn.camp.spi.resolve.interpret.PlanInterpretationNode;
+import io.brooklyn.util.yaml.Yamls;
+
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import brooklyn.util.stream.Streams;
+import brooklyn.util.text.Strings;
+
+@Test
+public class DeploymentPlanToyInterpreterTest {
+
+    private static final Logger log = LoggerFactory.getLogger(DeploymentPlanToyInterpreterTest.class);
+    
+    /**
+     * Allows testing:
+     * 
+     * $sample:foo becomes "bar"
+     * $sample:caps:x capitalises the argument x
+     * $sample:ignore as key causes key-value to be dropped (and value 0 for good measure)
+     * $sample:reset causes containing map or list to be cleared at that point
+     * $sample:remove as key causes argument as map to be dropped
+     */
+    public static class ToyInterpreter extends PlanInterpreterAdapter {
+        
+        @Override
+        public boolean isInterestedIn(PlanInterpretationNode node) {
+            return node.matchesPrefix("$sample:");
+        }
+        
+        @Override
+        public void applyYamlPrimitive(PlanInterpretationNode node) {
+            if (node.matchesLiteral("$sample:foo")) node.setNewValue("bar").exclude();
+            if (node.matchesPrefix("$sample:caps:")) {
+                node.setNewValue(Strings.removeFromStart(node.getNewValue().toString(), "$sample:caps:").toUpperCase()).exclude();
+            }
+        }
+
+        @Override
+        public boolean applyMapBefore(PlanInterpretationNode node, Map<Object, Object> mapIn) {
+            if (node.matchesLiteral("$sample:ignore"))
+                // replace
+                mapIn.put("$sample:ignore", 0);
+            return super.applyMapBefore(node, mapIn);
+        }
+        
+        @Override
+        public boolean applyMapEntry(PlanInterpretationNode node, Map<Object, Object> mapIn, Map<Object, Object> mapOut,
+                                PlanInterpretationNode key, PlanInterpretationNode value) {
+            if (key.matchesLiteral("$sample:ignore")) {
+                Assert.assertEquals(value.getNewValue(), 0);
+                return false;
+            }
+            if (key.matchesLiteral("$sample:reset")) {
+                mapOut.clear();
+                return false;
+            }
+            
+            return super.applyMapEntry(node, mapIn, mapOut, key, value);
+        }
+
+        @SuppressWarnings("rawtypes")
+        @Override
+        public void applyMapAfter(PlanInterpretationNode node, Map<Object, Object> mapIn, Map<Object, Object> mapOut) {
+            if (mapOut.containsKey("$sample:remove")) {
+                Map toRemove = (Map) mapOut.get("$sample:remove");
+                for (Object vv: toRemove.keySet()) mapOut.remove(vv);
+                mapOut.remove("$sample:remove");
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public void testToyInterpreter() {
+        @SuppressWarnings("rawtypes")
+        Map y1 = Yamls.getAs( Yamls.parseAll( Streams.reader(getClass().getResourceAsStream("yaml-sample-toy-interpreter.yaml"))), Map.class );
+        log.info("pre-interpreter have: "+y1);
+        
+        BasicCampPlatform p = new BasicCampPlatform();
+        p.pdp().addInterpreter(new ToyInterpreter());
+        Map<String, Object> y2 = p.pdp().applyInterpreters(y1);
+        log.info("interpreter gives: "+y2);
+        
+        Map<String, Object> y3 = Yamls.getAs( Yamls.parseAll( Streams.reader(getClass().getResourceAsStream("yaml-sample-toy-interpreter-result.yaml"))), Map.class );
+        Assert.assertEquals(y2, y3);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/test/java/io/brooklyn/camp/spi/pdp/PdpYamlTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/test/java/io/brooklyn/camp/spi/pdp/PdpYamlTest.java b/camp/camp-base/src/test/java/io/brooklyn/camp/spi/pdp/PdpYamlTest.java
new file mode 100644
index 0000000..3b90434
--- /dev/null
+++ b/camp/camp-base/src/test/java/io/brooklyn/camp/spi/pdp/PdpYamlTest.java
@@ -0,0 +1,60 @@
+package io.brooklyn.camp.spi.pdp;
+
+import io.brooklyn.camp.BasicCampPlatform;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+import io.brooklyn.camp.test.mock.web.MockWebPlatform;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import brooklyn.util.stream.Streams;
+
+public class PdpYamlTest {
+
+    private static final Logger log = LoggerFactory.getLogger(PdpYamlTest.class);
+    
+    @Test
+    public void testSimpleYamlArtifactParse() throws IOException {
+        BasicCampPlatform platform = MockWebPlatform.populate(new BasicCampPlatform());
+        Reader input = Streams.reader(getClass().getResourceAsStream("pdp-single-artifact.yaml"));
+        DeploymentPlan plan = platform.pdp().parseDeploymentPlan(input);
+        log.info("DP is:\n"+plan.toString());
+        Assert.assertEquals(plan.getName(), "sample");
+        Assert.assertEquals(plan.getArtifacts().size(), 1);
+        Assert.assertEquals(plan.getServices().size(), 0);
+        
+        Artifact artifact1 = plan.getArtifacts().iterator().next();
+        Assert.assertEquals(artifact1.getName(), "sample WAR");
+    }
+    
+    @Test
+    public void testSimpleYamlServiceParse() throws IOException {
+        BasicCampPlatform platform = MockWebPlatform.populate(new BasicCampPlatform());
+        Reader input = Streams.reader(getClass().getResourceAsStream("pdp-single-service.yaml"));
+        DeploymentPlan plan = platform.pdp().parseDeploymentPlan(input);
+        log.info("DP is:\n"+plan.toString());
+        Assert.assertEquals(plan.getName(), "sample");
+        Assert.assertEquals(plan.getArtifacts().size(), 0);
+        Assert.assertEquals(plan.getServices().size(), 1);
+        
+        Service service1 = plan.getServices().iterator().next();
+        Assert.assertEquals(service1.getName(), "Hello WAR");
+    }
+    
+    @Test
+    public void testSimpleYamlMatch() throws IOException {
+        BasicCampPlatform platform = MockWebPlatform.populate(new BasicCampPlatform());
+        Reader input = new InputStreamReader(getClass().getResourceAsStream("pdp-single-artifact.yaml"));
+        AssemblyTemplate at = platform.pdp().registerDeploymentPlan(input);
+        log.info("AT is:\n"+at.toString());
+        Assert.assertEquals(at.getApplicationComponentTemplates().links().size(), 1);
+        Assert.assertEquals(at.getName(), "sample");
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/test/java/io/brooklyn/camp/test/mock/web/MockAssemblyTemplateInstantiator.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/test/java/io/brooklyn/camp/test/mock/web/MockAssemblyTemplateInstantiator.java b/camp/camp-base/src/test/java/io/brooklyn/camp/test/mock/web/MockAssemblyTemplateInstantiator.java
new file mode 100644
index 0000000..198cb7d
--- /dev/null
+++ b/camp/camp-base/src/test/java/io/brooklyn/camp/test/mock/web/MockAssemblyTemplateInstantiator.java
@@ -0,0 +1,20 @@
+package io.brooklyn.camp.test.mock.web;
+
+import io.brooklyn.camp.CampPlatform;
+import io.brooklyn.camp.spi.Assembly;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+import io.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MockAssemblyTemplateInstantiator implements AssemblyTemplateInstantiator {
+
+    private static final Logger log = LoggerFactory.getLogger(MockAssemblyTemplateInstantiator.class);
+    
+    public Assembly instantiate(AssemblyTemplate template, CampPlatform platform) {
+        log.debug("Ignoring request to instantiate "+template);
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/test/java/io/brooklyn/camp/test/mock/web/MockWebPlatform.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/test/java/io/brooklyn/camp/test/mock/web/MockWebPlatform.java b/camp/camp-base/src/test/java/io/brooklyn/camp/test/mock/web/MockWebPlatform.java
new file mode 100644
index 0000000..9ad8d33
--- /dev/null
+++ b/camp/camp-base/src/test/java/io/brooklyn/camp/test/mock/web/MockWebPlatform.java
@@ -0,0 +1,71 @@
+package io.brooklyn.camp.test.mock.web;
+
+import io.brooklyn.camp.BasicCampPlatform;
+import io.brooklyn.camp.spi.ApplicationComponentTemplate;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+import io.brooklyn.camp.spi.PlatformComponentTemplate;
+import io.brooklyn.camp.spi.collection.BasicResourceLookup;
+import io.brooklyn.camp.spi.pdp.Artifact;
+import io.brooklyn.camp.spi.pdp.AssemblyTemplateConstructor;
+import io.brooklyn.camp.spi.resolve.PdpMatcher;
+
+public class MockWebPlatform {
+
+    public static final ApplicationComponentTemplate WAR = 
+            ApplicationComponentTemplate.builder()
+                .name("io.camp.mock:WAR")
+                .description("Mock WAR")
+                .build();
+
+    public static final PlatformComponentTemplate APPSERVER = 
+            PlatformComponentTemplate.builder()
+                .name("io.camp.mock:AppServer")
+                .description("Mock Application Server")
+                .build();
+
+    public static final PlatformComponentTemplate DATABASE = 
+            PlatformComponentTemplate.builder()
+                .name("io.camp.mock:Database")
+                .description("Mock Database")
+                .build();
+
+    public static final AssemblyTemplate ASSEMBLY1 =
+            AssemblyTemplate.builder()
+                .name("WebAppAssembly1")
+                .description("Mock Web App Assembly Template")
+                .applicationComponentTemplates(BasicResourceLookup.of(WAR))
+                .instantiator(MockAssemblyTemplateInstantiator.class)
+                .build();
+
+    public static final PdpMatcher WAR_GETS_WAR_MATCHER = new PdpMatcher.ArtifactMatcher("com.java:WAR") {
+        public boolean apply(Object art, AssemblyTemplateConstructor atc) {
+            ApplicationComponentTemplate act = ApplicationComponentTemplate.builder()
+                    .name( ((Artifact)art).getName() )
+                    .description( ((Artifact)art).getDescription() )
+                    .customAttribute("implementation", WAR.getName())
+                    .customAttribute("artifactType", ((Artifact)art).getArtifactType())
+                    .build();
+
+            // TODO requirements, etc
+            
+            atc.add(act);
+            
+            return true;
+        }
+    };
+    
+    public static <T extends BasicCampPlatform> T populate(T platform) {
+        platform.platformComponentTemplates().addAll(APPSERVER, DATABASE);
+        platform.applicationComponentTemplates().add(WAR);
+        platform.assemblyTemplates().add(ASSEMBLY1);
+        
+        platform.pdp().addMatcher(WAR_GETS_WAR_MATCHER);
+        
+        return platform;
+    }
+
+    public static BasicCampPlatform newPlatform() {
+        return MockWebPlatform.populate(new BasicCampPlatform());
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/test/java/io/brooklyn/camp/test/platform/BasicCampPlatformTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/test/java/io/brooklyn/camp/test/platform/BasicCampPlatformTest.java b/camp/camp-base/src/test/java/io/brooklyn/camp/test/platform/BasicCampPlatformTest.java
new file mode 100644
index 0000000..87570f6
--- /dev/null
+++ b/camp/camp-base/src/test/java/io/brooklyn/camp/test/platform/BasicCampPlatformTest.java
@@ -0,0 +1,69 @@
+package io.brooklyn.camp.test.platform;
+
+import io.brooklyn.camp.BasicCampPlatform;
+import io.brooklyn.camp.spi.AbstractResource;
+import io.brooklyn.camp.spi.ApplicationComponentTemplate;
+import io.brooklyn.camp.spi.PlatformComponentTemplate;
+import io.brooklyn.camp.spi.collection.ResolvableLink;
+import io.brooklyn.camp.test.mock.web.MockWebPlatform;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class BasicCampPlatformTest {
+
+    @Test
+    public void testEmptyPlatform() {
+        BasicCampPlatform p = new BasicCampPlatform();
+        assertResourceFieldsNotNull(p.root());
+        Assert.assertEquals(p.platformComponentTemplates().links().size(), 0);
+    }        
+
+    @Test
+    public void testWebPctSetup() {
+        BasicCampPlatform p = new BasicCampPlatform();
+        p.platformComponentTemplates().add(MockWebPlatform.APPSERVER);
+        
+        assertResourceFieldsNotNull(p.root());
+        
+        Assert.assertEquals(p.platformComponentTemplates().links().size(), 1);
+        ResolvableLink<PlatformComponentTemplate> l = p.platformComponentTemplates().links().get(0);
+        assertLinkFieldsNotNull(l);
+        Assert.assertEquals(l.getName(), "io.camp.mock:AppServer");
+        
+        PlatformComponentTemplate pct = l.resolve();
+        assertResourceFieldsNotNull(pct);
+    }        
+
+    @Test
+    public void testWarActSetup() {
+        BasicCampPlatform p = new BasicCampPlatform();
+        p.applicationComponentTemplates().add(MockWebPlatform.WAR);
+        
+        assertResourceFieldsNotNull(p.root());
+        
+        Assert.assertEquals(p.platformComponentTemplates().links().size(), 0);
+        Assert.assertEquals(p.applicationComponentTemplates().links().size(), 1);
+        ResolvableLink<ApplicationComponentTemplate> l = p.applicationComponentTemplates().links().get(0);
+        assertLinkFieldsNotNull(l);
+        Assert.assertEquals(l.getName(), "io.camp.mock:WAR");
+        
+        ApplicationComponentTemplate act = l.resolve();
+        assertResourceFieldsNotNull(act);
+    }        
+
+
+    public static void assertLinkFieldsNotNull(ResolvableLink<?> x) {
+        Assert.assertNotNull(x.getId());
+        Assert.assertNotNull(x.getName());
+    }
+
+    public static void assertResourceFieldsNotNull(AbstractResource x) {
+        Assert.assertNotNull(x.getId());
+        Assert.assertNotNull(x.getType());
+        Assert.assertNotNull(x.getCreated());
+        Assert.assertNotNull(x.getName());
+        Assert.assertNotNull(x.getTags());
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/test/resources/io/brooklyn/camp/spi/pdp/pdp-single-artifact.yaml
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/test/resources/io/brooklyn/camp/spi/pdp/pdp-single-artifact.yaml b/camp/camp-base/src/test/resources/io/brooklyn/camp/spi/pdp/pdp-single-artifact.yaml
new file mode 100644
index 0000000..2cf4c80
--- /dev/null
+++ b/camp/camp-base/src/test/resources/io/brooklyn/camp/spi/pdp/pdp-single-artifact.yaml
@@ -0,0 +1,9 @@
+name: sample
+description: Tomcat sample JSP and servlet application.
+origin: http://www.oracle.com/nCAMP/Hand
+artifacts:
+  -
+    type: com.java:WAR
+    content: { href: sample.war }
+    name: sample WAR
+    description: Tomcat sample WAR file

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/test/resources/io/brooklyn/camp/spi/pdp/pdp-single-service.yaml
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/test/resources/io/brooklyn/camp/spi/pdp/pdp-single-service.yaml b/camp/camp-base/src/test/resources/io/brooklyn/camp/spi/pdp/pdp-single-service.yaml
new file mode 100644
index 0000000..d3dfb54
--- /dev/null
+++ b/camp/camp-base/src/test/resources/io/brooklyn/camp/spi/pdp/pdp-single-service.yaml
@@ -0,0 +1,11 @@
+name: sample
+description: Tomcat sample JSP and servlet application.
+origin: http://www.oracle.com/nCAMP/Hand
+services:
+  -
+    type: brooklyn:WebAppCluster
+    name: Hello WAR
+    wars:
+        /: hello.war
+    controller.spec:
+        port: 80

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/test/resources/io/brooklyn/camp/spi/pdp/yaml-sample-toy-interpreter-result.yaml
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/test/resources/io/brooklyn/camp/spi/pdp/yaml-sample-toy-interpreter-result.yaml b/camp/camp-base/src/test/resources/io/brooklyn/camp/spi/pdp/yaml-sample-toy-interpreter-result.yaml
new file mode 100644
index 0000000..d71059d
--- /dev/null
+++ b/camp/camp-base/src/test/resources/io/brooklyn/camp/spi/pdp/yaml-sample-toy-interpreter-result.yaml
@@ -0,0 +1,4 @@
+keep: 1
+mess:
+  a: bar
+  b: [ c, D ]

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/test/resources/io/brooklyn/camp/spi/pdp/yaml-sample-toy-interpreter.yaml
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/test/resources/io/brooklyn/camp/spi/pdp/yaml-sample-toy-interpreter.yaml b/camp/camp-base/src/test/resources/io/brooklyn/camp/spi/pdp/yaml-sample-toy-interpreter.yaml
new file mode 100644
index 0000000..d90930f
--- /dev/null
+++ b/camp/camp-base/src/test/resources/io/brooklyn/camp/spi/pdp/yaml-sample-toy-interpreter.yaml
@@ -0,0 +1,10 @@
+$sample:ignore: 1
+keep: 1
+mess:
+  2: z
+  $sample:reset: 
+  $sample:ignore: z
+  a: $sample:foo
+  b: [ c, "$sample:caps:d" ]
+  3: $sample:caps:x
+  $sample:remove: {3: X}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/pom.xml
----------------------------------------------------------------------
diff --git a/camp/camp-server/pom.xml b/camp/camp-server/pom.xml
new file mode 100644
index 0000000..08a58b8
--- /dev/null
+++ b/camp/camp-server/pom.xml
@@ -0,0 +1,115 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <packaging>bundle</packaging>
+
+    <artifactId>camp-server</artifactId>
+
+    <name>CAMP Server</name>
+    <description>
+        REST Server classes for CAMP server implementation
+    </description>
+
+    <parent>
+        <groupId>io.brooklyn.camp</groupId>
+        <artifactId>camp-parent</artifactId>
+        <version>0.1.0-SNAPSHOT</version>  <!-- CAMP_IMPL_VERSION -->
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <properties>
+        <jersey.version>1.12</jersey.version>
+        <jetty.version>8.1.4.v20120524</jetty.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>io.brooklyn.camp</groupId>
+            <artifactId>camp-base</artifactId>
+            <version>${camp-impl.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>io.brooklyn.camp</groupId>
+            <artifactId>camp-base</artifactId>
+            <version>${camp-impl.version}</version>
+            <classifier>tests</classifier>
+            <scope>test</scope>
+        </dependency>
+        
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-annotations</artifactId>
+            <version>${fasterxml.jackson.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+            <version>${fasterxml.jackson.version}</version>
+        </dependency>
+        
+        <dependency>
+            <groupId>com.fasterxml.jackson.jaxrs</groupId>
+            <artifactId>jackson-jaxrs-json-provider</artifactId>
+            <version>${fasterxml.jackson.version}</version>
+        </dependency>
+        
+        <dependency>
+            <groupId>com.sun.jersey</groupId>
+            <artifactId>jersey-server</artifactId>
+            <version>${jersey.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.sun.jersey</groupId>
+            <artifactId>jersey-servlet</artifactId>
+            <version>${jersey.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.sun.jersey</groupId>
+            <artifactId>jersey-json</artifactId>
+            <version>${jersey.version}</version>
+              <exclusions>
+                <exclusion>
+                    <groupId>com.sun.xml.bind</groupId>
+                    <artifactId>jaxb-impl</artifactId>
+                </exclusion>
+            </exclusions>               
+        </dependency>
+
+        <dependency>
+            <groupId>com.sun.jersey.contribs</groupId>
+            <artifactId>jersey-multipart</artifactId>
+            <version>${jersey.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>javax.validation</groupId>
+            <artifactId>validation-api</artifactId>
+            <version>1.0.0.GA</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-webapp</artifactId>
+            <version>${jetty.version}</version>
+        </dependency>
+        
+        <dependency>
+            <groupId>io.brooklyn</groupId>
+            <artifactId>brooklyn-utils-rest-swagger</artifactId>
+            <version>${brooklyn.version}</version>
+        </dependency>
+        
+        <!-- TODO have a camp.log / logging module -->
+        <dependency>
+            <groupId>io.brooklyn</groupId>
+            <artifactId>brooklyn-logback-xml</artifactId>
+            <version>${brooklyn.version}</version>
+            <!-- optional so that this project has logging; dependencies may redeclare or supply their own -->
+            <optional>true</optional>
+        </dependency>
+        
+        
+    </dependencies>
+
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/CampRestResources.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/CampRestResources.java b/camp/camp-server/src/main/java/io/brooklyn/camp/CampRestResources.java
new file mode 100644
index 0000000..cb84b90
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/CampRestResources.java
@@ -0,0 +1,52 @@
+package io.brooklyn.camp;
+
+import io.brooklyn.camp.rest.resource.AbstractCampRestResource;
+import io.brooklyn.camp.rest.resource.ApidocRestResource;
+import io.brooklyn.camp.rest.resource.ApplicationComponentRestResource;
+import io.brooklyn.camp.rest.resource.ApplicationComponentTemplateRestResource;
+import io.brooklyn.camp.rest.resource.AssemblyRestResource;
+import io.brooklyn.camp.rest.resource.AssemblyTemplateRestResource;
+import io.brooklyn.camp.rest.resource.PlatformComponentRestResource;
+import io.brooklyn.camp.rest.resource.PlatformComponentTemplateRestResource;
+import io.brooklyn.camp.rest.resource.PlatformRestResource;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import brooklyn.rest.apidoc.ApidocHelpMessageBodyWriter;
+
+import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
+import com.google.common.collect.Iterables;
+
+public class CampRestResources {
+
+    public static Iterable<AbstractCampRestResource> getCampRestResources() {
+        List<AbstractCampRestResource> resources = new ArrayList<AbstractCampRestResource>();
+        resources.add(new PlatformRestResource());
+        resources.add(new AssemblyTemplateRestResource());
+        resources.add(new PlatformComponentTemplateRestResource());
+        resources.add(new ApplicationComponentTemplateRestResource());
+        resources.add(new AssemblyRestResource());
+        resources.add(new PlatformComponentRestResource());
+        resources.add(new ApplicationComponentRestResource());
+        return resources;
+    }
+
+    public static Iterable<Object> getApidocResources() {
+        List<Object> resources = new ArrayList<Object>();
+        resources.add(new ApidocHelpMessageBodyWriter());
+        resources.add(new ApidocRestResource());
+        return resources;
+    }
+
+    public static Iterable<Object> getMiscResources() {
+        List<Object> resources = new ArrayList<Object>();
+        resources.add(new JacksonJsonProvider());
+        return resources;
+    }
+
+    public static Iterable<Object> getAllResources() {
+        return Iterables.concat(getCampRestResources(), getApidocResources(), getMiscResources());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/CampServer.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/CampServer.java b/camp/camp-server/src/main/java/io/brooklyn/camp/CampServer.java
new file mode 100644
index 0000000..03f49e4
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/CampServer.java
@@ -0,0 +1,167 @@
+package io.brooklyn.camp;
+
+import io.brooklyn.camp.rest.resource.PlatformRestResource;
+import io.brooklyn.camp.rest.util.DtoFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.EnumSet;
+
+import javax.servlet.DispatcherType;
+
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.servlet.FilterHolder;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
+import org.eclipse.jetty.webapp.WebAppContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.net.Networking;
+
+import com.google.common.base.Charsets;
+import com.google.common.io.Files;
+import com.sun.jersey.api.core.DefaultResourceConfig;
+import com.sun.jersey.api.core.ResourceConfig;
+import com.sun.jersey.spi.container.servlet.ServletContainer;
+
+public class CampServer {
+
+    private static final Logger log = LoggerFactory.getLogger(CampServer.class);
+
+    public static final String CAMP_PLATFORM_ATTRIBUTE = CampPlatform.class.getCanonicalName();
+    public static final String DTO_FACTORY = DtoFactory.class.getCanonicalName();
+    
+    private final CampPlatform platform;
+    private final String uriBase;
+    private DtoFactory dtoFactory;
+    
+    WebAppContext webAppContext;
+    Server server;
+    
+    public CampServer(CampPlatform platform, String uriBase) {
+        this.platform = platform;
+        this.uriBase = uriBase;
+    }
+
+    public CampPlatform getPlatform() {
+        return platform;
+    }
+
+    public String getUriBase() {
+        return uriBase;
+    }
+    
+    public WebAppContext getWebAppContext() {
+        return webAppContext;
+    }
+    
+    public synchronized DtoFactory getDtoFactory() {
+        if (dtoFactory!=null) return dtoFactory;
+        dtoFactory = createDtoFactory();
+        return dtoFactory;
+    }
+    
+    protected DtoFactory createDtoFactory() {
+        return new DtoFactory(getPlatform(), getUriBase());
+    }
+    
+    public synchronized CampServer start() {
+        if (webAppContext!=null)
+            throw new IllegalStateException("Already started");
+        
+        webAppContext = new WebAppContext();
+        webAppContext.setContextPath("/");
+        webAppContext.setAttribute(CAMP_PLATFORM_ATTRIBUTE, getPlatform());
+        webAppContext.setAttribute(DTO_FACTORY, getDtoFactory());
+        webAppContext.setWar(
+                // TODO if there is a GUI or other war...
+                //findJsguiWebapp()!=null ? findJsguiWebapp() : 
+                CampServerUtils.createTempWebDirWithIndexHtml("CAMP REST API <p> (no gui available - " +
+                		"rest endpoint at <a href=\""+PlatformRestResource.CAMP_URI_PATH+"\">"+PlatformRestResource.CAMP_URI_PATH+"</a>)"));
+        CampServerUtils.installAsServletFilter(webAppContext);
+        
+        server = CampServerUtils.startServer(webAppContext, "CAMP server");
+        
+        return this;
+    }
+
+    public synchronized void stop() {
+        try {
+            server.stop();
+            server = null;
+            webAppContext.stop();
+            webAppContext = null;
+        } catch (Exception e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+    
+    public Integer getPort() {
+        if (server==null) return null;
+        return server.getConnectors()[0].getLocalPort();
+    }
+
+    public static class CampServerUtils {
+
+        public static void installAsServletFilter(ServletContextHandler context) {
+            // TODO security
+            //        installBrooklynPropertiesSecurityFilter(context);
+
+            // now set up the REST servlet resources
+            ResourceConfig config = new DefaultResourceConfig();
+            // load all our REST API modules, JSON, and Swagger
+            for (Object r: CampRestResources.getAllResources())
+                config.getSingletons().add(r);
+
+            // configure to match empty path, or any thing which looks like a file path with /assets/ and extension html, css, js, or png
+            // and treat that as static content
+            config.getProperties().put(ServletContainer.PROPERTY_WEB_PAGE_CONTENT_REGEX, "(/?|[^?]*/assets/[^?]+\\.[A-Za-z0-9_]+)");
+
+            // and anything which is not matched as a servlet also falls through (but more expensive than a regex check?)
+            config.getFeatures().put(ServletContainer.FEATURE_FILTER_FORWARD_ON_404, true);
+
+            // finally create this as a _filter_ which falls through to a web app or something (optionally)
+            FilterHolder filterHolder = new FilterHolder(new ServletContainer(config));
+            context.addFilter(filterHolder, "/*", EnumSet.allOf(DispatcherType.class));
+        }
+
+        public static Server startServer(ContextHandler context, String summary) {
+            // FIXME port hardcoded
+            int port = Networking.nextAvailablePort(8080);
+            Server server = new Server(port);
+            server.setHandler(context);
+            
+            // use a nice name in the thread pool (otherwise this is exactly the same as Server defaults)
+            QueuedThreadPool threadPool = new QueuedThreadPool();
+            threadPool.setName("camp-jetty-server-"+port+"-"+threadPool.getName());
+            server.setThreadPool(threadPool);
+
+            try {
+                server.start();
+            } catch (Exception e) {
+                throw Exceptions.propagate(e);
+            } 
+            log.info("CAMP REST server started ("+summary+") on");
+            log.info("  http://localhost:"+server.getConnectors()[0].getLocalPort()+"/");
+
+            return server;
+        }
+        
+        /** create a directory with a simple index.html so we have some content being served up */
+        public static String createTempWebDirWithIndexHtml(String indexHtmlContent) {
+            File dir = Files.createTempDir();
+            dir.deleteOnExit();
+            try {
+                Files.write(indexHtmlContent, new File(dir, "index.html"), Charsets.UTF_8);
+            } catch (IOException e) {
+                Exceptions.propagate(e);
+            }
+            return dir.getAbsolutePath();
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/dto/ApiErrorDto.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/dto/ApiErrorDto.java b/camp/camp-server/src/main/java/io/brooklyn/camp/dto/ApiErrorDto.java
new file mode 100644
index 0000000..9fc2ff6
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/dto/ApiErrorDto.java
@@ -0,0 +1,101 @@
+package io.brooklyn.camp.dto;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+import com.google.common.base.Throwables;
+
+/**
+ * A simple error message that provides a message and optional details.
+ *
+ * This class should eventually be replaced with an ErrorMessage object,
+ * as described in the CAMP spec.
+ */
+public class ApiErrorDto {
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * @return An {@link ApiErrorDto.Builder} whose message is initialised to either the throwable's
+     *         message or the throwable's class name if the message is null and whose details are
+     *         initialised to the throwable's stack trace.
+     */
+    public static Builder fromThrowable(Throwable t) {
+        checkNotNull(t, "throwable");
+        String message = Optional.fromNullable(t.getMessage())
+                .or(t.getClass().getName());
+        return builder()
+                .message(message)
+                .details(Throwables.getStackTraceAsString(t));
+    }
+
+    public static class Builder {
+        private String message;
+        private String details;
+
+        public Builder message(String message) {
+            this.message = checkNotNull(message, "message");
+            return this;
+        }
+
+        public Builder details(String details) {
+            this.details = checkNotNull(details, "details");
+            return this;
+        }
+
+        public ApiErrorDto build() {
+            return new ApiErrorDto(message, details);
+        }
+
+        public Builder fromApiErrorDto(ApiErrorDto error) {
+            return this
+                    .message(error.message)
+                    .details(error.details);
+        }
+    }
+
+    private final String message;
+    private final String details;
+
+    public ApiErrorDto(
+            @JsonProperty("message") String message,
+            @JsonProperty("details") String details) {
+        this.message = checkNotNull(message, "message");
+        this.details = details != null ? details : "";
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public String getDetails() {
+        return details;
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (this == other) return true;
+        if (other == null || getClass() != other.getClass()) return false;
+        ApiErrorDto that = ApiErrorDto.class.cast(other);
+        return Objects.equal(this.message, that.message) &&
+                Objects.equal(this.details, that.details);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(message, details);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this)
+                .add("message", message)
+                .add("details", details)
+                .toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/dto/ApplicationComponentDto.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/dto/ApplicationComponentDto.java b/camp/camp-server/src/main/java/io/brooklyn/camp/dto/ApplicationComponentDto.java
new file mode 100644
index 0000000..0d16a63
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/dto/ApplicationComponentDto.java
@@ -0,0 +1,54 @@
+package io.brooklyn.camp.dto;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+
+import io.brooklyn.camp.rest.util.DtoFactory;
+import io.brooklyn.camp.spi.ApplicationComponent;
+import io.brooklyn.camp.spi.Link;
+import io.brooklyn.camp.spi.PlatformComponent;
+
+public class ApplicationComponentDto extends ResourceDto {
+
+    // defined as a constant so can be used in Swagger REST API annotations
+    public static final String CLASS_NAME = "io.brooklyn.camp.dto.ApplicationComponentDto";
+    static { assert CLASS_NAME.equals(ApplicationComponentDto.class.getCanonicalName()); }
+
+    protected ApplicationComponentDto() {}
+    protected ApplicationComponentDto(DtoFactory dtoFactory, ApplicationComponent x) {
+        super(dtoFactory, x);
+        
+        platformComponents = new ArrayList<LinkDto>();
+        for (Link<PlatformComponent> t: x.getPlatformComponents().links()) {
+            platformComponents.add(LinkDto.newInstance(dtoFactory, PlatformComponent.class, t));
+        }
+        
+        applicationComponents = new ArrayList<LinkDto>();
+        for (Link<ApplicationComponent> t: x.getApplicationComponents().links()) {
+            applicationComponents.add(LinkDto.newInstance(dtoFactory, ApplicationComponent.class, t));
+        }
+    }
+ 
+    private List<LinkDto> platformComponents;
+    private List<LinkDto> applicationComponents;
+
+    @JsonInclude(Include.NON_EMPTY)
+    public List<LinkDto> getPlatformComponents() {
+        return platformComponents;
+    }
+    
+    @JsonInclude(Include.NON_EMPTY)
+    public List<LinkDto> getApplicationComponents() {
+        return applicationComponents;
+    }
+    
+    // --- building ---
+
+    public static ApplicationComponentDto newInstance(DtoFactory dtoFactory, ApplicationComponent x) {
+        return new ApplicationComponentDto(dtoFactory, x);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/dto/ApplicationComponentTemplateDto.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/dto/ApplicationComponentTemplateDto.java b/camp/camp-server/src/main/java/io/brooklyn/camp/dto/ApplicationComponentTemplateDto.java
new file mode 100644
index 0000000..97fee72
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/dto/ApplicationComponentTemplateDto.java
@@ -0,0 +1,26 @@
+package io.brooklyn.camp.dto;
+
+import io.brooklyn.camp.rest.util.DtoFactory;
+import io.brooklyn.camp.spi.ApplicationComponentTemplate;
+
+public class ApplicationComponentTemplateDto extends ResourceDto {
+
+    // defined as a constant so can be used in Swagger REST API annotations
+    public static final String CLASS_NAME = "io.brooklyn.camp.dto.ApplicationComponentTemplateDto";
+    static { assert CLASS_NAME.equals(ApplicationComponentTemplateDto.class.getCanonicalName()); }
+
+    protected ApplicationComponentTemplateDto() {}
+    protected ApplicationComponentTemplateDto(DtoFactory dtoFactory, ApplicationComponentTemplate x) {
+        super(dtoFactory, x);
+        // TODO set addl ACT fields
+    }
+ 
+    // TODO add addl ACT fields
+    
+    // --- building ---
+
+    public static ApplicationComponentTemplateDto newInstance(DtoFactory dtoFactory, ApplicationComponentTemplate x) {
+        return new ApplicationComponentTemplateDto(dtoFactory, x);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/dto/AssemblyDto.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/dto/AssemblyDto.java b/camp/camp-server/src/main/java/io/brooklyn/camp/dto/AssemblyDto.java
new file mode 100644
index 0000000..6ec80f8
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/dto/AssemblyDto.java
@@ -0,0 +1,59 @@
+package io.brooklyn.camp.dto;
+
+import io.brooklyn.camp.rest.util.DtoFactory;
+import io.brooklyn.camp.spi.ApplicationComponent;
+import io.brooklyn.camp.spi.Assembly;
+import io.brooklyn.camp.spi.Link;
+import io.brooklyn.camp.spi.PlatformComponent;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+
+public class AssemblyDto extends ResourceDto {
+
+    // defined as a constant so can be used in Swagger REST API annotations
+    public static final String CLASS_NAME = "io.brooklyn.camp.dto.AssemblyDto";
+    static { assert CLASS_NAME.equals(AssemblyDto.class.getCanonicalName()); }
+
+    protected AssemblyDto() {}
+    protected AssemblyDto(DtoFactory dtoFactory, Assembly x) {
+        super(dtoFactory, x);
+        
+        platformComponents = new ArrayList<LinkDto>();
+        for (Link<PlatformComponent> t: x.getPlatformComponents().links()) {
+            platformComponents.add(LinkDto.newInstance(dtoFactory, PlatformComponent.class, t));
+        }
+        
+        applicationComponents = new ArrayList<LinkDto>();
+        for (Link<ApplicationComponent> t: x.getApplicationComponents().links()) {
+            applicationComponents.add(LinkDto.newInstance(dtoFactory, ApplicationComponent.class, t));
+        }
+    }
+ 
+    private List<LinkDto> platformComponents;
+    private List<LinkDto> applicationComponents;
+
+    // TODO addl AssemblyTemplate fields
+//  "parameterDefinitionUri": URI,
+//  "pdpUri" : URI ?
+
+    @JsonInclude(Include.NON_EMPTY)
+    public List<LinkDto> getPlatformComponents() {
+        return platformComponents;
+    }
+    
+    @JsonInclude(Include.NON_EMPTY)
+    public List<LinkDto> getApplicationComponents() {
+        return applicationComponents;
+    }
+    
+    // --- building ---
+
+    public static AssemblyDto newInstance(DtoFactory dtoFactory, Assembly x) {
+        return new AssemblyDto(dtoFactory, x);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/dto/AssemblyTemplateDto.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/dto/AssemblyTemplateDto.java b/camp/camp-server/src/main/java/io/brooklyn/camp/dto/AssemblyTemplateDto.java
new file mode 100644
index 0000000..4db222c
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/dto/AssemblyTemplateDto.java
@@ -0,0 +1,54 @@
+package io.brooklyn.camp.dto;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import io.brooklyn.camp.rest.util.DtoFactory;
+import io.brooklyn.camp.spi.ApplicationComponentTemplate;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+import io.brooklyn.camp.spi.Link;
+import io.brooklyn.camp.spi.PlatformComponentTemplate;
+
+public class AssemblyTemplateDto extends ResourceDto {
+
+    // defined as a constant so can be used in Swagger REST API annotations
+    public static final String CLASS_NAME = "io.brooklyn.camp.dto.AssemblyTemplateDto";
+    static { assert CLASS_NAME.equals(AssemblyTemplateDto.class.getCanonicalName()); }
+
+    protected AssemblyTemplateDto() {}
+    protected AssemblyTemplateDto(DtoFactory dtoFactory, AssemblyTemplate x) {
+        super(dtoFactory, x);
+        
+        platformComponentTemplates = new ArrayList<LinkDto>();
+        for (Link<PlatformComponentTemplate> t: x.getPlatformComponentTemplates().links()) {
+            platformComponentTemplates.add(LinkDto.newInstance(dtoFactory, PlatformComponentTemplate.class, t));
+        }
+        
+        applicationComponentTemplates = new ArrayList<LinkDto>();
+        for (Link<ApplicationComponentTemplate> t: x.getApplicationComponentTemplates().links()) {
+            applicationComponentTemplates.add(LinkDto.newInstance(dtoFactory, ApplicationComponentTemplate.class, t));
+        }
+    }
+ 
+    private List<LinkDto> platformComponentTemplates;
+    private List<LinkDto> applicationComponentTemplates;
+
+    // TODO addl AssemblyTemplate fields
+//  "parameterDefinitionUri": URI,
+//  "pdpUri" : URI ?
+
+    public List<LinkDto> getPlatformComponentTemplates() {
+        return platformComponentTemplates;
+    }
+    
+    public List<LinkDto> getApplicationComponentTemplates() {
+        return applicationComponentTemplates;
+    }
+    
+    // --- building ---
+
+    public static AssemblyTemplateDto newInstance(DtoFactory dtoFactory, AssemblyTemplate x) {
+        return new AssemblyTemplateDto(dtoFactory, x);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/dto/DtoBase.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/dto/DtoBase.java b/camp/camp-server/src/main/java/io/brooklyn/camp/dto/DtoBase.java
new file mode 100644
index 0000000..067875b
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/dto/DtoBase.java
@@ -0,0 +1,13 @@
+package io.brooklyn.camp.dto;
+
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+public class DtoBase {
+
+    @Override public String toString() { return ToStringBuilder.reflectionToString(this); }
+    @Override public boolean equals(Object obj) { return EqualsBuilder.reflectionEquals(this, obj); }
+    @Override public int hashCode() { return HashCodeBuilder.reflectionHashCode(this); }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/dto/DtoCustomAttributes.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/dto/DtoCustomAttributes.java b/camp/camp-server/src/main/java/io/brooklyn/camp/dto/DtoCustomAttributes.java
new file mode 100644
index 0000000..fb4cf7d
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/dto/DtoCustomAttributes.java
@@ -0,0 +1,48 @@
+package io.brooklyn.camp.dto;
+
+import java.util.Map;
+
+import brooklyn.util.collections.MutableMap;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.google.common.collect.ImmutableMap;
+
+public class DtoCustomAttributes extends DtoBase {
+
+    private Map<String,Object> customAttributes = new MutableMap<String, Object>();
+
+    protected DtoCustomAttributes() {}
+    
+    public DtoCustomAttributes(Map<String,?> customAttributes) {
+        this.customAttributes = customAttributes==null ? ImmutableMap.<String, Object>of() : ImmutableMap.copyOf(customAttributes);
+    }
+    
+    @JsonIgnore
+    public Map<String, Object> getCustomAttributes() {
+        return customAttributes;
+    }
+
+    // --- json ---
+    
+    @JsonInclude(Include.NON_EMPTY)
+    @JsonAnyGetter
+    private Map<String,Object> any() {
+        return customAttributes;
+    }
+    @JsonAnySetter
+    private void set(String name, Object value) {
+        customAttributes.put(name, value);
+    }
+
+    // --- building ---
+
+    protected void newInstanceCustomAttributes(Map<String,?> customAttributes) {
+        if (customAttributes!=null)
+            this.customAttributes.putAll(customAttributes);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/dto/LinkDto.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/dto/LinkDto.java b/camp/camp-server/src/main/java/io/brooklyn/camp/dto/LinkDto.java
new file mode 100644
index 0000000..fe0a621
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/dto/LinkDto.java
@@ -0,0 +1,54 @@
+package io.brooklyn.camp.dto;
+
+import io.brooklyn.camp.rest.util.DtoFactory;
+import io.brooklyn.camp.spi.AbstractResource;
+import io.brooklyn.camp.spi.Link;
+
+import java.util.Map;
+
+public class LinkDto extends DtoCustomAttributes {
+
+    // defined as a constant so can be used in Swagger REST API annotations
+    public static final String CLASS_NAME = "io.brooklyn.camp.dto.LinkDto";
+    static { assert CLASS_NAME.equals(LinkDto.class.getCanonicalName()); }
+
+    private String href;
+    private String targetName;
+
+    protected LinkDto() {}
+    
+    public String getHref() {
+        return href;
+    }
+    
+    public String getTargetName() {
+        return targetName;
+    }
+    
+    // --- building ---
+
+    public static LinkDto newInstance(DtoFactory dtoFactory, Class<? extends AbstractResource> targetType, Link<?> x) {
+        return new LinkDto().newInstanceInitialization(dtoFactory, targetType, x);
+    }
+    
+    protected LinkDto newInstanceInitialization(DtoFactory dtoFactory, Class<? extends AbstractResource> targetType, Link<?> x) {
+        targetName = x.getName();
+        
+        href = dtoFactory.uri(targetType, x.getId());
+        return this;
+    }
+
+    public static LinkDto newInstance(String href, String targetName) {
+        LinkDto x = new LinkDto();
+        x.href = href;
+        x.targetName = targetName;
+        return x;
+    }
+    
+    public static LinkDto newInstance(String href, String targetName, Map<String,?> customAttributes) {
+        LinkDto x = newInstance(href, targetName);
+        x.newInstanceCustomAttributes(customAttributes);
+        return x;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/dto/PlatformComponentDto.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/dto/PlatformComponentDto.java b/camp/camp-server/src/main/java/io/brooklyn/camp/dto/PlatformComponentDto.java
new file mode 100644
index 0000000..e3ecb39
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/dto/PlatformComponentDto.java
@@ -0,0 +1,64 @@
+package io.brooklyn.camp.dto;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+
+import io.brooklyn.camp.rest.util.DtoFactory;
+import io.brooklyn.camp.spi.ApplicationComponent;
+import io.brooklyn.camp.spi.Link;
+import io.brooklyn.camp.spi.PlatformComponent;
+
+public class PlatformComponentDto extends ResourceDto {
+
+    // defined as a constant so can be used in Swagger REST API annotations
+    public static final String CLASS_NAME = "io.brooklyn.camp.dto.PlatformComponentDto";
+    static { assert CLASS_NAME.equals(PlatformComponentDto.class.getCanonicalName()); }
+ 
+    protected PlatformComponentDto() {}
+    protected PlatformComponentDto(DtoFactory dtoFactory, PlatformComponent x) {
+        super(dtoFactory, x);
+        setExternalManagementUri(x.getExternalManagementUri());
+        platformComponents = new ArrayList<LinkDto>();
+        for (Link<PlatformComponent> t: x.getPlatformComponents().links()) {
+            platformComponents.add(LinkDto.newInstance(dtoFactory, PlatformComponent.class, t));
+        }
+        
+        applicationComponents = new ArrayList<LinkDto>();
+        for (Link<ApplicationComponent> t: x.getApplicationComponents().links()) {
+            applicationComponents.add(LinkDto.newInstance(dtoFactory, ApplicationComponent.class, t));
+        }
+    }
+ 
+    private List<LinkDto> platformComponents;
+    private List<LinkDto> applicationComponents;
+
+    private String externalManagementUri;
+
+    @JsonInclude(Include.NON_EMPTY)
+    public List<LinkDto> getPlatformComponents() {
+        return platformComponents;
+    }
+    
+    @JsonInclude(Include.NON_EMPTY)
+    public List<LinkDto> getApplicationComponents() {
+        return applicationComponents;
+    } 
+    
+    @JsonInclude(Include.NON_EMPTY)
+    public String getExternalManagementUri() {
+        return externalManagementUri;
+    }
+    private void setExternalManagementUri(String externalManagementUri) {
+        this.externalManagementUri = externalManagementUri;
+    }
+    
+    // --- building ---
+
+    public static PlatformComponentDto newInstance(DtoFactory dtoFactory, PlatformComponent x) {
+        return new PlatformComponentDto(dtoFactory, x);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-server/src/main/java/io/brooklyn/camp/dto/PlatformComponentTemplateDto.java
----------------------------------------------------------------------
diff --git a/camp/camp-server/src/main/java/io/brooklyn/camp/dto/PlatformComponentTemplateDto.java b/camp/camp-server/src/main/java/io/brooklyn/camp/dto/PlatformComponentTemplateDto.java
new file mode 100644
index 0000000..b852d63
--- /dev/null
+++ b/camp/camp-server/src/main/java/io/brooklyn/camp/dto/PlatformComponentTemplateDto.java
@@ -0,0 +1,26 @@
+package io.brooklyn.camp.dto;
+
+import io.brooklyn.camp.rest.util.DtoFactory;
+import io.brooklyn.camp.spi.PlatformComponentTemplate;
+
+public class PlatformComponentTemplateDto extends ResourceDto {
+
+    // defined as a constant so can be used in Swagger REST API annotations
+    public static final String CLASS_NAME = "io.brooklyn.camp.dto.PlatformComponentTemplateDto";
+    static { assert CLASS_NAME.equals(PlatformComponentTemplateDto.class.getCanonicalName()); }
+ 
+    protected PlatformComponentTemplateDto() {}
+    protected PlatformComponentTemplateDto(DtoFactory dtoFactory, PlatformComponentTemplate x) {
+        super(dtoFactory, x);
+        // TODO set addl PCT fields
+    }
+ 
+    // TODO add addl PCT fields
+    
+    // --- building ---
+
+    public static PlatformComponentTemplateDto newInstance(DtoFactory dtoFactory, PlatformComponentTemplate x) {
+        return new PlatformComponentTemplateDto(dtoFactory, x);
+    }
+    
+}


[41/45] git commit: Merge pull request #2 from neykov/osgi

Posted by he...@apache.org.
Merge pull request #2 from neykov/osgi

Sample OSGi bundle defining empty entity and application.

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

Branch: refs/heads/master
Commit: 0fc710714e52a1aad9294d358e8bba75d155e1a2
Parents: 343fe33 b792276
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Jul 3 20:51:27 2014 +0300
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu Jul 3 20:51:27 2014 +0300

----------------------------------------------------------------------
 .../osgi/brooklyn-tests-osgi-entities-0.1.0.jar     | Bin 0 -> 4810 bytes
 1 file changed, 0 insertions(+), 0 deletions(-)
----------------------------------------------------------------------



[24/45] git commit: Merge remote-tracking branch 'sjcorbett/auto-deploy-bundles' into osgi2

Posted by he...@apache.org.
Merge remote-tracking branch 'sjcorbett/auto-deploy-bundles' into osgi2


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

Branch: refs/heads/master
Commit: 74ddd83b7a7563815618bb566643a3275da77481
Parents: 3e71512 7fec791
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Wed Jul 2 16:12:55 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Wed Jul 2 16:12:55 2014 +0100

----------------------------------------------------------------------
 .../catalog/internal/BasicBrooklynCatalog.java  | 32 +++++----
 .../catalog/internal/CatalogClasspathDo.java    | 49 +++++++-------
 .../brooklyn/catalog/internal/CatalogDo.java    | 30 ++++++---
 .../brooklyn/catalog/internal/CatalogDto.java   | 68 +++++++++++++++++---
 .../catalog/internal/CatalogDtoUtils.java       | 52 ---------------
 .../catalog/internal/CatalogItemDo.java         |  2 +-
 .../internal/CatalogItemDtoAbstract.java        |  4 ++
 .../catalog/internal/CatalogLibrariesDo.java    | 35 ++++++++++
 .../catalog/internal/CatalogLibrariesDto.java   |  7 +-
 .../brooklyn/management/ha/OsgiManager.java     | 10 +--
 .../internal/AbstractManagementContext.java     | 10 +--
 .../internal/ManagementContextInternal.java     |  6 +-
 .../src/main/java/brooklyn/util/osgi/Osgis.java | 15 +++--
 13 files changed, 190 insertions(+), 130 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/74ddd83b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------


[04/45] git commit: import of brooklyncentral/camp-server dependency to apache brooklyn project

Posted by he...@apache.org.
import of brooklyncentral/camp-server dependency to apache brooklyn project


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

Branch: refs/heads/master
Commit: d2191c9acb807c1092645e54fffed8f40f9decad
Parents: 9ca8250
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Jul 1 13:34:20 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Jul 1 13:34:20 2014 +0100

----------------------------------------------------------------------
 camp/camp-base/notes.txt                        |   64 ++
 camp/camp-base/pom.xml                          |   67 ++
 .../brooklyn/camp/AggregatingCampPlatform.java  |  113 ++
 .../io/brooklyn/camp/BasicCampPlatform.java     |  122 ++
 .../java/io/brooklyn/camp/CampPlatform.java     |   58 +
 .../camp/commontypes/RepresentationSkew.java    |    5 +
 .../io/brooklyn/camp/spi/AbstractResource.java  |  176 +++
 .../brooklyn/camp/spi/ApplicationComponent.java |   78 ++
 .../camp/spi/ApplicationComponentTemplate.java  |   39 +
 .../java/io/brooklyn/camp/spi/Assembly.java     |   94 ++
 .../io/brooklyn/camp/spi/AssemblyTemplate.java  |  102 ++
 .../main/java/io/brooklyn/camp/spi/Link.java    |   22 +
 .../io/brooklyn/camp/spi/PlatformComponent.java |   86 ++
 .../camp/spi/PlatformComponentTemplate.java     |   37 +
 .../brooklyn/camp/spi/PlatformRootSummary.java  |   55 +
 .../brooklyn/camp/spi/PlatformTransaction.java  |   28 +
 .../spi/collection/AbstractResourceLookup.java  |   17 +
 .../collection/AggregatingResourceLookup.java   |   38 +
 .../spi/collection/BasicResourceLookup.java     |   53 +
 .../camp/spi/collection/ResolvableLink.java     |   19 +
 .../camp/spi/collection/ResourceLookup.java     |   29 +
 .../AssemblyTemplateInstantiator.java           |   12 +
 .../BasicAssemblyTemplateInstantiator.java      |   18 +
 .../java/io/brooklyn/camp/spi/pdp/Artifact.java |   82 ++
 .../brooklyn/camp/spi/pdp/ArtifactContent.java  |   47 +
 .../camp/spi/pdp/ArtifactRequirement.java       |   55 +
 .../spi/pdp/AssemblyTemplateConstructor.java    |   76 ++
 .../brooklyn/camp/spi/pdp/DeploymentPlan.java   |   93 ++
 .../java/io/brooklyn/camp/spi/pdp/Service.java  |   77 ++
 .../camp/spi/pdp/ServiceCharacteristic.java     |   55 +
 .../brooklyn/camp/spi/resolve/PdpMatcher.java   |   33 +
 .../brooklyn/camp/spi/resolve/PdpProcessor.java |  154 +++
 .../camp/spi/resolve/PlanInterpreter.java       |   95 ++
 .../interpret/PlanInterpretationContext.java    |  134 +++
 .../interpret/PlanInterpretationNode.java       |  245 ++++
 .../main/java/io/brooklyn/util/yaml/Yamls.java  |   89 ++
 .../src/main/resources/logback-custom.xml       |    9 +
 .../pdp/DeploymentPlanToyInterpreterTest.java   |   96 ++
 .../io/brooklyn/camp/spi/pdp/PdpYamlTest.java   |   60 +
 .../web/MockAssemblyTemplateInstantiator.java   |   20 +
 .../camp/test/mock/web/MockWebPlatform.java     |   71 ++
 .../test/platform/BasicCampPlatformTest.java    |   69 ++
 .../camp/spi/pdp/pdp-single-artifact.yaml       |    9 +
 .../camp/spi/pdp/pdp-single-service.yaml        |   11 +
 .../pdp/yaml-sample-toy-interpreter-result.yaml |    4 +
 .../spi/pdp/yaml-sample-toy-interpreter.yaml    |   10 +
 camp/camp-server/pom.xml                        |  115 ++
 .../io/brooklyn/camp/CampRestResources.java     |   52 +
 .../main/java/io/brooklyn/camp/CampServer.java  |  167 +++
 .../java/io/brooklyn/camp/dto/ApiErrorDto.java  |  101 ++
 .../camp/dto/ApplicationComponentDto.java       |   54 +
 .../dto/ApplicationComponentTemplateDto.java    |   26 +
 .../java/io/brooklyn/camp/dto/AssemblyDto.java  |   59 +
 .../brooklyn/camp/dto/AssemblyTemplateDto.java  |   54 +
 .../main/java/io/brooklyn/camp/dto/DtoBase.java |   13 +
 .../brooklyn/camp/dto/DtoCustomAttributes.java  |   48 +
 .../main/java/io/brooklyn/camp/dto/LinkDto.java |   54 +
 .../brooklyn/camp/dto/PlatformComponentDto.java |   64 ++
 .../camp/dto/PlatformComponentTemplateDto.java  |   26 +
 .../java/io/brooklyn/camp/dto/PlatformDto.java  |  113 ++
 .../java/io/brooklyn/camp/dto/ResourceDto.java  |   94 ++
 .../rest/resource/AbstractCampRestResource.java |   38 +
 .../camp/rest/resource/ApidocRestResource.java  |   13 +
 .../ApplicationComponentRestResource.java       |   32 +
 ...pplicationComponentTemplateRestResource.java |   32 +
 .../rest/resource/AssemblyRestResource.java     |   34 +
 .../resource/AssemblyTemplateRestResource.java  |   70 ++
 .../resource/PlatformComponentRestResource.java |   32 +
 .../PlatformComponentTemplateRestResource.java  |   32 +
 .../rest/resource/PlatformRestResource.java     |   71 ++
 .../io/brooklyn/camp/rest/util/CampJsons.java   |   21 +
 .../camp/rest/util/CampRestContext.java         |   32 +
 .../brooklyn/camp/rest/util/CampRestGuavas.java |   14 +
 .../io/brooklyn/camp/rest/util/DtoFactory.java  |  158 +++
 .../camp/rest/util/WebResourceUtils.java        |   42 +
 .../ApplicationCompomentTemplateDtoTest.java    |   31 +
 .../java/io/brooklyn/camp/dto/BasicDtoTest.java |   72 ++
 .../java/io/brooklyn/camp/dto/LinkDtoTest.java  |   44 +
 .../dto/PlatformCompomentTemplateDtoTest.java   |   31 +
 .../io/brooklyn/camp/dto/ResourceDtoTest.java   |   59 +
 .../rest/resource/PlatformRestResourceTest.java |   24 +
 .../test/fixture/AbstractRestResourceTest.java  |   68 ++
 .../camp/test/fixture/InMemoryCamp.java         |   35 +
 camp/pom.xml                                    | 1060 ++++++++++++++++++
 84 files changed, 6011 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/notes.txt
----------------------------------------------------------------------
diff --git a/camp/camp-base/notes.txt b/camp/camp-base/notes.txt
new file mode 100644
index 0000000..7be3ba6
--- /dev/null
+++ b/camp/camp-base/notes.txt
@@ -0,0 +1,64 @@
+
+DONE
+
+SOME of these (for PCT's and ACT's)
+* dto classes and endpoints (jersey resources) to have a rest server
+* impl classes (abstract or composable?) which can make dto's
+* connect impl classes to brooklyn
+
+TODO
+
+* remaining classes
+* PDP formation
+
+
+
+
+
+
+THOUGHTS
+
+* get camp.io
+* project for camp-ops, camp-samp-le-server
+
+
+
+
+
+
+COMPARISON
+
+CAMP
+*   platform offers PlatformComponentTemplates (e.g. elasttic AppServer cluster) which a user can
+    stitch together in an AssemblyTemplate to create an Assembly which is their application;
+    user can also supply ApplicationComponentTemplate and ApplicationComponent instances
+    (e.g. WAR files) for use in assemblies;
+    and Requirements and Capabilities can be defined to e.g. indicate that a 3-tier app
+    Template requires a WAR file and a schema (from the user) and PlatformComponents
+    where these will run (from the platform) which get resolved at real-time 
+    with as little or as much guidance from the user as desired;
+    relies on conventions on types and tags (ie not specified in spec, yet) to facilitate re-use;
+*   defines REST API for interacting with these, and uploading assemblies and app components
+    (not platform components)
+*   example
+
+TOSCA
+    ServiceTemplate is the basic idea
+    Types
+        NodeType
+        RelationshipType
+    TopologyTemplate
+        NodeTemplate
+        RelationshipTemplate
+        GroupTemplate
+    internal elements
+        Artifacts:
+            "deployment artifacts" for creating nodes, 
+            "implementation artifacts" for operations)
+        Container capabilities / requirements
+        Properties, operations, scripts, constraints
+        Policies
+    Plans
+        Plan
+
+END

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/pom.xml
----------------------------------------------------------------------
diff --git a/camp/camp-base/pom.xml b/camp/camp-base/pom.xml
new file mode 100644
index 0000000..678fa69
--- /dev/null
+++ b/camp/camp-base/pom.xml
@@ -0,0 +1,67 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <packaging>bundle</packaging>
+
+    <artifactId>camp-base</artifactId>
+
+    <name>CAMP Base</name>
+    <description>
+        Core base classes for CAMP server implementation
+    </description>
+
+    <parent>
+        <groupId>io.brooklyn.camp</groupId>
+        <artifactId>camp-parent</artifactId>
+        <version>0.1.0-SNAPSHOT</version>  <!-- CAMP_IMPL_VERSION -->
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <dependencies>
+        <dependency>
+            <groupId>io.brooklyn</groupId>
+            <artifactId>brooklyn-utils-common</artifactId>
+            <version>${brooklyn.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.brooklyn</groupId>
+            <artifactId>brooklyn-test-support</artifactId>
+            <version>${brooklyn.version}</version>
+            <scope>tests</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>${commons-lang3.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-compress</artifactId>
+            <version>${commons-compress.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.yaml</groupId>
+            <artifactId>snakeyaml</artifactId>
+            <version>1.11</version>
+        </dependency>
+        
+            <!-- just for logging, not exported -->
+            <!-- 
+        <dependency>
+            <groupId>io.brooklyn</groupId>
+            <artifactId>brooklyn-logback-xml</artifactId>
+            <version>${brooklyn.version}</version>
+            <optional>true</optional>
+            <scope>tests</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.brooklyn</groupId>
+            <artifactId>brooklyn-core</artifactId>
+            <version>${brooklyn.version}</version>
+            <optional>true</optional>
+            <scope>tests</scope>
+        </dependency>
+             -->
+        
+    </dependencies>
+
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/AggregatingCampPlatform.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/AggregatingCampPlatform.java b/camp/camp-base/src/main/java/io/brooklyn/camp/AggregatingCampPlatform.java
new file mode 100644
index 0000000..a6caa73
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/AggregatingCampPlatform.java
@@ -0,0 +1,113 @@
+package io.brooklyn.camp;
+
+import io.brooklyn.camp.spi.AbstractResource;
+import io.brooklyn.camp.spi.ApplicationComponent;
+import io.brooklyn.camp.spi.ApplicationComponentTemplate;
+import io.brooklyn.camp.spi.Assembly;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+import io.brooklyn.camp.spi.PlatformComponent;
+import io.brooklyn.camp.spi.PlatformComponentTemplate;
+import io.brooklyn.camp.spi.PlatformRootSummary;
+import io.brooklyn.camp.spi.PlatformTransaction;
+import io.brooklyn.camp.spi.collection.AggregatingResourceLookup;
+import io.brooklyn.camp.spi.collection.ResourceLookup;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+
+/** A {@link CampPlatform} implementation which is empty but allows adding new items,
+ * as well as adding other platforms; meant for subclassing only */
+public class AggregatingCampPlatform extends CampPlatform {
+
+    private static final Logger log = LoggerFactory.getLogger(AggregatingCampPlatform.class);
+    
+    protected AggregatingCampPlatform(PlatformRootSummary root) {
+        this(root, new BasicCampPlatform(root));
+    }
+    
+    public AggregatingCampPlatform(PlatformRootSummary root, CampPlatform platformWhereTransactionsOccur) {
+        super(root);
+        log.debug("Creating {} with main platform: {}", this, platformWhereTransactionsOccur);
+        this.mainPlatform = platformWhereTransactionsOccur;
+    }
+    
+    /** platform where additions are made */
+    CampPlatform mainPlatform;
+    List<CampPlatform> otherPlatformsToSearch = new ArrayList<CampPlatform>();
+    
+    protected void addPlatform(CampPlatform platform) {
+        log.debug("Adding child platform to {}: {}", this, platform);
+        otherPlatformsToSearch.add(platform);
+    }
+    
+    protected <T extends AbstractResource> ResourceLookup<T> aggregatingLookup(Function<CampPlatform, ResourceLookup<T>> lookupFunction) {
+        List<ResourceLookup<T>> lookups = new ArrayList<ResourceLookup<T>>();
+        lookups.add(lookupFunction.apply(mainPlatform));
+        for (CampPlatform p: otherPlatformsToSearch)
+            lookups.add(lookupFunction.apply(p));
+        return AggregatingResourceLookup.of(lookups);
+    }
+    
+    public ResourceLookup<PlatformComponentTemplate> platformComponentTemplates() {
+        return aggregatingLookup(new Function<CampPlatform, ResourceLookup<PlatformComponentTemplate>>() {
+            public ResourceLookup<PlatformComponentTemplate> apply(@Nullable CampPlatform input) {
+                return input.platformComponentTemplates();
+            }
+        });
+    }
+
+    @Override
+    public ResourceLookup<ApplicationComponentTemplate> applicationComponentTemplates() {
+        return aggregatingLookup(new Function<CampPlatform, ResourceLookup<ApplicationComponentTemplate>>() {
+            public ResourceLookup<ApplicationComponentTemplate> apply(@Nullable CampPlatform input) {
+                return input.applicationComponentTemplates();
+            }
+        });
+    }
+
+    public ResourceLookup<AssemblyTemplate> assemblyTemplates() {
+        return aggregatingLookup(new Function<CampPlatform, ResourceLookup<AssemblyTemplate>>() {
+            public ResourceLookup<AssemblyTemplate> apply(@Nullable CampPlatform input) {
+                return input.assemblyTemplates();
+            }
+        });
+    }
+    
+    public ResourceLookup<PlatformComponent> platformComponents() {
+        return aggregatingLookup(new Function<CampPlatform, ResourceLookup<PlatformComponent>>() {
+            public ResourceLookup<PlatformComponent> apply(@Nullable CampPlatform input) {
+                return input.platformComponents();
+            }
+        });
+    }
+
+    @Override
+    public ResourceLookup<ApplicationComponent> applicationComponents() {
+        return aggregatingLookup(new Function<CampPlatform, ResourceLookup<ApplicationComponent>>() {
+            public ResourceLookup<ApplicationComponent> apply(@Nullable CampPlatform input) {
+                return input.applicationComponents();
+            }
+        });
+    }
+
+    public ResourceLookup<Assembly> assemblies() {
+        return aggregatingLookup(new Function<CampPlatform, ResourceLookup<Assembly>>() {
+            public ResourceLookup<Assembly> apply(@Nullable CampPlatform input) {
+                return input.assemblies();
+            }
+        });
+    }
+    
+    @Override
+    public PlatformTransaction transaction() {
+        return mainPlatform.transaction();
+    }
+        
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/BasicCampPlatform.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/BasicCampPlatform.java b/camp/camp-base/src/main/java/io/brooklyn/camp/BasicCampPlatform.java
new file mode 100644
index 0000000..0214c84
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/BasicCampPlatform.java
@@ -0,0 +1,122 @@
+package io.brooklyn.camp;
+
+import io.brooklyn.camp.spi.ApplicationComponent;
+import io.brooklyn.camp.spi.ApplicationComponentTemplate;
+import io.brooklyn.camp.spi.Assembly;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+import io.brooklyn.camp.spi.PlatformComponent;
+import io.brooklyn.camp.spi.PlatformComponentTemplate;
+import io.brooklyn.camp.spi.PlatformRootSummary;
+import io.brooklyn.camp.spi.PlatformTransaction;
+import io.brooklyn.camp.spi.collection.BasicResourceLookup;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** A {@link CampPlatform} implementation which is empty but allows adding new items */
+public class BasicCampPlatform extends CampPlatform {
+
+    private static final Logger log = LoggerFactory.getLogger(BasicCampPlatform.class);
+    
+    public BasicCampPlatform() {
+        this(PlatformRootSummary.builder().name("CAMP Platform").build());
+    }
+    
+    public BasicCampPlatform(PlatformRootSummary root) {
+        super(root);
+    }
+
+    BasicResourceLookup<PlatformComponentTemplate> platformComponentTemplates = new BasicResourceLookup<PlatformComponentTemplate>();
+    BasicResourceLookup<ApplicationComponentTemplate> applicationComponentTemplates = new BasicResourceLookup<ApplicationComponentTemplate>();
+    BasicResourceLookup<AssemblyTemplate> assemblyTemplates = new BasicResourceLookup<AssemblyTemplate>();
+
+    BasicResourceLookup<PlatformComponent> platformComponents = new BasicResourceLookup<PlatformComponent>();
+    BasicResourceLookup<ApplicationComponent> applicationComponents = new BasicResourceLookup<ApplicationComponent>();
+    BasicResourceLookup<Assembly> assemblies = new BasicResourceLookup<Assembly>();
+
+    public BasicResourceLookup<PlatformComponentTemplate> platformComponentTemplates() {
+        return platformComponentTemplates;
+    }
+
+    @Override
+    public BasicResourceLookup<ApplicationComponentTemplate> applicationComponentTemplates() {
+        return applicationComponentTemplates;
+    }
+
+    public BasicResourceLookup<AssemblyTemplate> assemblyTemplates() {
+        return assemblyTemplates;
+    }
+    
+    public BasicResourceLookup<PlatformComponent> platformComponents() {
+        return platformComponents;
+    }
+
+    @Override
+    public BasicResourceLookup<ApplicationComponent> applicationComponents() {
+        return applicationComponents;
+    }
+
+    public BasicResourceLookup<Assembly> assemblies() {
+        return assemblies;
+    }
+    
+    @Override
+    public PlatformTransaction transaction() {
+        return new BasicPlatformTransaction(this);
+    }
+    
+    public static class BasicPlatformTransaction extends PlatformTransaction {
+        private final BasicCampPlatform platform;
+        private final AtomicBoolean committed = new AtomicBoolean(false);
+        
+        public BasicPlatformTransaction(BasicCampPlatform platform) {
+            this.platform = platform;
+        }
+        
+        @Override
+        public void commit() {
+            if (committed.getAndSet(true)) 
+                throw new IllegalStateException("transaction being committed multiple times");
+            
+            for (Object o: additions) {
+                if (o instanceof AssemblyTemplate) {
+                    platform.assemblyTemplates.add((AssemblyTemplate) o);
+                    continue;
+                }
+                if (o instanceof PlatformComponentTemplate) {
+                    platform.platformComponentTemplates.add((PlatformComponentTemplate) o);
+                    continue;
+                }
+                if (o instanceof ApplicationComponentTemplate) {
+                    platform.applicationComponentTemplates.add((ApplicationComponentTemplate) o);
+                    continue;
+                }
+                
+                if (o instanceof Assembly) {
+                    platform.assemblies.add((Assembly) o);
+                    continue;
+                }
+                if (o instanceof PlatformComponent) {
+                    platform.platformComponents.add((PlatformComponent) o);
+                    continue;
+                }
+                if (o instanceof ApplicationComponent) {
+                    platform.applicationComponents.add((ApplicationComponent) o);
+                    continue;
+                }
+
+                throw new UnsupportedOperationException("Object "+o+" of type "+o.getClass()+" cannot be added to "+platform);
+            }
+        }
+        
+        @Override
+        protected void finalize() throws Throwable {
+            if (!committed.get())
+                log.warn("transaction "+this+" was never applied");
+            super.finalize();
+        }
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/CampPlatform.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/CampPlatform.java b/camp/camp-base/src/main/java/io/brooklyn/camp/CampPlatform.java
new file mode 100644
index 0000000..39c1751
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/CampPlatform.java
@@ -0,0 +1,58 @@
+package io.brooklyn.camp;
+
+import io.brooklyn.camp.spi.ApplicationComponent;
+import io.brooklyn.camp.spi.ApplicationComponentTemplate;
+import io.brooklyn.camp.spi.Assembly;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+import io.brooklyn.camp.spi.PlatformComponent;
+import io.brooklyn.camp.spi.PlatformComponentTemplate;
+import io.brooklyn.camp.spi.PlatformRootSummary;
+import io.brooklyn.camp.spi.PlatformTransaction;
+import io.brooklyn.camp.spi.collection.ResourceLookup;
+import io.brooklyn.camp.spi.resolve.PdpProcessor;
+
+import com.google.common.base.Preconditions;
+
+public abstract class CampPlatform {
+
+    private final PlatformRootSummary root;
+    private final PdpProcessor pdp;
+
+    public CampPlatform(PlatformRootSummary root) {
+        this.root = Preconditions.checkNotNull(root, "root");
+        pdp = createPdpProcessor();
+    }
+
+    // --- root
+    
+    public PlatformRootSummary root() {
+        return root;
+    }
+
+    // --- other aspects
+    
+    public PdpProcessor pdp() {
+        return pdp;
+    }
+
+    
+    // --- required custom implementation hooks
+    
+    public abstract ResourceLookup<PlatformComponentTemplate> platformComponentTemplates();
+    public abstract ResourceLookup<ApplicationComponentTemplate> applicationComponentTemplates();
+    public abstract ResourceLookup<AssemblyTemplate> assemblyTemplates();
+
+    public abstract ResourceLookup<PlatformComponent> platformComponents();
+    public abstract ResourceLookup<ApplicationComponent> applicationComponents();
+    public abstract ResourceLookup<Assembly> assemblies();
+
+    /** returns object where changes to a PDP can be made; note all changes must be committed */
+    public abstract PlatformTransaction transaction();
+
+    // --- optional customisation overrides
+    
+    protected PdpProcessor createPdpProcessor() {
+        return new PdpProcessor(this);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/commontypes/RepresentationSkew.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/commontypes/RepresentationSkew.java b/camp/camp-base/src/main/java/io/brooklyn/camp/commontypes/RepresentationSkew.java
new file mode 100644
index 0000000..02725ea
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/commontypes/RepresentationSkew.java
@@ -0,0 +1,5 @@
+package io.brooklyn.camp.commontypes;
+
+public enum RepresentationSkew {
+    CREATING, NONE, DESTROYING, UNKNOWN
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/AbstractResource.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/AbstractResource.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/AbstractResource.java
new file mode 100644
index 0000000..0fa50d2
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/AbstractResource.java
@@ -0,0 +1,176 @@
+package io.brooklyn.camp.spi;
+
+import io.brooklyn.camp.commontypes.RepresentationSkew;
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.text.Identifiers;
+import brooklyn.util.time.Time;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+/** Superclass of CAMP resource implementation objects.
+ * Typically used to hold common state of implementation objects
+ * and to populate the DTO's used by the REST API.
+ * <p>
+ * These class instances are typically created using the 
+ * static {@link #builder()} methods they contain. 
+ * The resulting instances are typically immutable,
+ * so where fields can change callers should use a new builder
+ * (or update an underlying data store).
+ * <p>
+ * This class is not meant to be instantiated directly, as
+ * CAMP only uses defined subclasses (ie containing these fields).
+ * It is instantiable for testing.
+ */
+public class AbstractResource {
+
+    public static final String CAMP_TYPE = "Resource";
+    
+    private String id = Identifiers.makeRandomId(8);
+    private String name;
+    private String type;
+    private String description;
+    private Date created = Time.dropMilliseconds(new Date());
+    private List<String> tags = Collections.emptyList();
+    private RepresentationSkew representationSkew;
+    
+    private Map<String,Object> customAttributes = new MutableMap<String, Object>();
+    
+    /** Use {@link #builder()} to create */
+    protected AbstractResource() {}
+    
+    // getters
+
+    public String getId() {
+        return id;
+    }
+    public String getName() {
+        return name;
+    }
+    public String getType() {
+        return type;
+    }
+    public String getDescription() {
+        return description;
+    }
+    public Date getCreated() {
+        return created;
+    }
+    public List<String> getTags() {
+        return tags;
+    }
+    public RepresentationSkew getRepresentationSkew() {
+        return representationSkew;
+    }
+    public Map<String, Object> getCustomAttributes() {
+        return ImmutableMap.copyOf(customAttributes);
+    }
+    
+    // setters
+
+    private void setId(String id) {
+        this.id = id;
+    }
+    private void setName(String name) {
+        this.name = name;
+    }
+    private void setDescription(String description) {
+        this.description = description;
+    }
+    private void setCreated(Date created) {
+        // precision beyond seconds breaks equals check
+        this.created = Time.dropMilliseconds(created);
+    }
+    private void setTags(List<String> tags) {
+        this.tags = ImmutableList.copyOf(tags);
+    }
+    private void setType(String type) {
+        this.type = type;
+    }
+    private void setRepresentationSkew(RepresentationSkew representationSkew) {
+        this.representationSkew = representationSkew;
+    }
+    public void setCustomAttribute(String key, Object value) {
+        this.customAttributes.put(key, value);
+    }
+            
+    // builder
+    @SuppressWarnings("rawtypes")
+    public static Builder<? extends AbstractResource,? extends Builder> builder() {
+        return new AbstractResourceBuilder(CAMP_TYPE);
+    }
+    
+    /** Builder creates the instance up front to avoid repetition of fields in the builder;
+     * but prevents object leakage until build and prevents changes after build,
+     * so effectively immutable.
+     * <p>
+     * Similarly setters in the class are private so those objects are also typically effectively immutable. */
+    public abstract static class Builder<T extends AbstractResource,U extends Builder<T,U>> {
+        
+        private boolean built = false;
+        private String type = null;
+        private T instance = null;
+        
+        protected Builder(String type) {
+            this.type = type;
+        }
+        
+        @SuppressWarnings("unchecked")
+        protected T createResource() {
+            return (T) new AbstractResource();
+        }
+        
+        protected synchronized T instance() {
+            if (built) 
+                throw new IllegalStateException("Builder instance from "+this+" cannot be access after build");
+            if (instance==null) {
+                instance = createResource();
+                initialize();
+            }
+            return instance;
+        }
+
+        protected void initialize() {
+            if (type!=null) type(type);
+        }
+        
+        public synchronized T build() {
+            T result = instance();
+            built = true;
+            return result;
+        }
+        
+        @SuppressWarnings("unchecked")
+        protected U thisBuilder() { return (U)this; }
+        
+        public U type(String x) { instance().setType(x); return thisBuilder(); }
+        public U id(String x) { instance().setId(x); return thisBuilder(); }
+        public U name(String x) { instance().setName(x); return thisBuilder(); }
+        public U description(String x) { instance().setDescription(x); return thisBuilder(); }
+        public U created(Date x) { instance().setCreated(x); return thisBuilder(); }
+        public U tags(List<String> x) { instance().setTags(x); return thisBuilder(); }
+        public U representationSkew(RepresentationSkew x) { instance().setRepresentationSkew(x); return thisBuilder(); }
+        public U customAttribute(String key, Object value) { instance().setCustomAttribute(key, value); return thisBuilder(); }
+        
+//        public String type() { return instance().type; }
+    }
+
+    @VisibleForTesting
+    protected static class AbstractResourceBuilder extends Builder<AbstractResource,AbstractResourceBuilder> {
+        protected AbstractResourceBuilder(String type) {
+            super(type);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return super.toString()+"[id="+getId()+"; type="+getType()+"]";
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/ApplicationComponent.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/ApplicationComponent.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/ApplicationComponent.java
new file mode 100644
index 0000000..5e24adb
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/ApplicationComponent.java
@@ -0,0 +1,78 @@
+package io.brooklyn.camp.spi;
+
+import io.brooklyn.camp.spi.collection.BasicResourceLookup;
+import io.brooklyn.camp.spi.collection.ResourceLookup;
+import io.brooklyn.camp.spi.collection.ResourceLookup.EmptyResourceLookup;
+
+
+/** Holds the metadata (name, description, etc) for a PCT
+ * as well as fields pointing to behaviour (eg creation of PlatformComponent).
+ * <p>
+ * See {@link AbstractResource} for more general information.
+ */
+public class ApplicationComponent extends AbstractResource {
+
+    public static final String CAMP_TYPE = "ApplicationComponent";
+    static { assert CAMP_TYPE.equals(ApplicationComponent.class.getSimpleName()); }
+    
+    /** Use {@link #builder()} to create */
+    protected ApplicationComponent() {}
+
+    ResourceLookup<ApplicationComponent> applicationComponents;
+    ResourceLookup<PlatformComponent> platformComponents;
+    String externalManagementUri;
+    
+    public ResourceLookup<ApplicationComponent> getApplicationComponents() {
+        return applicationComponents != null ? applicationComponents : new EmptyResourceLookup<ApplicationComponent>();
+    }
+    public ResourceLookup<PlatformComponent> getPlatformComponents() {
+        return platformComponents != null ? platformComponents : new EmptyResourceLookup<PlatformComponent>();
+    }
+
+    private void setApplicationComponents(ResourceLookup<ApplicationComponent> applicationComponents) {
+        this.applicationComponents = applicationComponents;
+    }
+    private void setPlatformComponents(ResourceLookup<PlatformComponent> platformComponents) {
+        this.platformComponents = platformComponents;
+    }
+    
+    // builder
+    
+    public static Builder<? extends ApplicationComponent> builder() {
+        return new Builder<ApplicationComponent>(CAMP_TYPE);
+    }
+    
+    public static class Builder<T extends ApplicationComponent> extends AbstractResource.Builder<T,Builder<T>> {
+        
+        protected Builder(String type) { super(type); }
+
+        public Builder<T> applicationComponentTemplates(ResourceLookup<ApplicationComponent> x) { instance().setApplicationComponents(x); return thisBuilder(); }
+        public Builder<T> platformComponentTemplates(ResourceLookup<PlatformComponent> x) { instance().setPlatformComponents(x); return thisBuilder(); }
+        
+        public synchronized Builder<T> add(ApplicationComponent x) {
+            if (instance().applicationComponents==null) {
+                instance().applicationComponents = new BasicResourceLookup<ApplicationComponent>();
+            }
+            if (!(instance().applicationComponents instanceof BasicResourceLookup)) {
+                throw new IllegalStateException("Cannot add to resource lookup "+instance().applicationComponents);
+            }
+            ((BasicResourceLookup<ApplicationComponent>)instance().applicationComponents).add(x);
+            return thisBuilder();
+        }
+        
+        public synchronized Builder<T> add(PlatformComponent x) {
+            if (instance().platformComponents==null) {
+                instance().platformComponents = new BasicResourceLookup<PlatformComponent>();
+            }
+            if (!(instance().platformComponents instanceof BasicResourceLookup)) {
+                throw new IllegalStateException("Cannot add to resource lookup "+instance().platformComponents);
+            }
+            ((BasicResourceLookup<PlatformComponent>)instance().platformComponents).add(x);
+            return thisBuilder();
+        }
+
+        @SuppressWarnings("unchecked")
+        protected T createResource() { return (T) new ApplicationComponent(); }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/ApplicationComponentTemplate.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/ApplicationComponentTemplate.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/ApplicationComponentTemplate.java
new file mode 100644
index 0000000..36af06a
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/ApplicationComponentTemplate.java
@@ -0,0 +1,39 @@
+package io.brooklyn.camp.spi;
+
+
+/** Holds the metadata (name, description, etc) for a PCT
+ * as well as fields pointing to behaviour (eg creation of PlatformComponent).
+ * <p>
+ * See {@link AbstractResource} for more general information.
+ */
+public class ApplicationComponentTemplate extends AbstractResource {
+
+    public static final String CAMP_TYPE = "ApplicationComponentTemplate";
+    static { assert CAMP_TYPE.equals(ApplicationComponentTemplate.class.getSimpleName()); }
+    
+    /** Use {@link #builder()} to create */
+    protected ApplicationComponentTemplate() {}
+
+    
+    // no fields beyond basic resource
+    
+    // TODO platform component templates, maybe other act's too ?
+    
+    
+    // builder
+    
+    public static Builder<? extends ApplicationComponentTemplate> builder() {
+        return new Builder<ApplicationComponentTemplate>(CAMP_TYPE);
+    }
+    
+    public static class Builder<T extends ApplicationComponentTemplate> extends AbstractResource.Builder<T,Builder<T>> {
+        
+        protected Builder(String type) { super(type); }
+        
+        @SuppressWarnings("unchecked")
+        protected T createResource() { return (T) new ApplicationComponentTemplate(); }
+        
+//        public Builder<T> foo(String x) { instance().setFoo(x); return thisBuilder(); }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/Assembly.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/Assembly.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/Assembly.java
new file mode 100644
index 0000000..719e88f
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/Assembly.java
@@ -0,0 +1,94 @@
+package io.brooklyn.camp.spi;
+
+import io.brooklyn.camp.spi.collection.BasicResourceLookup;
+import io.brooklyn.camp.spi.collection.ResourceLookup;
+import io.brooklyn.camp.spi.collection.ResourceLookup.EmptyResourceLookup;
+
+
+/** Holds the metadata (name, description, etc) for an AssemblyTemplate
+ * as well as fields pointing to behaviour (eg list of ACT's).
+ * <p>
+ * See {@link AbstractResource} for more general information.
+ */
+public class Assembly extends AbstractResource {
+
+    public static final String CAMP_TYPE = "Assembly";
+    static { assert CAMP_TYPE.equals(Assembly.class.getSimpleName()); }
+    
+    /** Use {@link #builder()} to create */
+    protected Assembly() {}
+
+    AssemblyTemplate assemblyTemplate;
+    ResourceLookup<ApplicationComponent> applicationComponents;
+    ResourceLookup<PlatformComponent> platformComponents;
+    
+    // TODO
+//    "parameterDefinitionUri": URI,
+//    "pdpUri" : URI ?
+                    
+    public AssemblyTemplate getAssemblyTemplate() {
+        return assemblyTemplate;
+    }
+    public ResourceLookup<ApplicationComponent> getApplicationComponents() {
+        return applicationComponents != null ? applicationComponents : new EmptyResourceLookup<ApplicationComponent>();
+    }
+    public ResourceLookup<PlatformComponent> getPlatformComponents() {
+        return platformComponents != null ? platformComponents : new EmptyResourceLookup<PlatformComponent>();
+    }
+    
+    private void setAssemblyTemplate(AssemblyTemplate assemblyTemplate) {
+        this.assemblyTemplate = assemblyTemplate;
+    }
+    private void setApplicationComponents(ResourceLookup<ApplicationComponent> applicationComponents) {
+        this.applicationComponents = applicationComponents;
+    }
+    private void setPlatformComponents(ResourceLookup<PlatformComponent> platformComponents) {
+        this.platformComponents = platformComponents;
+    }
+    
+    // builder
+    
+    public static Builder<? extends Assembly> builder() {
+        return new Builder<Assembly>(CAMP_TYPE);
+    }
+    
+    public static class Builder<T extends Assembly> extends AbstractResource.Builder<T,Builder<T>> {
+        
+        protected Builder(String type) { super(type); }
+        
+        @SuppressWarnings("unchecked")
+        protected T createResource() { return (T) new Assembly(); }
+        
+        public Builder<T> assemblyTemplate(AssemblyTemplate x) { instance().setAssemblyTemplate(x); return thisBuilder(); }
+        public Builder<T> applicationComponentTemplates(ResourceLookup<ApplicationComponent> x) { instance().setApplicationComponents(x); return thisBuilder(); }
+        public Builder<T> platformComponentTemplates(ResourceLookup<PlatformComponent> x) { instance().setPlatformComponents(x); return thisBuilder(); }
+        
+        public synchronized Builder<T> add(ApplicationComponent x) {
+            if (instance().applicationComponents==null) {
+                instance().applicationComponents = new BasicResourceLookup<ApplicationComponent>();
+            }
+            if (!(instance().applicationComponents instanceof BasicResourceLookup)) {
+                throw new IllegalStateException("Cannot add to resource lookup "+instance().applicationComponents);
+            }
+            ((BasicResourceLookup<ApplicationComponent>)instance().applicationComponents).add(x);
+            return thisBuilder();
+        }
+        
+        public synchronized Builder<T> add(PlatformComponent x) {
+            if (instance().platformComponents==null) {
+                instance().platformComponents = new BasicResourceLookup<PlatformComponent>();
+            }
+            if (!(instance().platformComponents instanceof BasicResourceLookup)) {
+                throw new IllegalStateException("Cannot add to resource lookup "+instance().platformComponents);
+            }
+            ((BasicResourceLookup<PlatformComponent>)instance().platformComponents).add(x);
+            return thisBuilder();
+        }
+        
+        @Override
+        public synchronized T build() {
+            return super.build();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/AssemblyTemplate.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/AssemblyTemplate.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/AssemblyTemplate.java
new file mode 100644
index 0000000..274f2be
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/AssemblyTemplate.java
@@ -0,0 +1,102 @@
+package io.brooklyn.camp.spi;
+
+import com.google.common.base.Preconditions;
+
+import io.brooklyn.camp.spi.collection.BasicResourceLookup;
+import io.brooklyn.camp.spi.collection.ResourceLookup;
+import io.brooklyn.camp.spi.collection.ResourceLookup.EmptyResourceLookup;
+import io.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
+
+
+/** Holds the metadata (name, description, etc) for an AssemblyTemplate
+ * as well as fields pointing to behaviour (eg list of ACT's).
+ * <p>
+ * See {@link AbstractResource} for more general information.
+ */
+public class AssemblyTemplate extends AbstractResource {
+
+    public static final String CAMP_TYPE = "AssemblyTemplate";
+    static { assert CAMP_TYPE.equals(AssemblyTemplate.class.getSimpleName()); }
+    
+    Class<? extends AssemblyTemplateInstantiator> instantiator;
+    ResourceLookup<ApplicationComponentTemplate> applicationComponentTemplates;
+    ResourceLookup<PlatformComponentTemplate> platformComponentTemplates;
+    
+    // TODO
+//    "parameterDefinitionUri": URI,
+//    "pdpUri" : URI ?
+                    
+    /** Use {@link #builder()} to create */
+    protected AssemblyTemplate() {}
+
+    public Class<? extends AssemblyTemplateInstantiator> getInstantiator() {
+        return instantiator;
+    }
+    public ResourceLookup<ApplicationComponentTemplate> getApplicationComponentTemplates() {
+        return applicationComponentTemplates != null ? applicationComponentTemplates : new EmptyResourceLookup<ApplicationComponentTemplate>();
+    }
+    public ResourceLookup<PlatformComponentTemplate> getPlatformComponentTemplates() {
+        return platformComponentTemplates != null ? platformComponentTemplates : new EmptyResourceLookup<PlatformComponentTemplate>();
+    }
+    
+    private void setInstantiator(Class<? extends AssemblyTemplateInstantiator> instantiator) {
+        this.instantiator = instantiator;
+    }
+    private void setApplicationComponentTemplates(ResourceLookup<ApplicationComponentTemplate> applicationComponentTemplates) {
+        this.applicationComponentTemplates = applicationComponentTemplates;
+    }
+    private void setPlatformComponentTemplates(ResourceLookup<PlatformComponentTemplate> platformComponentTemplates) {
+        this.platformComponentTemplates = platformComponentTemplates;
+    }
+    
+    // builder
+    
+    public static Builder<? extends AssemblyTemplate> builder() {
+        return new Builder<AssemblyTemplate>(CAMP_TYPE);
+    }
+    
+    public static class Builder<T extends AssemblyTemplate> extends AbstractResource.Builder<T,Builder<T>> {
+        
+        protected Builder(String type) { super(type); }
+        
+        @SuppressWarnings("unchecked")
+        protected T createResource() { return (T) new AssemblyTemplate(); }
+        
+        public Builder<T> instantiator(Class<? extends AssemblyTemplateInstantiator> x) { instance().setInstantiator(x); return thisBuilder(); }
+        public Builder<T> applicationComponentTemplates(ResourceLookup<ApplicationComponentTemplate> x) { instance().setApplicationComponentTemplates(x); return thisBuilder(); }
+        public Builder<T> platformComponentTemplates(ResourceLookup<PlatformComponentTemplate> x) { instance().setPlatformComponentTemplates(x); return thisBuilder(); }
+
+        /** allows callers to see the partially formed instance when needed, for example to query instantiators;
+         *  could be replaced by specific methods as and when that is preferred */
+        public T peek() { return instance(); }
+        
+        public synchronized Builder<T> add(ApplicationComponentTemplate x) {
+            if (instance().applicationComponentTemplates==null) {
+                instance().applicationComponentTemplates = new BasicResourceLookup<ApplicationComponentTemplate>();
+            }
+            if (!(instance().applicationComponentTemplates instanceof BasicResourceLookup)) {
+                throw new IllegalStateException("Cannot add to resource lookup "+instance().applicationComponentTemplates);
+            }
+            ((BasicResourceLookup<ApplicationComponentTemplate>)instance().applicationComponentTemplates).add(x);
+            return thisBuilder();
+        }
+        
+        public synchronized Builder<T> add(PlatformComponentTemplate x) {
+            if (instance().platformComponentTemplates==null) {
+                instance().platformComponentTemplates = new BasicResourceLookup<PlatformComponentTemplate>();
+            }
+            if (!(instance().platformComponentTemplates instanceof BasicResourceLookup)) {
+                throw new IllegalStateException("Cannot add to resource lookup "+instance().platformComponentTemplates);
+            }
+            ((BasicResourceLookup<PlatformComponentTemplate>)instance().platformComponentTemplates).add(x);
+            return thisBuilder();
+        }
+        
+        @Override
+        public synchronized T build() {
+            Preconditions.checkNotNull(instance().instantiator);
+            return super.build();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/Link.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/Link.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/Link.java
new file mode 100644
index 0000000..21058a3
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/Link.java
@@ -0,0 +1,22 @@
+package io.brooklyn.camp.spi;
+
+public class Link<T> {
+
+    private final String id;
+    private final String name;
+    
+    public Link(String id, String name) {
+        super();
+        this.id = id;
+        this.name = name;
+    }
+
+    public String getId() {
+        return id;
+    }
+    
+    public String getName() {
+        return name;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/PlatformComponent.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/PlatformComponent.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/PlatformComponent.java
new file mode 100644
index 0000000..326e7a9
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/PlatformComponent.java
@@ -0,0 +1,86 @@
+package io.brooklyn.camp.spi;
+
+import io.brooklyn.camp.spi.collection.BasicResourceLookup;
+import io.brooklyn.camp.spi.collection.ResourceLookup;
+import io.brooklyn.camp.spi.collection.ResourceLookup.EmptyResourceLookup;
+
+
+/** Holds the metadata (name, description, etc) for a PCT
+ * as well as fields pointing to behaviour (eg creation of PlatformComponent).
+ * <p>
+ * See {@link AbstractResource} for more general information.
+ */
+public class PlatformComponent extends AbstractResource {
+
+    public static final String CAMP_TYPE = "PlatformComponent";
+    static { assert CAMP_TYPE.equals(PlatformComponent.class.getSimpleName()); }
+    
+    /** Use {@link #builder()} to create */
+    protected PlatformComponent() {}
+
+    ResourceLookup<ApplicationComponent> applicationComponents;
+    ResourceLookup<PlatformComponent> platformComponents;
+    String externalManagementUri;
+    
+    public ResourceLookup<ApplicationComponent> getApplicationComponents() {
+        return applicationComponents != null ? applicationComponents : new EmptyResourceLookup<ApplicationComponent>();
+    }
+    public ResourceLookup<PlatformComponent> getPlatformComponents() {
+        return platformComponents != null ? platformComponents : new EmptyResourceLookup<PlatformComponent>();
+    }
+
+    private void setApplicationComponents(ResourceLookup<ApplicationComponent> applicationComponents) {
+        this.applicationComponents = applicationComponents;
+    }
+    private void setPlatformComponents(ResourceLookup<PlatformComponent> platformComponents) {
+        this.platformComponents = platformComponents;
+    }
+    
+    public String getExternalManagementUri() {
+        return externalManagementUri;
+    }
+    private void setExternalManagementUri(String externalManagementUri) {
+        this.externalManagementUri = externalManagementUri;
+    }
+    
+    // builder
+    
+    public static Builder<? extends PlatformComponent> builder() {
+        return new Builder<PlatformComponent>(CAMP_TYPE);
+    }
+    
+    public static class Builder<T extends PlatformComponent> extends AbstractResource.Builder<T,Builder<T>> {
+        
+        protected Builder(String type) { super(type); }
+        
+        public Builder<T> externalManagementUri(String x) { instance().setExternalManagementUri(x); return thisBuilder(); }
+        public Builder<T> applicationComponentTemplates(ResourceLookup<ApplicationComponent> x) { instance().setApplicationComponents(x); return thisBuilder(); }
+        public Builder<T> platformComponentTemplates(ResourceLookup<PlatformComponent> x) { instance().setPlatformComponents(x); return thisBuilder(); }
+        
+        public synchronized Builder<T> add(ApplicationComponent x) {
+            if (instance().applicationComponents==null) {
+                instance().applicationComponents = new BasicResourceLookup<ApplicationComponent>();
+            }
+            if (!(instance().applicationComponents instanceof BasicResourceLookup)) {
+                throw new IllegalStateException("Cannot add to resource lookup "+instance().applicationComponents);
+            }
+            ((BasicResourceLookup<ApplicationComponent>)instance().applicationComponents).add(x);
+            return thisBuilder();
+        }
+        
+        public synchronized Builder<T> add(PlatformComponent x) {
+            if (instance().platformComponents==null) {
+                instance().platformComponents = new BasicResourceLookup<PlatformComponent>();
+            }
+            if (!(instance().platformComponents instanceof BasicResourceLookup)) {
+                throw new IllegalStateException("Cannot add to resource lookup "+instance().platformComponents);
+            }
+            ((BasicResourceLookup<PlatformComponent>)instance().platformComponents).add(x);
+            return thisBuilder();
+        }
+
+        @SuppressWarnings("unchecked")
+        protected T createResource() { return (T) new PlatformComponent(); }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/PlatformComponentTemplate.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/PlatformComponentTemplate.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/PlatformComponentTemplate.java
new file mode 100644
index 0000000..cf8b9e5
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/PlatformComponentTemplate.java
@@ -0,0 +1,37 @@
+package io.brooklyn.camp.spi;
+
+
+/** Holds the metadata (name, description, etc) for a PCT
+ * as well as fields pointing to behaviour (eg creation of PlatformComponent).
+ * <p>
+ * See {@link AbstractResource} for more general information.
+ */
+public class PlatformComponentTemplate extends AbstractResource {
+
+    public static final String CAMP_TYPE = "PlatformComponentTemplate";
+    static { assert CAMP_TYPE.equals(PlatformComponentTemplate.class.getSimpleName()); }
+    
+    /** Use {@link #builder()} to create */
+    protected PlatformComponentTemplate() {}
+
+    
+    // no fields beyond basic resource
+    
+    
+    // builder
+    
+    public static Builder<? extends PlatformComponentTemplate> builder() {
+        return new Builder<PlatformComponentTemplate>(CAMP_TYPE);
+    }
+    
+    public static class Builder<T extends PlatformComponentTemplate> extends AbstractResource.Builder<T,Builder<T>> {
+        
+        protected Builder(String type) { super(type); }
+        
+        @SuppressWarnings("unchecked")
+        protected T createResource() { return (T) new PlatformComponentTemplate(); }
+        
+//        public Builder<T> foo(String x) { instance().setFoo(x); return thisBuilder(); }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/PlatformRootSummary.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/PlatformRootSummary.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/PlatformRootSummary.java
new file mode 100644
index 0000000..1ee2fc5
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/PlatformRootSummary.java
@@ -0,0 +1,55 @@
+package io.brooklyn.camp.spi;
+
+/** Holds the metadata (name, description, etc) for a CampPlatform.
+ * Required to initialize a CampPlatform.
+ * <p>
+ * See {@link AbstractResource} for more general information.
+ */
+public class PlatformRootSummary extends AbstractResource {
+
+    public static final String CAMP_TYPE = "Platform";
+    
+    /** Use {@link #builder()} to create */
+    protected PlatformRootSummary() {
+    }
+    
+    // no fields beyond basic resource
+    
+    //TODO:
+    
+    // in the DTO
+    
+//    "supportedFormatsUri": URI, 
+//    "extensionsUri": URI,
+//    "typeDefinitionsUri": URI,
+//    "tags": [ String, + ], ?
+//    "specificationVersion": String[], 
+//    "implementationVersion": String, ? 
+//    "assemblyTemplates": [ Link + ], ? 
+//    "assemblies": [ Link + ], ? 
+//    "platformComponentTemplates": [ Link + ], ? 
+//    "platformComponentCapabilities": [Link + ], ? 
+//    "platformComponents": [ Link + ], ?
+
+    
+    // builder
+    
+    public static Builder<? extends PlatformRootSummary> builder() {
+        return new Builder<PlatformRootSummary>(CAMP_TYPE);
+    }
+    
+    public static class Builder<T extends PlatformRootSummary> extends AbstractResource.Builder<T,Builder<T>> {
+        
+        protected Builder(String type) { super(type); }
+        
+        @SuppressWarnings("unchecked")
+        protected T createResource() { return (T) new PlatformRootSummary(); }
+        
+        protected void initialize() {
+            super.initialize();
+            // TODO a better way not to have an ID here (new subclass BasicIdentifiableResource for other BasicResource instances)
+            id("");
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/PlatformTransaction.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/PlatformTransaction.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/PlatformTransaction.java
new file mode 100644
index 0000000..c7f9490
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/PlatformTransaction.java
@@ -0,0 +1,28 @@
+package io.brooklyn.camp.spi;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class PlatformTransaction {
+
+    protected List<Object> additions = new ArrayList<Object>();
+    
+    /** apply the transaction */
+    public abstract void commit();
+    
+    public PlatformTransaction add(AssemblyTemplate at) {
+        additions.add(at);
+        return this;
+    }
+
+    public PlatformTransaction add(ApplicationComponentTemplate act) {
+        additions.add(act);
+        return this;
+    }
+
+    public PlatformTransaction add(PlatformComponentTemplate pct) {
+        additions.add(pct);
+        return this;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/collection/AbstractResourceLookup.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/collection/AbstractResourceLookup.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/collection/AbstractResourceLookup.java
new file mode 100644
index 0000000..8abe410
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/collection/AbstractResourceLookup.java
@@ -0,0 +1,17 @@
+package io.brooklyn.camp.spi.collection;
+
+import io.brooklyn.camp.spi.AbstractResource;
+
+public abstract class AbstractResourceLookup<T extends AbstractResource> implements ResourceLookup<T> {
+
+    /** convenience for concrete subclasses */
+    protected ResolvableLink<T> newLink(String id, String name) {
+        return new ResolvableLink<T>(id, name, this);
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return links().isEmpty();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/collection/AggregatingResourceLookup.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/collection/AggregatingResourceLookup.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/collection/AggregatingResourceLookup.java
new file mode 100644
index 0000000..00d759a
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/collection/AggregatingResourceLookup.java
@@ -0,0 +1,38 @@
+package io.brooklyn.camp.spi.collection;
+
+import io.brooklyn.camp.spi.AbstractResource;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class AggregatingResourceLookup<T extends AbstractResource> extends AbstractResourceLookup<T> {
+
+    List<ResourceLookup<T>> targets = new ArrayList<ResourceLookup<T>>();
+    
+    public static <T extends AbstractResource> AggregatingResourceLookup<T> of(ResourceLookup<T> ...targets) {
+        AggregatingResourceLookup<T> result = new AggregatingResourceLookup<T>();
+        for (ResourceLookup<T> item: targets) result.targets.add(item);
+        return result;
+    }
+    
+    public static <T extends AbstractResource> AggregatingResourceLookup<T> of(Iterable<ResourceLookup<T>> targets) {
+        AggregatingResourceLookup<T> result = new AggregatingResourceLookup<T>();
+        for (ResourceLookup<T> item: targets) result.targets.add(item);
+        return result;        
+    }
+
+    public T get(String id) {
+        for (ResourceLookup<T> item: targets) {
+            T result = item.get(id);
+            if (result!=null) return result;
+        }
+        return null;
+    }
+
+    public List<ResolvableLink<T>> links() {
+        List<ResolvableLink<T>> result = new ArrayList<ResolvableLink<T>>();
+        for (ResourceLookup<T> item: targets) result.addAll(item.links());
+        return result;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/collection/BasicResourceLookup.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/collection/BasicResourceLookup.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/collection/BasicResourceLookup.java
new file mode 100644
index 0000000..0621f60
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/collection/BasicResourceLookup.java
@@ -0,0 +1,53 @@
+package io.brooklyn.camp.spi.collection;
+
+import io.brooklyn.camp.spi.AbstractResource;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import brooklyn.util.collections.MutableMap;
+
+public class BasicResourceLookup<T extends AbstractResource> extends AbstractResourceLookup<T> {
+
+    Map<String,T> items = new MutableMap<String,T>();
+    Map<String,ResolvableLink<T>> links = new MutableMap<String,ResolvableLink<T>>();
+    
+    public T get(String id) {
+        return items.get(id);
+    }
+
+    public synchronized List<ResolvableLink<T>> links() {
+        return new ArrayList<ResolvableLink<T>>(links.values());
+    }
+
+    public synchronized void add(T item) {
+        T old = items.put(item.getId(), item);
+        if (old!=null) {
+            items.put(old.getId(), old);
+            throw new IllegalStateException("Already contains item for "+item.getId()+": "+old+" (adding "+item+")");
+        }
+        links.put(item.getId(), newLink(item.getId(), item.getName()));
+    }
+    
+    public synchronized void addAll(T... items) {
+        for (T item: items) add(item);
+    }
+    
+    public synchronized T update(T item) {
+        T old = items.put(item.getId(), item);
+        links.put(item.getId(), newLink(item.getId(), item.getName()));
+        return old;
+    }
+    
+    public synchronized boolean remove(String id) {
+        items.remove(id);
+        return links.remove(id)!=null;
+    }
+    
+    public static <T extends AbstractResource> BasicResourceLookup<T> of(T ...items) {
+        BasicResourceLookup<T> result = new BasicResourceLookup<T>();
+        for (T item: items) result.add(item);
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/collection/ResolvableLink.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/collection/ResolvableLink.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/collection/ResolvableLink.java
new file mode 100644
index 0000000..0899692
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/collection/ResolvableLink.java
@@ -0,0 +1,19 @@
+package io.brooklyn.camp.spi.collection;
+
+import io.brooklyn.camp.spi.AbstractResource;
+import io.brooklyn.camp.spi.Link;
+
+public class ResolvableLink<T extends AbstractResource> extends Link<T> {
+    
+    protected final ResourceLookup<T> provider;
+    
+    public ResolvableLink(String id, String name, ResourceLookup<T> provider) {
+        super(id, name);
+        this.provider = provider;
+    }
+
+    public T resolve() {
+        return provider.get(getId());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/collection/ResourceLookup.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/collection/ResourceLookup.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/collection/ResourceLookup.java
new file mode 100644
index 0000000..577896a
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/collection/ResourceLookup.java
@@ -0,0 +1,29 @@
+package io.brooklyn.camp.spi.collection;
+
+import io.brooklyn.camp.spi.AbstractResource;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+public interface ResourceLookup<T extends AbstractResource> {
+
+    public abstract T get(String id);
+    
+    public abstract List<ResolvableLink<T>> links();
+    
+    public abstract boolean isEmpty();
+
+    public static class EmptyResourceLookup<T extends AbstractResource> implements ResourceLookup<T> {
+        public T get(String id) {
+            throw new NoSuchElementException("no resource: "+id);
+        }
+        public List<ResolvableLink<T>> links() {
+            return Collections.emptyList();
+        }
+        public boolean isEmpty() {
+            return links().isEmpty();
+        }
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/instantiate/AssemblyTemplateInstantiator.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/instantiate/AssemblyTemplateInstantiator.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/instantiate/AssemblyTemplateInstantiator.java
new file mode 100644
index 0000000..60055dd
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/instantiate/AssemblyTemplateInstantiator.java
@@ -0,0 +1,12 @@
+package io.brooklyn.camp.spi.instantiate;
+
+import io.brooklyn.camp.CampPlatform;
+import io.brooklyn.camp.spi.Assembly;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+
+/** instances of this class should have a public no-arg constructor so the class names can be serialized */
+public interface AssemblyTemplateInstantiator {
+
+    public Assembly instantiate(AssemblyTemplate template, CampPlatform platform);
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/instantiate/BasicAssemblyTemplateInstantiator.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/instantiate/BasicAssemblyTemplateInstantiator.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/instantiate/BasicAssemblyTemplateInstantiator.java
new file mode 100644
index 0000000..e598eab
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/instantiate/BasicAssemblyTemplateInstantiator.java
@@ -0,0 +1,18 @@
+package io.brooklyn.camp.spi.instantiate;
+
+import io.brooklyn.camp.CampPlatform;
+import io.brooklyn.camp.spi.Assembly;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+
+/** A simple instantiator which simply invokes the component's instantiators in parallel */
+public class BasicAssemblyTemplateInstantiator implements AssemblyTemplateInstantiator {
+
+    public Assembly instantiate(AssemblyTemplate template, CampPlatform platform) {
+        // TODO this should build it based on the components
+//        template.getPlatformComponentTemplates().links().iterator().next().resolve();
+        
+        // platforms should set a bunch of instantiators, or else let the ComponentTemplates do this!
+        throw new UnsupportedOperationException("Basic instantiator not yet supported");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/Artifact.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/Artifact.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/Artifact.java
new file mode 100644
index 0000000..84445c9
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/Artifact.java
@@ -0,0 +1,82 @@
+package io.brooklyn.camp.spi.pdp;
+
+import io.brooklyn.util.yaml.Yamls;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+import brooklyn.util.collections.MutableMap;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+public class Artifact {
+
+    String name;
+    String description;
+    String artifactType;
+    
+    ArtifactContent content;
+    List<ArtifactRequirement> requirements;
+    
+    Map<String,Object> customAttributes;
+    
+    @SuppressWarnings("unchecked")
+    public static Artifact of(Map<String, Object> artifact) {
+        Map<String,Object> fields = MutableMap.copyOf(artifact);
+        
+        Artifact result = new Artifact();
+        result.name = (String) fields.remove("name");
+        result.description = (String) fields.remove("description");
+        result.artifactType = (String) (String) Yamls.removeMultinameAttribute(fields, "artifactType", "type");
+        
+        result.content = ArtifactContent.of( fields.remove("content") );
+        
+        result.requirements = new ArrayList<ArtifactRequirement>();
+        Object reqs = fields.remove("requirements");
+        if (reqs instanceof Iterable) {
+            for (Object req: (Iterable<Object>)reqs) {
+                if (req instanceof Map) {
+                    result.requirements.add(ArtifactRequirement.of((Map<String,Object>) req));
+                } else {
+                    throw new IllegalArgumentException("requirement should be a map, not "+req.getClass());
+                }
+            }
+        } else if (reqs!=null) {
+            // TODO "map" short form
+            throw new IllegalArgumentException("artifacts body should be iterable, not "+reqs.getClass());
+        }
+        
+        result.customAttributes = fields;
+        
+        return result;
+    }
+    
+    public String getName() {
+        return name;
+    }
+    public String getDescription() {
+        return description;
+    }
+    public String getArtifactType() {
+        return artifactType;
+    }
+    public ArtifactContent getContent() {
+        return content;
+    }
+    public List<ArtifactRequirement> getRequirements() {
+        return ImmutableList.copyOf(requirements);
+    }
+    public Map<String, Object> getCustomAttributes() {
+        return ImmutableMap.copyOf(customAttributes);
+    }
+    
+    @Override
+    public String toString() {
+        return ToStringBuilder.reflectionToString(this);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/ArtifactContent.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/ArtifactContent.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/ArtifactContent.java
new file mode 100644
index 0000000..8ae97dc
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/ArtifactContent.java
@@ -0,0 +1,47 @@
+package io.brooklyn.camp.spi.pdp;
+
+import java.util.Map;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+import brooklyn.util.collections.MutableMap;
+
+import com.google.common.collect.ImmutableMap;
+
+public class ArtifactContent {
+
+    String href;
+    Map<String,Object> customAttributes;
+    
+    public static ArtifactContent of(Object spec) {
+        if (spec==null) return null;
+        
+        ArtifactContent result = new ArtifactContent();
+        if (spec instanceof String) {
+            result.href = (String)spec;
+        } else if (spec instanceof Map) {
+            @SuppressWarnings("unchecked")
+            Map<String,Object> attrs = MutableMap.copyOf( (Map<String,Object>) spec );
+            result.href = (String) attrs.remove("href");
+            result.customAttributes = attrs;            
+        } else {
+            throw new IllegalArgumentException("artifact content should be map or string, not "+spec.getClass());
+        }
+        
+        return result;
+    }
+
+    public String getHref() {
+        return href;
+    }
+    
+    public Map<String, Object> getCustomAttributes() {
+        return ImmutableMap.copyOf(customAttributes);
+    }
+
+    @Override
+    public String toString() {
+        return ToStringBuilder.reflectionToString(this);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/ArtifactRequirement.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/ArtifactRequirement.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/ArtifactRequirement.java
new file mode 100644
index 0000000..5a19e5f
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/ArtifactRequirement.java
@@ -0,0 +1,55 @@
+package io.brooklyn.camp.spi.pdp;
+
+import io.brooklyn.util.yaml.Yamls;
+
+import java.util.Map;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+import brooklyn.util.collections.MutableMap;
+
+import com.google.common.collect.ImmutableMap;
+
+public class ArtifactRequirement {
+
+    String name;
+    String description;
+    String requirementType;
+    
+    Map<String,Object> customAttributes;
+    
+    public static ArtifactRequirement of(Map<String, Object> req) {
+        Map<String,Object> attrs = MutableMap.copyOf(req);
+        
+        ArtifactRequirement result = new ArtifactRequirement();
+        result.name = (String) attrs.remove("name");
+        result.description = (String) attrs.remove("description");
+        result.requirementType = (String) (String) Yamls.removeMultinameAttribute(attrs, "requirementType", "type");
+        
+        // TODO fulfillment
+        
+        result.customAttributes = attrs;
+        
+        return result;
+    }
+
+    public String getName() {
+        return name;
+    }
+    public String getDescription() {
+        return description;
+    }
+    public String getRequirementType() {
+        return requirementType;
+    }
+    
+    public Map<String, Object> getCustomAttributes() {
+        return ImmutableMap.copyOf(customAttributes);
+    }
+    
+    @Override
+    public String toString() {
+        return ToStringBuilder.reflectionToString(this);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/AssemblyTemplateConstructor.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/AssemblyTemplateConstructor.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/AssemblyTemplateConstructor.java
new file mode 100644
index 0000000..1bd582b
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/AssemblyTemplateConstructor.java
@@ -0,0 +1,76 @@
+package io.brooklyn.camp.spi.pdp;
+
+import java.util.Map;
+
+import io.brooklyn.camp.CampPlatform;
+import io.brooklyn.camp.spi.ApplicationComponentTemplate;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+import io.brooklyn.camp.spi.AssemblyTemplate.Builder;
+import io.brooklyn.camp.spi.PlatformComponentTemplate;
+import io.brooklyn.camp.spi.PlatformTransaction;
+import io.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
+
+public class AssemblyTemplateConstructor {
+
+    private final Builder<? extends AssemblyTemplate> builder;
+    private final CampPlatform campPlatform;
+    protected PlatformTransaction transaction;
+
+    public AssemblyTemplateConstructor(CampPlatform campPlatform) {
+        this.campPlatform = campPlatform;
+        this.builder = AssemblyTemplate.builder();
+        this.transaction = this.campPlatform.transaction();
+    }
+    
+    /** records all the templates to the underlying platform */
+    public AssemblyTemplate commit() {
+        checkState();
+        AssemblyTemplate at = builder.build();
+        transaction.add(at).commit();
+        transaction = null;
+        return at;
+    }
+
+    public void name(String name) {
+        checkState();
+        builder.name(name);
+    }
+
+    public void description(String description) {
+        checkState();
+        builder.description(description);
+    }
+
+    public void addCustomAttributes(Map<String, Object> attrs) {
+        for (Map.Entry<String, Object> attr : attrs.entrySet())
+            builder.customAttribute(attr.getKey(), attr.getValue());
+    }
+
+    public void instantiator(Class<? extends AssemblyTemplateInstantiator> instantiator) {
+        checkState();
+        builder.instantiator(instantiator);
+    }
+    
+    public Class<? extends AssemblyTemplateInstantiator> getInstantiator() {
+        checkState();
+        return builder.peek().getInstantiator();
+    }
+    
+    public void add(ApplicationComponentTemplate act) {
+        checkState();
+        builder.add(act);
+        transaction.add(act);
+    }
+
+    public void add(PlatformComponentTemplate pct) {
+        checkState();
+        builder.add(pct);
+        transaction.add(pct);
+    }
+
+    protected void checkState() {
+        if (transaction == null)
+            throw new IllegalStateException("transaction already committed");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/DeploymentPlan.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/DeploymentPlan.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/DeploymentPlan.java
new file mode 100644
index 0000000..e5fb05e
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/DeploymentPlan.java
@@ -0,0 +1,93 @@
+package io.brooklyn.camp.spi.pdp;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+import brooklyn.util.collections.MutableMap;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+public class DeploymentPlan {
+
+    String name;
+    String origin;
+    String description;
+    
+    List<Artifact> artifacts;
+    List<Service> services;
+    Map<String,Object> customAttributes;
+
+    @SuppressWarnings("unchecked")
+    public static DeploymentPlan of(Map<String,Object> root) {
+        Map<String,Object> attrs = MutableMap.copyOf(root);
+        
+        DeploymentPlan result = new DeploymentPlan();
+        result.name = (String) attrs.remove("name");
+        result.description = (String) attrs.remove("description");
+        result.origin = (String) attrs.remove("origin");
+        // TODO version
+        
+        result.services = new ArrayList<Service>();
+        Object services = attrs.remove("services");
+        if (services instanceof Iterable) {
+            for (Object service: (Iterable<Object>)services) {
+                if (service instanceof Map) {
+                    result.services.add(Service.of((Map<String,Object>) service));
+                } else {
+                    throw new IllegalArgumentException("service should be map, not "+service.getClass());
+                }
+            }
+        } else if (services!=null) {
+            // TODO "map" short form
+            throw new IllegalArgumentException("artifacts body should be iterable, not "+services.getClass());
+        }
+        
+        result.artifacts = new ArrayList<Artifact>();
+        Object artifacts = attrs.remove("artifacts");
+        if (artifacts instanceof Iterable) {
+            for (Object artifact: (Iterable<Object>)artifacts) {
+                if (artifact instanceof Map) {
+                    result.artifacts.add(Artifact.of((Map<String,Object>) artifact));
+                } else {
+                    throw new IllegalArgumentException("artifact should be map, not "+artifact.getClass());
+                }
+            }
+        } else if (artifacts!=null) {
+            // TODO "map" short form
+            throw new IllegalArgumentException("artifacts body should be iterable, not "+artifacts.getClass());
+        }
+        
+        result.customAttributes = attrs;
+        
+        return result;
+    }
+
+    public String getName() {
+        return name;
+    }
+    public String getDescription() {
+        return description;
+    }
+    public String getOrigin() {
+        return origin;
+    }
+    public List<Artifact> getArtifacts() {
+        return ImmutableList.copyOf(artifacts);
+    }
+    public List<Service> getServices() {
+        return ImmutableList.copyOf(services);
+    }
+    public Map<String, Object> getCustomAttributes() {
+        return ImmutableMap.copyOf(customAttributes);
+    }
+    
+    @Override
+    public String toString() {
+        return ToStringBuilder.reflectionToString(this);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/Service.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/Service.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/Service.java
new file mode 100644
index 0000000..21ff4a4
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/Service.java
@@ -0,0 +1,77 @@
+package io.brooklyn.camp.spi.pdp;
+
+import io.brooklyn.util.yaml.Yamls;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+import brooklyn.util.collections.MutableMap;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+public class Service {
+
+    String name;
+    String description;
+    String serviceType;
+    
+    List<ServiceCharacteristic> characteristics;
+    
+    Map<String,Object> customAttributes;
+    
+    @SuppressWarnings("unchecked")
+    public static Service of(Map<String, Object> service) {
+        Map<String,Object> fields = MutableMap.copyOf(service);
+        
+        Service result = new Service();
+        result.name = (String) fields.remove("name");
+        result.description = (String) fields.remove("description");
+        // FIXME _type needed in lots of places
+        result.serviceType = (String) (String) Yamls.removeMultinameAttribute(fields, "service_type", "serviceType", "type");
+        
+        result.characteristics = new ArrayList<ServiceCharacteristic>();
+        Object chars = fields.remove("characteristics");
+        if (chars instanceof Iterable) {
+            for (Object req: (Iterable<Object>)chars) {
+                if (req instanceof Map) {
+                    result.characteristics.add(ServiceCharacteristic.of((Map<String,Object>) req));
+                } else {
+                    throw new IllegalArgumentException("characteristics should be a map, not "+req.getClass());
+                }
+            }
+        } else if (chars!=null) {
+            // TODO "map" short form
+            throw new IllegalArgumentException("services body should be iterable, not "+chars.getClass());
+        }
+        
+        result.customAttributes = fields;
+        
+        return result;
+    }
+    
+    public String getName() {
+        return name;
+    }
+    public String getDescription() {
+        return description;
+    }
+    public String getServiceType() {
+        return serviceType;
+    }
+    public List<ServiceCharacteristic> getCharacteristics() {
+        return ImmutableList.copyOf(characteristics);
+    }
+    public Map<String, Object> getCustomAttributes() {
+        return ImmutableMap.copyOf(customAttributes);
+    }
+    
+    @Override
+    public String toString() {
+        return ToStringBuilder.reflectionToString(this);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/ServiceCharacteristic.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/ServiceCharacteristic.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/ServiceCharacteristic.java
new file mode 100644
index 0000000..97917dd
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/pdp/ServiceCharacteristic.java
@@ -0,0 +1,55 @@
+package io.brooklyn.camp.spi.pdp;
+
+import io.brooklyn.util.yaml.Yamls;
+
+import java.util.Map;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+import brooklyn.util.collections.MutableMap;
+
+import com.google.common.collect.ImmutableMap;
+
+public class ServiceCharacteristic {
+
+    String name;
+    String description;
+    String characteristicType;
+    
+    Map<String,Object> customAttributes;
+    
+    public static ServiceCharacteristic of(Map<String, Object> req) {
+        Map<String,Object> attrs = MutableMap.copyOf(req);
+        
+        ServiceCharacteristic result = new ServiceCharacteristic();
+        result.name = (String) attrs.remove("name");
+        result.description = (String) attrs.remove("description");
+        result.characteristicType = (String) Yamls.removeMultinameAttribute(attrs, "characteristicType", "type");
+        
+        // TODO fulfillment
+        
+        result.customAttributes = attrs;
+        
+        return result;
+    }
+
+    public String getName() {
+        return name;
+    }
+    public String getDescription() {
+        return description;
+    }
+    public String getCharacteristicType() {
+        return characteristicType;
+    }
+    
+    public Map<String, Object> getCustomAttributes() {
+        return ImmutableMap.copyOf(customAttributes);
+    }
+    
+    @Override
+    public String toString() {
+        return ToStringBuilder.reflectionToString(this);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2191c9a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/resolve/PdpMatcher.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/io/brooklyn/camp/spi/resolve/PdpMatcher.java b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/resolve/PdpMatcher.java
new file mode 100644
index 0000000..5ecbf72
--- /dev/null
+++ b/camp/camp-base/src/main/java/io/brooklyn/camp/spi/resolve/PdpMatcher.java
@@ -0,0 +1,33 @@
+package io.brooklyn.camp.spi.resolve;
+
+import io.brooklyn.camp.spi.pdp.Artifact;
+import io.brooklyn.camp.spi.pdp.AssemblyTemplateConstructor;
+import io.brooklyn.camp.spi.pdp.Service;
+
+/** Matchers build up the AssemblyTemplate by matching against items in the deployment plan */
+public interface PdpMatcher {
+
+    boolean accepts(Object deploymentPlanItem);
+    boolean apply(Object deploymentPlanItem, AssemblyTemplateConstructor atc);
+
+    public abstract class ArtifactMatcher implements PdpMatcher {
+        private String artifactType;
+        public ArtifactMatcher(String artifactType) {
+            this.artifactType = artifactType;
+        }
+        public boolean accepts(Object art) {
+            return (art instanceof Artifact) && this.artifactType.equals( ((Artifact)art).getArtifactType() );
+        }
+    }
+    
+    public abstract class ServiceMatcher implements PdpMatcher {
+        private String serviceType;
+        public ServiceMatcher(String serviceType) {
+            this.serviceType = serviceType;
+        }
+        public boolean accepts(Object svc) {
+            return (svc instanceof Service) && this.serviceType.equals( ((Service)svc).getServiceType() );
+        }
+    }
+
+}