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:44 UTC
[02/45] import of brooklyncentral/camp-server dependency to apache
brooklyn project
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
+
+ }
+
+
+}