2 * ============LICENSE_START==========================================
4 * ===================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ===================================================================
8 * Unless otherwise specified, all software contained herein is licensed
9 * under the Apache License, Version 2.0 (the "License");
10 * you may not use this software except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * Unless otherwise specified, all documentation contained herein is licensed
22 * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
23 * you may not use this documentation except in compliance with the License.
24 * You may obtain a copy of the License at
26 * https://creativecommons.org/licenses/by/4.0/
28 * Unless required by applicable law or agreed to in writing, documentation
29 * distributed under the License is distributed on an "AS IS" BASIS,
30 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
31 * See the License for the specific language governing permissions and
32 * limitations under the License.
34 * ============LICENSE_END============================================
38 package org.onap.portalapp.portal.controller;
40 import java.io.IOException;
41 import java.util.ArrayList;
42 import java.util.HashMap;
43 import java.util.List;
46 import javax.servlet.http.HttpServletRequest;
47 import javax.servlet.http.HttpServletResponse;
49 import org.onap.portalapp.controller.EPRestrictedRESTfulBaseController;
50 import org.onap.portalapp.portal.domain.SharedContext;
51 import org.onap.portalapp.portal.logging.aop.EPAuditLog;
52 import org.onap.portalapp.portal.service.SharedContextService;
53 import org.onap.portalapp.portal.utils.EPCommonSystemProperties;
54 import org.onap.portalapp.portal.utils.PortalConstants;
55 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
56 import org.springframework.beans.factory.annotation.Autowired;
57 import org.springframework.context.annotation.Configuration;
58 import org.springframework.context.annotation.EnableAspectJAutoProxy;
59 import org.springframework.http.HttpStatus;
60 import org.springframework.web.bind.annotation.ExceptionHandler;
61 import org.springframework.web.bind.annotation.RequestBody;
62 import org.springframework.web.bind.annotation.RequestMapping;
63 import org.springframework.web.bind.annotation.RequestMethod;
64 import org.springframework.web.bind.annotation.RequestParam;
65 import org.springframework.web.bind.annotation.RestController;
67 import com.fasterxml.jackson.core.JsonProcessingException;
68 import com.fasterxml.jackson.databind.ObjectMapper;
70 import io.swagger.annotations.ApiOperation;
73 * The shared-context feature allows onboarded applications to share data among
74 * themselves easily for a given session. It basically implements a Java map:
75 * put or get a key-value pair within a map identified by a session ID.
77 * This REST endpoint listens on the Portal app server and answers requests made
78 * by back-end application servers. Reads and writes values to the database
79 * using a Hibernate service to ensure all servers in a high-availability
80 * cluster see the same data.
84 @RequestMapping(PortalConstants.REST_AUX_API + "/context")
85 @EnableAspectJAutoProxy
87 public class SharedContextRestController extends EPRestrictedRESTfulBaseController {
90 * Model for a one-element JSON object returned by many methods.
92 class SharedContextJsonResponse {
97 * Access to the database
100 private SharedContextService contextService;
103 * Logger for debug etc.
105 private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(SharedContextRestController.class);
108 * Reusable JSON (de)serializer
110 private final ObjectMapper mapper = new ObjectMapper();
113 * Gets a value for the specified context and key (RESTful service method).
116 * HTTP servlet request
118 * ID that identifies the context, usually the ONAP Portal
121 * Key for the key-value pair to fetch
122 * @return JSON with shared context object; response=null if not found.
126 @ApiOperation(value = "Gets a value for the specified context and key.", response = SharedContext.class)
127 @RequestMapping(value = { "/get" }, method = RequestMethod.GET, produces = "application/json")
128 public String getContext(HttpServletRequest request, @RequestParam String context_id, @RequestParam String ckey)
131 logger.debug(EELFLoggerDelegate.debugLogger, "getContext for ID " + context_id + ", key " + ckey);
132 if (context_id == null || ckey == null)
133 throw new Exception("Received null for context_id and/or ckey");
135 SharedContext context = contextService.getSharedContext(context_id, ckey);
136 String jsonResponse = "";
138 jsonResponse = convertResponseToJSON(context);
140 jsonResponse = mapper.writeValueAsString(context);
146 * Gets user information for the specified context (RESTful service method).
149 * HTTP servlet request
151 * ID that identifies the context, usually the ONAP Portal
153 * @return List of shared-context objects as JSON; should have user's first
154 * name, last name and email address; null if none found
158 @ApiOperation(value = "Gets user information for the specified context.", response = SharedContext.class, responseContainer = "List")
159 @RequestMapping(value = { "/get_user" }, method = RequestMethod.GET, produces = "application/json")
160 public String getUserContext(HttpServletRequest request, @RequestParam String context_id) throws Exception {
162 logger.debug(EELFLoggerDelegate.debugLogger, "getUserContext for ID " + context_id);
163 if (context_id == null)
164 throw new Exception("Received null for context_id");
166 List<SharedContext> listSharedContext = new ArrayList<SharedContext>();
167 SharedContext firstNameContext = contextService.getSharedContext(context_id,
168 EPCommonSystemProperties.USER_FIRST_NAME);
169 SharedContext lastNameContext = contextService.getSharedContext(context_id,
170 EPCommonSystemProperties.USER_LAST_NAME);
171 SharedContext emailContext = contextService.getSharedContext(context_id, EPCommonSystemProperties.USER_EMAIL);
172 SharedContext orgUserIdContext = contextService.getSharedContext(context_id,
173 EPCommonSystemProperties.USER_ORG_USERID);
174 if (firstNameContext != null)
175 listSharedContext.add(firstNameContext);
176 if (lastNameContext != null)
177 listSharedContext.add(lastNameContext);
178 if (emailContext != null)
179 listSharedContext.add(emailContext);
180 if (orgUserIdContext != null)
181 listSharedContext.add(orgUserIdContext);
182 String jsonResponse = convertResponseToJSON(listSharedContext);
187 * Tests for presence of the specified key in the specified context (RESTful
191 * HTTP servlet request
193 * ID that identifies the context, usually the ONAP Portal
196 * Key for the key-value pair to test
197 * @return JSON with result indicating whether the context and key were
202 @ApiOperation(value = "Tests for presence of the specified key in the specified context.", response = SharedContextJsonResponse.class)
203 @RequestMapping(value = { "/check" }, method = RequestMethod.GET, produces = "application/json")
204 public String checkContext(HttpServletRequest request, @RequestParam String context_id, @RequestParam String ckey)
207 logger.debug(EELFLoggerDelegate.debugLogger, "checkContext for " + context_id + ", key " + ckey);
208 if (context_id == null || ckey == null)
209 throw new Exception("Received null for contextId and/or key");
211 String response = null;
212 SharedContext context = contextService.getSharedContext(context_id, ckey);
216 String jsonResponse = convertResponseToJSON(response);
221 * Removes the specified key in the specified context (RESTful service
225 * HTTP servlet request
227 * ID that identifies the context, usually the ONAP Portal
230 * Key for the key-value pair to remove
231 * @return JSON with result indicating whether the context and key were
236 @ApiOperation(value = "Removes the specified key in the specified context.", response = SharedContextJsonResponse.class)
237 @RequestMapping(value = { "/remove" }, method = RequestMethod.GET, produces = "application/json")
238 public String removeContext(HttpServletRequest request, @RequestParam String context_id, @RequestParam String ckey)
241 logger.debug(EELFLoggerDelegate.debugLogger, "removeContext for " + context_id + ", key " + ckey);
242 if (context_id == null || ckey == null)
243 throw new Exception("Received null for contextId and/or key");
245 SharedContext context = contextService.getSharedContext(context_id, ckey);
246 String response = null;
247 if (context != null) {
248 contextService.deleteSharedContext(context);
249 response = "removed";
252 String jsonResponse = convertResponseToJSON(response);
257 * Clears all key-value pairs in the specified context (RESTful service
261 * HTTP servlet request
263 * ID that identifies the context, usually the ONAP Portal
265 * @return JSON with result indicating the number of key-value pairs
270 @ApiOperation(value = "Clears all key-value pairs in the specified context.", response = SharedContextJsonResponse.class)
271 @RequestMapping(value = { "/clear" }, method = RequestMethod.GET, produces = "application/json")
272 public String clearContext(HttpServletRequest request, @RequestParam String context_id) throws Exception {
274 logger.debug(EELFLoggerDelegate.debugLogger, "clearContext for " + context_id);
275 if (context_id == null)
276 throw new Exception("clearContext: Received null for contextId");
278 int count = contextService.deleteSharedContexts(context_id);
279 String jsonResponse = convertResponseToJSON(Integer.toString(count));
284 * Sets a context value for the specified context and key (RESTful service
285 * method). Creates the context if no context with the specified ID-key pair
286 * exists, overwrites the value if it exists already.
289 * HTTP servlet request
291 * JSON block with these tag-value pairs:
293 * <LI>context_id: ID that identifies the context
294 * <LI>ckey: Key for the key-value pair to store
295 * <LI>cvalue: Value to store
297 * @return JSON with result indicating whether the value was added (key not
298 * previously known) or replaced (key previously known).
302 @ApiOperation(value = "Sets a context value for the specified context and key. Creates the context if no context with the specified ID-key pair exists, overwrites the value if it exists already.", response = SharedContextJsonResponse.class)
303 @RequestMapping(value = { "/set" }, method = RequestMethod.POST, produces = "application/json")
304 public String setContext(HttpServletRequest request, @RequestBody String userJson) throws Exception {
306 @SuppressWarnings("unchecked")
307 Map<String, Object> userData = mapper.readValue(userJson, Map.class);
308 // Use column names as JSON tags
309 final String contextId = (String) userData.get("context_id");
310 final String key = (String) userData.get("ckey");
311 final String value = (String) userData.get("cvalue");
312 if (contextId == null || key == null)
313 throw new Exception("setContext: received null for contextId and/or key");
315 logger.debug(EELFLoggerDelegate.debugLogger, "setContext: ID " + contextId + ", key " + key + "->" + value);
316 String response = null;
317 SharedContext existing = contextService.getSharedContext(contextId, key);
318 if (existing == null) {
319 contextService.addSharedContext(contextId, key, value);
321 existing.setCvalue(value);
322 contextService.saveSharedContext(existing);
324 response = existing == null ? "added" : "replaced";
325 String jsonResponse = convertResponseToJSON(response);
330 * Creates a two-element JSON object tagged "response".
332 * @param responseBody
333 * @return JSON object as String
334 * @throws JsonProcessingException
336 private String convertResponseToJSON(String responseBody) throws JsonProcessingException {
337 Map<String, String> responseMap = new HashMap<String, String>();
338 responseMap.put("response", responseBody);
339 String response = mapper.writeValueAsString(responseMap);
344 * Converts a list of SharedContext objects to a JSON array.
347 * @return JSON array as String
348 * @throws JsonProcessingException
350 private String convertResponseToJSON(List<SharedContext> contextList) throws JsonProcessingException {
351 String jsonArray = mapper.writeValueAsString(contextList);
356 * Creates a JSON object with the content of the shared context; null is ok.
359 * @return tag "response" with collection of context object's fields
360 * @throws JsonProcessingException
362 private String convertResponseToJSON(SharedContext context) throws JsonProcessingException {
363 Map<String, Object> responseMap = new HashMap<String, Object>();
364 responseMap.put("response", context);
365 String responseBody = mapper.writeValueAsString(responseMap);
370 * Handles any exception thrown by a method in this controller.
375 * HttpServletResponse
376 * @throws IOException
378 @ExceptionHandler(Exception.class)
379 protected void handleBadRequests(Exception e, HttpServletResponse response) throws IOException {
380 logger.error(EELFLoggerDelegate.errorLogger, "handleBadRequest caught exception", e);
381 response.sendError(HttpStatus.BAD_REQUEST.value(), e.getMessage());