added svcapi ui and camunda code
[it/otf.git] / otf-service-api / src / main / java / org / oran / otf / api / Utilities.java
1 /*  Copyright (c) 2019 AT&T Intellectual Property.                             #\r
2 #                                                                              #\r
3 #   Licensed under the Apache License, Version 2.0 (the "License");            #\r
4 #   you may not use this file except in compliance with the License.           #\r
5 #   You may obtain a copy of the License at                                    #\r
6 #                                                                              #\r
7 #       http://www.apache.org/licenses/LICENSE-2.0                             #\r
8 #                                                                              #\r
9 #   Unless required by applicable law or agreed to in writing, software        #\r
10 #   distributed under the License is distributed on an "AS IS" BASIS,          #\r
11 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #\r
12 #   See the License for the specific language governing permissions and        #\r
13 #   limitations under the License.                                             #\r
14 ##############################################################################*/\r
15 \r
16 \r
17 package org.oran.otf.api;\r
18 \r
19 import org.oran.otf.common.model.User;\r
20 import org.oran.otf.common.model.local.OTFApiResponse;\r
21 import org.oran.otf.common.repository.UserRepository;\r
22 import com.fasterxml.jackson.databind.DeserializationFeature;\r
23 import com.fasterxml.jackson.databind.ObjectMapper;\r
24 import com.google.common.base.Strings;\r
25 import com.google.gson.JsonObject;\r
26 import com.google.gson.JsonParseException;\r
27 import com.google.gson.JsonParser;\r
28 import java.io.IOException;\r
29 import java.io.PrintWriter;\r
30 import java.io.StringWriter;\r
31 import java.util.Arrays;\r
32 import java.util.Base64;\r
33 import java.util.Date;\r
34 import java.util.List;\r
35 import java.util.Map;\r
36 import java.util.Optional;\r
37 import javax.ws.rs.core.MediaType;\r
38 import javax.ws.rs.core.Response;\r
39 import org.apache.http.HttpEntity;\r
40 import org.apache.http.HttpResponse;\r
41 import org.apache.http.NameValuePair;\r
42 import org.apache.http.client.HttpClient;\r
43 import org.apache.http.client.entity.UrlEncodedFormEntity;\r
44 import org.apache.http.client.methods.HttpDelete;\r
45 import org.apache.http.client.methods.HttpGet;\r
46 import org.apache.http.client.methods.HttpPost;\r
47 import org.apache.http.conn.ssl.NoopHostnameVerifier;\r
48 import org.apache.http.entity.StringEntity;\r
49 import org.apache.http.impl.client.HttpClientBuilder;\r
50 import org.apache.http.message.BasicNameValuePair;\r
51 import org.apache.http.util.EntityUtils;\r
52 import org.bson.types.ObjectId;\r
53 import org.slf4j.Logger;\r
54 import org.slf4j.LoggerFactory;\r
55 import org.springframework.data.mongodb.repository.MongoRepository;\r
56 \r
57 public class Utilities {\r
58 \r
59   public static JsonObject parseJson(String str) {\r
60     try {\r
61       return new JsonParser().parse(str).getAsJsonObject();\r
62     } catch (JsonParseException jpe) {\r
63       logger.error("Cannot parse string as Json.");\r
64       return null;\r
65     }\r
66   }\r
67 \r
68   public static class Http {\r
69     public static class BuildResponse {\r
70       public static Response badRequest() {\r
71         return Response.status(400).build();\r
72       }\r
73 \r
74       public static Response badRequestWithMessage(String msg) {\r
75         return Response.status(400)\r
76             .type(MediaType.APPLICATION_JSON)\r
77             .entity(new OTFApiResponse(400, msg))\r
78             .build();\r
79       }\r
80 \r
81       public static Response internalServerError() {\r
82         return Response.status(500).build();\r
83       }\r
84 \r
85       public static Response internalServerErrorWithMessage(String msg) {\r
86         return Response.status(500)\r
87             .type(MediaType.APPLICATION_JSON)\r
88             .entity(new OTFApiResponse(500, msg))\r
89             .build();\r
90       }\r
91 \r
92       public static Response unauthorized() {\r
93         return Response.status(401).build();\r
94       }\r
95 \r
96       public static Response unauthorizedWithMessage(String msg) {\r
97         return Response.status(401)\r
98             .type(MediaType.APPLICATION_JSON)\r
99             .entity(new OTFApiResponse(401, msg))\r
100             .build();\r
101       }\r
102     }\r
103 \r
104     public static HttpResponse httpPostJsonUsingAAF(String url, String body) throws Exception {\r
105       HttpResponse response = null;\r
106 \r
107         String aafCredentialsDecoded =\r
108             System.getenv("AAF_ID") + ":" + System.getenv("AAF_MECH_PASSWORD");\r
109 \r
110         HttpPost post = new HttpPost(url);\r
111         post.setHeader("Content-Type", MediaType.APPLICATION_JSON);\r
112         post.setHeader(\r
113             "Authorization",\r
114             "Basic " + Base64.getEncoder().encodeToString(aafCredentialsDecoded.getBytes()));\r
115         post.setEntity(new StringEntity(body));\r
116 \r
117         HttpClient client =\r
118             HttpClientBuilder.create()\r
119                 .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)\r
120                 .build();\r
121         response = client.execute(post);\r
122 \r
123         // logger.info(String.format("[POST:%s]\n %s", url, body));\r
124 \r
125       return response;\r
126     }\r
127 \r
128     public static HttpResponse httpDeleteAAF(String url) {\r
129       HttpResponse response = null;\r
130 \r
131       try {\r
132         String aafCredentialsDecoded =\r
133             System.getenv("AAF_ID") + ":" + System.getenv("AAF_MECH_PASSWORD");\r
134 \r
135         HttpDelete delete = new HttpDelete(url);\r
136         delete.setHeader(\r
137             "Authorization",\r
138             "Basic " + Base64.getEncoder().encodeToString(aafCredentialsDecoded.getBytes()));\r
139         HttpClient client =\r
140             HttpClientBuilder.create()\r
141                 .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)\r
142                 .build();\r
143         response = client.execute(delete);\r
144 \r
145         // logger.info(String.format("[DELETE:%s]\n", url));\r
146       } catch (Exception e) {\r
147         e.printStackTrace();\r
148       }\r
149 \r
150       return response;\r
151     }\r
152 \r
153     public static HttpResponse httpPostXmlUsingAAF(String url, String body) {\r
154       HttpResponse response = null;\r
155 \r
156       try {\r
157         String aafCredentialsDecoded =\r
158             System.getenv("AAF_ID") + ":" + System.getenv("AAF_MECH_PASSWORD");\r
159 \r
160         HttpPost post = new HttpPost(url);\r
161         post.setHeader("Content-Type", MediaType.APPLICATION_JSON);\r
162         post.setHeader(\r
163             "Authorization",\r
164             "Basic " + Base64.getEncoder().encodeToString(aafCredentialsDecoded.getBytes()));\r
165         post.setEntity(new StringEntity(body));\r
166 \r
167         List<NameValuePair> urlParameters = Arrays.asList(new BasicNameValuePair("xml", body));\r
168         post.setEntity(new UrlEncodedFormEntity(urlParameters));\r
169 \r
170         HttpClient client = HttpClientBuilder.create().build();\r
171         response = client.execute(post);\r
172 \r
173         logger.info(String.format("[POST:%s]\n %s", url, body));\r
174       } catch (Exception e) {\r
175         e.printStackTrace();\r
176       }\r
177 \r
178       return response;\r
179     }\r
180 \r
181     public static HttpResponse httpGetUsingAAF(String url) {\r
182       HttpResponse response = null;\r
183 \r
184       try {\r
185         String aafCredentialsDecoded =\r
186             System.getenv("AAF_ID") + ":" + System.getenv("AAF_MECH_PASSWORD");\r
187 \r
188         HttpGet get = new HttpGet(url);\r
189         get.setHeader("Content-Type", "application/json");\r
190         get.setHeader(\r
191             "Authorization",\r
192             "Basic " + Base64.getEncoder().encodeToString(aafCredentialsDecoded.getBytes()));\r
193 \r
194         HttpClient client =\r
195             HttpClientBuilder.create()\r
196                 .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)\r
197                 .build();\r
198         response = client.execute(get);\r
199 \r
200         logger.info(String.format("[GET:%s]", url));\r
201       } catch (Exception e) {\r
202         e.printStackTrace();\r
203       }\r
204 \r
205       return response;\r
206     }\r
207   }\r
208 \r
209   public static class Camunda {\r
210 \r
211     public static boolean isCamundaOnline() {\r
212       final String healthUrl =\r
213           String.format(\r
214               "%s:%s/%s",\r
215               System.getenv("otf.camunda.host"),\r
216               System.getenv("otf.camunda.port"),\r
217               System.getenv("otf.camunda.uri.health"));\r
218 \r
219       HttpResponse res = Utilities.Http.httpGetUsingAAF(healthUrl);\r
220       return res != null && res.getStatusLine().getStatusCode() == 200;\r
221     }\r
222 \r
223     public static JsonObject processInstanceStatus(String executionId) {\r
224       // Read necessary environment variables - Avoiding using Spring dependencies (@Value)\r
225       String host = System.getenv("otf.camunda.host");\r
226       String path = System.getenv("otf.camunda.uri.process-instance-completion-check");\r
227       int port = Utilities.TryGetEnvironmentVariable("otf.camunda.port");\r
228 \r
229       if (!Utilities.isHostValid(host)) {\r
230         logger.error("Host (%s) must use either the http or https protocol.", host);\r
231         return null;\r
232       }\r
233 \r
234       if (!Utilities.isPortValid(port)) {\r
235         logger.error(\r
236             "Invalid port (%s) specified as environment variable 'otf.camunda.port'.",\r
237             System.getenv("otf.camunda.port"));\r
238         return null;\r
239       }\r
240       try {\r
241         String getUrl = String.format("%s:%s/%s/%s", host, port, path, executionId);\r
242         HttpResponse response = Utilities.Http.httpGetUsingAAF(getUrl);\r
243         HttpEntity entity = response.getEntity();\r
244         String result = EntityUtils.toString(entity);\r
245 \r
246         return parseJson(result);\r
247       } catch (IOException ioe) {\r
248         Utilities.printStackTrace(ioe, Utilities.LogLevel.ERROR);\r
249         logger.error("Cannot convert http entity to String.");\r
250       } catch (Exception e) {\r
251         Utilities.printStackTrace(e, Utilities.LogLevel.ERROR);\r
252       }\r
253       // conversion was unsuccessful\r
254       return null;\r
255     }\r
256   }\r
257 \r
258   private static final Logger logger = LoggerFactory.getLogger(Utilities.class);\r
259 \r
260   public static void printStackTrace(Exception exception, LogLevel logLevel) {\r
261     String stackTrace = getStackTrace(exception);\r
262 \r
263     switch (logLevel) {\r
264       case INFO:\r
265         logger.info(stackTrace);\r
266         break;\r
267       case WARN:\r
268         logger.warn(stackTrace);\r
269         break;\r
270       case DEBUG:\r
271         logger.debug(stackTrace);\r
272         break;\r
273       case ERROR:\r
274         logger.error(stackTrace);\r
275         break;\r
276     }\r
277   }\r
278 \r
279   public static int TryGetEnvironmentVariable(String variable) {\r
280     String value = System.getenv(variable);\r
281     int result = 0x80000000;\r
282 \r
283     try {\r
284       result = Integer.parseInt(value);\r
285     } catch (NumberFormatException error) {\r
286       error.printStackTrace();\r
287       logger.error(error.getMessage());\r
288     }\r
289 \r
290     return result;\r
291   }\r
292 \r
293   public static String getStackTrace(Exception exception) {\r
294     StringWriter stringWriter = new StringWriter();\r
295     exception.printStackTrace(new PrintWriter(stringWriter));\r
296     return stringWriter.toString();\r
297   }\r
298 \r
299   public static boolean isObjectIdValid(String input) {\r
300     ObjectId id = null;\r
301     try {\r
302       id = new ObjectId(input); // check if an ObjectId can be created from the string\r
303       if (id.toString().equalsIgnoreCase(input)) return true;\r
304       logger.warn("The input string does not have the same value as it's string representation.");\r
305     } catch (IllegalArgumentException e) {\r
306       logger.error(String.format("An ObjectId cannot be instantiated from the string: %s", input));\r
307     }\r
308 \r
309     return false;\r
310   }\r
311 \r
312   public static boolean isPortValid(int port) {\r
313     return (port >= 0 && port <= 65535);\r
314   }\r
315 \r
316   public static boolean isHostValid(String host) {\r
317     return host.startsWith("http");\r
318   }\r
319 \r
320   public static <T> boolean identifierExistsInCollection(\r
321       MongoRepository<T, String> repository, ObjectId identifier) {\r
322     return repository.findById(identifier.toString()).isPresent();\r
323   }\r
324 \r
325   public static <T> T findByIdGeneric(MongoRepository<T, String> repository, ObjectId identifier) {\r
326     Optional<T> optionalObj = repository.findById(identifier.toString());\r
327     return optionalObj.orElse(null);\r
328   }\r
329 \r
330   public static String[] decodeBase64AuthorizationHeader(String encodedHeader) {\r
331     try {\r
332       byte[] decodedAuthorization = Base64.getDecoder().decode(encodedHeader.replace("Basic ", ""));\r
333       String credentials = new String(decodedAuthorization);\r
334       return credentials.split(":");\r
335     } catch (Exception e) {\r
336       logger.error("Unable to decode authorization header: " + encodedHeader);\r
337       return null;\r
338     }\r
339   }\r
340 \r
341   public static User findUserByMechanizedId(String mechanizedId, UserRepository userRepository) {\r
342     Optional<User> optionalUser = userRepository.findFirstByEmail(mechanizedId);\r
343     return optionalUser.orElse(null);\r
344   }\r
345 \r
346   public static User findUserByAuthHeader(String authorization, UserRepository userRepository) {\r
347     try {\r
348       if (Strings.isNullOrEmpty(authorization)) {\r
349         return null;\r
350       }\r
351       String[] credentials = Utilities.decodeBase64AuthorizationHeader(authorization);\r
352       return findUserByMechanizedId(credentials[0], userRepository);\r
353     } catch (Exception e) {\r
354       return null;\r
355     }\r
356   }\r
357 \r
358   public static <T> T resolveOptional(Optional<T> optional) {\r
359     return optional.orElse(null);\r
360   }\r
361 \r
362   public static <T> T mapRequest(Class<T> targetType, String input) {\r
363     logger.info(targetType.getName());\r
364 \r
365     ObjectMapper mapper =\r
366         new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);\r
367     try {\r
368       return mapper.readValue(input, targetType);\r
369     } catch (IOException e) {\r
370       Utilities.printStackTrace(e, LogLevel.ERROR);\r
371       return null;\r
372     }\r
373   }\r
374 \r
375   public enum LogLevel {\r
376     WARN,\r
377     DEBUG,\r
378     INFO,\r
379     ERROR\r
380   }\r
381 \r
382   public static Date getCurrentDate() {\r
383     return new Date(System.currentTimeMillis());\r
384   }\r
385 \r
386   public static Map<String, Object> replaceObjectId(Map<String, Object> map, String objectIdKey) {\r
387     if (map.containsKey(objectIdKey)) {\r
388       ObjectId id = (ObjectId) map.get(objectIdKey);\r
389       map.replace(objectIdKey, id.toString());\r
390     }\r
391 \r
392     return map;\r
393   }\r
394 }\r