--- /dev/null
+/* Copyright (c) 2019 AT&T Intellectual Property. #\r
+# #\r
+# Licensed under the Apache License, Version 2.0 (the "License"); #\r
+# you may not use this file except in compliance with the License. #\r
+# You may obtain a copy of the License at #\r
+# #\r
+# http://www.apache.org/licenses/LICENSE-2.0 #\r
+# #\r
+# Unless required by applicable law or agreed to in writing, software #\r
+# distributed under the License is distributed on an "AS IS" BASIS, #\r
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #\r
+# See the License for the specific language governing permissions and #\r
+# limitations under the License. #\r
+##############################################################################*/\r
+\r
+\r
+package org.oran.otf.api;\r
+\r
+import org.oran.otf.common.model.User;\r
+import org.oran.otf.common.model.local.OTFApiResponse;\r
+import org.oran.otf.common.repository.UserRepository;\r
+import com.fasterxml.jackson.databind.DeserializationFeature;\r
+import com.fasterxml.jackson.databind.ObjectMapper;\r
+import com.google.common.base.Strings;\r
+import com.google.gson.JsonObject;\r
+import com.google.gson.JsonParseException;\r
+import com.google.gson.JsonParser;\r
+import java.io.IOException;\r
+import java.io.PrintWriter;\r
+import java.io.StringWriter;\r
+import java.util.Arrays;\r
+import java.util.Base64;\r
+import java.util.Date;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Optional;\r
+import javax.ws.rs.core.MediaType;\r
+import javax.ws.rs.core.Response;\r
+import org.apache.http.HttpEntity;\r
+import org.apache.http.HttpResponse;\r
+import org.apache.http.NameValuePair;\r
+import org.apache.http.client.HttpClient;\r
+import org.apache.http.client.entity.UrlEncodedFormEntity;\r
+import org.apache.http.client.methods.HttpDelete;\r
+import org.apache.http.client.methods.HttpGet;\r
+import org.apache.http.client.methods.HttpPost;\r
+import org.apache.http.conn.ssl.NoopHostnameVerifier;\r
+import org.apache.http.entity.StringEntity;\r
+import org.apache.http.impl.client.HttpClientBuilder;\r
+import org.apache.http.message.BasicNameValuePair;\r
+import org.apache.http.util.EntityUtils;\r
+import org.bson.types.ObjectId;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+import org.springframework.data.mongodb.repository.MongoRepository;\r
+\r
+public class Utilities {\r
+\r
+ public static JsonObject parseJson(String str) {\r
+ try {\r
+ return new JsonParser().parse(str).getAsJsonObject();\r
+ } catch (JsonParseException jpe) {\r
+ logger.error("Cannot parse string as Json.");\r
+ return null;\r
+ }\r
+ }\r
+\r
+ public static class Http {\r
+ public static class BuildResponse {\r
+ public static Response badRequest() {\r
+ return Response.status(400).build();\r
+ }\r
+\r
+ public static Response badRequestWithMessage(String msg) {\r
+ return Response.status(400)\r
+ .type(MediaType.APPLICATION_JSON)\r
+ .entity(new OTFApiResponse(400, msg))\r
+ .build();\r
+ }\r
+\r
+ public static Response internalServerError() {\r
+ return Response.status(500).build();\r
+ }\r
+\r
+ public static Response internalServerErrorWithMessage(String msg) {\r
+ return Response.status(500)\r
+ .type(MediaType.APPLICATION_JSON)\r
+ .entity(new OTFApiResponse(500, msg))\r
+ .build();\r
+ }\r
+\r
+ public static Response unauthorized() {\r
+ return Response.status(401).build();\r
+ }\r
+\r
+ public static Response unauthorizedWithMessage(String msg) {\r
+ return Response.status(401)\r
+ .type(MediaType.APPLICATION_JSON)\r
+ .entity(new OTFApiResponse(401, msg))\r
+ .build();\r
+ }\r
+ }\r
+\r
+ public static HttpResponse httpPostJsonUsingAAF(String url, String body) throws Exception {\r
+ HttpResponse response = null;\r
+\r
+ String aafCredentialsDecoded =\r
+ System.getenv("AAF_ID") + ":" + System.getenv("AAF_MECH_PASSWORD");\r
+\r
+ HttpPost post = new HttpPost(url);\r
+ post.setHeader("Content-Type", MediaType.APPLICATION_JSON);\r
+ post.setHeader(\r
+ "Authorization",\r
+ "Basic " + Base64.getEncoder().encodeToString(aafCredentialsDecoded.getBytes()));\r
+ post.setEntity(new StringEntity(body));\r
+\r
+ HttpClient client =\r
+ HttpClientBuilder.create()\r
+ .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)\r
+ .build();\r
+ response = client.execute(post);\r
+\r
+ // logger.info(String.format("[POST:%s]\n %s", url, body));\r
+\r
+ return response;\r
+ }\r
+\r
+ public static HttpResponse httpDeleteAAF(String url) {\r
+ HttpResponse response = null;\r
+\r
+ try {\r
+ String aafCredentialsDecoded =\r
+ System.getenv("AAF_ID") + ":" + System.getenv("AAF_MECH_PASSWORD");\r
+\r
+ HttpDelete delete = new HttpDelete(url);\r
+ delete.setHeader(\r
+ "Authorization",\r
+ "Basic " + Base64.getEncoder().encodeToString(aafCredentialsDecoded.getBytes()));\r
+ HttpClient client =\r
+ HttpClientBuilder.create()\r
+ .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)\r
+ .build();\r
+ response = client.execute(delete);\r
+\r
+ // logger.info(String.format("[DELETE:%s]\n", url));\r
+ } catch (Exception e) {\r
+ e.printStackTrace();\r
+ }\r
+\r
+ return response;\r
+ }\r
+\r
+ public static HttpResponse httpPostXmlUsingAAF(String url, String body) {\r
+ HttpResponse response = null;\r
+\r
+ try {\r
+ String aafCredentialsDecoded =\r
+ System.getenv("AAF_ID") + ":" + System.getenv("AAF_MECH_PASSWORD");\r
+\r
+ HttpPost post = new HttpPost(url);\r
+ post.setHeader("Content-Type", MediaType.APPLICATION_JSON);\r
+ post.setHeader(\r
+ "Authorization",\r
+ "Basic " + Base64.getEncoder().encodeToString(aafCredentialsDecoded.getBytes()));\r
+ post.setEntity(new StringEntity(body));\r
+\r
+ List<NameValuePair> urlParameters = Arrays.asList(new BasicNameValuePair("xml", body));\r
+ post.setEntity(new UrlEncodedFormEntity(urlParameters));\r
+\r
+ HttpClient client = HttpClientBuilder.create().build();\r
+ response = client.execute(post);\r
+\r
+ logger.info(String.format("[POST:%s]\n %s", url, body));\r
+ } catch (Exception e) {\r
+ e.printStackTrace();\r
+ }\r
+\r
+ return response;\r
+ }\r
+\r
+ public static HttpResponse httpGetUsingAAF(String url) {\r
+ HttpResponse response = null;\r
+\r
+ try {\r
+ String aafCredentialsDecoded =\r
+ System.getenv("AAF_ID") + ":" + System.getenv("AAF_MECH_PASSWORD");\r
+\r
+ HttpGet get = new HttpGet(url);\r
+ get.setHeader("Content-Type", "application/json");\r
+ get.setHeader(\r
+ "Authorization",\r
+ "Basic " + Base64.getEncoder().encodeToString(aafCredentialsDecoded.getBytes()));\r
+\r
+ HttpClient client =\r
+ HttpClientBuilder.create()\r
+ .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)\r
+ .build();\r
+ response = client.execute(get);\r
+\r
+ logger.info(String.format("[GET:%s]", url));\r
+ } catch (Exception e) {\r
+ e.printStackTrace();\r
+ }\r
+\r
+ return response;\r
+ }\r
+ }\r
+\r
+ public static class Camunda {\r
+\r
+ public static boolean isCamundaOnline() {\r
+ final String healthUrl =\r
+ String.format(\r
+ "%s:%s/%s",\r
+ System.getenv("otf.camunda.host"),\r
+ System.getenv("otf.camunda.port"),\r
+ System.getenv("otf.camunda.uri.health"));\r
+\r
+ HttpResponse res = Utilities.Http.httpGetUsingAAF(healthUrl);\r
+ return res != null && res.getStatusLine().getStatusCode() == 200;\r
+ }\r
+\r
+ public static JsonObject processInstanceStatus(String executionId) {\r
+ // Read necessary environment variables - Avoiding using Spring dependencies (@Value)\r
+ String host = System.getenv("otf.camunda.host");\r
+ String path = System.getenv("otf.camunda.uri.process-instance-completion-check");\r
+ int port = Utilities.TryGetEnvironmentVariable("otf.camunda.port");\r
+\r
+ if (!Utilities.isHostValid(host)) {\r
+ logger.error("Host (%s) must use either the http or https protocol.", host);\r
+ return null;\r
+ }\r
+\r
+ if (!Utilities.isPortValid(port)) {\r
+ logger.error(\r
+ "Invalid port (%s) specified as environment variable 'otf.camunda.port'.",\r
+ System.getenv("otf.camunda.port"));\r
+ return null;\r
+ }\r
+ try {\r
+ String getUrl = String.format("%s:%s/%s/%s", host, port, path, executionId);\r
+ HttpResponse response = Utilities.Http.httpGetUsingAAF(getUrl);\r
+ HttpEntity entity = response.getEntity();\r
+ String result = EntityUtils.toString(entity);\r
+\r
+ return parseJson(result);\r
+ } catch (IOException ioe) {\r
+ Utilities.printStackTrace(ioe, Utilities.LogLevel.ERROR);\r
+ logger.error("Cannot convert http entity to String.");\r
+ } catch (Exception e) {\r
+ Utilities.printStackTrace(e, Utilities.LogLevel.ERROR);\r
+ }\r
+ // conversion was unsuccessful\r
+ return null;\r
+ }\r
+ }\r
+\r
+ private static final Logger logger = LoggerFactory.getLogger(Utilities.class);\r
+\r
+ public static void printStackTrace(Exception exception, LogLevel logLevel) {\r
+ String stackTrace = getStackTrace(exception);\r
+\r
+ switch (logLevel) {\r
+ case INFO:\r
+ logger.info(stackTrace);\r
+ break;\r
+ case WARN:\r
+ logger.warn(stackTrace);\r
+ break;\r
+ case DEBUG:\r
+ logger.debug(stackTrace);\r
+ break;\r
+ case ERROR:\r
+ logger.error(stackTrace);\r
+ break;\r
+ }\r
+ }\r
+\r
+ public static int TryGetEnvironmentVariable(String variable) {\r
+ String value = System.getenv(variable);\r
+ int result = 0x80000000;\r
+\r
+ try {\r
+ result = Integer.parseInt(value);\r
+ } catch (NumberFormatException error) {\r
+ error.printStackTrace();\r
+ logger.error(error.getMessage());\r
+ }\r
+\r
+ return result;\r
+ }\r
+\r
+ public static String getStackTrace(Exception exception) {\r
+ StringWriter stringWriter = new StringWriter();\r
+ exception.printStackTrace(new PrintWriter(stringWriter));\r
+ return stringWriter.toString();\r
+ }\r
+\r
+ public static boolean isObjectIdValid(String input) {\r
+ ObjectId id = null;\r
+ try {\r
+ id = new ObjectId(input); // check if an ObjectId can be created from the string\r
+ if (id.toString().equalsIgnoreCase(input)) return true;\r
+ logger.warn("The input string does not have the same value as it's string representation.");\r
+ } catch (IllegalArgumentException e) {\r
+ logger.error(String.format("An ObjectId cannot be instantiated from the string: %s", input));\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ public static boolean isPortValid(int port) {\r
+ return (port >= 0 && port <= 65535);\r
+ }\r
+\r
+ public static boolean isHostValid(String host) {\r
+ return host.startsWith("http");\r
+ }\r
+\r
+ public static <T> boolean identifierExistsInCollection(\r
+ MongoRepository<T, String> repository, ObjectId identifier) {\r
+ return repository.findById(identifier.toString()).isPresent();\r
+ }\r
+\r
+ public static <T> T findByIdGeneric(MongoRepository<T, String> repository, ObjectId identifier) {\r
+ Optional<T> optionalObj = repository.findById(identifier.toString());\r
+ return optionalObj.orElse(null);\r
+ }\r
+\r
+ public static String[] decodeBase64AuthorizationHeader(String encodedHeader) {\r
+ try {\r
+ byte[] decodedAuthorization = Base64.getDecoder().decode(encodedHeader.replace("Basic ", ""));\r
+ String credentials = new String(decodedAuthorization);\r
+ return credentials.split(":");\r
+ } catch (Exception e) {\r
+ logger.error("Unable to decode authorization header: " + encodedHeader);\r
+ return null;\r
+ }\r
+ }\r
+\r
+ public static User findUserByMechanizedId(String mechanizedId, UserRepository userRepository) {\r
+ Optional<User> optionalUser = userRepository.findFirstByEmail(mechanizedId);\r
+ return optionalUser.orElse(null);\r
+ }\r
+\r
+ public static User findUserByAuthHeader(String authorization, UserRepository userRepository) {\r
+ try {\r
+ if (Strings.isNullOrEmpty(authorization)) {\r
+ return null;\r
+ }\r
+ String[] credentials = Utilities.decodeBase64AuthorizationHeader(authorization);\r
+ return findUserByMechanizedId(credentials[0], userRepository);\r
+ } catch (Exception e) {\r
+ return null;\r
+ }\r
+ }\r
+\r
+ public static <T> T resolveOptional(Optional<T> optional) {\r
+ return optional.orElse(null);\r
+ }\r
+\r
+ public static <T> T mapRequest(Class<T> targetType, String input) {\r
+ logger.info(targetType.getName());\r
+\r
+ ObjectMapper mapper =\r
+ new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);\r
+ try {\r
+ return mapper.readValue(input, targetType);\r
+ } catch (IOException e) {\r
+ Utilities.printStackTrace(e, LogLevel.ERROR);\r
+ return null;\r
+ }\r
+ }\r
+\r
+ public enum LogLevel {\r
+ WARN,\r
+ DEBUG,\r
+ INFO,\r
+ ERROR\r
+ }\r
+\r
+ public static Date getCurrentDate() {\r
+ return new Date(System.currentTimeMillis());\r
+ }\r
+\r
+ public static Map<String, Object> replaceObjectId(Map<String, Object> map, String objectIdKey) {\r
+ if (map.containsKey(objectIdKey)) {\r
+ ObjectId id = (ObjectId) map.get(objectIdKey);\r
+ map.replace(objectIdKey, id.toString());\r
+ }\r
+\r
+ return map;\r
+ }\r
+}\r