Revisions made to the Model Loader to use Babel
[aai/model-loader.git] / src / main / java / org / onap / aai / modelloader / restclient / AaiRestClient.java
1 /**
2  * ============LICENSE_START==========================================
3  * org.onap.aai
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
11  *
12  *        http://www.apache.org/licenses/LICENSE-2.0
13  *
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============================================
20  */
21 package org.onap.aai.modelloader.restclient;
22
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;
27 import java.net.URI;
28 import java.util.Collections;
29 import java.util.List;
30 import java.util.Map;
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;
51
52 /**
53  * Wrapper around the standard A&AI Rest Client interface. This currently uses Jersey client 1.x
54  *
55  */
56 public class AaiRestClient {
57
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";
62
63     private static Logger logger = LoggerFactory.getInstance().getLogger(AaiRestClient.class.getName());
64
65     private ModelLoaderConfig config = null;
66
67     public AaiRestClient(ModelLoaderConfig config) {
68         this.config = config;
69     }
70
71
72     /**
73      * Send a GET request to the A&AI for a resource.
74      *
75      * @param url
76      * @param transId
77      * @param mediaType
78      * @return
79      */
80     public OperationResult getResource(String url, String transId, MediaType mediaType) {
81         return setupClient().get(url, buildHeaders(transId), mediaType);
82     }
83
84     /**
85      * Send a PUT request to the A&AI.
86      *
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
92      */
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);
96     }
97
98
99     /**
100      * Send a POST request to the A&AI.
101      *
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
107      */
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);
111     }
112
113
114     /**
115      * Send a DELETE request to the A&AI.
116      *
117      * @param url - the url
118      * @param resourceVersion - the resource-version of the model to delete
119      * @param transId - transaction ID
120      * @return ClientResponse
121      */
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);
125     }
126
127     /**
128      * Does a GET on a resource to retrieve the resource version, and then DELETE that version.
129      *
130      * @param url - the url
131      * @param transId - transaction ID
132      * @return ClientResponse
133      */
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())) {
138             return getResponse;
139         }
140
141         // Delete the model using the resource version in the response
142         String resVersion = null;
143         try {
144             resVersion = getResourceVersion(getResponse);
145         } catch (Exception e) {
146             logger.error(ModelLoaderMsgs.AAI_REST_REQUEST_ERROR, "GET", url, e.getLocalizedMessage());
147             return null;
148         }
149
150         return deleteResource(url, resVersion, transId);
151     }
152
153
154     public boolean useBasicAuth() {
155         return (config.getAaiAuthenticationUser() != null) && (config.getAaiAuthenticationPassword() != null);
156     }
157
158     private RestClient setupClient() {
159         RestClient restClient = new RestClient();
160
161         // @formatter:off
162         restClient.validateServerHostname(false)
163                 .validateServerCertChain(false)
164                 .clientCertFile(config.getAaiKeyStorePath())
165                 .clientCertPassword(config.getAaiKeyStorePassword());
166         // @formatter:on
167
168         if (useBasicAuth()) {
169             restClient.authenticationMode(RestAuthenticationMode.SSL_BASIC);
170             restClient.basicAuthUsername(config.getAaiAuthenticationUser());
171             restClient.basicAuthPassword(config.getAaiAuthenticationPassword());
172         }
173
174         return restClient;
175     }
176
177     /**
178      * Create the HTTP headers required for an A&AI operation (GET/POST/PUT/DELETE)
179      * 
180      * @param transId
181      * @return map of headers
182      */
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));
188         return headers;
189     }
190
191     private String getResourceVersion(OperationResult getResponse)
192             throws ParserConfigurationException, SAXException, IOException {
193         String respData = getResponse.getResult();
194
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);
200
201         NodeList nodesList = doc.getDocumentElement().getChildNodes();
202
203         // @formatter:off
204         return IntStream.range(0, nodesList.getLength()).mapToObj(nodesList::item)
205                 .filter(childNode -> childNode.getNodeName().equals(RESOURCE_VERSION_PARAM))
206                 .findFirst()
207                 .map(Node::getTextContent)
208                 .orElse(null);
209         // @formatter:on
210     }
211 }