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

[5/7] git commit: Adds a Map message body reader and uses it in EffectorApi

Adds a Map<String,Object> message body reader and uses it in EffectorApi

* Adds FormMapProvider, which reads an InputStream into a
  Map<String, Object>, where the Object values are either a String, a
  List<String> or null.
* Uses this in EffectorApi to support form encoded data.
* Changes signature of EffectorApi.invoke parameters argument from
  Map<String, String> to Map<String, Object>.


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

Branch: refs/heads/master
Commit: a94678da8290ea3f31832caf5735cf9f81cc6a9f
Parents: 1035445
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Wed Jul 16 18:34:42 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Wed Jul 16 19:22:12 2014 +0100

----------------------------------------------------------------------
 .../java/brooklyn/rest/api/EffectorApi.java     |  5 +-
 .../ApplicationResourceIntegrationTest.java     |  2 +-
 .../rest-client/src/test/webapp/WEB-INF/web.xml |  1 +
 .../java/brooklyn/rest/BrooklynRestApi.java     |  2 +
 .../rest/resources/EffectorResource.java        |  2 +-
 .../brooklyn/rest/util/FormMapProvider.java     | 82 ++++++++++++++++++++
 .../brooklyn/rest/util/WebResourceUtils.java    | 12 +++
 .../rest-server/src/main/webapp/WEB-INF/web.xml |  1 +
 .../rest/resources/ApplicationResourceTest.java | 18 +++++
 .../rest/testing/BrooklynRestApiTest.java       |  2 +
 10 files changed, 123 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a94678da/usage/rest-api/src/main/java/brooklyn/rest/api/EffectorApi.java
----------------------------------------------------------------------
diff --git a/usage/rest-api/src/main/java/brooklyn/rest/api/EffectorApi.java b/usage/rest-api/src/main/java/brooklyn/rest/api/EffectorApi.java
index 8204927..c2ec68e 100644
--- a/usage/rest-api/src/main/java/brooklyn/rest/api/EffectorApi.java
+++ b/usage/rest-api/src/main/java/brooklyn/rest/api/EffectorApi.java
@@ -59,6 +59,7 @@ public interface EffectorApi {
   @ApiErrors(value = {
       @ApiError(code = 404, reason = "Could not find application, entity or effector")
   })
+  @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_FORM_URLENCODED})
   public Response invoke(
       @ApiParam(name = "application", value = "Application ID or name", required = true)
       @PathParam("application") String application,
@@ -80,7 +81,7 @@ public interface EffectorApi {
       
       @ApiParam(name = "parameters", value = "Effector parameters (as key value pairs)", required = false)
       @Valid 
-      Map<String, String> parameters
+      Map<String, Object> parameters
   ) ;
-  
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a94678da/usage/rest-client/src/test/java/brooklyn/rest/client/ApplicationResourceIntegrationTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-client/src/test/java/brooklyn/rest/client/ApplicationResourceIntegrationTest.java b/usage/rest-client/src/test/java/brooklyn/rest/client/ApplicationResourceIntegrationTest.java
index b1ce82b..b20e94d 100644
--- a/usage/rest-client/src/test/java/brooklyn/rest/client/ApplicationResourceIntegrationTest.java
+++ b/usage/rest-client/src/test/java/brooklyn/rest/client/ApplicationResourceIntegrationTest.java
@@ -153,7 +153,7 @@ public class ApplicationResourceIntegrationTest {
     @Test(groups = "Integration", dependsOnMethods = {"testListSensorsRedis", "testListEntities"})
     public void testTriggerRedisStopEffector() throws Exception {
         String entityId = getManagementContext().getApplications().iterator().next().getChildren().iterator().next().getId();
-        Response response = api.getEffectorApi().invoke("redis-app", entityId, "stop", "5000", ImmutableMap.<String, String>of());
+        Response response = api.getEffectorApi().invoke("redis-app", entityId, "stop", "5000", ImmutableMap.<String, Object>of());
 
         assertEquals(response.getStatus(), Response.Status.ACCEPTED.getStatusCode());
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a94678da/usage/rest-client/src/test/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/usage/rest-client/src/test/webapp/WEB-INF/web.xml b/usage/rest-client/src/test/webapp/WEB-INF/web.xml
index 0b211f4..7fe2c9c 100644
--- a/usage/rest-client/src/test/webapp/WEB-INF/web.xml
+++ b/usage/rest-client/src/test/webapp/WEB-INF/web.xml
@@ -65,6 +65,7 @@
             <param-name>com.sun.jersey.config.property.classnames</param-name>
             <param-value>
                 brooklyn.rest.apidoc.ApidocHelpMessageBodyWriter;
+                brooklyn.rest.util.FormMapProvider;
                 org.codehaus.jackson.jaxrs.JacksonJsonProvider;
                 brooklyn.rest.resources.ActivityResource;
                 brooklyn.rest.resources.ApidocResource;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a94678da/usage/rest-server/src/main/java/brooklyn/rest/BrooklynRestApi.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/BrooklynRestApi.java b/usage/rest-server/src/main/java/brooklyn/rest/BrooklynRestApi.java
index 69e3429..afcbe5c 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/BrooklynRestApi.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/BrooklynRestApi.java
@@ -42,6 +42,7 @@ import brooklyn.rest.resources.ServerResource;
 import brooklyn.rest.resources.UsageResource;
 import brooklyn.rest.resources.VersionResource;
 import brooklyn.rest.util.DefaultExceptionMapper;
+import brooklyn.rest.util.FormMapProvider;
 
 import com.google.common.collect.Iterables;
 
@@ -78,6 +79,7 @@ public class BrooklynRestApi {
         List<Object> resources = new ArrayList<Object>();
         resources.add(new DefaultExceptionMapper());
         resources.add(new JacksonJsonProvider());
+        resources.add(new FormMapProvider());
         return resources;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a94678da/usage/rest-server/src/main/java/brooklyn/rest/resources/EffectorResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/resources/EffectorResource.java b/usage/rest-server/src/main/java/brooklyn/rest/resources/EffectorResource.java
index 6543770..a7434d1 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/resources/EffectorResource.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/resources/EffectorResource.java
@@ -75,7 +75,7 @@ public class EffectorResource extends AbstractBrooklynRestResource implements Ef
 
     @Override
     public Response invoke(String application, String entityToken, String effectorName,
-                           String timeout, Map<String, String> parameters) {
+            String timeout, Map<String, Object> parameters) {
         final EntityLocal entity = brooklyn().getEntity(application, entityToken);
 
         // TODO check effectors?

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a94678da/usage/rest-server/src/main/java/brooklyn/rest/util/FormMapProvider.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/util/FormMapProvider.java b/usage/rest-server/src/main/java/brooklyn/rest/util/FormMapProvider.java
new file mode 100644
index 0000000..eb6a60a
--- /dev/null
+++ b/usage/rest-server/src/main/java/brooklyn/rest/util/FormMapProvider.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.rest.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.Map;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.Provider;
+
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.sun.jersey.core.impl.provider.entity.FormMultivaluedMapProvider;
+import com.sun.jersey.core.util.MultivaluedMapImpl;
+
+/**
+ * A MessageBodyReader producing a <code>Map&lt;String, Object&gt;</code>, where Object
+ * is either a <code>String</code>, a <code>List&lt;String&gt;</code> or null.
+ */
+@Provider
+@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+public class FormMapProvider implements MessageBodyReader<Map<String, Object>> {
+
+    @Override
+    public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+        if (!Map.class.equals(type) || !(genericType instanceof ParameterizedType)) {
+            return false;
+        }
+        ParameterizedType parameterized = (ParameterizedType) genericType;
+        return parameterized.getActualTypeArguments().length == 2 &&
+                parameterized.getActualTypeArguments()[0] == String.class &&
+                parameterized.getActualTypeArguments()[1] == Object.class;
+    }
+
+    @Override
+    public Map<String, Object> readFrom(Class<Map<String, Object>> type, Type genericType, Annotation[] annotations,
+            MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
+            throws IOException, WebApplicationException {
+        FormMultivaluedMapProvider delegate = new FormMultivaluedMapProvider();
+        MultivaluedMap<String, String> multi = new MultivaluedMapImpl();
+        multi = delegate.readFrom(multi, mediaType, entityStream);
+
+        Map<String, Object> map = Maps.newHashMapWithExpectedSize(multi.keySet().size());
+        for (String key : multi.keySet()) {
+            List<String> value = multi.get(key);
+            if (value.size() > 1) {
+                map.put(key, Lists.newArrayList(value));
+            } else if (value.size() == 1) {
+                map.put(key, Iterables.getOnlyElement(value));
+            } else {
+                map.put(key, null);
+            }
+        }
+        return map;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a94678da/usage/rest-server/src/main/java/brooklyn/rest/util/WebResourceUtils.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/util/WebResourceUtils.java b/usage/rest-server/src/main/java/brooklyn/rest/util/WebResourceUtils.java
index 0e19b29..61e4217 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/util/WebResourceUtils.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/util/WebResourceUtils.java
@@ -38,6 +38,16 @@ public class WebResourceUtils {
 
     private static final Logger log = LoggerFactory.getLogger(WebResourceUtils.class);
 
+    /** @throws WebApplicationException With code 400 bad request */
+    public static WebApplicationException badRequest(String format, Object... args) {
+        String msg = String.format(format, args);
+        if (log.isDebugEnabled()) log.debug("returning 400 bad request ("+msg+")");
+        throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
+                .type(MediaType.APPLICATION_JSON_TYPE)
+                .entity(ApiError.builder().message(msg).build()).build());
+    }
+
+    /** @throws WebApplicationException With code 401 unauthorized */
     public static WebApplicationException unauthorized(String format, Object... args) {
         String msg = String.format(format, args);
         if (log.isDebugEnabled()) log.debug("returning 401 unauthorized("+msg+")");
@@ -46,6 +56,7 @@ public class WebResourceUtils {
                 .entity(ApiError.builder().message(msg).build()).build());
     }
 
+    /** @throws WebApplicationException With code 404 not found */
     public static WebApplicationException notFound(String format, Object... args) {
         String msg = String.format(format, args);
         if (log.isDebugEnabled()) log.debug("returning 404 notFound("+msg+") - may be a stale browser session");
@@ -54,6 +65,7 @@ public class WebResourceUtils {
                 .entity(ApiError.builder().message(msg).build()).build());
     }
 
+    /** @throws WebApplicationException With code 412 precondition failed */
     public static WebApplicationException preconditionFailed(String format, Object... args) {
         String msg = String.format(format, args);
         if (log.isDebugEnabled()) log.debug("returning 412 preconditionFailed("+msg+")");

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a94678da/usage/rest-server/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/webapp/WEB-INF/web.xml b/usage/rest-server/src/main/webapp/WEB-INF/web.xml
index 61d4781..932691d 100644
--- a/usage/rest-server/src/main/webapp/WEB-INF/web.xml
+++ b/usage/rest-server/src/main/webapp/WEB-INF/web.xml
@@ -63,6 +63,7 @@
             <param-name>com.sun.jersey.config.property.classnames</param-name>
             <param-value>
                 brooklyn.rest.apidoc.ApidocHelpMessageBodyWriter;
+                brooklyn.rest.util.FormMapProvider;
                 org.codehaus.jackson.jaxrs.JacksonJsonProvider;
                 brooklyn.rest.resources.ActivityResource;
                 brooklyn.rest.resources.ApidocResource;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a94678da/usage/rest-server/src/test/java/brooklyn/rest/resources/ApplicationResourceTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/brooklyn/rest/resources/ApplicationResourceTest.java b/usage/rest-server/src/test/java/brooklyn/rest/resources/ApplicationResourceTest.java
index 1a030a9..22454f5 100644
--- a/usage/rest-server/src/test/java/brooklyn/rest/resources/ApplicationResourceTest.java
+++ b/usage/rest-server/src/test/java/brooklyn/rest/resources/ApplicationResourceTest.java
@@ -30,6 +30,7 @@ import java.util.Set;
 import java.util.concurrent.TimeoutException;
 
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
 
 import org.codehaus.jackson.JsonGenerationException;
@@ -80,6 +81,7 @@ import com.sun.jersey.api.client.ClientHandlerException;
 import com.sun.jersey.api.client.ClientResponse;
 import com.sun.jersey.api.client.GenericType;
 import com.sun.jersey.api.client.UniformInterfaceException;
+import com.sun.jersey.core.util.MultivaluedMapImpl;
 
 @Test(singleThreaded = true)
 public class ApplicationResourceTest extends BrooklynRestResourceTest {
@@ -431,6 +433,22 @@ public class ApplicationResourceTest extends BrooklynRestResourceTest {
     assertEquals(result, "foo4");
   }
 
+  @Test(dependsOnMethods = "testListSensors")
+  public void testTriggerSampleEffectorWithFormData() throws InterruptedException, IOException {
+    MultivaluedMap<String, String> data = new MultivaluedMapImpl();
+    data.add("param1", "foo");
+    data.add("param2", "4");
+    ClientResponse response = client().resource("/v1/applications/simple-app/entities/simple-ent/effectors/"+
+            RestMockSimpleEntity.SAMPLE_EFFECTOR.getName())
+        .type(MediaType.APPLICATION_FORM_URLENCODED)
+        .post(ClientResponse.class, data);
+
+    assertEquals(response.getStatus(), Response.Status.ACCEPTED.getStatusCode());
+
+    String result = response.getEntity(String.class);
+    assertEquals(result, "foo4");
+  }
+
   @Test(dependsOnMethods = "testTriggerSampleEffector")
   public void testBatchSensorValues() {
     Map<String,String> sensors = client().resource("/v1/applications/simple-app/entities/simple-ent/sensors/current-state")

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a94678da/usage/rest-server/src/test/java/brooklyn/rest/testing/BrooklynRestApiTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/brooklyn/rest/testing/BrooklynRestApiTest.java b/usage/rest-server/src/test/java/brooklyn/rest/testing/BrooklynRestApiTest.java
index 6391672..4370053 100644
--- a/usage/rest-server/src/test/java/brooklyn/rest/testing/BrooklynRestApiTest.java
+++ b/usage/rest-server/src/test/java/brooklyn/rest/testing/BrooklynRestApiTest.java
@@ -18,6 +18,7 @@
  */
 package brooklyn.rest.testing;
 
+import brooklyn.rest.util.FormMapProvider;
 import io.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherNoServer;
 
 import org.testng.annotations.AfterClass;
@@ -95,6 +96,7 @@ public abstract class BrooklynRestApiTest extends ResourceTest {
     
     protected void addResources() {
         addProvider(DefaultExceptionMapper.class);
+        addProvider(FormMapProvider.class);
         for (Object r: BrooklynRestApi.getBrooklynRestResources())
             addResource(r);
     }