Initial OpenECOMP Data Router Core commit
[aai/router-core.git] / src / main / java / org / openecomp / rest / RestClientProducer.java
1 /**
2  * ============LICENSE_START=======================================================
3  * DataRouter
4  * ================================================================================
5  * Copyright © 2017 AT&T Intellectual Property.
6  * Copyright © 2017 Amdocs
7  * All rights reserved.
8  * ================================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License ati
12  *
13  *    http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END=========================================================
21  *
22  * ECOMP and OpenECOMP are trademarks
23  * and service marks of AT&T Intellectual Property.
24  */
25 package org.openecomp.rest;
26
27 import org.apache.camel.Exchange;
28 import org.apache.camel.impl.DefaultProducer;
29 import org.eclipse.jetty.util.security.Password;
30 import org.openecomp.cl.api.Logger;
31 import org.openecomp.cl.eelf.LoggerFactory;
32 import org.openecomp.event.EventBusConsumer;
33
34 import org.openecomp.restclient.client.Headers;
35 import org.openecomp.restclient.client.OperationResult;
36 import org.openecomp.restclient.client.RestClient;
37 import org.openecomp.restclient.rest.HttpUtil;
38
39 import java.util.Arrays;
40 import java.util.HashMap;
41 import java.util.List;
42 import java.util.Map;
43
44 import javax.ws.rs.core.MediaType;
45 import javax.ws.rs.core.Response;
46
47
48 /**
49  * The EcompRest producer.
50  */
51 public class RestClientProducer extends DefaultProducer {
52
53   private static enum Operation {
54     GET, PUT, POST, DELETE
55   }
56
57   private RestClientEndpoint endpoint;
58
59   /** REST client used for sending HTTP requests. */
60   private RestClient restClient;
61
62   private Logger logger = LoggerFactory.getInstance().getLogger(RestClientProducer.class);
63
64
65   public RestClientProducer(RestClientEndpoint endpoint) {
66     super(endpoint);
67     this.endpoint = endpoint;
68   }
69
70   @Override
71   public void process(Exchange exchange) {
72
73     // Extract the URL for our REST request from the IN message header.
74     String url = exchange.getIn().getHeader(RestClientEndpoint.IN_HEADER_URL).toString();
75
76     // Populate the HTTP Request header values from any values passed in via the
77     // IN message headers.
78     Map<String, List<String>> headers = populateRestHeaders(exchange);
79
80     if (logger.isDebugEnabled()) {
81       StringBuilder sb = new StringBuilder();
82       sb.append("Process REST request - operation=").append(getOperation(exchange));
83       sb.append(" headers=[");
84       for (String key : headers.keySet()) {
85         sb.append("{").append(key).append("->").append(headers.get(key)).append("} ");
86       }
87       sb.append("]");
88       sb.append(" content: ").append(exchange.getIn().getBody());
89       logger.debug(sb.toString());
90     }
91
92     // Now, invoke the REST client to perform the operation.
93     OperationResult result = null;
94     switch (getOperation(exchange)) {
95
96       case GET:
97         result = getRestClient().get(url, headers, MediaType.APPLICATION_JSON_TYPE);
98         break;
99
100       case PUT:
101         result = getRestClient().put(url, exchange.getIn().getBody().toString(), headers,
102             MediaType.APPLICATION_JSON_TYPE, null);
103         break;
104
105       case POST:
106         result = getRestClient().post(url, exchange.getIn().getBody().toString(), headers,
107             MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE);
108         break;
109
110       case DELETE:
111         result = getRestClient().delete(url, headers, MediaType.APPLICATION_JSON_TYPE);
112         break;
113
114       default:
115         // The supplied operation is not supported.
116         result = new OperationResult();
117         result.setResultCode(Response.Status.BAD_REQUEST.getStatusCode());
118         result.setFailureCause("Unsupported HTTP Operation: " + getOperation(exchange));
119
120         break;
121     }
122
123     // Populate the OUT message with our result.
124     exchange.getOut().setHeader(RestClientEndpoint.OUT_HEADER_RESPONSE_CODE,
125         result.getResultCode());
126     if (HttpUtil.isHttpResponseClassSuccess(result.getResultCode())) {
127       exchange.getOut().setHeader(RestClientEndpoint.OUT_HEADER_RESPONSE_MSG,
128           responseStatusStringFromResult(result));
129       exchange.getOut().setBody(result.getResult());
130     } else {
131       exchange.getOut().setHeader(RestClientEndpoint.OUT_HEADER_RESPONSE_MSG,
132           result.getFailureCause());
133     }
134
135   }
136
137
138   /**
139    * Extracts the requested REST operation from the exchange message.
140    * 
141    * @param exchange - The Camel exchange to pull the operation from.
142    * 
143    * @return - The REST operation being requested.
144    */
145   private Operation getOperation(Exchange exchange) {
146
147     String toEndpoint = ((String) exchange.getProperty(Exchange.TO_ENDPOINT));
148
149     String operation = toEndpoint.substring((toEndpoint.lastIndexOf("://") + 3));
150
151     int position = operation.indexOf('?');
152     if (position >= 0) {
153       operation = operation.substring(0, position);
154     }
155
156     return Operation.valueOf(operation.toUpperCase());
157   }
158
159
160
161   /**
162    * This method extracts values from the IN message which are intended to be used to populate the
163    * HTTP Header entries for our REST request.
164    * 
165    * @param exchange - The Camel exchange to extract the HTTP header parameters from.
166    * 
167    * @return - A map of HTTP header names and values.
168    */
169   private Map<String, List<String>> populateRestHeaders(Exchange exchange) {
170
171     Map<String, List<String>> headers = new HashMap<>();
172
173     if (exchange.getIn().getHeader(Headers.FROM_APP_ID) != null) {
174       headers.put(Headers.FROM_APP_ID,
175           Arrays.asList(exchange.getIn().getHeader(Headers.FROM_APP_ID).toString()));
176     }
177     if (exchange.getIn().getHeader(Headers.TRANSACTION_ID) != null) {
178       headers.put(Headers.TRANSACTION_ID,
179           Arrays.asList(exchange.getIn().getHeader(Headers.TRANSACTION_ID).toString()));
180     }
181     if (exchange.getIn().getHeader(Headers.RESOURCE_VERSION) != null) {
182       headers.put(Headers.RESOURCE_VERSION,
183           Arrays.asList(exchange.getIn().getHeader(Headers.RESOURCE_VERSION).toString()));
184     }
185     if (exchange.getIn().getHeader(Headers.ETAG) != null) {
186       headers.put(Headers.ETAG, Arrays.asList(exchange.getIn().getHeader(Headers.ETAG).toString()));
187     }
188     if (exchange.getIn().getHeader(Headers.IF_MATCH) != null) {
189       headers.put(Headers.IF_MATCH,
190           Arrays.asList(exchange.getIn().getHeader(Headers.IF_MATCH).toString()));
191     }
192     if (exchange.getIn().getHeader(Headers.IF_NONE_MATCH) != null) {
193       headers.put(Headers.IF_NONE_MATCH,
194           Arrays.asList(exchange.getIn().getHeader(Headers.IF_NONE_MATCH).toString()));
195     }
196     if (exchange.getIn().getHeader(Headers.ACCEPT) != null) {
197       headers.put(Headers.ACCEPT,
198           Arrays.asList(exchange.getIn().getHeader(Headers.ACCEPT).toString()));
199     }
200     if (exchange.getIn().getHeader("Content-Type") != null) {
201       headers.put("Content-Type",
202           Arrays.asList(exchange.getIn().getHeader("Content-Type").toString()));
203     }
204
205     return headers;
206   }
207
208
209   /**
210    * This helper method converts an HTTP response code into the associated string.
211    * 
212    * @param result - A result object to get the response code from.
213    * 
214    * @return - The string message associated with the supplied response code.
215    */
216   private String responseStatusStringFromResult(OperationResult result) {
217
218     // Not every valid response code is actually represented by the Response.Status
219     // object, so we need to guard against missing codes, otherwise we throw null
220     // pointer exceptions when we try to generate our metrics logs...
221     Response.Status responseStatus = Response.Status.fromStatusCode(result.getResultCode());
222     String responseStatusCodeString = "";
223     if (responseStatus != null) {
224       responseStatusCodeString = responseStatus.toString();
225     }
226
227     return responseStatusCodeString;
228   }
229
230   /**
231    * Instantiate the REST client that will be used for sending our HTTP requests.
232    * 
233    * @return - An instance of the REST client.
234    */
235   private RestClient getRestClient() {
236
237     if (restClient == null) {
238
239       String keystoreFilename = endpoint.getEcompKeystore();
240       String keystorePassword = endpoint.getEcompKeystorePassword();
241       String clientCertFilename = endpoint.getEcompClientCert();
242
243       if (logger.isDebugEnabled()) {
244         logger.debug("Instantiating REST Client with client_cert=" + clientCertFilename
245             + " keystore=" + keystoreFilename + " keystorePassword=" + keystorePassword);
246       }
247
248       // Create REST client for search service
249       restClient = new RestClient().validateServerHostname(false).validateServerCertChain(true)
250           .clientCertFile(clientCertFilename)
251           .clientCertPassword(Password.deobfuscate(keystorePassword)).trustStore(keystoreFilename);
252     }
253
254     return restClient;
255   }
256 }