1 /* Copyright (c) 2019 AT&T Intellectual Property. #
\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
7 # http://www.apache.org/licenses/LICENSE-2.0 #
\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
17 package org.oran.otf.api;
\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
57 public class Utilities {
\r
59 public static JsonObject parseJson(String str) {
\r
61 return new JsonParser().parse(str).getAsJsonObject();
\r
62 } catch (JsonParseException jpe) {
\r
63 logger.error("Cannot parse string as Json.");
\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
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
81 public static Response internalServerError() {
\r
82 return Response.status(500).build();
\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
92 public static Response unauthorized() {
\r
93 return Response.status(401).build();
\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
104 public static HttpResponse httpPostJsonUsingAAF(String url, String body) throws Exception {
\r
105 HttpResponse response = null;
\r
107 String aafCredentialsDecoded =
\r
108 System.getenv("AAF_ID") + ":" + System.getenv("AAF_MECH_PASSWORD");
\r
110 HttpPost post = new HttpPost(url);
\r
111 post.setHeader("Content-Type", MediaType.APPLICATION_JSON);
\r
114 "Basic " + Base64.getEncoder().encodeToString(aafCredentialsDecoded.getBytes()));
\r
115 post.setEntity(new StringEntity(body));
\r
117 HttpClient client =
\r
118 HttpClientBuilder.create()
\r
119 .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
\r
121 response = client.execute(post);
\r
123 // logger.info(String.format("[POST:%s]\n %s", url, body));
\r
128 public static HttpResponse httpDeleteAAF(String url) {
\r
129 HttpResponse response = null;
\r
132 String aafCredentialsDecoded =
\r
133 System.getenv("AAF_ID") + ":" + System.getenv("AAF_MECH_PASSWORD");
\r
135 HttpDelete delete = new HttpDelete(url);
\r
138 "Basic " + Base64.getEncoder().encodeToString(aafCredentialsDecoded.getBytes()));
\r
139 HttpClient client =
\r
140 HttpClientBuilder.create()
\r
141 .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
\r
143 response = client.execute(delete);
\r
145 // logger.info(String.format("[DELETE:%s]\n", url));
\r
146 } catch (Exception e) {
\r
147 e.printStackTrace();
\r
153 public static HttpResponse httpPostXmlUsingAAF(String url, String body) {
\r
154 HttpResponse response = null;
\r
157 String aafCredentialsDecoded =
\r
158 System.getenv("AAF_ID") + ":" + System.getenv("AAF_MECH_PASSWORD");
\r
160 HttpPost post = new HttpPost(url);
\r
161 post.setHeader("Content-Type", MediaType.APPLICATION_JSON);
\r
164 "Basic " + Base64.getEncoder().encodeToString(aafCredentialsDecoded.getBytes()));
\r
165 post.setEntity(new StringEntity(body));
\r
167 List<NameValuePair> urlParameters = Arrays.asList(new BasicNameValuePair("xml", body));
\r
168 post.setEntity(new UrlEncodedFormEntity(urlParameters));
\r
170 HttpClient client = HttpClientBuilder.create().build();
\r
171 response = client.execute(post);
\r
173 logger.info(String.format("[POST:%s]\n %s", url, body));
\r
174 } catch (Exception e) {
\r
175 e.printStackTrace();
\r
181 public static HttpResponse httpGetUsingAAF(String url) {
\r
182 HttpResponse response = null;
\r
185 String aafCredentialsDecoded =
\r
186 System.getenv("AAF_ID") + ":" + System.getenv("AAF_MECH_PASSWORD");
\r
188 HttpGet get = new HttpGet(url);
\r
189 get.setHeader("Content-Type", "application/json");
\r
192 "Basic " + Base64.getEncoder().encodeToString(aafCredentialsDecoded.getBytes()));
\r
194 HttpClient client =
\r
195 HttpClientBuilder.create()
\r
196 .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
\r
198 response = client.execute(get);
\r
200 logger.info(String.format("[GET:%s]", url));
\r
201 } catch (Exception e) {
\r
202 e.printStackTrace();
\r
209 public static class Camunda {
\r
211 public static boolean isCamundaOnline() {
\r
212 final String healthUrl =
\r
215 System.getenv("otf.camunda.host"),
\r
216 System.getenv("otf.camunda.port"),
\r
217 System.getenv("otf.camunda.uri.health"));
\r
219 HttpResponse res = Utilities.Http.httpGetUsingAAF(healthUrl);
\r
220 return res != null && res.getStatusLine().getStatusCode() == 200;
\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
229 if (!Utilities.isHostValid(host)) {
\r
230 logger.error("Host (%s) must use either the http or https protocol.", host);
\r
234 if (!Utilities.isPortValid(port)) {
\r
236 "Invalid port (%s) specified as environment variable 'otf.camunda.port'.",
\r
237 System.getenv("otf.camunda.port"));
\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
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
253 // conversion was unsuccessful
\r
258 private static final Logger logger = LoggerFactory.getLogger(Utilities.class);
\r
260 public static void printStackTrace(Exception exception, LogLevel logLevel) {
\r
261 String stackTrace = getStackTrace(exception);
\r
263 switch (logLevel) {
\r
265 logger.info(stackTrace);
\r
268 logger.warn(stackTrace);
\r
271 logger.debug(stackTrace);
\r
274 logger.error(stackTrace);
\r
279 public static int TryGetEnvironmentVariable(String variable) {
\r
280 String value = System.getenv(variable);
\r
281 int result = 0x80000000;
\r
284 result = Integer.parseInt(value);
\r
285 } catch (NumberFormatException error) {
\r
286 error.printStackTrace();
\r
287 logger.error(error.getMessage());
\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
299 public static boolean isObjectIdValid(String input) {
\r
300 ObjectId id = null;
\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
312 public static boolean isPortValid(int port) {
\r
313 return (port >= 0 && port <= 65535);
\r
316 public static boolean isHostValid(String host) {
\r
317 return host.startsWith("http");
\r
320 public static <T> boolean identifierExistsInCollection(
\r
321 MongoRepository<T, String> repository, ObjectId identifier) {
\r
322 return repository.findById(identifier.toString()).isPresent();
\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
330 public static String[] decodeBase64AuthorizationHeader(String encodedHeader) {
\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
341 public static User findUserByMechanizedId(String mechanizedId, UserRepository userRepository) {
\r
342 Optional<User> optionalUser = userRepository.findFirstByEmail(mechanizedId);
\r
343 return optionalUser.orElse(null);
\r
346 public static User findUserByAuthHeader(String authorization, UserRepository userRepository) {
\r
348 if (Strings.isNullOrEmpty(authorization)) {
\r
351 String[] credentials = Utilities.decodeBase64AuthorizationHeader(authorization);
\r
352 return findUserByMechanizedId(credentials[0], userRepository);
\r
353 } catch (Exception e) {
\r
358 public static <T> T resolveOptional(Optional<T> optional) {
\r
359 return optional.orElse(null);
\r
362 public static <T> T mapRequest(Class<T> targetType, String input) {
\r
363 logger.info(targetType.getName());
\r
365 ObjectMapper mapper =
\r
366 new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
\r
368 return mapper.readValue(input, targetType);
\r
369 } catch (IOException e) {
\r
370 Utilities.printStackTrace(e, LogLevel.ERROR);
\r
375 public enum LogLevel {
\r
382 public static Date getCurrentDate() {
\r
383 return new Date(System.currentTimeMillis());
\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