2 * ============LICENSE_START======================================================================
3 * Copyright (C) 2021 Nokia. All rights reserved.
4 * ===============================================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
6 * in compliance with the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software distributed under the License
11 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12 * or implied. See the License for the specific language governing permissions and limitations under
14 * ============LICENSE_END========================================================================
16 package org.onap.dcaegen2.collectors.datafile.http;
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.net.UnknownHostException;
21 import java.nio.file.Files;
22 import java.nio.file.Path;
23 import java.nio.file.StandardCopyOption;
25 import javax.net.ssl.SSLHandshakeException;
26 import javax.net.ssl.SSLPeerUnverifiedException;
28 import org.apache.http.HttpEntity;
29 import org.apache.http.HttpResponse;
30 import org.apache.http.client.config.RequestConfig;
31 import org.apache.http.client.methods.CloseableHttpResponse;
32 import org.apache.http.client.methods.HttpGet;
33 import org.apache.http.config.SocketConfig;
34 import org.apache.http.conn.ConnectTimeoutException;
35 import org.apache.http.conn.HttpHostConnectException;
36 import org.apache.http.impl.client.CloseableHttpClient;
37 import org.apache.http.impl.client.HttpClients;
38 import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
39 import org.apache.http.util.EntityUtils;
40 import org.onap.dcaegen2.collectors.datafile.commons.FileCollectClient;
41 import org.onap.dcaegen2.collectors.datafile.commons.FileServerData;
42 import org.onap.dcaegen2.collectors.datafile.exceptions.DatafileTaskException;
43 import org.onap.dcaegen2.collectors.datafile.exceptions.NonRetryableDatafileTaskException;
44 import org.onap.dcaegen2.collectors.datafile.service.HttpUtils;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
49 * Gets file from PNF with HTTPS protocol.
51 * @author <a href="mailto:krzysztof.gajewski@nokia.com">Krzysztof Gajewski</a>
53 public class DfcHttpsClient implements FileCollectClient {
55 protected CloseableHttpClient httpsClient;
57 private static final Logger logger = LoggerFactory.getLogger(DfcHttpsClient.class);
58 private static final int FIFTEEN_SECONDS = 15 * 1000;
60 private final FileServerData fileServerData;
61 private final PoolingHttpClientConnectionManager connectionManager;
63 public DfcHttpsClient(FileServerData fileServerData, PoolingHttpClientConnectionManager connectionManager) {
64 this.fileServerData = fileServerData;
65 this.connectionManager = connectionManager;
70 logger.trace("Setting httpsClient for file download.");
71 SocketConfig socketConfig = SocketConfig.custom().setSoKeepAlive(true).build();
73 RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(FIFTEEN_SECONDS).build();
75 httpsClient = HttpClients.custom().setConnectionManager(connectionManager).setDefaultSocketConfig(socketConfig)
76 .setDefaultRequestConfig(requestConfig).build();
78 logger.trace("httpsClient prepared for connection.");
82 public void collectFile(String remoteFile, Path localFile) throws DatafileTaskException {
83 logger.trace("Prepare to collectFile {}", localFile);
84 HttpGet httpGet = new HttpGet(HttpUtils.prepareHttpsUri(fileServerData, remoteFile));
86 String authorizationContent = getAuthorizationContent();
87 if (!authorizationContent.isEmpty()) {
88 httpGet.addHeader("Authorization", authorizationContent);
91 HttpResponse httpResponse = makeCall(httpGet);
92 processResponse(httpResponse, localFile);
93 } catch (IOException e) {
94 logger.error("marker", e);
95 throw new DatafileTaskException("Error downloading file from server. ", e);
97 logger.trace("HTTPS collectFile OK");
100 private String getAuthorizationContent() throws DatafileTaskException {
101 String jwtToken = HttpUtils.getJWTToken(fileServerData);
102 if (shouldUseBasicAuth(jwtToken)) {
103 return HttpUtils.basicAuthContent(this.fileServerData.userId, this.fileServerData.password);
105 return HttpUtils.jwtAuthContent(jwtToken);
108 private boolean shouldUseBasicAuth(String jwtToken) throws DatafileTaskException {
109 return basicAuthValidNotPresentOrThrow() && jwtToken.isEmpty();
112 protected boolean basicAuthValidNotPresentOrThrow() throws DatafileTaskException {
113 if (isAuthDataEmpty()) {
116 if (HttpUtils.isBasicAuthDataFilled(fileServerData)) {
119 throw new DatafileTaskException("Not sufficient basic auth data for file.");
122 private boolean isAuthDataEmpty() {
123 return this.fileServerData.userId.isEmpty() && this.fileServerData.password.isEmpty();
126 protected HttpResponse makeCall(HttpGet httpGet) throws IOException, DatafileTaskException {
128 HttpResponse httpResponse = executeHttpClient(httpGet);
129 if (isResponseOk(httpResponse)) {
133 EntityUtils.consume(httpResponse.getEntity());
134 if (isErrorInConnection(httpResponse)) {
135 logger.warn("Failed to download file, reason: {}, code: {}",
136 httpResponse.getStatusLine().getReasonPhrase(), httpResponse.getStatusLine());
137 throw new NonRetryableDatafileTaskException(HttpUtils.retryableResponse(getResponseCode(httpResponse)));
139 throw new DatafileTaskException(HttpUtils.nonRetryableResponse(getResponseCode(httpResponse)));
140 } catch (ConnectTimeoutException | UnknownHostException | HttpHostConnectException | SSLHandshakeException
141 | SSLPeerUnverifiedException e) {
142 logger.warn("Unable to get file from xNF: {}", e.getMessage());
143 throw new NonRetryableDatafileTaskException("Unable to get file from xNF. No retry attempts will be done.",
148 protected CloseableHttpResponse executeHttpClient(HttpGet httpGet) throws IOException {
149 return httpsClient.execute(httpGet);
152 protected boolean isResponseOk(HttpResponse httpResponse) {
153 return getResponseCode(httpResponse) == 200;
156 private int getResponseCode(HttpResponse httpResponse) {
157 return httpResponse.getStatusLine().getStatusCode();
160 protected boolean isErrorInConnection(HttpResponse httpResponse) {
161 return getResponseCode(httpResponse) >= 400;
164 protected void processResponse(HttpResponse response, Path localFile) throws IOException {
165 logger.trace("Starting to process response.");
166 HttpEntity entity = response.getEntity();
167 InputStream stream = entity.getContent();
168 long numBytes = writeFile(localFile, stream);
170 EntityUtils.consume(entity);
171 logger.trace("Transmission was successful - {} bytes downloaded.", numBytes);
174 protected long writeFile(Path localFile, InputStream stream) throws IOException {
175 return Files.copy(stream, localFile, StandardCopyOption.REPLACE_EXISTING);
179 public void close() {
180 logger.trace("Https client has ended downloading process.");