Java 17 / Spring 6 / Spring Boot 3 Upgrade
[policy/api.git] / main / src / main / java / org / onap / policy / api / main / rest / CommonRestController.java
1 /*-\r
2  * ============LICENSE_START=======================================================\r
3  * ONAP Policy API\r
4  * ================================================================================\r
5  * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.\r
6  * Modifications Copyright (C) 2022 Bell Canada. All rights reserved.\r
7  * Modifications Copyright (C) 2022-2023 Nordix Foundation.\r
8  * ================================================================================\r
9  * Licensed under the Apache License, Version 2.0 (the "License");\r
10  * you may not use this file except in compliance with the License.\r
11  * You may obtain a copy of the License at\r
12  *\r
13  *      http://www.apache.org/licenses/LICENSE-2.0\r
14  *\r
15  * Unless required by applicable law or agreed to in writing, software\r
16  * distributed under the License is distributed on an "AS IS" BASIS,\r
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
18  * See the License for the specific language governing permissions and\r
19  * limitations under the License.\r
20  *\r
21  * SPDX-License-Identifier: Apache-2.0\r
22  * ============LICENSE_END=========================================================\r
23  */\r
24 \r
25 package org.onap.policy.api.main.rest;\r
26 \r
27 import java.util.Objects;\r
28 import java.util.UUID;\r
29 import org.onap.policy.api.main.exception.PolicyApiRuntimeException;\r
30 import org.onap.policy.common.utils.coder.Coder;\r
31 import org.onap.policy.common.utils.coder.CoderException;\r
32 import org.onap.policy.common.utils.coder.StandardCoder;\r
33 import org.slf4j.Logger;\r
34 import org.slf4j.LoggerFactory;\r
35 import org.springframework.http.HttpStatus;\r
36 import org.springframework.http.ResponseEntity;\r
37 import org.springframework.web.bind.annotation.ExceptionHandler;\r
38 import org.springframework.web.context.request.WebRequest;\r
39 \r
40 /**\r
41  * Super class from which REST controllers are derived.\r
42  */\r
43 public class CommonRestController {\r
44 \r
45     private static final Logger LOGGER = LoggerFactory.getLogger(CommonRestController.class);\r
46 \r
47     protected static final String EXTENSION_NAME = "interface info";\r
48 \r
49     protected static final String API_VERSION_NAME = "api-version";\r
50     protected static final String API_VERSION = "1.0.0";\r
51 \r
52     protected static final String LAST_MOD_NAME = "last-mod-release";\r
53 \r
54     protected static final String AUTHORIZATION_TYPE = "basicAuth";\r
55 \r
56     protected static final String VERSION_MINOR_NAME = "X-MinorVersion";\r
57     protected static final String VERSION_MINOR_DESCRIPTION =\r
58         "Used to request or communicate a MINOR version back from the client"\r
59             + " to the server, and from the server back to the client";\r
60 \r
61     protected static final String VERSION_PATCH_NAME = "X-PatchVersion";\r
62     protected static final String VERSION_PATCH_DESCRIPTION = "Used only to communicate a PATCH version in a "\r
63         + "response for troubleshooting purposes only, and will not be provided by" + " the client on request";\r
64 \r
65     protected static final String VERSION_LATEST_NAME = "X-LatestVersion";\r
66     protected static final String VERSION_LATEST_DESCRIPTION = "Used only to communicate an API's latest version";\r
67 \r
68     public static final String REQUEST_ID_NAME = "X-ONAP-RequestID";\r
69     protected static final String REQUEST_ID_HDR_DESCRIPTION = "Used to track REST transactions for logging purpose";\r
70     protected static final String REQUEST_ID_PARAM_DESCRIPTION = "RequestID for http transaction";\r
71 \r
72     protected static final String AUTHENTICATION_ERROR_MESSAGE = "Authentication Error";\r
73     protected static final String AUTHORIZATION_ERROR_MESSAGE = "Authorization Error";\r
74     protected static final String SERVER_ERROR_MESSAGE = "Internal Server Error";\r
75     protected static final String NOT_FOUND_MESSAGE = "Resource Not Found";\r
76     protected static final String INVALID_BODY_MESSAGE = "Invalid Body";\r
77     protected static final String INVALID_PAYLOAD_MESSAGE = "Not Acceptable Payload";\r
78     protected static final String HTTP_CONFLICT_MESSAGE = "Delete Conflict, Rule Violation";\r
79     protected static final String ERROR_MESSAGE_NO_POLICIES_FOUND = "No policies found";\r
80 \r
81     protected final Coder coder = new StandardCoder();\r
82 \r
83     protected <T> ResponseEntity<T> makeOkResponse(UUID requestId, T respEntity) {\r
84         return makeResponse(requestId, respEntity, HttpStatus.OK.value());\r
85     }\r
86 \r
87     protected <T> ResponseEntity<T> makeResponse(UUID requestId, T respEntity, int status) {\r
88         return CommonRestController\r
89             .addLoggingHeaders(addVersionControlHeaders(ResponseEntity.status(status)), requestId)\r
90             .body(respEntity);\r
91     }\r
92 \r
93     /**\r
94      * Adds version headers to the response.\r
95      *\r
96      * @param respBuilder response builder\r
97      * @return the response builder, with version headers\r
98      */\r
99     public static ResponseEntity.BodyBuilder addVersionControlHeaders(ResponseEntity.BodyBuilder respBuilder) {\r
100         return respBuilder.header(VERSION_MINOR_NAME, "0").header(VERSION_PATCH_NAME, "0").header(VERSION_LATEST_NAME,\r
101             API_VERSION);\r
102     }\r
103 \r
104     /**\r
105      * Adds logging headers to the response.\r
106      *\r
107      * @param respBuilder response builder\r
108      * @return the response builder, with version logging\r
109      */\r
110     public static ResponseEntity.BodyBuilder addLoggingHeaders(ResponseEntity.BodyBuilder respBuilder, UUID requestId) {\r
111         // Generate a random uuid if client does not embed requestId in rest request\r
112         return respBuilder.header(REQUEST_ID_NAME,\r
113             Objects.requireNonNullElseGet(requestId, UUID::randomUUID).toString());\r
114 \r
115     }\r
116 \r
117     /**\r
118      * Converts an object to a JSON string.\r
119      *\r
120      * @param object object to convert\r
121      * @return a JSON string representing the object\r
122      */\r
123     protected String toJson(Object object) {\r
124         if (object == null) {\r
125             return null;\r
126         }\r
127 \r
128         try {\r
129             return coder.encode(object);\r
130 \r
131         } catch (CoderException e) {\r
132             LOGGER.warn("cannot convert {} to JSON", object.getClass().getName(), e);\r
133             return null;\r
134         }\r
135     }\r
136 \r
137     @ExceptionHandler(value = {PolicyApiRuntimeException.class})\r
138     protected ResponseEntity<Object> handleException(PolicyApiRuntimeException ex, WebRequest req) {\r
139         LOGGER.warn(ex.getMessage(), ex.getCause());\r
140         final var requestId = req.getHeader(CommonRestController.REQUEST_ID_NAME);\r
141         final var status = ex.getErrorResponse().getResponseCode().getStatusCode();\r
142         return CommonRestController.addLoggingHeaders(\r
143             CommonRestController.addVersionControlHeaders(ResponseEntity.status(status)),\r
144             requestId != null ? UUID.fromString(requestId) : ex.getRequestId()).body(ex.getErrorResponse());\r
145     }\r
146 }\r