Mercurial > hg > thermostat-ng > web-gateway
changeset 238:1093c542f930
Add jvm-io service
This patch adds a jvm-io service, with GET /jvm-io/0.0.1/jvms/{jvmid} and GET|POST|PUT|DELETE /jvm-io/systems/{sysid}/jvms/{jvmid}
Reviewed-by: neugens
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2017-August/024771.html
author | Simon Tooke <stooke@redhat.com> |
---|---|
date | Thu, 31 Aug 2017 10:22:31 -0400 |
parents | 9a08bbf30b04 |
children | 4e58443cbb7f |
files | distribution/pom.xml distribution/src/etc/services.properties services/jvm-io/pom.xml services/jvm-io/src/main/java/com/redhat/thermostat/gateway/service/jvm/io/JvmIoHttpHandler.java services/jvm-io/src/main/java/com/redhat/thermostat/gateway/service/jvm/io/SwaggerSpecResourceHandler.java services/jvm-io/src/main/resources/jvm-io-swagger.yaml services/jvm-io/src/main/webapp/WEB-INF/web.xml services/pom.xml tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/service/jvm/io/JvmIoServiceIntegrationTest.java |
diffstat | 9 files changed, 1310 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/distribution/pom.xml Wed Aug 30 12:00:11 2017 -0400 +++ b/distribution/pom.xml Thu Aug 31 10:22:31 2017 -0400 @@ -244,6 +244,13 @@ </artifactItem> <artifactItem> <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-web-gateway-service-jvm-io</artifactId> + <version>${project.version}</version> + <type>war</type> + <overWrite>false</overWrite> + </artifactItem> + <artifactItem> + <groupId>com.redhat.thermostat</groupId> <artifactId>thermostat-web-gateway-service-systems</artifactId> <version>${project.version}</version> <type>war</type> @@ -305,6 +312,13 @@ </dependency> <dependency> <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-web-gateway-service-jvm-io</artifactId> + <version>${project.version}</version> + <type>war</type> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.redhat.thermostat</groupId> <artifactId>thermostat-web-gateway-service-systems</artifactId> <version>${project.version}</version> <type>war</type>
--- a/distribution/src/etc/services.properties Wed Aug 30 12:00:11 2017 -0400 +++ b/distribution/src/etc/services.properties Thu Aug 31 10:22:31 2017 -0400 @@ -1,5 +1,6 @@ /commands = thermostat-web-gateway-service-commands-@project.version@.war /jvm-gc = thermostat-web-gateway-service-jvm-gc-@project.version@.war +/jvm-io = thermostat-web-gateway-service-jvm-io-@project.version@.war /jvm-memory = thermostat-web-gateway-service-jvm-memory-@project.version@.war /jvms = thermostat-web-gateway-service-jvms-@project.version@.war /systems = thermostat-web-gateway-service-systems-@project.version@.war
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/services/jvm-io/pom.xml Thu Aug 31 10:22:31 2017 -0400 @@ -0,0 +1,96 @@ +<!-- + + Copyright 2012-2017 Red Hat, Inc. + + This file is part of Thermostat. + + Thermostat is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2, or (at your + option) any later version. + + Thermostat is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Thermostat; see the file COPYING. If not see + <http://www.gnu.org/licenses/>. + + Linking this code with other modules is making a combined work + based on this code. Thus, the terms and conditions of the GNU + General Public License cover the whole combination. + + As a special exception, the copyright holders of this code give + you permission to link this code with independent modules to + produce an executable, regardless of the license terms of these + independent modules, and to copy and distribute the resulting + executable under terms of your choice, provided that you also + meet, for each linked independent module, the terms and conditions + of the license of that module. An independent module is a module + which is not derived from or based on this code. If you modify + this code, you may extend this exception to your version of the + library, but you are not obligated to do so. If you do not wish + to do so, delete this exception statement from your version. + +--> +<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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <artifactId>thermostat-web-gateway-services</artifactId> + <groupId>com.redhat.thermostat</groupId> + <version>1.99.12-SNAPSHOT</version> + </parent> + + <artifactId>thermostat-web-gateway-service-jvm-io</artifactId> + + <packaging>war</packaging> + + <name>Thermostat Web Gateway JVM IO Service</name> + + <properties> + <com.redhat.thermostat.gateway.SERVICE_NAME>jvm-io</com.redhat.thermostat.gateway.SERVICE_NAME> + </properties> + <build> + <plugins> + <plugin> + <artifactId>maven-war-plugin</artifactId> + <configuration> + <webResources> + <resource> + <directory>src/main/webapp</directory> + <filtering>true</filtering> + </resource> + </webResources> + </configuration> + </plugin> + </plugins> + </build> + + <dependencies> + <!-- Thermostat Web Gateway Dependencies --> + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-web-gateway-common-mongodb</artifactId> + <version>${project.version}</version> + </dependency> + + <!-- Servlet API deps --> + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + <version>${javax.servlet.version}</version> + <scope>provided</scope> + </dependency> + + <!-- JAX-RS Dependencies --> + <dependency> + <groupId>javax.ws.rs</groupId> + <artifactId>javax.ws.rs-api</artifactId> + <version>${javax-rs-api.version}</version> + <scope>provided</scope> + </dependency> + </dependencies> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/services/jvm-io/src/main/java/com/redhat/thermostat/gateway/service/jvm/io/JvmIoHttpHandler.java Thu Aug 31 10:22:31 2017 -0400 @@ -0,0 +1,137 @@ +/* + * Copyright 2012-2017 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.gateway.service.jvm.io; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; + +import com.redhat.thermostat.gateway.common.core.model.OffsetParameter; +import com.redhat.thermostat.gateway.common.mongodb.servlet.RequestParameters; +import com.redhat.thermostat.gateway.common.mongodb.servlet.MongoHttpHandlerHelper; + +@Path("/") +public class JvmIoHttpHandler { + private static final String collectionName = "jvm-io"; + private final MongoHttpHandlerHelper serviceHelper = new MongoHttpHandlerHelper( collectionName ); + + @GET + @Path("/jvms/{" + RequestParameters.JVM_ID +"}") + @Consumes({ "application/json" }) + @Produces({ "application/json", "text/html; charset=utf-8" }) + public Response getJvmIo(@PathParam(RequestParameters.JVM_ID) String jvmId, + @QueryParam(RequestParameters.LIMIT) @DefaultValue("1") Integer limit, + @QueryParam(RequestParameters.OFFSET) @DefaultValue("0") OffsetParameter offsetParam, + @QueryParam(RequestParameters.SORT) String sort, + @QueryParam(RequestParameters.QUERY) String queries, + @QueryParam(RequestParameters.INCLUDE) String includes, + @QueryParam(RequestParameters.EXCLUDE) String excludes, + @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata, + @Context ServletContext context, + @Context HttpServletRequest httpServletRequest) { + return serviceHelper.handleGetWithJvmID(httpServletRequest, context, null, jvmId, limit, offsetParam.getValue(), sort, queries, includes, excludes, metadata); + } + + @GET + @Path("/systems/{" + RequestParameters.SYSTEM_ID +"}/jvms/{" + RequestParameters.JVM_ID +"}") + @Consumes({ "application/json" }) + @Produces({ "application/json", "text/html; charset=utf-8" }) + public Response getJvmIo(@PathParam(RequestParameters.SYSTEM_ID) String systemId, + @PathParam(RequestParameters.JVM_ID) String jvmId, + @QueryParam(RequestParameters.LIMIT) @DefaultValue("1") Integer limit, + @QueryParam(RequestParameters.OFFSET) @DefaultValue("0") OffsetParameter offsetParam, + @QueryParam(RequestParameters.SORT) String sort, + @QueryParam(RequestParameters.QUERY) String queries, + @QueryParam(RequestParameters.INCLUDE) String includes, + @QueryParam(RequestParameters.EXCLUDE) String excludes, + @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata, + @Context ServletContext context, + @Context HttpServletRequest httpServletRequest) { + return serviceHelper.handleGetWithJvmID(httpServletRequest, context, systemId, jvmId, limit, offsetParam.getValue(), sort, queries, includes, excludes, metadata); + } + + @PUT + @Path("/systems/{" + RequestParameters.SYSTEM_ID +"}/jvms/{" + RequestParameters.JVM_ID +"}") + @Consumes({ "application/json" }) + @Produces({ "application/json", "text/html; charset=utf-8" }) + public Response putJvmIo(String body, + @PathParam(RequestParameters.SYSTEM_ID) String systemId, + @PathParam(RequestParameters.JVM_ID) String jvmId, + @QueryParam(RequestParameters.QUERY) String queries, + @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata, + @Context ServletContext context, + @Context HttpServletRequest httpServletRequest) { + return serviceHelper.handlePutWithJvmId(httpServletRequest, context, systemId, jvmId, queries, metadata, body); + } + + @POST + @Path("/systems/{" + RequestParameters.SYSTEM_ID +"}/jvms/{" + RequestParameters.JVM_ID +"}") + @Consumes({ "application/json" }) + @Produces({ "application/json", "text/html; charset=utf-8" }) + public Response postJvmIo(String body, + @PathParam(RequestParameters.SYSTEM_ID) String systemId, + @PathParam(RequestParameters.JVM_ID) String jvmId, + @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata, + @Context ServletContext context, + @Context HttpServletRequest httpServletRequest) { + return serviceHelper.handlePostWithJvmID(httpServletRequest, context, systemId, jvmId, metadata, body); + } + + @DELETE + @Path("/systems/{" + RequestParameters.SYSTEM_ID +"}/jvms/{" + RequestParameters.JVM_ID +"}") + @Consumes({ "application/json" }) + @Produces({ "application/json", "text/html; charset=utf-8" }) + public Response deleteJvmIo(@PathParam(RequestParameters.SYSTEM_ID) String systemId, + @PathParam(RequestParameters.JVM_ID) String jvmId, + @QueryParam(RequestParameters.QUERY) String queries, + @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata, + @Context ServletContext context, + @Context HttpServletRequest httpServletRequest) { + return serviceHelper.handleDeleteWithJvmID(httpServletRequest, context, systemId, jvmId, queries, metadata); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/services/jvm-io/src/main/java/com/redhat/thermostat/gateway/service/jvm/io/SwaggerSpecResourceHandler.java Thu Aug 31 10:22:31 2017 -0400 @@ -0,0 +1,59 @@ +/* + * Copyright 2012-2017 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.gateway.service.jvm.io; + +import java.io.IOException; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import com.redhat.thermostat.gateway.common.core.servlet.BasicResourceHandler; + +@Path("doc/{fileName: .+\\.yaml}") +@Produces(MediaType.TEXT_PLAIN) +public class SwaggerSpecResourceHandler extends BasicResourceHandler { + + @GET + public Response getFileAsPlainText(@PathParam("fileName") String fileName) throws IOException { + return getFileAsResponse(SwaggerSpecResourceHandler.class.getClassLoader(), fileName); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/services/jvm-io/src/main/resources/jvm-io-swagger.yaml Thu Aug 31 10:22:31 2017 -0400 @@ -0,0 +1,226 @@ +swagger: '2.0' +info: + version: 0.0.1 + title: Thermostat Web Gateway JVM IO API + license: + name: GPL v2 with Classpath Exception + url: 'http://www.gnu.org/licenses' +consumes: + - application/json +produces: + - application/json + - text/html; charset=utf-8 +basePath: /jvm-memory/0.0.1 +paths: + /jvms/{jvmId}: + parameters: + - $ref: '#/parameters/thermostat-realms' + - $ref: '#/parameters/jvm-id' + get: + description: Get jvm IO information. + parameters: + - $ref: '#/parameters/limit' + - $ref: '#/parameters/offset' + - $ref: '#/parameters/sort' + - $ref: '#/parameters/include' + - $ref: '#/parameters/exclude' + - $ref: '#/parameters/query' + - $ref: '#/parameters/metadata' + responses: + '200': + description: OK + schema: + $ref: '#/definitions/jvm-io-stats-response' + /systems/{systemId}/jvms/{jvmId}: + parameters: + - $ref: '#/parameters/thermostat-realms' + - $ref: '#/parameters/system-id' + - $ref: '#/parameters/jvm-id' + get: + description: Get jvm io information. + parameters: + - $ref: '#/parameters/limit' + - $ref: '#/parameters/offset' + - $ref: '#/parameters/sort' + - $ref: '#/parameters/include' + - $ref: '#/parameters/exclude' + - $ref: '#/parameters/query' + - $ref: '#/parameters/metadata' + responses: + '200': + description: OK + schema: + $ref: '#/definitions/jvm-io-stats-response' + put: + description: Update jvm io information. + parameters: + - $ref: '#/parameters/put-body' + - $ref: '#/parameters/query' + - $ref: '#/parameters/metadata' + responses: + '200': + description: OK + schema: + $ref: '#/definitions/metadata' + post: + description: Add jvm io information + parameters: + - $ref: '#/parameters/jvm-io-stats' + responses: + '200': + description: OK + schema: + $ref: '#/definitions/metadata' + delete: + description: Delete jvm io information. + parameters: + - $ref: '#/parameters/query' + responses: + '200': + description: OK + schema: + $ref: '#/definitions/metadata' +definitions: + jvm-io-stats-response: + type: object + properties: + response: + $ref: '#/definitions/jvm-io-stats' + metadata: + $ref: '#/definitions/metadata' + jvm-io-stats: + type: array + items: + $ref: '#/definitions/jvm-io-stat' + jvm-io-stat: + type: object + properties: + agentId: + type: string + jvmId: + type: string + timeStamp: + $ref: '#/definitions/timestamp' + charactersRead: + ref: '#/definitions/metric' + charactersWritten: + ref: '#/definitions/metric' + readSyscalls: + ref: '#/definitions/metric' + writeSyscalls: + ref: '#/definitions/metric' + metadata: + type: object + properties: + payloadCount: + type: integer + count: + type: integer + prev: + type: string + next: + type: string + first: + type: string + last: + type: string + insertCount: + type: integer + matchCount: + type: integer + elapsed: + type: integer + format: int64 + metric: + type: object + properties: + $numberLong: + type: string + timestamp: + description: UNIX timestamp in milliseconds + type: object + properties: + $numberLong: + type: string + put-body: + type: object + properties: + "set": + type: object +parameters: + system-id: + name: systemId + in: path + required: true + type: string + jvm-id: + name: jvmId + in: path + required: true + type: string + jvm-io-stats: + name: jvm-io-stats + in: body + description: The jvm io statistics + required: true + schema: + $ref: '#/definitions/jvm-io-stats' + put-body: + name: putBody + in: body + description: "The JSON object containing a 'set' object. This contains single item JSON objects that specify the field to replace and the JSON value to replace with. Example { \"set\" : { \"field\" : \"value\", \"field2\":{\"object\":\"item\"} }" + required: true + schema: + $ref: '#/definitions/put-body' + limit: + name: limit + in: query + description: Limit of items to return. Example '1' + type: integer + offset: + name: offset + in: query + description: Offset of items to return. Example '0' + type: integer + sort: + name: sort + in: query + description: Sort string. Comma separated list of fields prefixed with '+' for ascending or '-' for descending. Example '?s=+a,-b' Fields use dot notation for embedded documents. Example 'outer.inner' refers to field inner contained in field outer. + type: string + query: + name: query + in: query + description: Query string. Comma separated list of key, comparator, value pairs. Comparator supports '==', '<=', '>=', '<', '>', '!='. Example '?q=a==b,c!=d'. Keys are fields in documents and use dot notation for embedded documents. Example 'outer.inner' refers to field inner contained in field outer. + type: string + include: + name: include + in: query + description: >- + Inclusion string. Comma separated list of fields to include in the + response. Example '?include=a,b' Fields use dot notation for embedded + documents. Example 'outer.inner' refers to field inner contained in field + outer. Cannot be used in combination with 'exclude' parameter. Overriden by + 'exclude' parameter + type: string + required: false + exclude: + name: exclude + in: query + description: >- + Exclusion string. Comma separated list of fields to exclude in the + response. Example '?exclude=a,b' Fields use dot notation for embedded + documents. Example 'outer.inner' refers to field inner contained in field + outer. Cannot be used in combination with 'include' parameter; takes + precedence over 'include' parameter + type: string + required: false + metadata: + name: metadata + type: boolean + in: query + description: "Metadata flag. If set to 'true', the subsequent request response will return metadata information. If set to 'false', such metadata information will be omitted." + thermostat-realms: + name: X-Thermostat-Realms + type: string + in: header + description: "Realms Header used to specify a subset of roles to use for Keycloak authorization. Attempts to specify realms that the client does not have, or no valid realms at all will result in a 400 Bad Request response. Expects a space separated list of realms. Example 'X-Thermostat-Realms: realm-one realm-two'"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/services/jvm-io/src/main/webapp/WEB-INF/web.xml Thu Aug 31 10:22:31 2017 -0400 @@ -0,0 +1,88 @@ +<!-- + + Copyright 2012-2017 Red Hat, Inc. + + This file is part of Thermostat. + + Thermostat is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2, or (at your + option) any later version. + + Thermostat is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Thermostat; see the file COPYING. If not see + <http://www.gnu.org/licenses/>. + + Linking this code with other modules is making a combined work + based on this code. Thus, the terms and conditions of the GNU + General Public License cover the whole combination. + + As a special exception, the copyright holders of this code give + you permission to link this code with independent modules to + produce an executable, regardless of the license terms of these + independent modules, and to copy and distribute the resulting + executable under terms of your choice, provided that you also + meet, for each linked independent module, the terms and conditions + of the license of that module. An independent module is a module + which is not derived from or based on this code. If you modify + this code, you may extend this exception to your version of the + library, but you are not obligated to do so. If you do not wish + to do so, delete this exception statement from your version. + +--> +<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee + http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" + version="3.1"> + <servlet> + <servlet-name>JvmIoServlet</servlet-name> + <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> + <init-param> + <param-name> + jersey.config.server.provider.packages + </param-name> + <param-value> + com.redhat.thermostat.gateway.service.jvm.io, + </param-value> + </init-param> + </servlet> + <filter> + <filter-name>ServiceVersionFilter</filter-name> + <filter-class>com.redhat.thermostat.gateway.common.core.servlet.ServiceVersionFilter</filter-class> + <init-param> + <param-name>version</param-name> + <param-value>0.0.1</param-value> + </init-param> + </filter> + <filter-mapping> + <filter-name>ServiceVersionFilter</filter-name> + <url-pattern>/*</url-pattern> + </filter-mapping> + <servlet-mapping> + <servlet-name>JvmIoServlet</servlet-name> + <url-pattern>/0.0.1/*</url-pattern> + </servlet-mapping> + <!-- Service configuration --> + <context-param> + <param-name>com.redhat.thermostat.gateway.SERVICE_NAME</param-name> + <param-value>@com.redhat.thermostat.gateway.SERVICE_NAME@</param-value> + </context-param> + <!-- Listener for setting up the storage connection --> + <listener> + <listener-class>com.redhat.thermostat.gateway.common.mongodb.servlet.StorageConnectionSettingListener</listener-class> + </listener> + <!-- Allow viewing of API spec without authentication --> + <security-constraint> + <web-resource-collection> + <web-resource-name>Swagger API Spec File</web-resource-name> + <url-pattern>/0.0.1/doc/@com.redhat.thermostat.gateway.SERVICE_NAME@-swagger.yaml</url-pattern> + </web-resource-collection> + <!-- Explicitly no auth constraint for this file --> + </security-constraint> +</web-app>
--- a/services/pom.xml Wed Aug 30 12:00:11 2017 -0400 +++ b/services/pom.xml Thu Aug 31 10:22:31 2017 -0400 @@ -55,6 +55,7 @@ <module>jvm-gc</module> <module>jvms</module> <module>jvm-memory</module> + <module>jvm-io</module> <module>systems</module> <module>system-cpu</module> <module>system-memory</module>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/service/jvm/io/JvmIoServiceIntegrationTest.java Thu Aug 31 10:22:31 2017 -0400 @@ -0,0 +1,688 @@ +/* + * Copyright 2012-2017 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.gateway.service.jvm.io; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.redhat.thermostat.gateway.tests.integration.MongoIntegrationTest; +import com.redhat.thermostat.gateway.tests.utils.HttpTestUtil; +import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.client.util.StringContentProvider; +import org.eclipse.jetty.http.HttpHeader; +import org.eclipse.jetty.http.HttpMethod; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class JvmIoServiceIntegrationTest extends MongoIntegrationTest { + + private static final String serviceName = "jvm-io"; + private static final String versionNumber = "0.0.1"; + + private static final int HTTP_200_OK = 200; + private static final int HTTP_404_NOTFOUND = 404; + + private static final String QUERY_PREFIX = "query"; + private static final String LIMIT_PREFIX = "limit"; + private static final String SORT_PREFIX = "sort"; + private static final String OFFSET_PREFIX = "offset"; + private static final String METADATA_PREFIX = "metadata"; + private static final String INCLUDE_PREFIX = "include"; + + private static final String TIMESTAMP_TOKEN = "\"$TIMESTAMP$\""; + private static final String JVMID_TOKEN = "\"$JVMID_TOKEN\""; + + private final String AGENT_ID = getRandomSystemId(); + private final String JVM_ID = getRandomJvmId(); + private long timeStamp = java.lang.System.nanoTime(); + private final String SYSTEM_JVM_FRAGMENT = ",\"systemId\":\"" + AGENT_ID + "\",\"jvmId\":\"" + JVM_ID + "\""; + + private final String jsonData = + "{\n" + + " \"timeStamp\" : " + TIMESTAMP_TOKEN + ",\n" + + " \"jvmId\" : " + JVMID_TOKEN + ",\n" + + " \"metaspaceMaxCapacity\" : \"1000\",\n" + + " \"metaspaceMinCapacity\" : \"22\",\n" + + " \"metaspaceCapacity\" : \"777\",\n" + + " \"metaspaceUsed\" : \"77\"\n" + + "}\n"; + + private final String simpleUrl = baseUrl + "/" + serviceName + "/" + versionNumber; + private final String serviceUrl = simpleUrl + "/systems/" + AGENT_ID + "/jvms/" + JVM_ID; + + private final String returnedUrl; + + public JvmIoServiceIntegrationTest() { + super(serviceName + "/" + versionNumber, serviceName); + this.returnedUrl = serviceUrl; + } + + @Test + public void testGetUnknown() throws InterruptedException, TimeoutException, ExecutionException { + getUnknown(getRandomSystemId(), getRandomJvmId()); + } + + @Test + public void testCreateOne() throws InterruptedException, TimeoutException, ExecutionException { + + final String systemid = getRandomSystemId(); + final String jvmid = getRandomJvmId(); + post(systemid, jvmid); + getKnown(systemid, jvmid); + } + + @Test + public void testPut() throws InterruptedException, TimeoutException, ExecutionException { + + final String systemid = getRandomSystemId(); + final String jvmid = getRandomJvmId(); + + final long timestamp = getTimestamp(); + + // create it + post(systemid, jvmid); + + // retrieve it + final ContentResponse response1 = getKnown(systemid, jvmid); + final List<TinyJvmIo> list1 = parse(response1, jvmid); + assertEquals(1, list1.size()); + + // modify it + put(systemid, jvmid, timestamp+1); + + // ensure it was changed + final ContentResponse response2 = getKnown(systemid, jvmid); + final List<TinyJvmIo> list2 = parse(response2, jvmid); + assertEquals(1, list2.size()); + } + + @Test + public void testDeleteUnknown() throws InterruptedException, TimeoutException, ExecutionException { + final String systemid = getRandomSystemId(); + final String jvmid = getRandomJvmId(); + // delete it + delete(systemid, jvmid); + } + + @Test + public void testDeleteOne() throws InterruptedException, ExecutionException, TimeoutException { + final String systemid = getRandomSystemId(); + final String jvmid = getRandomJvmId(); + + // create the new record + post(systemid, jvmid); + + // check that it's there + getKnown(systemid, jvmid); + + // delete it + delete(systemid, jvmid); + + // check that it's not there + getUnknown(systemid, jvmid); + } + + + + @Test + public void testGetWithUnsupportedQuery() throws InterruptedException, TimeoutException, ExecutionException { + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?xyz=5", 200, HttpTestUtil.EMPTY_RESPONSE); + } + + @Test + public void testDefaultLimitOne() throws InterruptedException, TimeoutException, ExecutionException { + String expected = "{\"response\":[{\"a\":\"b\"" + SYSTEM_JVM_FRAGMENT + "}]}"; + HttpTestUtil.addRecords(client, serviceUrl, "[{\"a\":\"b\"},{\"a\":\"d\"}]"); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?s=+a&l=", 200, expected); + } + + @Test + public void testGetWithCommaQuery() throws InterruptedException, TimeoutException, ExecutionException { + String expectedFirst = "{\"response\":[{\"a\":\"b\",\"c\":\"d\",\"e\":\"f\"" + SYSTEM_JVM_FRAGMENT + "}]}"; + String expectedAll = "{\"response\":[{\"a\":\"b\",\"c\":\"d\",\"e\":\"f\"" + SYSTEM_JVM_FRAGMENT + "},{\"x\":\"y\"" + SYSTEM_JVM_FRAGMENT + "},{\"z\":\"z\"" + SYSTEM_JVM_FRAGMENT + "}]}"; + HttpTestUtil.addRecords(client, serviceUrl, "[{\"a\":\"b\",\"c\":\"d\",\"e\":\"f\"},{\"x\":\"y\"},{\"z\":\"z\"}]"); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + LIMIT_PREFIX + "=5", 200, expectedAll); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + QUERY_PREFIX + "=a==b", 200, expectedFirst); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + QUERY_PREFIX + "=c==d", 200, expectedFirst); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + QUERY_PREFIX + "=a==b,c==d", 200, expectedFirst); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + QUERY_PREFIX + "=a==b,c==none", 200, HttpTestUtil.EMPTY_RESPONSE); + } + + @Test + public void testGetWithAmpersandQuery() throws InterruptedException, TimeoutException, ExecutionException { + String expectedAll = "{\"response\":[{\"a\":\"b\"" + SYSTEM_JVM_FRAGMENT + "},{\"c\":\"d\"" + SYSTEM_JVM_FRAGMENT + "}]}"; + String expectedAmpersand = "{\"response\":[{\"a\":\"b\"" + SYSTEM_JVM_FRAGMENT + "}]}"; + HttpTestUtil.addRecords(client, serviceUrl, "[{\"a\":\"b\"},{\"c\":\"d\"}]"); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + LIMIT_PREFIX + "=5", 200, expectedAll); + + // Since q=a==b&c==d means "q= 'a==b'" and "c= '=d'", we should only + // get 'a: b' back. + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + QUERY_PREFIX + "=a==b&c==d", 200, expectedAmpersand); + + // The following should find the one with multiple matches, not the + // single match. This means we will evaluate u==v only, and should get + // back the first one it finds since no limit query is specified. + String expectedSingleMatch = "{\"response\":[{\"u\":\"v\",\"x\":\"y\"" + SYSTEM_JVM_FRAGMENT + "}]}"; + String expectedMultiMatch = "{\"response\":[{\"u\":\"v\",\"x\":\"y\"" + SYSTEM_JVM_FRAGMENT + "},{\"u\":\"v\"" + SYSTEM_JVM_FRAGMENT + "}]}"; + HttpTestUtil.addRecords(client, serviceUrl, "[{\"x\":\"y\"},{\"u\":\"v\",\"x\":\"y\"},{\"u\":\"v\"}]"); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + QUERY_PREFIX + "=u==v&" + QUERY_PREFIX + "=x==y", 200, expectedSingleMatch); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + QUERY_PREFIX + "=u==v&" + QUERY_PREFIX + "=x==y&" + LIMIT_PREFIX + "=5", 200, expectedMultiMatch); + } + + @Test + public void testMultiplePosts() throws InterruptedException, TimeoutException, ExecutionException { + String expectedResponse = "{\"response\":[{\"fakedata\":\"test\"" + SYSTEM_JVM_FRAGMENT + "},{\"new\":\"data\"" + SYSTEM_JVM_FRAGMENT + "}]}"; + HttpTestUtil.addRecords(client, serviceUrl, "[{\"fakedata\":\"test\"}]"); + HttpTestUtil.addRecords(client, serviceUrl, "[{\"new\":\"data\"}]"); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + LIMIT_PREFIX + "=5", 200, expectedResponse); + } + + @Test + public void testPostPutAddsData() throws InterruptedException, TimeoutException, ExecutionException { + String expectedDataBeforePut = "{\"response\":[{\"a\":\"b\"" + SYSTEM_JVM_FRAGMENT + "}]}"; + String expectedDataAfterPut = "{\"response\":[{\"a\":\"b\"" + SYSTEM_JVM_FRAGMENT + ",\"x\":\"y\"}]}"; + HttpTestUtil.addRecords(client, serviceUrl, "[{\"a\":\"b\"},{\"a\":\"c\"}]"); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl, 200, expectedDataBeforePut); + HttpTestUtil.testContentResponse(client, HttpMethod.PUT, serviceUrl + "?" + QUERY_PREFIX + "=a==b", "{\"set\":{\"x\":\"y\"}}", 200); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl, 200, expectedDataAfterPut); + } + + @Test + public void testPostPutModifiesData() throws InterruptedException, TimeoutException, ExecutionException { + String expectedDataBeforePut = "{\"response\":[{\"a\":\"b\"" + SYSTEM_JVM_FRAGMENT + "}]}"; + String expectedDataAfterPut = "{\"response\":[{\"a\":\"c\"" + SYSTEM_JVM_FRAGMENT + "}]}"; + String expectedAllDataAfterPut = "{\"response\":[{\"a\":\"c\"" + SYSTEM_JVM_FRAGMENT + "},{\"x\":\"y\"" + SYSTEM_JVM_FRAGMENT + "}]}"; + HttpTestUtil.addRecords(client, serviceUrl, "[{\"a\":\"b\"},{\"x\":\"y\"}]"); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl, 200, expectedDataBeforePut); + HttpTestUtil.testContentResponse(client, HttpMethod.PUT, serviceUrl + "?" + QUERY_PREFIX + "=a==b", "{\"set\":{\"a\":\"c\"}}", 200); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl, 200, expectedDataAfterPut); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + LIMIT_PREFIX + "=5", 200, expectedAllDataAfterPut); + } + + @Test + public void testDeleteProperlyDeletesData() throws InterruptedException, TimeoutException, ExecutionException { + HttpTestUtil.addRecords(client, serviceUrl, "[{\"fakedata\":\"test\"}]"); + HttpTestUtil.testContentlessResponse(client, HttpMethod.DELETE, serviceUrl + "?" + QUERY_PREFIX + "=fakedata==test", 200); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl, 200, HttpTestUtil.EMPTY_RESPONSE); + + String expectedAfterDeletion = "{\"response\":[{\"c\":\"d\"" + SYSTEM_JVM_FRAGMENT + "}]}"; + HttpTestUtil.addRecords(client, serviceUrl, "[{\"fakedata\":\"test\",\"a\":\"b\"},{\"c\":\"d\"}]"); + HttpTestUtil.testContentlessResponse(client, HttpMethod.DELETE, serviceUrl + "?" + QUERY_PREFIX + "=a==b", 200); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl, 200, expectedAfterDeletion); + } + + @Test + public void testMalformedDeleteRequestDoesNotMutateData() throws InterruptedException, TimeoutException, ExecutionException { + String expectedDataResponse = "{\"response\":[{\"fakedata\":\"test\"" + SYSTEM_JVM_FRAGMENT + "}]}"; + HttpTestUtil.addRecords(client, serviceUrl, "[{\"fakedata\":\"test\"}]"); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl, 200, expectedDataResponse); + HttpTestUtil.testContentlessResponse(client, HttpMethod.DELETE, serviceUrl + "?" + QUERY_PREFIX + "=nosuchkey==", 200); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl, 200, expectedDataResponse); + } + + @Test + public void testPutDataWithoutUrlQuery() throws InterruptedException, TimeoutException, ExecutionException { + HttpTestUtil.addRecords(client, serviceUrl, "[{\"fakedata\":\"test\"}]"); + HttpTestUtil.testContentResponse(client, HttpMethod.PUT, serviceUrl, "{\"set\":{\"fakedata\":\"test\"}}", 200); + } + + @Test + public void testPostAndPutWithInvalidData() throws InterruptedException, TimeoutException, ExecutionException { + String expectedDataResponse = "{\"response\":[{\"fakedata\":\"test\"" + SYSTEM_JVM_FRAGMENT + "}]}"; + String urlQuery = serviceUrl + "?" + QUERY_PREFIX + "=nosuchkey==nosuchvalue"; + HttpTestUtil.addRecords(client, serviceUrl, "[{\"fakedata\":\"test\"}]"); + HttpTestUtil.testContentResponse(client, HttpMethod.PUT, urlQuery, "{\"set\":{\"fakedata\":\"somethingnew\"}}", 200); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + LIMIT_PREFIX + "=5", 200, expectedDataResponse); + } + + @Test + public void testPutWithIdenticalData() throws InterruptedException, TimeoutException, ExecutionException { + String expectedDataResponse = "{\"response\":[{\"fakedata\":\"test\"" + SYSTEM_JVM_FRAGMENT + "}]}"; + HttpTestUtil.addRecords(client, serviceUrl, "[{\"fakedata\":\"test\"}]"); + HttpTestUtil.testContentResponse(client, HttpMethod.PUT, serviceUrl, "{\"set\":{\"fakedata\":\"test\"}}", 200); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + LIMIT_PREFIX + "=5", 200, expectedDataResponse); + } + + @Test + public void testPutDifferentData() throws InterruptedException, TimeoutException, ExecutionException { + String expectedDataResponse = "{\"response\":[{\"a\":\"b\"" + SYSTEM_JVM_FRAGMENT + ",\"c\":\"d\"}]}"; + HttpTestUtil.addRecords(client, serviceUrl, "[{\"a\":\"b\"}]"); + HttpTestUtil.testContentResponse(client, HttpMethod.PUT, serviceUrl + "?" + QUERY_PREFIX + "=a==b", "{\"set\":{\"c\":\"d\"}}", 200); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + LIMIT_PREFIX + "=5", 200, expectedDataResponse); + } + + @Test + public void testChangeDataWithPutMultipleTimes() throws InterruptedException, TimeoutException, ExecutionException { + String expectedData = "{\"response\":[{\"a\":\"a2\"" + SYSTEM_JVM_FRAGMENT + ",\"b\":\"b2\",\"c\":\"c2\"}]}"; + HttpTestUtil.addRecords(client, serviceUrl, "[{\"a\":\"a2\"}]"); + HttpTestUtil.testContentResponse(client, HttpMethod.PUT, serviceUrl + "?" + QUERY_PREFIX + "=a==a2", "{\"set\":{\"b\":\"b2\"}}", 200); + HttpTestUtil.testContentResponse(client, HttpMethod.PUT, serviceUrl + "?" + QUERY_PREFIX + "=a==a2", "{\"set\":{\"c\":\"c2\"}}", 200); + + // It won't find the target from the query, so the addition should not occur to any object. + HttpTestUtil.testContentResponse(client, HttpMethod.PUT, serviceUrl + "?" + QUERY_PREFIX + "=a==none", "{\"set\":{\"d\":\"d2\"}}", 200); + + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + LIMIT_PREFIX + "=5", 200, expectedData); + } + + @Test + public void testGetWithBadUrlQuery() throws InterruptedException, TimeoutException, ExecutionException { + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + QUERY_PREFIX + "=2", 400); + } + + @Test + public void testGetLimitWithQuery() throws InterruptedException, TimeoutException, ExecutionException { + String expectedDataOne = "{\"response\":[{\"a\":\"a2\"" + SYSTEM_JVM_FRAGMENT + "}]}"; + String expectedDataAll = "{\"response\":[{\"a\":\"a2\"" + SYSTEM_JVM_FRAGMENT + "},{\"b\":\"b2\"" + SYSTEM_JVM_FRAGMENT + "}]}"; + HttpTestUtil.addRecords(client, serviceUrl, "[{\"a\":\"a2\"},{\"b\":\"b2\"}]"); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl, 200, expectedDataOne); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + LIMIT_PREFIX + "=2", 200, expectedDataAll); + } + + @Test + public void testQueryOffset() throws InterruptedException, TimeoutException, ExecutionException { + String expectedOffsetRestOfData = "{\"response\":[{\"b\":\"2\"" + SYSTEM_JVM_FRAGMENT + "},{\"c\":\"3\"" + SYSTEM_JVM_FRAGMENT + "}]}"; + HttpTestUtil.addRecords(client, serviceUrl, "[{\"a\":\"1\"},{\"b\":\"2\"},{\"c\":\"3\"}]"); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + OFFSET_PREFIX + "=1", 200, "{\"response\":[{\"b\":\"2\"" + SYSTEM_JVM_FRAGMENT + "}]}"); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + OFFSET_PREFIX + "=3", 200, HttpTestUtil.EMPTY_RESPONSE); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + LIMIT_PREFIX + "=5&" + OFFSET_PREFIX + "=1", 200, expectedOffsetRestOfData); + } + + @Test + public void testNegativeOffsetQuery() throws InterruptedException, TimeoutException, ExecutionException { + HttpTestUtil.addRecords(client, serviceUrl, "[{\"a\":\"1\"}]"); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + OFFSET_PREFIX + "=-1", 400); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + OFFSET_PREFIX + "=-582", 400); + } + + @Test + public void testQueryOrdering() throws InterruptedException, TimeoutException, ExecutionException { + String expectedGet = "{\"response\":[{\"a\":1" + SYSTEM_JVM_FRAGMENT + "},{\"a\":2" + SYSTEM_JVM_FRAGMENT + "}]}"; + String expectedGetReverse = "{\"response\":[{\"a\":2" + SYSTEM_JVM_FRAGMENT + "},{\"a\":1" + SYSTEM_JVM_FRAGMENT + "}]}"; + HttpTestUtil.addRecords(client, serviceUrl, "[{\"a\":1},{\"a\":2}]"); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + LIMIT_PREFIX + "=10&" + SORT_PREFIX + "=+a", 200, expectedGet); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + LIMIT_PREFIX + "=10&" + SORT_PREFIX + "=-a", 200, expectedGetReverse); + } + + @Test + public void testQueryProjection() throws InterruptedException, TimeoutException, ExecutionException { + String expectedGet = "{\"response\":[{\"b\":\"2\",\"c\":\"3\"}]}"; + HttpTestUtil.addRecords(client, serviceUrl, "[{\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"}]"); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + INCLUDE_PREFIX + "=b,c", 200, expectedGet); + } + + @Test + public void testGetWithMetaDataAndLimit() throws InterruptedException, TimeoutException, ExecutionException { + String data = "[{\"a\":\"test\",\"b\":\"test1\",\"c\":\"test2\"}, {\"b\":\"test1\"}," + + "{\"e\":\"test4\",\"b\":\"test1\"}]"; + + // {"response":["{\"a\":\"test\",\"b\":\"test1\",\"c\":\"test2\"}"], + // "metaData":{"payloadCount":1,"count":3, + // "next":"http://127.0.0.1:30000/jvm-io/0.0.2?o=1&l=1&q===test1&m=true"}} + String expectedResponse = "{\"response\":[{\"a\":\"test\",\"b\":\"test1\"," + + "\"c\":\"test2\"" + SYSTEM_JVM_FRAGMENT + "}],\"metaData\":{\"payloadCount\":1,\"count\":3," + + "\"next\":\"" + returnedUrl + "?" + OFFSET_PREFIX + "\\u003d1\\u0026" + LIMIT_PREFIX + "\\u003d1\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}"; + + HttpTestUtil.addRecords(client, serviceUrl, data); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + LIMIT_PREFIX + "=1", 200, expectedResponse); + } + + @Test + public void testGetWithVersions() throws InterruptedException, TimeoutException, ExecutionException { + String data = "[{\"a\":\"test\",\"b\":\"test1\",\"c\":\"test2\"}, {\"b\":\"test1\"}," + + "{\"e\":\"test4\",\"b\":\"test1\"}]"; + + String expectedResponse = "{\"response\":[{\"a\":\"test\",\"b\":\"test1\"," + + "\"c\":\"test2\"" + SYSTEM_JVM_FRAGMENT + "}],\"metaData\":{\"payloadCount\":1,\"count\":3," + + "\"next\":\"" + returnedUrl + "?" + OFFSET_PREFIX + "\\u003d1\\u0026" + LIMIT_PREFIX + "\\u003d1\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}"; + + HttpTestUtil.addRecords(client, serviceUrl, data); + final String url1 = baseUrl + "/" + serviceName + "/" + "0.0" + "/systems/" + AGENT_ID + "/jvms/" + JVM_ID; + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, url1 + "?" + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + LIMIT_PREFIX + "=1", 200, expectedResponse); + final String url2 = baseUrl + "/" + serviceName + "/" + "0.0.1" + "/systems/" + AGENT_ID + "/jvms/" + JVM_ID; + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, url2 + "?" + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + LIMIT_PREFIX + "=1", 200, expectedResponse); + final String url3 = baseUrl + "/" + serviceName + "/" + "0.0.3" + "/systems/" + AGENT_ID + "/jvms/" + JVM_ID; + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, url3 + "?" + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + LIMIT_PREFIX + "=1", 404, null); + } + + @Test + public void testGetWithMetaDataAndOffset() throws InterruptedException, TimeoutException, ExecutionException { + String data = "[{\"a\":\"test\",\"b\":\"test1\",\"c\":\"test2\"}, {\"b\":\"test1\"}," + + "{\"e\":\"test4\",\"b\":\"test1\"}]"; + + // {"response":["{\"b\":\"test1\"}"],"metaData":{"payloadCount":1,"count":3, + // "prev":"http://127.0.0.1:30000/jvm-io/0.0.2?q===test1&m=true&l=1", + // "next":"http://127.0.0.1:30000/jvm-io/0.0.2?o=2&l=1&q===test1&m=true"}} + String expectedResponse = "{\"response\":[{\"b\":\"test1\"" + SYSTEM_JVM_FRAGMENT + "}]," + + "\"metaData\":{\"payloadCount\":1,\"count\":3," + + "\"prev\":\"" + returnedUrl + "?" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\\u0026" + LIMIT_PREFIX + "\\u003d1\"," + + "\"next\":\"" + returnedUrl + "?" + OFFSET_PREFIX + "\\u003d2\\u0026" + LIMIT_PREFIX + "\\u003d1\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}"; + + HttpTestUtil.addRecords(client, serviceUrl, data); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + OFFSET_PREFIX + "=1", 200, expectedResponse); + } + + @Test + public void testGetMetDatPrevOffsetLessThanLimit() throws InterruptedException, TimeoutException, ExecutionException { + String data = "[{\"a\":\"test\",\"b\":\"test1\",\"c\":\"test2\"}, {\"b\":\"test1\"}," + + "{\"e\":\"test4\",\"b\":\"test1\"}, {\"b\":\"test1\"}, {\"b\":\"test1\"}]"; + + // {"response":["{\"b\":\"test1\"}","{\"e\":\"test4\",\"b\":\"test1\"}","{\"b\":\"test1\"}"], + // "metaData":{"payloadCount":1,"count":5, + // "prev":"http://127.0.0.1:30000/jvm-io/0.0.2?q===test1&m=true&l=1&o=0", + // "next":"http://127.0.0.1:30000/jvm-io/0.0.2?o=4&l=1&q===test1&m=true"}} + String expectedResponse = "{\"response\":[{\"b\":\"test1\"" + SYSTEM_JVM_FRAGMENT + "},{\"e\":\"test4\"," + + "\"b\":\"test1\"" + SYSTEM_JVM_FRAGMENT + "},{\"b\":\"test1\"" + SYSTEM_JVM_FRAGMENT + "}]," + + "\"metaData\":{\"payloadCount\":1,\"count\":5," + + "\"prev\":\"" + returnedUrl + "?" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue" + + "\\u0026" + LIMIT_PREFIX + "\\u003d1\\u0026" + OFFSET_PREFIX + "\\u003d0\",\"next\":\"" + returnedUrl + "?" + OFFSET_PREFIX + "\\u003d4" + + "\\u0026" + LIMIT_PREFIX + "\\u003d1\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}"; + + HttpTestUtil.addRecords(client, serviceUrl, data); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + OFFSET_PREFIX + "=1&" + LIMIT_PREFIX + "=3", 200, expectedResponse); + } + + @Test + public void testGetMetDatPrevOffsetBiggerThanLimit() throws InterruptedException, TimeoutException, ExecutionException { + String data = "[{\"a\":\"test\",\"b\":\"test1\",\"c\":\"test2\"}, {\"b\":\"test1\"}," + + "{\"e\":\"test4\",\"b\":\"test1\"}, {\"b\":\"test1\"}, {\"b\":\"test1\"}, " + + "{\"b\":\"test1\"}]"; + + // {"response":["{\"b\":\"test1\"}","{\"b\":\"test1\"}"], + // "metaData":{"payloadCount":1,"count":6, + // "prev":"http://127.0.0.1:30000/jvm-io/0.0.2?q===test1&m=true&l=2&o=1", + // "next":"http://127.0.0.1:30000/jvm-io/0.0.2?o=5&l=1&q===test1&m=true"}} + String expectedResponse = "{\"response\":[{\"b\":\"test1\"" + SYSTEM_JVM_FRAGMENT + "},{\"b\":\"test1\"" + SYSTEM_JVM_FRAGMENT + "}]," + + "\"metaData\":{\"payloadCount\":1,\"count\":6," + + "\"prev\":\"" + returnedUrl + "?" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\\u0026" + LIMIT_PREFIX + "\\u003d2\\u0026" + OFFSET_PREFIX + "\\u003d1\"," + + "\"next\":\"" + returnedUrl + "?" + OFFSET_PREFIX + "\\u003d5\\u0026" + LIMIT_PREFIX + "\\u003d1\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}"; + + HttpTestUtil.addRecords(client, serviceUrl, data); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + OFFSET_PREFIX + "=3&" + LIMIT_PREFIX + "=2", 200, expectedResponse); + } + + @Test + public void testGetMetDatPrevOffsetEqualToLimit() throws InterruptedException, TimeoutException, ExecutionException { + String data = "[{\"a\":\"test\",\"b\":\"test1\",\"c\":\"test2\"}, {\"b\":\"test1\"}," + + "{\"e\":\"test4\",\"b\":\"test1\"}]"; + + // {"response":["{\"b\":\"test1\"}"], + // "metaData":{"payloadCount":1,"count":3, + // "prev":"http://127.0.0.1:30000/jvm-io/0.0.2?q===test1&m=true&l=1", + // "next":"http://127.0.0.1:30000/jvm-io/0.0.2?o=2&l=1&q===test1&m=true"}} + String expectedResponse = "{\"response\":[{\"b\":\"test1\"" + SYSTEM_JVM_FRAGMENT + "}]," + + "\"metaData\":{\"payloadCount\":1,\"count\":3," + + "\"prev\":\"" + returnedUrl + "?" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\\u0026" + LIMIT_PREFIX + "\\u003d1\"," + + "\"next\":\"" + returnedUrl + "?" + OFFSET_PREFIX + "\\u003d2\\u0026" + LIMIT_PREFIX + "\\u003d1\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}"; + + HttpTestUtil.addRecords(client, serviceUrl, data); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + OFFSET_PREFIX + "=1&" + LIMIT_PREFIX + "=1", 200, expectedResponse); + } + + @Test + public void testGetMetDatNextOffsetLessThanLimit() throws InterruptedException, TimeoutException, ExecutionException { + String data = "[{\"a\":\"test\",\"b\":\"test1\",\"c\":\"test2\"}, {\"b\":\"test1\"}," + + "{\"e\":\"test4\",\"b\":\"test1\"}, {\"b\":\"test1\"}, {\"b\":\"test1\"}, " + + "{\"b\":\"test1\"}]"; + + // {"response":["{\"b\":\"test1\"}","{\"e\":\"test4\",\"b\":\"test1\"}"], + // "metaData":{"payloadCount":2,"count":6, + // "prev":"http://127.0.0.1:30000/jvm-io/0.0.2?q===test1&m=true&l=1&o=0", + // "next":"http://127.0.0.1:30000/jvm-io/0.0.2?o=3&l=2&q===test1&m=true"}} + String expectedResponse = "{\"response\":[{\"b\":\"test1\"" + SYSTEM_JVM_FRAGMENT + "},{\"e\":\"test4\"," + + "\"b\":\"test1\"" + SYSTEM_JVM_FRAGMENT + "}],\"metaData\":{\"payloadCount\":2,\"count\":6," + + "\"prev\":\"" + returnedUrl + "?" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\\u0026" + LIMIT_PREFIX + "\\u003d1\\u0026" + OFFSET_PREFIX + "\\u003d0\"," + + "\"next\":\"" + returnedUrl + "?" + OFFSET_PREFIX + "\\u003d3\\u0026" + LIMIT_PREFIX + "\\u003d2\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}"; + + HttpTestUtil.addRecords(client, serviceUrl, data); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + OFFSET_PREFIX + "=1&" + LIMIT_PREFIX + "=2", 200, expectedResponse); + } + + @Test + public void testGetMetDatNextOffsetBiggerThanLimit() throws InterruptedException, TimeoutException, ExecutionException { + String data = "[{\"a\":\"test\",\"b\":\"test1\",\"c\":\"test2\"}, {\"b\":\"test1\"}," + + "{\"e\":\"test4\",\"b\":\"test1\"}, {\"b\":\"test1\"}, {\"b\":\"test1\"}, " + + "{\"b\":\"test1\"}]"; + + // {"response":["{\"b\":\"test1\"}","{\"b\":\"test1\"}"], + // "metaData":{"payloadCount":1,"count":6, + // "prev":"http://127.0.0.1:30000/jvm-io/0.0.2?q===test1&m=true&l=2&o=1", + // "next":"http://127.0.0.1:30000/jvm-io/0.0.2?o=5&l=1&q===test1&m=true"}} + String expectedResponse = "{\"response\":[{\"b\":\"test1\"" + SYSTEM_JVM_FRAGMENT + "},{\"b\":\"test1\"" + SYSTEM_JVM_FRAGMENT + "}]," + + "\"metaData\":{\"payloadCount\":1,\"count\":6," + + "\"prev\":\"" + returnedUrl + "?" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\\u0026" + LIMIT_PREFIX + "\\u003d2\\u0026" + OFFSET_PREFIX + "\\u003d1\"," + + "\"next\":\"" + returnedUrl + "?" + OFFSET_PREFIX + "\\u003d5\\u0026" + LIMIT_PREFIX + "\\u003d1\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}"; + + HttpTestUtil.addRecords(client, serviceUrl, data); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + OFFSET_PREFIX + "=3&" +LIMIT_PREFIX + "=2", 200, expectedResponse); + } + + @Test + public void testGetMetDatNextOffsetEqualToLimit() throws InterruptedException, TimeoutException, ExecutionException { + String data = "[{\"a\":\"test\",\"b\":\"test1\",\"c\":\"test2\"}, {\"b\":\"test1\"}," + + "{\"e\":\"test4\",\"b\":\"test1\"}, {\"b\":\"test1\"}, {\"b\":\"test1\"}, " + + "{\"b\":\"test1\"}]"; + // {"response":["{\"e\":\"test4\",\"b\":\"test1\"}","{\"b\":\"test1\"}"], + // "metaData":{"payloadCount":2,"count":6, + // "prev":"http://127.0.0.1:30000/jvm-io/0.0.2?q===test1&m=true&l=2&o=0", + // "next":"http://127.0.0.1:30000/jvm-io/0.0.2?o=4&l=2&q===test1&m=true"}} + String expectedResponse = "{\"response\":[{\"e\":\"test4\",\"b\":\"test1\"" + SYSTEM_JVM_FRAGMENT + "},{\"b\":\"test1\"" + SYSTEM_JVM_FRAGMENT + "}]," + + "\"metaData\":{\"payloadCount\":2,\"count\":6," + + "\"prev\":\"" + returnedUrl + "?" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\\u0026" + LIMIT_PREFIX + "\\u003d2\\u0026" + OFFSET_PREFIX + "\\u003d0\"," + + "\"next\":\"" + returnedUrl + "?" + OFFSET_PREFIX + "\\u003d4\\u0026" + LIMIT_PREFIX + "\\u003d2\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}"; + + HttpTestUtil.addRecords(client, serviceUrl, data); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + OFFSET_PREFIX + "=2&" + LIMIT_PREFIX + "=2", 200, expectedResponse); + } + + @Test + public void testGetMetDatNextExtremity() throws InterruptedException, TimeoutException, ExecutionException { + String data = "[{\"a\":\"test\",\"b\":\"test1\",\"c\":\"test2\"}, {\"b\":\"test1\"}," + + "{\"e\":\"test4\",\"b\":\"test1\"}, {\"b\":\"test1\"}, {\"b\":\"test1\"}, " + + "{\"b\":\"test1\"}]"; + + // {"response":["{\"e\":\"test4\",\"b\":\"test1\"}","{\"b\":\"test1\"}"], + // "metaData":{"payloadCount":2,"count":6, + // "prev":"http://127.0.0.1:30000/jvm-io/0.0.2?q===test1&m=true&l=2&o=0", + // "next":"http://127.0.0.1:30000/jvm-io/0.0.2?o=4&l=2&q===test1&m=true"}} + String expectedResponse = "{\"response\":[{\"e\":\"test4\",\"b\":\"test1\"" + SYSTEM_JVM_FRAGMENT + "},{\"b\":\"test1\"" + SYSTEM_JVM_FRAGMENT + "}]," + + "\"metaData\":{\"payloadCount\":2,\"count\":6," + + "\"prev\":\"" + returnedUrl + "?" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\\u0026" + LIMIT_PREFIX + "\\u003d2\\u0026" + OFFSET_PREFIX + "\\u003d0\"," + + "\"next\":\"" + returnedUrl + "?" + OFFSET_PREFIX + "\\u003d4\\u0026" + LIMIT_PREFIX + "\\u003d2\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}"; + + HttpTestUtil.addRecords(client, serviceUrl, data); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + OFFSET_PREFIX + "=2&" + LIMIT_PREFIX + "=2", 200, expectedResponse); + } + + @Test + public void testGetMetDatPrevExtremity() throws InterruptedException, TimeoutException, ExecutionException { + String data = "[{\"a\":\"test\",\"b\":\"test1\",\"c\":\"test2\"}, {\"b\":\"test1\"}," + + "{\"e\":\"test4\",\"b\":\"test1\"}, {\"b\":\"test1\"}, {\"b\":\"test1\"}, " + + "{\"b\":\"test1\"}]"; + + // {"response":["{\"e\":\"test4\",\"b\":\"test1\"}","{\"b\":\"test1\"}","{\"b\":\"test1\"}"]," + // metaData":{"payloadCount":1,"count":6, + // "prev":"http://127.0.0.1:30000/jvm-io/0.0.2?q=b==test1&m=true&l=2&o=0", + // "next":"http://127.0.0.1:30000/jvm-io/0.0.2?o=5&l=1&q=b==test1&m=true"}} + String expectedResponse = "{\"response\":[{\"e\":\"test4\",\"b\":\"test1\"" + SYSTEM_JVM_FRAGMENT + "}," + + "{\"b\":\"test1\"" + SYSTEM_JVM_FRAGMENT + "},{\"b\":\"test1\"" + SYSTEM_JVM_FRAGMENT + "}]," + + "\"metaData\":{\"payloadCount\":1,\"count\":6," + + "\"prev\":\"" + returnedUrl + "?" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\\u0026" + LIMIT_PREFIX + "\\u003d2\\u0026" + OFFSET_PREFIX + "\\u003d0\"," + + "\"next\":\"" + returnedUrl + "?" + OFFSET_PREFIX + "\\u003d5\\u0026" + LIMIT_PREFIX + "\\u003d1\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}"; + + HttpTestUtil.addRecords(client, serviceUrl, data); + HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, serviceUrl + "?" + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + OFFSET_PREFIX + "=2&" + LIMIT_PREFIX + "=3", 200, expectedResponse); + } + + + private static String getRandomSystemId() { + return UUID.randomUUID().toString(); + } + + private static String getRandomJvmId() { + return UUID.randomUUID().toString(); + } + + private String createJSON() { + return createJSON(getTimestamp()); + } + + private long getTimestamp() { + timeStamp += 1; + return timeStamp; + } + + private String createJSON(final long ts) { + return jsonData.replace(TIMESTAMP_TOKEN, Long.toString(ts)); + } + + private ContentResponse put(final String systemid, final String jvmid, final long ts) throws InterruptedException, ExecutionException, TimeoutException { + final Request request = client.newRequest(simpleUrl + "/systems/" + systemid + "/jvms/" + jvmid); + request.header(HttpHeader.CONTENT_TYPE, "application/json"); + final String contentStr = createJSON(ts); + request.content(new StringContentProvider("{ \"set\" : " +contentStr + "}")); + ContentResponse response = request.method(HttpMethod.PUT).send(); + assertEquals(HTTP_200_OK, response.getStatus()); + final String expected = ""; + assertEquals(expected, response.getContentAsString()); + return response; + } + + private ContentResponse post(final String systemid, final String jvmid) throws InterruptedException, ExecutionException, TimeoutException { + final Request request = client.newRequest(simpleUrl + "/systems/" + systemid + "/jvms/" + jvmid); + request.header(HttpHeader.CONTENT_TYPE, "application/json"); + request.content(new StringContentProvider( '[' + createJSON() + ']')); + ContentResponse response = request.method(HttpMethod.POST).send(); + assertEquals(HTTP_200_OK, response.getStatus()); + final String expected = ""; + assertEquals(expected, response.getContentAsString()); + return response; + } + + private ContentResponse getUnknown(final String systemid, final String jvmid) throws InterruptedException, ExecutionException, TimeoutException { + ContentResponse response = get(systemid, jvmid); + assertTrue(parse(response, jvmid).isEmpty()); + return response; + } + + private ContentResponse getKnown(final String systemid, final String jvmid) throws InterruptedException, ExecutionException, TimeoutException { + ContentResponse response = get(systemid, jvmid); + assertEquals(1, parse(response, jvmid).size()); + return response; + } + + private ContentResponse get(final String systemid, final String jvmid) throws InterruptedException, ExecutionException, TimeoutException { + ContentResponse response = client.newRequest(simpleUrl + "/systems/" + systemid + "/jvms/" + jvmid).method(HttpMethod.GET).send(); + assertEquals(HTTP_200_OK, response.getStatus()); + return response; + } + + private ContentResponse get(final String systemid, final String jvmid, final String query) throws InterruptedException, ExecutionException, TimeoutException { + final Request rq = client.newRequest(simpleUrl + "/systems/" + systemid + "/jvms/" + jvmid + query); + rq.method(HttpMethod.GET); + ContentResponse response = rq.send(); + assertEquals(HTTP_200_OK, response.getStatus()); + return response; + } + + private ContentResponse delete(final String systemid, final String jvmid) throws InterruptedException, ExecutionException, TimeoutException { + ContentResponse response = client.newRequest(simpleUrl + "/systems/" + systemid + "/jvms/" + jvmid).method(HttpMethod.DELETE).send(); + assertEquals(HTTP_200_OK, response.getStatus()); + final String expected = ""; + assertEquals(expected, response.getContentAsString()); + return response; + } + + class TinyJvmIo { + String jvmId; + long timeStamp; + public TinyJvmIo(String jvmId, long ts) { + this.jvmId = jvmId; + this.timeStamp = ts; + } + } + private List<TinyJvmIo> parse(ContentResponse contentResponse, final String expectedJvmId) { + + JsonParser parser = new JsonParser(); + JsonObject json = (JsonObject) parser.parse(contentResponse.getContentAsString()); + JsonElement response = json.get("response"); + + JsonArray allData = response.getAsJsonArray(); + List<TinyJvmIo> result = new ArrayList<>(); + + for (JsonElement entry : allData) { + + json = (JsonObject) parser.parse(entry.toString()); + + assertTrue(json.has("jvmId")); + //assertTrue(json.has("agentId")); + assertTrue(json.has("timeStamp")); + + final String jvmId = json.get("jvmId").getAsString(); + //final String agentId = json.get("agentId").getAsString(); + //final long timeStamp = getLong(json, "timeStamp"); + + if (expectedJvmId != null) { + assertEquals(expectedJvmId, jvmId); + } + + TinyJvmIo hi = new TinyJvmIo(jvmId, 0); + + result.add(hi); + } + return result; + } + + private static long getLong(JsonObject json, final String id) { + JsonElement el = json.get(id); + if (el.isJsonObject()) { + final JsonObject o = el.getAsJsonObject(); + return o.get("$numberLong").getAsLong(); + } else { + return el.getAsLong(); + } + } +}