X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=ves-nf-oam-adopter%2Fves-nf-oam-adopter-pm-sb-rest-client%2Fsrc%2Fmain%2Fjava%2Forg%2Fo%2Fran%2Foam%2Fnf%2Foam%2Fadopter%2Fpm%2Fsb%2Frest%2Fclient%2FDefaultHttpRestClient.java;fp=ves-nf-oam-adopter%2Fves-nf-oam-adopter-pm-sb-rest-client%2Fsrc%2Fmain%2Fjava%2Forg%2Fo%2Fran%2Foam%2Fnf%2Foam%2Fadopter%2Fpm%2Fsb%2Frest%2Fclient%2FDefaultHttpRestClient.java;h=b1d60086621c13e7adb003d7b72e0ecd83ed93a5;hb=5868c88405a5057923095e84b225adc23feef84b;hp=0000000000000000000000000000000000000000;hpb=3d81c2eabbdd3e5187a824fc5d2dff4e58f62a68;p=oam%2Fnf-oam-adopter.git diff --git a/ves-nf-oam-adopter/ves-nf-oam-adopter-pm-sb-rest-client/src/main/java/org/o/ran/oam/nf/oam/adopter/pm/sb/rest/client/DefaultHttpRestClient.java b/ves-nf-oam-adopter/ves-nf-oam-adopter-pm-sb-rest-client/src/main/java/org/o/ran/oam/nf/oam/adopter/pm/sb/rest/client/DefaultHttpRestClient.java new file mode 100644 index 0000000..b1d6008 --- /dev/null +++ b/ves-nf-oam-adopter/ves-nf-oam-adopter-pm-sb-rest-client/src/main/java/org/o/ran/oam/nf/oam/adopter/pm/sb/rest/client/DefaultHttpRestClient.java @@ -0,0 +1,157 @@ +/* + * ============LICENSE_START======================================================= + * O-RAN-SC + * ================================================================================ + * Copyright © 2021 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.o.ran.oam.nf.oam.adopter.pm.sb.rest.client; + +import static org.o.ran.oam.nf.oam.adopter.pm.sb.rest.client.http.DownloadPerformanceManagementFilesHandler.readPerformanceManagementFiles; +import static org.o.ran.oam.nf.oam.adopter.pm.sb.rest.client.http.OffSetTimeZoneHandler.readTimeZone; +import static org.o.ran.oam.nf.oam.adopter.pm.sb.rest.client.http.TokenHandler.returnToken; +import static org.springframework.util.MimeTypeUtils.APPLICATION_JSON_VALUE; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import io.reactivex.rxjava3.core.Single; +import java.time.Instant; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.zip.ZipInputStream; +import org.apache.hc.client5.http.async.methods.SimpleHttpRequest; +import org.apache.hc.client5.http.async.methods.SimpleHttpRequests; +import org.apache.hc.client5.http.async.methods.SimpleHttpResponse; +import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; +import org.apache.hc.core5.http.ConnectionClosedException; +import org.apache.hc.core5.http.HttpHeaders; +import org.checkerframework.checker.lock.qual.GuardedBy; +import org.o.ran.oam.nf.oam.adopter.pm.rest.manager.api.HttpRestClient; +import org.o.ran.oam.nf.oam.adopter.pm.rest.manager.exceptions.PerformanceManagementException; +import org.o.ran.oam.nf.oam.adopter.pm.rest.manager.exceptions.TokenGenerationException; +import org.o.ran.oam.nf.oam.adopter.pm.rest.manager.exceptions.ZoneIdException; +import org.o.ran.oam.nf.oam.adopter.pm.rest.manager.pojos.Adapter; +import org.o.ran.oam.nf.oam.adopter.pm.sb.rest.client.properties.PmEndpointsUrlsProperties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public final class DefaultHttpRestClient implements HttpRestClient { + private static final Logger LOG = LoggerFactory.getLogger(DefaultHttpRestClient.class); + + public static final String HTTPS = "https://"; + public static final String BEARER = "Bearer "; + private static final DateTimeFormatter OFFSET_FORMATTER = DateTimeFormatter.ofPattern("xxx"); + private final CloseableHttpAsyncClient client; + @GuardedBy("this") + private final LoadingCache sessionCache = + CacheBuilder.newBuilder().refreshAfterWrite(59, TimeUnit.MINUTES).build(new CacheLoader<>() { + @Override + public String load(final Adapter adapter) throws ExecutionException, InterruptedException { + try { + return returnToken(DefaultHttpRestClient.this.client, DefaultHttpRestClient.this.tokenEndpoint, + adapter); + } catch (final Exception error) { + LOG.error("Failed to read time zone", error); + throw error; + } + } + }); + + @GuardedBy("this") + private final LoadingCache zoneIdCache = + CacheBuilder.newBuilder().build(new CacheLoader<>() { + @Override + public ZoneId load(final Adapter adapter) { + return readTimeZone(DefaultHttpRestClient.this, timeZoneEndpoint, adapter) + .doOnError(error -> LOG.error("Failed to read time zone", error)) + .blockingGet(); + } + }); + private final String pmFilesEndpoint; + private final String timeZoneEndpoint; + private final String tokenEndpoint; + + /** + * Default constructor. + */ + @Autowired + public DefaultHttpRestClient(final CloseableHttpAsyncClient httpAsyncClient, + final PmEndpointsUrlsProperties properties) { + this.client = httpAsyncClient; + this.pmFilesEndpoint = properties.getRanPmEndpoint(); + this.timeZoneEndpoint = properties.getRanTimeZoneOffsetEndpoint(); + this.tokenEndpoint = properties.getRanTokenEndpoint(); + } + + + @Override + public synchronized Single readFiles(final Adapter adapter) { + return readPerformanceManagementFiles(this, pmFilesEndpoint, adapter); + } + + @Override + public Single getTimeZone(final Adapter adapter) { + try { + final ZoneId zoneId = zoneIdCache.get(adapter); + LOG.info("Adapter {} has offset {}", adapter.getHostIpAddress(), + OFFSET_FORMATTER.format(zoneId.getRules().getOffset(Instant.now()))); + return Single.just(zoneId); + } catch (final Exception e) { + final Throwable cause = e.getCause(); + if (cause instanceof PerformanceManagementException) { + return Single.error(cause); + } + return Single.error(new ZoneIdException("Failed to get Zone ID for " + adapter.getHostIpAddress(), cause)); + } + } + + /** + * Execute GET request on adapter endpoint. + * @param adapter destiny + * @param url endpoint + * @return response + */ + public Single get(final Adapter adapter, final String url) { + return getToken(adapter).flatMap(token -> { + final SimpleHttpRequest request = + SimpleHttpRequests.get(HTTPS + adapter.getHostIpAddress() + url); + request.addHeader(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON_VALUE); + request.addHeader(HttpHeaders.AUTHORIZATION, BEARER + token); + return Single.fromFuture(client.execute(request, null)) + .doOnSubscribe(result -> LOG.trace("GET Request started {} ...", request.toString())) + .doOnSuccess(result -> LOG.trace("GET Request finished {}", request)); + }); + } + + private Single getToken(final Adapter adapter) { + try { + final String token = sessionCache.get(adapter); + return Single.just(token); + } catch (final Exception e) { + if (e.getCause() instanceof TokenGenerationException) { + return Single.error(e.getCause()); + } else if (e.getCause() instanceof ConnectionClosedException) { + return Single.error(e.getCause()); + } + return Single.error(e); + } + } +}