aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIttay Stern <ittay.stern@att.com>2019-07-25 20:33:03 +0300
committerIttay Stern <ittay.stern@att.com>2019-07-29 09:57:54 +0300
commit88753b87947fdacb003a9aec4142c2f5745ea006 (patch)
tree253d73bf2b481bf9397aad374f017f8e72caebb1
parentb75aff807050009af821f2072417d8806efd56a2 (diff)
Patch NPE in Unirest HttpResponse::getBody when getRawBody is null
Issue-ID: VID-267 Change-Id: I469bbeea52d6e86f8f12f88e9754af81b3ae6ae6 Signed-off-by: Ittay Stern <ittay.stern@att.com>
-rw-r--r--vid-app-common/src/main/java/org/onap/vid/client/SyncRestClient.java32
-rw-r--r--vid-app-common/src/main/java/org/onap/vid/client/UnirestPatch.kt55
-rw-r--r--vid-app-common/src/main/java/org/onap/vid/controller/WebConfig.java38
3 files changed, 103 insertions, 22 deletions
diff --git a/vid-app-common/src/main/java/org/onap/vid/client/SyncRestClient.java b/vid-app-common/src/main/java/org/onap/vid/client/SyncRestClient.java
index 5f76044bb..50556e7ec 100644
--- a/vid-app-common/src/main/java/org/onap/vid/client/SyncRestClient.java
+++ b/vid-app-common/src/main/java/org/onap/vid/client/SyncRestClient.java
@@ -20,12 +20,28 @@
package org.onap.vid.client;
+import static org.apache.commons.lang3.StringUtils.isEmpty;
+import static org.onap.vid.client.UnirestPatchKt.patched;
+
import io.joshworks.restclient.http.HttpResponse;
import io.joshworks.restclient.http.JsonNode;
import io.joshworks.restclient.http.RestClient;
import io.joshworks.restclient.http.exceptions.RestClientException;
import io.joshworks.restclient.http.mapper.ObjectMapper;
import io.joshworks.restclient.request.GetRequest;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.util.Map;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLException;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
@@ -36,16 +52,6 @@ import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
import org.onap.portalsdk.core.util.SystemProperties;
import org.onap.vid.properties.VidProperties;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLException;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.*;
-import java.security.cert.CertificateException;
-import java.util.Map;
-
public class SyncRestClient implements SyncRestClientInterface {
private static final EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(SyncRestClient.class);
private static final String[] SUPPORTED_SSL_VERSIONS = {"TLSv1", "TLSv1.2"};
@@ -151,11 +157,11 @@ public class SyncRestClient implements SyncRestClientInterface {
private <T> HttpResponse<T> callWithRetryOverHttpThrows(String url, HttpRequest<T> httpRequest) throws IOException {
try {
- return httpRequest.apply(url);
+ return patched(httpRequest.apply(url));
} catch (RestClientException e) {
if (causedBySslHandshakeError(e)) {
logger.warn(EELFLoggerDelegate.debugLogger, "SSL Handshake problem occured. Will try to retry over Http.", e);
- return httpRequest.apply(url.replaceFirst(HTTPS_SCHEMA, HTTP_SCHEMA));
+ return patched(httpRequest.apply(url.replaceFirst(HTTPS_SCHEMA, HTTP_SCHEMA)));
}
throw e;
}
@@ -172,7 +178,7 @@ public class SyncRestClient implements SyncRestClientInterface {
@Override
public <T> T readValue(String value, Class<T> aClass) {
try {
- return objectMapper.readValue(value, aClass);
+ return isEmpty(value) ? null : objectMapper.readValue(value, aClass);
} catch (IOException e) {
throw new SyncRestClientException("IOException while reading value", e);
}
diff --git a/vid-app-common/src/main/java/org/onap/vid/client/UnirestPatch.kt b/vid-app-common/src/main/java/org/onap/vid/client/UnirestPatch.kt
new file mode 100644
index 000000000..750646621
--- /dev/null
+++ b/vid-app-common/src/main/java/org/onap/vid/client/UnirestPatch.kt
@@ -0,0 +1,55 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * VID
+ * ================================================================================
+ * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.vid.client
+
+import io.joshworks.restclient.http.Headers
+import io.joshworks.restclient.http.HttpResponse
+import org.apache.http.HttpVersion
+import org.apache.http.message.BasicHttpResponse
+import java.io.InputStream
+
+/// Patch NPE in joshworks's Unirest HttpResponse::getBody when getRawBody is null
+fun <T> patched(httpResponse: HttpResponse<T>) =
+ if (willGetBodyTriggerNPE(httpResponse)) HttpResponsePatch(httpResponse) else httpResponse
+
+private fun <T> willGetBodyTriggerNPE(httpResponse: HttpResponse<T>) =
+ httpResponse.rawBody == null || httpResponse.rawBody.available() == 0
+
+private val dummyHttpResponse = BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "ok")
+
+/**
+ * This class inherits HttpResponse to have compatible interface,
+ * but implementation is done through delegation to another
+ * instance.
+ * For that, it's enough to pass dummy values to HttpResponse's
+ * constructor, as parent HttpResponse methods won't be used,
+ * only overridden.
+ */
+private class HttpResponsePatch<T>(private val delegatee: HttpResponse<T>) : HttpResponse<T>(
+ dummyHttpResponse, null, null
+) {
+ override fun getBody(): T? = if (willGetBodyTriggerNPE(delegatee)) null else delegatee.body
+ override fun getHeaders(): Headers? = delegatee.headers
+ override fun getStatus() = delegatee.status
+ override fun isSuccessful() = delegatee.isSuccessful
+ override fun getStatusText(): String? = delegatee.statusText
+ override fun getRawBody(): InputStream? = delegatee.rawBody
+}
diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/WebConfig.java b/vid-app-common/src/main/java/org/onap/vid/controller/WebConfig.java
index fc656fc14..8d55c62c6 100644
--- a/vid-app-common/src/main/java/org/onap/vid/controller/WebConfig.java
+++ b/vid-app-common/src/main/java/org/onap/vid/controller/WebConfig.java
@@ -21,13 +21,32 @@
package org.onap.vid.controller;
+import static org.apache.commons.lang3.StringUtils.isEmpty;
+
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.module.kotlin.KotlinModule;
import io.joshworks.restclient.http.mapper.ObjectMapper;
+import java.io.File;
+import java.io.IOException;
+import javax.servlet.ServletContext;
import org.onap.portalsdk.core.util.SystemProperties;
-import org.onap.vid.aai.*;
+import org.onap.vid.aai.AaiClient;
+import org.onap.vid.aai.AaiClientInterface;
+import org.onap.vid.aai.AaiOverTLSClient;
+import org.onap.vid.aai.AaiOverTLSClientInterface;
+import org.onap.vid.aai.AaiOverTLSPropertySupplier;
+import org.onap.vid.aai.AaiResponseTranslator;
+import org.onap.vid.aai.PombaClientImpl;
+import org.onap.vid.aai.PombaClientInterface;
+import org.onap.vid.aai.PombaRestInterface;
import org.onap.vid.aai.model.PortDetailsTranslator;
-import org.onap.vid.aai.util.*;
+import org.onap.vid.aai.util.AAIRestInterface;
+import org.onap.vid.aai.util.CacheProvider;
+import org.onap.vid.aai.util.HttpsAuthClient;
+import org.onap.vid.aai.util.SSLContextProvider;
+import org.onap.vid.aai.util.ServiceInstanceStandardQuery;
+import org.onap.vid.aai.util.ServletRequestHelper;
+import org.onap.vid.aai.util.SystemPropertyHelper;
import org.onap.vid.asdc.AsdcClient;
import org.onap.vid.asdc.parser.ToscaParserImpl2;
import org.onap.vid.asdc.parser.VidNotionsBuilder;
@@ -37,7 +56,13 @@ import org.onap.vid.client.SyncRestClientInterface;
import org.onap.vid.properties.AsdcClientConfiguration;
import org.onap.vid.scheduler.SchedulerService;
import org.onap.vid.scheduler.SchedulerServiceImpl;
-import org.onap.vid.services.*;
+import org.onap.vid.services.AAIServiceTree;
+import org.onap.vid.services.AAITreeNodeBuilder;
+import org.onap.vid.services.AaiService;
+import org.onap.vid.services.AaiServiceImpl;
+import org.onap.vid.services.ChangeManagementService;
+import org.onap.vid.services.PombaService;
+import org.onap.vid.services.PombaServiceImpl;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -48,11 +73,6 @@ import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
-
-import javax.servlet.ServletContext;
-import java.io.File;
-import java.io.IOException;
-
@EnableSwagger2
@Configuration
public class WebConfig {
@@ -177,7 +197,7 @@ public class WebConfig {
@Override
public <T> T readValue(String s, Class<T> aClass) {
try {
- return objectMapper.readValue(s, aClass);
+ return isEmpty(s) ? null : objectMapper.readValue(s, aClass);
} catch (IOException e) {
throw new RuntimeException(e);
}