diff --git a/src/main/java/com/coscale/sdk/client/ApiClient.java b/src/main/java/com/coscale/sdk/client/ApiClient.java index 257f325..a7fdad9 100755 --- a/src/main/java/com/coscale/sdk/client/ApiClient.java +++ b/src/main/java/com/coscale/sdk/client/ApiClient.java @@ -29,7 +29,7 @@ public class ApiClient { private final String APPID; /** API_PATH, API_VERSION for request URL. */ - private final String API_PATH = "api"; + private static final String API_PATH = "api"; private String API_VERSION = "v1"; /** URL path separator */ @@ -199,19 +199,20 @@ public int getDeserializationExceptions() { * used by request. * @param uri * of the API call. - * @param data - * in string format to pass to the request. + * @param payload + * data in string format to pass to the request. + * @param authenticate + * True if the call requires authenticate, false if not. * @return String response for the request. * @throws IOException */ private String doHttpRequest(String method, String uri, String payload, boolean authenticate) throws IOException { - URL url; HttpURLConnection conn = null; int responseCode = -1; try { - url = new URL(uri); + URL url = new URL(uri); conn = (HttpURLConnection) url.openConnection(); // Set connection timeout. @@ -288,8 +289,7 @@ private void login() throws IOException { String uri = credentials.usesToken() ? getAppRequestURL("/login/") : getGlobalRequestURL("/users/login/"); Credentials.TokenHelper data = call("POST", uri, credentials, - new TypeReference() { - }, false); + new TokenHelperTypeReference(), false); token = data.token; } @@ -328,6 +328,7 @@ public T callWithAuth(String method, String endpoint, Object obj, TypeRefere } catch (CoscaleApiException e) { if (e.statusCode == HttpURLConnection.HTTP_UNAUTHORIZED) { this.token = null; // will trigger new login + responseCode = 401; // 401 means login failed: https://httpstatuses.com/401 } else { throw e; } @@ -349,6 +350,8 @@ public T callWithAuth(String method, String endpoint, Object obj, TypeRefere * object with data for the request. This parameter can be null. * @param valueType * is the type expected. + * @param auth + * true if the call requires authentication, false if not. * @return The Object received as a result for the request. * @throws IOException */ @@ -410,11 +413,11 @@ public String getGlobalRequestURL(String endpoint) { public String getRequesUrl(String endpoint, Options options, boolean globalApi) { StringBuilder sb = new StringBuilder(); - sb.append(getBaseURL()); + sb.append(API_BASE_URL); sb.append(PATH_DIV); - sb.append(getApiPath()); + sb.append(API_PATH); sb.append(PATH_DIV); - sb.append(getApiVersion()); + sb.append(API_VERSION); if (!globalApi) { sb.append(PATH_DIV); sb.append("app"); @@ -486,4 +489,12 @@ private String objectToJson(T obj) throws IOException { } } } + + /** + * Copied from the Intellij code analysis: + * A static inner class does not keep an implicit reference to its enclosing instance. + * This prevents a common cause of memory leaks and uses less memory per instance of the class. + */ + private static class TokenHelperTypeReference extends TypeReference { + } } \ No newline at end of file diff --git a/src/main/java/com/coscale/sdk/client/data/DataApi.java b/src/main/java/com/coscale/sdk/client/data/DataApi.java index b3d07af..42c97ee 100755 --- a/src/main/java/com/coscale/sdk/client/data/DataApi.java +++ b/src/main/java/com/coscale/sdk/client/data/DataApi.java @@ -35,7 +35,14 @@ public DataApi(ApiClient api) { * @throws IOException */ public Msg insert(String subjectId, DataInsert data) throws IOException { - return api.callWithAuth("POST", "/data/" + subjectId + '/', data, new TypeReference() { - }); + return api.callWithAuth("POST", "/data/" + subjectId + '/', data, new MsgTypeReference()); + } + + /** + * Copied from the Intellij code analysis: + * A static inner class does not keep an implicit reference to its enclosing instance. + * This prevents a common cause of memory leaks and uses less memory per instance of the class. + */ + private static class MsgTypeReference extends TypeReference { } } diff --git a/src/main/java/com/coscale/sdk/client/events/EventsApi.java b/src/main/java/com/coscale/sdk/client/events/EventsApi.java index a8b58f4..3f71863 100755 --- a/src/main/java/com/coscale/sdk/client/events/EventsApi.java +++ b/src/main/java/com/coscale/sdk/client/events/EventsApi.java @@ -39,8 +39,7 @@ public EventsApi(ApiClient api) { * @throws IOException */ public List all() throws IOException { - return api.callWithAuth("GET", "/events/", null, new TypeReference>() { - }); + return api.callWithAuth("GET", "/events/", null, new EventListTypeReference()); } /** @@ -54,8 +53,7 @@ public List all() throws IOException { public List all(Options options) throws IOException { String url = "/events/"; url += (options.hasQuery() ? "?" : "&") + options.query(); - return api.callWithAuth("GET", url, null, new TypeReference>() { - }); + return api.callWithAuth("GET", url, null, new EventListTypeReference()); } /** @@ -67,8 +65,7 @@ public List all(Options options) throws IOException { * @throws IOException */ public Event get(long id) throws IOException { - return api.callWithAuth("GET", "/events/" + id + '/', null, new TypeReference() { - }); + return api.callWithAuth("GET", "/events/" + id + '/', null, new EventTypeReference()); } /** @@ -80,8 +77,7 @@ public Event get(long id) throws IOException { * @throws IOException */ public Event insert(EventInsert event) throws IOException { - return api.callWithAuth("POST", "/events/", event, new TypeReference() { - }); + return api.callWithAuth("POST", "/events/", event, new EventTypeReference()); } /** @@ -93,8 +89,7 @@ public Event insert(EventInsert event) throws IOException { * @throws IOException */ public Msg delete(long id) throws IOException { - return api.callWithAuth("DELETE", "/events/" + id + '/', null, new TypeReference() { - }); + return api.callWithAuth("DELETE", "/events/" + id + '/', null, new MsgTypeReference()); } /** Events data end point calls. */ @@ -127,8 +122,7 @@ public List allData(Long eventId, @Nullable Long start, @Nullable Lon first = false; } - return api.callWithAuth("GET", endpoint, null, new TypeReference>() { - }); + return api.callWithAuth("GET", endpoint, null, new EventDataListTypeReference()); } /** @@ -143,8 +137,7 @@ public List allData(Long eventId, @Nullable Long start, @Nullable Lon */ public EventData getData(Long eventId, Long dataId) throws IOException { return api.callWithAuth("GET", "/events/" + eventId + "/data/get/" + dataId + '/', null, - new TypeReference() { - }); + new EventDataTypeReference()); } /** @@ -159,8 +152,7 @@ public EventData getData(Long eventId, Long dataId) throws IOException { */ public EventData insertData(Long eventId, EventDataInsert data) throws IOException { return api.callWithAuth("POST", "/events/" + eventId + "/data/", data, - new TypeReference() { - }); + new EventDataTypeReference()); } /** @@ -175,8 +167,26 @@ public EventData insertData(Long eventId, EventDataInsert data) throws IOExcepti */ public Msg deleteData(Long eventId, Long dataId) throws IOException { return api.callWithAuth("DELETE", "/events/" + eventId + "/data/" + dataId + '/', null, - new TypeReference() { - }); + new MsgTypeReference()); } + /** + * Copied from the Intellij code analysis: + * A static inner class does not keep an implicit reference to its enclosing instance. + * This prevents a common cause of memory leaks and uses less memory per instance of the class. + */ + private static class EventListTypeReference extends TypeReference> { + } + + private static class EventTypeReference extends TypeReference { + } + + private static class MsgTypeReference extends TypeReference { + } + + private static class EventDataListTypeReference extends TypeReference> { + } + + private static class EventDataTypeReference extends TypeReference { + } } diff --git a/src/main/java/com/coscale/sdk/client/metrics/MetricGroup.java b/src/main/java/com/coscale/sdk/client/metrics/MetricGroup.java index bb5bffc..3224f98 100755 --- a/src/main/java/com/coscale/sdk/client/metrics/MetricGroup.java +++ b/src/main/java/com/coscale/sdk/client/metrics/MetricGroup.java @@ -4,6 +4,7 @@ import com.google.common.base.MoreObjects; import com.google.common.base.Objects; +import com.google.common.collect.Lists; public class MetricGroup { @@ -48,13 +49,13 @@ public MetricGroup(Long id, String source, java.util.List metrics, Subje java.util.List metricIds, String type, Long version) { this.id = id; this.source = source; - this.metrics = metrics; + this.metrics = Lists.newArrayList(metrics); // Copy the contents, don't keep reference. this.subject = subject; this.description = description; this.name = name; this.state = state; - this.metricgroups = metricgroups; - this.metricIds = metricIds; + this.metricgroups = Lists.newArrayList(metricgroups); + this.metricIds = Lists.newArrayList(metricIds); this.type = type; this.version = version; } diff --git a/src/main/java/com/coscale/sdk/client/metrics/MetricsApi.java b/src/main/java/com/coscale/sdk/client/metrics/MetricsApi.java index 8bf6b88..de8045c 100755 --- a/src/main/java/com/coscale/sdk/client/metrics/MetricsApi.java +++ b/src/main/java/com/coscale/sdk/client/metrics/MetricsApi.java @@ -37,8 +37,7 @@ public MetricsApi(ApiClient api) { * @throws IOException */ public List all() throws IOException { - return api.callWithAuth("GET", "/metrics/", null, new TypeReference>() { - }); + return api.callWithAuth("GET", "/metrics/", null, new MetricListTypeReference()); } /** @@ -52,8 +51,7 @@ public List all() throws IOException { public List all(Options options) throws IOException { String url = "/metrics/"; url += (options.hasQuery() ? "?" : "&") + options.query(); - return api.callWithAuth("GET", url, null, new TypeReference>() { - }); + return api.callWithAuth("GET", url, null, new MetricListTypeReference()); } /** @@ -65,8 +63,7 @@ public List all(Options options) throws IOException { * @throws IOException */ public Metric get(long id) throws IOException { - return api.callWithAuth("GET", "/metrics/" + id + '/', null, new TypeReference() { - }); + return api.callWithAuth("GET", "/metrics/" + id + '/', null, new MetricTypeReference()); } /** @@ -78,8 +75,7 @@ public Metric get(long id) throws IOException { * @throws IOException */ public Metric insert(MetricInsert metric) throws IOException { - return api.callWithAuth("POST", "/metrics/", metric, new TypeReference() { - }); + return api.callWithAuth("POST", "/metrics/", metric, new MetricTypeReference()); } /** @@ -91,8 +87,7 @@ public Metric insert(MetricInsert metric) throws IOException { * @throws IOException */ public Msg delete(long id) throws IOException { - return api.callWithAuth("DELETE", "/metrics/" + id + '/', null, new TypeReference() { - }); + return api.callWithAuth("DELETE", "/metrics/" + id + '/', null, new MsgTypeReference()); } /** Metric groups Calls */ @@ -105,8 +100,7 @@ public Msg delete(long id) throws IOException { */ public List getAllMetricGroups() throws IOException { return api.callWithAuth("GET", "/metricgroups/", null, - new TypeReference>() { - }); + new MetricGroupListTypeReference()); } /** @@ -121,8 +115,7 @@ public List getAllMetricGroups() throws IOException { public List getAllMetricGroups(Options options) throws IOException { String url = "/metricgroups/"; url += (options.hasQuery() ? "?" : "&") + options.query(); - return api.callWithAuth("GET", url, null, new TypeReference>() { - }); + return api.callWithAuth("GET", url, null, new MetricGroupListTypeReference()); } /** @@ -135,8 +128,7 @@ public List getAllMetricGroups(Options options) throws IOException */ public MetricGroup getMetricGroup(long id) throws IOException { return api.callWithAuth("GET", "/metricgroups/" + id + '/', null, - new TypeReference() { - }); + new MetricGroupTypeReference()); } /** @@ -150,8 +142,7 @@ public MetricGroup getMetricGroup(long id) throws IOException { */ public MetricGroup insertMetricGroup(MetricGroupInsert metricGroup) throws IOException { return api.callWithAuth("POST", "/metricgroups/", metricGroup, - new TypeReference() { - }); + new MetricGroupTypeReference()); } /** @@ -164,8 +155,7 @@ public MetricGroup insertMetricGroup(MetricGroupInsert metricGroup) throws IOExc */ public Msg deleteMetricGroup(long id) throws IOException { return api.callWithAuth("DELETE", "/metricgroups/" + id + '/', null, - new TypeReference() { - }); + new MsgTypeReference()); } /** @@ -178,8 +168,7 @@ public Msg deleteMetricGroup(long id) throws IOException { */ public List addGroupToGroup(long childId, long parentId) throws IOException { return api.callWithAuth("POST", "/metricgroups/" + parentId + "/metricgroups/" + childId - + '/', null, new TypeReference>() { - }); + + '/', null, new MetricGroupListTypeReference()); } /** @@ -192,8 +181,7 @@ public List addGroupToGroup(long childId, long parentId) throws IOE */ public List addMetricToGroup(long metricId, long groupId) throws IOException { return api.callWithAuth("POST", "/metricgroups/" + groupId + "/metrics/" + metricId + '/', - null, new TypeReference>() { - }); + null, new MetricListTypeReference()); } /** @@ -206,8 +194,7 @@ public List addMetricToGroup(long metricId, long groupId) throws IOExcep */ public List getGroupMetrics(long groupId) throws IOException { return api.callWithAuth("GET", "/metricgroups/" + groupId + "/metrics/", null, - new TypeReference>() { - }); + new MetricListTypeReference()); } /** @@ -223,8 +210,7 @@ public List getGroupMetrics(long groupId) throws IOException { public Msg deleteMetricFromGroup(long metricId, long groupId) throws IOException { return api.callWithAuth("DELETE", "/metricgroups/" + groupId + "/metrics/" + metricId + '/', null, - new TypeReference() { - }); + new MsgTypeReference()); } /** @@ -237,8 +223,7 @@ public Msg deleteMetricFromGroup(long metricId, long groupId) throws IOException */ public List getGroupsFromGroup(long groupId) throws IOException { return api.callWithAuth("GET", "/metricgroups/" + groupId + "/metricgroups/", null, - new TypeReference>() { - }); + new MetricGroupListTypeReference()); } /** @@ -254,7 +239,26 @@ public List getGroupsFromGroup(long groupId) throws IOException { */ public Msg deleteGroupFromGroup(long childId, long parentId) throws IOException { return api.callWithAuth("DELETE", "/metricgroups/" + parentId + "/metricgroups/" + childId - + '/', null, new TypeReference() { - }); + + '/', null, new MsgTypeReference()); + } + + /** + * Copied from the Intellij code analysis: + * A static inner class does not keep an implicit reference to its enclosing instance. + * This prevents a common cause of memory leaks and uses less memory per instance of the class. + */ + private static class MetricListTypeReference extends TypeReference> { + } + + private static class MetricTypeReference extends TypeReference { + } + + private static class MsgTypeReference extends TypeReference { + } + + private static class MetricGroupListTypeReference extends TypeReference> { + } + + private static class MetricGroupTypeReference extends TypeReference { } } diff --git a/src/main/java/com/coscale/sdk/client/requests/Request.java b/src/main/java/com/coscale/sdk/client/requests/Request.java index b408683..50da542 100644 --- a/src/main/java/com/coscale/sdk/client/requests/Request.java +++ b/src/main/java/com/coscale/sdk/client/requests/Request.java @@ -8,6 +8,7 @@ import com.coscale.sdk.client.metrics.State; import com.google.common.base.MoreObjects; import com.google.common.base.Objects; +import com.google.common.collect.Lists; public class Request { @@ -60,7 +61,7 @@ public Request(Protocol protocol, State state, String classifierConfig, Long ver this.id = id; this.parentId = parentId; this.classifierType = classifierType; - this.requests = requests; + this.requests = Lists.newArrayList(requests); this.source = source; this.description = description; this.priority = priority; diff --git a/src/main/java/com/coscale/sdk/client/requests/RequestsApi.java b/src/main/java/com/coscale/sdk/client/requests/RequestsApi.java index c6a48a1..026e0c4 100644 --- a/src/main/java/com/coscale/sdk/client/requests/RequestsApi.java +++ b/src/main/java/com/coscale/sdk/client/requests/RequestsApi.java @@ -37,8 +37,7 @@ public RequestsApi(ApiClient api) { * @throws IOException */ public List all() throws IOException { - return api.callWithAuth("GET", "/requests/", null, new TypeReference>() { - }); + return api.callWithAuth("GET", "/requests/", null, new RequestListTypeReference()); } /** @@ -52,8 +51,7 @@ public List all() throws IOException { public List all(Options options) throws IOException { String url = "/requests/"; url += (options.hasQuery() ? "?" : "&") + options.query(); - return api.callWithAuth("GET", url, null, new TypeReference>() { - }); + return api.callWithAuth("GET", url, null, new RequestListTypeReference()); } /** @@ -65,8 +63,7 @@ public List all(Options options) throws IOException { * @throws IOException */ public Request get(long id) throws IOException { - return api.callWithAuth("GET", "/requests/" + id + '/', null, new TypeReference() { - }); + return api.callWithAuth("GET", "/requests/" + id + '/', null, new RequestTypeReference()); } /** @@ -82,7 +79,17 @@ public Request get(long id) throws IOException { public Request get(long id, Options options) throws IOException { String url = "/requests/" + id + '/'; url += (options.hasQuery() ? "?" : "&") + options.query(); - return api.callWithAuth("GET", url, null, new TypeReference() { - }); + return api.callWithAuth("GET", url, null, new RequestTypeReference()); + } + + /** + * Copied from the Intellij code analysis: + * A static inner class does not keep an implicit reference to its enclosing instance. + * This prevents a common cause of memory leaks and uses less memory per instance of the class. + */ + private static class RequestListTypeReference extends TypeReference> { + } + + private static class RequestTypeReference extends TypeReference { } } \ No newline at end of file diff --git a/src/main/java/com/coscale/sdk/client/servers/Server.java b/src/main/java/com/coscale/sdk/client/servers/Server.java index d658933..c84be72 100755 --- a/src/main/java/com/coscale/sdk/client/servers/Server.java +++ b/src/main/java/com/coscale/sdk/client/servers/Server.java @@ -8,6 +8,7 @@ import com.coscale.sdk.client.metrics.State; import com.google.common.base.MoreObjects; import com.google.common.base.Objects; +import com.google.common.collect.Lists; public class Server { @@ -49,14 +50,14 @@ public Server(Long id, String source, List metrics, String description, List attributes) { this.id = id; this.source = source; - this.metrics = metrics; + this.metrics = Lists.newArrayList(metrics); this.description = description; this.name = name; this.state = state; - this.children = children; + this.children = Lists.newArrayList(children); this.type = type; this.version = version; - this.attributes = attributes; + this.attributes = Lists.newArrayList(attributes); } public Server() { diff --git a/src/main/java/com/coscale/sdk/client/servers/ServerGroup.java b/src/main/java/com/coscale/sdk/client/servers/ServerGroup.java index aeb6df3..7a2cc32 100644 --- a/src/main/java/com/coscale/sdk/client/servers/ServerGroup.java +++ b/src/main/java/com/coscale/sdk/client/servers/ServerGroup.java @@ -7,6 +7,7 @@ import com.coscale.sdk.client.metrics.State; import com.google.common.base.MoreObjects; import com.google.common.base.Objects; +import com.google.common.collect.Lists; public class ServerGroup { @@ -44,11 +45,11 @@ public ServerGroup(Long id, String source, List servers, String descript String name, State state, List servergroups, String type, Long version) { this.id = id; this.source = source; - this.servers = servers; + this.servers = Lists.newArrayList(servers); this.description = description; this.name = name; this.state = state; - this.servergroups = servergroups; + this.servergroups = Lists.newArrayList(servergroups); this.type = type; this.version = version; } diff --git a/src/main/java/com/coscale/sdk/client/servers/ServersApi.java b/src/main/java/com/coscale/sdk/client/servers/ServersApi.java index 5f6d520..1df7baf 100755 --- a/src/main/java/com/coscale/sdk/client/servers/ServersApi.java +++ b/src/main/java/com/coscale/sdk/client/servers/ServersApi.java @@ -36,8 +36,7 @@ public ServersApi(ApiClient api) { * @throws IOException */ public List all() throws IOException { - return api.callWithAuth("GET", "/servers/", null, new TypeReference>() { - }); + return api.callWithAuth("GET", "/servers/", null, new ServerListTypeReference()); } /** @@ -51,8 +50,7 @@ public List all() throws IOException { public List all(Options options) throws IOException { String url = "/servers/"; url += (options.hasQuery() ? "?" : "&") + options.query(); - return api.callWithAuth("GET", url, null, new TypeReference>() { - }); + return api.callWithAuth("GET", url, null, new ServerListTypeReference()); } /** @@ -65,8 +63,7 @@ public List all(Options options) throws IOException { */ public Server getServer(long serverId) throws IOException { return api.callWithAuth("GET", "/servers/" + serverId + '/', null, - new TypeReference() { - }); + new ServerTypeReference()); } /** @@ -82,8 +79,7 @@ public Server getServer(long serverId) throws IOException { public Server getServer(long serverId, Options options) throws IOException { String url = "/servers/" + serverId + '/'; url += (options.hasQuery() ? "?" : "&") + options.query(); - return api.callWithAuth("GET", url, null, new TypeReference() { - }); + return api.callWithAuth("GET", url, null, new ServerTypeReference()); } /** @@ -96,8 +92,7 @@ public Server getServer(long serverId, Options options) throws IOException { * @throws IOException */ public Server insert(ServerInsert serverInsert) throws IOException { - return api.callWithAuth("POST", "/servers/", serverInsert, new TypeReference() { - }); + return api.callWithAuth("POST", "/servers/", serverInsert, new ServerTypeReference()); } /** @@ -110,8 +105,7 @@ public Server insert(ServerInsert serverInsert) throws IOException { */ public Msg delete(long serverId) throws IOException { return api.callWithAuth("DELETE", "/servers/" + serverId + '/', null, - new TypeReference() { - }); + new MsgTypeReference()); } /** Server groups Calls */ @@ -123,9 +117,7 @@ public Msg delete(long serverId) throws IOException { * @throws IOException */ public List getAllServerGroups() throws IOException { - return api.callWithAuth("GET", "/servergroups/", null, - new TypeReference>() { - }); + return api.callWithAuth("GET", "/servergroups/", null, new ServerGroupListTypeReference()); } /** @@ -140,8 +132,7 @@ public List getAllServerGroups() throws IOException { public List getAllServerGroups(Options options) throws IOException { String url = "/servergroups/"; url += (options.hasQuery() ? "?" : "&") + options.query(); - return api.callWithAuth("GET", url, null, new TypeReference>() { - }); + return api.callWithAuth("GET", url, null, new ServerGroupListTypeReference()); } /** @@ -154,8 +145,7 @@ public List getAllServerGroups(Options options) throws IOException */ public ServerGroup getServerGroup(long id) throws IOException { return api.callWithAuth("GET", "/servergroups/" + id + '/', null, - new TypeReference() { - }); + new ServerGroupTypeReference()); } /** @@ -169,8 +159,7 @@ public ServerGroup getServerGroup(long id) throws IOException { */ public ServerGroup insertServerGroup(ServerGroupInsert serverGroup) throws IOException { return api.callWithAuth("POST", "/servergroups/", serverGroup, - new TypeReference() { - }); + new ServerGroupTypeReference()); } /** @@ -183,8 +172,7 @@ public ServerGroup insertServerGroup(ServerGroupInsert serverGroup) throws IOExc */ public Msg deleteServerGroup(long id) throws IOException { return api.callWithAuth("DELETE", "/servergroups/" + id + '/', null, - new TypeReference() { - }); + new MsgTypeReference()); } /** @@ -197,8 +185,7 @@ public Msg deleteServerGroup(long id) throws IOException { */ public List addGroupToGroup(long childId, long parentId) throws IOException { return api.callWithAuth("POST", "/servergroups/" + parentId + "/servergroups/" + childId - + '/', null, new TypeReference>() { - }); + + '/', null, new ServerGroupListTypeReference()); } /** @@ -211,8 +198,7 @@ public List addGroupToGroup(long childId, long parentId) throws IOE */ public List addServerToGroup(long serverId, long groupId) throws IOException { return api.callWithAuth("POST", "/servergroups/" + groupId + "/servers/" + serverId + '/', - null, new TypeReference>() { - }); + null, new ServerListTypeReference()); } /** @@ -225,8 +211,7 @@ public List addServerToGroup(long serverId, long groupId) throws IOExcep */ public List getGroupServers(long groupId) throws IOException { return api.callWithAuth("GET", "/servergroups/" + groupId + "/servers/", null, - new TypeReference>() { - }); + new ServerListTypeReference()); } /** @@ -242,8 +227,7 @@ public List getGroupServers(long groupId) throws IOException { public Msg deleteServerFromGroup(long serverId, long groupId) throws IOException { return api.callWithAuth("DELETE", "/servergroups/" + groupId + "/servers/" + serverId + '/', null, - new TypeReference() { - }); + new MsgTypeReference()); } /** @@ -256,8 +240,7 @@ public Msg deleteServerFromGroup(long serverId, long groupId) throws IOException */ public List getGroupsFromGroup(long groupId) throws IOException { return api.callWithAuth("GET", "/servergroups/" + groupId + "/servergroups/", null, - new TypeReference>() { - }); + new ServerGroupListTypeReference()); } /** @@ -273,7 +256,26 @@ public List getGroupsFromGroup(long groupId) throws IOException { */ public Msg deleteGroupFromGroup(long childId, long parentId) throws IOException { return api.callWithAuth("DELETE", "/servergroups/" + parentId + "/servergroups/" + childId - + '/', null, new TypeReference() { - }); + + '/', null, new MsgTypeReference()); + } + + /** + * Copied from the Intellij code analysis: + * A static inner class does not keep an implicit reference to its enclosing instance. + * This prevents a common cause of memory leaks and uses less memory per instance of the class. + */ + private static class ServerListTypeReference extends TypeReference> { + } + + private static class ServerGroupListTypeReference extends TypeReference> { + } + + private static class ServerTypeReference extends TypeReference { + } + + private static class ServerGroupTypeReference extends TypeReference { + } + + private static class MsgTypeReference extends TypeReference { } }