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.aai;
25 import java.io.IOException;
26 import java.net.URLEncoder;
27 import java.nio.ByteBuffer;
28 import java.util.List;
29 import java.util.NoSuchElementException;
31 import org.apache.http.client.utils.URIBuilder;
32 import org.onap.aai.sparky.config.oxm.OxmEntityDescriptor;
33 import org.onap.aai.sparky.config.oxm.OxmModelLoader;
34 import org.onap.aai.sparky.dal.aai.config.ActiveInventoryConfig;
35 import org.onap.aai.sparky.dal.aai.config.ActiveInventoryRestConfig;
36 import org.onap.aai.sparky.dal.aai.enums.RestAuthenticationMode;
37 import org.onap.aai.sparky.dal.exception.ElasticSearchOperationException;
38 import org.onap.aai.sparky.dal.rest.OperationResult;
39 import org.onap.aai.sparky.dal.rest.RestClientBuilder;
40 import org.onap.aai.sparky.dal.rest.RestfulDataAccessor;
41 import org.onap.aai.sparky.logging.AaiUiMsgs;
42 import org.onap.aai.sparky.security.SecurityContextFactory;
43 import org.onap.aai.sparky.util.NodeUtils;
44 import org.onap.aai.cl.api.Logger;
45 import org.onap.aai.cl.eelf.LoggerFactory;
47 import com.sun.jersey.api.client.Client;
48 import com.sun.jersey.api.client.WebResource.Builder;
52 * The Class ActiveInventoryAdapter.
59 public class ActiveInventoryAdapter extends RestfulDataAccessor
60 implements ActiveInventoryDataProvider {
62 private static final Logger LOG =
63 LoggerFactory.getInstance().getLogger(ActiveInventoryAdapter.class);
65 private static final String HEADER_TRANS_ID = "X-TransactionId";
66 private static final String HEADER_FROM_APP_ID = "X-FromAppId";
67 private static final String HEADER_AUTHORIZATION = "Authorization";
69 private static final String TRANSACTION_ID_PREFIX = "txnId-";
70 private static final String UI_APP_NAME = "AAI-UI";
73 private ActiveInventoryConfig config;
76 * Instantiates a new active inventory adapter.
78 * @param restClientBuilder the rest client builder
79 * @throws ElasticSearchOperationException the elastic search operation exception
80 * @throws IOException Signals that an I/O exception has occurred.
82 public ActiveInventoryAdapter(RestClientBuilder restClientBuilder)
83 throws ElasticSearchOperationException, IOException {
84 super(restClientBuilder);
87 this.config = ActiveInventoryConfig.getConfig();
88 } catch (Exception exc) {
89 throw new ElasticSearchOperationException("Error getting active inventory configuration",
93 clientBuilder.setUseHttps(true);
95 clientBuilder.setValidateServerHostname(config.getAaiSslConfig().isValidateServerHostName());
97 SecurityContextFactory sslContextFactory = clientBuilder.getSslContextFactory();
99 sslContextFactory.setServerCertificationChainValidationEnabled(
100 config.getAaiSslConfig().isValidateServerCertificateChain());
102 if (config.getAaiRestConfig().getAuthenticationMode() == RestAuthenticationMode.SSL_CERT) {
103 sslContextFactory.setClientCertFileName(config.getAaiSslConfig().getKeystoreFilename());
104 sslContextFactory.setClientCertPassword(config.getAaiSslConfig().getKeystorePassword());
105 sslContextFactory.setTrustStoreFileName(config.getAaiSslConfig().getTruststoreFilename());
108 clientBuilder.setConnectTimeoutInMs(config.getAaiRestConfig().getConnectTimeoutInMs());
109 clientBuilder.setReadTimeoutInMs(config.getAaiRestConfig().getReadTimeoutInMs());
114 * @see org.onap.aai.sparky.dal.rest.RestfulDataAccessor#setClientDefaults(com.sun.jersey.api.client.Client, java.lang.String, java.lang.String, java.lang.String)
117 protected Builder setClientDefaults(Client client, String url, String payloadContentType,
118 String acceptContentType) {
119 Builder builder = super.setClientDefaults(client, url, payloadContentType, acceptContentType);
121 builder = builder.header(HEADER_FROM_APP_ID, UI_APP_NAME);
122 byte bytes[] = new byte[6];
123 txnIdGenerator.nextBytes(bytes);
125 builder.header(HEADER_TRANS_ID, TRANSACTION_ID_PREFIX + ByteBuffer.wrap(bytes).getInt());
127 if (config.getAaiRestConfig().getAuthenticationMode() == RestAuthenticationMode.SSL_BASIC) {
128 builder = builder.header(HEADER_AUTHORIZATION,
129 config.getAaiSslConfig().getBasicAuthenticationCredentials());
138 * @param resourceUrl the resource url
139 * @return the full url
140 * @throws Exception the exception
142 private String getFullUrl(String resourceUrl) throws Exception {
143 ActiveInventoryRestConfig aaiRestConfig = ActiveInventoryConfig.getConfig().getAaiRestConfig();
144 final String host = aaiRestConfig.getHost();
145 final String port = aaiRestConfig.getPort();
146 final String basePath = aaiRestConfig.getResourceBasePath();
147 return String.format("https://%s:%s%s%s", host, port, basePath, resourceUrl);
150 public String getGenericQueryForSelfLink(String startNodeType, List<String> queryParams) throws Exception {
152 URIBuilder urlBuilder = new URIBuilder(getFullUrl("/search/generic-query"));
154 for( String queryParam : queryParams) {
155 urlBuilder.addParameter("key", queryParam);
158 urlBuilder.addParameter("start-node-type", startNodeType);
159 urlBuilder.addParameter("include", startNodeType);
161 final String constructedLink = urlBuilder.toString();
163 // TODO: debug log for constructed link
165 return constructedLink;
171 * @see org.onap.aai.sparky.dal.aai.ActiveInventoryDataProvider#getSelfLinksByEntityType(java.lang.String)
174 public OperationResult getSelfLinksByEntityType(String entityType) throws Exception {
177 * For this one, I want to dynamically construct the nodes-query for self-link discovery as a
178 * utility method that will use the OXM model entity data to drive the query as well.
181 if (entityType == null) {
182 throw new NullPointerException(
183 "Failed to getSelfLinksByEntityType() because entityType is null");
186 OxmEntityDescriptor entityDescriptor =
187 OxmModelLoader.getInstance().getEntityDescriptor(entityType);
189 if (entityDescriptor == null) {
190 throw new NoSuchElementException("Failed to getSelfLinksByEntityType() because could"
191 + " not find entity descriptor from OXM with type = " + entityType);
195 final String primaryKeyStr =
196 NodeUtils.concatArray(entityDescriptor.getPrimaryKeyAttributeName(), "/");
198 link = getFullUrl("/search/nodes-query?search-node-type=" + entityType + "&filter="
199 + primaryKeyStr + ":EXISTS");
203 return doGet(link, "application/json");
208 * @see org.onap.aai.sparky.dal.aai.ActiveInventoryDataProvider#getSelfLinkForEntity(java.lang.String, java.lang.String, java.lang.String)
211 public OperationResult getSelfLinkForEntity(String entityType, String primaryKeyName,
212 String primaryKeyValue) throws Exception {
214 if (entityType == null) {
215 throw new NullPointerException("Failed to getSelfLinkForEntity() because entityType is null");
218 if (primaryKeyName == null) {
219 throw new NullPointerException(
220 "Failed to getSelfLinkForEntity() because primaryKeyName is null");
223 if (primaryKeyValue == null) {
224 throw new NullPointerException(
225 "Failed to getSelfLinkForEntity() because primaryKeyValue is null");
230 * Try to protect ourselves from illegal URI formatting exceptions caused by characters that
231 * aren't natively supported in a URI, but can be escaped to make them legal.
234 String encodedEntityType = URLEncoder.encode(entityType, "UTF-8");
235 String encodedPrimaryKeyName = URLEncoder.encode(primaryKeyName, "UTF-8");
236 String encodedPrimaryKeyValue = URLEncoder.encode(primaryKeyValue, "UTF-8");
240 if ("service-instance".equals(entityType)) {
242 link = getFullUrl("/search/generic-query?key=" + encodedEntityType + "."
243 + encodedPrimaryKeyName + ":" + encodedPrimaryKeyValue + "&start-node-type="
244 + encodedEntityType + "&include=customer&depth=2");
249 getFullUrl("/search/generic-query?key=" + encodedEntityType + "." + encodedPrimaryKeyName
250 + ":" + encodedPrimaryKeyValue + "&start-node-type=" + encodedEntityType);
254 return queryActiveInventoryWithRetries(link, "application/json",
255 this.config.getAaiRestConfig().getNumRequestRetries());
261 * Our retry conditions should be very specific.
264 * @return true, if successful
266 private boolean shouldRetryRequest(OperationResult r) {
272 int rc = r.getResultCode();
287 * Query active inventory.
290 * @param acceptContentType the accept content type
291 * @return the operation result
293 // package protected for test classes instead of private
294 OperationResult queryActiveInventory(String url, String acceptContentType) {
295 return doGet(url, acceptContentType);
299 * @see org.onap.aai.sparky.dal.aai.ActiveInventoryDataProvider#queryActiveInventoryWithRetries(java.lang.String, java.lang.String, int)
302 public OperationResult queryActiveInventoryWithRetries(String url, String responseType,
305 OperationResult result = null;
307 for (int x = 0; x < numRetries; x++) {
309 LOG.debug(AaiUiMsgs.QUERY_AAI_RETRY_SEQ, url, String.valueOf(x + 1));
311 result = queryActiveInventory(url, responseType);
314 * Record number of times we have attempted the request to later summarize how many times we
315 * are generally retrying over thousands of messages in a sync.
317 * If the number of retries is surprisingly high, then we need to understand why that is as
318 * the number of retries is also causing a heavier load on AAI beyond the throttling controls
319 * we already have in place in term of the transaction rate controller and number of
320 * parallelized threads per task processor.
323 result.setNumRequestRetries(x);
325 if (!shouldRetryRequest(result)) {
328 * if (myConfig.getAaiRestConfig().isCacheEnabled()) {
330 * CachedHttpRequest cachedRequest = new CachedHttpRequest();
331 * cachedRequest.setHttpRequestMethod("GET"); cachedRequest.setPayload("");
332 * cachedRequest.setPayloadMimeType(""); cachedRequest.setUrl(url);
333 * cachedRequest.setOperationType( TransactionStorageType.ACTIVE_INVENTORY_QUERY.getIndex()
336 * CachedHttpResponse cachedResponse = new CachedHttpResponse();
337 * cachedResponse.setPayload(result.getResult());
338 * cachedResponse.setPayloadMimeType("application/json");
339 * cachedResponse.setStatusCode(result.getResultCode());
341 * CachedHttpTransaction txn = new CachedHttpTransaction(cachedRequest, cachedResponse);
342 * storageProvider.persistTransaction(txn);
348 result.setResolvedLinkFromServer(true);
349 LOG.debug(AaiUiMsgs.QUERY_AAI_RETRY_DONE_SEQ, url, String.valueOf(x + 1));
356 * Sleep between re-tries to be nice to the target system.
359 } catch (InterruptedException exc) {
360 LOG.error(AaiUiMsgs.QUERY_AAI_WAIT_INTERRUPTION, exc.getLocalizedMessage());
363 LOG.error(AaiUiMsgs.QUERY_AAI_RETRY_FAILURE_WITH_SEQ, url, String.valueOf(x + 1));
367 result.setResolvedLinkFailure(true);
368 LOG.info(AaiUiMsgs.QUERY_AAI_RETRY_MAXED_OUT, url);
375 * @see org.onap.aai.sparky.dal.rest.RestfulDataAccessor#shutdown()
378 public void shutdown() {
379 // TODO Auto-generated method stub
381 if (entityCache != null) {
382 entityCache.shutdown();