2 * ============LICENSE_START==========================================
4 * ===================================================================
5 * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6 * Copyright © 2017-2018 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 package org.onap.aai.modelloader.restclient;
23 import com.sun.jersey.core.util.MultivaluedMapImpl; // NOSONAR
24 // import edu.emory.mathcs.backport.java.util.Collections;
25 import java.io.IOException;
26 import java.io.StringReader;
28 import java.util.Collections;
29 import java.util.List;
31 import java.util.stream.IntStream;
32 import javax.ws.rs.core.MediaType;
33 import javax.ws.rs.core.MultivaluedMap;
34 import javax.ws.rs.core.Response;
35 import javax.ws.rs.core.UriBuilder;
36 import javax.xml.parsers.DocumentBuilder;
37 import javax.xml.parsers.DocumentBuilderFactory;
38 import javax.xml.parsers.ParserConfigurationException;
39 import org.onap.aai.cl.api.Logger;
40 import org.onap.aai.cl.eelf.LoggerFactory;
41 import org.onap.aai.modelloader.config.ModelLoaderConfig;
42 import org.onap.aai.modelloader.service.ModelLoaderMsgs;
43 import org.onap.aai.restclient.client.OperationResult;
44 import org.onap.aai.restclient.client.RestClient;
45 import org.onap.aai.restclient.enums.RestAuthenticationMode;
46 import org.w3c.dom.Document;
47 import org.w3c.dom.Node;
48 import org.w3c.dom.NodeList;
49 import org.xml.sax.InputSource;
50 import org.xml.sax.SAXException;
53 * Wrapper around the standard A&AI Rest Client interface. This currently uses Jersey client 1.x
56 public class AaiRestClient {
58 public static final String HEADER_TRANS_ID = "X-TransactionId";
59 public static final String HEADER_FROM_APP_ID = "X-FromAppId";
60 public static final String ML_APP_NAME = "ModelLoader";
61 private static final String RESOURCE_VERSION_PARAM = "resource-version";
63 private static Logger logger = LoggerFactory.getInstance().getLogger(AaiRestClient.class.getName());
65 private ModelLoaderConfig config = null;
67 public AaiRestClient(ModelLoaderConfig config) {
73 * Send a GET request to the A&AI for a resource.
80 public OperationResult getResource(String url, String transId, MediaType mediaType) {
81 return setupClient().get(url, buildHeaders(transId), mediaType);
85 * Send a PUT request to the A&AI.
87 * @param url - the url
88 * @param payload - the XML or JSON payload for the request
89 * @param transId - transaction ID
90 * @param mediaType - the content type (XML or JSON)
91 * @return operation result
93 public OperationResult putResource(String url, String payload, String transId, MediaType mediaType) {
94 logger.info(ModelLoaderMsgs.AAI_REST_REQUEST_PAYLOAD, payload);
95 return setupClient().put(url, payload, buildHeaders(transId), mediaType, mediaType);
100 * Send a POST request to the A&AI.
102 * @param url - the url
103 * @param transId - transaction ID
104 * @param payload - the XML or JSON payload for the request
105 * @param mimeType - the content type (XML or JSON)
106 * @return ClientResponse
108 public OperationResult postResource(String url, String payload, String transId, MediaType mediaType) {
109 logger.info(ModelLoaderMsgs.AAI_REST_REQUEST_PAYLOAD, payload);
110 return setupClient().post(url, payload, buildHeaders(transId), mediaType, mediaType);
115 * Send a DELETE request to the A&AI.
117 * @param url - the url
118 * @param resourceVersion - the resource-version of the model to delete
119 * @param transId - transaction ID
120 * @return ClientResponse
122 public OperationResult deleteResource(String url, String resourceVersion, String transId) {
123 URI uri = UriBuilder.fromUri(url).queryParam(RESOURCE_VERSION_PARAM, resourceVersion).build();
124 return setupClient().delete(uri.toString(), buildHeaders(transId), null);
128 * Does a GET on a resource to retrieve the resource version, and then DELETE that version.
130 * @param url - the url
131 * @param transId - transaction ID
132 * @return ClientResponse
134 public OperationResult getAndDeleteResource(String url, String transId) {
135 // First, GET the model
136 OperationResult getResponse = getResource(url, transId, MediaType.APPLICATION_XML_TYPE);
137 if ((getResponse == null) || (getResponse.getResultCode() != Response.Status.OK.getStatusCode())) {
141 // Delete the model using the resource version in the response
142 String resVersion = null;
144 resVersion = getResourceVersion(getResponse);
145 } catch (Exception e) {
146 logger.error(ModelLoaderMsgs.AAI_REST_REQUEST_ERROR, "GET", url, e.getLocalizedMessage());
150 return deleteResource(url, resVersion, transId);
154 public boolean useBasicAuth() {
155 return (config.getAaiAuthenticationUser() != null) && (config.getAaiAuthenticationPassword() != null);
158 private RestClient setupClient() {
159 RestClient restClient = new RestClient();
162 restClient.validateServerHostname(false)
163 .validateServerCertChain(false)
164 .clientCertFile(config.getAaiKeyStorePath())
165 .clientCertPassword(config.getAaiKeyStorePassword());
168 if (useBasicAuth()) {
169 restClient.authenticationMode(RestAuthenticationMode.SSL_BASIC);
170 restClient.basicAuthUsername(config.getAaiAuthenticationUser());
171 restClient.basicAuthPassword(config.getAaiAuthenticationPassword());
178 * Create the HTTP headers required for an A&AI operation (GET/POST/PUT/DELETE)
181 * @return map of headers
183 @SuppressWarnings("unchecked")
184 private Map<String, List<String>> buildHeaders(String transId) {
185 MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
186 headers.put(HEADER_TRANS_ID, Collections.singletonList(transId));
187 headers.put(HEADER_FROM_APP_ID, Collections.singletonList(ML_APP_NAME));
191 private String getResourceVersion(OperationResult getResponse)
192 throws ParserConfigurationException, SAXException, IOException {
193 String respData = getResponse.getResult();
195 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
196 factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
197 DocumentBuilder builder = factory.newDocumentBuilder();
198 InputSource is = new InputSource(new StringReader(respData));
199 Document doc = builder.parse(is);
201 NodeList nodesList = doc.getDocumentElement().getChildNodes();
204 return IntStream.range(0, nodesList.getLength()).mapToObj(nodesList::item)
205 .filter(childNode -> childNode.getNodeName().equals(RESOURCE_VERSION_PARAM))
207 .map(Node::getTextContent)