2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
6 * Copyright © 2017 Amdocs
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
21 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
23 package org.onap.aai.sparky.dal;
25 import java.io.IOException;
27 import java.net.URISyntaxException;
28 import java.util.ArrayList;
29 import java.util.HashMap;
30 import java.util.List;
33 import javax.ws.rs.core.MediaType;
34 import javax.ws.rs.core.UriBuilder;
36 import org.onap.aai.cl.api.Logger;
37 import org.onap.aai.cl.eelf.LoggerFactory;
38 import org.onap.aai.restclient.client.OperationResult;
39 import org.onap.aai.restclient.client.RestClient;
40 import org.onap.aai.restclient.enums.RestAuthenticationMode;
41 import org.onap.aai.sparky.config.oxm.OxmModelLoader;
42 import org.onap.aai.sparky.dal.exception.ElasticSearchOperationException;
43 import org.onap.aai.sparky.dal.rest.RestClientConstructionException;
44 import org.onap.aai.sparky.dal.rest.RestClientFactory;
45 import org.onap.aai.sparky.dal.rest.config.RestEndpointConfig;
46 import org.onap.aai.sparky.logging.AaiUiMsgs;
47 import org.onap.aai.sparky.util.NodeUtils;
50 * The Class GizmoAdapter.
53 public class GizmoAdapter {
55 private static final Logger LOG = LoggerFactory.getInstance().getLogger(GizmoAdapter.class);
57 private static final String HEADER_TRANS_ID = "X-TransactionId";
58 private static final String HEADER_FROM_APP_ID = "X-FromAppId";
59 private static final String HEADER_AUTHORIZATION = "Authorization";
61 private static final String HTTP_SCHEME = "http";
62 private static final String HTTPS_SCHEME = "https";
64 private static final String TRANSACTION_ID_PREFIX = "txnId-";
65 private static final String UI_APP_NAME = "AAI-UI";
67 private OxmModelLoader oxmModelLoader;
69 private RestEndpointConfig endpointConfig;
71 private RestClient restClient;
73 private String inventoryBasePath;
74 private String relationshipsBasePath;
77 * Instantiates a new active inventory adapter.
79 * @throws RestClientConstructionException
83 public GizmoAdapter(OxmModelLoader oxmModelLoader, RestEndpointConfig endpointConfig)
84 throws ElasticSearchOperationException, IOException, RestClientConstructionException {
86 this.oxmModelLoader = oxmModelLoader;
87 this.endpointConfig = endpointConfig;
88 this.restClient = RestClientFactory.buildClient(endpointConfig);
92 public String getRelationshipsBasePath() {
93 return relationshipsBasePath;
96 public void setRelationshipsBasePath(String relationshipsBasePath) {
97 this.relationshipsBasePath = relationshipsBasePath;
100 public String getInventoryBasePath() {
101 return inventoryBasePath;
104 public void setInventoryBasePath(String inventoryBasePath) {
105 this.inventoryBasePath = inventoryBasePath;
108 public String getFullInventoryUrl(String resourceUrl) throws Exception {
109 final String host = endpointConfig.getEndpointIpAddress();
110 final String port = endpointConfig.getEndpointServerPort();
111 final String basePath = getInventoryBasePath();
112 return String.format("https://%s:%s%s%s", host, port, basePath, resourceUrl);
115 public String addServerDetailsToUrl(String resourceUrl) throws Exception {
116 final String host = endpointConfig.getEndpointIpAddress();
117 final String port = endpointConfig.getEndpointServerPort();
118 return String.format("https://%s:%s/%s", host, port, resourceUrl);
121 public String getFullRelationshipUrl(String resourceUrl) throws Exception {
122 final String host = endpointConfig.getEndpointIpAddress();
123 final String port = endpointConfig.getEndpointServerPort();
124 final String basePath = getRelationshipsBasePath();
125 return String.format("https://%s:%s%s%s", host, port, basePath, resourceUrl);
128 protected Map<String, List<String>> getMessageHeaders() {
130 Map<String, List<String>> headers = new HashMap<String, List<String>>();
132 headers.putIfAbsent(HEADER_FROM_APP_ID, new ArrayList<String>());
133 headers.get(HEADER_FROM_APP_ID).add(UI_APP_NAME);
135 headers.putIfAbsent(HEADER_TRANS_ID, new ArrayList<String>());
136 headers.get(HEADER_TRANS_ID).add(TRANSACTION_ID_PREFIX + NodeUtils.getRandomTxnId());
138 if (endpointConfig.getRestAuthenticationMode() == RestAuthenticationMode.SSL_BASIC) {
140 headers.putIfAbsent(HEADER_AUTHORIZATION, new ArrayList<String>());
141 headers.get(HEADER_AUTHORIZATION).add(getBasicAuthenticationCredentials());
148 protected String getBasicAuthenticationCredentials() {
149 String usernameAndPassword = String.join(":", endpointConfig.getBasicAuthUserName(),
150 endpointConfig.getBasicAuthPassword());
151 return "Basic " + java.util.Base64.getEncoder().encodeToString(usernameAndPassword.getBytes());
155 * Our retry conditions should be very specific.
159 * @return true, if successful
161 private boolean shouldRetryRequest(OperationResult r) {
167 int rc = r.getResultCode();
182 * Query active inventory.
186 * @param acceptContentType
187 * the accept content type
188 * @return the operation result
190 OperationResult queryGizmo(String url, String acceptContentType) {
192 return restClient.get(url, getMessageHeaders(), MediaType.APPLICATION_JSON_TYPE);
196 public RestEndpointConfig getEndpointConfig() {
197 return endpointConfig;
200 public void setEndpointConfig(RestEndpointConfig endpointConfig) {
201 this.endpointConfig = endpointConfig;
204 public OperationResult queryGizmoWithRetries(String url, String responseType, int numRetries) {
206 OperationResult result = null;
208 for (int retryCount = 0; retryCount < numRetries; retryCount++) {
210 LOG.debug(AaiUiMsgs.QUERY_AAI_RETRY_SEQ, url, String.valueOf(retryCount + 1));
212 result = queryGizmo(url, responseType);
215 * Record number of times we have attempted the request to later
216 * summarize how many times we are generally retrying over thousands
217 * of messages in a sync.
219 * If the number of retries is surprisingly high, then we need to
220 * understand why that is as the number of retries is also causing a
221 * heavier load on AAI beyond the throttling controls we already
222 * have in place in term of the transaction rate controller and
223 * number of parallelized threads per task processor.
226 result.setNumRetries(retryCount);
228 if (!shouldRetryRequest(result)) {
230 result.setFromCache(false);
231 LOG.debug(AaiUiMsgs.QUERY_AAI_RETRY_DONE_SEQ, url, String.valueOf(retryCount + 1));
238 * Sleep between re-tries to be nice to the target system.
241 } catch (InterruptedException exc) {
242 LOG.error(AaiUiMsgs.QUERY_AAI_WAIT_INTERRUPTION, exc.getLocalizedMessage());
245 LOG.error(AaiUiMsgs.QUERY_AAI_RETRY_FAILURE_WITH_SEQ, url, String.valueOf(retryCount + 1));
249 LOG.info(AaiUiMsgs.QUERY_AAI_RETRY_MAXED_OUT, url);
256 * This method adds a scheme, host and port (if missing) to the passed-in
257 * URI. If these parts of the URI are already present, they will not be
263 * The query parameters as a single string
264 * @return The corrected URI (i.e. includes a scheme/host/port)
267 private String repairGizmoSelfLink(String baseUrlPath, String selfLink, String queryParams) {
269 if (selfLink == null) {
273 if (selfLink.startsWith("http") || selfLink.startsWith("https")) {
277 UriBuilder builder = UriBuilder.fromPath(baseUrlPath + "/" + selfLink)
278 .host(endpointConfig.getEndpointIpAddress())
279 .port(Integer.parseInt(endpointConfig.getEndpointServerPort()));
281 switch (endpointConfig.getRestAuthenticationMode()) {
285 builder.scheme(HTTPS_SCHEME);
290 builder.scheme(HTTP_SCHEME);
294 boolean includeQueryParams = ((null != queryParams) && (!"".equals(queryParams)));
297 * builder.build().toString() will encode special characters to hexadecimal pairs prefixed with
298 * a '%' so we're adding the query parameters separately, in their UTF-8 representations, so
299 * that characters such as '?', '&', etc. remain intact as needed by the synchronizer
301 return (builder.build().toString() + (includeQueryParams ? queryParams : ""));
305 public String repairRelationshipSelfLink(String selflink, String queryParams) {
306 return repairGizmoSelfLink(relationshipsBasePath, selflink, queryParams);
309 public String repairInventorySelfLink(String selflink, String queryParams) {
310 return repairGizmoSelfLink(inventoryBasePath, selflink, queryParams);
313 public OperationResult getSelfLinksByEntityType(String entityType) throws Exception {
315 if (entityType == null) {
316 throw new NullPointerException("Failed to getSelfLinksByEntityType() because entityType is null");
319 String link = getFullInventoryUrl(entityType);
321 return queryGizmoWithRetries(link, "application/json", endpointConfig.getNumRequestRetries());
325 public static String extractResourcePath(String selflink) {
327 return new URI(selflink).getRawPath();
328 } catch (URISyntaxException uriSyntaxException) {
329 LOG.error(AaiUiMsgs.ERROR_EXTRACTING_RESOURCE_PATH_FROM_LINK, uriSyntaxException.getMessage());